Modify the BLE LED Control so that it toggles the LED on the other board only if you keep the button pressed
Revision 0:8c76e25a3cff, committed 2018-11-29
- Comitter:
- vicara
- Date:
- Thu Nov 29 18:32:03 2018 +0000
- Commit message:
- Modify the BLE LED Control so that it; toggles the LED on the other board only if; you keep the button pressed
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Thu Nov 29 18:32:03 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#bf6f2c3c6434a6de9eb9511feffa5948b3d1f20f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_app.json Thu Nov 29 18:32:03 2018 +0000 @@ -0,0 +1,16 @@ +{ + "target_overrides": { + "K64F": { + "target.features_add": ["BLE"], + "target.extra_labels_add": ["CORDIO", "CORDIO_BLUENRG"] + }, + "NUCLEO_F401RE": { + "target.features_add": ["BLE"], + "target.extra_labels_add": ["CORDIO", "CORDIO_BLUENRG"] + }, + "DISCO_L475VG_IOT01A": { + "target.features_add": ["BLE"], + "target.extra_labels_add": ["CORDIO", "CORDIO_BLUENRG"] + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/module.json Thu Nov 29 18:32:03 2018 +0000 @@ -0,0 +1,15 @@ +{ + "name": "ble-ledblinker", + "version": "0.0.1", + "description": "An initial demo showcasing the GattClient APIs. Drives an LED service exported by a BLE_LED peripheral. Shows scanning, connections, service-discovery, and reads/writes.", + "licenses": [ + { + "url": "https://spdx.org/licenses/Apache-2.0", + "type": "Apache-2.0" + } + ], + "dependencies": { + "ble": "^2.0.0" + }, + "bin": "./source" +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/readme.md Thu Nov 29 18:32:03 2018 +0000 @@ -0,0 +1,54 @@ +# BLE LED Blinker + +This example demonstrates using the ``GattClient`` API to control BLE client devices. + +The example uses two applications running on two different devices: + +1. The first device - the central - runs the application ``BLE_LEDBlinker`` from this repository. This application sends an on/off toggle over BLE. + +1. The second device - the peripheral - runs the application [``BLE_LED``](https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_LED) to respond to the toggle. + + The toggle simply turns the LED on the peripheral device on and off. + +# Running the application + +## Requirements + +Hardware requirements are in the [main readme](https://github.com/ARMmbed/mbed-os-example-ble/blob/master/README.md). + +This example requires *two* devices. + +## Building instructions + +You will need to build both applications and flash each one to a different board. + +Please note: The application ``BLE_LEDBlinker`` in this repository initiate a connection to all ble devices which advertise "LED" as complete local name. By default, the application `BLE_LED` advertise "LED" as complete local name. If you change the local name advertised by the application `BLE_LED` you should reflect your change in this application by changing the value of the constant `PEER_NAME` in `main.cpp`. + +**Tip:** You may notice that the application also checks the LED characteristic's UUID; you don't need to change this parameter's value, because it already matches the UUID provided by the second application, ``BLE_LED``. + +Building instructions for all mbed OS samples are in the [main readme](https://github.com/ARMmbed/mbed-os-example-ble/blob/master/README.md). + +## Checking for success + +1. Build both applications and install one on each device, as explained in the building instructions. + +1. The LED number two of the device running ``BLE_LED`` should blink. + + +## Monitoring the application through a serial port + +You can run ``BLE_LEDBlinker`` and see that it works properly by monitoring its serial output. + +You need a terminal program to listen to the output through a serial port. You can download one, for example: + +* Tera Term for Windows. +* CoolTerm for Mac OS X. +* GNU Screen for Linux. + +To see the application's output: + +1. Check which serial port your device is connected to. +1. Run a terminal program with the correct serial port and set the baud rate to 9600. For example, to use GNU Screen, run: ``screen /dev/tty.usbmodem1412 9600``. +1. The application should start printing the toggle's value to the terminal. + +**Note:** ``BLE_LEDBlinker`` will not run properly if the ``BLE_LED`` application is not running on a second device. The terminal will show a few print statements, but you will not be able to see the application in full operation.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shields/TARGET_CORDIO_BLUENRG.lib Thu Nov 29 18:32:03 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/cordio-ble-x-nucleo-idb0xa1/#5e49580a0303c48c11f78ad2e5d92b5ffc02aadc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main.cpp Thu Nov 29 18:32:03 2018 +0000 @@ -0,0 +1,211 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 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. + */ + +#include <events/mbed_events.h> +#include <mbed.h> +#include "ble/BLE.h" +#include "ble/DiscoveredCharacteristic.h" +#include "ble/DiscoveredService.h" + +DigitalOut alivenessLED(LED1, 1); +static DiscoveredCharacteristic ledCharacteristic; +static bool triggerLedCharacteristic; +static const char PEER_NAME[] = "LED_RED"; +InterruptIn button(USER_BUTTON); +static uint8_t toggledValue = 0x0; + +static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE); + +void periodicCallback(void) { + alivenessLED = !alivenessLED; /* Do blinky on LED1 while we're waiting for BLE events */ +} + +void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) { + // parse the advertising payload, looking for data type COMPLETE_LOCAL_NAME + // The advertising payload is a collection of key/value records where + // byte 0: length of the record excluding this byte + // byte 1: The key, it is the type of the data + // byte [2..N] The value. N is equal to byte0 - 1 + for (uint8_t i = 0; i < params->advertisingDataLen; ++i) { + + const uint8_t record_length = params->advertisingData[i]; + if (record_length == 0) { + continue; + } + const uint8_t type = params->advertisingData[i + 1]; + const uint8_t* value = params->advertisingData + i + 2; + const uint8_t value_length = record_length - 1; + + if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) { + if ((value_length == sizeof(PEER_NAME)) && (memcmp(value, PEER_NAME, value_length) == 0)) { + printf( + "adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n", + params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], + params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type + ); + BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL); + break; + } + } + i += record_length; + } +} + +void serviceDiscoveryCallback(const DiscoveredService *service) { + if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) { + printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle()); + } else { + printf("S UUID-"); + const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID(); + for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { + printf("%02x", longUUIDBytes[i]); + } + printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle()); + } +} + +void updateLedCharacteristic(void) { + if (!BLE::Instance().gattClient().isServiceDiscoveryActive()) { + ledCharacteristic.read(); + } +} + +void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) { + printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast()); + if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* !ALERT! Alter this filter to suit your device. */ + ledCharacteristic = *characteristicP; + triggerLedCharacteristic = true; + } +} + +void discoveryTerminationCallback(Gap::Handle_t connectionHandle) { + printf("terminated SD for handle %u\r\n", connectionHandle); + if (triggerLedCharacteristic) { + triggerLedCharacteristic = false; + eventQueue.call(updateLedCharacteristic); + } +} + +void connectionCallback(const Gap::ConnectionCallbackParams_t *params) { + if (params->role == Gap::CENTRAL) { + BLE &ble = BLE::Instance(); + ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback); + ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, 0xa000, 0xa001); + } +} + +void triggerToggledWrite(const GattReadCallbackParams *response) { + if (response->handle == ledCharacteristic.getValueHandle()) { + printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len); + for (unsigned index = 0; index < response->len; index++) { + printf("%c[%02x]", response->data[index], response->data[index]); + } + printf("\r\n"); + + ledCharacteristic.write(1, &toggledValue); + } +} + +void triggerRead(const GattWriteCallbackParams *response) { + if (response->handle == ledCharacteristic.getValueHandle()) { + ledCharacteristic.read(); + } +} + +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) { + printf("disconnected\r\n"); + /* Start scanning and try to connect again */ + BLE::Instance().gap().startScan(advertisementCallback); +} + +void onBleInitError(BLE &ble, ble_error_t error) +{ + /* Initialization error handling should go here */ +} + +void printMacAddress() +{ + /* Print out device MAC address to the console*/ + Gap::AddressType_t addr_type; + Gap::Address_t address; + BLE::Instance().gap().getAddress(&addr_type, address); + printf("DEVICE MAC ADDRESS: "); + for (int i = 5; i >= 1; i--){ + printf("%02x:", address[i]); + } + printf("%02x\r\n", address[0]); +} + +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; + } + + /* Ensure that it is the default instance of BLE */ + if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { + return; + } + + ble.gap().onDisconnection(disconnectionCallback); + ble.gap().onConnection(connectionCallback); + + ble.gattClient().onDataRead(triggerToggledWrite); + ble.gattClient().onDataWrite(triggerRead); + + // scan interval: 400ms and scan window: 400ms. + // Every 400ms the device will scan for 400ms + // This means that the device will scan continuously. + ble.gap().setScanParams(400, 400); + ble.gap().startScan(advertisementCallback); + + printMacAddress(); +} + +void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { + BLE &ble = BLE::Instance(); + eventQueue.call(Callback<void()>(&ble, &BLE::processEvents)); +} + +void btn_on (){ + toggledValue = 0x1; +} + +void btn_off (){ + toggledValue = 0x0; +} + +int main() +{ + triggerLedCharacteristic = false; + eventQueue.call_every(500, periodicCallback); + + button.fall(&btn_on); + button.rise(&btn_off); + + BLE &ble = BLE::Instance(); + ble.onEventsToProcess(scheduleBleEventsProcessing); + ble.init(bleInitComplete); + + eventQueue.dispatch_forever(); + + return 0; +}