Modify the BLE LED Control so that it toggles the LED on the other board only if you keep the button pressed

Files at this revision

API Documentation at this revision

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

mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
module.json Show annotated file Show diff for this revision Revisions of this file
readme.md Show annotated file Show diff for this revision Revisions of this file
shields/TARGET_CORDIO_BLUENRG.lib Show annotated file Show diff for this revision Revisions of this file
source/main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /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;
+}