![](/media/cache/profiles/profile2.jpg.50x50_q85.jpg)
This software setup a central node of a star topology network
Dependencies: MQTT target_st_bluenrg
Fork of ble-star-mbed by
source/BleMasterService.cpp
- Committer:
- lorevee
- Date:
- 2018-03-31
- Revision:
- 4:4af40af2530e
- Parent:
- 3:3f35e80ed848
File content as of revision 4:4af40af2530e:
#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; } } } /*----------------------------------------------------------------------------*/