The eddystone config service allows you to configure the eddystone frame data over BLE for a set period of time and then starts an eddystone beacon. This example defaults to 30 seconds of config time.

Dependencies:   BLE_API mbed nRF51822 X_NUCLEO_IDB0XA1

Fork of BLE_EddystoneBeaconConfigServiceRelease by Austin Blackstone

This is the eddystone config service. This code starts up and for a user configured time period (default 30 seconds) will advertise the configuration service.

The configuration service allows for modifying various frames of the eddystone specification.

For more details on the Configuration Service please see : https://github.com/google/eddystone/blob/master/eddystone-url/docs/config-service-spec.md

Revision:
5:fbd10ac20d91
Parent:
4:2dd4bacf1cb8
Child:
6:321047f0190a
--- a/main.cpp	Tue Nov 24 10:14:30 2015 +0000
+++ b/main.cpp	Tue Nov 24 11:56:20 2015 +0000
@@ -16,12 +16,23 @@
 
 #include "mbed.h"
 #include "ble/BLE.h"
-#include "EddystoneService.h"
+#include "ble/services/EddystoneConfigService.h"
+#include "ConfigParamsPersistence.h"
+
+BLE ble;
+EddystoneConfigService *EddystoneBeaconConfig;
+EddystoneConfigService::Params_t params;
 
-EddystoneService *eddyServicePtr;
-
-/* Duration after power-on that config service is available. */
-static const int CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS = 30;
+/**
+ * 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 = 30;  // Duration after power-on that config service is available.
 
 Ticker configAdvertisementTimeout;
 
@@ -31,10 +42,10 @@
 void timeout(void)
 {
     Gap::GapState_t state;
-    state = BLE::Instance(BLE::DEFAULT_INSTANCE).getGapState();
+    state = ble.getGapState();
     if (!state.connected) { /* don't switch if we're in a connected state. */
         configAdvertisementTimeout.detach(); /* disable the callback from the timeout Ticker. */
-        eddyServicePtr->startBeaconService(5, 5, 5);  
+        EddystoneBeaconConfig->setupEddystoneAdvertisements();        
     }
 }
 
@@ -43,61 +54,58 @@
  */
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *cbParams)
 {
-    (void) cbParams;
-    BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
-}
-
-void onBleInitError(BLE::InitializationCompleteCallbackContext* initContext)
-{
-    /* Initialization error handling goes here... */
-    (void) initContext;
-}
-
-void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext)
-{
-    BLE         &ble  = initContext->ble;
-    ble_error_t error = initContext->error;
-
-    if (error != BLE_ERROR_NONE) {
-        onBleInitError(initContext);
-        return;
+    if (true == params.isConfigured){
+        // end advertising, the beacon is configured
+        timeout();
     }
-
-    ble.gap().onDisconnection(disconnectionCallback);
-
-    /* Set UID and TLM frame data */
-    const UIDNamespaceID_t uidNamespaceID = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99};
-    const UIDInstanceID_t  uidInstanceID  = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
-    uint8_t tlmVersion = 0x00;
-
-    /* Initialize a EddystoneBeaconConfig service providing config params, default URI, and power levels. */
-    static const PowerLevels_t defaultAdvPowerLevels = {-47, -33, -21, -13}; // Values for ADV packets related to firmware levels, calibrated based on measured values at 1m
-    static const PowerLevels_t radioPowerLevels      = {-30, -16, -4, 4};    // Values for radio power levels, provided by manufacturer.
-
-    /* Set everything to defaults */
-    eddyServicePtr = new EddystoneService(ble, defaultAdvPowerLevels, radioPowerLevels, 500);
-
-    /* Set default URL, UID and TLM frame data if not initialized through the config service */
-    eddyServicePtr->setURLData("http://mbed.org");
-    eddyServicePtr->setUIDData(&uidNamespaceID, &uidInstanceID);
-    eddyServicePtr->setTLMData(tlmVersion);
-
-    /* Start Eddystone in config mode */
-    eddyServicePtr->startConfigService();
-
-    configAdvertisementTimeout.attach(timeout, CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS);
+    else{
+        // eddystone is not configured, continue advertising    
+        ble.gap().startAdvertising();
+    }
 }
 
 int main(void)
 {
-    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
-    ble.init(bleInitComplete);
+    ble.init();
+    ble.gap().onDisconnection(disconnectionCallback);
 
-    /* SpinWait for initialization to complete. This is necessary because the
-     * BLE object is used in the main loop below. */
-    while (ble.hasInitialized()  == false) { /* spin loop */ }
+    /*
+     * 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.
+     */
+    bool fetchedFromPersistentStorage = loadURIBeaconConfigParams(&params);
+    
+    // Set UID and TLM frame data
+    EddystoneConfigService::UIDNamespaceID_t uidNamespaceID = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}; // 10Byte Namespace UUID
+    EddystoneConfigService::UIDInstanceID_t  uidInstanceID = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; // 6Byte Instance ID
+    uint8_t tlmVersion = 0x00;
+    
+    /* Initialize a EddystoneBeaconConfig service providing config params, default URI, and power levels. */
+    static EddystoneConfigService::PowerLevels_t defaultAdvPowerLevels = {-47, -33, -21, -13}; // Values for ADV packets related to firmware levels, calibrated based on measured values at 1m
+    static EddystoneConfigService::PowerLevels_t radioPowerLevels =      {-30, -16, -4, 4};    // Values for radio power levels, provided by manufacturer.
     
+    // Create Eddystone Config Service object
+    EddystoneBeaconConfig = new EddystoneConfigService(ble, params, defaultAdvPowerLevels, radioPowerLevels);
+    
+    // Set default URI, UID and TLM frame data if not initialized through the config service
+    EddystoneBeaconConfig->setDefaultURIFrameData("http://mbed.net/bcn",2);
+    EddystoneBeaconConfig->setDefaultUIDFrameData(&uidNamespaceID, &uidInstanceID,5);
+    EddystoneBeaconConfig->setDefaultTLMFrameData(tlmVersion,10);
+    
+    // start the config service
+    EddystoneBeaconConfig->start(!fetchedFromPersistentStorage);
+    
+    if (!EddystoneBeaconConfig->initSuccessfully()) {
+        error("failed to accommodate URI");
+    }
+    configAdvertisementTimeout.attach(timeout, CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS);
+
+    ble.gap().startAdvertising(); /* Set the whole thing in motion. After this call a GAP central can scan the EddystoneBeaconConfig
+                                   * service. This can then be switched to the normal URIBeacon functionality after a timeout. */
     while (true) {
-        ble.waitForEvent(); /* this will return upon any system event (such as an interrupt or a ticker wakeup) */
+        ble.waitForEvent();
     }
-}
+}
\ No newline at end of file