Prog pour OBCP Steffen
Embed:
(wiki syntax)
Show/hide line numbers
SimpleBLE.h
00001 /* 00002 * Copyright (c) 2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include <string> 00018 #include <sstream> 00019 #include <vector> 00020 #include <map> 00021 #include "ble/BLE.h" 00022 00023 #define def_fn(T, postfix) \ 00024 SimpleChar<T> readOnly_##postfix \ 00025 (uint16_t serviceUuid, const UUID& charUuid, bool enableNotify = true, T defaultValue = T()) { \ 00026 return readOnly<T>(serviceUuid, charUuid, enableNotify, defaultValue); \ 00027 }\ 00028 SimpleChar<T> readOnly_##postfix \ 00029 (const char* serviceUuid, const UUID& charUuid, bool enableNotify = true, T defaultValue = T()) { \ 00030 return readOnly<T>(serviceUuid, charUuid, enableNotify, defaultValue); \ 00031 }\ 00032 \ 00033 SimpleChar<T> readWrite_##postfix \ 00034 (uint16_t serviceUuid, const UUID& charUuid, bool enableNotify = true, T defaultValue = T(), void(*callback)(T) = NULL) { \ 00035 return readWrite<T>(serviceUuid, charUuid, enableNotify, defaultValue, callback); \ 00036 }\ 00037 SimpleChar<T> readWrite_##postfix \ 00038 (const char* serviceUuid, const UUID& charUuid, bool enableNotify = true, T defaultValue = T(), void(*callback)(T) = NULL) { \ 00039 return readWrite<T>(serviceUuid, charUuid, enableNotify, defaultValue, callback); \ 00040 }\ 00041 SimpleChar<T> readWrite_##postfix \ 00042 (uint16_t serviceUuid, const UUID& charUuid, void(*callback)(T) = NULL) { \ 00043 return readWrite<T>(serviceUuid, charUuid, callback); \ 00044 }\ 00045 SimpleChar<T> readWrite_##postfix \ 00046 (const char* serviceUuid, const UUID& charUuid, void(*callback)(T) = NULL) { \ 00047 return readWrite<T>(serviceUuid, charUuid, callback); \ 00048 }\ 00049 \ 00050 SimpleChar<T> writeOnly_##postfix \ 00051 (uint16_t serviceUuid, const UUID& charUuid, void(*callback)(T) = NULL) { \ 00052 return writeOnly<T>(serviceUuid, charUuid, callback); \ 00053 }\ 00054 SimpleChar<T> writeOnly_##postfix \ 00055 (const char* serviceUuid, const UUID& charUuid, void(*callback)(T) = NULL) { \ 00056 return writeOnly<T>(serviceUuid, charUuid, callback); \ 00057 } 00058 00059 using namespace std; 00060 00061 /** 00062 * Class so we can call onDataWritten on any SimpleCharInternal regardless of <T,U> 00063 */ 00064 class Updatable { 00065 public: 00066 virtual void onDataWritten(const uint8_t* data, size_t len) = 0; 00067 }; 00068 00069 /** 00070 * Class that we wrap in SimpleChar so we can just implement operators, 00071 * without having to type the full type of U when using this code. 00072 * Whenever we get 'auto' we can get rid of this. 00073 */ 00074 template <class T> 00075 class SimpleCharBase { 00076 public: 00077 virtual void update(T newValue) = 0; 00078 virtual T* getValue(void) = 0; 00079 }; 00080 00081 /** 00082 * Actual implementation of the char 00083 * T is the underlying type, U is the GattCharacteristic it's wrapping 00084 */ 00085 template <class T, template <typename T2> class U> 00086 class SimpleCharInternal : public Updatable, public SimpleCharBase<T> { 00087 public: 00088 SimpleCharInternal(BLE* aBle, 00089 const UUID &uuid, 00090 GattCharacteristic::Properties_t aGattChar, 00091 T aDefaultValue, 00092 void(*aCallback)(T) = NULL) : 00093 ble(aBle), value(new T(aDefaultValue)), callback(aCallback) 00094 { 00095 state = new U<T>(uuid, value, aGattChar); 00096 } 00097 00098 ~SimpleCharInternal() { 00099 if (state) { 00100 free(state); 00101 } 00102 if (value) { 00103 free(value); 00104 } 00105 } 00106 00107 virtual void update(T newValue) { 00108 *value = newValue; 00109 ble->gattServer().write(state->getValueHandle(), (uint8_t *)value, sizeof(T)); 00110 } 00111 00112 U<T>* getChar(void) { 00113 return state; 00114 } 00115 00116 virtual T* getValue(void) { 00117 return value; 00118 } 00119 00120 virtual void onDataWritten(const uint8_t* data, size_t len) { 00121 *value = ((T*)data)[0]; 00122 if (callback) { 00123 callback(*value); 00124 } 00125 } 00126 00127 private: 00128 BLE* ble; 00129 T* value; 00130 U<T>* state; 00131 void(*callback)(T); 00132 }; 00133 00134 /** 00135 * This is what the user gets back. it's nice and short so don't have to type much. 00136 * If we get 'auto' we can get rid of this. 00137 */ 00138 template <class T> 00139 class SimpleChar { 00140 public: 00141 SimpleChar(SimpleCharBase<T>* aBase) : base(aBase) { 00142 } 00143 ~SimpleChar() { 00144 if (base) { 00145 delete base; 00146 } 00147 } 00148 00149 T operator=(const T& newValue) { 00150 base->update(newValue); 00151 return newValue; 00152 }; 00153 operator T() const { 00154 return *(base->getValue()); 00155 }; 00156 00157 private: 00158 SimpleCharBase<T>* base; 00159 }; 00160 00161 00162 class SimpleBLE { 00163 public: 00164 SimpleBLE(const char* aName, uint16_t aInterval = 1000, bool aLogging = true) 00165 : name(aName), interval(aInterval), logging(aLogging) 00166 { 00167 ble = &BLE::Instance(); 00168 } 00169 ~SimpleBLE() {} 00170 00171 void start() { 00172 ble->init(this, &SimpleBLE::bleInitComplete); 00173 00174 /* SpinWait for initialization to complete. This is necessary because the 00175 * BLE object is used in the main loop below. */ 00176 while (ble->hasInitialized() == false) { /* spin loop */ } 00177 } 00178 00179 // Start up the BLE service and just run with it! 00180 void waitForEvent() { 00181 ble->waitForEvent(); 00182 } 00183 00184 void onDisconnection(Gap::DisconnectionEventCallback_t callback) { 00185 ble->gap().onDisconnection(callback); 00186 } 00187 00188 void onConnection(Gap::ConnectionEventCallback_t callback) { 00189 ble->gap().onConnection(callback); 00190 } 00191 00192 BLE* getBle(void) { 00193 return ble; 00194 } 00195 00196 def_fn(uint8_t, u8) 00197 def_fn(uint16_t, u16) 00198 def_fn(uint32_t, u32) 00199 def_fn(int8_t, i8) 00200 def_fn(int16_t, i16) 00201 def_fn(int32_t, i32) 00202 def_fn(bool, bool) 00203 def_fn(float, float) 00204 00205 private: 00206 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) 00207 { 00208 if (logging) printf("bleInitComplete\r\n"); 00209 00210 BLE& ble = params->ble; 00211 ble_error_t error = params->error; 00212 00213 if (error != BLE_ERROR_NONE) { 00214 if (logging) printf("BLE Init error %d\r\n", error); 00215 return; 00216 } 00217 00218 /* Ensure that it is the default instance of BLE */ 00219 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { 00220 return; 00221 } 00222 00223 ble.gattServer().onDataWritten(this, &SimpleBLE::onDataWrittenCallback); 00224 00225 // let's add some services yo (why is there no 'auto' in mbed?) 00226 uint16_t uuid16_list[uint16_services.size()]; 00227 size_t uuid16_counter = 0; 00228 { 00229 typedef std::map<uint16_t, vector<GattCharacteristic*>* >::iterator it_type; 00230 for(it_type it = uint16_services.begin(); it != uint16_services.end(); it++) { 00231 if (logging) printf("Creating service 0x%x\n", it->first); 00232 uuid16_list[uuid16_counter++] = it->first; 00233 00234 GattCharacteristic* charTable[it->second->size()]; 00235 for (size_t git = 0; git < it->second->size(); git++) { 00236 charTable[git] = it->second->at(git); 00237 } 00238 00239 GattService service(it->first, charTable, it->second->size()); 00240 ble.gattServer().addService(service); 00241 } 00242 } 00243 00244 // 128 Bit services 00245 const char* uuid128_list[uint128_services.size()]; 00246 size_t uuid128_counter = 0; 00247 { 00248 typedef std::map<string, vector<GattCharacteristic*>* >::iterator it_type; 00249 for(it_type it = uint128_services.begin(); it != uint128_services.end(); it++) { 00250 if (logging) printf("Creating service %s\n", it->first.c_str()); 00251 uuid128_list[uuid128_counter++] = it->first.c_str(); 00252 00253 GattCharacteristic* charTable[it->second->size()]; 00254 for (size_t git = 0; git < it->second->size(); git++) { 00255 charTable[git] = it->second->at(git); 00256 } 00257 00258 GattService service(UUID(it->first.c_str()), charTable, it->second->size()); 00259 ble.gattServer().addService(service); 00260 } 00261 } 00262 00263 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 00264 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, uuid16_counter); 00265 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *)uuid128_list, uuid128_counter); 00266 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)name, strlen(name)); 00267 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00268 ble.gap().setAdvertisingInterval(interval); 00269 ble.gap().startAdvertising(); 00270 00271 if (logging) printf("Started advertising\r\n"); 00272 } 00273 00274 void onDataWrittenCallback(const GattWriteCallbackParams *params) { 00275 // see if we know for which char this message is... 00276 typedef std::map<GattCharacteristic*, Updatable* >::iterator it_type; 00277 for(it_type it = writeCallbacks.begin(); it != writeCallbacks.end(); it++) { 00278 if (it->first->getValueHandle() == params->handle) { 00279 it->second->onDataWritten(params->data, params->len); 00280 } 00281 } 00282 } 00283 00284 void addToServices(uint16_t uuid, GattCharacteristic* c) { 00285 if (uint16_services.count(uuid) == 0) { 00286 uint16_services[uuid] = new vector<GattCharacteristic*>(); 00287 } 00288 00289 uint16_services[uuid]->push_back(c); 00290 } 00291 00292 void addToServices(const char* aUuid, GattCharacteristic* c) { 00293 string uuid(aUuid); 00294 if (uint128_services.count(uuid) == 0) { 00295 uint128_services[uuid] = new vector<GattCharacteristic*>(); 00296 } 00297 00298 uint128_services[uuid]->push_back(c); 00299 } 00300 00301 // === START READONLY === 00302 00303 template <typename T> 00304 SimpleChar<T> readOnly(uint16_t serviceUuid, 00305 const UUID& charUuid, 00306 bool enableNotify = true, 00307 T defaultValue = T()) { 00308 GattCharacteristic::Properties_t gattChar = enableNotify ? 00309 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY : 00310 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ; 00311 00312 SimpleCharInternal<T, ReadOnlyGattCharacteristic>* c = 00313 new SimpleCharInternal<T, ReadOnlyGattCharacteristic>(ble, charUuid, gattChar, defaultValue); 00314 00315 addToServices(serviceUuid, c->getChar()); 00316 00317 return *(new SimpleChar<T>(c)); 00318 } 00319 00320 template <typename T> 00321 SimpleChar<T> readOnly(const char* serviceUuid, 00322 const UUID& charUuid, 00323 bool enableNotify = true, 00324 T defaultValue = T()) { 00325 GattCharacteristic::Properties_t gattChar = enableNotify ? 00326 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY : 00327 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ; 00328 00329 SimpleCharInternal<T, ReadOnlyGattCharacteristic>* c = 00330 new SimpleCharInternal<T, ReadOnlyGattCharacteristic>(ble, charUuid, gattChar, defaultValue); 00331 00332 addToServices(serviceUuid, c->getChar()); 00333 00334 return *(new SimpleChar<T>(c)); 00335 } 00336 00337 // === END READONLY === 00338 00339 // === START READWRITE === 00340 00341 template <typename T> 00342 SimpleChar<T> readWrite(uint16_t serviceUuid, 00343 const UUID& charUuid, 00344 bool enableNotify = true, 00345 T defaultValue = T(), 00346 void(*callback)(T) = NULL) { 00347 GattCharacteristic::Properties_t gattChar = enableNotify ? 00348 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY : 00349 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ; 00350 00351 SimpleCharInternal<T, ReadWriteGattCharacteristic>* c = 00352 new SimpleCharInternal<T, ReadWriteGattCharacteristic>(ble, charUuid, gattChar, defaultValue, callback); 00353 00354 addToServices(serviceUuid, c->getChar()); 00355 00356 writeCallbacks[c->getChar()] = c; 00357 00358 return *(new SimpleChar<T>(c)); 00359 } 00360 00361 00362 00363 template <typename T> 00364 SimpleChar<T> readWrite(const char* serviceUuid, 00365 const UUID& charUuid, 00366 bool enableNotify = true, 00367 T defaultValue = T(), 00368 void(*callback)(T) = NULL) { 00369 GattCharacteristic::Properties_t gattChar = enableNotify ? 00370 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY : 00371 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ; 00372 00373 SimpleCharInternal<T, ReadWriteGattCharacteristic>* c = 00374 new SimpleCharInternal<T, ReadWriteGattCharacteristic>(ble, charUuid, gattChar, defaultValue, callback); 00375 00376 addToServices(serviceUuid, c->getChar()); 00377 00378 writeCallbacks[c->getChar()] = c; 00379 00380 return *(new SimpleChar<T>(c)); 00381 } 00382 00383 template <typename T> 00384 SimpleChar<T> readWrite(uint16_t serviceUuid, 00385 const UUID& charUuid, 00386 void(*callback)(T) = NULL) { 00387 return readWrite(serviceUuid, charUuid, true, T(), callback); 00388 } 00389 00390 template <typename T> 00391 SimpleChar<T> readWrite(const char* serviceUuid, 00392 const UUID& charUuid, 00393 void(*callback)(T) = NULL) { 00394 return readWrite(serviceUuid, charUuid, true, T(), callback); 00395 } 00396 00397 // === END READWRITE === 00398 00399 // === START WRITEONLY === 00400 00401 template <typename T> 00402 SimpleChar<T> writeOnly(uint16_t serviceUuid, 00403 const UUID& charUuid, 00404 void(*callback)(T) = NULL) { 00405 SimpleCharInternal<T, WriteOnlyGattCharacteristic>* c = 00406 new SimpleCharInternal<T, WriteOnlyGattCharacteristic>(ble, charUuid, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NONE, T(), callback); 00407 00408 addToServices(serviceUuid, c->getChar()); 00409 00410 writeCallbacks[c->getChar()] = c; 00411 00412 return *(new SimpleChar<T>(c)); 00413 } 00414 00415 template <typename T> 00416 SimpleChar<T> writeOnly(const char* serviceUuid, 00417 const UUID& charUuid, 00418 void(*callback)(T) = NULL) { 00419 00420 SimpleCharInternal<T, WriteOnlyGattCharacteristic>* c = 00421 new SimpleCharInternal<T, WriteOnlyGattCharacteristic>(ble, charUuid, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NONE, T(), callback); 00422 00423 addToServices(serviceUuid, c->getChar()); 00424 00425 writeCallbacks[c->getChar()] = c; 00426 00427 return *(new SimpleChar<T>(c)); 00428 } 00429 00430 // === END WRITEONLY === 00431 00432 BLE* ble; 00433 const char* name; 00434 uint16_t interval; 00435 bool logging; 00436 map<uint16_t, vector<GattCharacteristic*>* > uint16_services; 00437 map<string, vector<GattCharacteristic*>* > uint128_services; 00438 map<GattCharacteristic*, Updatable*> writeCallbacks; 00439 }; 00440
Generated on Fri Jul 15 2022 03:48:31 by
1.7.2