Simple example to demonstrate custom made BLE service and characteristics.
Fork of BLE_GATT_Example by
Diff: main.cpp
- Revision:
- 23:924d0ef8f1cb
- Parent:
- 22:406127954d1f
--- a/main.cpp Mon Nov 09 17:08:47 2015 +0000 +++ b/main.cpp Thu Nov 09 16:08:04 2017 +0000 @@ -1,104 +1,166 @@ -#include "mbed.h" -#include "ble/BLE.h" +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -DigitalOut led(LED1, 1); -uint16_t customServiceUUID = 0xA000; -uint16_t readCharUUID = 0xA001; -uint16_t writeCharUUID = 0xA002; +#include <mbed-events/events.h> +#include <mbed.h> +#include "ble/BLE.h" +#include "AckService.h" -const static char DEVICE_NAME[] = "ChangeMe!!"; // change this -static const uint16_t uuid16_list[] = {0xFFFF}; //Custom UUID, FFFF is reserved for development +#define DEBUG (0) +#define MSD_SIZE (18) -/* Set Up custom Characteristics */ -static uint8_t readValue[10] = {0}; -ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(readCharUUID, readValue); +#if DEBUG + #define RX (p26) // SERIAL STILL DOES NOT WORK!!! + #define TX (p25) +#endif -static uint8_t writeValue[10] = {0}; -WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue); +ACKService<4> *ackServicePtr; +#if DEBUG + Serial pc(TX, RX); +#endif -/* Set up custom service */ -GattCharacteristic *characteristics[] = {&readChar, &writeChar}; -GattService customService(customServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *)); +BLE &ble = BLE::Instance(); + +DigitalOut redLed(p22); +DigitalOut greenLed(p24); +DigitalOut blueLed(p23); +DigitalOut alivenessLED(p26); +const static char DEVICE_NAME[] = "CRP_ACK"; +const static uint16_t ACK_CHARACTERISTIC_UUID = 0xA001; +const static uint16_t ACK_SERVICE_UUID = 0xA000; +uint8_t MSD[MSD_SIZE] = {0x59, 0x00, 0xE1, 0x61, 0x35, 0xBA, 0xC0, 0xEC, 0x47, 0x2A, 0x98, 0x00, 0xAF, 0x18, 0x43, 0xFF, 0x05, 0x00}; +uint8_t macAddress[6] = {0x23, 0x24, 0x35, 0x22, 0x24, 0x45}; -/* - * Restart advertising when phone app disconnects -*/ -void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) -{ - BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); +static EventQueue eventQueue( + /* event count */ 10 * /* event size */ 32 +); + +void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params){ + #if DEBUG + pc.printf("BLE device is connected.\n"); + #endif + redLed = 1; + greenLed = 1; + blueLed = 0; } -/* - * Handle writes to writeCharacteristic -*/ -void writeCharCallback(const GattWriteCallbackParams *params) -{ - /* Check to see what characteristic was written, by handle */ - if(params->handle == writeChar.getValueHandle()) { - /* toggle LED if only 1 byte is written */ - if(params->len == 1) { - led = params->data[0]; - (params->data[0] == 0x00) ? printf("led on\n\r") : printf("led off\n\r"); // print led toggle - } - /* Print the data if more than 1 byte is written */ - else { - printf("Data received: length = %d, data = 0x",params->len); - for(int x=0; x < params->len; x++) { - printf("%x", params->data[x]); - } - printf("\n\r"); - } - /* Update the readChar with the value of writeChar */ - BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(readChar.getValueHandle(), params->data, params->len); +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ + (void) params; + redLed = 0; + greenLed = 1; + blueLed = 1; + ble.disconnect(Gap::LOCAL_HOST_TERMINATED_CONNECTION); + BLE::Instance().gap().startAdvertising(); +} + +void blinkCallback(void){ + alivenessLED = !alivenessLED; /* Do blinky on LED1 to indicate system aliveness. */ +} + +void updateMac(const GattReadCallbackParams *response){ + ackServicePtr->updateMacAddress(macAddress); // Update MAC address +} + + +/** + * This callback allows the LEDService to receive updates to the ledState Characteristic. + * + * @param[in] params + * Information about the characterisitc being updated. + */ +void onDataWrittenCallback(const GattWriteCallbackParams *params) { + #if DEBUG + pc.printf("Data written into characteristic.\n"); + #endif + + + if(params->data[0] == 0xBA) + if(params->data[1] == 0xBE) + greenLed = 0; + + if(params->data[0] == 0xDE) + if(params->data[1] == 0xAD) + greenLed = 1; +} + +/** + * This function is called when the ble initialization process has failled + */ +void onBleInitError(BLE &ble, ble_error_t error){ + /* Initialization error handling should go here */ +} + +/** + * Callback triggered when the ble initialization process has finished + */ +void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){ + BLE& ble = params->ble; + ble_error_t error = params->error; + + if (error != BLE_ERROR_NONE) { + /* In case of error, forward the error handling to onBleInitError */ + onBleInitError(ble, error); + return; } -} -/* - * Initialization callback - */ -void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) -{ - BLE &ble = params->ble; - ble_error_t error = params->error; - - if (error != BLE_ERROR_NONE) { + + /* Ensure that it is the default instance of BLE */ + if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { return; } ble.gap().onDisconnection(disconnectionCallback); - ble.gattServer().onDataWritten(writeCharCallback); + ble.gap().onConnection(onConnectionCallback); + ble.gattServer().onDataWritten(onDataWrittenCallback); + ble.gattClient().onDataRead(updateMac); - /* Setup advertising */ - ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // BLE only, no classic BT - ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // advertising type - ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name - ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // UUID's broadcast in advertising packet - ble.gap().setAdvertisingInterval(100); // 100ms. - - /* Add our custom service */ - ble.addService(customService); - - /* Start advertising */ + uint8_t init_values[4] = {0,0,0,0}; + /* Get my MAC address */ + BLEProtocol::AddressType_t macAddressType; + ble.gap().getAddress(&macAddressType, macAddress); + ackServicePtr = new ACKService<4>(ble, init_values); + ackServicePtr->updateMacAddress(macAddress); // Update MAC address + + /* setup advertising */ + //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 *)DEVICE_NAME, sizeof(DEVICE_NAME)); + //ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)MSD, MSD_SIZE); + ble.gap().setAdvertisingInterval(500); /* 1000ms. */ ble.gap().startAdvertising(); } -/* - * Main loop -*/ -int main(void) -{ - /* initialize stuff */ - printf("\n\r********* Starting Main Loop *********\n\r"); +void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { + BLE &ble = BLE::Instance(); + eventQueue.post(Callback<void()>(&ble, &BLE::processEvents)); +} + + + +int main(){ + redLed = 1; + greenLed = 1; + blueLed = 1; - BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE); + eventQueue.post_every(500, blinkCallback); + + ble.onEventsToProcess(scheduleBleEventsProcessing); ble.init(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 */ } - - /* Infinite loop waiting for BLE interrupt events */ while (true) { - ble.waitForEvent(); /* Save power */ + eventQueue.dispatch(); } -} \ No newline at end of file +}