Dependencies:   BLE_API mbed nRF51822

Fork of CoolTourHat by Karl Engelhardt

Revision:
23:ba3d7a28096d
Parent:
22:406127954d1f
Child:
24:78ef9deab4bc
--- a/main.cpp	Mon Nov 09 17:08:47 2015 +0000
+++ b/main.cpp	Sun Mar 05 06:00:31 2017 +0000
@@ -1,61 +1,231 @@
 #include "mbed.h"
 #include "ble/BLE.h"
+#include "ble/BLEProtocol.h"
+#include "ble/GapAdvertisingData.h"
+#include "ble/DiscoveredService.h"
+#include "ble/DiscoveredCharacteristic.h"
 
-DigitalOut led(LED1, 1);
-uint16_t customServiceUUID  = 0xA000;
-uint16_t readCharUUID       = 0xA001;
-uint16_t writeCharUUID      = 0xA002;
+BLE &ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
+Serial pc(USBTX, USBRX);
+// Connect handle
+uint16_t peripheral_handle = GattAttribute::INVALID_HANDLE;
+uint16_t client_handle = GattAttribute::INVALID_HANDLE;
+
+DiscoveredCharacteristic interests_other;
+DiscoveredCharacteristic alarm_read_other;
+DiscoveredCharacteristic alarm_write_other;
 
-const static char     DEVICE_NAME[]        = "ChangeMe!!"; // change this
+const uint8_t NRF_SUCCESS = 1;
+const uint8_t NRF_ERROR_NOT_FOUND = 2;
+
+uint16_t customServiceUUID  = 0x6f6c;
+uint16_t interestUUID       = 0x0001;
+uint16_t alertUUID          = 0x0002;
+uint16_t alertReadUUID      = 0x0003;
+
+const static char     DEVICE_NAME[]        = "CoolTourHat";
 static const uint16_t uuid16_list[]        = {0xFFFF}; //Custom UUID, FFFF is reserved for development
 
-/* Set Up custom Characteristics */
-static uint8_t readValue[10] = {0};
-ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(readCharUUID, readValue);
+
+static uint8_t interestValue[22] = {0x01, 0xFF};
+ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(interestValue)> interestChar(interestUUID, interestValue);
+
 
-static uint8_t writeValue[10] = {0};
-WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue);
+static uint8_t alertValue[1] = {0};
+WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(alertValue)> alarmChar(alertUUID, alertValue);
+static uint8_t alertReadValue[1] = {0};
+ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(alertReadValue)> readAlarmChar(alertReadUUID, alertReadValue);
 
 /* Set up custom service */
-GattCharacteristic *characteristics[] = {&readChar, &writeChar};
+GattCharacteristic *characteristics[] = {&interestChar, &alarmChar, &readAlarmChar};
 GattService        customService(customServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
 
 
 /*
  *  Restart advertising when phone app disconnects
 */
+
+void alarm() {
+    pc.printf("ALARRRRM\r\n");
+    wait(0.1);
+}
+void onAlarmWritten(const GattWriteCallbackParams *response) {
+    alarm();
+    alarm_write_other.write(1, (uint8_t[1]) {0x01}, onAlarmWritten);
+}
+void onDataRead(const GattReadCallbackParams *response) {
+    if (response->len == 22) {
+        bool a = false;
+        for (unsigned i=0;i<=22;i++) {
+            if (response->data[i] ^ interestValue[i] != 0)
+                a = true;
+        }
+        if (a) {
+            alarm_write_other.write(1, (uint8_t[1]) {0x01}, onAlarmWritten);
+        }
+
+    } else {
+        pc.printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
+        for (unsigned index = 0; index < response->len; index++) {
+            pc.printf("%c[%02x]", response->data[index], response->data[index]);
+        }
+        pc.printf("\r\n");
+    }
+}
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
 {
     BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
 }
 
-/*
- *  Handle writes to writeCharacteristic
-*/
+
+void discoveredServiceCallBack(const DiscoveredService *service) {
+  pc.printf("\r\n----Servuce Discovered"); pc.printf("\n");
+
+  if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        pc.printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
+    } else {
+        pc.printf("S UUID-");
+        const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
+        for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
+            pc.printf("%02x", longUUIDBytes[i]);
+        }
+        pc.printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
+    }
+  pc.printf("The service start handle : %x\n", service->getStartHandle());
+  pc.printf("The service end handle   : %x\n", service->getEndHandle());
+
+
+}
+
+void discoveredCharacteristicCallBack(const DiscoveredCharacteristic *chars) {
+  pc.printf("\r\n----Characteristic Discovered"); pc.printf("\n");
+    pc.printf("Chars UUID type        : %x\n", chars->getUUID().shortOrLong()); pc.printf("\n");// 0 16bit_uuid, 1 128bit_uuid
+
+    pc.printf("S UUID-%04x\r\n", chars->getUUID().getShortUUID());
+
+
+  pc.printf("properties_read        : %d\n", chars->getProperties().read());
+  pc.printf("properties_writeWoResp : %d\n", chars->getProperties().writeWoResp());
+  pc.printf("properties_write       : %d\n", chars->getProperties().write());
+  pc.printf("properties_notify      : %d\n", chars->getProperties().notify());
+
+  pc.printf("declHandle             : %x\n", chars->getDeclHandle());
+  pc.printf("valueHandle            : %x\n", chars->getValueHandle());
+  pc.printf("lastHandle             : %x\n", chars->getLastHandle());
+  if (chars->getUUID().getShortUUID() == 0x0001) {
+    pc.printf("interests_other\n");
+    interests_other = *chars;
+  } else if (chars->getUUID().getShortUUID() == 0x0002) {
+    pc.printf("alarm_write_other\n");
+    alarm_write_other = *chars;
+  } else if (chars->getUUID().getShortUUID() == 0x0003) {
+    pc.printf("alarm_read_other\n");
+    alarm_read_other = *chars;
+    interests_other.read(0, onDataRead);
+  }
+
+}
 void writeCharCallback(const GattWriteCallbackParams *params)
 {
-    /* Check to see what characteristic was written, by handle */
-    if(params->handle == writeChar.getValueHandle()) {
-        /* toggle LED if only 1 byte is written */
-        if(params->len == 1) {
-            led = params->data[0];
-            (params->data[0] == 0x00) ? printf("led on\n\r") : printf("led off\n\r"); // print led toggle
+    if(params->handle == alarmChar.getValueHandle()) {
+        if(params->len == 1 && params->data[0] == 0x01) {            
+            pc.printf("alarm\n");
+            static uint8_t v[1] = {0x01};
+            BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(readAlarmChar.getValueHandle(), 
+                v, sizeof(v));
+            alarm();
+            pc.printf("alarm stop\n");
+            v[0] = 0x00;
+            BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(readAlarmChar.getValueHandle(), v, sizeof(v));
         }
-        /* Print the data if more than 1 byte is written */
-        else {
-            printf("Data received: length = %d, data = 0x",params->len);
-            for(int x=0; x < params->len; x++) {
-                printf("%x", params->data[x]);
-            }
-            printf("\n\r");
-        }
-        /* Update the readChar with the value of writeChar */
-        BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(readChar.getValueHandle(), params->data, params->len);
     }
 }
-/*
- * Initialization callback
- */
+uint32_t ble_advdata_parser(uint8_t type, uint8_t advdata_len, uint8_t *p_advdata, uint8_t *len, uint8_t *p_field_data) {
+  uint8_t index=0;
+  uint8_t field_length, field_type;
+
+  while(index<advdata_len) {
+    field_length = p_advdata[index];
+    field_type   = p_advdata[index+1];
+    if(field_type == type) {
+      memcpy(p_field_data, &p_advdata[index+2], (field_length-1));
+      *len = field_length - 1;
+      return NRF_SUCCESS;
+    }
+    index += field_length + 1;
+  }
+  return NRF_ERROR_NOT_FOUND;
+}
+void scanCallBack(const Gap::AdvertisementCallbackParams_t *params) {
+  pc.printf("Scan CallBack \n");
+  pc.printf("PerrAddress: ");
+  for(uint8_t index=0; index<6; index++) {
+    pc.printf("%02x ", params->peerAddr[index]);
+  }
+  pc.printf("\n");
+  pc.printf("The Rssi : ");
+  pc.printf("%d\n", params->rssi);
+
+  // Get local name in advertisement
+  uint8_t len=0;
+  uint8_t adv_name[31];
+  if(NRF_SUCCESS == ble_advdata_parser(GapAdvertisingData::COMPLETE_LOCAL_NAME, params->advertisingDataLen, (uint8_t *)params->advertisingData, &len, adv_name)) {
+    pc.printf("Complete name len : %d\n", len);
+    pc.printf("Complete name is  : %s\n", (const char*)adv_name);
+    if((len >= 10) && (memcmp("CoolTourHat", adv_name, 10) == 0x00)) {
+      pc.printf("Find device, stop scanning and start connecting\n");
+      ble.gap().stopScan();
+      ble.connect(params->peerAddr, BLEProtocol::AddressType::RANDOM_STATIC, NULL, NULL);
+    }
+  }
+}
+void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
+    pc.printf("terminated SD for handle %u\r\n", connectionHandle);
+}
+void connectionCallBack( const Gap::ConnectionCallbackParams_t *params ) {
+  if(params->role == Gap::CENTRAL) {
+    pc.printf("Central, connected to remote device\n");
+    pc.printf("The conn handle : %x\n", params->handle);
+
+    pc.printf("  The peerAddr : ");
+    for(uint8_t index=6; index>0; index--) {
+      pc.printf("%02x ", params->peerAddr[index-1]);
+    }
+    ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
+    // Start to discovery
+    ble.gattClient().launchServiceDiscovery(params->handle, discoveredServiceCallBack, discoveredCharacteristicCallBack, 0x6f6c);//, customServiceUUID, interestUUID);
+  }
+  else {
+    pc.printf("peripheral, be connected by a central device\n");
+    peripheral_handle = params->handle;
+    pc.printf("The conn handle : %x\n", params->handle);
+  }
+}
+
+void disconnectionCallBack(const Gap::DisconnectionCallbackParams_t *params) {
+  pc.printf("Disconnected handler  %x\n", params->handle);
+  pc.printf("Disconnected reson %x \n", params->reason);
+  if(peripheral_handle == params->handle) {
+    peripheral_handle = 0;
+    pc.printf("Restart advertising\n");
+    ble.startAdvertising();
+  }
+  else if(client_handle == params->handle) {
+    client_handle = 0;
+    pc.printf("Restart scanning\n");
+    ble.startScan(scanCallBack);
+  }
+}
+
+ 
+void onDataWrite(const GattWriteCallbackParams *response) {
+    pc.printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
+        for (unsigned index = 0; index < response->len; index++) {
+            pc.printf("%c[%02x]", response->data[index], response->data[index]);
+        }
+        pc.printf("\r\n");
+ 
+}
 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
 {
     BLE &ble          = params->ble;
@@ -65,7 +235,8 @@
         return;
     }
 
-    ble.gap().onDisconnection(disconnectionCallback);
+    ble.onConnection(connectionCallBack);
+    ble.onDisconnection(disconnectionCallBack);
     ble.gattServer().onDataWritten(writeCharCallback);
 
     /* Setup advertising */
@@ -80,25 +251,27 @@
 
     /* Start advertising */
     ble.gap().startAdvertising();
+    ble.setScanParams(2000, 200, 0, false);
+    // start scanning
+    ble.startScan(scanCallBack);
+    pc.printf("Start scanning\n");
+    // start advertising
+    ble.startAdvertising();
+    pc.printf("Start advertising\n");
 }
 
-/*
- *  Main loop
-*/
 int main(void)
 {
-    /* initialize stuff */
-    printf("\n\r********* Starting Main Loop *********\n\r");
     
-    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
-    ble.init(bleInitComplete);
+    /* initialize stuff */
+    pc.printf("\n\r********* Starting Main Loop *********\n\r");
+    
     
-    /* SpinWait for initialization to complete. This is necessary because the
-     * BLE object is used in the main loop below. */
-    while (ble.hasInitialized()  == false) { /* spin loop */ }
+    ble.init(bleInitComplete);
 
-    /* Infinite loop waiting for BLE interrupt events */
+    while (ble.hasInitialized()  == false) {}
+
     while (true) {
-        ble.waitForEvent(); /* Save power */
+        ble.waitForEvent();
     }
 }
\ No newline at end of file