This software setup a central node of a star topology network

Dependencies:   MQTT target_st_bluenrg

Fork of ble-star-mbed by Lorenzo Invidia

Revision:
0:1902469bdd2d
Child:
1:110b5e896bc9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/BleSlaveService.cpp	Tue Feb 20 11:21:41 2018 +0000
@@ -0,0 +1,885 @@
+#include <BleSlaveService.h>
+
+
+/* ----- Private variables ----- */
+/* Struct of slave dev */
+SlaveDevice_t slaveDev;
+
+
+ChangeNotificationQueue notifyQ, *notifyP;
+
+
+/* Struct of periph dev */
+extern PeripheralDevices_t perDevs;
+
+/* Notification frequency */
+uint8_t notification_freq = NOTIFICATION_FREQ_WIFI_OFF;
+
+
+/* Star Service and Characteristic */
+uint8_t sUuid[16]    = {0x00,0x00,0x00,0x00,0x00,0x01,0x11,0xe1,0x9a,0xb4,0x00,0x02,0xa5,0xd5,0xc5,0x1b};
+uint8_t dataUuid[16] = {0x00,0x08,0x00,0x00,0x00,0x01,0x11,0xe1,0xac,0x36,0x00,0x02,0xa5,0xd5,0xc5,0x1b};
+uint8_t confUuid[16] = {0x00,0x04,0x00,0x00,0x00,0x01,0x11,0xe1,0xac,0x36,0x00,0x02,0xa5,0xd5,0xc5,0x1b};
+
+
+/*---- Create the two characteristic ----*/
+/* Config char */
+GattCharacteristic configChar(confUuid, slaveDev.star_config_value, STAR_CHAR_MAX_VALUE_LEN, STAR_CHAR_MAX_VALUE_LEN,
+               GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE,
+               NULL, 0, true);
+
+
+/* Data char */
+GattCharacteristic dataChar(dataUuid, slaveDev.notification_data.attribute_value, STAR_CHAR_MAX_VALUE_LEN, STAR_CHAR_MAX_VALUE_LEN,
+             GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE,
+             NULL, 0, true);
+
+
+/* MANUFACTURER_SPECIFIC_DATA */
+    uint8_t manuf_data[6] = {
+                0x01, /*SKD version */
+                0x81, /* NUCLEO-Board remote */
+                0x00, /* Led Prox+Lux */ //Unused
+                0x0C, /* Star Config Char + Star Data Char */ //Unused
+                0x00, /* SensorFusionShort */ //Unused
+                0x00 /* SensorFusionFloat */ //Unused
+    };
+
+
+
+
+
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Set the device as a slave in discoverable mode */
+void setSlaveDiscoverable(void) {
+    //printf("\r\nsetSlaveDiscoverable\n");//DEBUG
+    BLE& ble = BLE::Instance();
+    ble_error_t e2;
+
+
+    //if-MAIN - discovery/reading/writing ops completed
+    if ((discoveryCompleted == 1) /*&& (readCompleted == 1) && (writeDescriptorCompleted == 1)*/){
+
+
+
+        /* Start advertisng */
+        if ((!ble.gap().getState().advertising)){
+            advEnds =0;
+
+            printf("\r\nSet Discoverable Mode (%d)\n", perDevs.status);
+            e2 = ble.gap().startAdvertising();
+            if ( e2 == BLE_ERROR_NONE ){
+                /* Giving some time to connect */
+                eventQ.call_in(7000, stopAdv);//N ms
+            }else{
+                printf("\r\nError while starting advertising (err: %d - stat: %d)\n", e2, perDevs.status);
+                advEnds=1;//terminated because not started
+            }
+
+        }//if-not-adv
+    }//if-MAIN
+
+
+    //Restart loop ops
+    perDevs.status = CONN_INIT;
+    perDevs.discovery_enabled = true;
+    //printf("\rstatus = CONN_INIT (%d)\n", perDevs.status);//DEBUG
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+void stopAdv(){
+
+    if ((slaveDev.is_connected == false) && (discoveryCompleted == 1)){
+        if (BLE::Instance().gap().getState().advertising){
+            ble_error_t e = BLE::Instance().gap().stopAdvertising();
+            if ( e != BLE_ERROR_NONE ) {
+                printf("\r\nError stopping ADV\n");//DEBUG
+            }
+        }
+    }//if
+
+    advEnds = 1;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/**
+ * @brief  This function sets some notification properties (e.g. the
+ *         notification period) by sending a command according to the
+ *         following format:
+ *         FEATURE_MASK (4bytes) + Command (1byte) + Data (1byte)
+ *         In case of the notification period the command is 255 while the allowed data are:
+ *         50 @5S, 10 @1S, 1 @100mS, 0 @50mS (default).
+ * @param  connection handle
+ * @param  peripheral device index
+ * @param  feature mask
+ * @param  command
+ * @param  data
+ * @retval None
+ */
+void setNotificationProperty(uint16_t conn_handle, uint8_t i, uint32_t feature_mask,
+                             uint8_t command, uint8_t data) {
+    //printf("\r\nsetNotificationProperty\n");//DEBUG
+
+    uint16_t attr_handle;
+    uint8_t  value_len;
+    uint8_t  attr_value[6];
+
+    attr_handle = perDevs.cfg_char_handle[i] + 1;
+    attr_value[0] = (uint8_t)((feature_mask) >> 24);
+    attr_value[1] = (uint8_t)((feature_mask) >> 16);
+    attr_value[2] = (uint8_t)((feature_mask) >> 8);
+    attr_value[3] = (uint8_t)((feature_mask));
+    attr_value[4] = command;
+    attr_value[5] = data;
+    value_len = 6;  /* FEATURE_MASK len (4bytes) + Command len (1byte) + Data len (1byte) */
+
+
+    /* The gatt write function above is w/out response, so we just wait for a short time before going on */
+    writeCharacValueWithoutResp(conn_handle, attr_handle, value_len, attr_value);
+    HAL_Delay(2000);//N ms
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Forwards to master all notifications from peripherals */
+void notifyMaster(uint8_t data_length, uint8_t* attribute_value, uint16_t attribute_handle){
+    //printf("\r\nnotifyMaster\n");//DEBUG
+    ble_error_t notifyError;
+
+    if (discoveryCompleted == 1){
+        
+        notifyError = BLE::Instance().gattServer().write(attribute_handle+1, attribute_value, data_length, false);
+
+        if (notifyError != BLE_ERROR_NONE){
+            printf("\r\n(notifyMaster) Error (%d) while updating characteristic\n", notifyError);//BLE_STACK_BUSY
+            //HAL_Delay(1000);//giving some time to slowdown the rate
+            return;
+        }
+        
+    } else {
+        //HAL_Delay(1000);//giving some time to slowdown the rate
+        //dOING SOMETHING !
+        return;
+    }   
+}
+/*----------------------------------------------------------------------------*/
+
+
+/* Add all services using a vendor specific UUIDs */
+void addAllServices(void){
+
+    ble_error_t error;
+    notifyP = &notifyQ;
+
+
+    GattCharacteristic *charTable[] = {&configChar, &dataChar};
+
+    /*---- Create the hw service ----*/
+    GattService starService(sUuid, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+
+    /*---- Add the hw service ----*/
+    error = BLE::Instance().addService(starService);
+    slaveDev.star_hw_serv_handle     = starService.getHandle();
+    slaveDev.star_config_char_handle = configChar.getValueHandle()-1;   //-1 for decl handle
+    slaveDev.star_data_char_handle   = dataChar.getValueHandle()-1;     //-1 for decl handle
+
+
+
+    if ( error != BLE_ERROR_NONE ){
+        printf("\r\nError while creating starService(error: %d)\n", error);
+
+    } else {
+        printf("\r\nStar HW Gatt Service added (handle 0x%004x)\n", slaveDev.star_hw_serv_handle);
+        printf("\rStar HW Config Char added (handle 0x%004x)\n", slaveDev.star_config_char_handle);
+        printf("\rStar HW Data Char added (handle 0x%004x)", slaveDev.star_data_char_handle);
+        printf("\r\n");
+    }
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+/* Disable all notifications */
+void disableAllNotifications(void){
+    //printf("\r\ndisableAllNotifications\n");//DEBUG
+
+    
+    uint8_t j;
+    uint16_t attr_handle;
+    uint8_t  value_len;
+    uint8_t  attr_value[2];
+    char* feat = NULL;
+
+    for (j=0; j<(perDevs.connDevices+perDevs.discDevices); j++) {
+
+        if ((perDevs.mic_event[j]) && (perDevs.mic_event_enabled))  {
+            feat = "MIC";
+            perDevs.mic_event_enabled = 0;
+            perDevs.mic_event[j] = 0;
+            attr_handle = perDevs.mic_char_handle[j] + 2;
+
+        } else if ((perDevs.prx_event[j]) && (perDevs.prx_event_enabled)) {
+            feat = "PRX";
+            perDevs.prx_event_enabled = 0;
+            perDevs.prx_on[j] = 0;
+            attr_handle = perDevs.prx_char_handle[j] + 2;
+
+        } else if ((perDevs.agm_event[j]) && (perDevs.agm_event_enabled)) {
+            feat = "AGM";
+            perDevs.acc_event_enabled = 0;
+            perDevs.gyr_event_enabled = 0;
+            perDevs.mag_event_enabled = 0;
+            perDevs.agm_event_enabled = 0;
+            perDevs.agm_on[j] = 0;
+            attr_handle = perDevs.agm_char_handle[j] + 2;
+
+        } else if ((perDevs.sfusion_event[j]) && (perDevs.sfusion_event_enabled)) {
+            feat = "SFUSION";
+            perDevs.sfusion_event_enabled = 0;
+            perDevs.sfusion_on[j] = 0;
+            attr_handle = perDevs.sfusion_char_handle[j] + 2;
+
+        } else {
+            continue;
+        }
+
+        value_len = 2;
+        attr_value[0] = DISABLE;
+        
+
+        writeDescriptorCompleted=0;
+        ble_error_t disableErr = writeCharacDescriptorWithError(perDevs.connection_handle[j], attr_handle, value_len, attr_value);
+        printf("\r\nSet OFF the %s notifications on node %d\n", feat, j);
+
+        if (disableErr != BLE_ERROR_NONE){
+            printf("\r\n(disableAllNotifications) Write charac descriptor failed (%d)\n", disableErr);
+            writeDescriptorCompleted=1;
+            //HAL_Delay(500);
+            //disableAllNotifications();
+        }//if-error
+    }//for
+    
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* This function enables or disables the new peripheral scanning */
+void setNewNodesScanning(uint8_t enabled){
+
+    STORE_LE_16(slaveDev.star_config_value,(HAL_GetTick()>>3)); /* Timestamp */
+
+    switch (enabled) {
+    case 0x01:
+        perDevs.discovery_enabled = true;
+        //printf("\r\nScanning enabled (%d)\n", enabled);
+    break;
+
+    case 0x02:
+        perDevs.discovery_enabled = false;
+        //printf("\r\nScanning disabled (%d)\n", enabled);
+    break;
+
+    default:
+        //printf("\r\nScanning set to unrecognized value (%d)\n", enabled);
+    break;
+    }
+
+    slaveDev.star_config_value[2] = enabled;
+    slaveDev.star_config_value_len = 3;
+    //HAL_Delay(300);
+
+    /* Notify master for scanning */
+
+/* Stack busy, solve this */
+//    notifyMaster(slaveDev.star_config_value_len, slaveDev.star_config_value,
+//                 slaveDev.star_config_char_handle);
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+//NOT USED FOR NOW !!
+/* This function forwards to the peripheral device the command coming from the Cloud */
+void Forward_Command_To_BlueNRG(uint8_t* data_ptr, uint8_t data_length){
+
+    uint16_t handle;
+    uint8_t  buffer[4] = {0, 0, 0, 0};
+    uint8_t  num, even, odd;
+    uint8_t  i;
+    uint8_t cmd_type;
+
+    cmd_type = (data_ptr[0] - '0') << 4 | (data_ptr[1] - '0');
+    //printf("\r\ncommand %d\n", cmd_type);
+
+  switch (cmd_type)
+  {
+  case 0:
+    printf("\rScan cmd type (%d)\n", cmd_type);
+    handle = slaveDev.star_config_char_handle + 1;
+    break;
+  case 1:
+    printf("\rLED/MIC/PRX cmd type (%d)\n", cmd_type);
+    handle = slaveDev.star_data_char_handle + 1;
+    break;
+  default:
+    printf("\rUnknown cmd type (%d)\n", cmd_type);
+    return;
+    //break;
+  }
+
+  /**
+  * For Scan cmd type:
+  * |Value  |
+  * |1 byte |
+  * For LED/MIC/PRX cmd type:
+  * |Node ID | Type ID | Value   |
+  * |2 bytes | 1 byte  | x bytes |
+  */
+  for (i=2; i<data_length; i++) {
+    switch (data_ptr[i])
+    {
+    case 'A':
+    case 'a':
+      num = 10;
+      break;
+    case 'B':
+    case 'b':
+      num = 11;
+      break;
+    case 'C':
+    case 'c':
+      num = 12;
+      break;
+    case 'D':
+    case 'd':
+      num = 13;
+      break;
+    case 'E':
+    case 'e':
+      num = 14;
+      break;
+    case 'F':
+    case 'f':
+      num = 15;
+      break;
+    default:
+      num = data_ptr[i] - '0';
+      break;
+    }
+    if (!(i%2)) {
+      even = num << 4;
+    }
+    else {
+      odd = num;
+      buffer[(i-2)/2] = even | odd;
+    }
+  }
+
+  createAttribute_Modified_CB_Prototype(handle, (data_length-2)/2, buffer);
+}
+/*----------------------------------------------------------------------------*/
+
+
+/* Function used to call AttributeModified_CB outside the callback call */
+void createAttribute_Modified_CB_Prototype(uint16_t handle, uint8_t data_length, uint8_t *att_data){
+
+    GattWriteCallbackParams paramStruct, *pointerToParam;
+    pointerToParam = &paramStruct;
+
+    pointerToParam->handle = handle;
+    pointerToParam->len = data_length;
+    pointerToParam->data = att_data;
+
+    AttributeModified_CB(pointerToParam);
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* This function is called when a local attribute gets modified */
+void AttributeModified_CB(const GattWriteCallbackParams* param){
+//    printf("\r\nAttributeModified_CB (%d)\n", perDevs.status);//DEBUG
+
+
+    /* Assign prototype vars */
+    uint16_t handle     = param->handle;
+    //uint8_t data_length = param->len; //not used
+    uint8_t *att_data   = (uint8_t *)param->data;
+
+
+    uint8_t  i;
+    uint16_t conn_handle;
+    uint16_t attr_handle;
+    uint8_t  value_len;
+    uint8_t  attr_value[6];
+    char* mems;
+
+    if (handle == slaveDev.star_config_char_handle + 1) {
+
+        perDevs.status = ALL_DATA_READ;
+        if (att_data[0]==0x01) {
+            /* Disabling all previously enabled notifications */
+            disableAllNotifications();
+        }//if
+        setNewNodesScanning(att_data[0]);
+
+
+    } else if (handle == slaveDev.star_config_char_handle + 2) {
+        if (att_data[0]==0x01) {
+            //printf("\r\nEnable scanning notification\n");
+            STORE_LE_16(slaveDev.star_config_value,(HAL_GetTick()>>3)); /* Timestamp */
+            slaveDev.star_config_value[2] = perDevs.discovery_enabled;
+            slaveDev.star_config_value_len = 3;
+
+            /* send the status of the scanning when notifications are enabled */
+            notifyMaster(slaveDev.star_config_value_len, slaveDev.star_config_value,
+                         slaveDev.star_config_char_handle);
+
+            /* enable here the data notifications since sometimes the relative command gets lost (FIXME) */
+            //printf("\r\nEnable data notification (0)\n");
+            slaveDev.star_data_char_notify = 1;
+
+        } else if (att_data[0]==0x00) {
+            //printf("\r\nDisable scanning notification\n");
+        }
+
+    } else if (handle == slaveDev.star_data_char_handle + 2) {
+        if (att_data[0]==0x01) {
+            //printf("\r\nEnable data notification (1)\n");
+            slaveDev.star_data_char_notify = 1;
+
+
+        } else if (att_data[0]==0x00) {
+            //printf("\r\nDisable data notification\n");
+            slaveDev.star_data_char_notify = 0;
+
+        }
+
+    } else if (handle == slaveDev.star_data_char_handle + 1) {
+
+    /*
+     * Forward the command to the proper peripheral node.
+     * It can be:
+     * - the ON/OFF of a LED
+     * - the notification enabling/disabling for a MIC Level or a Proximity Sensor
+     * The coming data are received according to the following format:
+     * |Node ID | Type ID | value   |
+     * |2 bytes | 1 byte  | x bytes |
+     */
+        
+        i = Get_Device_Index_From_Addr(att_data);
+        if ((i < MAX_NUM_OF_NODES) && (!perDevs.is_disconnected[i]) && (perDevs.cfg_char_handle[i] != 0)) {
+            conn_handle = perDevs.connection_handle[i];
+
+            switch (att_data[2]) {
+
+
+            //LED_TYPE_ID
+            case LED_TYPE_ID:
+                attr_handle = perDevs.cfg_char_handle[i] + 1;
+                value_len   = 5; /* 4 bytes for the feature mask + 1 byte for the command (0=ON, 1=OFF) */
+                attr_value[0] = (uint8_t)(((uint32_t)FEATURE_MASK_LED_EVENTS) >> 24);
+                attr_value[1] = (uint8_t)(((uint32_t)FEATURE_MASK_LED_EVENTS) >> 16);
+                attr_value[2] = (uint8_t)(((uint32_t)FEATURE_MASK_LED_EVENTS) >> 8);
+                attr_value[3] = (uint8_t)(((uint32_t)FEATURE_MASK_LED_EVENTS));
+                attr_value[4] = att_data[3];
+
+                writeCharacValueWithoutResp(conn_handle, attr_handle, value_len, attr_value);
+
+                perDevs.readDeviceIdx = i;
+            break;
+
+
+
+            //MICLEVEL_TYPE_ID
+            case MICLEVEL_TYPE_ID:
+            //perDevs.status = CHANGE_NOTIFICATION_STATUS;//47
+            
+                if (readCompleted == 0){
+                    notificationPending = 1;
+                
+                    /* Fill the temp struct */
+                    notifyP->att_data     = att_data;
+                    notifyP->attr_value   = attr_value;
+                    notifyP->conn_handle  = conn_handle;
+                    notifyP->i            = i;
+                    notifyP->feature_mask = FEATURE_MASK_MIC;
+                    notifyP->frequency    = notification_freq;    
+                
+                    /* Then, call the Change_Notification_Status from the readCallback with these params */
+                
+                }else if (readCompleted == 1) {
+                    notificationPending = 0;
+                    Change_Notification_Status(att_data, attr_value, conn_handle, i, FEATURE_MASK_MIC, notification_freq);
+                }
+                perDevs.prx_on[i] = attr_value[0];
+                printf("\r\nMIC notifications [%d] %s (status %d, discovery %d)\n", i, (attr_value[0]==1 ? "ON" : "OFF"), perDevs.status, perDevs.discovery_enabled);    
+            
+#if SCAN_AFTER_NOTIFICATION
+                /* Restart peripheral discovery and notification*/
+                if (attr_value[0]!=1){
+                    perDevs.discovery_enabled = 1;
+                    setNewNodesScanning(0x01);
+                    //HAL_Delay(300);
+                }
+#endif
+            break;
+
+
+
+
+
+            //PRX_TYPE_ID
+            case PRX_TYPE_ID:
+                //perDevs.status = CHANGE_NOTIFICATION_STATUS;//47
+            
+                if (readCompleted == 0){
+                    notificationPending = 1;    
+                
+                    /* Fill the temp struct */
+                    notifyP->att_data     = att_data;
+                    notifyP->attr_value   = attr_value;
+                    notifyP->conn_handle  = conn_handle;
+                    notifyP->i            = i;
+                    notifyP->feature_mask = FEATURE_MASK_PROX;
+                    notifyP->frequency    = SENDING_INTERVAL_100MS_MULTIPLE;
+                
+                    /* Then, call the Change_Notification_Status from the readCallback with these params */
+                
+                }else if (readCompleted == 1) {
+                    notificationPending = 0;
+                    Change_Notification_Status(att_data, attr_value, conn_handle, i, FEATURE_MASK_PROX, SENDING_INTERVAL_100MS_MULTIPLE);
+                }    
+                    perDevs.prx_on[i] = attr_value[0];
+                    printf("\r\nPRX notifications [%d] %s (status %d)\n", i, (attr_value[0]==1 ? "ON" : "OFF"), perDevs.status);
+
+#if SCAN_AFTER_NOTIFICATION
+                /* Restart peripheral discovery and notification*/
+                if (attr_value[0]!=1){
+                    perDevs.discovery_enabled = 1;
+                    setNewNodesScanning(0x01);
+                    //HAL_Delay(300);
+                }
+#endif
+            break;
+
+
+
+            //ACC_TYPE_ID
+            //GYR_TYPE_ID
+            //MAG_TYPE_ID
+            case ACC_TYPE_ID:
+            case GYR_TYPE_ID:
+            case MAG_TYPE_ID:
+                //perDevs.status = CHANGE_NOTIFICATION_STATUS;//47
+                
+                if (readCompleted == 0){
+                    notificationPending = 1;        
+                
+                    /* Fill the temp struct */
+                    notifyP->att_data     = att_data;
+                    notifyP->attr_value   = attr_value;
+                    notifyP->conn_handle  = conn_handle;
+                    notifyP->i            = i;
+                    notifyP->feature_mask = FEATURE_MASK_ACC;
+                    notifyP->frequency    = SENDING_INTERVAL_100MS_MULTIPLE;
+                
+                
+                    /* Then, call the Change_Notification_Status from the readCallback with these params */
+                
+                }else if (readCompleted == 1) {
+                    notificationPending = 0;
+                    Change_Notification_Status(att_data, attr_value, conn_handle, i, FEATURE_MASK_ACC, SENDING_INTERVAL_100MS_MULTIPLE);
+                }
+                perDevs.agm_on[i] = attr_value[0];
+
+                if (att_data[2] == 0x09) {
+                    perDevs.acc_event_enabled = attr_value[0];
+                    mems = "ACC";
+
+                } else if (att_data[2] == 0x0A) {
+                    perDevs.gyr_event_enabled = attr_value[0];
+                    mems = "GYR";
+
+                } else if (att_data[2] == 0x0B) {
+                    perDevs.mag_event_enabled = attr_value[0];
+                    mems = "MAG";
+                }
+
+                printf("\r\nAGM notifications [%d] %s (%s) (status %d)\n", i, (attr_value[0]==1 ? "ON" : "OFF"), mems, perDevs.status);
+#if SCAN_AFTER_NOTIFICATION
+                /* Restart peripheral discovery and notification*/
+                if (attr_value[0]!=1){
+                    perDevs.discovery_enabled = 1;
+                    setNewNodesScanning(0x01);
+                    //HAL_Delay(300);
+                }
+#endif
+            break;
+
+
+
+            //SFUSION_TYPE_ID
+            case SFUSION_TYPE_ID:
+                //perDevs.status = CHANGE_NOTIFICATION_STATUS;//47
+                
+                    if (readCompleted == 0){
+                        notificationPending = 1;        
+                
+                        /* Fill the temp struct */
+                        notifyP->att_data     = att_data;
+                        notifyP->attr_value   = attr_value;
+                        notifyP->conn_handle  = conn_handle;
+                        notifyP->i            = i;
+                        notifyP->feature_mask = FEATURE_MASK_SENSORFUSION;
+                        notifyP->frequency    = SENDING_INTERVAL_100MS_MULTIPLE;
+            
+                        /* Then, call the Change_Notification_Status from the readCallback with these params */
+            
+                    }else if (readCompleted == 1) {
+                        notificationPending = 0;
+                        Change_Notification_Status(att_data, attr_value, conn_handle, i, FEATURE_MASK_SENSORFUSION, SENDING_INTERVAL_100MS_MULTIPLE);
+                    }
+                
+                    perDevs.sfusion_on[i] = attr_value[0];
+                    printf("\r\nSFUSION notifications [%d] %s (status %d)\n", i, (attr_value[0]==1 ? "ON" : "OFF"), perDevs.status);
+
+#if SCAN_AFTER_NOTIFICATION
+                /* Restart peripheral discovery and notification*/
+                if (attr_value[0]!=1){
+                    perDevs.discovery_enabled = 1;
+                    setNewNodesScanning(0x01);
+                    //HAL_Delay(300);
+
+                }
+#endif
+            break;
+            }
+        }//if
+    }//if-main
+
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Retrieve the device index from the peripheral device address */
+uint8_t Get_Device_Index_From_Addr(uint8_t *addr){
+
+    uint8_t i;
+
+    for (i=0; i<MAX_NUM_OF_NODES; i++) {
+
+        if ((perDevs.devInfo[i].bdaddr[NODE_ID_B2] == addr[0]) && (perDevs.devInfo[i].bdaddr[NODE_ID_B1] == addr[1])) {
+            return i;
+        }
+    }
+    return MAX_NUM_OF_NODES;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/**
+ * @brief  This function is called to Enable/Disable MIC/PRX/AGM/SFusion notifications
+ * @param  att_data : pointer to the modified attribute data
+ * @param  connection handle
+ * @param  peripheral device index
+ * @param  feature mask
+ * @param  notification frequency
+ * @retval None
+ */
+ void Change_Notification_Status(uint8_t *att_data, uint8_t  *attr_value, uint16_t conn_handle, uint8_t i,
+                                 uint32_t feature_mask, uint8_t frequency) {
+    printf("\r\nChange_Notification_Status (status: %d) (read: %s) (write: %s)\n", perDevs.status, (readCompleted == 1 ? "completed" : "pending"),(writeDescriptorCompleted == 1 ? "completed" : "pending"));//DEBUG
+
+
+
+        uint8_t  value_len;
+        uint16_t attr_handle;
+
+
+        if (att_data[3] == 1) {
+
+            /* Setting notification frequency (wait of 2s for writing op)*/
+            setNotificationProperty(conn_handle, i, feature_mask, NOTIFICATION_FREQ_CMD, frequency);
+
+            /* Stopping the scanning for new peripheral nodes */
+            if (perDevs.discovery_enabled) {
+                //Disable scanning when notification is enabled
+                setNewNodesScanning(0x02);
+            }
+
+            /* Disabling all previously enabled notifications */
+            disableAllNotifications();
+
+        }//if
+
+
+
+
+        /* Enabling/Disabling notifications */
+        value_len = 2;
+        attr_value[0] = att_data[3];
+
+        if (feature_mask==FEATURE_MASK_MIC){
+            attr_handle = perDevs.mic_char_handle[i] + 2;
+            perDevs.mic_event_enabled = attr_value[0];
+
+        } else if (feature_mask==FEATURE_MASK_PROX){
+            attr_handle = perDevs.prx_char_handle[i] + 2;
+            perDevs.prx_event_enabled = attr_value[0];
+
+        } else if (feature_mask==FEATURE_MASK_ACC){
+            attr_handle = perDevs.agm_char_handle[i] + 2;
+            perDevs.agm_event_enabled = attr_value[0];
+
+        } else if (feature_mask==FEATURE_MASK_SENSORFUSION){
+            attr_handle = perDevs.sfusion_char_handle[i] + 2;
+            perDevs.sfusion_event_enabled = attr_value[0];
+        }
+
+        
+//        if ((discoveryCompleted == 1)){
+        
+            ble_error_t err;
+            
+            writeDescriptorCompleted=0;
+            err = writeCharacDescriptorWithError(conn_handle, attr_handle, value_len, attr_value);
+
+            if (err != BLE_ERROR_NONE){
+                writeDescriptorCompleted=1;
+                printf("\r\nERROR Enabling/Disabling Notification (err: %d) (stat: %d)\n", err, perDevs.status);
+//                HAL_Delay(500);
+//                //retrying
+//                err = writeCharacDescriptorWithError(conn_handle, attr_handle, value_len, attr_value);
+//                if (err != BLE_ERROR_NONE){
+//                    writeDescriptorCompleted=1;
+//                    printf("\r\nERROR Enabling/Disabling Notification (err: %d) (stat: %d)\n", err, perDevs.status);
+//                }
+            }
+
+//
+//        
+//        // discovery not completed 
+//        }else {
+//            ble_error_t err;
+//        
+//            //waiting for scan stopping
+//            HAL_Delay(3000);
+//            writeDescriptorCompleted=0;
+//
+//            //Send the enable/disable
+//            err = writeCharacDescriptorWithError(conn_handle, attr_handle, value_len, attr_value);
+//
+//            if (err != BLE_ERROR_NONE){
+//                //printf("\r\nWrite charac descriptor failed! (%d)\n", err);
+//                HAL_Delay(500);
+//                //retrying
+//                err = writeCharacDescriptorWithError(conn_handle, attr_handle, value_len, attr_value);
+//                if (err != BLE_ERROR_NONE){
+//                    writeDescriptorCompleted=1;
+//                    printf("\r\nERROR Enabling/Disabling Notification (%d)\n", err);
+//                }
+//            }
+//        }//if-else-discovery-completed
+        
+
+
+
+    
+    /* WUP notification enable/disable */
+//    if(attr_value[0]==0x00){
+//        for (uint8_t j=0; j<(perDevs.connDevices+perDevs.discDevices); j++) {
+//            if (!perDevs.wup_event[j] && perDevs.devInfo[j].dev_v == NODE_ME1 && perDevs.is_connected[j]) {
+//                attr_handle = perDevs.wup_char_handle[j] + 2;
+//                attr_value[0] = 0x01;
+//    
+//                setNotificationProperty(perDevs.connection_handle[j], j, FEATURE_MASK_WAKEUP_EVENTS, WAKEUP_NOTIFICATION_CMD, 1);
+//
+//                if (discoveryCompleted == 1){
+//                    
+//                    writeDescriptorCompleted=0;
+//                    ble_error_t wupErrOn = writeCharacDescriptorWithError(perDevs.connection_handle[j], attr_handle, value_len, attr_value);
+//
+//                    if (wupErrOn == BLE_ERROR_NONE){
+//                        perDevs.wup_event_enabled = 1;
+//                        perDevs.wup_event[j] = 1;
+//                        printf("\r\nWUP notification on node [%d] ON\n", j);
+//                    
+//                    } else {
+//                        printf("\r\nWrite WUP char descriptor failed! (%d)\n", wupErrOn);
+//
+//                    }//if-else
+//                    writeDescriptorCompleted=1;
+//                                           
+//                }//if-else-discovery-completed
+//            }//if
+//        }//for
+//
+//
+//        if (perDevs.wup_event_enabled == 1)
+//            //printf("\r\nAll WUP notifications turned ON\n");//DEBUG
+//        perDevs.status = ALL_DATA_READ;
+//
+//
+//    } else{
+//        for (uint8_t j=0; j<(perDevs.connDevices+perDevs.discDevices); j++) {
+//            if ((perDevs.wup_event[j]) && (perDevs.devInfo[j].dev_v == NODE_ME1) && (perDevs.is_connected[j])) {
+//                attr_handle = perDevs.wup_char_handle[j] + 2;
+//                attr_value[0] = 0x00;
+//
+//
+//                if (discoveryCompleted == 1){
+//                    
+//                    writeDescriptorCompleted=0;
+//                    ble_error_t wupErrOff = writeCharacDescriptorWithError(perDevs.connection_handle[j], attr_handle, value_len, attr_value);
+//
+//                    if (wupErrOff == BLE_ERROR_NONE){
+//                        perDevs.wup_event_enabled = 0;
+//                        perDevs.wup_event[j] = 0;
+//                        printf("\r\nWUP notification on node [%d] OFF\n", j);
+//
+//                    } else {         
+//                        printf("\r\nWrite WUP char descriptor failed! (%d)\n", wupErrOff);
+//
+//                    }
+//                    writeDescriptorCompleted=1;
+//                    
+//                }//if-discovery-completed
+//            }//if
+//        }//for
+//        
+//        perDevs.status = NOTIFICATIONS_DATA_READ;
+//
+//    }//if-else-wup
+
+        attr_value[0] = att_data[3];
+        perDevs.readDeviceIdx = i;
+
+        notificationPending = 0;
+        
+        //Return to connectionProcess
+        perDevs.status = CONN_INIT;
+    
+    
+    
+
+}
+/*----------------------------------------------------------------------------*/