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:43:15 2016 +0200
Revision:
6:15ec6cd75928
Parent:
5:9b33cae085cc
Child:
8:953b3164e80f
Restart advertising on disconnect

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 onConnection(Gap::ConnectionEventCallback_t callback) {
janjongboom 1:17c8f5afa7bc 181 ble->gap().onConnection(callback);
janjongboom 1:17c8f5afa7bc 182 }
Jan Jongboom 4:0c99ff9d2373 183
janjongboom 1:17c8f5afa7bc 184 BLE* getBle(void) {
janjongboom 1:17c8f5afa7bc 185 return ble;
janjongboom 1:17c8f5afa7bc 186 }
Jan Jongboom 4:0c99ff9d2373 187
janjongboom 1:17c8f5afa7bc 188 def_fn(uint8_t, u8)
janjongboom 1:17c8f5afa7bc 189 def_fn(uint16_t, u16)
janjongboom 1:17c8f5afa7bc 190 def_fn(uint32_t, u32)
janjongboom 1:17c8f5afa7bc 191 def_fn(int8_t, i8)
janjongboom 1:17c8f5afa7bc 192 def_fn(int16_t, i16)
janjongboom 1:17c8f5afa7bc 193 def_fn(int32_t, i32)
janjongboom 1:17c8f5afa7bc 194 def_fn(bool, bool)
janjongboom 2:15329a3de04c 195 def_fn(float, float)
Jan Jongboom 4:0c99ff9d2373 196
janjongboom 1:17c8f5afa7bc 197 private:
janjongboom 1:17c8f5afa7bc 198 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
janjongboom 1:17c8f5afa7bc 199 {
janjongboom 1:17c8f5afa7bc 200 if (logging) printf("bleInitComplete\r\n");
Jan Jongboom 4:0c99ff9d2373 201
janjongboom 1:17c8f5afa7bc 202 BLE& ble = params->ble;
janjongboom 1:17c8f5afa7bc 203 ble_error_t error = params->error;
Jan Jongboom 4:0c99ff9d2373 204
janjongboom 1:17c8f5afa7bc 205 if (error != BLE_ERROR_NONE) {
janjongboom 1:17c8f5afa7bc 206 if (logging) printf("BLE Init error %d\r\n", error);
janjongboom 1:17c8f5afa7bc 207 return;
janjongboom 1:17c8f5afa7bc 208 }
Jan Jongboom 4:0c99ff9d2373 209
janjongboom 1:17c8f5afa7bc 210 /* Ensure that it is the default instance of BLE */
janjongboom 1:17c8f5afa7bc 211 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
janjongboom 1:17c8f5afa7bc 212 return;
janjongboom 1:17c8f5afa7bc 213 }
janjongboom 1:17c8f5afa7bc 214
janjongboom 1:17c8f5afa7bc 215 ble.gattServer().onDataWritten(this, &SimpleBLE::onDataWrittenCallback);
Jan Jongboom 4:0c99ff9d2373 216
janjongboom 1:17c8f5afa7bc 217 // let's add some services yo (why is there no 'auto' in mbed?)
janjongboom 1:17c8f5afa7bc 218 uint16_t uuid16_list[uint16_services.size()];
janjongboom 1:17c8f5afa7bc 219 size_t uuid16_counter = 0;
Jan Jongboom 4:0c99ff9d2373 220 {
janjongboom 1:17c8f5afa7bc 221 typedef std::map<uint16_t, vector<GattCharacteristic*>* >::iterator it_type;
janjongboom 1:17c8f5afa7bc 222 for(it_type it = uint16_services.begin(); it != uint16_services.end(); it++) {
janjongboom 1:17c8f5afa7bc 223 if (logging) printf("Creating service 0x%x\n", it->first);
Jan Jongboom 4:0c99ff9d2373 224 uuid16_list[uuid16_counter++] = it->first;
Jan Jongboom 4:0c99ff9d2373 225
janjongboom 1:17c8f5afa7bc 226 GattCharacteristic* charTable[it->second->size()];
janjongboom 1:17c8f5afa7bc 227 for (size_t git = 0; git < it->second->size(); git++) {
janjongboom 1:17c8f5afa7bc 228 charTable[git] = it->second->at(git);
janjongboom 1:17c8f5afa7bc 229 }
Jan Jongboom 4:0c99ff9d2373 230
janjongboom 1:17c8f5afa7bc 231 GattService service(it->first, charTable, it->second->size());
janjongboom 1:17c8f5afa7bc 232 ble.gattServer().addService(service);
janjongboom 1:17c8f5afa7bc 233 }
janjongboom 1:17c8f5afa7bc 234 }
janjongboom 1:17c8f5afa7bc 235
janjongboom 1:17c8f5afa7bc 236 // 128 Bit services
janjongboom 1:17c8f5afa7bc 237 const char* uuid128_list[uint128_services.size()];
janjongboom 1:17c8f5afa7bc 238 size_t uuid128_counter = 0;
janjongboom 1:17c8f5afa7bc 239 {
janjongboom 1:17c8f5afa7bc 240 typedef std::map<string, vector<GattCharacteristic*>* >::iterator it_type;
janjongboom 1:17c8f5afa7bc 241 for(it_type it = uint128_services.begin(); it != uint128_services.end(); it++) {
janjongboom 1:17c8f5afa7bc 242 if (logging) printf("Creating service %s\n", it->first.c_str());
Jan Jongboom 4:0c99ff9d2373 243 uuid128_list[uuid128_counter++] = it->first.c_str();
Jan Jongboom 4:0c99ff9d2373 244
janjongboom 1:17c8f5afa7bc 245 GattCharacteristic* charTable[it->second->size()];
janjongboom 1:17c8f5afa7bc 246 for (size_t git = 0; git < it->second->size(); git++) {
janjongboom 1:17c8f5afa7bc 247 charTable[git] = it->second->at(git);
janjongboom 1:17c8f5afa7bc 248 }
Jan Jongboom 4:0c99ff9d2373 249
janjongboom 1:17c8f5afa7bc 250 GattService service(UUID(it->first.c_str()), charTable, it->second->size());
janjongboom 1:17c8f5afa7bc 251 ble.gattServer().addService(service);
janjongboom 1:17c8f5afa7bc 252 }
janjongboom 1:17c8f5afa7bc 253 }
janjongboom 1:17c8f5afa7bc 254
Jan Jongboom 6:15ec6cd75928 255 ble.gap().onDisconnection(Gap::DisconnectionEventCallback_t(this, &SimpleBLE::disconnectionCallback));
Jan Jongboom 6:15ec6cd75928 256
janjongboom 1:17c8f5afa7bc 257 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
janjongboom 1:17c8f5afa7bc 258 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, uuid16_counter);
janjongboom 1:17c8f5afa7bc 259 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *)uuid128_list, uuid128_counter);
janjongboom 1:17c8f5afa7bc 260 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)name, strlen(name));
janjongboom 1:17c8f5afa7bc 261 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
janjongboom 1:17c8f5afa7bc 262 ble.gap().setAdvertisingInterval(interval);
janjongboom 1:17c8f5afa7bc 263 ble.gap().startAdvertising();
Jan Jongboom 4:0c99ff9d2373 264
janjongboom 1:17c8f5afa7bc 265 if (logging) printf("Started advertising\r\n");
janjongboom 1:17c8f5afa7bc 266 }
Jan Jongboom 4:0c99ff9d2373 267
Jan Jongboom 6:15ec6cd75928 268 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
Jan Jongboom 6:15ec6cd75928 269 {
Jan Jongboom 6:15ec6cd75928 270 BLE::Instance().gap().startAdvertising(); // restart advertising
Jan Jongboom 6:15ec6cd75928 271 }
Jan Jongboom 6:15ec6cd75928 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 5:9b33cae085cc 301 BLE &ble = BLE::Instance();
Jan Jongboom 5:9b33cae085cc 302 eventQueue->post(Callback<void()>(&ble, &BLE::processEvents));
Jan Jongboom 4:0c99ff9d2373 303 }
Jan Jongboom 4:0c99ff9d2373 304
janjongboom 0:2ecd71f6ab04 305 // === START READONLY ===
Jan Jongboom 4:0c99ff9d2373 306
janjongboom 0:2ecd71f6ab04 307 template <typename T>
Jan Jongboom 4:0c99ff9d2373 308 SimpleChar<T> readOnly(uint16_t serviceUuid,
Jan Jongboom 4:0c99ff9d2373 309 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 310 bool enableNotify = true,
janjongboom 0:2ecd71f6ab04 311 T defaultValue = T()) {
Jan Jongboom 4:0c99ff9d2373 312 GattCharacteristic::Properties_t gattChar = enableNotify ?
janjongboom 0:2ecd71f6ab04 313 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:2ecd71f6ab04 314 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ;
janjongboom 0:2ecd71f6ab04 315
Jan Jongboom 4:0c99ff9d2373 316 SimpleCharInternal<T, ReadOnlyGattCharacteristic>* c =
janjongboom 0:2ecd71f6ab04 317 new SimpleCharInternal<T, ReadOnlyGattCharacteristic>(ble, charUuid, gattChar, defaultValue);
Jan Jongboom 4:0c99ff9d2373 318
janjongboom 0:2ecd71f6ab04 319 addToServices(serviceUuid, c->getChar());
Jan Jongboom 4:0c99ff9d2373 320
janjongboom 0:2ecd71f6ab04 321 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 322 }
janjongboom 0:2ecd71f6ab04 323
janjongboom 0:2ecd71f6ab04 324 template <typename T>
Jan Jongboom 4:0c99ff9d2373 325 SimpleChar<T> readOnly(const char* serviceUuid,
Jan Jongboom 4:0c99ff9d2373 326 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 327 bool enableNotify = true,
janjongboom 0:2ecd71f6ab04 328 T defaultValue = T()) {
Jan Jongboom 4:0c99ff9d2373 329 GattCharacteristic::Properties_t gattChar = enableNotify ?
janjongboom 0:2ecd71f6ab04 330 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:2ecd71f6ab04 331 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ;
janjongboom 0:2ecd71f6ab04 332
Jan Jongboom 4:0c99ff9d2373 333 SimpleCharInternal<T, ReadOnlyGattCharacteristic>* c =
janjongboom 0:2ecd71f6ab04 334 new SimpleCharInternal<T, ReadOnlyGattCharacteristic>(ble, charUuid, gattChar, defaultValue);
Jan Jongboom 4:0c99ff9d2373 335
janjongboom 0:2ecd71f6ab04 336 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 337
janjongboom 0:2ecd71f6ab04 338 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 339 }
janjongboom 0:2ecd71f6ab04 340
janjongboom 0:2ecd71f6ab04 341 // === END READONLY ===
Jan Jongboom 4:0c99ff9d2373 342
janjongboom 0:2ecd71f6ab04 343 // === START READWRITE ===
janjongboom 0:2ecd71f6ab04 344
janjongboom 0:2ecd71f6ab04 345 template <typename T>
Jan Jongboom 4:0c99ff9d2373 346 SimpleChar<T> readWrite(uint16_t serviceUuid,
Jan Jongboom 4:0c99ff9d2373 347 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 348 bool enableNotify = true,
janjongboom 0:2ecd71f6ab04 349 T defaultValue = T(),
janjongboom 0:2ecd71f6ab04 350 void(*callback)(T) = NULL) {
Jan Jongboom 4:0c99ff9d2373 351 GattCharacteristic::Properties_t gattChar = enableNotify ?
janjongboom 0:2ecd71f6ab04 352 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:2ecd71f6ab04 353 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ;
janjongboom 0:2ecd71f6ab04 354
Jan Jongboom 4:0c99ff9d2373 355 SimpleCharInternal<T, ReadWriteGattCharacteristic>* c =
janjongboom 0:2ecd71f6ab04 356 new SimpleCharInternal<T, ReadWriteGattCharacteristic>(ble, charUuid, gattChar, defaultValue, callback);
janjongboom 0:2ecd71f6ab04 357
janjongboom 0:2ecd71f6ab04 358 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 359
janjongboom 0:2ecd71f6ab04 360 writeCallbacks[c->getChar()] = c;
janjongboom 0:2ecd71f6ab04 361
janjongboom 0:2ecd71f6ab04 362 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 363 }
Jan Jongboom 4:0c99ff9d2373 364
Jan Jongboom 4:0c99ff9d2373 365
janjongboom 0:2ecd71f6ab04 366
janjongboom 0:2ecd71f6ab04 367 template <typename T>
Jan Jongboom 4:0c99ff9d2373 368 SimpleChar<T> readWrite(const char* serviceUuid,
Jan Jongboom 4:0c99ff9d2373 369 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 370 bool enableNotify = true,
janjongboom 0:2ecd71f6ab04 371 T defaultValue = T(),
janjongboom 0:2ecd71f6ab04 372 void(*callback)(T) = NULL) {
Jan Jongboom 4:0c99ff9d2373 373 GattCharacteristic::Properties_t gattChar = enableNotify ?
janjongboom 0:2ecd71f6ab04 374 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:2ecd71f6ab04 375 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ;
janjongboom 0:2ecd71f6ab04 376
Jan Jongboom 4:0c99ff9d2373 377 SimpleCharInternal<T, ReadWriteGattCharacteristic>* c =
janjongboom 0:2ecd71f6ab04 378 new SimpleCharInternal<T, ReadWriteGattCharacteristic>(ble, charUuid, gattChar, defaultValue, callback);
janjongboom 0:2ecd71f6ab04 379
janjongboom 0:2ecd71f6ab04 380 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 381
janjongboom 0:2ecd71f6ab04 382 writeCallbacks[c->getChar()] = c;
Jan Jongboom 4:0c99ff9d2373 383
janjongboom 0:2ecd71f6ab04 384 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 385 }
Jan Jongboom 4:0c99ff9d2373 386
janjongboom 0:2ecd71f6ab04 387 template <typename T>
Jan Jongboom 4:0c99ff9d2373 388 SimpleChar<T> readWrite(uint16_t serviceUuid,
Jan Jongboom 4:0c99ff9d2373 389 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 390 void(*callback)(T) = NULL) {
janjongboom 0:2ecd71f6ab04 391 return readWrite(serviceUuid, charUuid, true, T(), callback);
janjongboom 0:2ecd71f6ab04 392 }
janjongboom 0:2ecd71f6ab04 393
janjongboom 0:2ecd71f6ab04 394 template <typename T>
Jan Jongboom 4:0c99ff9d2373 395 SimpleChar<T> readWrite(const char* serviceUuid,
Jan Jongboom 4:0c99ff9d2373 396 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 397 void(*callback)(T) = NULL) {
janjongboom 0:2ecd71f6ab04 398 return readWrite(serviceUuid, charUuid, true, T(), callback);
janjongboom 0:2ecd71f6ab04 399 }
Jan Jongboom 4:0c99ff9d2373 400
janjongboom 0:2ecd71f6ab04 401 // === END READWRITE ===
Jan Jongboom 4:0c99ff9d2373 402
janjongboom 0:2ecd71f6ab04 403 // === START WRITEONLY ===
janjongboom 0:2ecd71f6ab04 404
janjongboom 0:2ecd71f6ab04 405 template <typename T>
Jan Jongboom 4:0c99ff9d2373 406 SimpleChar<T> writeOnly(uint16_t serviceUuid,
janjongboom 0:2ecd71f6ab04 407 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 408 void(*callback)(T) = NULL) {
Jan Jongboom 4:0c99ff9d2373 409 SimpleCharInternal<T, WriteOnlyGattCharacteristic>* c =
janjongboom 1:17c8f5afa7bc 410 new SimpleCharInternal<T, WriteOnlyGattCharacteristic>(ble, charUuid, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NONE, T(), callback);
janjongboom 0:2ecd71f6ab04 411
janjongboom 0:2ecd71f6ab04 412 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 413
janjongboom 0:2ecd71f6ab04 414 writeCallbacks[c->getChar()] = c;
janjongboom 0:2ecd71f6ab04 415
janjongboom 0:2ecd71f6ab04 416 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 417 }
janjongboom 0:2ecd71f6ab04 418
janjongboom 0:2ecd71f6ab04 419 template <typename T>
Jan Jongboom 4:0c99ff9d2373 420 SimpleChar<T> writeOnly(const char* serviceUuid,
janjongboom 0:2ecd71f6ab04 421 const UUID& charUuid,
janjongboom 0:2ecd71f6ab04 422 void(*callback)(T) = NULL) {
janjongboom 0:2ecd71f6ab04 423
Jan Jongboom 4:0c99ff9d2373 424 SimpleCharInternal<T, WriteOnlyGattCharacteristic>* c =
janjongboom 1:17c8f5afa7bc 425 new SimpleCharInternal<T, WriteOnlyGattCharacteristic>(ble, charUuid, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NONE, T(), callback);
janjongboom 0:2ecd71f6ab04 426
janjongboom 0:2ecd71f6ab04 427 addToServices(serviceUuid, c->getChar());
janjongboom 0:2ecd71f6ab04 428
janjongboom 0:2ecd71f6ab04 429 writeCallbacks[c->getChar()] = c;
Jan Jongboom 4:0c99ff9d2373 430
janjongboom 0:2ecd71f6ab04 431 return *(new SimpleChar<T>(c));
janjongboom 0:2ecd71f6ab04 432 }
Jan Jongboom 4:0c99ff9d2373 433
janjongboom 1:17c8f5afa7bc 434 // === END WRITEONLY ===
janjongboom 0:2ecd71f6ab04 435
janjongboom 0:2ecd71f6ab04 436 BLE* ble;
janjongboom 0:2ecd71f6ab04 437 const char* name;
janjongboom 0:2ecd71f6ab04 438 uint16_t interval;
janjongboom 1:17c8f5afa7bc 439 bool logging;
janjongboom 0:2ecd71f6ab04 440 map<uint16_t, vector<GattCharacteristic*>* > uint16_services;
janjongboom 0:2ecd71f6ab04 441 map<string, vector<GattCharacteristic*>* > uint128_services;
janjongboom 0:2ecd71f6ab04 442 map<GattCharacteristic*, Updatable*> writeCallbacks;
Jan Jongboom 4:0c99ff9d2373 443 EventQueue* eventQueue;
janjongboom 0:2ecd71f6ab04 444 };
janjongboom 0:2ecd71f6ab04 445