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
TemperatureGatewayService.h@0:3aa044e110b8, 2015-10-05 (annotated)
- 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?
User | Revision | Line number | New 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__ */ |