Ble for smart sOlutions

Dependencies:   Adafruit_WS2801

Revision:
9:92d861703f96
Parent:
8:369b80cef5ae
Child:
10:d845189d146e
--- a/source/BleDevice.h	Tue May 21 13:57:27 2019 +0200
+++ b/source/BleDevice.h	Tue Jun 11 11:16:55 2019 +0200
@@ -8,6 +8,7 @@
 
 #include <mbed.h>
 #include "SecurityManager.h"
+#include "CustomUUIDs.h"
 #include "ble/BLE.h"
 
 #include "ble/DiscoveredCharacteristic.h"
@@ -24,6 +25,16 @@
                   public SecurityManager::EventHandler,
                   public ble::Gap::EventHandler
 {
+    typedef BleDevice Self;
+    typedef CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t
+            DiscoveryCallbackParams_t;
+
+    typedef CharacteristicDescriptorDiscovery::TerminationCallbackParams_t
+            TerminationCallbackParams_t;
+
+    typedef DiscoveredCharacteristic::Properties_t Properties_t;
+
+
 public:
     inline void print_error(ble_error_t error, const char* msg)
     {
@@ -110,7 +121,8 @@
             _ble(const_cast<BLE &>(ble)),
             _event_queue(event_queue),
             _handle(0),
-            _is_connecting(false) { };
+            _is_connecting(false),
+            hi(false){ };
 
     virtual ~BleDevice()
     {
@@ -153,8 +165,7 @@
 
         /* this will not return until shutdown */
         //BUT IT SHOULD!
-//        _event_queue.dispatch_forever();
-//        wait(2);
+//        _event_queue.dispatch_forever();//        wait(2);
 //        printf(" Waited? ");
         _event_queue.dispatch(time);
     };
@@ -199,6 +210,173 @@
     };
 
 private:
+    static void print_uuid(const UUID &uuid)
+    {
+        const uint8_t *uuid_value = uuid.getBaseUUID();
+
+        // UUIDs are in little endian, print them in big endian
+        for (size_t i = 0; i < uuid.getLen(); ++i) {
+            printf("%02X", uuid_value[(uuid.getLen() - 1) - i]);
+        }
+    }
+    void when_service_discovered(const DiscoveredService *discovered_service)
+    {
+        // print information of the service discovered
+        printf("Service discovered: value = ");
+        print_uuid(discovered_service->getUUID());
+        printf(", start = %u, end = %u.\r\n",
+               discovered_service->getStartHandle(),
+               discovered_service->getEndHandle()
+        );
+    }
+    /**
+       * Add a discovered characteristic into the list of discovered characteristics.
+       */
+//    bool add_characteristic(const DiscoveredCharacteristic *characteristic)
+//    {
+//        //TODO: If char UUID == UUID, store char for reading
+//        if
+//        printf("Adding char");
+//
+////        if (new_node == false) {
+////            printf("Error while allocating a new characteristic.\r\n");
+////            return false;
+////        }
+//        printf("Added char");
+//
+//        if (_characteristics == NULL) {
+//            _characteristics = const_cast<DiscoveredCharacteristic *>(characteristic);
+//        } else {
+//            DiscoveredCharacteristic* c = _characteristics;
+//            while() {
+//                c = c->next;
+//            }
+//            c->next = new_node;
+//        }
+//        delete new_node;
+//        return true;
+//    }
+    /**
+     * Handle characteristics discovered.
+     *
+     * The GattClient invoke this function when a characteristic has been
+     * discovered.
+     *
+     * @see GattClient::launchServiceDiscovery
+     */
+    void when_characteristic_discovered(const DiscoveredCharacteristic *discovered_characteristic)
+    {
+        // print characteristics properties
+        printf("\tCharacteristic discovered: uuid = ");
+        print_uuid(discovered_characteristic->getUUID());
+        printf(", properties = ");
+//        print_properties(discovered_characteristic->getProperties());
+        printf(
+                ", decl handle = %u, value handle = %u, last handle = %u.\r\n",
+                discovered_characteristic->getDeclHandle(),
+                discovered_characteristic->getValueHandle(),
+                discovered_characteristic->getLastHandle()
+        );
+        if(discovered_characteristic->getUUID() == CustomUUIDs::UUID_INTEREST_CHAR){
+            printf("You have the interest char!");
+            hi = true;
+            _interest_characteristic = discovered_characteristic;
+        }
+    }
+
+    /**
+     * Handle termination of the service and characteristic discovery process.
+     *
+     * The GattClient invokes this function when the service and characteristic
+     * discovery process ends.
+     *
+     * @see GattClient::onServiceDiscoveryTermination
+     */
+    void when_service_discovery_ends(Gap::Handle_t connection_handle)
+    {
+        if (!hi) {
+            printf("No characteristics discovered, end of the process.\r\n");
+            return;
+        }
+
+        printf("All services and characteristics discovered, process them.\r\n");
+
+        process_next_characteristic();
+        // reset iterator and start processing characteristics in order
+//        _event_queue.call(mbed::callback(this, &Self::process_next_characteristic));
+    }
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Processing of characteristics based on their properties.
+
+    void process_next_characteristic(void)
+    {
+        printf("Test");
+        if(_interest_characteristic){
+            //Interest char can be null; check that
+            Properties_t properties = _interest_characteristic->getProperties();
+
+            if (properties.read()) {
+                read_characteristic(*_interest_characteristic);
+                return;
+            } else {
+//                printf(
+//                        "Skip processing of characteristic %u\r\n",
+//                        _it->value.getValueHandle()
+//                );
+//                _it = _it->next;
+            }
+
+        }
+
+        printf("All characteristics discovered have been processed.\r\n");
+    }
+    /**
+     * Initate the read of the characteristic in input.
+     *
+     * The completion of the operation will happens in when_characteristic_read()
+     */
+    void read_characteristic(const DiscoveredCharacteristic &characteristic)
+    {
+        printf("Initiating read at %u.\r\n", characteristic.getValueHandle());
+        ble_error_t error = characteristic.read(
+                0, makeFunctionPointer(this, &Self::when_characteristic_read)
+        );
+
+        if (error) {
+            printf(
+                    "Error: cannot initiate read at %u due to %u\r\n",
+                    characteristic.getValueHandle(), error
+            );
+        }
+    }
+
+        /**
+         * Handle the reception of a read response.
+         *
+         * If the characteristic can emit notification or indication then start the
+         * discovery of the the characteristic descriptors then subscribe to the
+         * server initiated event by writing the CCCD discovered. Otherwise start
+         * the processing of the next characteristic discovered in the server.
+     */
+    void when_characteristic_read(const GattReadCallbackParams *read_event)
+    {
+        printf("\tCharacteristic value at %u equal to: ", read_event->handle);
+        for (size_t i = 0; i <  read_event->len; ++i) {
+            printf("0x%02X ", read_event->data[i]);
+        }
+        printf(".\r\n");
+
+//        Properties_t properties = _>getProperties();
+
+//        if(properties.notify() || properties.indicate()) {
+//            discover_descriptors(_it->value);
+//        } else {
+//            process_next_characteristic();
+//        }
+    }
+
     /* Event handler */
 
     /** This is called by Gap to notify the application we disconnected,
@@ -224,6 +402,37 @@
         _event_queue.break_dispatch();
     }
 
+    /** This is called by Gap to notify the application we connected,
+  *  in our case it immediately request pairing */
+    virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event)
+    {
+        if (event.getStatus() == BLE_ERROR_NONE) {
+            /* store the handle for future Security Manager requests */
+            _handle = event.getConnectionHandle();
+
+            printf("Connected\r\n");
+
+            /* in this example the local device is the master so we request pairing */
+//            ble_error_t error = _ble.securityManager().requestPairing(_handle);
+
+//            if (error) {
+//                printf("Error during SM::requestPairing %d\r\n", error);
+//                return;
+//            }
+            _ble.gattClient().onServiceDiscoveryTermination(makeFunctionPointer(this, &Self::when_service_discovery_ends));
+            _ble.gattClient().launchServiceDiscovery(_handle, makeFunctionPointer(this, &Self::when_service_discovered), makeFunctionPointer(this, &Self::when_characteristic_discovered));
+            /* upon pairing success the application will disconnect */
+        }
+
+        /* failed to connect - restart scan */
+//        ble_error_t error = _ble.gap().startScan();
+
+//        if (error) {
+//            print_error(error, "Error in Gap::startScan %d\r\n");
+//            return;
+//        }
+    }
+
 private:
     DigitalOut _led1;
 
@@ -232,6 +441,9 @@
     events::EventQueue &_event_queue;
     ble::connection_handle_t _handle;
     bool _is_connecting;
+    bool hi;
+    const DiscoveredCharacteristic *_interest_characteristic;
+
 };