Gestione Bluetooth per il progetto Tarallo

Revision:
76:652c2be531c7
Parent:
45:0d307fc39fd0
Child:
82:443323e7d4c9
--- a/source/main.cpp	Fri Dec 14 13:15:15 2018 +0000
+++ b/source/main.cpp	Mon Jan 14 10:45:18 2019 +0000
@@ -17,85 +17,218 @@
 #include <events/mbed_events.h>
 #include <mbed.h>
 #include "ble/BLE.h"
-#include "ble/services/iBeacon.h"
-
-static iBeacon* ibeaconPtr;
-
-static EventQueue eventQueue(/* event count */ 4 * EVENTS_EVENT_SIZE);
+#include "pretty_printer.h"
 
-/**
- * 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 */
-}
+static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE);
 
-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]);
-}
+/** @deprecated This demo is deprecated and no replacement is currently available.
+ */
+MBED_DEPRECATED_SINCE(
+   "mbed-os-5.11",
+   "This demo is deprecated and no replacement is currently available."
+)
+class BeaconDemo : ble::Gap::EventHandler {
+public:
+    BeaconDemo(BLE &ble, events::EventQueue &event_queue) :
+        _ble(ble),
+        _event_queue(event_queue),
+        _adv_data_builder(_adv_buffer) { }
 
-/**
- * Callback triggered when the ble initialization process has finished
- */
-void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
-{
-    BLE&        ble   = params->ble;
-    ble_error_t error = params->error;
+    void start() {
+        _ble.gap().setEventHandler(this);
 
-    if (error != BLE_ERROR_NONE) {
-        /* In case of error, forward the error handling to onBleInitError */
-        onBleInitError(ble, error);
-        return;
+        _ble.init(this, &BeaconDemo::on_init_complete);
+
+        _event_queue.dispatch_forever();
     }
 
-    /* Ensure that it is the default instance of BLE */
-    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
-        return;
+private:
+    /**
+     * iBeacon payload builder.
+     *
+     * This data structure contains the payload of an iBeacon. The payload is
+     * built at construction time and application code can set up an iBeacon by
+     * injecting the raw field into the GAP advertising payload as a
+     * GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA.
+     */
+    union Payload {
+        /**
+         * Raw data of the payload.
+         */
+        uint8_t raw[25];
+        struct {
+            /**
+             * Beacon manufacturer identifier.
+             */
+            uint16_t companyID;
+
+            /**
+             * Packet ID; Equal to 2 for an iBeacon.
+             */
+            uint8_t ID;
+
+            /**
+             * Length of the remaining data presents in the payload.
+             */
+            uint8_t len;
+
+            /**
+             * Beacon UUID.
+             */
+            uint8_t proximityUUID[16];
+
+            /**
+             * Beacon Major group ID.
+             */
+            uint16_t majorNumber;
+
+            /**
+             * Beacon minor ID.
+             */
+            uint16_t minorNumber;
+
+            /**
+             * Tx power received at 1 meter; in dBm.
+             */
+            uint8_t txPower;
+        };
+
+        /**
+         * Assemble an iBeacon payload.
+         *
+         * @param[in] uuid Beacon network ID. iBeacon operators use this value
+         * to group their iBeacons into a single network, a single region and
+         * identify their organization among others.
+         *
+         * @param[in] majNum Beacon major group ID. iBeacon exploitants may use
+         * this field to divide the region into subregions, their network into
+         * subnetworks.
+         *
+         * @param[in] minNum Identifier of the Beacon in its subregion.
+         *
+         * @param[in] transmitPower Measured transmit power of the beacon at 1
+         * meter. Scanners use this parameter to approximate the distance
+         * to the beacon.
+         *
+         * @param[in] companyIDIn ID of the beacon manufacturer.
+         */
+        Payload(
+            const uint8_t *uuid,
+            uint16_t majNum,
+            uint16_t minNum,
+            uint8_t transmitPower,
+            uint16_t companyIDIn
+        ) : companyID(companyIDIn),
+            ID(0x02),
+            len(0x15),
+            majorNumber(__REV16(majNum)),
+            minorNumber(__REV16(minNum)),
+            txPower(transmitPower)
+        {
+            memcpy(proximityUUID, uuid, 16);
+        }
+    };
+
+    /** Callback triggered when the ble initialization process has finished */
+    void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
+        if (params->error != BLE_ERROR_NONE) {
+            printf("Ble initialization failed.");
+            return;
+        }
+
+        print_mac_address();
+
+        start_advertising();
     }
 
-    /**
-     * The Beacon payload has the following composition:
-     * 128-Bit / 16byte UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61
-     * Major/Minor  = 0x1122 / 0x3344
-     * Tx Power     = 0xC8 = 200, 2's compliment is 256-200 = (-56dB)
-     *
-     * Note: please remember to calibrate your beacons TX Power for more accurate results.
-     */
-    static const uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4,
-                                   0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61};
-    uint16_t majorNumber = 1122;
-    uint16_t minorNumber = 3344;
-    uint16_t txPower     = 0xC8;
-    ibeaconPtr = new iBeacon(ble, uuid, majorNumber, minorNumber, txPower);
+    void start_advertising() {
+        /* Create advertising parameters and payload */
+
+        ble::AdvertisingParameters adv_parameters(
+            ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
+            ble::adv_interval_t(ble::millisecond_t(1000))
+        );
+
+        _adv_data_builder.setFlags();
+
+        /**
+         * The Beacon payload has the following composition:
+         * 128-Bit / 16byte UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61
+         * Major/Minor  = 0x1122 / 0x3344
+         * Tx Power     = 0xC8 = 200, 2's compliment is 256-200 = (-56dB)
+         *
+         * Note: please remember to calibrate your beacons TX Power for more accurate results.
+         */
+        static const uint8_t uuid[] = { 0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4,
+                                        0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61 };
+        uint16_t major_number = 1122;
+        uint16_t minor_number = 3344;
+        uint16_t tx_power     = 0xC8;
+        uint16_t comp_id      = 0x004C;
+
+        Payload ibeacon(uuid, major_number, minor_number, tx_power, comp_id);
+
+        _adv_data_builder.setManufacturerSpecificData(ibeacon.raw);
+
+        /* Setup advertising */
+
+        ble_error_t error = _ble.gap().setAdvertisingParameters(
+            ble::LEGACY_ADVERTISING_HANDLE,
+            adv_parameters
+        );
 
-    ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
-    ble.gap().startAdvertising();
+        if (error) {
+            print_error(error, "_ble.gap().setAdvertisingParameters() failed");
+            return;
+        }
+
+        error = _ble.gap().setAdvertisingPayload(
+            ble::LEGACY_ADVERTISING_HANDLE,
+            _adv_data_builder.getAdvertisingData()
+        );
+
+        if (error) {
+            print_error(error, "_ble.gap().setAdvertisingPayload() failed");
+            return;
+        }
+
+        /* Start advertising */
+
+        error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
 
-    printMacAddress();
-}
+        if (error) {
+            print_error(error, "_ble.gap().startAdvertising() failed");
+            return;
+        }
+    }
+
+private:
+    /* Event handler */
 
-void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
-    BLE &ble = BLE::Instance();
-    eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
+    void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) {
+        _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
+    }
+
+private:
+    BLE &_ble;
+    events::EventQueue &_event_queue;
+
+    uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
+    ble::AdvertisingDataBuilder _adv_data_builder;
+};
+
+/** Schedule processing of events from the BLE middleware in the event queue. */
+void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
+    event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
 }
 
 int main()
 {
     BLE &ble = BLE::Instance();
-    ble.onEventsToProcess(scheduleBleEventsProcessing);
-    ble.init(bleInitComplete);
+    ble.onEventsToProcess(schedule_ble_events);
 
-    eventQueue.dispatch_forever();
+    BeaconDemo demo(ble, event_queue);
+    demo.start();
 
     return 0;
 }