Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 2:204381095967, committed 2017-03-28
- Comitter:
- michaesc
- Date:
- Tue Mar 28 15:57:46 2017 +0000
- Parent:
- 1:f8f97a4d8f02
- Commit message:
- Implemented Blinkyserv class and GATT derived service and characteristic logic.
Changed in this revision
source/Service.h | 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 |
diff -r f8f97a4d8f02 -r 204381095967 source/Service.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/Service.h Tue Mar 28 15:57:46 2017 +0000 @@ -0,0 +1,63 @@ +/* Blinky service application + * + * 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. + */ + +#ifndef __BLE_BUTLED_SERVICE_H__ +#define __BLE_BUTLED_SERVICE_H__ + +class Blinkyserv { +public: + // These are stale UUIDs, not corresponding to Nordic + //const static uint16_t LED_SERVICE_UUID = 0xA002; + //const static uint16_t LED_STATE_CHARACTERISTIC_UUID = 0xA004; + //const static uint16_t BUT_STATE_CHARACTERISTIC_UUID = 0xA005; + + // https://github.com/NordicSemiconductor/Android-nRF-Blinky/tree/master/app/src/main/java/no/nordicsemi/android/blinky/service/BlinkyManager.java + // BaseUUID = {0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x23, 0x15, 0x00, 0x00}; + //const static UUID *LED_SERVICE_UUID = new UUID("00001523-1212-efde-1523-785feabcd123"); + //std::shared_ptr<UUID> LED_SERVICE_UUID; + const UUID *LED_SERVICE_UUID; + + Blinkyserv(BLEDevice &_ble, bool initialValueForLEDCharacteristic, bool initialValueForButCharacteristic) : + ble(_ble), ledState(UUID("00001525-1212-efde-1523-785feabcd123"), &initialValueForLEDCharacteristic), + butState(UUID("00001524-1212-efde-1523-785feabcd123"), &initialValueForButCharacteristic, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) + { + // Service definition logic + GattCharacteristic *charTable[] = {&ledState, &butState}; + LED_SERVICE_UUID = new UUID("00001523-1212-efde-1523-785feabcd123"); + + GattService GATTServ(static_cast<UUID>(*LED_SERVICE_UUID), charTable, sizeof(charTable) / sizeof(GattCharacteristic *)); + ble.addService(GATTServ); + } + + // FIXME: Does this need a butState equivalent? + GattAttribute::Handle_t getValueHandle() const { + return ledState.getValueHandle(); + } + + void updateButtonState(bool newState) { // Sets button state characteristic appropriately + //ble.gattServer().write(butState.getValueHandle(), (uint8_t *)&newState, sizeof(bool)); + ble.updateCharacteristicValue(butState.getValueHandle(), (uint8_t *)&newState, sizeof(bool)); + } + +private: + BLEDevice &ble; + ReadWriteGattCharacteristic<bool> ledState; + ReadOnlyGattCharacteristic<bool> butState; + ~Blinkyserv() { + delete LED_SERVICE_UUID; + } +}; + +#endif /* #ifndef __BLE_BUTLED_SERVICE_H__ */ \ No newline at end of file
diff -r f8f97a4d8f02 -r 204381095967 source/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main.cpp Tue Mar 28 15:57:46 2017 +0000 @@ -0,0 +1,209 @@ +/* Blinky service application + * + * This Bluetooth Smart application intends to serve as a substitute + * for existing applications implemented using the Nordic Semiconductor + * proprietary nRF 5 SDK. This application interfaces with example + * client applications such as the preexisting 'nRF Blinky' and + * 'nRF52 Blinky Web App', while complying with proprietary Nordic + * Semiconductor service and characteristic UUIDs. + * + * 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 <mbed.h> +#include "ble/BLE.h" +#include "ble/Gap.h" +#include "Service.h" + +// FIXME: initializing has no effect! +DigitalOut alivenessLED(LED1); +DigitalOut actuatedLED(LED2); +InterruptIn button(BUTTON1); + +enum { // Button! + RELEASED = 0, + PRESSED, + IDLE +}; + +// Stores the state of button sensor +static uint8_t buttonState = IDLE; + +const static char DEVICE_NAME[] = "Lightsw"; // Seems this string has a limited maximum length? +//static const uint16_t uuid16_list[] = {Blinkyserv::LED_SERVICE_UUID}; // Only works on short URLs +//static const uint8_t uuid128_list[] = {0x0000, 0x1523, 0x1212, 0xefde, 0x1523, 0x785f, 0xeabc, 0xd123}; + +Blinkyserv *blinkySvcptr; + +static EventQueue eventQueue( + /* event count */ 16 * /* event size */ 32 +); + +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) +{ + printf("Disconnected handle %u!\n", params->handle); + printf("Restarting the advertising process\n"); + BLE::Instance().gap().startAdvertising(); + actuatedLED = 1; // Reinitialize actuator, + // according to svc value + // initialValueForLEDCharacteristic +} + +void connectionCallback(const Gap::ConnectionCallbackParams_t *params) +{ + printf("Connected handle %u!\n", params->handle); + printf("Stopping the advertising process\n"); + BLE::Instance().gap().stopAdvertising(); + alivenessLED = 1; // Indicate end of adverts +} + +void blinkCallback(void) +{ + BLE &ble = BLE::Instance(); + + // Hack to avoid hung connections + if (!ble.gap().getState().connected + && !ble.gap().getState().advertising) { + BLE::Instance().gap().startAdvertising(); + } + + // Indicate adverts by blinking a LED + if (ble.gap().getState().advertising) { + alivenessLED = !alivenessLED; + } +} + +/** + * Allows the LED service to receive updates to the ledState characteristic. + * + * @param[in] params + * Information about the characterisitc being updated. + */ +void onDataWrittenCallback(const GattWriteCallbackParams *params) { + if ((params->handle == blinkySvcptr->getValueHandle()) && (params->len == 1)) { + printf("Going to set the LED actuator!\n"); + actuatedLED = !*(params->data); // Inverse + } +} + +/** + * Allows the LED service to receive updates to the ledState characteristic. + */ +void onUpdatesCallback(Gap::Handle_t handle) { + printf("Notifications enabled for %d\n!", handle); +} + +/* Callback user space helper method */ +void fall_handler_user_context(void) { + // Fall handler is called on button actions + blinkySvcptr->updateButtonState(buttonState); + buttonState = IDLE; +} + +/* Callback user space helper method */ +void rise_handler_user_context(void) { + // Fall handler is called on button actions + blinkySvcptr->updateButtonState(buttonState); + buttonState = IDLE; +} + +/* Note that the buttonPressedCallback() executes in interrupt context, + * so it is safer to access BLE device API from the main thread. For + * example, do not try to call printf(3) inside interrupt context! */ +void buttonPressedCallback(void) +{ + buttonState = PRESSED; + eventQueue.call(fall_handler_user_context); +} + +/* Note that the buttonReleasedCallback() executes in interrupt context, + * so it is safer to access BLE device API from the main thread. For + * example, do not try to call printf(3) inside interrupt context! */ +void buttonReleasedCallback(void) +{ + buttonState = RELEASED; + eventQueue.call(rise_handler_user_context); +} + +/** + * This function is called when the ble initialization process has failed + */ +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; + } + + /* Ensure that it is the default instance of BLE */ + if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { + return; + } + + ble.gap().onConnection(connectionCallback); + ble.gap().onDisconnection(disconnectionCallback); + ble.gattServer().onDataWritten(onDataWrittenCallback); + ble.gattServer().onUpdatesEnabled(onUpdatesCallback); + + /* Setup primary service */ + bool initialValueForLEDCharacteristic = false; + bool initialValueForButCharacteristic = false; + blinkySvcptr = new Blinkyserv(ble, initialValueForLEDCharacteristic, initialValueForButCharacteristic); + + /* Setup advertising */ + 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_LIST_128BIT_SERVICE_IDS, (uint8_t *) uuid128_list, sizeof(uuid128_list)); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, blinkySvcptr->LED_SERVICE_UUID->getBaseUUID(), blinkySvcptr->LED_SERVICE_UUID->getLen()); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME)); + ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + ble.gap().setAdvertisingInterval(1000); /* 1000ms */ + ble.gap().startAdvertising(); +} + +void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { + BLE &ble = BLE::Instance(); + + // Finally redirect call to BLE callback handler + eventQueue.call(Callback<void()>(&ble, &BLE::processEvents)); +} + +int main() +{ + printf("Starting application main entry point...\n"); + eventQueue.call_every(200, blinkCallback); + + BLE &ble = BLE::Instance(); + ble.onEventsToProcess(scheduleBleEventsProcessing); + ble.init(bleInitComplete); + + actuatedLED = 1; // initialize off + button.fall(buttonPressedCallback); + button.rise(buttonReleasedCallback); + + eventQueue.dispatch_forever(); + + return 0; +} \ No newline at end of file