Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
Revision 0:3aa044e110b8, committed 2015-10-05
- Comitter:
- andresag
- Date:
- Mon Oct 05 12:59:40 2015 +0000
- Commit message:
- Initial version of a simple BLE temperature gateway that scans temperature broadcasts while simultaneously acting as a peripheral.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BLE_API.lib Mon Oct 05 12:59:40 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#d494ad3e87bd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/TMP_nrf51/TMP_nrf51.cpp Mon Oct 05 12:59:40 2015 +0000
@@ -0,0 +1,31 @@
+/* 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 "TMP_nrf51.h"
+#include "nrf_soc.h" // for internal thermometer sensor
+
+/**
+ * @brief Get the temperature value.
+ *
+ * @return Die temperature in °C
+ */
+TMP_nrf51::TempSensorValue_t TMP_nrf51::get(void)
+{
+ int32_t p_temp;
+ sd_temp_get(&p_temp);
+
+ return ((TempSensorValue_t)p_temp * 0.25); /* 0.25 is temperature sensor resolution */
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/TMP_nrf51/TMP_nrf51.h Mon Oct 05 12:59:40 2015 +0000
@@ -0,0 +1,37 @@
+/* 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 TMP_NRF51_H
+#define TMP_NRF51_H
+
+#include "mbed.h"
+
+//!Library for the nrf51822 internal temperature sensor.
+
+class TMP_nrf51
+{
+public:
+ typedef float TempSensorValue_t;
+
+ /**
+ * @brief Get the temperature value.
+ *
+ * @return Die temperature in °C.
+ */
+ TempSensorValue_t get(void);
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/TemperatureGatewayService.h Mon Oct 05 12:59:40 2015 +0000
@@ -0,0 +1,108 @@
+/* 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_TEMP_GATEWAY_SERVICE_H__
+#define __BLE_TEMP_GATEWAY_SERVICE_H__
+
+template <unsigned MAX_BEACONS>
+class TemperatureGatewayService {
+public:
+ /* UUIDs for service and characteristic. Note that the values are not meaningful,
+ but they are convenient for debugging. */
+ const static uint16_t TEMPERATURE_SERVICE_UUID = 0xFEFF;
+ const static uint16_t TEMPERATURE_LIST_CHARACTERISTIC_UUID = 0xFAFA;
+
+ TemperatureGatewayService(BLEDevice &_ble) : ble(_ble), tempList(), tempListChar(TEMPERATURE_LIST_CHARACTERISTIC_UUID, tempList.getPointer(), 0, MAX_BEACONS * TemperatureListRepresentation::OFFSET_PER_BEACON, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NONE)
+ {
+ GattCharacteristic *charTable[] = {&tempListChar};
+ GattService temperatureService(TEMPERATURE_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+ ble.addService(temperatureService);
+ }
+
+ /* Return the characteristic UUID */
+ GattAttribute::Handle_t getValueHandle() const {
+ return tempListChar.getValueHandle();
+ }
+
+ void updateTemperature(uint8_t totalBeacons, uint32_t* beaconIds, float* temperatures) {
+ size_t payloadSize = tempList.updateBytes(totalBeacons, beaconIds, temperatures);
+ /* We want to send the exact number of bytes i.e. 8 * totalBeacons
+ since each beacon has 4 bytes Id and 4 bytes temperature */
+ ble.gattServer().write(tempListChar.getValueHandle(), tempList.getPointer(), payloadSize);
+ }
+
+private:
+ /* Private internal representation for the bytes sent over BLE to the client device */
+ struct TemperatureListRepresentation {
+ static const unsigned OFFSET_PER_BEACON = 2 * sizeof(uint32_t);
+ static const unsigned MIN_PAYLOAD_SIZE = 10;
+
+ TemperatureListRepresentation(void) : bytes() {
+ }
+
+ /* Transform the TemperatureTable into plain bytes */
+ size_t updateBytes(uint8_t totalBeacons, const uint32_t* beaconIds, const float* temperatures) {
+ size_t payloadSize = totalBeacons * OFFSET_PER_BEACON * sizeof(uint8_t);
+ if (payloadSize < MIN_PAYLOAD_SIZE) {
+ payloadSize = MIN_PAYLOAD_SIZE;
+ }
+
+ /* Copy each beacon key-value pair into the array */
+ for (uint32_t i = 0; i < totalBeacons; i++) {
+ memcpy(&bytes[i * OFFSET_PER_BEACON], &beaconIds[i], sizeof(uint32_t));
+ uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperatures[i]);
+ memcpy(&bytes[i * OFFSET_PER_BEACON + sizeof(uint32_t)], &temp_ieee11073 , sizeof(uint32_t));
+ }
+ return payloadSize;
+ }
+
+ uint8_t *getPointer(void) {
+ return bytes;
+ }
+
+ const uint8_t *getPointer(void) const {
+ return bytes;
+ }
+
+private:
+ /**
+ * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
+ * @param temperature The temperature as a float.
+ * @return The temperature in 11073-20601 FLOAT-Type format.
+ */
+ uint32_t quick_ieee11073_from_float(float temperature) {
+ uint8_t exponent = 0xFE; //exponent is -2
+ uint32_t mantissa = (uint32_t)(temperature * 100);
+
+ return (((uint32_t)exponent) << 24) | mantissa;
+ }
+
+private:
+ /* This array contains the actual bytes to be sent over BLE. However, we send as much data
+ as we need to, not the whole array (unless we reached max capacity.
+ The data is organised as follows:
+ BeaconId0 - Temperature0 - BeaconId1 - Temperature1 -.....- BeaconIdN - TemperatureN
+ Note that each item is composed of 4 bytes. */
+ uint8_t bytes[MAX_BEACONS * OFFSET_PER_BEACON];
+ };
+
+private:
+ BLEDevice &ble;
+ TemperatureListRepresentation tempList;
+ GattCharacteristic tempListChar;
+};
+
+#endif /* #ifndef __BLE_TEMP_GATEWAY_SERVICE_H__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/TemperatureTable.h Mon Oct 05 12:59:40 2015 +0000
@@ -0,0 +1,76 @@
+/* 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_TEMPERATURE_TABLE_H__
+#define __BLE_TEMPERATURE_TABLE_H__
+
+template <typename BeaconIDType, typename TemperatureType, unsigned MAX_SIZE>
+class TemperatureTable {
+public:
+ TemperatureTable(void) : totalBeacons(0), hasUpdatedData(true), tempValues(), beaconIds() {
+ /* empty */
+ }
+
+ /* Add temperature to the table IF AND ONLY IF the data is not already there */
+ void addBeacon(BeaconIDType beaconId, TemperatureType temperature) {
+ for (unsigned i = 0; i < totalBeacons; i++) {
+ if (beaconId == beaconIds[i]) {
+ if (tempValues[i] != temperature) { /* Update old temperature value */
+ tempValues[i] = temperature;
+ hasUpdatedData = true;
+ }
+ return;
+ }
+ }
+
+ /* The beacon doesn't exist in the table; add an entry if there is space. */
+ if (totalBeacons < MAX_SIZE) {
+ beaconIds[totalBeacons] = beaconId;
+ tempValues[totalBeacons] = temperature;
+ totalBeacons++;
+ hasUpdatedData = true;
+ }
+ }
+
+
+ TemperatureType *getTemperatures(void) {
+ return tempValues;
+ }
+
+ size_t getTotalBeacons(void) const {
+ return totalBeacons;
+ }
+
+ BeaconIDType *getBeaconIds(void) {
+ return beaconIds;
+ }
+
+ bool hasUpdate(void) const {
+ return hasUpdatedData;
+ }
+
+ void resetHasUpdate(void) {
+ hasUpdatedData = false;
+ }
+
+private:
+ size_t totalBeacons;
+ bool hasUpdatedData;
+ TemperatureType tempValues[MAX_SIZE];
+ BeaconIDType beaconIds[MAX_SIZE];
+};
+
+#endif /* #ifndef __BLE_TEMPERATURE_TABLE_H__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Mon Oct 05 12:59:40 2015 +0000
@@ -0,0 +1,130 @@
+/* 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 "mbed.h"
+#include "ble/BLE.h"
+#include "ble/services/BatteryService.h"
+#include "ble/services/DeviceInformationService.h"
+
+#include "toolchain.h"
+#include "TMP_nrf51/TMP_nrf51.h"
+#include "TemperatureGatewayService.h"
+#include "TemperatureTable.h"
+
+#define MAX_BEACONS 10
+
+BLE ble;
+DigitalOut led1(LED1);
+
+TemperatureGatewayService<MAX_BEACONS>* tempGatewayServicePtr;
+TemperatureTable<uint32_t, float, MAX_BEACONS> temperatureTable;
+
+/* Setup device name and new service information */
+const static char DEVICE_NAME[] = "TGW1";
+static const uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE,
+ GattService::UUID_DEVICE_INFORMATION_SERVICE};
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
+{
+ ble.gap().startAdvertising(); // restart advertising
+}
+
+void periodicCallback(void)
+{
+ led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
+}
+
+void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
+
+ struct AdvertisingData_t {
+ uint8_t length; /* doesn't include itself */
+ GapAdvertisingData::DataType_t dataType;
+ uint8_t data[0];
+ } PACKED;
+
+ struct ApplicationData_t {
+ uint16_t applicationSpecificId; /* An ID used to identify temperature value
+ in the manufacture specific AD data field */
+ TMP_nrf51::TempSensorValue_t tmpSensorValue; /* User defined application data */
+ } PACKED;
+
+ /* This ID is not very meaningful, but makes it easy to find the device for debugging */
+ static const uint16_t APP_SPECIFIC_ID_TEST = 0xFEFE;
+
+ /* Search for the manufacturer specific data with matching application-ID */
+ AdvertisingData_t *pAdvData;
+ for (size_t index = 0; index < params->advertisingDataLen; index += (pAdvData->length + 1)) {
+ pAdvData = (AdvertisingData_t *)¶ms->advertisingData[index];
+
+ if (pAdvData->dataType != GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA) {
+ continue;
+ }
+
+ const ApplicationData_t *pAppData = (const ApplicationData_t *)pAdvData->data;
+ if (pAppData->applicationSpecificId == APP_SPECIFIC_ID_TEST) {
+ uint32_t beaconId = (params->peerAddr[3] << 24) | (params->peerAddr[2] << 16) | (params->peerAddr[1] << 8) | (params->peerAddr[0]);
+ TMP_nrf51::TempSensorValue_t temperature = (TMP_nrf51::TempSensorValue_t)pAppData->tmpSensorValue;
+
+ /* If new data was added to the table, then update the payload */
+ temperatureTable.addBeacon(beaconId, temperature);
+ if (temperatureTable.hasUpdate()) {
+ tempGatewayServicePtr->updateTemperature(temperatureTable.getTotalBeacons(), temperatureTable.getBeaconIds(), temperatureTable.getTemperatures());
+ temperatureTable.resetHasUpdate();
+ }
+ break;
+ }
+ }
+}
+
+void configureScanTemperature(void)
+{
+ ble.gap().setScanParams(500 /* scan interval */, 200 /* scan window */);
+ ble.gap().startScan(advertisementCallback);
+}
+
+int main(void)
+{
+ /* Blink LED every second to tell whether the app is running */
+ led1 = 1;
+ Ticker ticker;
+ ticker.attach(periodicCallback, 1);
+
+ ble.init();
+
+ configureScanTemperature();
+
+ ble.gap().onDisconnection(disconnectionCallback);
+
+ /* Setup primary service. */
+ TemperatureGatewayService<MAX_BEACONS> temperatureGatewayService(ble);
+ tempGatewayServicePtr = &temperatureGatewayService;
+
+ /* Setup auxiliary service. */
+ DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
+
+ /* Setup advertising. */
+ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
+ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+ ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+ ble.gap().setAdvertisingInterval(1000); /* 1000ms */
+ ble.gap().startAdvertising();
+
+ /* infinite loop */
+ while (1) {
+ ble.waitForEvent(); // low power wait for event
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Oct 05 12:59:40 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/4f6c30876dfa \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nRF51822.lib Mon Oct 05 12:59:40 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#088f5738bf18