This software setup a central node of a star topology network

Dependencies:   MQTT target_st_bluenrg

Fork of ble-star-mbed by Lorenzo Invidia

source/BleMasterService.cpp

Committer:
lorevee
Date:
2018-04-04
Revision:
5:5cfb069b2587
Parent:
4:4af40af2530e

File content as of revision 5:5cfb069b2587:

#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);

/* 1 to disable reading after master disconnection */
uint8_t discFlag = 0;


/* 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;



/* Flag to indicate if the ble stack is busy
 * 1                        busy
 * 0 or anything else       not busy                                    */
uint8_t stackBusy = 0;



/* Connection Parameters struct  */
Gap::ConnectionParams_t connection_parameters = {
       0x0032, // min connection interval
       0x0087, // max connection interval
       0, // slave latency
       0x0C80 // connection supervision timeout
};



/* 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};

extern uint8_t wifi_data[256];
extern uint8_t new_data;
extern uint8_t *data;
extern uint8_t wifi_present;

char print_msg_buff[512];

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 (stat: %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){





    if ( perDevs.status == CONN_INIT ) {
        if ( (perDevs.connDevices < MAX_NUM_OF_NODES) && (perDevs.discovery_enabled) ) {
            /* Start discovery of new peripheral nodes and connect them */
            //startDiscovery();
            if (notificationPending == 0)
                eventQ.call(startDiscovery);
        }
        else {
            perDevs.status = DEVICE_CONNECTED;
         }

    }//if






    if ( perDevs.status == DEVICE_DISCOVERY_COMPLETE ) {
        if ( perDevs.device_found == true ) {
            /* Establishing connection with a peripheral device */
            perDevs.status = START_DEVICE_CONNECTION;
            eventQ.call(connectPeripheral);
            //connectPeripheral();
        }else {
            perDevs.status = DEVICE_NOT_FOUND;
        }
    }//if






    // if all devices are connected or no devices are discovered start reading
    if ((perDevs.status == DEVICE_CONNECTED) || (perDevs.status == DEVICE_NOT_FOUND) ){
     
        if (perDevs.device_found == true) {
            perDevs.status = DISCOVERABLE_MODE_SET;
            perDevs.device_found = false;
        }

        else {
            perDevs.readDeviceIdx = perDevs.connDevices+perDevs.discDevices-1;
            perDevs.status = 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++;
        }

        perDevs.readDeviceIdx = perDevs.connDevices-1;
        perDevs.status = READ_INIT;
    }//if





    /* Start reading process */
    eventQ.call(readingProcess);
  
}
/*----------------------------------------------------------------------------*/



/* 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 e1;
    BLE& ble = BLE::Instance();


/* if 1 to enable */
#if 0
    ble_error_t 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, BLEProtocol::AddressType::RANDOM_STATIC, &connection_parameters, NULL);
    
    if (e1 != BLE_ERROR_NONE){
        printf("\r\nError (%d) while connecting per %d (%02x%02x) (stat: %d) (read: %s) (write: %s)\n", e1, index+1,
                perDevs.devInfo[index].bdaddr[NODE_ID_B2], perDevs.devInfo[index].bdaddr[NODE_ID_B1], perDevs.status, 
                (readCompleted == 1 ? "completed" : "pending"),(writeDescriptorCompleted == 1 ? "completed" : "pending"));
                
                
        perDevs.is_unconnectable[index] = true;
        //perDevs.is_unconnectable[index] = false;
        
        perDevs.device_found = false;
        perDevs.status = DEVICE_NOT_FOUND;
    }//if-error
}
/*----------------------------------------------------------------------------*/




/* 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]){
     
        //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){
             
                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
    
    /* Disable reading after master disconnection */
    //discFlag = 1;
   
    

    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\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\nConnected to master: [%02x %02x %02x %02x %02x %02x] (role: %s)\n",
                      tempAddr[5], tempAddr[4], tempAddr[3], tempAddr[2],
                      tempAddr[1], tempAddr[0], (role == 1 ? "slave" : "master"));

    }//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);

      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 {
        //perDevs.status = DEVICE_DISCOVERY_COMPLETE;
        //discoveryCompleted = 1;
        
        /* Set the same timeout */
        eventQ.call_in(3000, scanTimeOut);
    }

 }//if-MAIN
}
/*----------------------------------------------------------------------------*/


void scanTimeOut(void){
    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);

    discoveryCompleted = 1;
}
/*----------------------------------------------------------------------------*/




/* Function called as response of advertising */
void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) { //defined in Gap.h

        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, i;
        uint8_t found_zero_pos = 0;
        BLEProtocol::AddressBytes_t zeroAddr;
        memset(zeroAddr, 0, 6);


        if (perDevs.status != DEVICE_FOUND) {
                
                //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;
                
                if ((manuf_data[1] == MANUF_SPECIFIC_TYPE) && ((manuf_data[3] == STM32_NUCLEO) 
                    || (manuf_data[3] == SENSOR_TILE) || (manuf_data[3] == BLUE_COIN)) && (peripheral_name_len == 8)) {
                
                    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;
                
                
                    /* Switch the kind of node */
                    if (mic_event) {
                        peripheral_v = NODE_AM1;
                    
                    }else if (prx_event) {
                        peripheral_v = NODE_FL1;
                  
                    }else {
                        peripheral_v = NODE_ME1;
                    }

                    
                    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;
                                }
                            }
                        }//perDevs.is_disconnected[i]
                    }//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;

                        switch(peripheral_v){
                            case 0x01:  /* MOTENV1 */
                                printf("\r\nPeripheral (MOTENV) %d inserted [%02x %02x %02x %02x %02x %02x] \n", perDevs.connDevices+1,
                                       tempAddr[5], tempAddr[4], tempAddr[3], tempAddr[2], tempAddr[1], tempAddr[0]);
                                break;
        
                            case 0x02:  /* FLIGHT1 */
                                printf("\r\nPeripheral (FLIGHT) %d inserted [%02x %02x %02x %02x %02x %02x] \n", perDevs.connDevices+1,
                                       tempAddr[5], tempAddr[4], tempAddr[3], tempAddr[2], tempAddr[1], tempAddr[0]);
                                break;

                            case 0x03:  /* ALLMEMS1 */
                                printf("\r\nPeripheral (ALLMEMS) %d inserted [%02x %02x %02x %02x %02x %02x] \n", perDevs.connDevices+1,
                                       tempAddr[5], tempAddr[4], tempAddr[3], tempAddr[2], tempAddr[1], tempAddr[0]);
                                break;
                        }
                        
                    }//IF-alreadyIn
                }//IF-ST-hw
        }//IF-!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;
 
  //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;
      
        // 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;
        // 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;
  
        //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;
      
        // 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;
   
        // 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;
   
        // 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;
    
        // 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;
    
        // 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;
   

        // 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;
           
            if ((stackBusy == 0) && (writeDescriptorCompleted ==1)){
                notifyMaster(ATTR_HEAD_LEN+WUP_DATA_LEN, star_attr_value, slave_attr_handle);
            }else {
                return; 
            }
             
        }


    } 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;
            if ((stackBusy == 0) && (writeDescriptorCompleted ==1)){
                notifyMaster(ATTR_HEAD_LEN+MIC_DATA_LEN, star_attr_value, slave_attr_handle);
            }else {
                return; 
            }
        }


    } 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;
            if ((stackBusy == 0) && (writeDescriptorCompleted ==1)){
                notifyMaster(ATTR_HEAD_LEN+PRX_DATA_LEN, star_attr_value, slave_attr_handle);
            }else {
                return; 
            }
        }


    } 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;
            if ((stackBusy == 0) && (writeDescriptorCompleted ==1)){
                notifyMaster(ATTR_HEAD_LEN+data_len, star_attr_value, slave_attr_handle);
            }else {
                return; 
            }

        } 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;
            if ((stackBusy == 0) && (writeDescriptorCompleted ==1)){
                notifyMaster(ATTR_HEAD_LEN+SFUSION_DATA_LEN, star_attr_value, slave_attr_handle);
            }else {
                return; 
            }
            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)) {
            if ((stackBusy == 0) && (writeDescriptorCompleted ==1)){
                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 {
                return; 
            }
        }


    } 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;
            }
            if ((stackBusy == 0) && (writeDescriptorCompleted ==1)){
                notifyMaster(ATTR_HEAD_LEN+LED_DATA_LEN, star_attr_value, slave_attr_handle);
            }else {
                return; 
            }
        }


    } 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)) {
            if ((stackBusy == 0) && (writeDescriptorCompleted ==1)){
                notifyMaster(ATTR_HEAD_LEN+LUX_DATA_LEN, star_attr_value, slave_attr_handle);
            }else {
                return; 
            }
        }


    }//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
    
    writeDescriptorCompleted = 1;
    eventQ.call(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);

      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;
  }


  /* Enable notification here because a reading operation was pending */
  if (notificationPending == 1){
    readCompleted = 1;
    Change_Notification_Status(notifyP->att_data, notifyP->attr_value, notifyP->conn_handle, notifyP->i, notifyP->feature_mask, notifyP->frequency);
  }else {
    readCompleted = 1;
    setNewStatus();
  }
}
/*----------------------------------------------------------------------------*/



/* 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;
    pointer->data       = 0;

    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;
            perDevs.status = ALL_DATA_READ;
            if (!perDevs.is_disconnected[i]) {
                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) || (discFlag)){
                        //printf("\r\nNotification event enabled, skip reading\n");//DEBUG
                        
                    } else {
                        perDevs.status = READING_ENVIRONMENTAL;
                    }
                    break;
                    default:
                    break;
                }
            }
        } else {
            perDevs.status = CONN_INIT;
        }
    }//if-READ_INIT






    //ENVIRONMENTAL
    if ((perDevs.status == READING_ENVIRONMENTAL) && (readCompleted == 1) && (writeDescriptorCompleted ==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) && (readCompleted == 1) && (writeDescriptorCompleted ==1)) {
        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) && (writeDescriptorCompleted ==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) && (readCompleted == 1) && (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) && (writeDescriptorCompleted ==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) && (readCompleted == 1) && (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) && (writeDescriptorCompleted ==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)) {
        if (i>0) {
            perDevs.readDeviceIdx--;
        }//i>0
        
        perDevs.status = READ_INIT;
      
        if ((slaveDev.is_connected == false) && (slaveDev.is_discoverable == true)) {
#if ENABLE_MEMS
            disableAllNotifications(); /* Called here to disable the SFUSION notifications */
#endif
            setSlaveDiscoverable();
        }
        // All peripherals are read!
        if (i==0) {
            perDevs.status = CONN_INIT;
        }//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()){
        error = characteristic.read();
        
        if (error != BLE_ERROR_NONE){
            printf("\r\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 
}
/*----------------------------------------------------------------------------*/



/* 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 {
                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])) {
                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:
        if ((slaveDev.is_connected) && (slaveDev.star_data_char_notify) &&
            (perDevs.prx_event[i]) && (!perDevs.prx_char_read[i])) {
            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;
        }
    }
}
/*----------------------------------------------------------------------------*/