Lorenzo Invidia / Mbed OS ble-star-mbed

Dependencies:   MQTT target_st_bluenrg

Fork of ble-star-mbed by Lorenzo Invidia

Files at this revision

API Documentation at this revision

Comitter:
lorevee
Date:
Tue Feb 20 11:21:41 2018 +0000
Child:
1:110b5e896bc9
Commit message:
First commit of Ble Star demo

Changed in this revision

inc/BleMasterService.h Show annotated file Show diff for this revision Revisions of this file
inc/BleSlaveService.h Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
module.json Show annotated file Show diff for this revision Revisions of this file
shields/target_st_bluenrg.lib Show annotated file Show diff for this revision Revisions of this file
source/BleMasterService.cpp Show annotated file Show diff for this revision Revisions of this file
source/BleSlaveService.cpp 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/inc/BleMasterService.h	Tue Feb 20 11:21:41 2018 +0000
@@ -0,0 +1,584 @@
+#ifndef __BLEMASTERSERVICE_H__
+#define __BLEMASTERSERVICE_H__
+
+#include <events/mbed_events.h>
+#include <mbed.h>
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "ble/DiscoveredCharacteristic.h"
+#include "ble/DiscoveredService.h"
+#include <UUID.h>
+#include <BleSlaveService.h>
+
+
+
+/* Max number of connectable nodes */
+#define MAX_NUM_OF_NODES        7
+
+/* brief Data type length */
+#define ONE_BYTE_LEN         1
+#define TWO_BYTES_LEN        2
+
+#define ENV_DATA_LEN_SHORT  8
+#define ENV_DATA_LEN_LONG  12
+#define PRESS_DATA_LEN      4
+#define HUM_DATA_LEN        2
+#define TEMP_DATA_LEN       2
+#define LED_DATA_LEN        ONE_BYTE_LEN
+#define MIC_DATA_LEN        ONE_BYTE_LEN
+#define LUX_DATA_LEN        TWO_BYTES_LEN
+#define PRX_DATA_LEN        TWO_BYTES_LEN
+#define ACC_DATA_LEN        6
+#define GYR_DATA_LEN        6
+#define MAG_DATA_LEN        6
+#define SFUSION_DATA_LEN    6
+#define X_DATA_LEN          2
+#define Y_DATA_LEN          2
+#define Z_DATA_LEN          2
+#define WUP_DATA_LEN        0
+#define STATUS_DATA_LEN     0
+
+#define TSTAMP_LEN          2
+#define NODE_ID_LEN         2
+#define TYPE_ID_LEN         1
+
+#define ATTR_HEAD_LEN       TSTAMP_LEN+NODE_ID_LEN+TYPE_ID_LEN
+#define ENV_DATA_LEN        PRESS_DATA_LEN+HUM_DATA_LEN+TEMP_DATA_LEN+TEMP_DATA_LEN
+#define MEMS_DATA_LEN       ACC_DATA_LEN+GYR_DATA_LEN+MAG_DATA_LEN
+
+#define INT_VALUE           1
+#define FLOAT_VALUE         2
+
+
+/* Supported peripheral nodes ID */
+#define NODE_ME1                0x01 /* MOTENV1 */
+#define NODE_FL1                0x02 /* FLIGHT1 */
+#define NODE_AM1                0x03 /* ALLMEMS1 */
+
+#define BDADDR_SIZE             6
+#define NODE_ID_B1              0 /* byte of the node BLE address used as 1st byte of the node ID */
+#define NODE_ID_B2              1 /* byte of the node BLE address used as 2nd byte of the node ID */
+#define NODE_ID_OFFSET          NODE_ID_B1
+
+#define ME1_WUP_EVENT_ENABLED   1             /* To enable/disable Wake Up events from MOTENV1 nodes                                    */
+#define AM1_WUP_EVENT_ENABLED   0             /* To enable/disable Wake Up events from ALLMEMS1 nodes                                   */
+                                              /* It is present, without the need of any additional board, on the X-NUCLEO-IKS01A2.      */
+#define MIC_PRESENT             (0x20 | 0x04) /* MIC on the X-NUCLEO-CCA02M1 (in this case the fw running on the node is the ALLMEMS1). */
+#define PLUX_PRESENT            (0x03)        /* Proximity and Lux sensor on X-NUCLEO-6180XA1 (in this case the fw running on the node  */
+                                              /* is the FLIGHT1).                                                                       */
+
+#define BDADDR_SIZE             6
+#define NODE_ID_B1              0 /* byte of the node BLE address used as 1st byte of the node ID */
+#define NODE_ID_B2              1 /* byte of the node BLE address used as 2nd byte of the node ID */
+#define NODE_ID_OFFSET          NODE_ID_B1
+
+#define BUF_LEN 27
+
+#define ENABLE  1
+#define DISABLE 0
+
+#define MANUF_SPECIFIC_TYPE     0xFF
+#define STM32_NUCLEO            0x80
+#define SENSOR_TILE             0x02
+#define BLUE_COIN               0x03
+#define WUP_POS                 0x0A
+#define MIC_POS                 0x1A
+#define PRX_POS                 0x19
+#define ACC_POS                 0x17
+#define SFUS_POS                0x07
+
+/* Feature mask for Temperature1 */
+#define FEATURE_MASK_TEMP1 0x00040000
+/* Feature mask for Temperature2 */
+#define FEATURE_MASK_TEMP2 0x00010000
+/* Feature mask for Pressure */
+#define FEATURE_MASK_PRESS 0x00100000
+/* Feature mask for Humidity */
+#define FEATURE_MASK_HUM   0x00080000
+/* Feature mask for Accelerometer */
+#define FEATURE_MASK_ACC   0x00800000
+/* Feature mask for Gyroscope */
+#define FEATURE_MASK_GYR   0x00400000
+/* Feature mask for Magnetometer */
+#define FEATURE_MASK_MAG   0x00200000
+/* Feature mask for Sensor fusion */
+#define FEATURE_MASK_SENSORFUSION 0x00000100
+/* Feature mask for LED */
+#define FEATURE_MASK_LED_EVENTS    0x20000000
+/* Feature mask for WakeUp EVENT (here used as Motion Detector) */
+#define FEATURE_MASK_WAKEUP_EVENTS 0x00000400
+/* Feature mask for PROXIMITY EVENT  */
+#define FEATURE_MASK_PROX          0x02000000
+/* Feature mask for MICROPHONE */
+#define FEATURE_MASK_MIC           0x04000000
+/* Command to set the WakeUp notification (here used as Motion Detector) */
+#define WAKEUP_NOTIFICATION_CMD    'w'
+/* Command to set the notification frequency */
+#define NOTIFICATION_FREQ_CMD      255
+/* Notification frequency @50mS (default) */
+#define NOTIFICATION_FREQ_50     0
+/* Notification frequency @100mS */
+#define NOTIFICATION_FREQ_100    1
+/* Notification frequency @1S */
+#define NOTIFICATION_FREQ_1000   10
+/* Notification frequency @5S */
+#define NOTIFICATION_FREQ_5000   50
+/* Set the notification frequency to 100ms multiple */
+#define SENDING_INTERVAL_100MS_MULTIPLE 10
+/* Notification frequency when wifi is enabled */
+#define NOTIFICATION_FREQ_WIFI_ON    NOTIFICATION_FREQ_1000 /* reduced to 1000 from NOTIFICATION_FREQ_5000 */
+/* Notification frequency when wifi is disabled */
+#define NOTIFICATION_FREQ_WIFI_OFF   NOTIFICATION_FREQ_1000
+/* 1 to enable mems noifications */
+#define ENABLE_MEMS 0
+/* 1 to enable the scanning after disabling a notification */
+#define SCAN_AFTER_NOTIFICATION 1
+
+extern EventQueue   eventQ;
+
+
+
+/* This var defines the central role
+ * 0 if master
+ * 1 if slave                     */
+extern uint8_t role;
+
+/* Pointer to var (uint8_t role)  */
+//uint8_t * pRole;
+
+
+
+/* Flag to indicate that the characteristic read is completed successful
+ * 1                        successful
+ * 0 or anything else       failed                                      */
+extern uint8_t readCompleted;
+
+
+
+/* Flag to indicate if the device discovery is completed successful
+ * 1                        successful
+ * 0 or anything else       failed                                      */
+extern uint8_t discoveryCompleted;
+
+
+
+/* Flag to indicate if the ch descriptor write is completed successful
+ * 1                        successful
+ * 0 or anything else       failed                                      */
+extern uint8_t writeDescriptorCompleted;
+
+
+
+/* Flag to indicate if the advertising is completed
+ * 1                        completed
+ * 0 or anything else       not completed                               */
+extern uint8_t advEnds;
+
+
+/* Flag to indicate if a change of notification is pending
+ * 1                        pending
+ * 0 or anything else       not pending                                 */
+extern uint8_t notificationPending;
+
+
+
+
+/* Supported peripheral nodes name */
+const char NODE_MOTENV[] =      "ME1V310";
+const char NODE_FLIGHT[] =      "FL1V310";
+const char NODE_ALLMEMS[] =     "AM1V320";
+
+
+/* Properties mask */
+static uint8_t props_mask[] = {
+  0x01,
+  0x02,
+  0x04,
+  0x08,
+  0x10,
+  0x20,
+  0x40,
+  0x80
+};
+
+
+/* Enum of different states */
+typedef enum {
+  CONN_INIT,                                   // 0
+  START_DEVICE_DISCOVERY,                      // 1
+  DEVICE_FOUND,                                // 2
+  DEVICE_NOT_FOUND,                            // 3
+  DEVICE_DISCOVERY_COMPLETE,                   // 4
+  START_DEVICE_CONNECTION,                     // 5
+  DEVICE_CONNECTED,                            // 6
+  DEVICE_CONNECTION_COMPLETE,                  // 7
+  START_DISCOVERABLE_MODE,                     // 8
+  DISCOVERABLE_MODE_SET,                       // 9
+  START_SERVICE_DISCOVERY,                     //10
+  SERVICE_DISCOVERED,                          //11
+  SERVICE_DISCOVERY_COMPLETE,                  //12
+  START_HARDWARE_SERV_CHARS_DISCOVERY,         //13
+  HARDWARE_SERV_CHARS_DISCOVERED,              //14
+  HARDWARE_SERV_CHARS_DISCOVERY_COMPLETE,      //15
+  START_SOFTWARE_SERV_CHARS_DISCOVERY,         //16
+  SOFTWARE_SERV_CHARS_DISCOVERED,              //17
+  SOFTWARE_SERV_CHARS_DISCOVERY_COMPLETE,      //18
+  START_CONFIGURATION_SERV_CHARS_DISCOVERY,    //19
+  CONFIGURATION_SERV_CHARS_DISCOVERED,         //20
+  CONFIGURATION_SERV_CHARS_DISCOVERY_COMPLETE, //21
+  ENABLE_ME1_LED_NOTIFICATIONS,                //22
+  ENABLE_ME1_WUP_NOTIFICATIONS,                //23
+  NOTIFICATIONS_ENABLED,                       //24
+  READ_INIT,                                   //25
+  READING_PRX,                                 //26
+  NOTIFY_PRX_TO_CLIENT,                        //27
+  READING_ENVIRONMENTAL,                       //28
+  NOTIFY_ENV_TO_CLIENT,                        //29
+  READING_LED,                                 //30
+  NOTIFY_LED_TO_CLIENT,                        //31
+  READING_LUX,                                 //32
+  NOTIFY_LUX_TO_CLIENT,                        //33
+  READING_MIC,                                 //34
+  NOTIFY_MIC_TO_CLIENT,                        //35
+  READING_AGM,                                 //36
+  NOTIFY_AGM_TO_CLIENT,                        //37
+  READING_SFUSION,                             //38
+  NOTIFY_SFUSION_TO_CLIENT,                    //39
+  READING_PRESSURE,                            //40
+  READING_HUMIDITY,                            //41
+  READING_TEMPERATURE,                         //42
+  ALL_DATA_READ,                               //43
+  NOTIFICATIONS_DATA_READ,                     //44
+  DISABLE_NOTIFICATIONS,                       //45
+  READING_DISCONNECTION,                       //46
+  CHANGE_NOTIFICATION_STATUS                   //47
+} Status_t;
+
+
+/* (Service) Handle struct */
+typedef struct {
+  uint16_t start_h;
+  uint16_t end_h;
+} Handle_t;
+
+typedef DiscoveredCharacteristic::Properties_t Properties_t;
+
+typedef BLEProtocol::AddressBytes_t tBDAddr;
+
+/* Peripheral device info struct */
+typedef struct {
+  uint8_t  dev_v;           // per device ID
+  tBDAddr  bdaddr;          // per device addr
+} devInfo_t;
+
+
+/* Struct contains the peripheral devices informations  */
+typedef struct {
+  devInfo_t                 devInfo[MAX_NUM_OF_NODES];
+  uint8_t                   discovery_enabled;
+  bool                      device_found;
+  uint8_t                   connDevices;
+  uint8_t                   discDevices;
+  uint8_t                   connDeviceIdx;
+  uint8_t                   readDeviceIdx;
+  uint16_t                  connection_handle[MAX_NUM_OF_NODES];
+  bool                      is_connected[MAX_NUM_OF_NODES];
+  bool                      is_disconnected[MAX_NUM_OF_NODES];
+  bool                      is_unconnectable[MAX_NUM_OF_NODES];
+
+  Handle_t                  gen_access_profile_handle[MAX_NUM_OF_NODES];
+  Handle_t                  gen_attribute_profile_handle[MAX_NUM_OF_NODES];
+  Handle_t                  hardware_service_handle[MAX_NUM_OF_NODES];
+  Handle_t                  configuration_service_handle[MAX_NUM_OF_NODES];
+  Handle_t                  software_service_handle[MAX_NUM_OF_NODES];
+
+  // Characteristic handles
+  uint16_t                  environmental_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  pressure_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  humidity_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  temperature_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  led_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  cfg_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  wup_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  mic_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  prx_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  lux_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  agm_char_handle[MAX_NUM_OF_NODES];
+  uint16_t                  sfusion_char_handle[MAX_NUM_OF_NODES];
+
+  uint8_t                   led_char_read[MAX_NUM_OF_NODES];
+  uint8_t                   wup_char_read[MAX_NUM_OF_NODES];
+  uint8_t                   mic_char_read[MAX_NUM_OF_NODES];
+  uint8_t                   prx_char_read[MAX_NUM_OF_NODES];
+  uint8_t                   agm_char_read[MAX_NUM_OF_NODES];
+  uint8_t                   sfusion_char_read[MAX_NUM_OF_NODES];
+  uint8_t                   wup_event[MAX_NUM_OF_NODES];
+  uint8_t                   mic_event[MAX_NUM_OF_NODES];
+  uint8_t                   prx_event[MAX_NUM_OF_NODES];
+  uint8_t                   agm_event[MAX_NUM_OF_NODES];
+  uint8_t                   sfusion_event[MAX_NUM_OF_NODES];
+  uint8_t                   prx_on[MAX_NUM_OF_NODES];
+  uint8_t                   agm_on[MAX_NUM_OF_NODES];
+  uint8_t                   sfusion_on[MAX_NUM_OF_NODES];
+  uint8_t                   mic_event_enabled;
+  uint8_t                   prx_event_enabled;
+  uint8_t                   agm_event_enabled;
+  uint8_t                   sfusion_event_enabled;
+  uint8_t                   wup_event_enabled;
+  uint8_t                   acc_event_enabled;
+  uint8_t                   gyr_event_enabled;
+  uint8_t                   mag_event_enabled;
+  Status_t                  status;
+
+} PeripheralDevices_t;
+
+
+
+
+/* List of type id */
+typedef enum {
+  UNKNOWN_TYPE_ID,  //0
+  PRESS_TYPE_ID,    //1   (its data value is 4 bytes long)
+  HUM_TYPE_ID,      //2   (its data value is 2 bytes long)
+  TEMP_TYPE_ID,     //3   (its data value is 2 bytes long)
+  LED_TYPE_ID,      //4   (its data value is 1 byte long)
+  PRX_TYPE_ID,      //5   (its data value is 2 bytes long)
+  WUP_TYPE_ID,      //6   (no data value)
+  MICLEVEL_TYPE_ID, //7   (its data value is 1 byte long)
+  LUX_TYPE_ID,      //8   (its data value is 2 bytes long)
+  ACC_TYPE_ID,      //9   (its data value is 6 bytes long)
+  GYR_TYPE_ID,      //10  (its data value is 6 bytes long)
+  MAG_TYPE_ID,      //11  (its data value is 6 bytes long)
+  STATUS_TYPE_ID,   //12  (no data value)
+  SFUSION_TYPE_ID   //13  (its data value is 8 bytes long)
+                    //  (increase the enum to add new data type IDs)
+} Data_Type_ID_t;
+
+
+
+/* Struct of the generic DiscoveredCharacteristic node */
+struct DiscoveredCharacteristicNode{
+    //data
+    DiscoveredCharacteristic data;
+    //pointer to next node
+    DiscoveredCharacteristicNode * next;
+};
+
+
+/* Header pointer of the DiscoveredCharacteristic list */
+extern DiscoveredCharacteristicNode * headCharacteristic[MAX_NUM_OF_NODES];
+extern DiscoveredCharacteristicNode * tmp[MAX_NUM_OF_NODES];
+
+
+/* Primary Service UUID expected from Sensor demo peripherals */
+extern UUID::ShortUUIDBytes_t GENERIC_ACCESS_PROFILE_UUID;
+extern UUID::ShortUUIDBytes_t GENERIC_ATTRIBUTE_PROFILE_UUID;
+
+
+
+
+/* Services UUID */        //  1b:c5:d5:a5:02:00:b4:9a:e1:11:XX:XX:XX:XX:XX:XX
+extern UUID::LongUUIDBytes_t HARDWARE_SERVICE_UUID;
+
+extern UUID::LongUUIDBytes_t CONFIG_SERVICE_UUID;
+
+extern UUID::LongUUIDBytes_t SOFTWARE_SERVICE_UUID;
+
+
+
+
+/* Characteristics UUID */
+/* ENVIRONMENTAL */
+extern UUID::LongUUIDBytes_t ENVIRONMENTAL_CHAR_UUID;
+
+/* ENVIRONMENTAL for Sensor Tile */
+extern UUID::LongUUIDBytes_t ENVIRONMENTAL_ST_CHAR_UUID;
+
+/* ACC + GYRO + MAG */
+extern UUID::LongUUIDBytes_t ACCGYROMAG_CHAR_UUID;
+
+/* MEMS SENSOR FUSION */
+extern UUID::LongUUIDBytes_t SFUSION_CHAR_UUID;
+
+/* LED */
+extern UUID::LongUUIDBytes_t LED_CHAR_UUID;
+
+/* WAKEUP */
+extern UUID::LongUUIDBytes_t WAKEUP_EVENT_CHAR_UUID;
+
+/* MICROPHONE */
+extern UUID::LongUUIDBytes_t MIC_EVENT_CHAR_UUID;
+
+/* PROXIMITY */
+extern UUID::LongUUIDBytes_t PROXIMITY_CHAR_UUID;
+
+/* LUX */
+extern UUID::LongUUIDBytes_t LUX_CHAR_UUID;
+
+/* CONFIGURATION */
+extern UUID::LongUUIDBytes_t CONFIG_CHAR_UUID;
+
+
+/*-----  -----*/
+extern uint8_t wifi_data[256];
+extern uint8_t new_data;
+extern uint8_t *data;
+extern uint8_t wifi_present;
+
+extern char print_msg_buff[512];
+//extern UART_HandleTypeDef UartMsgHandle;
+
+//extern uint16_t connection_handle = 0;
+
+extern uint8_t attribute_value[20];
+extern uint8_t star_attr_value[256];
+//extern uint8_t bnrg_expansion_board_type = IDB04A1; /* at startup, suppose the X-NUCLEO-IDB04A1 is used */
+extern uint8_t notification_freq;
+
+
+/*---- Main functions declaration ----*/
+/* Complete the initialization of ble module */
+void bleInitComplete                        (BLE::InitializationCompleteCallbackContext *params);
+
+/* scheduleBleEventsProcessing */
+void scheduleBleEventsProcessing            (BLE::OnEventsToProcessCallbackContext* context);
+
+/* Initialization error handling */
+void onBleInitError                         (BLE &ble, ble_error_t error);
+
+void checkStatus                                (void);
+
+
+/*---- Master service functions declarations ----*/
+/* Scan for new peripheral nodes and establish new connections */
+void connectionProcess                          (void);
+
+/* Read data from peripheral nodes */
+void readingProcess                             (void);
+
+/* Create a null gatt read pointer */
+GattReadCallbackParams * nullGattReadCallbackP  (uint16_t connection_handle);
+
+
+/* Print the central mac addr */
+void printMacAddress                            (void);
+
+/* Complete the initialization of ble module */
+void bleInitComplete                            (BLE::InitializationCompleteCallbackContext *params);
+
+/* Callback functions */
+void disconnectionCallback                      (const Gap::DisconnectionCallbackParams_t *);
+
+void connectionCallback                         (const Gap::ConnectionCallbackParams_t *params);
+
+void advertisementCallback                      (const Gap::AdvertisementCallbackParams_t *params);
+
+void onStopScan                                 (Gap::TimeoutSource_t t);
+
+void serviceDiscoveryCallback                   (const DiscoveredService *service);
+
+void characteristicDiscoveryCallback            (const DiscoveredCharacteristic *characteristicP);
+
+void discoveryTerminationCallback               (Gap::Handle_t connectionHandle);
+
+/* Method called after the reading of a characteristic */
+void readCharacteristicCallback                 (const GattReadCallbackParams *response);
+
+/* Method called after a periph descriptor is written */
+void perDescriptorWrittenCallback               (const GattWriteCallbackParams* event);
+
+
+
+/* Save the found peripheral device in the struct containing all the
+   found peripheral devices. */
+void saveDeviceFound                            (uint8_t adv_type, BLEProtocol::AddressBytes_t addr,
+                                                 uint8_t data_length, const uint8_t* data_RSSI, uint8_t pos, uint8_t dev_v,
+                                                 uint8_t wup_event, uint8_t mic_event, uint8_t prx_event,
+                                                 uint8_t agm_event, uint8_t sfusion_event);
+
+/* Connect the device as Master to a peripheral device */
+void connectPeripheral                          (void);
+
+/* Service discovery */
+void discoverServices                           (void);
+
+/* Initialize the struct where all peripheral devices are stored */
+void initProcess                                (void);
+
+/* Start the discovery of new peripheral nodes */
+void startDiscovery                             (void);
+
+/* This function retrieves the peripheral device index from the connection handle */
+void getDeviceFromConnHandle                    (uint16_t handle, uint8_t *index, tBDAddr devAddr);
+
+/* This method reads the characteristic in input */
+void readSensorData                             (const DiscoveredCharacteristic &characteristic,
+                                                 uint16_t connection_handle, uint8_t index);
+
+/* Set the new status */
+void setNewStatus                               (void);
+
+/* Method that enables characteristic notifications */
+void enableNotifications                        (uint16_t conn_handle, uint8_t index, uint8_t dev_v, uint8_t set_mode);
+
+/* Write a characteristic descriptor */
+void writeCharacDescriptor                      (uint16_t conn_handle, uint16_t attr_handle, uint8_t attr_len,
+                                                 uint8_t* attr_value);
+
+/* Get error */
+ble_error_t writeCharacDescriptorWithError      (uint16_t conn_handle, uint16_t attr_handle, uint8_t attr_len,
+                                                 uint8_t* attr_value);
+
+/* Write a characteristic value without waiting for any response */
+void writeCharacValueWithoutResp                (uint16_t conn_handle, uint16_t attr_handle, uint8_t attr_len,
+                                                 uint8_t* attr_value);
+
+/* Get error */
+ble_error_t writeCharacValueWithoutRespWithError       (uint16_t conn_handle, uint16_t attr_handle, uint8_t attr_len,
+                                                        uint8_t* attr_value);
+
+/* Builds a Jason format string */
+void Build_MEMS_Packet                          (uint8_t *attr_value, char *data_type, tBDAddr devAddr, uint8_t num_type);
+
+
+/* Create new attr value for the master */
+void Create_New_Attr_Value                      (uint8_t *tstamp, tBDAddr  devAddr, uint8_t data_type_id, uint8_t *data, uint8_t data_length);
+
+/* Method called when there is a notification from the sever */
+void onNotificationCallback                     (const GattHVXCallbackParams* event);
+
+
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* DiscoveredCharacteristic List methods */
+
+/* Creating a new DiscoveredCharacteristicNode (struct r308)*/
+DiscoveredCharacteristicNode * createDCNode     (const DiscoveredCharacteristic &ch, DiscoveredCharacteristicNode *next);
+
+/* Prepend a DiscoveredCharacteristicNode (struct r308)*/
+DiscoveredCharacteristicNode * prependDCNode    (DiscoveredCharacteristicNode *head, const DiscoveredCharacteristic *characteristic);
+
+/* Append a DiscoveredCharacteristicNode (struct r308)*/
+DiscoveredCharacteristicNode * appendDCNode     (DiscoveredCharacteristicNode *head, const DiscoveredCharacteristic *characteristic);
+
+/* Number of DiscoveredCharacteristic nodes */
+int countElements                               (DiscoveredCharacteristicNode *head);
+
+/* Search for a DiscoveredCharacteristic node by declaration handle */
+DiscoveredCharacteristicNode * searchDCNode     (DiscoveredCharacteristicNode *head, uint16_t declHandle);
+
+/* Delete the DCN list */
+void deleteDCNList                              (DiscoveredCharacteristicNode *head);
+
+/*----------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+#endif /*__BLEMASTERSERVICE_H__*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/BleSlaveService.h	Tue Feb 20 11:21:41 2018 +0000
@@ -0,0 +1,129 @@
+#ifndef __BLESLAVESERVICE_H__
+#define __BLESLAVESERVICE_H__
+
+#include "ble/GattService.h"
+#include "ble/GattCharacteristic.h"
+#include <BleMasterService.h>
+
+/* Attribute value format of the STAR_CHAR */   
+/* Timestamp | Node ID | Type ID | value   | Type ID | value   | Type ID | value   | */
+/* 2 bytes   | 2 bytes | 1 byte  | x bytes | 1 byte  | x bytes | 1 byte  | x bytes | */
+#define STAR_CHAR_MAX_VALUE_LEN   20
+
+#define uint8_tNAME_BLESTAR1           'B','l','e','S','t','a','r','1'
+
+
+/* Store Value into a buffer in Little Endian Format */
+#define STORE_LE_16(buf, val)    ( ((buf)[0] =  (uint8_t) (val)     ) , \
+                                   ((buf)[1] =  (uint8_t) (val>>8)  ) )
+
+#define STORE_LE_32(buf, val)    ( ((buf)[0] =  (uint8_t) (val)     ) , \
+                                   ((buf)[1] =  (uint8_t) (val>>8)  ) , \
+                                   ((buf)[2] =  (uint8_t) (val>>16) ) , \
+                                   ((buf)[3] =  (uint8_t) (val>>24) ) )
+
+#define STORE_BE_32(buf, val)    ( ((buf)[3] =  (uint8_t) (val)     ) , \
+                                   ((buf)[2] =  (uint8_t) (val>>8)  ) , \
+                                   ((buf)[1] =  (uint8_t) (val>>16) ) , \
+                                   ((buf)[0] =  (uint8_t) (val>>24) ) )   
+                                   
+                                   
+
+
+
+typedef BLEProtocol::AddressBytes_t tBDAddr;
+                                   
+ /* MANUFACTURER_SPECIFIC_DATA */
+extern uint8_t manuf_data[6];
+                                   
+                                   
+                                   
+                                   
+/* BLE Slave Service exported types */
+typedef struct {
+  uint8_t data_length;
+  uint8_t *attribute_value;
+  tBDAddr devAddr;
+  uint16_t attribute_handle;  
+} NotificationData_t;
+   
+typedef struct {
+  uint8_t  is_discoverable;
+  uint8_t  is_connected;  
+  uint16_t conn_handle;
+  uint16_t star_hw_serv_handle;
+  uint16_t star_data_char_handle;
+  uint16_t star_config_char_handle;
+  uint8_t  star_data_char_notify;
+  uint8_t  star_config_value[3];
+  uint8_t  star_config_value_len;
+  NotificationData_t notification_data;
+} SlaveDevice_t;
+
+
+/* This struct owns the Change_Notification_Status() parameters */
+typedef struct {
+    uint8_t     *att_data; 
+    uint8_t     *attr_value; 
+    uint16_t    conn_handle; 
+    uint8_t     i; 
+    uint32_t    feature_mask; 
+    uint8_t     frequency;
+}ChangeNotificationQueue;
+
+
+
+
+/* ---- BLE Slave Service exported functions ---- */
+/* Set the device as a slave in discoverable mode */   
+void setSlaveDiscoverable                   (void);
+
+/* Stop advertising */
+void stopAdv                                (void);
+
+/* Sets some notification properties */
+void setNotificationProperty                (uint16_t conn_handle, uint8_t i, uint32_t feature_mask, 
+                                             uint8_t command, uint8_t data);
+/* Disable all notifications */
+void disableAllNotifications                (void);
+
+/* This function enables or disables the new peripheral scanning */
+void setNewNodesScanning                    (uint8_t enabled);
+
+/* 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);
+
+/* This function is called when an attribute gets modified */
+void AttributeModified_CB                   (const GattWriteCallbackParams* param);
+
+/* Notification callbacks */
+void onUpdatesDisabledCallback              (Gap::Handle_t handle);
+void onUpdatesEnabledCallback               (GattAttribute::Handle_t handle);
+
+/* Retrieve the device index from the peripheral device address */
+uint8_t Get_Device_Index_From_Addr          (uint8_t *addr);
+
+/* This function is called to Enable/Disable MIC/PRX/AGM/SFusion notifications */
+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);
+
+/* Add all services using a vendor specific UUIDs */
+void addAllServices                         (void);
+
+/* Forwards to master all notifications from peripherals */
+//void notifyMaster                       (uint8_t data_length, uint8_t* attribute_value, GattCharacteristic *pCharac);
+void notifyMaster                           (uint8_t data_length, uint8_t* attribute_value, uint16_t attribute_handle);
+
+/* Function used to call Attribute_Modified_CB outside the callback call */
+void createAttribute_Modified_CB_Prototype  (uint16_t handle, uint8_t data_length, uint8_t *att_data);
+
+
+
+
+                             
+
+
+
+
+
+#endif /*__BLESLAVESERVICE_H__*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Tue Feb 20 11:21:41 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#569159b784f70feaa32ce226aaca896fb83452f7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app.json	Tue Feb 20 11:21:41 2018 +0000
@@ -0,0 +1,16 @@
+{
+    "target_overrides": {
+        "K64F": {
+            "target.features_add": ["BLE"],
+            "target.extra_labels_add": ["ST_BLUENRG"]
+        },
+        "NUCLEO_F401RE": {
+            "target.features_add": ["BLE"],
+            "target.extra_labels_add": ["ST_BLUENRG"]
+        },
+        "DISCO_L475VG_IOT01A": {
+            "target.features_add": ["BLE"],
+            "target.extra_labels_add": ["ST_BLUENRG"]
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/module.json	Tue Feb 20 11:21:41 2018 +0000
@@ -0,0 +1,15 @@
+{
+  "name": "ble-star-mbed",
+  "version": "0.0.1",
+  "description": "",
+  "licenses": [
+    {
+      "url": "https://spdx.org/licenses/Apache-2.0",
+      "type": "Apache-2.0"
+    }
+  ],
+  "dependencies": {
+    "ble": "^2.0.0"
+  },
+  "bin": "./source"
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/shields/target_st_bluenrg.lib	Tue Feb 20 11:21:41 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/lorevee/code/target_st_bluenrg/#ac0b0725c6fa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/BleMasterService.cpp	Tue Feb 20 11:21:41 2018 +0000
@@ -0,0 +1,3081 @@
+#include <BleMasterService.h>
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
+#include "../inc/BleMasterService.h"
+#include "../inc/BleSlaveService.h"
+
+EventQueue eventQ(/* event count */ 128 * EVENTS_EVENT_SIZE);
+
+/* This var defines the central role
+ * 0 if master
+ * 1 if slave                     */
+uint8_t role = 1;
+
+
+
+/* Flag to indicate that the characteristic read is completed successful
+ * 1                        successful
+ * 0 or anything else       failed                                      */
+uint8_t readCompleted;
+
+
+
+
+/* Flag to indicate if the device discovery is completed successful
+ * 1                        successful
+ * 0 or anything else       failed                                      */
+uint8_t discoveryCompleted;
+
+
+/* Flag to indicate if the ch descriptor write is completed successful
+ * 1                        successful
+ * 0 or anything else       failed                                      */
+uint8_t writeDescriptorCompleted = 1;
+
+
+/* Flag to indicate if the advertising is completed
+ * 1                        completed
+ * 0 or anything else       not completed                               */
+uint8_t advEnds = 1;
+
+
+/* Flag to indicate if a change of notification is pending
+ * 1                        pending
+ * 0 or anything else       not pending                                 */
+uint8_t notificationPending = 0;
+
+
+/* Header pointer of the DiscoveredCharacteristic list */
+DiscoveredCharacteristicNode * headCharacteristic[MAX_NUM_OF_NODES];
+DiscoveredCharacteristicNode * tmp[MAX_NUM_OF_NODES];
+
+/* Primary Service UUID expected from Sensor demo peripherals */
+UUID::ShortUUIDBytes_t GENERIC_ACCESS_PROFILE_UUID      = 0x1800;
+UUID::ShortUUIDBytes_t GENERIC_ATTRIBUTE_PROFILE_UUID   = 0x1801;
+
+/* Services UUID */
+UUID::LongUUIDBytes_t HARDWARE_SERVICE_UUID             = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0xb4,0x9a,0xe1,0x11,0x01,0x00,0x00,0x00,0x00,0x00};
+UUID::LongUUIDBytes_t CONFIG_SERVICE_UUID               = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0xb4,0x9a,0xe1,0x11,0x0F,0x00,0x00,0x00,0x00,0x00};
+UUID::LongUUIDBytes_t SOFTWARE_SERVICE_UUID             = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0xb4,0x9a,0xe1,0x11,0x02,0x00,0x00,0x00,0x00,0x00};
+
+/* Characteristics UUID */
+UUID::LongUUIDBytes_t ENVIRONMENTAL_CHAR_UUID           = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x00,0x1d,0x00};
+UUID::LongUUIDBytes_t ENVIRONMENTAL_ST_CHAR_UUID        = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x00,0x14,0x00};
+UUID::LongUUIDBytes_t ACCGYROMAG_CHAR_UUID              = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x00,0xE0,0x00};
+UUID::LongUUIDBytes_t SFUSION_CHAR_UUID                 = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x01,0x00,0x00};
+UUID::LongUUIDBytes_t LED_CHAR_UUID                     = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x00,0x00,0x20};
+UUID::LongUUIDBytes_t WAKEUP_EVENT_CHAR_UUID            = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x04,0x00,0x00};
+UUID::LongUUIDBytes_t MIC_EVENT_CHAR_UUID               = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x00,0x00,0x04};
+UUID::LongUUIDBytes_t PROXIMITY_CHAR_UUID               = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x00,0x00,0x02};
+UUID::LongUUIDBytes_t LUX_CHAR_UUID                     = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x00,0x00,0x01};
+UUID::LongUUIDBytes_t CONFIG_CHAR_UUID                  = {0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x0F,0x00,0x02,0x00,0x00,0x00};
+
+/*-----  -----*/
+uint8_t wifi_data[256];
+uint8_t new_data = 0;
+uint8_t *data;
+uint8_t wifi_present;
+
+char print_msg_buff[512];
+//UART_HandleTypeDef UartMsgHandle;
+
+//uint16_t connection_handle = 0;
+
+uint8_t attribute_value[20];
+uint8_t star_attr_value[256];
+
+
+
+PeripheralDevices_t perDevs;
+extern SlaveDevice_t slaveDev;
+extern ChangeNotificationQueue notifyQ, *notifyP;
+
+/* Private variable set in discoveryTerminationCallback and used
+ * in connectionProcess for enabling notification */
+uint8_t customDev_v;
+
+
+
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Initialize the struct where all peripheral devices are stored */
+void initProcess(void) {
+  //printf("\rinitProcess\n");//DEBUG
+
+    //Init the lists of characteristics
+    for(int i=0; i<MAX_NUM_OF_NODES; i++){
+        headCharacteristic[i] = NULL;
+        tmp[i] = NULL;
+    }
+
+
+
+  /* The first char read */
+  readCompleted = 1;
+
+  /* No discovery started */
+  discoveryCompleted = 1;
+
+
+  perDevs.discovery_enabled                                             = true;
+  perDevs.device_found                                                  = false;
+  perDevs.connDevices                                                   = 0;
+  perDevs.discDevices                                                   = 0;
+  perDevs.connDeviceIdx                                                 = 0;
+  perDevs.readDeviceIdx                                                 = 0;
+
+  for(unsigned i=0;i<MAX_NUM_OF_NODES;i++){
+    perDevs.devInfo[i].dev_v                                            = 0;
+    perDevs.connection_handle[i]                                        = 0;
+    perDevs.is_connected[i]                                             = false;
+    perDevs.is_disconnected[i]                                          = true;
+    perDevs.is_unconnectable[i]                                         = false;
+    perDevs.gen_access_profile_handle[i].start_h                        = 0;
+    perDevs.gen_access_profile_handle[i].end_h                          = 0;
+    perDevs.gen_attribute_profile_handle[i].start_h                     = 0;
+    perDevs.gen_attribute_profile_handle[i].end_h                       = 0;
+    perDevs.hardware_service_handle[i].start_h                          = 0;
+    perDevs.hardware_service_handle[i].end_h                            = 0;
+    perDevs.software_service_handle[i].start_h                          = 0;
+    perDevs.software_service_handle[i].end_h                            = 0;
+    perDevs.led_char_read[i]                                            = 0;
+    perDevs.wup_char_read[i]                                            = 0;
+    perDevs.mic_char_read[i]                                            = 0;
+    perDevs.prx_char_read[i]                                            = 0;
+    perDevs.agm_char_read[i]                                            = 0;
+    perDevs.sfusion_char_read[i]                                        = 0;
+    perDevs.wup_event[i]                                                = 0;
+    perDevs.mic_event[i]                                                = 0;
+    perDevs.prx_on[i]                                                   = 0;
+    perDevs.agm_on[i]                                                   = 0;
+    perDevs.sfusion_on[i]                                               = 0;
+  }
+
+  perDevs.mic_event_enabled                                             = 0;
+  perDevs.prx_event_enabled                                             = 0;
+  perDevs.agm_event_enabled                                             = 0;
+  perDevs.sfusion_event_enabled                                         = 0;
+  perDevs.acc_event_enabled                                             = 0;
+  perDevs.gyr_event_enabled                                             = 0;
+  perDevs.mag_event_enabled                                             = 0;
+  perDevs.status                                                        = CONN_INIT;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Called every 10 seconds to return the current status */
+void checkStatus(){
+    if ((perDevs.status != 10) && (perDevs.status != 11) && (perDevs.status != 12) && (perDevs.status != 13) && (perDevs.status != 14)
+        && (perDevs.status != 15) && (perDevs.status != 16) && (perDevs.status != 17) && (perDevs.status != 18)
+        && (perDevs.status != 19) && (perDevs.status != 20) && (perDevs.status != 21)){
+            printf("\r\nCurrent Status (status: %d) (read: %s) (write: %s)\n", perDevs.status, (readCompleted == 1 ? "completed" : "pending"),(writeDescriptorCompleted == 1 ? "completed" : "pending"));
+    }
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Print out device MAC address to the console*/
+void printMacAddress()
+{
+    Gap::AddressType_t addr_type;
+    Gap::Address_t address;
+    BLE::Instance().gap().getAddress(&addr_type, address);
+    printf("\rBLE CENTRAL MAC ADDRESS: ");
+    for (int i = 5; i >= 1; i--){
+        printf("%02x:", address[i]);
+    }
+    printf("%02x\n\n", address[0]);
+}
+/*----------------------------------------------------------------------------*/
+
+
+void connectionProcess(void){
+    //printf("\r\nconnectionProcess(%d)\n", perDevs.status);//DEBUG
+
+
+
+
+    if ( perDevs.status == CONN_INIT ) {
+        if ( (perDevs.connDevices < MAX_NUM_OF_NODES) && (perDevs.discovery_enabled) ) {
+         //printf("\r\nIF 1\n");//DEBUG
+            /* Start discovery of new peripheral nodes and connect them */
+            startDiscovery();
+        }
+        else {
+            perDevs.status = DEVICE_CONNECTED;
+            //printf("\r\nstatus: DEVICE_CONNECTED\n");//DEBUG
+        }
+
+    }//if
+
+
+
+
+
+
+    if ( perDevs.status == DEVICE_DISCOVERY_COMPLETE ) {
+        //printf("\r\nDEVICE_DISCOVERY_COMPLETE\n");//DEBUG
+        if ( perDevs.device_found == true ) {
+            /* Establishing connection with a peripheral device */
+            perDevs.status = START_DEVICE_CONNECTION;
+            //printf("\r\n\nstatus: START_DEVICE_CONNECTION\n");//DEBUG
+            connectPeripheral();
+        }else {
+            perDevs.status = DEVICE_NOT_FOUND;
+            //printf("\r\n\nstatus: DEVICE_NOT_FOUND (%d)\n", DEVICE_NOT_FOUND);//DEBUG
+        }
+    }//if
+
+
+
+
+
+
+    // if all devices are connected or no devices are discovered start reading
+    if ((perDevs.status == DEVICE_CONNECTED) || (perDevs.status == DEVICE_NOT_FOUND) ){
+        //printf("\r\nDEVICE_CONNECTED or DEVICE_NOT_FOUND\n");//DEBUG
+
+
+        if (perDevs.device_found == true) {
+            perDevs.status = DISCOVERABLE_MODE_SET;
+            perDevs.device_found = false;
+        }
+
+        //perDevs.device_found == false -- start reading
+        else {
+            perDevs.readDeviceIdx = perDevs.connDevices+perDevs.discDevices-1;
+            perDevs.status = READ_INIT;
+            //printf("\r\nstatus: READ_INIT (%u)\n", READ_INIT);
+        }
+
+    }//if-main
+
+
+
+
+
+
+    if (perDevs.status == DISCOVERABLE_MODE_SET) {
+        /* Search for all services */
+        perDevs.status = START_SERVICE_DISCOVERY;
+        eventQ.call(discoverServices);
+    }//if
+
+
+
+
+
+
+     if ( ((perDevs.status == ENABLE_ME1_LED_NOTIFICATIONS) ||
+         (perDevs.status == ENABLE_ME1_WUP_NOTIFICATIONS)) && (writeDescriptorCompleted == 1) ) {
+
+        writeDescriptorCompleted =0;
+        /* Enabling notifications on peripheral node */
+        uint8_t i = perDevs.connDeviceIdx;
+        uint16_t connection_handle = perDevs.connection_handle[i];
+        enableNotifications(connection_handle, i, customDev_v, 1);
+    }//if
+
+
+
+
+
+
+
+    if (perDevs.status == NOTIFICATIONS_ENABLED) {
+        if (!perDevs.is_disconnected[perDevs.connDeviceIdx]) {
+            perDevs.is_connected[perDevs.connDeviceIdx] = true;
+            perDevs.connDeviceIdx++;
+            perDevs.connDevices++;
+            //printf("\r\nConnected Devices %d\n", perDevs.connDevices);//DEBUG
+        }
+
+        perDevs.readDeviceIdx = perDevs.connDevices-1;
+        perDevs.status = READ_INIT;
+    }//if
+
+
+
+
+
+    /* Start reading process */
+    eventQ.call(readingProcess);
+    //eventQ.call(connectionProcess);//DEBUG_ONLY /* Call in loop coonnectionProcess */
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Method called in advertingCallback when a device is found */
+void saveDeviceFound (uint8_t adv_type, BLEProtocol::AddressBytes_t addr,
+                                                 uint8_t data_length, const uint8_t* data_RSSI, uint8_t pos, uint8_t dev_v,
+                                                 uint8_t wup_event, uint8_t mic_event, uint8_t prx_event,
+                                                 uint8_t agm_event, uint8_t sfusion_event){
+
+  perDevs.devInfo[pos].dev_v = dev_v;
+  perDevs.wup_event[pos] = wup_event;
+  perDevs.mic_event[pos] = mic_event;
+  perDevs.prx_event[pos] = prx_event;
+  perDevs.agm_event[pos] = agm_event;
+  perDevs.sfusion_event[pos] = sfusion_event;
+  memcpy(perDevs.devInfo[pos].bdaddr, addr, 6);
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Function called to connect a peripheral */
+void connectPeripheral(void){
+
+    ble_error_t e0, e1;
+    BLE& ble = BLE::Instance();
+
+
+/* if 1 to enable */
+#if 1
+    e0 = ble.gap().stopScan();
+    if (e0 != BLE_ERROR_NONE){
+         printf("\r\nError while stopping scan\n");
+    }
+#endif
+
+    uint8_t index;
+    index = perDevs.connDeviceIdx;
+
+    printf("\r\nClient create connection with peripheral %d at pos %d\n",
+           perDevs.connDevices+1, index+1);
+
+    //Connect as master (0)
+    role = 0;
+
+
+    e1 = ble.gap().connect(perDevs.devInfo[index].bdaddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+
+
+    if (e1 != BLE_ERROR_NONE){
+        printf("Error while starting connection with peripheral %d (%02x%02x).\n",
+                index+1, perDevs.devInfo[index].bdaddr[NODE_ID_B2], perDevs.devInfo[index].bdaddr[NODE_ID_B1]);
+        perDevs.is_unconnectable[index] = true;
+    }
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Function called on disconnection event */
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) {
+  //printf("\r\ndisconnectionCallback (%d)\n", perDevs.status);//DEBUG
+  BLE& ble = BLE::Instance();
+
+  uint8_t i;
+
+  // current handle
+  uint16_t handle = params->handle;
+
+
+
+
+
+  for (unsigned i=0; i<MAX_NUM_OF_NODES; i++) {
+
+    //if-MAIN
+    if (handle == perDevs.connection_handle[i]){
+        //printf("\r\n\nif (handle == perDevs.connection_handle[i]) - BleMasterService.cpp\n\n");//DEBUG
+
+        //Delete its DCList
+        deleteDCNList(headCharacteristic[i]);
+        headCharacteristic[i] = NULL;
+        tmp[i] = NULL;
+
+        if (perDevs.is_disconnected[i] == true){
+            perDevs.is_unconnectable[i] = true;
+
+            printf("\r\nPeripheral 0x%02x%02x disconnected (%d Ch in DCList)\n",
+                                perDevs.devInfo[i].bdaddr[NODE_ID_B2], perDevs.devInfo[i].bdaddr[NODE_ID_B1], countElements(headCharacteristic[i]));
+
+        }else {
+            perDevs.is_disconnected[i] = true;
+            perDevs.is_unconnectable[i] = false;
+
+
+            if (perDevs.is_connected[i] == true){
+                //printf("\r\nperDevs.is_connected[i] = true - connDevices: %d\n", perDevs.connDevices);//DEBUG
+
+                perDevs.connDevices--;
+                //disconnected_devices
+                perDevs.discDevices++;
+                perDevs.is_connected[i] = false;
+            }
+
+            /* Notify device disconnection to client */
+            perDevs.status = READING_DISCONNECTION;
+
+            readCharacteristicCallback(nullGattReadCallbackP(perDevs.connection_handle[i]));
+
+
+            notifyMaster(slaveDev.notification_data.data_length, slaveDev.notification_data.attribute_value,
+                         slaveDev.notification_data.attribute_handle);
+            perDevs.status = CONN_INIT;
+
+
+            printf("\r\nPeripheral 0x%02x%02x disconnected (%d still connected) (%d Ch in DCList)\n",
+                        perDevs.devInfo[i].bdaddr[NODE_ID_B2], perDevs.devInfo[i].bdaddr[NODE_ID_B1],
+                        perDevs.connDevices, countElements(headCharacteristic[i]));
+        }//if-else
+        break;
+
+    }//if-MAIN
+  }//for
+
+
+
+  /* SLAVE ROLE */
+  if (handle == slaveDev.conn_handle) {
+    printf("\r\nMaster disconnected (adv: %d - status %d)\n", ble.gap().getState().advertising, perDevs.status);//DEBUG
+
+
+    slaveDev.is_discoverable         = true;
+    slaveDev.is_connected            = false;
+    slaveDev.conn_handle             = 0;
+    slaveDev.star_data_char_notify   = 0;
+
+    for (i=0; i<MAX_NUM_OF_NODES; i++) {
+      perDevs.led_char_read[i]       = 0;
+      perDevs.wup_char_read[i]       = 0;
+      perDevs.mic_char_read[i]       = 0;
+      perDevs.prx_char_read[i]       = 0;
+      perDevs.agm_char_read[i]       = 0;
+      perDevs.sfusion_char_read[i]   = 0;
+      perDevs.prx_on[i]              = 0;
+      perDevs.agm_on[i]              = 0;
+      perDevs.sfusion_on[i]          = 0;
+    }//for
+
+    perDevs.discovery_enabled        = true;
+    perDevs.status = DISABLE_NOTIFICATIONS;
+
+
+    //setSlaveDiscoverable();//DEBUG_only
+
+  }//SLAVE-ROLE
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Function called on connection */
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
+      //printf("\r\n----> connectionCallback\n\n");//DEBUG
+
+      BLE& ble = BLE::Instance();
+
+      static const size_t ADDR_LEN = 6;
+      //the current address
+      BLEProtocol::AddressBytes_t tempAddr;
+      //fill the address
+      for(unsigned i=0;i<ADDR_LEN;i++) {
+        tempAddr[i]=params->peerAddr[i];
+      }
+
+      // connection handle
+      uint16_t handle = params ->handle;
+
+      //ROLE    uint8_t role
+      //        0 = master
+      //        1 = slave
+
+      uint8_t index = perDevs.connDeviceIdx;
+
+
+
+
+    /* MASTER ROLE */
+    if (role == 0) {
+
+      if (perDevs.is_unconnectable[index] == false) {
+        perDevs.connection_handle[index] = handle;
+        perDevs.is_disconnected[index] = false;
+
+        printf("\r\n\nConnected to peripheral: [%02x %02x %02x %02x %02x %02x] (%d/%d - 0x%04x) (role: %s)\n",
+                      tempAddr[5], tempAddr[4], tempAddr[3], tempAddr[2],
+                      tempAddr[1], tempAddr[0], index+1, perDevs.connDevices+1, handle, (role == 1 ? "slave" : "master"));
+
+        perDevs.status = DEVICE_CONNECTED;
+
+      } else {
+        perDevs.is_unconnectable[index] = false;
+        perDevs.device_found = false;
+        perDevs.status = DEVICE_NOT_FOUND;
+      }
+
+    }//if-MASTER
+
+
+
+
+    /* SLAVE ROLE */
+    if (role == 1) {
+    //When connected the adv seams disabled
+        slaveDev.conn_handle = handle;
+        slaveDev.is_connected = true;
+        slaveDev.is_discoverable = false;
+
+
+        printf("\r\n\nConnected to master: [%02x %02x %02x %02x %02x %02x] (role: %s) (adv: %d)\n",
+                      tempAddr[5], tempAddr[4], tempAddr[3], tempAddr[2],
+                      tempAddr[1], tempAddr[0], (role == 1 ? "slave" : "master"), ble.gap().getState().advertising);
+
+    }//if-SLAVE
+
+
+    role = 1;
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Service discovery */
+void discoverServices(void){
+
+    BLE& ble = BLE::Instance();
+    uint8_t  index = perDevs.connDeviceIdx;
+    uint16_t conn_handle = perDevs.connection_handle[index];
+    ble_error_t e0;
+
+    printf("\r\nDiscovering services for peripheral %d (0x%04x)\n", index+1, conn_handle);
+
+    if (perDevs.is_disconnected[index]){
+        printf("\r\nPeripheral %d (0x%04x) disconnected\n", index+1, conn_handle);
+        eventQ.call(setNewStatus);
+
+    }else {
+        ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
+        e0 = ble.gattClient().launchServiceDiscovery(conn_handle, serviceDiscoveryCallback,
+                                                 characteristicDiscoveryCallback);
+        if (e0 != BLE_ERROR_NONE){
+            printf("\r\nError while discovering primary services (error: %d)\n", e0);
+            eventQ.call(setNewStatus);
+        }
+    }//if-else
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+void onStopScan(Gap::TimeoutSource_t t){
+    //printf("\r\nScanning ends\n");//DEBUG
+
+
+      if (perDevs.status == DEVICE_FOUND) {
+        perDevs.device_found = true;
+      }
+      else {
+        perDevs.device_found = false;
+      }
+      perDevs.status = DEVICE_DISCOVERY_COMPLETE;
+      printf("\r\nDevice Discovery Complete (%d)\n", perDevs.status);
+
+      //HAL_Delay(100);
+
+      discoveryCompleted = 1;
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+void startDiscovery(void) {
+  //printf("\r\nstartDiscovery - status: %d\n", perDevs.status);//DEBUG
+
+
+
+
+  BLE &ble = BLE::Instance();
+  ble_error_t e1;
+
+
+//if-MAIN
+ if ((perDevs.status == CONN_INIT) && (discoveryCompleted == 1) && (advEnds == 1)){
+
+  discoveryCompleted = 0;
+
+ /* if 1 to enable
+  * if 0 default because of the adv timer setup  */
+
+#if 0
+  if ((slaveDev.is_connected == false) && (slaveDev.is_discoverable == true)){
+    //printf("\r\nslaveDev.is_discoverable == true\n");//DEBUG
+
+        ble_error_t e0;
+        e0= ble.gap().stopAdvertising();
+        if ( e0 == BLE_ERROR_NONE ) {
+        }else {
+            printf("\r\nERROR stopping advertising\n");//DEBUG
+        }
+        slaveDev.is_discoverable = false;
+  }//stopAdv
+#endif
+
+
+
+  /* MASTER ROLE */
+  perDevs.status = START_DEVICE_DISCOVERY;
+  printf("\r\nStart Device Discovery (%d)\n", perDevs.status);
+
+    e1 = ble.gap().startScan(advertisementCallback);
+
+    if ( e1 == BLE_ERROR_NONE ) {
+        //printf("\r\nScan started correctly\n");//DEBUG
+    }else {
+        printf("\r\nERROR starting scan (err: %d stat: %d)\n", e1, perDevs.status);//DEBUG
+        //doing something
+        return;
+    }
+
+ }//if-MAIN
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Function called as response of advertising */
+void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) { //defined in Gap.h
+    //printf("\r----> advertisementCallback\n");//DEBUG
+
+        static const size_t ADDR_LEN = 6;
+        //the current address
+        BLEProtocol::AddressBytes_t tempAddr;
+        //fill the address
+        for(unsigned i=0;i<ADDR_LEN;i++) {
+            tempAddr[i]=params->peerAddr[i];
+        }
+
+
+        uint8_t alreadyIn = 1;
+        uint8_t index;
+        //uint8_t i;
+        uint8_t found_zero_pos = 0;
+        BLEProtocol::AddressBytes_t zeroAddr;
+        memset(zeroAddr, 0, 6);
+
+
+
+if (perDevs.status != DEVICE_FOUND) {
+
+
+    for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
+
+        const uint8_t record_length = params->advertisingData[i];
+        if (record_length == 0) {
+            continue;
+        }
+        const uint8_t type = params->advertisingData[i + 1];
+        const uint8_t* value = params->advertisingData + i + 2;
+        const uint8_t value_length = record_length - 1;
+
+
+
+
+
+
+
+        /* Switch because per NAMES */
+        if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
+
+
+
+        /* Switch the peripheral nodes */
+
+          // M O T E N V
+            if (((value_length == sizeof(NODE_MOTENV)-1) && (memcmp(value, NODE_MOTENV, value_length) == 0))) {
+                //printf("\r(If statement 1)\n\n");//DEBUG
+
+
+
+                //initial per data
+                uint8_t peripheral_v;
+                uint8_t wup_event = 0;
+                uint8_t mic_event = 0;
+                uint8_t prx_event = 0;
+                uint8_t agm_event = 0;
+                uint8_t sfusion_event = 0;
+
+                uint8_t peripheral_name_len = params->advertisingData[3];
+                const uint8_t * manuf_data = params->advertisingData+4+peripheral_name_len;
+                uint32_t features = 0;
+
+
+                features = (manuf_data[4]<<24) | (manuf_data[5]<<16) | (manuf_data[6]<<8) | manuf_data[7];
+                wup_event = (features & FEATURE_MASK_WAKEUP_EVENTS) >> WUP_POS;
+                mic_event = (features & FEATURE_MASK_MIC) >> MIC_POS;
+                prx_event = (features & FEATURE_MASK_PROX) >> PRX_POS;
+                agm_event = (features & FEATURE_MASK_ACC) >> ACC_POS;
+                sfusion_event = (features & FEATURE_MASK_SENSORFUSION) >> SFUS_POS;
+                peripheral_v = NODE_ME1;//MOTENV
+
+
+                for (i=0; i<MAX_NUM_OF_NODES; i++) {
+                    if (perDevs.is_disconnected[i]) {
+                      if (memcmp(zeroAddr, perDevs.devInfo[i].bdaddr, 6)==0) {
+                        if (!found_zero_pos) {
+                          index = i;
+                          perDevs.connDeviceIdx = i;
+                          found_zero_pos = 1;
+                          alreadyIn = 0;
+                        }
+                      }
+                      else if (memcmp(tempAddr, perDevs.devInfo[i].bdaddr, 6)==0) {
+                        index = i;
+                        perDevs.connDeviceIdx = i;
+                        alreadyIn = 0;
+                        perDevs.discDevices--;
+                        break;
+                      }
+                      else {
+                        if (!found_zero_pos) {
+                          index = i;
+                          perDevs.connDeviceIdx = i;
+                          alreadyIn = 0;
+                        }
+                      }
+                    }
+                }//for
+
+
+                if ((!alreadyIn) && (perDevs.connDevices < MAX_NUM_OF_NODES)) {
+
+
+                    /* Save the found peripheral device in the struct containing all the found peripheral devices */
+                    saveDeviceFound(params->type, tempAddr, params->advertisingDataLen, params->advertisingData, index,
+                                    peripheral_v, wup_event, mic_event, prx_event, agm_event, sfusion_event);
+
+                    perDevs.status = DEVICE_FOUND;
+
+                    printf("\r\nPeripheral %d inserted (%02x%02x%02x%02x%02x%02x) \n", perDevs.connDevices+1,
+                           tempAddr[5], tempAddr[4], tempAddr[3], tempAddr[2], tempAddr[1], tempAddr[0]);
+
+                }//if-alreadyIn
+
+
+            }//IF-MOTENV
+
+
+
+
+          // F L I G H T
+            if ((value_length == sizeof(NODE_FLIGHT)-1) && (memcmp(value, NODE_FLIGHT, value_length) == 0)) {
+                //printf("\r(If statement 2)\n\n");//DEBUG
+
+
+
+                //initial per data
+                uint8_t peripheral_v;
+                uint8_t wup_event = 0;
+                uint8_t mic_event = 0;
+                uint8_t prx_event = 0;
+                uint8_t agm_event = 0;
+                uint8_t sfusion_event = 0;
+
+                uint8_t peripheral_name_len = params->advertisingData[3];
+                const uint8_t * manuf_data = params->advertisingData+4+peripheral_name_len;
+                uint32_t features = 0;
+
+
+                features = (manuf_data[4]<<24) | (manuf_data[5]<<16) | (manuf_data[6]<<8) | manuf_data[7];
+                wup_event = (features & FEATURE_MASK_WAKEUP_EVENTS) >> WUP_POS;
+                mic_event = (features & FEATURE_MASK_MIC) >> MIC_POS;
+                prx_event = (features & FEATURE_MASK_PROX) >> PRX_POS;
+                agm_event = (features & FEATURE_MASK_ACC) >> ACC_POS;
+                sfusion_event = (features & FEATURE_MASK_SENSORFUSION) >> SFUS_POS;
+                peripheral_v = NODE_FL1;//FLIGHT
+
+
+
+                for (i=0; i<MAX_NUM_OF_NODES; i++) {
+                    if (perDevs.is_disconnected[i]) {
+                      if (memcmp(zeroAddr, perDevs.devInfo[i].bdaddr, 6)==0) {
+                        if (!found_zero_pos) {
+                          index = i;
+                          perDevs.connDeviceIdx = i;
+                          found_zero_pos = 1;
+                          alreadyIn = 0;
+                        }
+                      }
+                      else if (memcmp(tempAddr, perDevs.devInfo[i].bdaddr, 6)==0) {
+                        index = i;
+                        perDevs.connDeviceIdx = i;
+                        alreadyIn = 0;
+                        perDevs.discDevices--;
+                        break;
+                      }
+                      else {
+                        if (!found_zero_pos) {
+                          index = i;
+                          perDevs.connDeviceIdx = i;
+                          alreadyIn = 0;
+                        }
+                      }
+                    }
+                }//for
+
+
+                if ((!alreadyIn) && (perDevs.connDevices < MAX_NUM_OF_NODES)) {
+
+
+                    /* Save the found peripheral device in the struct containing all the found peripheral devices */
+                    saveDeviceFound(params->type, tempAddr, params->advertisingDataLen, params->advertisingData, index,
+                                    peripheral_v, wup_event, mic_event, prx_event, agm_event, sfusion_event);
+
+                    perDevs.status = DEVICE_FOUND;
+
+                    printf("\r\nPeripheral %d inserted (%02x%02x%02x%02x%02x%02x) \n", perDevs.connDevices+1,
+                           tempAddr[5], tempAddr[4], tempAddr[3], tempAddr[2], tempAddr[1], tempAddr[0]);
+                }//if-alreadyIn
+
+            }//IF-FLIGHT
+
+
+
+
+
+
+
+          // A L L M E M S
+             if ((value_length == sizeof(NODE_ALLMEMS)-1) && (memcmp(value, NODE_ALLMEMS, value_length) == 0)){
+               //printf("\r(If statement 3)\n\n");//DEBUG
+
+
+
+                //initial per data
+                uint8_t peripheral_v;
+                uint8_t wup_event = 0;
+                uint8_t mic_event = 0;
+                uint8_t prx_event = 0;
+                uint8_t agm_event = 0;
+                uint8_t sfusion_event = 0;
+
+                uint8_t peripheral_name_len = params->advertisingData[3];
+                const uint8_t * manuf_data = params->advertisingData+4+peripheral_name_len;
+                uint32_t features = 0;
+
+
+                features = (manuf_data[4]<<24) | (manuf_data[5]<<16) | (manuf_data[6]<<8) | manuf_data[7];
+                wup_event = (features & FEATURE_MASK_WAKEUP_EVENTS) >> WUP_POS;
+                mic_event = (features & FEATURE_MASK_MIC) >> MIC_POS;
+                prx_event = (features & FEATURE_MASK_PROX) >> PRX_POS;
+                agm_event = (features & FEATURE_MASK_ACC) >> ACC_POS;
+                sfusion_event = (features & FEATURE_MASK_SENSORFUSION) >> SFUS_POS;
+                peripheral_v = NODE_AM1;//ALLMEMS
+
+
+                for (i=0; i<MAX_NUM_OF_NODES; i++) {
+                    if (perDevs.is_disconnected[i]) {
+                      //printf("\r\n\n  if(perDevs.is_disconnected[i])\n\n");//DEBUG
+                      if (memcmp(zeroAddr, perDevs.devInfo[i].bdaddr, 6)==0) {
+                        //printf("\r\n\n  if(memcmp(zeroAddr, perDevs.devInfo[i].bdaddr, 6)==0)\n\n");//DEBUG
+                        if (!found_zero_pos) {
+                          //printf("\r\n\n  if(!found_zero_pos)\n\n");//DEBUG
+                          index = i;
+                          perDevs.connDeviceIdx = i;
+                          found_zero_pos = 1;
+                          alreadyIn = 0;
+                        }
+                      }
+                      else if (memcmp(tempAddr, perDevs.devInfo[i].bdaddr, 6)==0) {
+                        //printf("\r\n\n  else if(memcmp(tempAddr, perDevs.devInfo[i].bdaddr, 6)==0)\n\n");//DEBUG
+                        index = i;
+                        perDevs.connDeviceIdx = i;
+                        alreadyIn = 0;
+                        perDevs.discDevices--;
+                        break;
+                      }
+                      else {
+                        //printf("\r\n\n  else - ROW 514\n\n");//DEBUG
+                        if (!found_zero_pos) {
+                          //printf("\r\n\n  if(!found_zero_pos)\n\n");//DEBUG
+                          index = i;
+                          perDevs.connDeviceIdx = i;
+                          alreadyIn = 0;
+                        }
+                      }
+                    }
+                }//for
+
+
+                if ((!alreadyIn) && (perDevs.connDevices < MAX_NUM_OF_NODES)) {
+
+
+                    /* Save the found peripheral device in the struct containing all the found peripheral devices */
+                    saveDeviceFound(params->type, tempAddr, params->advertisingDataLen, params->advertisingData, index,
+                                    peripheral_v, wup_event, mic_event, prx_event, agm_event, sfusion_event);
+
+                    perDevs.status = DEVICE_FOUND;
+
+
+                    printf("\r\nPeripheral %d inserted (%02x%02x%02x%02x%02x%02x) \n", perDevs.connDevices+1,
+                           tempAddr[5], tempAddr[4], tempAddr[3], tempAddr[2], tempAddr[1], tempAddr[0]);
+
+                }//if-alreadyIn
+
+
+            }//IF-ALLMEMS
+
+
+        }//IF-typeCOMPLETE_LOCAL_NAME
+
+
+        i += record_length;
+    }//for-MAIN
+
+}//if status != DEVICE_FOUND
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Function called after the discovery of a service */
+void serviceDiscoveryCallback(const DiscoveredService *service) {
+  //printf("\r\n\n----> serviceDiscoveryCallback\n\n");//DEBUG
+  printf("\r\n");
+
+
+  //printf("\r\nstatus: SERVICE_DISCOVERED\n\n");
+  perDevs.status = SERVICE_DISCOVERED;
+
+  //length of the long uuid
+  unsigned uuidLength = UUID::LENGTH_OF_LONG_UUID; //16
+  //pointer to the current service uuid
+  const uint8_t * pointerToUUID = service->getUUID().getBaseUUID();
+  //temp long array
+  UUID::LongUUIDBytes_t tempUUID;
+  //temp short array
+  UUID::ShortUUIDBytes_t shortTempUUID;
+
+
+  /*  Switch the known services */
+    //create the temp array
+    for (unsigned i=0;i<uuidLength;i++){
+      tempUUID[i]=pointerToUUID[i];
+    }
+
+
+
+  /* Switch the known services */
+    // HARDWARE_SERVICE_UUID
+    if ((memcmp(tempUUID, HARDWARE_SERVICE_UUID, uuidLength)) == 0){
+      printf("\r\nHARDWARE service:  [ ");
+
+      for (unsigned i = 0; i < uuidLength; i++) {
+        printf("%02x ", tempUUID[i]);
+      }
+
+      //handles
+      perDevs.hardware_service_handle[perDevs.connDeviceIdx].start_h = service->getStartHandle();
+      perDevs.hardware_service_handle[perDevs.connDeviceIdx].end_h = service->getEndHandle();
+
+      //status HW
+      perDevs.status = START_HARDWARE_SERV_CHARS_DISCOVERY;
+      //prinft("\r\nstatus = START_HARDWARE_SERV_CHARS_DISCOVERY\n");
+
+
+
+
+
+
+    // CONFIG_SERVICE_UUID
+    }else if ((memcmp(tempUUID, CONFIG_SERVICE_UUID, uuidLength)) == 0){
+      printf("\r\nCFG service:  [ ");
+
+      for (unsigned i = 0; i < uuidLength; i++) {
+        printf("%02x ", tempUUID[i]);
+      }
+
+      //handles
+      perDevs.configuration_service_handle[perDevs.connDeviceIdx].start_h = service->getStartHandle();
+      perDevs.configuration_service_handle[perDevs.connDeviceIdx].end_h = service->getEndHandle();
+
+      //status CFG
+      perDevs.status = START_CONFIGURATION_SERV_CHARS_DISCOVERY;
+      //prinft("\r\nstatus = START_CONFIGURATION_SERV_CHARS_DISCOVERY\n");
+
+
+
+
+
+    // SOFTWARE_SERVICE_UUID
+    }else if ((memcmp(tempUUID, SOFTWARE_SERVICE_UUID, uuidLength)) == 0){
+      printf("\r\nSOFTWARE service:  [ ");
+
+      for (unsigned i = 0; i < uuidLength; i++) {
+        printf("%02x ", tempUUID[i]);
+      }
+
+      //handles
+      perDevs.software_service_handle[perDevs.connDeviceIdx].start_h = service->getStartHandle();
+      perDevs.software_service_handle[perDevs.connDeviceIdx].end_h = service->getEndHandle();
+
+      //status SW
+      perDevs.status = START_SOFTWARE_SERV_CHARS_DISCOVERY;
+      //prinft("\r\nstatus = START_SOFTWARE_SERV_CHARS_DISCOVERY\n");
+
+
+
+
+
+    // Short UUID services
+    } else if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        //get the short uuid
+        shortTempUUID = service->getUUID().getShortUUID();
+//        printf("\r\n\n\nS UUID [ %x ", service->getUUID().getShortUUID());//DEBUG
+
+
+
+
+
+
+
+        // GENERIC_ACCESS_PROFILE_UUID
+        if (shortTempUUID == GENERIC_ACCESS_PROFILE_UUID) {
+          printf("\r\nGeneric Access Profile (GAP):  [ %x ", shortTempUUID);
+
+          //handles
+          perDevs.gen_access_profile_handle[perDevs.connDeviceIdx].start_h = service->getStartHandle();
+          perDevs.gen_access_profile_handle[perDevs.connDeviceIdx].end_h = service->getEndHandle();
+
+
+
+
+
+
+
+        // GENERIC_ATTRIBUTE_PROFILE_UUID
+        } else if (shortTempUUID == GENERIC_ATTRIBUTE_PROFILE_UUID) {
+          printf("\r\nGeneric Attribute Profile (GATT):  [ %x ", shortTempUUID);
+
+          //handles
+          perDevs.gen_attribute_profile_handle[perDevs.connDeviceIdx].start_h = service->getStartHandle();
+          perDevs.gen_attribute_profile_handle[perDevs.connDeviceIdx].end_h = service->getEndHandle();
+
+
+
+
+
+
+        // UNKNOWN short service
+        } else {
+          printf("\r\nUNKNOWN service:  [ %x", shortTempUUID);
+        }
+
+
+
+
+
+
+      // UNKNOWN long service
+      } else {
+        printf("\r\nUNKNOWN service:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", tempUUID[i]);
+        }
+      }
+
+
+
+
+    printf("]");
+    printf("\r\n\n");
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+
+/* Function called after the discovery of a characteristic */
+void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
+    //printf("\r----> characteristicDiscoveryCallback\n\n");//DEBUG
+
+  //current characteristic handles
+  uint16_t declHandle = characteristicP->getDeclHandle(); //identify chars
+  uint16_t valueHandle = characteristicP->getValueHandle();
+
+
+  //-----> index of current device
+  uint8_t  idx = perDevs.connDeviceIdx;
+  //printf("\r\nconnDeviceIdx: %d\n", idx);//DEBUG
+
+  //Prepend the DiscoveredCharacteristic into the list
+  headCharacteristic[idx] = prependDCNode(headCharacteristic[idx], characteristicP);
+
+
+
+  //length of the long uuid
+  unsigned uuidLength = UUID::LENGTH_OF_LONG_UUID; //16
+  //pointer to the current service uuid
+  const uint8_t * pointerToUUID = characteristicP->getUUID().getBaseUUID();
+  //temp array
+  UUID::LongUUIDBytes_t tempUUID;
+
+  //create the temp uuid array
+    for (unsigned i=0;i<uuidLength;i++){
+      tempUUID[i]=pointerToUUID[i];
+    }
+
+
+
+
+
+
+
+  /* switch the known characteristic */
+    // ENVIRONMENTAL_CHAR_UUID
+    // ENVIRONMENTAL_ST_CHAR_UUID
+    if (((memcmp(tempUUID, ENVIRONMENTAL_CHAR_UUID, uuidLength)) == 0) ||
+        ((memcmp(tempUUID, ENVIRONMENTAL_ST_CHAR_UUID, uuidLength)) == 0)){
+
+        //HW
+        perDevs.status = HARDWARE_SERV_CHARS_DISCOVERED;
+        //printf("\r\nstatus = HARDWARE_SERV_CHARS_DISCOVERED\n\n");
+
+
+        // Set the handle
+        perDevs.environmental_char_handle[idx] = declHandle;
+
+        printf("\r\n - Enviromental Ch:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+      }
+
+
+
+
+
+
+
+     // ACCGYROMAG_CHAR_UUID
+    }else if ((memcmp(tempUUID, ACCGYROMAG_CHAR_UUID, uuidLength)) == 0){
+
+        //HW
+        perDevs.status = HARDWARE_SERV_CHARS_DISCOVERED;
+        //printf("\r\nstatus = HARDWARE_SERV_CHARS_DISCOVERED\n\n");
+
+        // Set the handle
+        perDevs.agm_char_handle[idx] = declHandle;
+
+
+        printf("\r\n - Acc-Gyro-Mag Ch:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+        }
+
+
+
+
+
+
+
+     // SFUSION_CHAR_UUID
+    }else if ((memcmp(tempUUID, SFUSION_CHAR_UUID, uuidLength)) == 0){
+
+        //SW
+        perDevs.status = SOFTWARE_SERV_CHARS_DISCOVERED;
+        //printf("\r\nstatus = SOFTWARE_SERV_CHARS_DISCOVERED\n\n");
+
+        //Set the handle
+        perDevs.sfusion_char_handle[idx] = declHandle;
+        //Init value
+        perDevs.sfusion_char_read[idx]   = 0;
+        perDevs.sfusion_on[idx]          = 0;
+
+
+
+        printf("\r\n - SFusion Ch:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+        }
+
+
+
+
+
+
+     // LED_CHAR_UUID
+    }else if ((memcmp(tempUUID, LED_CHAR_UUID, uuidLength)) == 0){
+
+        //HW
+        perDevs.status = HARDWARE_SERV_CHARS_DISCOVERED;
+        //printf("\r\nstatus = HARDWARE_SERV_CHARS_DISCOVERED\n\n");
+
+        // Set the handle
+        perDevs.led_char_handle[idx] = declHandle;
+        // Init value
+        perDevs.led_char_read[idx]   = 0;
+        printf("\r\n - Led Ch:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+        }
+
+
+
+
+
+     // WAKEUP_EVENT_CHAR_UUID
+    }else if ((memcmp(tempUUID, WAKEUP_EVENT_CHAR_UUID, uuidLength)) == 0){
+
+        //HW
+        perDevs.status = HARDWARE_SERV_CHARS_DISCOVERED;
+        //printf("\r\nstatus = HARDWARE_SERV_CHARS_DISCOVERED\n\n");
+
+        // Set the handle
+        perDevs.wup_char_handle[idx] = declHandle;
+        // Init value
+        perDevs.wup_char_read[idx]   = 0;
+        printf("\r\n - Wakeup Event Ch:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+        }
+
+
+
+
+
+
+     // MIC_EVENT_CHAR_UUID
+    }else if ((memcmp(tempUUID, MIC_EVENT_CHAR_UUID, uuidLength)) == 0){
+
+        //HW
+        perDevs.status = HARDWARE_SERV_CHARS_DISCOVERED;
+        //printf("\r\nstatus = HARDWARE_SERV_CHARS_DISCOVERED\n\n");
+
+        // Set the handle
+        perDevs.mic_char_handle[idx] = declHandle;
+        // Init value
+        perDevs.mic_char_read[idx]   = 0;
+        printf("\r\n - Mic Event Ch:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+        }
+
+
+
+
+
+     // PROXIMITY_CHAR_UUID
+    }else if ((memcmp(tempUUID, PROXIMITY_CHAR_UUID, uuidLength)) == 0){
+
+        //HW
+        perDevs.status = HARDWARE_SERV_CHARS_DISCOVERED;
+        //printf("\r\nstatus = HARDWARE_SERV_CHARS_DISCOVERED\n\n");
+
+        // Set the handle
+        perDevs.prx_char_handle[idx] = declHandle;
+        // Init value
+        perDevs.prx_char_read[idx]   = 0;
+        perDevs.prx_on[idx]          = 0;
+        printf("\r\n - Proximity Ch:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+        }
+
+
+
+
+
+
+     // LUX_CHAR_UUID
+    }else if ((memcmp(tempUUID, LUX_CHAR_UUID, uuidLength)) == 0){
+
+        //HW
+        perDevs.status = HARDWARE_SERV_CHARS_DISCOVERED;
+        //printf("\r\nstatus = HARDWARE_SERV_CHARS_DISCOVERED\n\n");
+
+        // Set the handle
+        perDevs.lux_char_handle[idx] = declHandle;
+
+
+        printf("\r\n - Lux Ch:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+        }
+
+
+
+
+
+
+     // CONFIG_CHAR_UUID
+    }else if ((memcmp(tempUUID, CONFIG_CHAR_UUID, uuidLength)) == 0){
+
+        //CFG
+        perDevs.status = CONFIGURATION_SERV_CHARS_DISCOVERED;
+        //printf("\r\nstatus = CONFIGURATION_SERV_CHARS_DISCOVERED\n\n");
+
+
+        // Set the handle
+        perDevs.cfg_char_handle[idx] = declHandle;
+
+        printf("\r\n - Config Ch:  [ ");
+
+        for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+        }
+
+
+
+
+
+     // UNKNOWN
+    }else {
+
+      printf("\r\n - Unknown Ch:  [ ");
+
+      for (unsigned i = 0; i < uuidLength; i++) {
+          printf("%02x ", pointerToUUID[i]);
+        }
+    }
+
+
+
+
+  printf("] ");
+  printf("(declH 0x%04x), r: %x\n", declHandle, (uint8_t)characteristicP->getProperties().read());
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Function called when discovery is terminated */
+void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
+    //printf("\r----> discoveryTerminationCallback\n\n");//DEBUG
+
+    uint8_t * pointerToCustomDev_v;
+    pointerToCustomDev_v = &customDev_v;
+
+    uint8_t idx = perDevs.connDeviceIdx; //idx
+
+    printf("\r\n\n%d characteristics discovered and added into the DCList \n", countElements(headCharacteristic[idx]));
+    printf("\r\nTerminated SERVICE DISCOVERY for Handle 0x%04x\n\n", connectionHandle);
+
+
+
+
+////Enable notifications after the discovery of the configuration characteristics
+////------------
+    if (!perDevs.is_disconnected[perDevs.connDeviceIdx]) {
+        *pointerToCustomDev_v = perDevs.devInfo[perDevs.connDeviceIdx].dev_v;
+
+        if (perDevs.devInfo[perDevs.connDeviceIdx].dev_v == NODE_ME1) {
+            perDevs.status = ENABLE_ME1_LED_NOTIFICATIONS;
+
+        }else if (perDevs.devInfo[perDevs.connDeviceIdx].dev_v == NODE_AM1) {
+            perDevs.status = NOTIFICATIONS_ENABLED;
+
+        }else if (perDevs.devInfo[perDevs.connDeviceIdx].dev_v == NODE_FL1) {
+            perDevs.status = NOTIFICATIONS_ENABLED;
+        }
+    } else {
+        perDevs.status = NOTIFICATIONS_ENABLED;
+    }
+
+
+////------------
+
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+/* Method called when there is a notification from the sever */
+void onNotificationCallback(const GattHVXCallbackParams* event){
+     //printf("\r\nonNotificationCallback\n");//DEBUG
+
+    /* GATT Notification params */
+    uint16_t conn_handle = event->connHandle;
+    uint16_t attr_handle = event->handle;
+    uint8_t attr_len = event->len;
+    uint8_t *attr_value = (uint8_t *)event->data;
+
+
+    int32_t  tmp = 0;
+    uint8_t  tmp_data[256];
+    uint8_t  notify = 0;
+    tBDAddr  devAddr;
+    uint8_t  index;
+    uint16_t slave_attr_handle;
+    static uint8_t wupevt_value = 0;
+
+    /* Retrieving the peripheral device index and address from the connection handle */
+    getDeviceFromConnHandle(conn_handle, &index, devAddr);
+    slave_attr_handle = slaveDev.star_data_char_handle;
+
+
+
+    /* Build buffer in JSON format */
+    if (attr_handle == perDevs.wup_char_handle[index]+1) {
+
+        /**
+        * The motion is detected when a WakeUp event notification is received.
+        * The received data is composed by 2 bytes for the tstamp + 2 bytes
+        * for the value. Since we transmit only information about the detected
+        * motion, we don't care of the last 2 bytes.
+        */
+        if (attr_len != TSTAMP_LEN+2)
+            printf("\r\n(NC)WUP Warning: received data length is %d (while expecting %d)\n", attr_len, (TSTAMP_LEN+2));
+
+        wupevt_value = !wupevt_value;
+        tmp = wupevt_value;
+        sprintf((char *)wifi_data, "\"WUpEvt_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+        notify = 1;
+
+        /*
+        * Modify the attribute value according to the following format:
+        * Timestamp | Node ID | WakeUp Type ID |
+        * 2 bytes   | 2 bytes | 1 byte         |
+        */
+        Create_New_Attr_Value(attr_value, devAddr, WUP_TYPE_ID, NULL, WUP_DATA_LEN);
+
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+            perDevs.status = ALL_DATA_READ;
+            notifyMaster(ATTR_HEAD_LEN+WUP_DATA_LEN, star_attr_value, slave_attr_handle);
+        }
+
+
+    } else if (attr_handle == perDevs.mic_char_handle[index]+1) {
+
+        /* The level in dB (the mic level is detected when a mic event notification is received) */
+        /* The Sensor Tile board has only Mic1 so it sends 3 bytes */
+        if ((attr_len != TSTAMP_LEN+(2*MIC_DATA_LEN)) && (attr_len != TSTAMP_LEN+MIC_DATA_LEN))
+            printf("\r\n(NC)MIC Warning: received data length is %d (while expecting %d or %d)\n", attr_len, (TSTAMP_LEN+MIC_DATA_LEN), (TSTAMP_LEN+(2*MIC_DATA_LEN)));
+
+        tmp = attr_value[2];
+        sprintf((char *)wifi_data, "\"Mic1_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+        /* We do not send the audio level from Mic2 anyway */
+        //tmp = attr_value[3];
+        //sprintf((char *)tmp_data,  ",\"Mic2_0x%02x%02x\":%d",  devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+        //strcat((char *)wifi_data, (char *)tmp_data);
+        notify = 1;
+
+        /*
+        * Modify the attribute value according to the following format:
+        * Timestamp | Node ID | MIC Event Type ID | value  |
+        * 2 bytes   | 2 bytes | 1 byte            | 1 byte |
+        */
+        Create_New_Attr_Value(attr_value, devAddr, MICLEVEL_TYPE_ID, attr_value+TSTAMP_LEN, MIC_DATA_LEN);
+
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+            perDevs.status = ALL_DATA_READ;
+            notifyMaster(ATTR_HEAD_LEN+MIC_DATA_LEN, star_attr_value, slave_attr_handle);
+        }
+
+
+    } else if (attr_handle == perDevs.prx_char_handle[index]+1) {
+        /* the distance value (in mm) */
+        if (attr_len != TSTAMP_LEN+PRX_DATA_LEN)
+            printf("\r\n(NC)PRX Warning: received data length is %d (while expecting %d)\n", attr_len, (TSTAMP_LEN+PRX_DATA_LEN));
+
+        tmp = (attr_value[3]<<8) | attr_value[2];
+        sprintf((char *)wifi_data, "\"PRX_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+        notify = 1;
+
+        /*
+        * Modify the attribute value according to the following format:
+        * Timestamp | Node ID | Proximity Type ID | value   |
+        * 2 bytes   | 2 bytes | 1 byte            | 2 bytes |
+        */
+        Create_New_Attr_Value(attr_value, devAddr, PRX_TYPE_ID, attr_value+TSTAMP_LEN, PRX_DATA_LEN); /* Timestamp, Node ID, Proximity Type ID, data, len */
+
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+            perDevs.status = ALL_DATA_READ;
+            notifyMaster(ATTR_HEAD_LEN+PRX_DATA_LEN, star_attr_value, slave_attr_handle);
+        }
+
+
+    } else if (attr_handle == perDevs.agm_char_handle[index]+1) {
+        uint8_t type_id;
+        uint8_t data_len;
+        uint8_t value_offset;
+
+        /* Acc values in mg, Gyro values in dps, Mag values in mGa */
+        if (attr_len != TSTAMP_LEN+MEMS_DATA_LEN)
+            printf("\r\n(NC)AGM Warning: received data length is %d (while expecting %d)\n", attr_len, (TSTAMP_LEN+MEMS_DATA_LEN));
+
+        if (perDevs.acc_event_enabled) {
+            Build_MEMS_Packet(attr_value+2, "Acc", devAddr, INT_VALUE);
+            type_id = ACC_TYPE_ID;
+            data_len = ACC_DATA_LEN;
+            value_offset = TSTAMP_LEN;
+
+        } else if (perDevs.gyr_event_enabled) {
+            Build_MEMS_Packet(attr_value+8, "Gyr", devAddr, FLOAT_VALUE);
+            type_id = GYR_TYPE_ID;
+            data_len = GYR_DATA_LEN;
+            value_offset = TSTAMP_LEN+ACC_DATA_LEN;
+
+        } else if (perDevs.mag_event_enabled) {
+            Build_MEMS_Packet(attr_value+14, "Mag", devAddr, INT_VALUE);
+            type_id = MAG_TYPE_ID;
+            data_len = MAG_DATA_LEN;
+            value_offset = TSTAMP_LEN+ACC_DATA_LEN+GYR_DATA_LEN;
+        }
+        notify = 1;
+
+        /*
+        * Modify the attribute value according to the following format:
+        * Timestamp | Node ID | Acc/Gyro/Mag Type ID | value   |
+        * 2 bytes   | 2 bytes | 1 byte               | 6 bytes |
+        */
+        Create_New_Attr_Value(attr_value, devAddr, type_id, attr_value+value_offset, data_len);
+
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) && (perDevs.agm_on[index])) {
+            perDevs.status = NOTIFICATIONS_DATA_READ;
+            notifyMaster(ATTR_HEAD_LEN+data_len, star_attr_value, slave_attr_handle);
+
+        } else {
+            perDevs.status = ALL_DATA_READ;
+        }
+
+
+
+    } else if (attr_handle == perDevs.sfusion_char_handle[index]+1) {
+
+        /* Quaternion values */
+        tmp = (int8_t)attr_value[3]<<8 | attr_value[2];
+        sprintf((char *)wifi_data, "\"Q1_0x%02x%02x\":%s0.%.4d; ", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], (tmp<0 ? "-" : ""), (tmp<0 ? -tmp : tmp));
+        tmp = (int8_t)attr_value[5]<<8 | attr_value[4];
+        sprintf((char *)tmp_data, "\"Q2_0x%02x%02x\":%s0.%.4d; ", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], (tmp<0 ? "-" : ""), (tmp<0 ? -tmp : tmp));
+        strcat((char *)wifi_data, (char *)tmp_data);
+        tmp = (int8_t)attr_value[7]<<8 | attr_value[6];
+        sprintf((char *)tmp_data, "\"Q3_0x%02x%02x\":%s0.%.4d; ", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], (tmp<0 ? "-" : ""), (tmp<0 ? -tmp : tmp));
+        strcat((char *)wifi_data, (char *)tmp_data);
+        notify = 1;
+
+        /*
+        * Modify the attribute value according to the following format:
+        * Timestamp | Node ID | SFusion Type ID |  value  |
+        * 2 bytes   | 2 bytes |     1 byte      | 6 bytes |
+        */
+        Create_New_Attr_Value(attr_value, devAddr, SFUSION_TYPE_ID, attr_value+TSTAMP_LEN, SFUSION_DATA_LEN);
+
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) && (perDevs.sfusion_on[index])) {
+            perDevs.status = NOTIFICATIONS_DATA_READ;
+            notifyMaster(ATTR_HEAD_LEN+SFUSION_DATA_LEN, star_attr_value, slave_attr_handle);
+            perDevs.sfusion_char_read[index] = 1;
+
+        } else {
+            perDevs.status = ALL_DATA_READ;
+        }
+    } else if (attr_handle == perDevs.environmental_char_handle[index]+1) {
+        /* P value in mBar, H value in percentage, T2 and T1 values in Celtius degree */
+        if (attr_len != TSTAMP_LEN+ENV_DATA_LEN)
+            printf("\r\n(NC)SFUSION Warning: received data length is %d (while expecting %d)\n", attr_len, (TSTAMP_LEN+ENV_DATA_LEN));
+
+        tmp = (attr_value[5]<<24) | (attr_value[4]<<16) | (attr_value[3]<<8) | attr_value[2];
+        sprintf((char *)wifi_data, "\"Pressure_0x%02x%02x\":%ld.%ld,", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp/100, tmp%100);
+        tmp = (attr_value[7]<<8) | attr_value[6];
+        sprintf((char *)tmp_data,  "\"Humidity_0x%02x%02x\":%ld.%ld,", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp/10, tmp%10);
+        strcat((char *)wifi_data, (char *)tmp_data);
+
+        /* Showing only one Temperature from the same peripheral node */
+        //tmp = (attr_value[9]<<8) | attr_value[8];
+        //sprintf((char *)tmp_data, "\"Temperature2_0x%02x%02x\":%d.%d,", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp/10, tmp%10);
+        //strcat((char *)wifi_data, (char *)tmp_data);
+        tmp = (attr_value[11]<<8) | attr_value[10];
+        sprintf((char *)tmp_data,  "\"Temperature1_0x%02x%02x\":%ld.%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp/10, tmp%10);
+        strcat((char *)wifi_data, (char *)tmp_data);
+        notify = 1;
+
+        /*
+        * Modify the attribute value according to the following format:
+        * Tstamp  | Node ID | P Type ID | value   | H Type ID | value   | T Type ID | value   | T Type ID | value   |
+        * 2 bytes | 2 bytes | 1 byte    | 4 bytes | 1 byte    | 2 bytes | 1 byte    | 2 bytes | 1 byte    | 2 bytes |
+        */
+        Create_New_Attr_Value(attr_value, devAddr, PRESS_TYPE_ID, attr_value+TSTAMP_LEN, attr_len-TSTAMP_LEN);
+
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+            notifyMaster(ATTR_HEAD_LEN+PRESS_DATA_LEN+(3*TYPE_ID_LEN)+HUM_DATA_LEN+(2*TEMP_DATA_LEN),
+                    star_attr_value, slave_attr_handle);
+        }
+
+
+    } else if (attr_handle == perDevs.led_char_handle[index]+1) {
+        /* the status (0x01 = ON, 0x00 = OFF) */
+        if (attr_len != TSTAMP_LEN+LED_DATA_LEN)
+            printf("\r\n(NC)LED Warning: received data length is %d (while expecting %d)\n", attr_len, (TSTAMP_LEN+LED_DATA_LEN));
+
+        tmp = attr_value[2];
+        sprintf((char *)wifi_data, "\"LED_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+        notify = 1;
+
+        /*
+        * Modify the attribute value according to the following format:
+        * Timestamp | Node ID | LED Type ID | value  |
+        * 2 bytes   | 2 bytes | 1 byte      | 1 byte |
+        */
+        Create_New_Attr_Value(attr_value, devAddr, LED_TYPE_ID, attr_value+TSTAMP_LEN, LED_DATA_LEN);
+
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+            if (perDevs.led_char_read[index]==1) {
+                perDevs.status = ALL_DATA_READ;
+            }
+            notifyMaster(ATTR_HEAD_LEN+LED_DATA_LEN, star_attr_value, slave_attr_handle);
+        }
+
+
+    } else if (attr_handle == perDevs.lux_char_handle[index]+1) {
+        /* Lux value */
+        if (attr_len != TSTAMP_LEN+LUX_DATA_LEN)
+            printf("\r\n(NC)LUX Warning: received data length is %d (while expecting %d)\n", attr_len, (TSTAMP_LEN+LUX_DATA_LEN));
+
+        tmp = (attr_value[3]<<8) | attr_value[2];
+        sprintf((char *)wifi_data, "\"LUX_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+        notify = 1;
+
+        /*
+        * Modify the attribute value according to the following format:
+        * Timestamp | Node ID | LUX Type ID | value   |
+        * 2 bytes   | 2 bytes | 1 byte      | 2 bytes |
+        */
+        Create_New_Attr_Value(attr_value, devAddr, LUX_TYPE_ID, attr_value+TSTAMP_LEN, LUX_DATA_LEN);
+
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+            notifyMaster(ATTR_HEAD_LEN+LUX_DATA_LEN, star_attr_value, slave_attr_handle);
+        }
+
+
+    }//if-else-MAIN
+
+    if (notify == 1) {
+        strcat((char *)wifi_data, "\n");
+        
+        if (discoveryCompleted == 1){
+            printf("\r\nNOTIFICATION => %s", (char *)wifi_data); /* print locally the buffer in JSON format */
+        }
+        
+        data = wifi_data;
+        if ((attr_handle!=perDevs.sfusion_char_handle[index]+1) && (attr_handle!=perDevs.agm_char_handle[index]+1))
+            new_data = 1;
+    }//notify=1
+    
+    if (readCompleted != 1){
+        readCompleted = 1;
+    }
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/**
+ * @brief  Enable characteristic notifications
+ * @param  Connection Handle
+ * @param  Position of the peripheral in the struct containing all peripherals
+ * @param  Peripheral node type
+ * @param  uint8_t indicating if the notification has to be enabled (1) or disabled (0)
+ * @retval None
+ */
+void enableNotifications(uint16_t conn_handle, uint8_t index, uint8_t dev_v, uint8_t set_mode) {
+//printf("\r\nenableNotifications\n");//DEBUG
+
+
+    uint16_t attr_handle;
+    uint8_t  attr_value[6]={0,0,0,0,0,0};
+    uint8_t  attr_len;
+
+
+    const char * event_type;
+
+    switch (perDevs.status) {
+      case ENABLE_ME1_LED_NOTIFICATIONS:
+      {
+        event_type = "LED";
+        attr_handle = perDevs.led_char_handle[index] + 2;
+      }
+        break;
+
+      case ENABLE_ME1_WUP_NOTIFICATIONS:
+      {
+        event_type = "WUPEVT";
+
+        // Enable/Disable the WakeUp notifications on the Motenv1
+        setNotificationProperty(conn_handle, index, FEATURE_MASK_WAKEUP_EVENTS, WAKEUP_NOTIFICATION_CMD, set_mode);
+
+        attr_handle = perDevs.wup_char_handle[index] + 2;
+      }
+      break;
+      default:
+      break;
+    }
+
+    attr_value[0] = set_mode;
+    attr_len = 2;
+
+
+    if (perDevs.status == ENABLE_ME1_LED_NOTIFICATIONS){
+        writeDescriptorCompleted=0;
+        printf("\r\n%s notifications set to %d for periph %d (0x%04x)\n", event_type, set_mode, index+1, conn_handle);
+        writeCharacDescriptor(conn_handle, attr_handle, attr_len, attr_value);
+
+    }
+
+    if ((perDevs.status == ENABLE_ME1_WUP_NOTIFICATIONS)/* && (writeDescriptorCompleted == 1)*/){
+        writeDescriptorCompleted=0;
+        printf("\r\n%s notifications set to %d for periph %d (0x%04x)\n", event_type, set_mode, index+1, conn_handle);
+        writeCharacDescriptor(conn_handle, attr_handle, attr_len, attr_value);
+    }
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Method called after a periph descriptor is written */
+void perDescriptorWrittenCallback(const GattWriteCallbackParams* event){
+    //printf("\r\nperDescriptorWrittenCallback\n");//DEBUG
+
+    setNewStatus();
+    writeDescriptorCompleted = 1;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Write a characteristic descriptor */
+//cmd == GattClient::GATT_OP_WRITE_REQ
+void writeCharacDescriptor(uint16_t conn_handle, uint16_t attr_handle, uint8_t attr_len,
+                           uint8_t* attr_value){
+
+    ble_error_t error = BLE::Instance().gattClient().write( GattClient::GATT_OP_WRITE_REQ,
+                                                            conn_handle,
+                                                            attr_handle,
+                                                            attr_len,
+                                                            attr_value );
+
+    if (error != BLE_ERROR_NONE){
+        printf("\r\nWrite charac descriptor failed!\n");
+        writeDescriptorCompleted = 1;
+    }
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+
+/* Get error */
+ble_error_t writeCharacDescriptorWithError(uint16_t conn_handle, uint16_t attr_handle, uint8_t attr_len,
+                                                 uint8_t* attr_value){
+
+    ble_error_t error = BLE::Instance().gattClient().write( GattClient::GATT_OP_WRITE_REQ,
+                                                            conn_handle,
+                                                            attr_handle,
+                                                            attr_len,
+                                                            attr_value );
+    return error;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Write a characteristic value without waiting for any response */
+//cmd == GATT_OP_WRITE_CMD
+void writeCharacValueWithoutResp(uint16_t conn_handle, uint16_t attr_handle, uint8_t attr_len,
+                                 uint8_t* attr_value){
+
+    ble_error_t error = BLE::Instance().gattClient().write( GattClient::GATT_OP_WRITE_CMD,
+                                                            conn_handle,
+                                                            attr_handle,
+                                                            attr_len,
+                                                            attr_value );
+
+    if (error != BLE_ERROR_NONE){
+        printf("\r\nWrite charac descriptor wo resp failed!\n");
+        writeDescriptorCompleted = 1;
+    }
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* Get error */
+ble_error_t writeCharacValueWithoutRespWithError(uint16_t conn_handle, uint16_t attr_handle, uint8_t attr_len,
+                                                 uint8_t* attr_value){
+
+    ble_error_t error = BLE::Instance().gattClient().write( GattClient::GATT_OP_WRITE_CMD,
+                                                            conn_handle,
+                                                            attr_handle,
+                                                            attr_len,
+                                                            attr_value );
+    return error;
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/**
+ * @brief  This function builds a Jason format string
+ * @param  attribute value
+ * @param  string indicating the data type (Acc, Gyr or Mag)
+ * @param  address of the device
+ * @param  data type (integer or float)
+ * @retval None
+ */
+void Build_MEMS_Packet(uint8_t *attr_value, char *data_type, tBDAddr devAddr, uint8_t num_type){
+
+    int32_t tmp = 0;
+    uint8_t tmp_data[256];
+    const char* sign = "";
+    char axes[3] = {'X','Y','Z'};
+    uint8_t i, j = 0;
+
+    for (i=0; i<5; i++) {
+        tmp = ((int8_t)attr_value[i+1]<<8) | attr_value[i];
+
+        if (num_type==1) {
+            if (i==0) {
+                sprintf((char *)wifi_data, "\"%s%c_0x%02x%02x\":%ld; ", data_type, axes[j], devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+
+            } else {
+                sprintf((char *)tmp_data,  "\"%s%c_0x%02x%02x\":%ld; ", data_type, axes[j], devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+                strcat ((char *)wifi_data, (char *)tmp_data);
+            }
+
+        } else {
+            sign = (tmp < 0) ? "-" : "";
+            tmp = (tmp < 0) ? (-tmp) : (tmp);
+            if (i==0) {
+                sprintf((char *)wifi_data, "\"%s%c_0x%02x%02x\":%s%ld.%ld; ", data_type, axes[j], devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], sign, tmp/10, tmp%10);
+
+            } else {
+                sprintf((char *)tmp_data,  "\"%s%c_0x%02x%02x\":%s%ld.%ld; ", data_type, axes[j], devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], sign, tmp/10, tmp%10);
+                strcat ((char *)wifi_data, (char *)tmp_data);
+            }
+        }//if-MAIN
+
+        i++;
+        j++;
+
+    }//for
+}
+/*----------------------------------------------------------------------------*/
+
+
+/**
+ * @brief  This function creates, from an attribute value received from a
+ *         peripheral node, a new attribute value to be sent to the client
+ * @param  tstamp        Timestamp
+ * @param  data_type_id  Data Type ID
+ * @param  devAddr       Device address
+ * @param  data_length   Data Length
+ * @retval None
+ */
+void Create_New_Attr_Value (uint8_t *tstamp, tBDAddr  devAddr, uint8_t data_type_id, uint8_t *data, uint8_t data_length){
+    //printf("\r\nCreate_New_Attr_Value\n");//DEBUG
+
+
+
+    uint8_t* new_attr_value = star_attr_value;
+
+    memcpy(new_attr_value, tstamp, TSTAMP_LEN); /* Timestamp */
+    new_attr_value += TSTAMP_LEN;
+
+    memcpy(new_attr_value, devAddr+NODE_ID_OFFSET, NODE_ID_LEN); /* Node ID */
+    new_attr_value += NODE_ID_LEN;
+
+    memcpy(new_attr_value, &data_type_id, TYPE_ID_LEN); /* Data Type ID */
+    new_attr_value += TYPE_ID_LEN;
+
+  switch(data_type_id)
+  {
+
+  //
+  case PRESS_TYPE_ID:
+    {
+      memcpy(new_attr_value, data, PRESS_DATA_LEN); /* Pressure value */
+      new_attr_value  += PRESS_DATA_LEN;
+      data += PRESS_DATA_LEN;
+
+      if (data_length == ENV_DATA_LEN_LONG-TSTAMP_LEN) {
+        data_type_id = HUM_TYPE_ID;
+
+        memcpy(new_attr_value, &data_type_id, TYPE_ID_LEN);   /* Humidity Type ID */
+        new_attr_value  += TYPE_ID_LEN;
+
+        memcpy(new_attr_value, data,          HUM_DATA_LEN);  /* Humidity value */
+        new_attr_value  += HUM_DATA_LEN;
+        data += HUM_DATA_LEN;
+        data_type_id = TEMP_TYPE_ID;
+
+        memcpy(new_attr_value, &data_type_id, TYPE_ID_LEN);   /* Temperature Type ID */
+        new_attr_value  += TYPE_ID_LEN;
+
+        memcpy(new_attr_value, data,          TEMP_DATA_LEN); /* Temperature value */
+        new_attr_value  += TEMP_DATA_LEN;
+        data += TEMP_DATA_LEN;
+
+        memcpy(new_attr_value, &data_type_id, TYPE_ID_LEN);   /* Temperature Type ID */
+        new_attr_value  += TYPE_ID_LEN;
+        memcpy(new_attr_value, data,          TEMP_DATA_LEN); /* Temperature value */
+      }
+
+      else { /* Sensor Tile */
+        data_type_id = TEMP_TYPE_ID;
+        memcpy(new_attr_value, &data_type_id, TYPE_ID_LEN);   /* Temperature Type ID */
+        new_attr_value  += TYPE_ID_LEN;
+        memcpy(new_attr_value, data,          TEMP_DATA_LEN); /* Temperature value */
+      }
+    }
+    break;
+  case LED_TYPE_ID:
+  case MICLEVEL_TYPE_ID:
+    {
+      memcpy(new_attr_value, data, ONE_BYTE_LEN); /* LED or MIC value */
+    }
+    break;
+  case PRX_TYPE_ID:
+  case LUX_TYPE_ID:
+    {
+      memcpy(new_attr_value, data, TWO_BYTES_LEN); /* LUX or PRX value */
+    }
+    break;
+  case ACC_TYPE_ID:
+    {
+      memcpy(new_attr_value, data, X_DATA_LEN); /* ACC value */
+      new_attr_value += X_DATA_LEN;
+      data += X_DATA_LEN;
+      memcpy(new_attr_value, data, Y_DATA_LEN);
+      new_attr_value += Y_DATA_LEN;
+      data += Y_DATA_LEN;
+      memcpy(new_attr_value, data, Z_DATA_LEN);
+      new_attr_value += Z_DATA_LEN;
+      data += Z_DATA_LEN;
+      if (data_length == MEMS_DATA_LEN) {
+        data_type_id = GYR_TYPE_ID;
+        memcpy(new_attr_value, &data_type_id, TYPE_ID_LEN); /* GYR Type ID */
+        new_attr_value += TYPE_ID_LEN;
+        memcpy(new_attr_value, data, X_DATA_LEN);           /* GYR value */
+        new_attr_value += X_DATA_LEN;
+        data += X_DATA_LEN;
+        memcpy(new_attr_value, data, Y_DATA_LEN);
+        new_attr_value += Y_DATA_LEN;
+        data += Y_DATA_LEN;
+        memcpy(new_attr_value, data, Z_DATA_LEN);
+        new_attr_value += Z_DATA_LEN;
+        data += Z_DATA_LEN;
+
+        data_type_id = MAG_TYPE_ID;
+        memcpy(new_attr_value, &data_type_id, TYPE_ID_LEN); /* MAG Type ID */
+        new_attr_value += TYPE_ID_LEN;
+        memcpy(new_attr_value, data, X_DATA_LEN);           /* MAG value */
+        new_attr_value += X_DATA_LEN;
+        data += X_DATA_LEN;
+        memcpy(new_attr_value, data, Y_DATA_LEN);
+        new_attr_value += Y_DATA_LEN;
+        data += Y_DATA_LEN;
+        memcpy(new_attr_value, data, Z_DATA_LEN);
+      }
+    }
+    break;
+  case GYR_TYPE_ID:
+  case MAG_TYPE_ID:
+  case SFUSION_TYPE_ID:
+    {
+      memcpy(new_attr_value, data, X_DATA_LEN); /* X or Q1 value */
+      new_attr_value += X_DATA_LEN;
+      data += X_DATA_LEN;
+      memcpy(new_attr_value, data, Y_DATA_LEN); /* Y or Q2 value */
+      new_attr_value += Y_DATA_LEN;
+      data += Y_DATA_LEN;
+      memcpy(new_attr_value, data, Z_DATA_LEN); /* Z or Q3 value */
+    }
+    break;
+  default:
+    break;
+  }
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Method called after the reading of a characteristic */
+void readCharacteristicCallback(const GattReadCallbackParams *response) {
+  //printf("\r\nreadCharacteristicCallback - status (%d)\n\n", perDevs.status);//DEBUG
+
+
+
+  uint16_t handle = response->connHandle;
+  uint8_t data_length = response->len;
+  uint8_t * attr_value = (uint8_t *)response->data;
+
+
+  int32_t  tmp = 0;
+  uint8_t  tmp_data[256];
+  uint8_t  index;
+  tBDAddr  devAddr;
+  uint16_t attribute_handle; //slave
+  uint8_t  new_buffer = 0;
+  getDeviceFromConnHandle(handle, &index, devAddr);
+
+
+  /* Building the buffer in JSON format */
+  switch (perDevs.status) {
+
+  case READING_ENVIRONMENTAL:
+    {
+      /* P in mBar, H in percentage, T2 and T1 value in Celtius degree */
+      if ((data_length != ENV_DATA_LEN_LONG) && (data_length != ENV_DATA_LEN_SHORT)) {
+        printf("\rENV Warning: received data length is %d (while expecting %d or %d) - status=%d\n\n", data_length, (ENV_DATA_LEN_LONG), (ENV_DATA_LEN_SHORT), perDevs.status);
+      }
+      else {
+        tmp = (attr_value[5]<<24) | (attr_value[4]<<16) | (attr_value[3]<<8) | attr_value[2];
+        sprintf((char *)wifi_data, "\"Pressure_0x%02x%02x\":%ld.%ld,", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp/100, tmp%100);
+        if (data_length == ENV_DATA_LEN_LONG) {
+          tmp = (attr_value[7]<<8) | attr_value[6];
+          sprintf((char *)tmp_data, "\"Humidity_0x%02x%02x\":%ld.%ld,", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp/10, tmp%10);
+          strcat((char *)wifi_data, (char *)tmp_data);
+          //Showing only one Temperature from the same peripheral node
+          //tmp = (attr_value[9]<<8) | attr_value[8];
+          //sprintf((char *)tmp_data, "\"Temperature2_0x%02x%02x\":%ld.%ld,", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp/10, tmp%10);
+          //strcat((char *)wifi_data, (char *)tmp_data);
+          tmp = (attr_value[11]<<8) | attr_value[10];
+          sprintf((char *)tmp_data, "\"Temperature1_0x%02x%02x\":%ld.%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp/10, tmp%10);
+          strcat((char *)wifi_data, (char *)tmp_data);
+        }
+        else { /* ENV_DATA_LEN_SHORT (that is when using the Sensor Tile) */
+          tmp = (attr_value[7]<<8) | attr_value[6];
+          sprintf((char *)tmp_data, "\"Temperature1_0x%02x%02x\":%ld.%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp/10, tmp%10);
+          strcat((char *)wifi_data, (char *)tmp_data);
+        }
+
+
+
+
+        attribute_handle = slaveDev.star_data_char_handle;
+
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+          /*
+          * Modify the attribute value according to the following format:
+          * Tstamp  | Node ID | P Type ID | value   | H Type ID | value   | T Type ID | value   | T Type ID | value   |
+          * 2 bytes | 2 bytes | 1 byte    | 4 bytes | 1 byte    | 2 bytes | 1 byte    | 2 bytes | 1 byte    | 2 bytes |
+          */
+          Create_New_Attr_Value(attr_value, devAddr, PRESS_TYPE_ID, attr_value+TSTAMP_LEN, data_length-TSTAMP_LEN);
+          if (data_length == ENV_DATA_LEN_LONG) {
+            slaveDev.notification_data.data_length = ATTR_HEAD_LEN+PRESS_DATA_LEN+(3*TYPE_ID_LEN)+HUM_DATA_LEN+(2*TEMP_DATA_LEN);
+          }
+          else { /* ENV_DATA_LEN_SHORT (that is when using the Sensor Tile) */
+            slaveDev.notification_data.data_length = ATTR_HEAD_LEN+PRESS_DATA_LEN+TYPE_ID_LEN+TEMP_DATA_LEN;
+          }
+
+          slaveDev.notification_data.attribute_value = star_attr_value;
+          memcpy(slaveDev.notification_data.devAddr, devAddr, 6);
+          slaveDev.notification_data.attribute_handle = attribute_handle;
+        }
+
+        new_buffer = 1;
+      }
+    }
+    break;
+
+
+
+  case READING_LED:
+    {
+      /* the status (0=OFF, 1=ON) */
+      if (data_length != TSTAMP_LEN+LED_DATA_LEN) {
+        printf("\rLED Warning: received data length is %d (while expecting %d) - status=%d\n\n", data_length, (TSTAMP_LEN+LED_DATA_LEN), perDevs.status);
+      }
+      else {
+        tmp = attr_value[2];
+        sprintf((char *)wifi_data, "\"LED_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+
+
+        attribute_handle = slaveDev.star_data_char_handle;
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+          /*
+          * Modify the attribute value according to the following format:
+          * Timestamp | Node ID | LED Type ID | value  |
+          * 2 bytes   | 2 bytes | 1 byte      | 1 byte |
+          */
+          Create_New_Attr_Value(attr_value, devAddr, LED_TYPE_ID, attr_value+TSTAMP_LEN, LED_DATA_LEN);
+
+          slaveDev.notification_data.data_length = ATTR_HEAD_LEN+LED_DATA_LEN;
+          slaveDev.notification_data.attribute_value = star_attr_value;
+          memcpy(slaveDev.notification_data.devAddr, devAddr, 6);
+          slaveDev.notification_data.attribute_handle = attribute_handle;
+        }
+        new_buffer = 1;
+      }
+    }
+    break;
+
+
+
+  case READING_MIC:
+    {
+      tmp = 0; /* fake value used to just notify the mic presence */
+      sprintf((char *)wifi_data, "\"Mic1_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+
+      attribute_handle = slaveDev.star_data_char_handle;
+      if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+        uint8_t val = tmp;
+        /*
+         * Modify the attribute value according to the following format:
+         * Timestamp | Node ID | MIC Type ID | value  |
+         * 2 bytes   | 2 bytes | 1 byte      | 1 byte |
+         */
+        // STORE_LE_16(star_attr_value, (HAL_GetTick()>>3)); /* Timestamp */
+        Create_New_Attr_Value(attr_value, devAddr, MICLEVEL_TYPE_ID, &val, MIC_DATA_LEN);
+
+        slaveDev.notification_data.data_length = ATTR_HEAD_LEN+MIC_DATA_LEN;
+        slaveDev.notification_data.attribute_value = star_attr_value;
+        memcpy(slaveDev.notification_data.devAddr, devAddr, 6);
+        slaveDev.notification_data.attribute_handle = attribute_handle;
+      }
+      new_buffer = 1;
+    }
+    break;
+
+
+
+  case READING_LUX:
+    {
+      /* Lux value */
+      if (data_length != TSTAMP_LEN+LUX_DATA_LEN) {
+        printf("\rLUX Warning: received data length is %d (while expecting %d) - status=%d\n\n", data_length, (TSTAMP_LEN+LUX_DATA_LEN), perDevs.status);
+      }
+      else {
+        tmp = (attr_value[3]<<8) | attr_value[2];
+        sprintf((char *)wifi_data, "\"LUX_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+
+        attribute_handle = slaveDev.star_data_char_handle;
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+          /*
+          * Modify the attribute value according to the following format:
+          * Timestamp | Node ID | LUX Type ID | value   |
+          * 2 bytes   | 2 bytes | 1 byte      | 2 bytes |
+          */
+          Create_New_Attr_Value(attr_value, devAddr, LUX_TYPE_ID, attr_value+TSTAMP_LEN, LUX_DATA_LEN);
+
+          slaveDev.notification_data.data_length = ATTR_HEAD_LEN+LUX_DATA_LEN;
+          slaveDev.notification_data.attribute_value = star_attr_value;
+          memcpy(slaveDev.notification_data.devAddr, devAddr, 6);
+          slaveDev.notification_data.attribute_handle = attribute_handle;
+        }
+        new_buffer = 1;
+      }
+    }
+    break;
+
+
+
+  case READING_PRX:
+    {
+      /* the distance value in mm */
+      tmp = 0; /* fake value used to just notify the prx presence */
+      sprintf((char *)wifi_data, "\"PRX_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+
+//      if (attr_value == NULL){
+//        printf("\r\nattr_value == NULL\n");
+//      }else{
+//        printf("\r\nattr_value != NULL\n");
+//      }
+
+      attribute_handle = slaveDev.star_data_char_handle;
+      if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+        uint8_t val[PRX_DATA_LEN];
+        memcpy((void *)val, (void *)tmp, sizeof(val));
+        /*
+         * Modify the attribute value according to the following format:
+         * Timestamp | Node ID | Proximity Type ID | value   |
+         * 2 bytes   | 2 bytes | 1 byte            | 2 bytes |
+         */
+        Create_New_Attr_Value(attr_value, devAddr, PRX_TYPE_ID, val, PRX_DATA_LEN);
+
+        slaveDev.notification_data.data_length = ATTR_HEAD_LEN+PRX_DATA_LEN;
+        slaveDev.notification_data.attribute_value = star_attr_value;
+        memcpy(slaveDev.notification_data.devAddr, devAddr, 6);
+        slaveDev.notification_data.attribute_handle = attribute_handle;
+      }
+      new_buffer = 1;
+    }
+    break;
+
+
+
+  case READING_DISCONNECTION:
+    {
+      /* Device disconnected */
+        attribute_handle = slaveDev.star_data_char_handle;
+        /*
+        * Modify the attribute value according to the following format:
+        * Timestamp | Node ID | Status Type ID  |
+        * 2 bytes   | 2 bytes |     1 byte      |
+        */
+        Create_New_Attr_Value(attr_value, devAddr, STATUS_TYPE_ID, NULL, STATUS_DATA_LEN);
+
+        slaveDev.notification_data.data_length = ATTR_HEAD_LEN+STATUS_DATA_LEN;
+        slaveDev.notification_data.attribute_value = star_attr_value;
+        memcpy(slaveDev.notification_data.devAddr, devAddr, 6);
+        slaveDev.notification_data.attribute_handle = attribute_handle;
+
+        new_buffer = 1;
+    }
+    break;
+
+
+
+  case READING_AGM:
+    {
+      /* the acceleration value in mg */
+      tmp = 0; /* fake value used to just notify the agm presence */
+      sprintf((char *)wifi_data, "\"AGM_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+
+      attribute_handle = slaveDev.star_data_char_handle;
+      if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+        uint8_t val[MEMS_DATA_LEN];
+        memcpy((void *)val, (void *)tmp, sizeof(val));
+        /*
+         * Modify the attribute value according to the following format:
+         * Timestamp | Node ID | ACC Type ID | value   | GYR Type ID | value   | MAG Type ID | value   |
+         * 2 bytes   | 2 bytes | 1 byte      | 6 bytes | 1 byte      | 6 bytes | 1 byte      | 6 bytes |
+         */
+        Create_New_Attr_Value(attr_value, devAddr, ACC_TYPE_ID, val, MEMS_DATA_LEN);
+
+        slaveDev.notification_data.data_length = ATTR_HEAD_LEN+ACC_DATA_LEN+(2*TYPE_ID_LEN)+GYR_DATA_LEN+MAG_DATA_LEN;
+        slaveDev.notification_data.attribute_value = star_attr_value;
+        memcpy(slaveDev.notification_data.devAddr, devAddr, 6);
+        slaveDev.notification_data.attribute_handle = attribute_handle;
+      }
+      new_buffer = 1;
+    }
+    break;
+
+
+
+  case READING_SFUSION:
+    {
+      /* the mems sensor fusion value */
+      tmp = 0; /* fake value used to just notify the sensor fusion presence */
+      sprintf((char *)wifi_data, "\"SFUSION_0x%02x%02x\":%ld", devAddr[NODE_ID_B2], devAddr[NODE_ID_B1], tmp);
+
+      attribute_handle = slaveDev.star_data_char_handle;
+      if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+        uint8_t val[3];
+        memcpy((void *)val, (void *)tmp, sizeof(val));
+        /*
+         * Modify the attribute value according to the following format:
+         * Timestamp | Node ID | SFUSION Type ID |  value  |
+         * 2 bytes   | 2 bytes |     1 byte      | 6 bytes |
+         */
+        Create_New_Attr_Value(attr_value, devAddr, SFUSION_TYPE_ID, val, SFUSION_DATA_LEN);
+
+        slaveDev.notification_data.data_length = ATTR_HEAD_LEN+SFUSION_DATA_LEN;
+        slaveDev.notification_data.attribute_value = star_attr_value;
+        memcpy(slaveDev.notification_data.devAddr, devAddr, 6);
+        slaveDev.notification_data.attribute_handle = attribute_handle;
+      }
+      new_buffer = 1;
+    }
+    break;
+
+
+
+  default:
+    break;
+
+  }
+
+
+
+  if (new_buffer == 1){
+    strcat((char *)wifi_data, "\n");
+    printf("\r\n%s", (char *)wifi_data); /* print locally the buffer in JSON format */
+
+    data = wifi_data;
+    new_data = 1;
+  }
+
+
+  if (notificationPending == 1){
+    readCompleted = 1;
+    Change_Notification_Status(notifyP->att_data, notifyP->attr_value, notifyP->conn_handle, notifyP->i, notifyP->feature_mask, notifyP->frequency);
+    notificationPending = 0;
+  }
+  
+  setNewStatus();
+  readCompleted = 1;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* This function retrieves the peripheral device index and address
+ * from the connection handle */
+void getDeviceFromConnHandle(uint16_t handle, uint8_t *index, tBDAddr devAddr){
+
+  //printf("\r\ngetDeviceFromConnHandle\n\n");//DEBUG
+
+  uint8_t i;
+
+  for (i=0; i<MAX_NUM_OF_NODES; i++){
+    if (perDevs.connection_handle[i] == handle){
+      memcpy(devAddr, perDevs.devInfo[i].bdaddr, 6);
+      *index = i;
+      break;
+    }
+  }
+}
+/*----------------------------------------------------------------------------*/
+
+
+/* Create a null gatt read pointer */
+GattReadCallbackParams * nullGattReadCallbackP(uint16_t connection_handle){
+    GattReadCallbackParams gattReadCallbackParamsStruct, *pointer;
+    pointer = &gattReadCallbackParamsStruct;
+
+    pointer->connHandle = connection_handle;
+    pointer->len        = 0;
+    pointer->data       = NULL;
+
+    return pointer;
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+void readingProcess(void) {
+    //printf("\r\nreadingProcess - status: %d - connDevices: %d\n", perDevs.status, perDevs.connDevices);//DEBUG
+
+
+    /* This index defines which peripheral is going to be read */
+    uint8_t i = perDevs.readDeviceIdx;
+    //fetch the current connection handle
+    uint16_t connHandle = perDevs.connection_handle[i];
+
+
+
+
+    if ((perDevs.status == NOTIFICATIONS_DATA_READ) && (perDevs.sfusion_event_enabled) && (!perDevs.sfusion_char_read[i])){
+        perDevs.status = ALL_DATA_READ;
+    }
+
+
+
+    //READ_INIT
+    if ((perDevs.status == READ_INIT)) {
+        if (perDevs.connDevices > 0) {
+            slaveDev.is_discoverable = true;
+            //printf("\r\nperDevs.connDevices > 0 (i=%d)\n", i);//DEBUG
+            perDevs.status = ALL_DATA_READ;
+            if (!perDevs.is_disconnected[i]) {
+                //printf("\r\n!perDevs.is_disconnected\n");//DEBUG
+                switch (perDevs.devInfo[i].dev_v) {
+                    case NODE_ME1:
+                    case NODE_AM1:
+                    case NODE_FL1:
+                    /* start to read sensors data from environmental */
+
+                    if ((perDevs.mic_event_enabled) || (perDevs.prx_event_enabled) || (perDevs.agm_event_enabled)
+                        || (perDevs.sfusion_event_enabled)){
+                        //printf("\r\nNotification event enabled, skip reading\n");//DEBUG
+                    } else {
+                        perDevs.status = READING_ENVIRONMENTAL;
+                    }
+                    break;
+                    default:
+                    break;
+                }
+            }
+        } else {
+            //printf("\r\nconnDevices: %d - status = CONN_INIT - ELSE readingProces\n", perDevs.connDevices);//DEBUG
+            perDevs.status = CONN_INIT;
+        }
+    }//if-READ_INIT
+
+
+
+
+
+
+    //ENVIRONMENTAL
+    if ((perDevs.status == READING_ENVIRONMENTAL) && (readCompleted == 1)) {
+        //reading is starting
+        readCompleted = 0;
+        //fetch the characteristic declHandle
+        uint16_t declHandle = perDevs.environmental_char_handle[i];
+        //current data pointer
+        DiscoveredCharacteristic c = searchDCNode(headCharacteristic[i], declHandle)->data;
+        //pass characteristic and connection handle
+        readSensorData(c, connHandle, i);
+
+
+    }//if-ENVIRONMENTAL
+
+
+
+
+
+
+
+    //NOTIFY_ENV_TO_CLIENT
+    if ((perDevs.status == NOTIFY_ENV_TO_CLIENT) && (writeDescriptorCompleted ==1)) {
+        //printf("\r\nNOTIFY_ENV_TO_CLIENT\n");//DEBUG
+        notifyMaster(slaveDev.notification_data.data_length, slaveDev.notification_data.attribute_value,
+                     slaveDev.notification_data.attribute_handle);
+        eventQ.call(setNewStatus);
+    }//if-NOTIFY_ENV_TO_CLIENT
+
+
+
+
+
+
+
+    //READING_LED
+    if ((perDevs.status == READING_LED) && (readCompleted == 1)) {
+        //reading is starting
+        readCompleted = 0;
+        //fetch the characteristic declHandle
+        uint16_t declHandle = perDevs.led_char_handle[i];
+        //current data pointer
+        DiscoveredCharacteristic c = searchDCNode(headCharacteristic[i], declHandle)->data;
+        //pass characteristic and connection handle
+        readSensorData(c, connHandle, i);
+    }
+
+
+
+
+
+
+    //NOTIFY_LED_TO_CLIENT
+    if ((perDevs.status == NOTIFY_LED_TO_CLIENT) && (writeDescriptorCompleted ==1)) {
+        notifyMaster(slaveDev.notification_data.data_length, slaveDev.notification_data.attribute_value,
+                     slaveDev.notification_data.attribute_handle);
+        eventQ.call(setNewStatus);
+    }//if-NOTIFY_LED_TO_CLIENT
+
+
+
+
+
+
+    //READING_LUX
+    if ((perDevs.status == READING_LUX) && (readCompleted == 1)) {
+        //reading is starting
+        readCompleted = 0;
+        //fetch the characteristic declHandle
+        uint16_t declHandle = perDevs.lux_char_handle[i];
+        //current data pointer
+        DiscoveredCharacteristic c = searchDCNode(headCharacteristic[i], declHandle)->data;
+        //pass characteristic and connection handle
+        readSensorData(c, connHandle, i);
+    }//if-READING_LUX
+
+
+
+
+
+
+    //NOTIFY_LUX_TO_CLIENT
+    if ((perDevs.status == NOTIFY_LUX_TO_CLIENT) && (writeDescriptorCompleted ==1)) {
+        notifyMaster(slaveDev.notification_data.data_length, slaveDev.notification_data.attribute_value,
+                     slaveDev.notification_data.attribute_handle);
+        eventQ.call(setNewStatus);
+    }//if-NOTIFY_LUX_TO_CLIENT
+
+
+
+
+
+
+
+    //READING_MIC
+    if ((perDevs.status == READING_MIC) && (readCompleted == 1)){
+        //reading is starting
+        readCompleted = 0;
+        HAL_Delay(300);
+        /* Sending a 0 value to master just to notify the MIC sensor presence */
+        readCharacteristicCallback(nullGattReadCallbackP(connHandle));
+
+        perDevs.status = NOTIFY_MIC_TO_CLIENT;
+        notifyMaster(slaveDev.notification_data.data_length, slaveDev.notification_data.attribute_value,
+                     slaveDev.notification_data.attribute_handle);
+        eventQ.call(setNewStatus);
+    }//if-READING_MIC
+
+
+
+
+
+
+    //READING_PRX
+    if ((perDevs.status == READING_PRX) && (readCompleted == 1) && (writeDescriptorCompleted ==1)) {
+        //reading is starting
+        readCompleted = 0;
+        HAL_Delay(300);
+        /* Sending a 0 value to master just to notify the PRX sensor presence */
+        readCharacteristicCallback(nullGattReadCallbackP(connHandle));
+
+        perDevs.status = NOTIFY_PRX_TO_CLIENT;
+        notifyMaster(slaveDev.notification_data.data_length, slaveDev.notification_data.attribute_value,
+                     slaveDev.notification_data.attribute_handle);
+        eventQ.call(setNewStatus);
+  }//if-READING_PRX
+
+
+
+
+
+
+
+    //READING_AGM
+    if ((perDevs.status == READING_AGM) && (readCompleted == 1) && (writeDescriptorCompleted ==1)) {
+        //reading is starting
+        readCompleted = 0;
+        HAL_Delay(300);
+        /* Sending a 0 value to master just to notify the AGM sensors presence */
+        readCharacteristicCallback(nullGattReadCallbackP(connHandle));
+
+        perDevs.status = NOTIFY_AGM_TO_CLIENT;
+        notifyMaster(slaveDev.notification_data.data_length, slaveDev.notification_data.attribute_value,
+                     slaveDev.notification_data.attribute_handle);
+        eventQ.call(setNewStatus);
+    }//if-READING_AGM
+
+
+
+
+
+
+    //READING_SFUSION
+    if ((perDevs.status == READING_SFUSION) && (readCompleted == 1) && (writeDescriptorCompleted ==1)) {
+        //reading is starting
+        readCompleted = 0;
+        HAL_Delay(300);
+        /* Sending a 0 value to master just to notify the SFusion feature presence */
+        readCharacteristicCallback(nullGattReadCallbackP(connHandle));
+
+        perDevs.status = NOTIFY_SFUSION_TO_CLIENT;
+        notifyMaster(slaveDev.notification_data.data_length, slaveDev.notification_data.attribute_value,
+                     slaveDev.notification_data.attribute_handle);
+        eventQ.call(setNewStatus);
+    }//if-READING_SFUSION
+
+
+
+
+
+
+
+
+
+    //ALL_DATA_READ
+    if ((perDevs.status == ALL_DATA_READ) && (readCompleted == 1) && (writeDescriptorCompleted ==1)) {
+        //printf("\r\nstatus: ALL_DATA_READ (%d)\n", perDevs.status);//DEBUG
+        if (i>0) {
+            perDevs.readDeviceIdx--;
+        }
+        perDevs.status = READ_INIT;
+        //printf("\r\nstatus: READ_INIT (%d) - readingProcess\n", perDevs.status);//DEBUG
+
+
+        // All peripherals are read!
+        if (i==0) {
+
+            if ((slaveDev.is_connected == false) && (slaveDev.is_discoverable == true)) {
+#if ENABLE_MEMS
+                disableAllNotifications(); /* Called here to disable the SFUSION notifications */
+#endif
+                setSlaveDiscoverable();
+
+            } else {
+                perDevs.status = CONN_INIT;
+            }//if-else-adv
+
+        }//if-i=0
+    }//if-ALL_DATA_READ
+
+
+
+
+
+
+
+    //DISABLE_NOTIFICATIONS
+    if ((perDevs.status == DISABLE_NOTIFICATIONS) && (readCompleted == 1) && (writeDescriptorCompleted ==1)) {
+        //printf("\r\nperDevs.status == DISABLE_NOTIFICATIONS\n");//DEBUG
+        disableAllNotifications();
+        perDevs.status = ALL_DATA_READ;
+        perDevs.readDeviceIdx = i;
+
+    }//if-DISABLE_NOTIFICATIONS
+
+
+
+
+
+    /* Start connection process */
+    eventQ.call(connectionProcess);
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* This method reads the characteristic in input */
+void readSensorData(const DiscoveredCharacteristic &characteristic, uint16_t connection_handle, uint8_t index){
+    //printf("\r\nreadSensorData\n");//DEBUG
+
+    ble_error_t error;
+
+
+
+
+        if (!perDevs.is_disconnected[index] && characteristic.getDeclHandle()){
+//          printf("\r\n\nReading sensor data from periph %d (0x%04x - 0x%04x) - status=%d\n", index+1,
+//                      connection_handle, characteristic.getDeclHandle(), perDevs.status);//DEBUG
+
+            error = characteristic.read();
+
+            if (error != BLE_ERROR_NONE){
+                printf("\r\n\nUnable to read data from periph %d (err %d, cHndl 0x%04x - dHdl 0x%04x)\n", index+1,
+                        error, connection_handle, characteristic.getDeclHandle());
+
+                eventQ.call(setNewStatus);
+                readCompleted = 1;
+            }//if-failed
+
+
+        } else {
+            eventQ.call(setNewStatus);
+        
+        }//if-else-isConnected
+        
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Set the new status */
+void setNewStatus(void) {
+  //printf("\r\nsetNewStatus\n");//DEBUG
+
+
+  uint8_t i = perDevs.readDeviceIdx;
+
+
+  //Switch status
+  switch (perDevs.status) {
+
+
+
+
+
+    //
+    case ENABLE_ME1_LED_NOTIFICATIONS:
+        if (perDevs.wup_event[perDevs.connDeviceIdx]) {
+            perDevs.status = ENABLE_ME1_WUP_NOTIFICATIONS;
+        }else {
+            perDevs.status = NOTIFICATIONS_ENABLED;
+        }
+    break;
+
+
+
+
+
+
+    //
+    case ENABLE_ME1_WUP_NOTIFICATIONS:
+        perDevs.status = NOTIFICATIONS_ENABLED;
+    break;
+
+
+
+
+
+
+
+    //
+    case READING_ENVIRONMENTAL:
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+            perDevs.status = NOTIFY_ENV_TO_CLIENT;
+        }else {
+            if ((perDevs.devInfo[i].dev_v == NODE_FL1) && (perDevs.prx_on[i]==0)) {
+                perDevs.status = READING_LUX;
+            }else {
+                //printf("\r\nstatus = ALL_DATA_READ (setNewStatus)\n");
+                perDevs.status = ALL_DATA_READ;
+            }
+        }//if-MAIN
+    break;
+
+
+
+
+
+
+
+
+    //
+    case NOTIFY_ENV_TO_CLIENT:
+
+        //NODE_FL1
+        if (perDevs.devInfo[i].dev_v == NODE_FL1) {
+
+            if (perDevs.prx_on[i]==0) {
+                perDevs.status = READING_LUX;
+            }
+            else if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+               (perDevs.prx_event[i]) && (!perDevs.prx_char_read[i])) {
+                //printf("\r\n----->if\n");//DEBUG
+                perDevs.status = READING_PRX;
+            }
+
+#if ENABLE_MEMS
+            else if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+               (perDevs.agm_event[i]) && (!perDevs.agm_char_read[i])) {
+                perDevs.status = READING_AGM;
+            }
+            else if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+               (perDevs.sfusion_event[i]) && (!perDevs.sfusion_char_read[i])) {
+                perDevs.status = READING_SFUSION;
+            }
+#endif
+            else {
+                perDevs.status = ALL_DATA_READ;
+            }
+        }//if-NODE_FL1
+
+
+        //NODE_ME1
+        else if (perDevs.devInfo[i].dev_v == NODE_ME1) {
+            if (!perDevs.led_char_read[i]) {
+                perDevs.status = READING_LED;
+            }
+#if ENABLE_MEMS
+            else if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+                   (perDevs.agm_event[i]) && (!perDevs.agm_char_read[i])) {
+                    perDevs.status = READING_AGM;
+            }
+            else if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+                   (perDevs.sfusion_event[i]) && (!perDevs.sfusion_char_read[i])) {
+                    perDevs.status = READING_SFUSION;
+            }
+#endif
+            else {
+                perDevs.status = ALL_DATA_READ;
+            }
+        }//if-NODE_ME1
+
+
+        //NODE_AM1
+        else if (perDevs.devInfo[i].dev_v == NODE_AM1) {
+            if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+            (perDevs.mic_event[i]) && (!perDevs.mic_char_read[i])) {
+            perDevs.status = READING_MIC;
+            }
+#if ENABLE_MEMS
+            else if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+               (perDevs.agm_event[i]) && (!perDevs.agm_char_read[i])) {
+                perDevs.status = READING_AGM;
+            }
+            else if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+               (perDevs.sfusion_event[i]) && (!perDevs.sfusion_char_read[i])) {
+                perDevs.status = READING_SFUSION;
+            }
+#endif
+            else {
+                perDevs.status = ALL_DATA_READ;
+            }
+        }//if-NODE_AM1
+    break;
+
+
+
+
+
+
+
+    //
+    case READING_LED:
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+            perDevs.status = NOTIFY_LED_TO_CLIENT;
+        }else {
+            perDevs.status = ALL_DATA_READ;
+        }
+    break;
+
+
+
+
+
+
+
+    //
+    case NOTIFY_LED_TO_CLIENT:
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+            (!perDevs.led_char_read[i])) {
+            perDevs.led_char_read[i] = 1;
+        }
+#if ENABLE_MEMS
+        else if (perDevs.agm_event[i]) {
+            perDevs.status = READING_AGM;
+        }
+#endif
+        else {
+            perDevs.status = ALL_DATA_READ;
+        }
+    break;
+
+
+
+
+
+
+
+
+    //
+    case READING_LUX:
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify)) {
+            perDevs.status = NOTIFY_LUX_TO_CLIENT;
+        }else {
+            perDevs.status = ALL_DATA_READ;
+        }
+    break;
+
+
+
+
+
+
+
+
+    //
+    case NOTIFY_LUX_TO_CLIENT:
+        //printf("NOTIFY_LUX_TO_CLIENT");//DEBUG
+        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
+            (perDevs.prx_event[i]) && (!perDevs.prx_char_read[i])) {
+            //printf("IF-LUX");//DEBUG
+            perDevs.status = READING_PRX;
+        }else {
+            perDevs.status = ALL_DATA_READ;
+        }
+    break;
+
+
+
+
+
+
+
+    //
+    case NOTIFY_MIC_TO_CLIENT:
+        perDevs.mic_char_read[i] = 1;
+
+#if ENABLE_MEMS
+        if (perDevs.agm_event[i]) {
+            perDevs.status = READING_AGM;
+        }
+        else if (perDevs.sfusion_event[i]) {
+            perDevs.status = READING_SFUSION;
+        }else {
+            perDevs.status = ALL_DATA_READ;
+        }
+#else
+        perDevs.status = ALL_DATA_READ;
+#endif
+    break;
+
+
+
+
+
+
+
+    //
+    case NOTIFY_PRX_TO_CLIENT:
+        perDevs.prx_char_read[i] = 1;
+
+#if ENABLE_MEMS
+        if (perDevs.agm_event[i]) {
+            perDevs.status = READING_AGM;
+        }
+        else if (perDevs.sfusion_event[i]) {
+            perDevs.status = READING_SFUSION;
+        }else {
+            perDevs.status = ALL_DATA_READ;
+        }
+#else
+        perDevs.status = ALL_DATA_READ;
+#endif
+    break;
+
+
+
+
+
+
+
+    //
+    case NOTIFY_AGM_TO_CLIENT:
+        perDevs.agm_char_read[i] = 1;
+        if (perDevs.sfusion_event[i]) {
+            perDevs.status = READING_SFUSION;
+        }else {
+            perDevs.status = ALL_DATA_READ;
+        }
+    break;
+
+
+
+
+
+    //
+    case NOTIFY_SFUSION_TO_CLIENT:
+        perDevs.sfusion_char_read[i] = 1;
+        perDevs.status = ALL_DATA_READ;
+    break;
+
+
+
+    //
+    default:
+    break;
+  }
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Creating a new DiscoveredCharacteristicNode */
+DiscoveredCharacteristicNode * createDCNode(const DiscoveredCharacteristic &ch, DiscoveredCharacteristicNode *next){
+
+    DiscoveredCharacteristicNode *newNode = (DiscoveredCharacteristicNode *)malloc(sizeof(DiscoveredCharacteristicNode));
+
+    if(newNode == NULL){
+        printf("\r\nError creating a new node\n\n");
+    }
+    newNode->data = ch;
+    newNode->next = next;
+
+    return newNode;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Prepend a DiscoveredCharacteristicNode */
+DiscoveredCharacteristicNode * prependDCNode(DiscoveredCharacteristicNode *head, const DiscoveredCharacteristic *characteristic){
+
+    DiscoveredCharacteristicNode * newNode = createDCNode(*characteristic, head);
+    head = newNode;
+
+    return head;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Append a DiscoveredCharacteristicNode */
+DiscoveredCharacteristicNode * appendDCNode(DiscoveredCharacteristicNode *head, const DiscoveredCharacteristic *characteristic){
+
+    DiscoveredCharacteristicNode * cursor = head;
+    // find the last node
+    while(cursor->next != NULL){
+        cursor = cursor->next;
+    }
+
+    DiscoveredCharacteristicNode * newNode = createDCNode(*characteristic, NULL);
+    cursor->next = newNode;
+
+    return head;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Number of DiscoveredCharacteristic nodes */
+int countElements(DiscoveredCharacteristicNode *head){
+
+    DiscoveredCharacteristicNode * cursor = head;
+
+    int c=0;
+    //cursor because starts from 0
+    while (cursor != NULL){
+        c++;
+        cursor = cursor->next;
+    }
+
+    return c;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Search for a DiscoveredCharacteristic node by declaration handle */
+DiscoveredCharacteristicNode * searchDCNode(DiscoveredCharacteristicNode *head, uint16_t declHandle) {
+
+    DiscoveredCharacteristicNode * cursor = head;
+
+    while(cursor != NULL){
+
+        // search for declaration handle
+        if(cursor->data.getDeclHandle() == declHandle){
+            return cursor;
+        }
+        cursor = cursor->next;
+    }
+    return NULL;
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+/* Delete the DCN list */
+void deleteDCNList(DiscoveredCharacteristicNode *head){
+
+    DiscoveredCharacteristicNode * cursor, *tmp;
+
+    if (head != NULL){
+        cursor = head->next;
+        head->next = NULL;
+
+        while(cursor != NULL) {
+            tmp = cursor->next;
+            free(cursor);
+            cursor = tmp;
+        }
+    }
+}
+/*----------------------------------------------------------------------------*/
--- /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;
+    
+    
+    
+
+}
+/*----------------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/main.cpp	Tue Feb 20 11:21:41 2018 +0000
@@ -0,0 +1,152 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 ARM Limited
+ *
+ * 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 <events/mbed_events.h>
+#include <mbed.h>
+#include "ble/BLE.h"
+#include "ble/DiscoveredCharacteristic.h"
+#include "ble/DiscoveredService.h"
+#include <UUID.h>
+#include <BleMasterService.h>
+#include <BleSlaveService.h>
+
+const char NAME_BLESTAR1[] =    "BleStar1";
+
+/*----------------------------------------------------------------------------*/
+
+
+
+
+/* scheduleBleEventsProcessing */
+void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
+    BLE &ble = BLE::Instance();
+    eventQ.call(Callback<void()>(&ble, &BLE::processEvents));
+}
+/*----------------------------------------------------------------------------*/
+/* Complete the initialization of ble module */
+void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){
+  
+  
+    initProcess();
+    ble_error_t a0, a1, a2, a3;
+        
+    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;
+    }
+    
+    printf("\r\nBLE Init Completed\n");
+    
+    
+    /* notification */
+    //ble.gattServer().onUpdatesEnabled(onUpdatesEnabledCallback);
+    //ble.gattServer().onUpdatesDisabled(onUpdatesDisabledCallback);
+    
+    /* notification + attr writing */
+    ble.gattServer().onDataWritten(AttributeModified_CB);
+    /* data read */
+    ble.gattClient().onDataRead(readCharacteristicCallback);
+    /* when a peripheral node characteristics change */
+    ble.gattClient().onHVX(onNotificationCallback);    
+    /* when a peripheral descriptor is written */
+    ble.gattClient().onDataWritten(perDescriptorWrittenCallback);
+    
+    
+    /* disconnection */
+    ble.gap().onDisconnection(disconnectionCallback);    
+    /* connection */
+    ble.gap().onConnection(connectionCallback);
+    ble.gap().setScanParams(600, 200);    //(scanInterval,scanWindow)ms
+    ble.gap().setScanTimeout(0x0003);     //stop scanning after N sec
+    ble.gap().onTimeout(onStopScan);      //callback when scan stops
+    
+    
+    
+    
+    /* Setup adv */
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    a0 = ble.gap().accumulateScanResponse(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, manuf_data, sizeof(manuf_data));
+    a1 = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::UNKNOWN);
+    a2 = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)NAME_BLESTAR1, sizeof(NAME_BLESTAR1));
+    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //Advertising_Event_Type
+    ble.gap().setAdvertisingInterval(1000); //Adv_Interval
+    a3 = ble.gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST); //Adv_Filter_Policy      
+    if ((a0 != BLE_ERROR_NONE) || (a1 != BLE_ERROR_NONE) || (a2 != BLE_ERROR_NONE) || (a3 != BLE_ERROR_NONE)){
+        printf("\r\nError setup ADV\n");
+    }
+    
+    
+    addAllServices();
+    printMacAddress();
+    
+    
+    /* Start connection, service/chars discovery and enable notification */
+    connectionProcess();
+    
+    /* Start advertising from this point */
+    //setSlaveDiscoverable();//DEBUG_ONLY
+
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+void onBleInitError(BLE &ble, ble_error_t error) {}
+/*----------------------------------------------------------------------------*/
+
+
+
+int main()
+{
+    printf("\r\n\n/*******************************************************\n");
+    printf("\r*                                                      *\n");
+    printf("\r*      FP-NET-BLESTAR1 (MBED) Expansion Software       *\n");
+    printf("\r*                                                      *\n");
+    printf("\r*******************************************************/\n\n\n");
+  
+    /* Create the ble instance */
+    BLE &ble = BLE::Instance();
+    
+    ble.onEventsToProcess(scheduleBleEventsProcessing);
+    
+    /* Uncommenting to debug the status*/
+    //eventQ.call_every(20000, checkStatus);
+    
+    ble.init(bleInitComplete);   
+    
+    
+    //dispatch events
+    eventQ.dispatch_forever();
+
+    return 0;   
+}
+/*----------------------------------------------------------------------------*/
+
+
+
+
+