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

Committer:
andresag
Date:
2015-10-05
Revision:
0:3aa044e110b8

File content as of revision 0:3aa044e110b8:

/* 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__ */