Library that exposes BLE characteristics as ordinary variables.

Dependents:   SimpleBLE-Example-mbed-os-5 SimpleBLE-Example ObCP_ENSMM_Test SimpleBLE-ObCP_ENSMM_V2019_Test_BLE

Looking for example code? See SimpleBLE-Example.

Looking for the blog post about this library? See A new Bluetooth library: SimpleBLE.

SimpleBLE is a library which allows you to easily add Bluetooth Low Energy support to any application, without having to change the way you write code. It's goal is to expose any value or sensor over BLE in a single line of code. Let's say you're reading a sensor value every second from pin A0:

uint16_t lightValue;

AnalogIn light(A0);
void read() {
  lightValue = light.read_u16();
  printf("Value is now %d\n", lightValue);
}

Ticker t;
t.attach(&read, 1.0f);

Now we can expose this sensor to any BLE client using SimpleBLE:

SimpleChar<uint16_t> lightValue = ble.readOnly_u16(0x8000, 0x8001);

AnalogIn light(A0);
void read() {
  lightValue = light.read_u16();
  printf("Value is now %d\n", lightValue);
}

Ticker t;
t.attach(&read, 1.0f);

SimpleBLE will automatically gather services for you, bootstrap the BLE runtime, react to write callbacks and update the underlying BLE characteristic whenever the variable gets changed.

Setting up the library

First import this library to the application where you want to use it. Then load SimpleBLE like this:

#include "mbed.h"
#include "SimpleBLE.h"

SimpleBLE ble("DEVICE_NAME"); // second argument is the advertisement interval (default: 1000 ms.)

// variables here!

int main(int, char**) {
    ble.start();
    while (1) {
        ble.waitForEvent();
    }
}

You'll also need to import the BLE library for your platform (e.g. nrf51822 for nRF51-DK and micro:bit). If you grab the example program, all should be set.

After you build and flash this application the device will now show up as 'DEVICE_NAME' in any BLE scanner like nRF Master Control Panel.

Reading and writing values

Every variable that you declare after creating the `SimpleBLE` object, and calling `start()` will automatically be exposed over BLE. We have three different types of objects:

  • readOnly - Variable can only be read over BLE.
  • readWrite - Variable can be read and written over BLE.
  • writeOnly - Variable can be written over BLE, but not read.

Creating a new variable is done by calling the respective function on the simpleBLE object, postfixed by the type you want the variable to have:

SimpleBLE ble("DEVICE_NAME");

SimpleChar<uint8_t> myVar = ble.readOnly_u8(0x8200, 0x8201); // creates uint8_t

The postfix has to be either: u8 (uint8_t), u16 (uint16_t), u32 (uint32_t), i8 (int8_t), i16 (int16_t), i32 (int32_t), bool (bool) or float (float).

The functions take four (non-write) or five (write) arguments:

  • serviceUUID - Which service should this variable fall under. Either use a uint16_t (shorthand) or you can use a string (full UUID).
  • characterUUID - Which character this variable should have. Also, use uint16_t or a string.
  • observable - Whether a BLE client can subscribe to updates on this characteristic (default: true).
  • defaultValue - Default value of the characteristic (default: 0 or 0.0f, depending on your type).
  • callback - Function to be called whenever the value of your characteristic was updated over BLE (only available for variables that support writing).

For example, this is how we make a non-observable readWrite characteristic, with a default value of 100, and a callback function:

SimpleBLE ble("DEVICE_NAME");

void updated(uint32_t newValue) {
  printf("My value was updated, and is now %d\n", newValue);
}

SimpleChar<uint32_t> myVar = ble.readWrite_u32(0x9341, 0x9342, false, 100, &updated);

Just like normal variables

SimpleBLE variables behave just like normal variables, you can read and write straight from them. For example, this will compile just fine:

SimpleChar<uint8_t> heartrate = ble.readOnly_u8(0x180d, 0x2a37, true, 100);

void updateHr() {
  heartrate = heartrate + 1;
  if (heartrate > 180) {
    heartrate = 100;
  }
}

Ticker t;
t.attach(updateHr, 1.0f);

What to use it for?

I wrote this library because I do quite a lot of workshops and hackathons, and I have seen that BLE_API is too complicated for people who do not do embedded development or C++ on a daily basis. Exposing a new sensor over Bluetooth should be a single line of code. So if you're running any workshops, give this lib a go and let me know your experiences.

Committer:
Jan Jongboom
Date:
Mon Oct 10 12:12:21 2016 +0200
Revision:
5:9b33cae085cc
Parent:
4:0c99ff9d2373
Child:
6:15ec6cd75928
Working on mbed-os-5.1.5

Who changed what in which revision?

UserRevisionLine numberNew contents of line
janjongboom 1:17c8f5afa7bc 1 /*
janjongboom 1:17c8f5afa7bc 2 * Copyright (c) 2015 ARM Limited. All rights reserved.
janjongboom 1:17c8f5afa7bc 3 * SPDX-License-Identifier: Apache-2.0
janjongboom 1:17c8f5afa7bc 4 * Licensed under the Apache License, Version 2.0 (the License); you may
janjongboom 1:17c8f5afa7bc 5 * not use this file except in compliance with the License.
janjongboom 1:17c8f5afa7bc 6 * You may obtain a copy of the License at
janjongboom 1:17c8f5afa7bc 7 *
janjongboom 1:17c8f5afa7bc 8 * http://www.apache.org/licenses/LICENSE-2.0
janjongboom 1:17c8f5afa7bc 9 *
janjongboom 1:17c8f5afa7bc 10 * Unless required by applicable law or agreed to in writing, software
janjongboom 1:17c8f5afa7bc 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
janjongboom 1:17c8f5afa7bc 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
janjongboom 1:17c8f5afa7bc 13 * See the License for the specific language governing permissions and
janjongboom 1:17c8f5afa7bc 14 * limitations under the License.
janjongboom 0:2ecd71f6ab04 15 */
Jan Jongboom 4:0c99ff9d2373 16
janjongboom 0:2ecd71f6ab04 17 #include <string>
janjongboom 0:2ecd71f6ab04 18 #include <sstream>
janjongboom 0:2ecd71f6ab04 19 #include <vector>
janjongboom 0:2ecd71f6ab04 20 #include <map>
Jan Jongboom 5:9b33cae085cc 21 #include <mbed-events/events.h>
Jan Jongboom 5:9b33cae085cc 22 #include <mbed.h>
janjongboom 0:2ecd71f6ab04 23 #include "ble/BLE.h"
janjongboom 0:2ecd71f6ab04 24
janjongboom 1:17c8f5afa7bc 25 #define def_fn(T, postfix) \
janjongboom 1:17c8f5afa7bc 26 SimpleChar<T> readOnly_##postfix \
janjongboom 1:17c8f5afa7bc 27 (uint16_t serviceUuid, const UUID& charUuid, bool enableNotify = true, T defaultValue = T()) { \
janjongboom 1:17c8f5afa7bc 28 return readOnly<T>(serviceUuid, charUuid, enableNotify, defaultValue); \
janjongboom 1:17c8f5afa7bc 29 }\
janjongboom 1:17c8f5afa7bc 30 SimpleChar<T> readOnly_##postfix \
janjongboom 1:17c8f5afa7bc 31 (const char* serviceUuid, const UUID& charUuid, bool enableNotify = true, T defaultValue = T()) { \
janjongboom 1:17c8f5afa7bc 32 return readOnly<T>(serviceUuid, charUuid, enableNotify, defaultValue); \
janjongboom 1:17c8f5afa7bc 33 }\
janjongboom 1:17c8f5afa7bc 34 \
janjongboom 1:17c8f5afa7bc 35 SimpleChar<T> readWrite_##postfix \
janjongboom 1:17c8f5afa7bc 36 (uint16_t serviceUuid, const UUID& charUuid, bool enableNotify = true, T defaultValue = T(), void(*callback)(T) = NULL) { \
janjongboom 1:17c8f5afa7bc 37 return readWrite<T>(serviceUuid, charUuid, enableNotify, defaultValue, callback); \
janjongboom 1:17c8f5afa7bc 38 }\
janjongboom 1:17c8f5afa7bc 39 SimpleChar<T> readWrite_##postfix \
janjongboom 1:17c8f5afa7bc 40 (const char* serviceUuid, const UUID& charUuid, bool enableNotify = true, T defaultValue = T(), void(*callback)(T) = NULL) { \
janjongboom 1:17c8f5afa7bc 41 return readWrite<T>(serviceUuid, charUuid, enableNotify, defaultValue, callback); \
janjongboom 1:17c8f5afa7bc 42 }\
janjongboom 1:17c8f5afa7bc 43 SimpleChar<T> readWrite_##postfix \
janjongboom 1:17c8f5afa7bc 44 (uint16_t serviceUuid, const UUID& charUuid, void(*callback)(T) = NULL) { \
janjongboom 1:17c8f5afa7bc 45 return readWrite<T>(serviceUuid, charUuid, callback); \
janjongboom 1:17c8f5afa7bc 46 }\
janjongboom 1:17c8f5afa7bc 47 SimpleChar<T> readWrite_##postfix \
janjongboom 1:17c8f5afa7bc 48 (const char* serviceUuid, const UUID& charUuid, void(*callback)(T) = NULL) { \
janjongboom 1:17c8f5afa7bc 49 return readWrite<T>(serviceUuid, charUuid, callback); \
janjongboom 1:17c8f5afa7bc 50 }\
janjongboom 1:17c8f5afa7bc 51 \
janjongboom 1:17c8f5afa7bc 52 SimpleChar<T> writeOnly_##postfix \
janjongboom 1:17c8f5afa7bc 53 (uint16_t serviceUuid, const UUID& charUuid, void(*callback)(T) = NULL) { \
janjongboom 1:17c8f5afa7bc 54 return writeOnly<T>(serviceUuid, charUuid, callback); \
janjongboom 1:17c8f5afa7bc 55 }\
janjongboom 1:17c8f5afa7bc 56 SimpleChar<T> writeOnly_##postfix \
janjongboom 1:17c8f5afa7bc 57 (const char* serviceUuid, const UUID& charUuid, void(*callback)(T) = NULL) { \
janjongboom 1:17c8f5afa7bc 58 return writeOnly<T>(serviceUuid, charUuid, callback); \
janjongboom 1:17c8f5afa7bc 59 }
janjongboom 1:17c8f5afa7bc 60
janjongboom 0:2ecd71f6ab04 61 using namespace std;
janjongboom 0:2ecd71f6ab04 62
janjongboom 0:2ecd71f6ab04 63 /**
janjongboom 0:2ecd71f6ab04 64 * Class so we can call onDataWritten on any SimpleCharInternal regardless of <T,U>
janjongboom 0:2ecd71f6ab04 65 */
janjongboom 0:2ecd71f6ab04 66 class Updatable {
janjongboom 0:2ecd71f6ab04 67 public:
janjongboom 0:2ecd71f6ab04 68 virtual void onDataWritten(const uint8_t* data, size_t len) = 0;
janjongboom 0:2ecd71f6ab04 69 };
janjongboom 0:2ecd71f6ab04 70
janjongboom 0:2ecd71f6ab04 71 /**
janjongboom 0:2ecd71f6ab04 72 * Class that we wrap in SimpleChar so we can just implement operators,
janjongboom 0:2ecd71f6ab04 73 * without having to type the full type of U when using this code.
janjongboom 0:2ecd71f6ab04 74 * Whenever we get 'auto' we can get rid of this.
janjongboom 0:2ecd71f6ab04 75 */
janjongboom 0:2ecd71f6ab04 76 template <class T>
janjongboom 0:2ecd71f6ab04 77 class SimpleCharBase {
janjongboom 0:2ecd71f6ab04 78 public:
janjongboom 0:2ecd71f6ab04 79 virtual void update(T newValue) = 0;
Jan Jongboom 4:0c99ff9d2373 80 virtual T* getValue(void) = 0;
janjongboom 0:2ecd71f6ab04 81 };
janjongboom 0:2ecd71f6ab04 82
janjongboom 0:2ecd71f6ab04 83 /**
janjongboom 0:2ecd71f6ab04 84 * Actual implementation of the char
janjongboom 0:2ecd71f6ab04 85 * T is the underlying type, U is the GattCharacteristic it's wrapping
janjongboom 0:2ecd71f6ab04 86 */
janjongboom 0:2ecd71f6ab04 87 template <class T, template <typename T2> class U>
janjongboom 0:2ecd71f6ab04 88 class SimpleCharInternal : public Updatable, public SimpleCharBase<T> {
janjongboom 0:2ecd71f6ab04 89 public:
Jan Jongboom 4:0c99ff9d2373 90 SimpleCharInternal(BLE* aBle,
Jan Jongboom 4:0c99ff9d2373 91 const UUID &uuid,
Jan Jongboom 4:0c99ff9d2373 92 GattCharacteristic::Properties_t aGattChar,
janjongboom 0:2ecd71f6ab04 93 T aDefaultValue,
janjongboom 0:2ecd71f6ab04 94 void(*aCallback)(T) = NULL) :
janjongboom 0:2ecd71f6ab04 95 ble(aBle), value(new T(aDefaultValue)), callback(aCallback)
janjongboom 0:2ecd71f6ab04 96 {
janjongboom 0:2ecd71f6ab04 97 state = new U<T>(uuid, value, aGattChar);
janjongboom 0:2ecd71f6ab04 98 }
Jan Jongboom 4:0c99ff9d2373 99
janjongboom 0:2ecd71f6ab04 100 ~SimpleCharInternal() {
janjongboom 0:2ecd71f6ab04 101 if (state) {
janjongboom 0:2ecd71f6ab04 102 free(state);
janjongboom 0:2ecd71f6ab04 103 }
janjongboom 0:2ecd71f6ab04 104 if (value) {
janjongboom 0:2ecd71f6ab04 105 free(value);
janjongboom 0:2ecd71f6ab04 106 }
janjongboom 0:2ecd71f6ab04 107 }
Jan Jongboom 4:0c99ff9d2373 108
janjongboom 0:2ecd71f6ab04 109 virtual void update(T newValue) {
janjongboom 0:2ecd71f6ab04 110 *value = newValue;
janjongboom 0:2ecd71f6ab04 111 ble->gattServer().write(state->getValueHandle(), (uint8_t *)value, sizeof(T));
janjongboom 0:2ecd71f6ab04 112 }
Jan Jongboom 4:0c99ff9d2373 113
janjongboom 0:2ecd71f6ab04 114 U<T>* getChar(void) {
janjongboom 0:2ecd71f6ab04 115 return state;
janjongboom 0:2ecd71f6ab04 116 }
janjongboom 0:2ecd71f6ab04 117
janjongboom 0:2ecd71f6ab04 118 virtual T* getValue(void) {
janjongboom 0:2ecd71f6ab04 119 return value;
janjongboom 0:2ecd71f6ab04 120 }
Jan Jongboom 4:0c99ff9d2373 121
janjongboom 0:2ecd71f6ab04 122 virtual void onDataWritten(const uint8_t* data, size_t len) {
janjongboom 0:2ecd71f6ab04 123 *value = ((T*)data)[0];
janjongboom 0:2ecd71f6ab04 124 if (callback) {
janjongboom 0:2ecd71f6ab04 125 callback(*value);
janjongboom 0:2ecd71f6ab04 126 }
janjongboom 0:2ecd71f6ab04 127 }
janjongboom 0:2ecd71f6ab04 128
janjongboom 0:2ecd71f6ab04 129 private:
janjongboom 0:2ecd71f6ab04 130 BLE* ble;
janjongboom 0:2ecd71f6ab04 131 T* value;
janjongboom 0:2ecd71f6ab04 132 U<T>* state;
janjongboom 0:2ecd71f6ab04 133 void(*callback)(T);
janjongboom 0:2ecd71f6ab04 134 };
janjongboom 0:2ecd71f6ab04 135
janjongboom 0:2ecd71f6ab04 136 /**
janjongboom 0:2ecd71f6ab04 137 * This is what the user gets back. it's nice and short so don't have to type much.
janjongboom 0:2ecd71f6ab04 138 * If we get 'auto' we can get rid of this.
janjongboom 0:2ecd71f6ab04 139 */
janjongboom 0:2ecd71f6ab04 140 template <class T>
janjongboom 0:2ecd71f6ab04 141 class SimpleChar {
janjongboom 0:2ecd71f6ab04 142 public:
janjongboom 0:2ecd71f6ab04 143 SimpleChar(SimpleCharBase<T>* aBase) : base(aBase) {
janjongboom 0:2ecd71f6ab04 144 }
janjongboom 0:2ecd71f6ab04 145 ~SimpleChar() {
janjongboom 0:2ecd71f6ab04 146 if (base) {
janjongboom 0:2ecd71f6ab04 147 delete base;
janjongboom 0:2ecd71f6ab04 148 }
janjongboom 0:2ecd71f6ab04 149 }
janjongboom 0:2ecd71f6ab04 150
janjongboom 0:2ecd71f6ab04 151 T operator=(const T& newValue) {
janjongboom 0:2ecd71f6ab04 152 base->update(newValue);
janjongboom 0:2ecd71f6ab04 153 return newValue;
janjongboom 0:2ecd71f6ab04 154 };
janjongboom 0:2ecd71f6ab04 155 operator T() const {
janjongboom 0:2ecd71f6ab04 156 return *(base->getValue());
janjongboom 0:2ecd71f6ab04 157 };
Jan Jongboom 4:0c99ff9d2373 158
janjongboom 0:2ecd71f6ab04 159 private:
janjongboom 0:2ecd71f6ab04 160 SimpleCharBase<T>* base;
janjongboom 0:2ecd71f6ab04 161 };
janjongboom 0:2ecd71f6ab04 162
janjongboom 0:2ecd71f6ab04 163
janjongboom 0:2ecd71f6ab04 164 class SimpleBLE {
janjongboom 0:2ecd71f6ab04 165 public:
Jan Jongboom 4:0c99ff9d2373 166 SimpleBLE(const char* aName, uint16_t aInterval = 1000, bool aLogging = true)
Jan Jongboom 4:0c99ff9d2373 167 : name(aName), interval(aInterval), logging(aLogging)
janjongboom 1:17c8f5afa7bc 168 {
janjongboom 0:2ecd71f6ab04 169 ble = &BLE::Instance();
janjongboom 0:2ecd71f6ab04 170 }
janjongboom 0:2ecd71f6ab04 171 ~SimpleBLE() {}
Jan Jongboom 4:0c99ff9d2373 172
Jan Jongboom 4:0c99ff9d2373 173 void start(EventQueue* aEventQueue) {
Jan Jongboom 4:0c99ff9d2373 174 eventQueue = aEventQueue;
Jan Jongboom 4:0c99ff9d2373 175
Jan Jongboom 5:9b33cae085cc 176 ble->onEventsToProcess(BLE::OnEventsToProcessCallback_t(this, &SimpleBLE::scheduleBleEventsProcessing));
janjongboom 0:2ecd71f6ab04 177 ble->init(this, &SimpleBLE::bleInitComplete);
janjongboom 0:2ecd71f6ab04 178 }
Jan Jongboom 4:0c99ff9d2373 179
janjongboom 1:17c8f5afa7bc 180 void onDisconnection(Gap::DisconnectionEventCallback_t callback) {
janjongboom 1:17c8f5afa7bc 181 ble->gap().onDisconnection(callback);
janjongboom 1:17c8f5afa7bc 182 }
Jan Jongboom 4:0c99ff9d2373 183
janjongboom 1:17c8f5afa7bc 184 void onConnection(Gap::ConnectionEventCallback_t callback) {
janjongboom 1:17c8f5afa7bc 185 ble->gap().onConnection(callback);
janjongboom 1:17c8f5afa7bc 186 }
Jan Jongboom 4:0c99ff9d2373 187
janjongboom 1:17c8f5afa7bc 188 BLE* getBle(void) {
janjongboom 1:17c8f5afa7bc 189 return ble;
janjongboom 1:17c8f5afa7bc 190 }
Jan Jongboom 4:0c99ff9d2373 191
janjongboom 1:17c8f5afa7bc 192 def_fn(uint8_t, u8)
janjongboom 1:17c8f5afa7bc 193 def_fn(uint16_t, u16)
janjongboom 1:17c8f5afa7bc 194 def_fn(uint32_t, u32)
janjongboom 1:17c8f5afa7bc 195 def_fn(int8_t, i8)
janjongboom 1:17c8f5afa7bc 196 def_fn(int16_t, i16)
janjongboom 1:17c8f5afa7bc 197 def_fn(int32_t, i32)
janjongboom 1:17c8f5afa7bc 198 def_fn(bool, bool)
janjongboom 2:15329a3de04c 199 def_fn(float, float)
Jan Jongboom 4:0c99ff9d2373 200
janjongboom 1:17c8f5afa7bc 201 private:
janjongboom 1:17c8f5afa7bc 202 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
janjongboom 1:17c8f5afa7bc 203 {
janjongboom 1:17c8f5afa7bc 204 if (logging) printf("bleInitComplete\r\n");
Jan Jongboom 4:0c99ff9d2373 205
janjongboom 1:17c8f5afa7bc 206 BLE& ble = params->ble;
janjongboom 1:17c8f5afa7bc 207 ble_error_t error = params->error;
Jan Jongboom 4:0c99ff9d2373 208
janjongboom 1:17c8f5afa7bc 209 if (error != BLE_ERROR_NONE) {
janjongboom 1:17c8f5afa7bc 210 if (logging) printf("BLE Init error %d\r\n", error);
janjongboom 1:17c8f5afa7bc 211 return;
janjongboom 1:17c8f5afa7bc 212 }
Jan Jongboom 4:0c99ff9d2373 213
janjongboom 1:17c8f5afa7bc 214 /* Ensure that it is the default instance of BLE */
janjongboom 1:17c8f5afa7bc 215 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
janjongboom 1:17c8f5afa7bc 216 return;
janjongboom 1:17c8f5afa7bc 217 }
janjongboom 1:17c8f5afa7bc 218
janjongboom 1:17c8f5afa7bc 219 ble.gattServer().onDataWritten(this, &SimpleBLE::onDataWrittenCallback);
Jan Jongboom 4:0c99ff9d2373 220
janjongboom 1:17c8f5afa7bc 221 // let's add some services yo (why is there no 'auto' in mbed?)
janjongboom 1:17c8f5afa7bc 222 uint16_t uuid16_list[uint16_services.size()];
janjongboom 1:17c8f5afa7bc 223 size_t uuid16_counter = 0;
Jan Jongboom 4:0c99ff9d2373 224 {
janjongboom 1:17c8f5afa7bc 225 typedef std::map<uint16_t, vector<GattCharacteristic*>* >::iterator it_type;
janjongboom 1:17c8f5afa7bc 226 for(it_type it = uint16_services.begin(); it != uint16_services.end(); it++) {
janjongboom 1:17c8f5afa7bc 227 if (logging) printf("Creating service 0x%x\n", it->first);
Jan Jongboom 4:0c99ff9d2373 228 uuid16_list[uuid16_counter++] = it->first;
Jan Jongboom 4:0c99ff9d2373 229
janjongboom 1:17c8f5afa7bc 230 GattCharacteristic* charTable[it->second->size()];
janjongboom 1:17c8f5afa7bc 231 for (size_t git = 0; git < it->second->size(); git++) {
janjongboom 1:17c8f5afa7bc 232 charTable[git] = it->second->at(git);
janjongboom 1:17c8f5afa7bc 233 }
Jan Jongboom 4:0c99ff9d2373 234
janjongboom 1:17c8f5afa7bc 235 GattService service(it->first, charTable, it->second->size());
janjongboom 1:17c8f5afa7bc 236 ble.gattServer().addService(service);
janjongboom 1:17c8f5afa7bc 237 }
janjongboom 1:17c8f5afa7bc 238 }
janjongboom 1:17c8f5afa7bc 239
janjongboom 1:17c8f5afa7bc 240 // 128 Bit services
janjongboom 1:17c8f5afa7bc 241 const char* uuid128_list[uint128_services.size()];
janjongboom 1:17c8f5afa7bc 242 size_t uuid128_counter = 0;
janjongboom 1:17c8f5afa7bc 243 {
janjongboom 1:17c8f5afa7bc 244 typedef std::map<string, vector<GattCharacteristic*>* >::iterator it_type;
janjongboom 1:17c8f5afa7bc 245 for(it_type it = uint128_services.begin(); it != uint128_services.end(); it++) {
janjongboom 1:17c8f5afa7bc 246 if (logging) printf("Creating service %s\n", it->first.c_str());
Jan Jongboom 4:0c99ff9d2373 247 uuid128_list[uuid128_counter++] = it->first.c_str();
Jan Jongboom 4:0c99ff9d2373 248
janjongboom 1:17c8f5afa7bc 249 GattCharacteristic* charTable[it->second->size()];
janjongboom 1:17c8f5afa7bc 250 for (size_t git = 0; git < it->second->size(); git++) {
janjongboom 1:17c8f5afa7bc 251 charTable[git] = it->second->at(git);
janjongboom 1:17c8f5afa7bc 252 }
Jan Jongboom 4:0c99ff9d2373 253
janjongboom 1:17c8f5afa7bc 254 GattService service(UUID(it->first.c_str()), charTable, it->second->size());
janjongboom 1:17c8f5afa7bc 255 ble.gattServer().addService(service);
janjongboom 1:17c8f5afa7bc 256 }
janjongboom 1:17c8f5afa7bc 257 }
janjongboom 1:17c8f5afa7bc 258
janjongboom 1:17c8f5afa7bc 259 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
janjongboom 1:17c8f5afa7bc 260 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, uuid16_counter);
janjongboom 1:17c8f5afa7bc 261 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *)uuid128_list, uuid128_counter);
janjongboom 1:17c8f5afa7bc 262 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)name, strlen(name));
janjongboom 1:17c8f5afa7bc 263 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
janjongboom 1:17c8f5afa7bc 264 ble.gap().setAdvertisingInterval(interval);
janjongboom 1:17c8f5afa7bc 265 ble.gap().startAdvertising();
Jan Jongboom 4:0c99ff9d2373 266
janjongboom 1:17c8f5afa7bc 267 if (logging) printf("Started advertising\r\n");
janjongboom 1:17c8f5afa7bc 268 }
Jan Jongboom 4:0c99ff9d2373 269
janjongboom 1:17c8f5afa7bc 270 void onDataWrittenCallback(const GattWriteCallbackParams *params) {
janjongboom 1:17c8f5afa7bc 271 // see if we know for which char this message is...
janjongboom 1:17c8f5afa7bc 272 typedef std::map<GattCharacteristic*, Updatable* >::iterator it_type;
janjongboom 1:17c8f5afa7bc 273 for(it_type it = writeCallbacks.begin(); it != writeCallbacks.end(); it++) {
janjongboom 1:17c8f5afa7bc 274 if (it->first->getValueHandle() == params->handle) {
janjongboom 1:17c8f5afa7bc 275 it->second->onDataWritten(params->data, params->len);
janjongboom 1:17c8f5afa7bc 276 }
janjongboom 1:17c8f5afa7bc 277 }
janjongboom 1:17c8f5afa7bc 278 }
Jan Jongboom 4:0c99ff9d2373 279
janjongboom 1:17c8f5afa7bc 280 void addToServices(uint16_t uuid, GattCharacteristic* c) {
janjongboom 1:17c8f5afa7bc 281 if (uint16_services.count(uuid) == 0) {
janjongboom 1:17c8f5afa7bc 282 uint16_services[uuid] = new vector<GattCharacteristic*>();
janjongboom 1:17c8f5afa7bc 283 }
janjongboom 1:17c8f5afa7bc 284
janjongboom 1:17c8f5afa7bc 285 uint16_services[uuid]->push_back(c);
janjongboom 1:17c8f5afa7bc 286 }
Jan Jongboom 4:0c99ff9d2373 287
janjongboom 1:17c8f5afa7bc 288 void addToServices(const char* aUuid, GattCharacteristic* c) {
janjongboom 1:17c8f5afa7bc 289 string uuid(aUuid);
janjongboom 1:17c8f5afa7bc 290 if (uint128_services.count(uuid) == 0) {
janjongboom 1:17c8f5afa7bc 291 uint128_services[uuid] = new vector<GattCharacteristic*>();
janjongboom 1:17c8f5afa7bc 292 }
janjongboom 1:17c8f5afa7bc 293
janjongboom 1:17c8f5afa7bc 294 uint128_services[uuid]->push_back(c);
janjongboom 0:2ecd71f6ab04 295 }
Jan Jongboom 4:0c99ff9d2373 296
Jan Jongboom 4:0c99ff9d2373 297 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
Jan Jongboom 5:9b33cae085cc 298 BLE &ble = BLE::Instance();
Jan Jongboom 5:9b33cae085cc 299 eventQueue->post(Callback<void()>(&ble, &BLE::processEvents));
Jan Jongboom 4:0c99ff9d2373 300 }
Jan Jongboom 4:0c99ff9d2373 301
janjongboom 0:2ecd71f6ab04 302 // === START READONLY ===
Jan Jongboom 4:0c99ff9d2373 303
janjongboom 0:2ecd71f6ab04 304 template <typename T>
Jan Jongboom 4:0c99ff9d2373 305 SimpleChar<T> readOnly(uint16_t serviceUuid,
Jan Jongboom 4:0c99ff9d2373 306 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 307 bool enableNotify = true,
janjongboom 0:2ecd71f6ab04 308 T defaultValue = T()) {
Jan Jongboom 4:0c99ff9d2373 309 GattCharacteristic::Properties_t gattChar = enableNotify ?
janjongboom 0:2ecd71f6ab04 310 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:2ecd71f6ab04 311 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ;
janjongboom 0:2ecd71f6ab04 312
Jan Jongboom 4:0c99ff9d2373 313 SimpleCharInternal<T, ReadOnlyGattCharacteristic>* c =
janjongboom 0:2ecd71f6ab04 314 new SimpleCharInternal<T, ReadOnlyGattCharacteristic>(ble, charUuid, gattChar, defaultValue);
Jan Jongboom 4:0c99ff9d2373 315
janjongboom 0:2ecd71f6ab04 316 addToServices(serviceUuid, c->getChar());
Jan Jongboom 4:0c99ff9d2373 317
janjongboom 0:2ecd71f6ab04 318 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 319 }
janjongboom 0:2ecd71f6ab04 320
janjongboom 0:2ecd71f6ab04 321 template <typename T>
Jan Jongboom 4:0c99ff9d2373 322 SimpleChar<T> readOnly(const char* serviceUuid,
Jan Jongboom 4:0c99ff9d2373 323 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 324 bool enableNotify = true,
janjongboom 0:2ecd71f6ab04 325 T defaultValue = T()) {
Jan Jongboom 4:0c99ff9d2373 326 GattCharacteristic::Properties_t gattChar = enableNotify ?
janjongboom 0:2ecd71f6ab04 327 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:2ecd71f6ab04 328 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ;
janjongboom 0:2ecd71f6ab04 329
Jan Jongboom 4:0c99ff9d2373 330 SimpleCharInternal<T, ReadOnlyGattCharacteristic>* c =
janjongboom 0:2ecd71f6ab04 331 new SimpleCharInternal<T, ReadOnlyGattCharacteristic>(ble, charUuid, gattChar, defaultValue);
Jan Jongboom 4:0c99ff9d2373 332
janjongboom 0:2ecd71f6ab04 333 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 334
janjongboom 0:2ecd71f6ab04 335 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 336 }
janjongboom 0:2ecd71f6ab04 337
janjongboom 0:2ecd71f6ab04 338 // === END READONLY ===
Jan Jongboom 4:0c99ff9d2373 339
janjongboom 0:2ecd71f6ab04 340 // === START READWRITE ===
janjongboom 0:2ecd71f6ab04 341
janjongboom 0:2ecd71f6ab04 342 template <typename T>
Jan Jongboom 4:0c99ff9d2373 343 SimpleChar<T> readWrite(uint16_t serviceUuid,
Jan Jongboom 4:0c99ff9d2373 344 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 345 bool enableNotify = true,
janjongboom 0:2ecd71f6ab04 346 T defaultValue = T(),
janjongboom 0:2ecd71f6ab04 347 void(*callback)(T) = NULL) {
Jan Jongboom 4:0c99ff9d2373 348 GattCharacteristic::Properties_t gattChar = enableNotify ?
janjongboom 0:2ecd71f6ab04 349 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:2ecd71f6ab04 350 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ;
janjongboom 0:2ecd71f6ab04 351
Jan Jongboom 4:0c99ff9d2373 352 SimpleCharInternal<T, ReadWriteGattCharacteristic>* c =
janjongboom 0:2ecd71f6ab04 353 new SimpleCharInternal<T, ReadWriteGattCharacteristic>(ble, charUuid, gattChar, defaultValue, callback);
janjongboom 0:2ecd71f6ab04 354
janjongboom 0:2ecd71f6ab04 355 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 356
janjongboom 0:2ecd71f6ab04 357 writeCallbacks[c->getChar()] = c;
janjongboom 0:2ecd71f6ab04 358
janjongboom 0:2ecd71f6ab04 359 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 360 }
Jan Jongboom 4:0c99ff9d2373 361
Jan Jongboom 4:0c99ff9d2373 362
janjongboom 0:2ecd71f6ab04 363
janjongboom 0:2ecd71f6ab04 364 template <typename T>
Jan Jongboom 4:0c99ff9d2373 365 SimpleChar<T> readWrite(const char* serviceUuid,
Jan Jongboom 4:0c99ff9d2373 366 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 367 bool enableNotify = true,
janjongboom 0:2ecd71f6ab04 368 T defaultValue = T(),
janjongboom 0:2ecd71f6ab04 369 void(*callback)(T) = NULL) {
Jan Jongboom 4:0c99ff9d2373 370 GattCharacteristic::Properties_t gattChar = enableNotify ?
janjongboom 0:2ecd71f6ab04 371 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:2ecd71f6ab04 372 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ;
janjongboom 0:2ecd71f6ab04 373
Jan Jongboom 4:0c99ff9d2373 374 SimpleCharInternal<T, ReadWriteGattCharacteristic>* c =
janjongboom 0:2ecd71f6ab04 375 new SimpleCharInternal<T, ReadWriteGattCharacteristic>(ble, charUuid, gattChar, defaultValue, callback);
janjongboom 0:2ecd71f6ab04 376
janjongboom 0:2ecd71f6ab04 377 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 378
janjongboom 0:2ecd71f6ab04 379 writeCallbacks[c->getChar()] = c;
Jan Jongboom 4:0c99ff9d2373 380
janjongboom 0:2ecd71f6ab04 381 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 382 }
Jan Jongboom 4:0c99ff9d2373 383
janjongboom 0:2ecd71f6ab04 384 template <typename T>
Jan Jongboom 4:0c99ff9d2373 385 SimpleChar<T> readWrite(uint16_t serviceUuid,
Jan Jongboom 4:0c99ff9d2373 386 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 387 void(*callback)(T) = NULL) {
janjongboom 0:2ecd71f6ab04 388 return readWrite(serviceUuid, charUuid, true, T(), callback);
janjongboom 0:2ecd71f6ab04 389 }
janjongboom 0:2ecd71f6ab04 390
janjongboom 0:2ecd71f6ab04 391 template <typename T>
Jan Jongboom 4:0c99ff9d2373 392 SimpleChar<T> readWrite(const char* serviceUuid,
Jan Jongboom 4:0c99ff9d2373 393 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 394 void(*callback)(T) = NULL) {
janjongboom 0:2ecd71f6ab04 395 return readWrite(serviceUuid, charUuid, true, T(), callback);
janjongboom 0:2ecd71f6ab04 396 }
Jan Jongboom 4:0c99ff9d2373 397
janjongboom 0:2ecd71f6ab04 398 // === END READWRITE ===
Jan Jongboom 4:0c99ff9d2373 399
janjongboom 0:2ecd71f6ab04 400 // === START WRITEONLY ===
janjongboom 0:2ecd71f6ab04 401
janjongboom 0:2ecd71f6ab04 402 template <typename T>
Jan Jongboom 4:0c99ff9d2373 403 SimpleChar<T> writeOnly(uint16_t serviceUuid,
janjongboom 0:2ecd71f6ab04 404 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 405 void(*callback)(T) = NULL) {
Jan Jongboom 4:0c99ff9d2373 406 SimpleCharInternal<T, WriteOnlyGattCharacteristic>* c =
janjongboom 1:17c8f5afa7bc 407 new SimpleCharInternal<T, WriteOnlyGattCharacteristic>(ble, charUuid, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NONE, T(), callback);
janjongboom 0:2ecd71f6ab04 408
janjongboom 0:2ecd71f6ab04 409 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 410
janjongboom 0:2ecd71f6ab04 411 writeCallbacks[c->getChar()] = c;
janjongboom 0:2ecd71f6ab04 412
janjongboom 0:2ecd71f6ab04 413 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 414 }
janjongboom 0:2ecd71f6ab04 415
janjongboom 0:2ecd71f6ab04 416 template <typename T>
Jan Jongboom 4:0c99ff9d2373 417 SimpleChar<T> writeOnly(const char* serviceUuid,
janjongboom 0:2ecd71f6ab04 418 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 419 void(*callback)(T) = NULL) {
janjongboom 0:2ecd71f6ab04 420
Jan Jongboom 4:0c99ff9d2373 421 SimpleCharInternal<T, WriteOnlyGattCharacteristic>* c =
janjongboom 1:17c8f5afa7bc 422 new SimpleCharInternal<T, WriteOnlyGattCharacteristic>(ble, charUuid, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NONE, T(), callback);
janjongboom 0:2ecd71f6ab04 423
janjongboom 0:2ecd71f6ab04 424 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 425
janjongboom 0:2ecd71f6ab04 426 writeCallbacks[c->getChar()] = c;
Jan Jongboom 4:0c99ff9d2373 427
janjongboom 0:2ecd71f6ab04 428 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 429 }
Jan Jongboom 4:0c99ff9d2373 430
janjongboom 1:17c8f5afa7bc 431 // === END WRITEONLY ===
janjongboom 0:2ecd71f6ab04 432
janjongboom 0:2ecd71f6ab04 433 BLE* ble;
janjongboom 0:2ecd71f6ab04 434 const char* name;
janjongboom 0:2ecd71f6ab04 435 uint16_t interval;
janjongboom 1:17c8f5afa7bc 436 bool logging;
janjongboom 0:2ecd71f6ab04 437 map<uint16_t, vector<GattCharacteristic*>* > uint16_services;
janjongboom 0:2ecd71f6ab04 438 map<string, vector<GattCharacteristic*>* > uint128_services;
janjongboom 0:2ecd71f6ab04 439 map<GattCharacteristic*, Updatable*> writeCallbacks;
Jan Jongboom 4:0c99ff9d2373 440 EventQueue* eventQueue;
janjongboom 0:2ecd71f6ab04 441 };
janjongboom 0:2ecd71f6ab04 442