first release Intelligent Lumen iBeacon
Dependencies: BLE_API mbed nRF51822
Revision 1:2e474d4e7092, committed 2016-10-17
- Comitter:
- javiervelasco
- Date:
- Mon Oct 17 07:41:30 2016 +0000
- Branch:
- INTELLIGENT_LUMEN_BEACON
- Parent:
- 0:720b1ee20d33
- Commit message:
- First release
Changed in this revision
BLE_API.lib | 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 |
diff -r 720b1ee20d33 -r 2e474d4e7092 BLE_API.lib --- a/BLE_API.lib Thu Sep 15 14:43:08 2016 +0000 +++ b/BLE_API.lib Mon Oct 17 07:41:30 2016 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#65474dc93927 +https://developer.mbed.org/users/javiervelasco/code/BLE_API/#1cdc132601a3
diff -r 720b1ee20d33 -r 2e474d4e7092 main.cpp --- a/main.cpp Thu Sep 15 14:43:08 2016 +0000 +++ b/main.cpp Mon Oct 17 07:41:30 2016 +0000 @@ -15,48 +15,217 @@ */ #include "mbed.h" +#include <string.h> +#include <stddef.h> +#include <Serial.h> #include "ble/services/iBeacon.h" #include "ble/services/UARTService.h" +#include "ble/services/DFUService.h" +#include "nrf.h" +#include "nrf_sdm.h" +extern "C" { + #include "pstorage.h" +} +#include "nrf_error.h" + +#define _DEBUG + BLE ble; - -void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) -{ - BLE &ble = params->ble; - ble_error_t error = params->error; +UARTService *uarts; +DFUService *dfus; +iBeacon *ibeacon; +pstorage_handle_t pstorageHandle; +#ifdef _DEBUG +Serial pc(USBTX, USBRX); +#endif +Ticker ticker; - if (error != BLE_ERROR_NONE) { - return; +// Struct to hold persistent data across power cycles +typedef struct PersistentData_t { + char name[32]; + uint16_t majorNumber; + uint16_t minorNumber; + uint16_t txPower; +} __attribute__ ((aligned (4))); +PersistentData_t persistentData; +static const int PERSISTENT_DATA_ALIGNED_SIZE = sizeof(PersistentData_t); + +/* Dummy callback handler needed by Nordic's pstorage module. */ +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); */ +} + +void pstorageLoad(){ + if (pstorage_init()!=NRF_SUCCESS) { } - /** - * The Beacon payload has the following composition: - * 128-Bit / 16byte UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 - * Major/Minor = 0x1122 / 0x3344 - * Tx Power = 0xC8 = 200, 2's compliment is 256-200 = (-56dB) - * - * Note: please remember to calibrate your beacons TX Power for more accurate results. - */ - const uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, - 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61}; - uint16_t majorNumber = 1122; - uint16_t minorNumber = 3344; - uint16_t txPower = 0x40; - iBeacon *ibeacon = new iBeacon(ble, uuid, majorNumber, minorNumber, txPower); + pstorage_module_param_t pstorageParams = { + .cb = pstorageNotificationCallback, + .block_size = PERSISTENT_DATA_ALIGNED_SIZE, + .block_count = 1 + }; + pstorage_register(&pstorageParams, &pstorageHandle); + if (pstorage_load( + reinterpret_cast<uint8_t *>(&persistentData), + &pstorageHandle, PERSISTENT_DATA_ALIGNED_SIZE, 0 + ) != NRF_SUCCESS) { + // On failure zero out and let the service reset to defaults + sprintf(persistentData.name,"INTELLIGENTLUMEN"); + persistentData.majorNumber=1234; + persistentData.minorNumber=5678; + persistentData.txPower=54; + } +} + + + +void pstorageSave() { + pstorage_store( + &pstorageHandle, + reinterpret_cast<uint8_t *>(&persistentData), + sizeof(PersistentData_t), + 0 /* offset */ + ); + wait(2); +} + + - ble.gap().setAdvertisingInterval(1000); /* 1000ms. */ - ble.gap().startAdvertising(); +/* BLE UART data received callback */ +void onDataWritten(const GattWriteCallbackParams *params) +{ + char *bp = (char*)params->data; + bp[params->len]=0; //Fix string end with zero. + #ifdef _DEBUG + pc.printf("%s\r\n",bp); + #endif + char *token; + token = strtok(bp," ,"); + if (token!=NULL) { + #ifdef _DEBUG + pc.printf("Recv: %s\r\n",token); + #endif + if (strcmp(token,"name")==0) { + token = strtok(NULL," ,"); + if (token==NULL) { + #ifdef _DEBUG + pc.printf("Cfg error: invalid name \r\n"); + #endif + return; + } + sprintf((char *)persistentData.name,"%s",token); + } else if (strcmp(token,"major")==0) { + token = strtok(NULL," ,"); + if (token==NULL) { + #ifdef _DEBUG + pc.printf("Cfg error: invalid majorNumber \r\n"); + #endif + return; + } + persistentData.majorNumber=atoi(token); + } else if (strcmp(token,"minor")==0) { + token = strtok(NULL," ,"); + if (token==NULL) { + #ifdef _DEBUG + pc.printf("Cfg error: invalid minorNumber \r\n"); + #endif + return; + } + persistentData.minorNumber=atoi(token); + } else if (strcmp(token,"rssi")==0) { + token = strtok(NULL," ,"); + if (token==NULL) { + #ifdef _DEBUG + pc.printf("Cfg error: invalid txPower \r\n"); + #endif + return; + } + persistentData.txPower=atoi(token); + #ifdef _DEBUG + pc.printf("Cfg txPower:%i\r\n",persistentData.txPower); + #endif + } else if (strcmp(token,"save")==0) { + pstorageSave(); + #ifdef _DEBUG + pc.printf("Config name:%s major:%i minor:%i tx:%i\r\n",persistentData.name,persistentData.majorNumber,persistentData.minorNumber,persistentData.txPower); + #endif + NVIC_SystemReset(); + } else if (strcmp(token,"dfu")==0) { + sd_power_gpregret_set(BOOTLOADER_DFU_START); + sd_softdevice_disable(); + sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR); + NVIC_SystemReset(); + } + } } + + +void connectionCallback(const Gap::ConnectionCallbackParams_t *params) +{ + #ifdef _DEBUG + pc.printf("Connected!\n"); + #endif +} + +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *cbParams) +{ + #ifdef _DEBUG + pc.printf("Disconnected!\n"); + pc.printf("Restarting the advertising process\n"); + #endif + ble.startAdvertising(); +} + + int main(void) { - ble.init(bleInitComplete); + const uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, + 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61}; + #ifdef _DEBUG + pc.baud(9600); + pc.printf("INTELLIGENT LUMEN BEACON DFU v1.1\r\n"); + #endif + + /* Load mayor minor and txpower from storage */ + pstorageLoad(); + #ifdef _DEBUG + pc.printf("Storage size:%i\r\n",PERSISTENT_DATA_ALIGNED_SIZE); + pc.printf("Config name:%s mayor:%i minor:%i tx:%i\r\n",persistentData.name,persistentData.majorNumber,persistentData.minorNumber,persistentData.txPower); + #endif + + ble.init(); + while (!ble.hasInitialized()) { wait(0.5);/* wait for BLE initialization */ } - /* SpinWait for initialization to complete. This is necessary because the - * BLE object is used in the main loop below. */ - while (!ble.hasInitialized()) { /* spin loop */ } + ble.gap().onDisconnection(disconnectionCallback); + ble.gap().onConnection(connectionCallback); + ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, + (const uint8_t*)persistentData.name, strlen((const char*)persistentData.name)); + + UARTService uartService(ble); + uarts = &uartService; + DFUService dfu(ble); + dfus = &dfu; + ibeacon = new iBeacon(ble, uuid, persistentData.majorNumber, persistentData.minorNumber, persistentData.txPower); + ble.onDataWritten(onDataWritten); + + /* setup advertising */ + ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); + ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, + (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); + ble.setAdvertisingInterval(100); /* 100ms; in multiples of 0.625ms. */ + ble.gap().startAdvertising(); + + while (true) { ble.waitForEvent(); // allows or low power operation }