This is a basic code to be used for Sequana BLE Lab exercises.

Committer:
lru
Date:
Thu Mar 14 09:47:17 2019 +0000
Revision:
0:ff033dfc838b
Initial version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lru 0:ff033dfc838b 1 /*
lru 0:ff033dfc838b 2 * Copyright (c) 20170-2018 Future Electronics
lru 0:ff033dfc838b 3 *
lru 0:ff033dfc838b 4 * Licensed under the Apache License, Version 2.0 (the "License");
lru 0:ff033dfc838b 5 * you may not use this file except in compliance with the License.
lru 0:ff033dfc838b 6 * You may obtain a copy of the License at
lru 0:ff033dfc838b 7 *
lru 0:ff033dfc838b 8 * http://www.apache.org/licenses/LICENSE-2.0
lru 0:ff033dfc838b 9 *
lru 0:ff033dfc838b 10 * Unless required by applicable law or agreed to in writing, software
lru 0:ff033dfc838b 11 * distributed under the License is distributed on an "AS IS" BASIS,
lru 0:ff033dfc838b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
lru 0:ff033dfc838b 13 * See the License for the specific language governing permissions and
lru 0:ff033dfc838b 14 * limitations under the License.
lru 0:ff033dfc838b 15 */
lru 0:ff033dfc838b 16
lru 0:ff033dfc838b 17 #ifndef SENSOR_CHARACTERISTIC_H_
lru 0:ff033dfc838b 18 #define SENSOR_CHARACTERISTIC_H_
lru 0:ff033dfc838b 19
lru 0:ff033dfc838b 20 #include <mbed.h>
lru 0:ff033dfc838b 21 #include "ble/BLE.h"
lru 0:ff033dfc838b 22 #include "Sensor.h"
lru 0:ff033dfc838b 23
lru 0:ff033dfc838b 24 //#define ENABLE_CHAR_TEMPLATE_DEBUG 1
lru 0:ff033dfc838b 25
lru 0:ff033dfc838b 26 namespace sequana {
lru 0:ff033dfc838b 27
lru 0:ff033dfc838b 28 #if ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 29 /** Get differentiating part of the characteristic long UUID.
lru 0:ff033dfc838b 30 *
lru 0:ff033dfc838b 31 * Helper function to help print useful part of the long UUID to identify characteristic.
lru 0:ff033dfc838b 32 */
lru 0:ff033dfc838b 33 static inline uint32_t get_char_id(GattCharacteristic& characteristic)
lru 0:ff033dfc838b 34 {
lru 0:ff033dfc838b 35 const UUID& uuid = characteristic.getValueAttribute().getUUID();
lru 0:ff033dfc838b 36 return uuid.shortOrLong()? *(uint32_t *)(uuid.getBaseUUID()+12) : uuid.getShortUUID();
lru 0:ff033dfc838b 37 }
lru 0:ff033dfc838b 38 #endif // ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 39
lru 0:ff033dfc838b 40
lru 0:ff033dfc838b 41 /** Public interface to buffer holding characteristic binary value.
lru 0:ff033dfc838b 42 *
lru 0:ff033dfc838b 43 * Default implementation is valid only for constant data length characteristics,
lru 0:ff033dfc838b 44 * but can be overloaded to support also dynamic data size.
lru 0:ff033dfc838b 45 *
lru 0:ff033dfc838b 46 * @param ValueT Type representing related sensor value.
lru 0:ff033dfc838b 47 * @param SIZE Size in bytes of the characteristic data part.
lru 0:ff033dfc838b 48 */
lru 0:ff033dfc838b 49 template <typename ValueT, size_t SIZE> class CharBuffer{
lru 0:ff033dfc838b 50 public:
lru 0:ff033dfc838b 51 /** Default constructor.
lru 0:ff033dfc838b 52 *
lru 0:ff033dfc838b 53 * Clears binary data to zero.
lru 0:ff033dfc838b 54 */
lru 0:ff033dfc838b 55 CharBuffer() {memset(_bytes, 0, SIZE);}
lru 0:ff033dfc838b 56
lru 0:ff033dfc838b 57 /** Return pointer to binary data buffer.
lru 0:ff033dfc838b 58 */
lru 0:ff033dfc838b 59 uint8_t *get_ptr() { return _bytes; }
lru 0:ff033dfc838b 60
lru 0:ff033dfc838b 61 /** Return length of the binary data.
lru 0:ff033dfc838b 62 */
lru 0:ff033dfc838b 63 size_t get_length() { return SIZE; }
lru 0:ff033dfc838b 64
lru 0:ff033dfc838b 65 /** Default conversion/assignment operator, performs a simple copy.
lru 0:ff033dfc838b 66 */
lru 0:ff033dfc838b 67 CharBuffer<ValueT, SIZE>& operator= (const ValueT& val)
lru 0:ff033dfc838b 68 {
lru 0:ff033dfc838b 69 memcpy(_bytes, &val, SIZE);
lru 0:ff033dfc838b 70 return *this;
lru 0:ff033dfc838b 71 }
lru 0:ff033dfc838b 72
lru 0:ff033dfc838b 73 protected:
lru 0:ff033dfc838b 74 uint8_t _bytes[SIZE]; // Buffer holding binary representation of characteristic value.
lru 0:ff033dfc838b 75 };
lru 0:ff033dfc838b 76
lru 0:ff033dfc838b 77
lru 0:ff033dfc838b 78 /** Wrapper, holding BLE characteristic with its value buffer
lru 0:ff033dfc838b 79 * and processing value updates.
lru 0:ff033dfc838b 80 *
lru 0:ff033dfc838b 81 * @param B Class representing characteristic's binary data buffer.
lru 0:ff033dfc838b 82 * @param V Data type representing sensor value.
lru 0:ff033dfc838b 83 */
lru 0:ff033dfc838b 84 template <class B, class V> class SensorCharacteristic
lru 0:ff033dfc838b 85 {
lru 0:ff033dfc838b 86 public:
lru 0:ff033dfc838b 87 /** Create BLE characteristic for a sensor.
lru 0:ff033dfc838b 88 *
lru 0:ff033dfc838b 89 * @param ble BLE interface
lru 0:ff033dfc838b 90 * @param uuid characteristic UUID
lru 0:ff033dfc838b 91 * @param sensor sensor interface
lru 0:ff033dfc838b 92 */
lru 0:ff033dfc838b 93 SensorCharacteristic(BLE& ble, const UUID& uuid, Sensor<V>& sensor) :
lru 0:ff033dfc838b 94 _ble(ble),
lru 0:ff033dfc838b 95 _characteristic(uuid,
lru 0:ff033dfc838b 96 &_buffer,
lru 0:ff033dfc838b 97 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
lru 0:ff033dfc838b 98 _sensor(sensor)
lru 0:ff033dfc838b 99 {
lru 0:ff033dfc838b 100 #if ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 101 printf("Registered char 0x%08lx\n", get_char_id(_characteristic));
lru 0:ff033dfc838b 102 #endif // ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 103 _sensor.register_updater(callback(this, &SensorCharacteristic::update));
lru 0:ff033dfc838b 104 }
lru 0:ff033dfc838b 105
lru 0:ff033dfc838b 106 /** Get sensor characteristic.
lru 0:ff033dfc838b 107 *
lru 0:ff033dfc838b 108 * @returns pointer to sensor's GATT characteristic
lru 0:ff033dfc838b 109 */
lru 0:ff033dfc838b 110 GattCharacteristic* get_characteristic() { return &_characteristic; }
lru 0:ff033dfc838b 111
lru 0:ff033dfc838b 112 /** Get characteristic data pointer.
lru 0:ff033dfc838b 113 *
lru 0:ff033dfc838b 114 * @returns pointer to buffer holding characteristic binary data value
lru 0:ff033dfc838b 115 */
lru 0:ff033dfc838b 116 uint8_t *get_ptr() { return _buffer.get_ptr(); }
lru 0:ff033dfc838b 117
lru 0:ff033dfc838b 118 /** Get characteristic data length.
lru 0:ff033dfc838b 119 *
lru 0:ff033dfc838b 120 * @returns characteristic current binary data length
lru 0:ff033dfc838b 121 */
lru 0:ff033dfc838b 122 size_t get_length() { return _buffer.get_length(); }
lru 0:ff033dfc838b 123
lru 0:ff033dfc838b 124 protected:
lru 0:ff033dfc838b 125 /** Process update of the sensor's value.
lru 0:ff033dfc838b 126 */
lru 0:ff033dfc838b 127 void update()
lru 0:ff033dfc838b 128 {
lru 0:ff033dfc838b 129 if (_ble.gap().getState().connected) {
lru 0:ff033dfc838b 130 _buffer = _sensor.get_value();
lru 0:ff033dfc838b 131 #if ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 132 printf("Updating char 0x%08lx with: ", get_char_id(_characteristic));
lru 0:ff033dfc838b 133 uint8_t *ptr = _buffer.get_ptr();
lru 0:ff033dfc838b 134 for (uint32_t i = 0; i < _buffer.get_length(); ++i) {
lru 0:ff033dfc838b 135 printf("%02x", *ptr++);
lru 0:ff033dfc838b 136 }
lru 0:ff033dfc838b 137 printf("\n");
lru 0:ff033dfc838b 138 #endif // ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 139 _ble.gattServer().write(_characteristic.getValueHandle(),
lru 0:ff033dfc838b 140 _buffer.get_ptr(),
lru 0:ff033dfc838b 141 _buffer.get_length());
lru 0:ff033dfc838b 142 }
lru 0:ff033dfc838b 143 }
lru 0:ff033dfc838b 144
lru 0:ff033dfc838b 145
lru 0:ff033dfc838b 146 protected:
lru 0:ff033dfc838b 147 BLE& _ble;
lru 0:ff033dfc838b 148 ReadOnlyGattCharacteristic<B> _characteristic;
lru 0:ff033dfc838b 149 B _buffer;
lru 0:ff033dfc838b 150 Sensor<V>& _sensor;
lru 0:ff033dfc838b 151 };
lru 0:ff033dfc838b 152
lru 0:ff033dfc838b 153
lru 0:ff033dfc838b 154 /*****************************************************************************/
lru 0:ff033dfc838b 155 /* Multi-characteristic sensor */
lru 0:ff033dfc838b 156 /*****************************************************************************/
lru 0:ff033dfc838b 157
lru 0:ff033dfc838b 158
lru 0:ff033dfc838b 159 /** Object describing (parameterizing) single characteristic
lru 0:ff033dfc838b 160 * used to define multi-characteristic sensors.
lru 0:ff033dfc838b 161 */
lru 0:ff033dfc838b 162 struct SingleCharParams {
lru 0:ff033dfc838b 163 UUID* uuid; // characteristic UUID
lru 0:ff033dfc838b 164 uint16_t offset; // offset in the sensor value buffer where characteristic value starts
lru 0:ff033dfc838b 165 uint16_t length; // length of the characteristic value
lru 0:ff033dfc838b 166 };
lru 0:ff033dfc838b 167
lru 0:ff033dfc838b 168 /** Wrapper, holding multiple BLE characteristics with its value buffers
lru 0:ff033dfc838b 169 * and processing value updates.
lru 0:ff033dfc838b 170 *
lru 0:ff033dfc838b 171 * Useful in a case where a single sensor should return multiple characteristic values.
lru 0:ff033dfc838b 172 *
lru 0:ff033dfc838b 173 * @param B Class representing characteristic's binary data buffer.
lru 0:ff033dfc838b 174 * @param V Data type representing sensor value.
lru 0:ff033dfc838b 175 */
lru 0:ff033dfc838b 176 template <size_t N, class B, class V> class SensorMultiCharacteristic
lru 0:ff033dfc838b 177 {
lru 0:ff033dfc838b 178 public:
lru 0:ff033dfc838b 179 /** Create characteristic set for a sensor.
lru 0:ff033dfc838b 180 *
lru 0:ff033dfc838b 181 * @param ble BLE interface
lru 0:ff033dfc838b 182 * @param params set of characteristics and their parameters
lru 0:ff033dfc838b 183 * @param sensor senasor interface
lru 0:ff033dfc838b 184 */
lru 0:ff033dfc838b 185 SensorMultiCharacteristic(BLE& ble, SingleCharParams params[N], Sensor<V>& sensor) :
lru 0:ff033dfc838b 186 _ble(ble),
lru 0:ff033dfc838b 187 _sensor(sensor),
lru 0:ff033dfc838b 188 _params(params)
lru 0:ff033dfc838b 189 {
lru 0:ff033dfc838b 190 for (size_t i = 0; i < N; ++i) {
lru 0:ff033dfc838b 191 SingleCharParams &p = _params[i];
lru 0:ff033dfc838b 192 _characteristic[i] = new GattCharacteristic(
lru 0:ff033dfc838b 193 *p.uuid,
lru 0:ff033dfc838b 194 _buffer.get_ptr() + p.offset,
lru 0:ff033dfc838b 195 p.length,
lru 0:ff033dfc838b 196 p.length,
lru 0:ff033dfc838b 197 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY,
lru 0:ff033dfc838b 198 NULL,
lru 0:ff033dfc838b 199 0,
lru 0:ff033dfc838b 200 false);
lru 0:ff033dfc838b 201 #if ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 202 printf("Registered mchar 0x%08lx\n", get_char_id(*_characteristic[i]));
lru 0:ff033dfc838b 203 #endif // ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 204 }
lru 0:ff033dfc838b 205 _sensor.register_updater(callback(this, &SensorMultiCharacteristic::update));
lru 0:ff033dfc838b 206 }
lru 0:ff033dfc838b 207
lru 0:ff033dfc838b 208 /** Get pointer to GATT characteristic object for n'ths characteristic.
lru 0:ff033dfc838b 209 *
lru 0:ff033dfc838b 210 * @param idx index of the characteristic
lru 0:ff033dfc838b 211 */
lru 0:ff033dfc838b 212 GattCharacteristic* get_characteristic(size_t idx)
lru 0:ff033dfc838b 213 {
lru 0:ff033dfc838b 214 MBED_ASSERT(idx < N);
lru 0:ff033dfc838b 215 return _characteristic[idx];
lru 0:ff033dfc838b 216 }
lru 0:ff033dfc838b 217
lru 0:ff033dfc838b 218 /** Get number of characteristics in this set.
lru 0:ff033dfc838b 219 */
lru 0:ff033dfc838b 220 size_t get_num()
lru 0:ff033dfc838b 221 {
lru 0:ff033dfc838b 222 return N;
lru 0:ff033dfc838b 223 }
lru 0:ff033dfc838b 224
lru 0:ff033dfc838b 225 ~SensorMultiCharacteristic()
lru 0:ff033dfc838b 226 {
lru 0:ff033dfc838b 227 for (size_t i = 0; i < N; ++i) {
lru 0:ff033dfc838b 228 if (_characteristic[i]) {
lru 0:ff033dfc838b 229 delete _characteristic[i];
lru 0:ff033dfc838b 230 }
lru 0:ff033dfc838b 231 }
lru 0:ff033dfc838b 232 }
lru 0:ff033dfc838b 233
lru 0:ff033dfc838b 234 protected:
lru 0:ff033dfc838b 235 void update()
lru 0:ff033dfc838b 236 {
lru 0:ff033dfc838b 237 if (_ble.gap().getState().connected) {
lru 0:ff033dfc838b 238 _buffer = _sensor.get_value();
lru 0:ff033dfc838b 239 for (size_t i = 0; i < N; ++i) {
lru 0:ff033dfc838b 240 SingleCharParams& p = _params[i];
lru 0:ff033dfc838b 241 #if ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 242 printf("Updating mchar 0x%08lx with: ", get_char_id(*_characteristic[i]));
lru 0:ff033dfc838b 243
lru 0:ff033dfc838b 244 uint8_t* ptr = _buffer.get_ptr()+p.offset;
lru 0:ff033dfc838b 245 for (uint32_t j = 0; j < p.length; ++j) {
lru 0:ff033dfc838b 246 printf("%02x", *ptr++);
lru 0:ff033dfc838b 247 }
lru 0:ff033dfc838b 248 printf("\n");
lru 0:ff033dfc838b 249 #endif // ENABLE_CHAR_TEMPLATE_DEBUG
lru 0:ff033dfc838b 250 _ble.gattServer().write(_characteristic[i]->getValueHandle(),
lru 0:ff033dfc838b 251 _buffer.get_ptr() + p.offset,
lru 0:ff033dfc838b 252 p.length);
lru 0:ff033dfc838b 253 }
lru 0:ff033dfc838b 254 }
lru 0:ff033dfc838b 255 }
lru 0:ff033dfc838b 256
lru 0:ff033dfc838b 257 protected:
lru 0:ff033dfc838b 258 BLE& _ble;
lru 0:ff033dfc838b 259 Sensor<V>& _sensor;
lru 0:ff033dfc838b 260 GattCharacteristic* _characteristic[N];
lru 0:ff033dfc838b 261 B _buffer;
lru 0:ff033dfc838b 262 SingleCharParams* _params;
lru 0:ff033dfc838b 263 };
lru 0:ff033dfc838b 264
lru 0:ff033dfc838b 265 } // namespace
lru 0:ff033dfc838b 266
lru 0:ff033dfc838b 267
lru 0:ff033dfc838b 268 #endif // SENSOR_CHARACTERISTIC_H_