jan

Dependencies:   BLE_API mbed nRF51822

Files at this revision

API Documentation at this revision

Comitter:
janjongboom
Date:
Sat Nov 14 09:39:14 2015 +0000
Commit message:
jan

Changed in this revision

BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
ConfigParamsPersistence.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
nRF51822.lib Show annotated file Show diff for this revision Revisions of this file
nrfConfigParamsPersistence.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r f17fb1bb4f3a BLE_API.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BLE_API.lib	Sat Nov 14 09:39:14 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#a782d73aae68
diff -r 000000000000 -r f17fb1bb4f3a ConfigParamsPersistence.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ConfigParamsPersistence.h	Sat Nov 14 09:39:14 2015 +0000
@@ -0,0 +1,53 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BLE_CONFIG_PARAMS_PERSISTENCE_H__
+#define __BLE_CONFIG_PARAMS_PERSISTENCE_H__
+
+#include "ble/services/URIBeaconConfigService.h"
+
+/**
+ * Generic API to load the URIBeacon configuration parameters from persistent
+ * storage. If persistent storage isn't available, the persistenceSignature
+ * member of params may be left un-initialized to the MAGIC, and this will cause
+ * a reset to default values.
+ *
+ * @param[out] paramsP
+ *                 The parameters to be filled in from persistence storage. This
+                   argument can be NULL if the caller is only interested in
+                   discovering the persistence status of params.
+
+ * @return true if params were loaded from persistent storage and have usefully
+ *         initialized fields.
+ */
+bool loadURIBeaconConfigParams(URIBeaconConfigService::Params_t *paramsP);
+
+/**
+ * Generic API to store the URIBeacon configuration parameters to persistent
+ * storage. It typically initializes the persistenceSignature member of the
+ * params to the MAGIC value to indicate persistence.
+ *
+ * @note: the save operation may be asynchronous. It may be a short while before
+ * the request takes affect. Reading back saved configParams may not yield
+ * correct behaviour if attempted soon after a store.
+ *
+ * @param[in/out] paramsP
+ *                    The params to be saved; persistenceSignature member gets
+ *                    updated if persistence is successful.
+ */
+void saveURIBeaconConfigParams(const URIBeaconConfigService::Params_t *paramsP);
+
+#endif /* #ifndef __BLE_CONFIG_PARAMS_PERSISTENCE_H__*/
diff -r 000000000000 -r f17fb1bb4f3a main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Nov 14 09:39:14 2015 +0000
@@ -0,0 +1,95 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mbed.h"
+#include "ble/BLE.h"
+#include "ble/services/URIBeaconConfigService.h"
+#include "ble/services/DFUService.h"
+#include "ble/services/DeviceInformationService.h"
+#include "ConfigParamsPersistence.h"
+
+BLE ble;
+URIBeaconConfigService *uriBeaconConfig;
+
+/**
+ * URIBeaconConfig service can operate in two modes: a configuration mode which
+ * allows a user to update settings over a connection; and normal URIBeacon mode
+ * which involves advertising a URI. Constructing an object from URIBeaconConfig
+ * service sets up advertisements for the configuration mode. It is then up to
+ * the application to switch to URIBeacon mode based on some timeout.
+ *
+ * The following help with this switch.
+ */
+static const int CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS = 5;  // Duration after power-on that config service is available.
+Ticker configAdvertisementTimeoutTicker;
+
+/**
+ * Stop advertising the UriBeaconConfig Service after a delay; and switch to normal URIBeacon.
+ */
+void timeout(void)
+{
+    Gap::GapState_t state;
+    state = ble.getGapState();
+    if (!state.connected) { /* don't switch if we're in a connected state. */
+        uriBeaconConfig->setupURIBeaconAdvertisements();
+        ble.startAdvertising();
+
+        configAdvertisementTimeoutTicker.detach(); /* disable the callback from the timeout Ticker. */
+    }
+}
+
+/**
+ * Callback triggered upon a disconnection event. Needs to re-enable advertisements.
+ */
+void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
+{
+    ble.startAdvertising();
+}
+
+int main(void)
+{
+    ble.init();
+    ble.onDisconnection(disconnectionCallback);
+
+    /*
+     * Load parameters from (platform specific) persistent storage. Parameters
+     * can be set to non-default values while the URIBeacon is in configuration
+     * mode (within the first 60 seconds of power-up). Thereafter, parameters
+     * get copied out to persistent storage before switching to normal URIBeacon
+     * operation.
+     */
+    URIBeaconConfigService::Params_t params;
+    bool fetchedFromPersistentStorage = loadURIBeaconConfigParams(&params);
+
+    /* Initialize a URIBeaconConfig service providing config params, default URI, and power levels. */
+    static URIBeaconConfigService::PowerLevels_t defaultAdvPowerLevels = {-20, -4, 0, 10}; // Values for ADV packets related to firmware levels
+    uriBeaconConfig = new URIBeaconConfigService(ble, params, !fetchedFromPersistentStorage, "http://beacon1", defaultAdvPowerLevels);
+    if (!uriBeaconConfig->configuredSuccessfully()) {
+        error("failed to accommodate URI");
+    }
+    configAdvertisementTimeoutTicker.attach(timeout, CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS);
+
+    // Setup auxiliary services to allow over-the-air firmware updates, etc
+    DFUService dfu(ble);
+    DeviceInformationService deviceInfo(ble, "ARM", "UriBeacon", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
+
+    ble.startAdvertising(); /* Set the whole thing in motion. After this call a GAP central can scan the URIBeaconConfig
+                             * service. This can then be switched to the normal URIBeacon functionality after a timeout. */
+
+    while (true) {
+        ble.waitForEvent();
+    }
+}
diff -r 000000000000 -r f17fb1bb4f3a mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Nov 14 09:39:14 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/b9ad9a133dc7
\ No newline at end of file
diff -r 000000000000 -r f17fb1bb4f3a nRF51822.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF51822.lib	Sat Nov 14 09:39:14 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#a9ed252089c4
diff -r 000000000000 -r f17fb1bb4f3a nrfConfigParamsPersistence.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nrfConfigParamsPersistence.cpp	Sat Nov 14 09:39:14 2015 +0000
@@ -0,0 +1,103 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pstorage.h"
+#include "nrf_error.h"
+#include "ConfigParamsPersistence.h"
+
+/**
+ * Nordic specific structure used to store params persistently.
+ * It extends URIBeaconConfigService::Params_t with a persistence signature.
+ */
+struct PersistentParams_t {
+    URIBeaconConfigService::Params_t params;
+    uint32_t                         persistenceSignature; /* This isn't really a parameter, but having the expected
+                                                            * magic value in this field indicates persistence. */
+
+    static const uint32_t MAGIC = 0x1BEAC000;              /* Magic that identifies persistence */
+};
+
+/**
+ * The following is a module-local variable to hold configuration parameters for
+ * short periods during flash access. This is necessary because the pstorage
+ * APIs don't copy in the memory provided as data source. The memory cannot be
+ * freed or reused by the application until this flash access is complete. The
+ * load and store operations in this module initialize persistentParams and then
+ * pass it on to the 'pstorage' APIs.
+ */
+static PersistentParams_t persistentParams;
+
+static pstorage_handle_t pstorageHandle;
+
+/**
+ * Dummy callback handler needed by Nordic's pstorage module. This is called
+ * after every flash access.
+ */
+static void pstorageNotificationCallback(pstorage_handle_t *p_handle,
+                                         uint8_t            op_code,
+                                         uint32_t           result,
+                                         uint8_t           *p_data,
+                                         uint32_t           data_len)
+{
+    /* APP_ERROR_CHECK(result); */
+}
+
+/* Platform-specific implementation for persistence on the nRF5x. Based on the
+ * pstorage module provided by the Nordic SDK. */
+bool loadURIBeaconConfigParams(URIBeaconConfigService::Params_t *paramsP)
+{
+    static bool pstorageInitied = false;
+    if (!pstorageInitied) {
+        pstorage_init();
+
+        static pstorage_module_param_t pstorageParams = {
+            .cb          = pstorageNotificationCallback,
+            .block_size  = sizeof(PersistentParams_t),
+            .block_count = 1
+        };
+        pstorage_register(&pstorageParams, &pstorageHandle);
+        pstorageInitied = true;
+    }
+
+    if ((pstorage_load(reinterpret_cast<uint8_t *>(&persistentParams), &pstorageHandle, sizeof(PersistentParams_t), 0) != NRF_SUCCESS) ||
+        (persistentParams.persistenceSignature != PersistentParams_t::MAGIC)) {
+        // On failure zero out and let the service reset to defaults
+        memset(paramsP, 0, sizeof(URIBeaconConfigService::Params_t));
+        return false;
+    }
+
+    memcpy(paramsP, &persistentParams.params, sizeof(URIBeaconConfigService::Params_t));
+    return true;
+}
+
+/* Platform-specific implementation for persistence on the nRF5x. Based on the
+ * pstorage module provided by the Nordic SDK. */
+void saveURIBeaconConfigParams(const URIBeaconConfigService::Params_t *paramsP)
+{
+    memcpy(&persistentParams.params, paramsP, sizeof(URIBeaconConfigService::Params_t));
+    if (persistentParams.persistenceSignature != PersistentParams_t::MAGIC) {
+        persistentParams.persistenceSignature = PersistentParams_t::MAGIC;
+        pstorage_store(&pstorageHandle,
+                       reinterpret_cast<uint8_t *>(&persistentParams),
+                       sizeof(PersistentParams_t),
+                       0 /* offset */);
+    } else {
+        pstorage_update(&pstorageHandle,
+                        reinterpret_cast<uint8_t *>(&persistentParams),
+                        sizeof(PersistentParams_t),
+                        0 /* offset */);
+    }
+}