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 #ifndef __BLE_TEMP_GATEWAY_SERVICE_H__
andresag 0:3aa044e110b8 18 #define __BLE_TEMP_GATEWAY_SERVICE_H__
andresag 0:3aa044e110b8 19
andresag 0:3aa044e110b8 20 template <unsigned MAX_BEACONS>
andresag 0:3aa044e110b8 21 class TemperatureGatewayService {
andresag 0:3aa044e110b8 22 public:
andresag 0:3aa044e110b8 23 /* UUIDs for service and characteristic. Note that the values are not meaningful,
andresag 0:3aa044e110b8 24 but they are convenient for debugging. */
andresag 0:3aa044e110b8 25 const static uint16_t TEMPERATURE_SERVICE_UUID = 0xFEFF;
andresag 0:3aa044e110b8 26 const static uint16_t TEMPERATURE_LIST_CHARACTERISTIC_UUID = 0xFAFA;
andresag 0:3aa044e110b8 27
andresag 0:3aa044e110b8 28 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)
andresag 0:3aa044e110b8 29 {
andresag 0:3aa044e110b8 30 GattCharacteristic *charTable[] = {&tempListChar};
andresag 0:3aa044e110b8 31 GattService temperatureService(TEMPERATURE_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
andresag 0:3aa044e110b8 32 ble.addService(temperatureService);
andresag 0:3aa044e110b8 33 }
andresag 0:3aa044e110b8 34
andresag 0:3aa044e110b8 35 /* Return the characteristic UUID */
andresag 0:3aa044e110b8 36 GattAttribute::Handle_t getValueHandle() const {
andresag 0:3aa044e110b8 37 return tempListChar.getValueHandle();
andresag 0:3aa044e110b8 38 }
andresag 0:3aa044e110b8 39
andresag 0:3aa044e110b8 40 void updateTemperature(uint8_t totalBeacons, uint32_t* beaconIds, float* temperatures) {
andresag 0:3aa044e110b8 41 size_t payloadSize = tempList.updateBytes(totalBeacons, beaconIds, temperatures);
andresag 0:3aa044e110b8 42 /* We want to send the exact number of bytes i.e. 8 * totalBeacons
andresag 0:3aa044e110b8 43 since each beacon has 4 bytes Id and 4 bytes temperature */
andresag 0:3aa044e110b8 44 ble.gattServer().write(tempListChar.getValueHandle(), tempList.getPointer(), payloadSize);
andresag 0:3aa044e110b8 45 }
andresag 0:3aa044e110b8 46
andresag 0:3aa044e110b8 47 private:
andresag 0:3aa044e110b8 48 /* Private internal representation for the bytes sent over BLE to the client device */
andresag 0:3aa044e110b8 49 struct TemperatureListRepresentation {
andresag 0:3aa044e110b8 50 static const unsigned OFFSET_PER_BEACON = 2 * sizeof(uint32_t);
andresag 0:3aa044e110b8 51 static const unsigned MIN_PAYLOAD_SIZE = 10;
andresag 0:3aa044e110b8 52
andresag 0:3aa044e110b8 53 TemperatureListRepresentation(void) : bytes() {
andresag 0:3aa044e110b8 54 }
andresag 0:3aa044e110b8 55
andresag 0:3aa044e110b8 56 /* Transform the TemperatureTable into plain bytes */
andresag 0:3aa044e110b8 57 size_t updateBytes(uint8_t totalBeacons, const uint32_t* beaconIds, const float* temperatures) {
andresag 0:3aa044e110b8 58 size_t payloadSize = totalBeacons * OFFSET_PER_BEACON * sizeof(uint8_t);
andresag 0:3aa044e110b8 59 if (payloadSize < MIN_PAYLOAD_SIZE) {
andresag 0:3aa044e110b8 60 payloadSize = MIN_PAYLOAD_SIZE;
andresag 0:3aa044e110b8 61 }
andresag 0:3aa044e110b8 62
andresag 0:3aa044e110b8 63 /* Copy each beacon key-value pair into the array */
andresag 0:3aa044e110b8 64 for (uint32_t i = 0; i < totalBeacons; i++) {
andresag 0:3aa044e110b8 65 memcpy(&bytes[i * OFFSET_PER_BEACON], &beaconIds[i], sizeof(uint32_t));
andresag 0:3aa044e110b8 66 uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperatures[i]);
andresag 0:3aa044e110b8 67 memcpy(&bytes[i * OFFSET_PER_BEACON + sizeof(uint32_t)], &temp_ieee11073 , sizeof(uint32_t));
andresag 0:3aa044e110b8 68 }
andresag 0:3aa044e110b8 69 return payloadSize;
andresag 0:3aa044e110b8 70 }
andresag 0:3aa044e110b8 71
andresag 0:3aa044e110b8 72 uint8_t *getPointer(void) {
andresag 0:3aa044e110b8 73 return bytes;
andresag 0:3aa044e110b8 74 }
andresag 0:3aa044e110b8 75
andresag 0:3aa044e110b8 76 const uint8_t *getPointer(void) const {
andresag 0:3aa044e110b8 77 return bytes;
andresag 0:3aa044e110b8 78 }
andresag 0:3aa044e110b8 79
andresag 0:3aa044e110b8 80 private:
andresag 0:3aa044e110b8 81 /**
andresag 0:3aa044e110b8 82 * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
andresag 0:3aa044e110b8 83 * @param temperature The temperature as a float.
andresag 0:3aa044e110b8 84 * @return The temperature in 11073-20601 FLOAT-Type format.
andresag 0:3aa044e110b8 85 */
andresag 0:3aa044e110b8 86 uint32_t quick_ieee11073_from_float(float temperature) {
andresag 0:3aa044e110b8 87 uint8_t exponent = 0xFE; //exponent is -2
andresag 0:3aa044e110b8 88 uint32_t mantissa = (uint32_t)(temperature * 100);
andresag 0:3aa044e110b8 89
andresag 0:3aa044e110b8 90 return (((uint32_t)exponent) << 24) | mantissa;
andresag 0:3aa044e110b8 91 }
andresag 0:3aa044e110b8 92
andresag 0:3aa044e110b8 93 private:
andresag 0:3aa044e110b8 94 /* This array contains the actual bytes to be sent over BLE. However, we send as much data
andresag 0:3aa044e110b8 95 as we need to, not the whole array (unless we reached max capacity.
andresag 0:3aa044e110b8 96 The data is organised as follows:
andresag 0:3aa044e110b8 97 BeaconId0 - Temperature0 - BeaconId1 - Temperature1 -.....- BeaconIdN - TemperatureN
andresag 0:3aa044e110b8 98 Note that each item is composed of 4 bytes. */
andresag 0:3aa044e110b8 99 uint8_t bytes[MAX_BEACONS * OFFSET_PER_BEACON];
andresag 0:3aa044e110b8 100 };
andresag 0:3aa044e110b8 101
andresag 0:3aa044e110b8 102 private:
andresag 0:3aa044e110b8 103 BLEDevice &ble;
andresag 0:3aa044e110b8 104 TemperatureListRepresentation tempList;
andresag 0:3aa044e110b8 105 GattCharacteristic tempListChar;
andresag 0:3aa044e110b8 106 };
andresag 0:3aa044e110b8 107
andresag 0:3aa044e110b8 108 #endif /* #ifndef __BLE_TEMP_GATEWAY_SERVICE_H__ */