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 |
--- /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
--- /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