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:
Fri Aug 19 11:47:47 2016 +0200
Revision:
4:0c99ff9d2373
Parent:
2:15329a3de04c
Child:
5:9b33cae085cc
Depend on EventQueue library

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