Demo program of a simple BLE temperature gateway that scans for temperature broadcasts from beacons while simultaneously acting as a peripheral.

Dependencies:   BLE_API mbed nRF51822

Committer:
andresag
Date:
Mon Oct 05 12:59:40 2015 +0000
Revision:
0:3aa044e110b8
Initial version of a simple BLE temperature gateway that scans temperature broadcasts while simultaneously acting as a peripheral.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andresag 0:3aa044e110b8 1 /* mbed Microcontroller Library
andresag 0:3aa044e110b8 2 * Copyright (c) 2006-2015 ARM Limited
andresag 0:3aa044e110b8 3 *
andresag 0:3aa044e110b8 4 * Licensed under the Apache License, Version 2.0 (the "License");
andresag 0:3aa044e110b8 5 * you may not use this file except in compliance with the License.
andresag 0:3aa044e110b8 6 * You may obtain a copy of the License at
andresag 0:3aa044e110b8 7 *
andresag 0:3aa044e110b8 8 * http://www.apache.org/licenses/LICENSE-2.0
andresag 0:3aa044e110b8 9 *
andresag 0:3aa044e110b8 10 * Unless required by applicable law or agreed to in writing, software
andresag 0:3aa044e110b8 11 * distributed under the License is distributed on an "AS IS" BASIS,
andresag 0:3aa044e110b8 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
andresag 0:3aa044e110b8 13 * See the License for the specific language governing permissions and
andresag 0:3aa044e110b8 14 * limitations under the License.
andresag 0:3aa044e110b8 15 */
andresag 0:3aa044e110b8 16
andresag 0:3aa044e110b8 17 #include "mbed.h"
andresag 0:3aa044e110b8 18 #include "ble/BLE.h"
andresag 0:3aa044e110b8 19 #include "ble/services/BatteryService.h"
andresag 0:3aa044e110b8 20 #include "ble/services/DeviceInformationService.h"
andresag 0:3aa044e110b8 21
andresag 0:3aa044e110b8 22 #include "toolchain.h"
andresag 0:3aa044e110b8 23 #include "TMP_nrf51/TMP_nrf51.h"
andresag 0:3aa044e110b8 24 #include "TemperatureGatewayService.h"
andresag 0:3aa044e110b8 25 #include "TemperatureTable.h"
andresag 0:3aa044e110b8 26
andresag 0:3aa044e110b8 27 #define MAX_BEACONS 10
andresag 0:3aa044e110b8 28
andresag 0:3aa044e110b8 29 BLE ble;
andresag 0:3aa044e110b8 30 DigitalOut led1(LED1);
andresag 0:3aa044e110b8 31
andresag 0:3aa044e110b8 32 TemperatureGatewayService<MAX_BEACONS>* tempGatewayServicePtr;
andresag 0:3aa044e110b8 33 TemperatureTable<uint32_t, float, MAX_BEACONS> temperatureTable;
andresag 0:3aa044e110b8 34
andresag 0:3aa044e110b8 35 /* Setup device name and new service information */
andresag 0:3aa044e110b8 36 const static char DEVICE_NAME[] = "TGW1";
andresag 0:3aa044e110b8 37 static const uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE,
andresag 0:3aa044e110b8 38 GattService::UUID_DEVICE_INFORMATION_SERVICE};
andresag 0:3aa044e110b8 39
andresag 0:3aa044e110b8 40 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
andresag 0:3aa044e110b8 41 {
andresag 0:3aa044e110b8 42 ble.gap().startAdvertising(); // restart advertising
andresag 0:3aa044e110b8 43 }
andresag 0:3aa044e110b8 44
andresag 0:3aa044e110b8 45 void periodicCallback(void)
andresag 0:3aa044e110b8 46 {
andresag 0:3aa044e110b8 47 led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
andresag 0:3aa044e110b8 48 }
andresag 0:3aa044e110b8 49
andresag 0:3aa044e110b8 50 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
andresag 0:3aa044e110b8 51
andresag 0:3aa044e110b8 52 struct AdvertisingData_t {
andresag 0:3aa044e110b8 53 uint8_t length; /* doesn't include itself */
andresag 0:3aa044e110b8 54 GapAdvertisingData::DataType_t dataType;
andresag 0:3aa044e110b8 55 uint8_t data[0];
andresag 0:3aa044e110b8 56 } PACKED;
andresag 0:3aa044e110b8 57
andresag 0:3aa044e110b8 58 struct ApplicationData_t {
andresag 0:3aa044e110b8 59 uint16_t applicationSpecificId; /* An ID used to identify temperature value
andresag 0:3aa044e110b8 60 in the manufacture specific AD data field */
andresag 0:3aa044e110b8 61 TMP_nrf51::TempSensorValue_t tmpSensorValue; /* User defined application data */
andresag 0:3aa044e110b8 62 } PACKED;
andresag 0:3aa044e110b8 63
andresag 0:3aa044e110b8 64 /* This ID is not very meaningful, but makes it easy to find the device for debugging */
andresag 0:3aa044e110b8 65 static const uint16_t APP_SPECIFIC_ID_TEST = 0xFEFE;
andresag 0:3aa044e110b8 66
andresag 0:3aa044e110b8 67 /* Search for the manufacturer specific data with matching application-ID */
andresag 0:3aa044e110b8 68 AdvertisingData_t *pAdvData;
andresag 0:3aa044e110b8 69 for (size_t index = 0; index < params->advertisingDataLen; index += (pAdvData->length + 1)) {
andresag 0:3aa044e110b8 70 pAdvData = (AdvertisingData_t *)&params->advertisingData[index];
andresag 0:3aa044e110b8 71
andresag 0:3aa044e110b8 72 if (pAdvData->dataType != GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA) {
andresag 0:3aa044e110b8 73 continue;
andresag 0:3aa044e110b8 74 }
andresag 0:3aa044e110b8 75
andresag 0:3aa044e110b8 76 const ApplicationData_t *pAppData = (const ApplicationData_t *)pAdvData->data;
andresag 0:3aa044e110b8 77 if (pAppData->applicationSpecificId == APP_SPECIFIC_ID_TEST) {
andresag 0:3aa044e110b8 78 uint32_t beaconId = (params->peerAddr[3] << 24) | (params->peerAddr[2] << 16) | (params->peerAddr[1] << 8) | (params->peerAddr[0]);
andresag 0:3aa044e110b8 79 TMP_nrf51::TempSensorValue_t temperature = (TMP_nrf51::TempSensorValue_t)pAppData->tmpSensorValue;
andresag 0:3aa044e110b8 80
andresag 0:3aa044e110b8 81 /* If new data was added to the table, then update the payload */
andresag 0:3aa044e110b8 82 temperatureTable.addBeacon(beaconId, temperature);
andresag 0:3aa044e110b8 83 if (temperatureTable.hasUpdate()) {
andresag 0:3aa044e110b8 84 tempGatewayServicePtr->updateTemperature(temperatureTable.getTotalBeacons(), temperatureTable.getBeaconIds(), temperatureTable.getTemperatures());
andresag 0:3aa044e110b8 85 temperatureTable.resetHasUpdate();
andresag 0:3aa044e110b8 86 }
andresag 0:3aa044e110b8 87 break;
andresag 0:3aa044e110b8 88 }
andresag 0:3aa044e110b8 89 }
andresag 0:3aa044e110b8 90 }
andresag 0:3aa044e110b8 91
andresag 0:3aa044e110b8 92 void configureScanTemperature(void)
andresag 0:3aa044e110b8 93 {
andresag 0:3aa044e110b8 94 ble.gap().setScanParams(500 /* scan interval */, 200 /* scan window */);
andresag 0:3aa044e110b8 95 ble.gap().startScan(advertisementCallback);
andresag 0:3aa044e110b8 96 }
andresag 0:3aa044e110b8 97
andresag 0:3aa044e110b8 98 int main(void)
andresag 0:3aa044e110b8 99 {
andresag 0:3aa044e110b8 100 /* Blink LED every second to tell whether the app is running */
andresag 0:3aa044e110b8 101 led1 = 1;
andresag 0:3aa044e110b8 102 Ticker ticker;
andresag 0:3aa044e110b8 103 ticker.attach(periodicCallback, 1);
andresag 0:3aa044e110b8 104
andresag 0:3aa044e110b8 105 ble.init();
andresag 0:3aa044e110b8 106
andresag 0:3aa044e110b8 107 configureScanTemperature();
andresag 0:3aa044e110b8 108
andresag 0:3aa044e110b8 109 ble.gap().onDisconnection(disconnectionCallback);
andresag 0:3aa044e110b8 110
andresag 0:3aa044e110b8 111 /* Setup primary service. */
andresag 0:3aa044e110b8 112 TemperatureGatewayService<MAX_BEACONS> temperatureGatewayService(ble);
andresag 0:3aa044e110b8 113 tempGatewayServicePtr = &temperatureGatewayService;
andresag 0:3aa044e110b8 114
andresag 0:3aa044e110b8 115 /* Setup auxiliary service. */
andresag 0:3aa044e110b8 116 DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
andresag 0:3aa044e110b8 117
andresag 0:3aa044e110b8 118 /* Setup advertising. */
andresag 0:3aa044e110b8 119 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
andresag 0:3aa044e110b8 120 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
andresag 0:3aa044e110b8 121 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
andresag 0:3aa044e110b8 122 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
andresag 0:3aa044e110b8 123 ble.gap().setAdvertisingInterval(1000); /* 1000ms */
andresag 0:3aa044e110b8 124 ble.gap().startAdvertising();
andresag 0:3aa044e110b8 125
andresag 0:3aa044e110b8 126 /* infinite loop */
andresag 0:3aa044e110b8 127 while (1) {
andresag 0:3aa044e110b8 128 ble.waitForEvent(); // low power wait for event
andresag 0:3aa044e110b8 129 }
andresag 0:3aa044e110b8 130 }