SimpleBLE prototype
Dependencies: BLE_API mbed nRF51822
SimpleBLE.h
- Committer:
- janjongboom
- Date:
- 2016-05-11
- Revision:
- 1:acae50e4bc88
- Parent:
- 0:0c885d287f5a
File content as of revision 1:acae50e4bc88:
/** * Because BLE_API is too hard */ #include <string> #include <vector> #include <map> #include "ble/BLE.h" using namespace std; template <class T> class ReadOnlyCharacteristic { public: ReadOnlyCharacteristic(BLE* aBle, const uint16_t aCharUuid, bool enableNotify, T defaultValue) : ble(aBle) { state = new ReadOnlyGattCharacteristic<T>(aCharUuid, new T(defaultValue), enableNotify ? GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY : GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); } ~ReadOnlyCharacteristic() { // @todo clear defaultValue if (state) { free(state); } } void update(T newValue) { ble->gattServer().write(state->getValueHandle(), (uint8_t *)&newValue, sizeof(T)); } ReadOnlyGattCharacteristic<T>* getChar(void) { return state; } private: BLE* ble; ReadOnlyGattCharacteristic<T>* state; }; template <class T> class ReadWriteCharacteristic { public: ReadWriteCharacteristic(BLE* aBle, const uint16_t aCharUuid, bool enableNotify, T defaultValue) : ble(aBle) { state = new ReadWriteGattCharacteristic<T>(aCharUuid, new T(defaultValue), enableNotify ? GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY : GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); } ~ReadWriteCharacteristic() { // @todo clear defaultValue if (state) { free(state); } } void update(T newValue) { ble->gattServer().write(state->getValueHandle(), (uint8_t *)&newValue, sizeof(T)); } ReadWriteGattCharacteristic<T>* getChar(void) { return state; } private: BLE* ble; ReadWriteGattCharacteristic<T>* state; }; class SimpleBLE { public: SimpleBLE(const char* aName, uint16_t aInterval = 1000) : name(aName), interval(aInterval) { ble = &BLE::Instance(); } ~SimpleBLE() {} // Start up the BLE service and just run with it! void spin() { ble->init(this, &SimpleBLE::bleInitComplete); /* SpinWait for initialization to complete. This is necessary because the * BLE object is used in the main loop below. */ while (ble->hasInitialized() == false) { /* spin loop */ } while (true) { ble->waitForEvent(); } } template <typename T> ReadOnlyCharacteristic<T>* createReadOnlyChar(uint16_t serviceUuid, uint16_t charUuid, bool enableNotify, T defaultValue) { ReadOnlyCharacteristic<T>* c = new ReadOnlyCharacteristic<T>(ble, charUuid, enableNotify, defaultValue); if (services.count(serviceUuid) == 0) { services[serviceUuid] = new vector<GattCharacteristic*>(); } services[serviceUuid]->push_back(c->getChar()); return c; } template <typename T> ReadWriteCharacteristic<T>* createReadWriteChar(uint16_t serviceUuid, uint16_t charUuid, bool enableNotify, T defaultValue, void(*callback)(const uint8_t*, size_t)) { ReadWriteCharacteristic<T>* c = new ReadWriteCharacteristic<T>(ble, charUuid, enableNotify, defaultValue); if (services.count(serviceUuid) == 0) { services[serviceUuid] = new vector<GattCharacteristic*>(); } services[serviceUuid]->push_back(c->getChar()); writeCallbacks[c->getChar()] = (void*)callback; return c; } void onDisconnection(Gap::DisconnectionEventCallback_t callback) { ble->gap().onDisconnection(callback); } void onConnection(Gap::ConnectionEventCallback_t callback) { ble->gap().onConnection(callback); } void onDataWrittenCallback(const GattWriteCallbackParams *params) { // see if we know for which char this message is... typedef std::map<GattCharacteristic*, void* >::iterator it_type; for(it_type it = writeCallbacks.begin(); it != writeCallbacks.end(); it++) { if (it->first->getValueHandle() == params->handle) { void(*func)(const uint8_t*, size_t) = (void(*)(const uint8_t*, size_t))it->second; func(params->data, params->len); } } // handle corresponds to the characteristic being written // then we can read data to get a buffer of the actual data // if ((params->handle == ledServicePtr->getValueHandle()) && (params->len == 1)) { // // When writing 1 -> turn LED on, 0 -> turn LED off // char val = params->data[0]; // actuatedLED = val == 1 ? LED_ON : LED_OFF; // } } private: void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) { printf("bleInitComplete\r\n"); BLE& ble = params->ble; ble_error_t error = params->error; if (error != BLE_ERROR_NONE) { printf("BLE Init error %d\r\n", error); return; } /* Ensure that it is the default instance of BLE */ if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { return; } ble.gattServer().onDataWritten(this, &SimpleBLE::onDataWrittenCallback); // let's add some services yo (why is there no 'auto' in mbed?) uint16_t uuid16_list[services.size()]; size_t counter = 0; typedef std::map<std::uint16_t, vector<GattCharacteristic*>* >::iterator it_type; for(it_type it = services.begin(); it != services.end(); it++) { printf("Creating service 0x%x\n", it->first); uuid16_list[counter++] = it->first; GattCharacteristic* charTable[it->second->size()]; for (size_t git = 0; git < it->second->size(); git++) { charTable[git] = it->second->at(git); } GattService service(it->first, charTable, it->second->size()); ble.gattServer().addService(service); } ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)name, strlen(name)); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(interval); ble.gap().startAdvertising(); printf("Started advertising\n"); } BLE* ble; const char* name; uint16_t interval; map<uint16_t, vector<GattCharacteristic*>* > services; map<GattCharacteristic*, void*> writeCallbacks; };