![](/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/BleSlaveService.cpp@1:110b5e896bc9, 2018-02-26 (annotated)
- Committer:
- lorevee
- Date:
- Mon Feb 26 10:10:37 2018 +0000
- Revision:
- 1:110b5e896bc9
- Parent:
- 0:1902469bdd2d
- Child:
- 2:1525f4848cf2
Notification frequency fixes
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
lorevee | 0:1902469bdd2d | 1 | #include <BleSlaveService.h> |
lorevee | 0:1902469bdd2d | 2 | |
lorevee | 0:1902469bdd2d | 3 | |
lorevee | 0:1902469bdd2d | 4 | /* ----- Private variables ----- */ |
lorevee | 0:1902469bdd2d | 5 | /* Struct of slave dev */ |
lorevee | 0:1902469bdd2d | 6 | SlaveDevice_t slaveDev; |
lorevee | 0:1902469bdd2d | 7 | |
lorevee | 0:1902469bdd2d | 8 | |
lorevee | 0:1902469bdd2d | 9 | ChangeNotificationQueue notifyQ, *notifyP; |
lorevee | 0:1902469bdd2d | 10 | |
lorevee | 0:1902469bdd2d | 11 | |
lorevee | 0:1902469bdd2d | 12 | /* Struct of periph dev */ |
lorevee | 0:1902469bdd2d | 13 | extern PeripheralDevices_t perDevs; |
lorevee | 0:1902469bdd2d | 14 | |
lorevee | 0:1902469bdd2d | 15 | /* Notification frequency */ |
lorevee | 0:1902469bdd2d | 16 | uint8_t notification_freq = NOTIFICATION_FREQ_WIFI_OFF; |
lorevee | 0:1902469bdd2d | 17 | |
lorevee | 0:1902469bdd2d | 18 | |
lorevee | 0:1902469bdd2d | 19 | /* Star Service and Characteristic */ |
lorevee | 0:1902469bdd2d | 20 | uint8_t sUuid[16] = {0x00,0x00,0x00,0x00,0x00,0x01,0x11,0xe1,0x9a,0xb4,0x00,0x02,0xa5,0xd5,0xc5,0x1b}; |
lorevee | 0:1902469bdd2d | 21 | uint8_t dataUuid[16] = {0x00,0x08,0x00,0x00,0x00,0x01,0x11,0xe1,0xac,0x36,0x00,0x02,0xa5,0xd5,0xc5,0x1b}; |
lorevee | 0:1902469bdd2d | 22 | uint8_t confUuid[16] = {0x00,0x04,0x00,0x00,0x00,0x01,0x11,0xe1,0xac,0x36,0x00,0x02,0xa5,0xd5,0xc5,0x1b}; |
lorevee | 0:1902469bdd2d | 23 | |
lorevee | 0:1902469bdd2d | 24 | |
lorevee | 0:1902469bdd2d | 25 | /*---- Create the two characteristic ----*/ |
lorevee | 0:1902469bdd2d | 26 | /* Config char */ |
lorevee | 0:1902469bdd2d | 27 | GattCharacteristic configChar(confUuid, slaveDev.star_config_value, STAR_CHAR_MAX_VALUE_LEN, STAR_CHAR_MAX_VALUE_LEN, |
lorevee | 0:1902469bdd2d | 28 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE, |
lorevee | 0:1902469bdd2d | 29 | NULL, 0, true); |
lorevee | 0:1902469bdd2d | 30 | |
lorevee | 0:1902469bdd2d | 31 | |
lorevee | 0:1902469bdd2d | 32 | /* Data char */ |
lorevee | 0:1902469bdd2d | 33 | GattCharacteristic dataChar(dataUuid, slaveDev.notification_data.attribute_value, STAR_CHAR_MAX_VALUE_LEN, STAR_CHAR_MAX_VALUE_LEN, |
lorevee | 0:1902469bdd2d | 34 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE, |
lorevee | 0:1902469bdd2d | 35 | NULL, 0, true); |
lorevee | 0:1902469bdd2d | 36 | |
lorevee | 0:1902469bdd2d | 37 | |
lorevee | 0:1902469bdd2d | 38 | /* MANUFACTURER_SPECIFIC_DATA */ |
lorevee | 0:1902469bdd2d | 39 | uint8_t manuf_data[6] = { |
lorevee | 0:1902469bdd2d | 40 | 0x01, /*SKD version */ |
lorevee | 0:1902469bdd2d | 41 | 0x81, /* NUCLEO-Board remote */ |
lorevee | 0:1902469bdd2d | 42 | 0x00, /* Led Prox+Lux */ //Unused |
lorevee | 0:1902469bdd2d | 43 | 0x0C, /* Star Config Char + Star Data Char */ //Unused |
lorevee | 0:1902469bdd2d | 44 | 0x00, /* SensorFusionShort */ //Unused |
lorevee | 0:1902469bdd2d | 45 | 0x00 /* SensorFusionFloat */ //Unused |
lorevee | 0:1902469bdd2d | 46 | }; |
lorevee | 0:1902469bdd2d | 47 | |
lorevee | 0:1902469bdd2d | 48 | |
lorevee | 0:1902469bdd2d | 49 | |
lorevee | 0:1902469bdd2d | 50 | |
lorevee | 0:1902469bdd2d | 51 | |
lorevee | 0:1902469bdd2d | 52 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 53 | |
lorevee | 0:1902469bdd2d | 54 | |
lorevee | 0:1902469bdd2d | 55 | |
lorevee | 0:1902469bdd2d | 56 | /* Set the device as a slave in discoverable mode */ |
lorevee | 0:1902469bdd2d | 57 | void setSlaveDiscoverable(void) { |
lorevee | 0:1902469bdd2d | 58 | //printf("\r\nsetSlaveDiscoverable\n");//DEBUG |
lorevee | 0:1902469bdd2d | 59 | BLE& ble = BLE::Instance(); |
lorevee | 0:1902469bdd2d | 60 | ble_error_t e2; |
lorevee | 0:1902469bdd2d | 61 | |
lorevee | 0:1902469bdd2d | 62 | |
lorevee | 0:1902469bdd2d | 63 | //if-MAIN - discovery/reading/writing ops completed |
lorevee | 0:1902469bdd2d | 64 | if ((discoveryCompleted == 1) /*&& (readCompleted == 1) && (writeDescriptorCompleted == 1)*/){ |
lorevee | 0:1902469bdd2d | 65 | |
lorevee | 0:1902469bdd2d | 66 | |
lorevee | 0:1902469bdd2d | 67 | |
lorevee | 0:1902469bdd2d | 68 | /* Start advertisng */ |
lorevee | 0:1902469bdd2d | 69 | if ((!ble.gap().getState().advertising)){ |
lorevee | 0:1902469bdd2d | 70 | advEnds =0; |
lorevee | 0:1902469bdd2d | 71 | |
lorevee | 0:1902469bdd2d | 72 | printf("\r\nSet Discoverable Mode (%d)\n", perDevs.status); |
lorevee | 0:1902469bdd2d | 73 | e2 = ble.gap().startAdvertising(); |
lorevee | 0:1902469bdd2d | 74 | if ( e2 == BLE_ERROR_NONE ){ |
lorevee | 0:1902469bdd2d | 75 | /* Giving some time to connect */ |
lorevee | 0:1902469bdd2d | 76 | eventQ.call_in(7000, stopAdv);//N ms |
lorevee | 0:1902469bdd2d | 77 | }else{ |
lorevee | 0:1902469bdd2d | 78 | printf("\r\nError while starting advertising (err: %d - stat: %d)\n", e2, perDevs.status); |
lorevee | 0:1902469bdd2d | 79 | advEnds=1;//terminated because not started |
lorevee | 0:1902469bdd2d | 80 | } |
lorevee | 0:1902469bdd2d | 81 | |
lorevee | 0:1902469bdd2d | 82 | }//if-not-adv |
lorevee | 0:1902469bdd2d | 83 | }//if-MAIN |
lorevee | 0:1902469bdd2d | 84 | |
lorevee | 0:1902469bdd2d | 85 | |
lorevee | 0:1902469bdd2d | 86 | //Restart loop ops |
lorevee | 0:1902469bdd2d | 87 | perDevs.status = CONN_INIT; |
lorevee | 0:1902469bdd2d | 88 | perDevs.discovery_enabled = true; |
lorevee | 0:1902469bdd2d | 89 | //printf("\rstatus = CONN_INIT (%d)\n", perDevs.status);//DEBUG |
lorevee | 0:1902469bdd2d | 90 | |
lorevee | 0:1902469bdd2d | 91 | } |
lorevee | 0:1902469bdd2d | 92 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 93 | |
lorevee | 0:1902469bdd2d | 94 | |
lorevee | 0:1902469bdd2d | 95 | |
lorevee | 0:1902469bdd2d | 96 | void stopAdv(){ |
lorevee | 0:1902469bdd2d | 97 | |
lorevee | 0:1902469bdd2d | 98 | if ((slaveDev.is_connected == false) && (discoveryCompleted == 1)){ |
lorevee | 0:1902469bdd2d | 99 | if (BLE::Instance().gap().getState().advertising){ |
lorevee | 0:1902469bdd2d | 100 | ble_error_t e = BLE::Instance().gap().stopAdvertising(); |
lorevee | 0:1902469bdd2d | 101 | if ( e != BLE_ERROR_NONE ) { |
lorevee | 0:1902469bdd2d | 102 | printf("\r\nError stopping ADV\n");//DEBUG |
lorevee | 0:1902469bdd2d | 103 | } |
lorevee | 0:1902469bdd2d | 104 | } |
lorevee | 0:1902469bdd2d | 105 | }//if |
lorevee | 0:1902469bdd2d | 106 | |
lorevee | 0:1902469bdd2d | 107 | advEnds = 1; |
lorevee | 0:1902469bdd2d | 108 | } |
lorevee | 0:1902469bdd2d | 109 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 110 | |
lorevee | 0:1902469bdd2d | 111 | |
lorevee | 0:1902469bdd2d | 112 | |
lorevee | 0:1902469bdd2d | 113 | /** |
lorevee | 0:1902469bdd2d | 114 | * @brief This function sets some notification properties (e.g. the |
lorevee | 0:1902469bdd2d | 115 | * notification period) by sending a command according to the |
lorevee | 0:1902469bdd2d | 116 | * following format: |
lorevee | 0:1902469bdd2d | 117 | * FEATURE_MASK (4bytes) + Command (1byte) + Data (1byte) |
lorevee | 0:1902469bdd2d | 118 | * In case of the notification period the command is 255 while the allowed data are: |
lorevee | 0:1902469bdd2d | 119 | * 50 @5S, 10 @1S, 1 @100mS, 0 @50mS (default). |
lorevee | 0:1902469bdd2d | 120 | * @param connection handle |
lorevee | 0:1902469bdd2d | 121 | * @param peripheral device index |
lorevee | 0:1902469bdd2d | 122 | * @param feature mask |
lorevee | 0:1902469bdd2d | 123 | * @param command |
lorevee | 0:1902469bdd2d | 124 | * @param data |
lorevee | 0:1902469bdd2d | 125 | * @retval None |
lorevee | 0:1902469bdd2d | 126 | */ |
lorevee | 0:1902469bdd2d | 127 | void setNotificationProperty(uint16_t conn_handle, uint8_t i, uint32_t feature_mask, |
lorevee | 0:1902469bdd2d | 128 | uint8_t command, uint8_t data) { |
lorevee | 0:1902469bdd2d | 129 | //printf("\r\nsetNotificationProperty\n");//DEBUG |
lorevee | 0:1902469bdd2d | 130 | |
lorevee | 0:1902469bdd2d | 131 | uint16_t attr_handle; |
lorevee | 0:1902469bdd2d | 132 | uint8_t value_len; |
lorevee | 0:1902469bdd2d | 133 | uint8_t attr_value[6]; |
lorevee | 0:1902469bdd2d | 134 | |
lorevee | 0:1902469bdd2d | 135 | attr_handle = perDevs.cfg_char_handle[i] + 1; |
lorevee | 0:1902469bdd2d | 136 | attr_value[0] = (uint8_t)((feature_mask) >> 24); |
lorevee | 0:1902469bdd2d | 137 | attr_value[1] = (uint8_t)((feature_mask) >> 16); |
lorevee | 0:1902469bdd2d | 138 | attr_value[2] = (uint8_t)((feature_mask) >> 8); |
lorevee | 0:1902469bdd2d | 139 | attr_value[3] = (uint8_t)((feature_mask)); |
lorevee | 0:1902469bdd2d | 140 | attr_value[4] = command; |
lorevee | 0:1902469bdd2d | 141 | attr_value[5] = data; |
lorevee | 0:1902469bdd2d | 142 | value_len = 6; /* FEATURE_MASK len (4bytes) + Command len (1byte) + Data len (1byte) */ |
lorevee | 0:1902469bdd2d | 143 | |
lorevee | 0:1902469bdd2d | 144 | |
lorevee | 0:1902469bdd2d | 145 | /* The gatt write function above is w/out response, so we just wait for a short time before going on */ |
lorevee | 0:1902469bdd2d | 146 | writeCharacValueWithoutResp(conn_handle, attr_handle, value_len, attr_value); |
lorevee | 0:1902469bdd2d | 147 | HAL_Delay(2000);//N ms |
lorevee | 0:1902469bdd2d | 148 | } |
lorevee | 0:1902469bdd2d | 149 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 150 | |
lorevee | 0:1902469bdd2d | 151 | |
lorevee | 0:1902469bdd2d | 152 | |
lorevee | 0:1902469bdd2d | 153 | |
lorevee | 0:1902469bdd2d | 154 | /* Forwards to master all notifications from peripherals */ |
lorevee | 0:1902469bdd2d | 155 | void notifyMaster(uint8_t data_length, uint8_t* attribute_value, uint16_t attribute_handle){ |
lorevee | 0:1902469bdd2d | 156 | //printf("\r\nnotifyMaster\n");//DEBUG |
lorevee | 0:1902469bdd2d | 157 | ble_error_t notifyError; |
lorevee | 0:1902469bdd2d | 158 | |
lorevee | 0:1902469bdd2d | 159 | |
lorevee | 0:1902469bdd2d | 160 | notifyError = BLE::Instance().gattServer().write(attribute_handle+1, attribute_value, data_length, false); |
lorevee | 0:1902469bdd2d | 161 | |
lorevee | 0:1902469bdd2d | 162 | if (notifyError != BLE_ERROR_NONE){ |
lorevee | 0:1902469bdd2d | 163 | printf("\r\n(notifyMaster) Error (%d) while updating characteristic\n", notifyError);//BLE_STACK_BUSY |
lorevee | 1:110b5e896bc9 | 164 | if (notifyError == BLE_STACK_BUSY){ |
lorevee | 1:110b5e896bc9 | 165 | stackBusy = 1; |
lorevee | 1:110b5e896bc9 | 166 | return; |
lorevee | 1:110b5e896bc9 | 167 | } |
lorevee | 1:110b5e896bc9 | 168 | }else { |
lorevee | 1:110b5e896bc9 | 169 | writeDescriptorCompleted =1; |
lorevee | 1:110b5e896bc9 | 170 | stackBusy = 0; |
lorevee | 1:110b5e896bc9 | 171 | return; |
lorevee | 0:1902469bdd2d | 172 | } |
lorevee | 1:110b5e896bc9 | 173 | |
lorevee | 0:1902469bdd2d | 174 | } |
lorevee | 0:1902469bdd2d | 175 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 176 | |
lorevee | 0:1902469bdd2d | 177 | |
lorevee | 0:1902469bdd2d | 178 | /* Add all services using a vendor specific UUIDs */ |
lorevee | 0:1902469bdd2d | 179 | void addAllServices(void){ |
lorevee | 0:1902469bdd2d | 180 | |
lorevee | 0:1902469bdd2d | 181 | ble_error_t error; |
lorevee | 0:1902469bdd2d | 182 | notifyP = ¬ifyQ; |
lorevee | 0:1902469bdd2d | 183 | |
lorevee | 0:1902469bdd2d | 184 | |
lorevee | 0:1902469bdd2d | 185 | GattCharacteristic *charTable[] = {&configChar, &dataChar}; |
lorevee | 0:1902469bdd2d | 186 | |
lorevee | 0:1902469bdd2d | 187 | /*---- Create the hw service ----*/ |
lorevee | 0:1902469bdd2d | 188 | GattService starService(sUuid, charTable, sizeof(charTable) / sizeof(GattCharacteristic *)); |
lorevee | 0:1902469bdd2d | 189 | |
lorevee | 0:1902469bdd2d | 190 | /*---- Add the hw service ----*/ |
lorevee | 1:110b5e896bc9 | 191 | error = BLE::Instance().gattServer().addService(starService); |
lorevee | 0:1902469bdd2d | 192 | slaveDev.star_hw_serv_handle = starService.getHandle(); |
lorevee | 0:1902469bdd2d | 193 | slaveDev.star_config_char_handle = configChar.getValueHandle()-1; //-1 for decl handle |
lorevee | 0:1902469bdd2d | 194 | slaveDev.star_data_char_handle = dataChar.getValueHandle()-1; //-1 for decl handle |
lorevee | 0:1902469bdd2d | 195 | |
lorevee | 0:1902469bdd2d | 196 | |
lorevee | 0:1902469bdd2d | 197 | |
lorevee | 0:1902469bdd2d | 198 | if ( error != BLE_ERROR_NONE ){ |
lorevee | 0:1902469bdd2d | 199 | printf("\r\nError while creating starService(error: %d)\n", error); |
lorevee | 0:1902469bdd2d | 200 | |
lorevee | 0:1902469bdd2d | 201 | } else { |
lorevee | 0:1902469bdd2d | 202 | printf("\r\nStar HW Gatt Service added (handle 0x%004x)\n", slaveDev.star_hw_serv_handle); |
lorevee | 0:1902469bdd2d | 203 | printf("\rStar HW Config Char added (handle 0x%004x)\n", slaveDev.star_config_char_handle); |
lorevee | 0:1902469bdd2d | 204 | printf("\rStar HW Data Char added (handle 0x%004x)", slaveDev.star_data_char_handle); |
lorevee | 0:1902469bdd2d | 205 | printf("\r\n"); |
lorevee | 0:1902469bdd2d | 206 | } |
lorevee | 0:1902469bdd2d | 207 | |
lorevee | 0:1902469bdd2d | 208 | } |
lorevee | 0:1902469bdd2d | 209 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 210 | |
lorevee | 0:1902469bdd2d | 211 | |
lorevee | 0:1902469bdd2d | 212 | /* Disable all notifications */ |
lorevee | 0:1902469bdd2d | 213 | void disableAllNotifications(void){ |
lorevee | 0:1902469bdd2d | 214 | //printf("\r\ndisableAllNotifications\n");//DEBUG |
lorevee | 0:1902469bdd2d | 215 | |
lorevee | 0:1902469bdd2d | 216 | |
lorevee | 0:1902469bdd2d | 217 | uint8_t j; |
lorevee | 0:1902469bdd2d | 218 | uint16_t attr_handle; |
lorevee | 0:1902469bdd2d | 219 | uint8_t value_len; |
lorevee | 0:1902469bdd2d | 220 | uint8_t attr_value[2]; |
lorevee | 0:1902469bdd2d | 221 | char* feat = NULL; |
lorevee | 0:1902469bdd2d | 222 | |
lorevee | 0:1902469bdd2d | 223 | for (j=0; j<(perDevs.connDevices+perDevs.discDevices); j++) { |
lorevee | 0:1902469bdd2d | 224 | |
lorevee | 0:1902469bdd2d | 225 | if ((perDevs.mic_event[j]) && (perDevs.mic_event_enabled)) { |
lorevee | 0:1902469bdd2d | 226 | feat = "MIC"; |
lorevee | 0:1902469bdd2d | 227 | perDevs.mic_event_enabled = 0; |
lorevee | 0:1902469bdd2d | 228 | perDevs.mic_event[j] = 0; |
lorevee | 0:1902469bdd2d | 229 | attr_handle = perDevs.mic_char_handle[j] + 2; |
lorevee | 0:1902469bdd2d | 230 | |
lorevee | 0:1902469bdd2d | 231 | } else if ((perDevs.prx_event[j]) && (perDevs.prx_event_enabled)) { |
lorevee | 0:1902469bdd2d | 232 | feat = "PRX"; |
lorevee | 0:1902469bdd2d | 233 | perDevs.prx_event_enabled = 0; |
lorevee | 0:1902469bdd2d | 234 | perDevs.prx_on[j] = 0; |
lorevee | 0:1902469bdd2d | 235 | attr_handle = perDevs.prx_char_handle[j] + 2; |
lorevee | 0:1902469bdd2d | 236 | |
lorevee | 0:1902469bdd2d | 237 | } else if ((perDevs.agm_event[j]) && (perDevs.agm_event_enabled)) { |
lorevee | 0:1902469bdd2d | 238 | feat = "AGM"; |
lorevee | 0:1902469bdd2d | 239 | perDevs.acc_event_enabled = 0; |
lorevee | 0:1902469bdd2d | 240 | perDevs.gyr_event_enabled = 0; |
lorevee | 0:1902469bdd2d | 241 | perDevs.mag_event_enabled = 0; |
lorevee | 0:1902469bdd2d | 242 | perDevs.agm_event_enabled = 0; |
lorevee | 0:1902469bdd2d | 243 | perDevs.agm_on[j] = 0; |
lorevee | 0:1902469bdd2d | 244 | attr_handle = perDevs.agm_char_handle[j] + 2; |
lorevee | 0:1902469bdd2d | 245 | |
lorevee | 0:1902469bdd2d | 246 | } else if ((perDevs.sfusion_event[j]) && (perDevs.sfusion_event_enabled)) { |
lorevee | 0:1902469bdd2d | 247 | feat = "SFUSION"; |
lorevee | 0:1902469bdd2d | 248 | perDevs.sfusion_event_enabled = 0; |
lorevee | 0:1902469bdd2d | 249 | perDevs.sfusion_on[j] = 0; |
lorevee | 0:1902469bdd2d | 250 | attr_handle = perDevs.sfusion_char_handle[j] + 2; |
lorevee | 0:1902469bdd2d | 251 | |
lorevee | 0:1902469bdd2d | 252 | } else { |
lorevee | 0:1902469bdd2d | 253 | continue; |
lorevee | 0:1902469bdd2d | 254 | } |
lorevee | 0:1902469bdd2d | 255 | |
lorevee | 0:1902469bdd2d | 256 | value_len = 2; |
lorevee | 0:1902469bdd2d | 257 | attr_value[0] = DISABLE; |
lorevee | 0:1902469bdd2d | 258 | |
lorevee | 0:1902469bdd2d | 259 | |
lorevee | 0:1902469bdd2d | 260 | writeDescriptorCompleted=0; |
lorevee | 0:1902469bdd2d | 261 | ble_error_t disableErr = writeCharacDescriptorWithError(perDevs.connection_handle[j], attr_handle, value_len, attr_value); |
lorevee | 0:1902469bdd2d | 262 | printf("\r\nSet OFF the %s notifications on node %d\n", feat, j); |
lorevee | 0:1902469bdd2d | 263 | |
lorevee | 0:1902469bdd2d | 264 | if (disableErr != BLE_ERROR_NONE){ |
lorevee | 1:110b5e896bc9 | 265 | printf("\r\n(disableAllNotifications) Write charac descriptor failed (err: %d, stat: %d)\n", disableErr, perDevs.status); |
lorevee | 0:1902469bdd2d | 266 | writeDescriptorCompleted=1; |
lorevee | 0:1902469bdd2d | 267 | //HAL_Delay(500); |
lorevee | 0:1902469bdd2d | 268 | //disableAllNotifications(); |
lorevee | 0:1902469bdd2d | 269 | }//if-error |
lorevee | 0:1902469bdd2d | 270 | }//for |
lorevee | 0:1902469bdd2d | 271 | } |
lorevee | 0:1902469bdd2d | 272 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 273 | |
lorevee | 0:1902469bdd2d | 274 | |
lorevee | 0:1902469bdd2d | 275 | |
lorevee | 0:1902469bdd2d | 276 | /* This function enables or disables the new peripheral scanning */ |
lorevee | 0:1902469bdd2d | 277 | void setNewNodesScanning(uint8_t enabled){ |
lorevee | 0:1902469bdd2d | 278 | |
lorevee | 0:1902469bdd2d | 279 | STORE_LE_16(slaveDev.star_config_value,(HAL_GetTick()>>3)); /* Timestamp */ |
lorevee | 0:1902469bdd2d | 280 | |
lorevee | 0:1902469bdd2d | 281 | switch (enabled) { |
lorevee | 0:1902469bdd2d | 282 | case 0x01: |
lorevee | 0:1902469bdd2d | 283 | perDevs.discovery_enabled = true; |
lorevee | 0:1902469bdd2d | 284 | //printf("\r\nScanning enabled (%d)\n", enabled); |
lorevee | 0:1902469bdd2d | 285 | break; |
lorevee | 0:1902469bdd2d | 286 | |
lorevee | 0:1902469bdd2d | 287 | case 0x02: |
lorevee | 0:1902469bdd2d | 288 | perDevs.discovery_enabled = false; |
lorevee | 0:1902469bdd2d | 289 | //printf("\r\nScanning disabled (%d)\n", enabled); |
lorevee | 0:1902469bdd2d | 290 | break; |
lorevee | 0:1902469bdd2d | 291 | |
lorevee | 0:1902469bdd2d | 292 | default: |
lorevee | 0:1902469bdd2d | 293 | //printf("\r\nScanning set to unrecognized value (%d)\n", enabled); |
lorevee | 0:1902469bdd2d | 294 | break; |
lorevee | 0:1902469bdd2d | 295 | } |
lorevee | 0:1902469bdd2d | 296 | |
lorevee | 0:1902469bdd2d | 297 | slaveDev.star_config_value[2] = enabled; |
lorevee | 0:1902469bdd2d | 298 | slaveDev.star_config_value_len = 3; |
lorevee | 0:1902469bdd2d | 299 | //HAL_Delay(300); |
lorevee | 0:1902469bdd2d | 300 | |
lorevee | 0:1902469bdd2d | 301 | /* Notify master for scanning */ |
lorevee | 0:1902469bdd2d | 302 | |
lorevee | 0:1902469bdd2d | 303 | /* Stack busy, solve this */ |
lorevee | 0:1902469bdd2d | 304 | // notifyMaster(slaveDev.star_config_value_len, slaveDev.star_config_value, |
lorevee | 0:1902469bdd2d | 305 | // slaveDev.star_config_char_handle); |
lorevee | 0:1902469bdd2d | 306 | |
lorevee | 0:1902469bdd2d | 307 | } |
lorevee | 0:1902469bdd2d | 308 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 309 | |
lorevee | 0:1902469bdd2d | 310 | |
lorevee | 0:1902469bdd2d | 311 | //NOT USED FOR NOW !! |
lorevee | 0:1902469bdd2d | 312 | /* This function forwards to the peripheral device the command coming from the Cloud */ |
lorevee | 0:1902469bdd2d | 313 | void Forward_Command_To_BlueNRG(uint8_t* data_ptr, uint8_t data_length){ |
lorevee | 0:1902469bdd2d | 314 | |
lorevee | 0:1902469bdd2d | 315 | uint16_t handle; |
lorevee | 0:1902469bdd2d | 316 | uint8_t buffer[4] = {0, 0, 0, 0}; |
lorevee | 0:1902469bdd2d | 317 | uint8_t num, even, odd; |
lorevee | 0:1902469bdd2d | 318 | uint8_t i; |
lorevee | 0:1902469bdd2d | 319 | uint8_t cmd_type; |
lorevee | 0:1902469bdd2d | 320 | |
lorevee | 0:1902469bdd2d | 321 | cmd_type = (data_ptr[0] - '0') << 4 | (data_ptr[1] - '0'); |
lorevee | 0:1902469bdd2d | 322 | //printf("\r\ncommand %d\n", cmd_type); |
lorevee | 0:1902469bdd2d | 323 | |
lorevee | 0:1902469bdd2d | 324 | switch (cmd_type) |
lorevee | 0:1902469bdd2d | 325 | { |
lorevee | 0:1902469bdd2d | 326 | case 0: |
lorevee | 0:1902469bdd2d | 327 | printf("\rScan cmd type (%d)\n", cmd_type); |
lorevee | 0:1902469bdd2d | 328 | handle = slaveDev.star_config_char_handle + 1; |
lorevee | 0:1902469bdd2d | 329 | break; |
lorevee | 0:1902469bdd2d | 330 | case 1: |
lorevee | 0:1902469bdd2d | 331 | printf("\rLED/MIC/PRX cmd type (%d)\n", cmd_type); |
lorevee | 0:1902469bdd2d | 332 | handle = slaveDev.star_data_char_handle + 1; |
lorevee | 0:1902469bdd2d | 333 | break; |
lorevee | 0:1902469bdd2d | 334 | default: |
lorevee | 0:1902469bdd2d | 335 | printf("\rUnknown cmd type (%d)\n", cmd_type); |
lorevee | 0:1902469bdd2d | 336 | return; |
lorevee | 0:1902469bdd2d | 337 | //break; |
lorevee | 0:1902469bdd2d | 338 | } |
lorevee | 0:1902469bdd2d | 339 | |
lorevee | 0:1902469bdd2d | 340 | /** |
lorevee | 0:1902469bdd2d | 341 | * For Scan cmd type: |
lorevee | 0:1902469bdd2d | 342 | * |Value | |
lorevee | 0:1902469bdd2d | 343 | * |1 byte | |
lorevee | 0:1902469bdd2d | 344 | * For LED/MIC/PRX cmd type: |
lorevee | 0:1902469bdd2d | 345 | * |Node ID | Type ID | Value | |
lorevee | 0:1902469bdd2d | 346 | * |2 bytes | 1 byte | x bytes | |
lorevee | 0:1902469bdd2d | 347 | */ |
lorevee | 0:1902469bdd2d | 348 | for (i=2; i<data_length; i++) { |
lorevee | 0:1902469bdd2d | 349 | switch (data_ptr[i]) |
lorevee | 0:1902469bdd2d | 350 | { |
lorevee | 0:1902469bdd2d | 351 | case 'A': |
lorevee | 0:1902469bdd2d | 352 | case 'a': |
lorevee | 0:1902469bdd2d | 353 | num = 10; |
lorevee | 0:1902469bdd2d | 354 | break; |
lorevee | 0:1902469bdd2d | 355 | case 'B': |
lorevee | 0:1902469bdd2d | 356 | case 'b': |
lorevee | 0:1902469bdd2d | 357 | num = 11; |
lorevee | 0:1902469bdd2d | 358 | break; |
lorevee | 0:1902469bdd2d | 359 | case 'C': |
lorevee | 0:1902469bdd2d | 360 | case 'c': |
lorevee | 0:1902469bdd2d | 361 | num = 12; |
lorevee | 0:1902469bdd2d | 362 | break; |
lorevee | 0:1902469bdd2d | 363 | case 'D': |
lorevee | 0:1902469bdd2d | 364 | case 'd': |
lorevee | 0:1902469bdd2d | 365 | num = 13; |
lorevee | 0:1902469bdd2d | 366 | break; |
lorevee | 0:1902469bdd2d | 367 | case 'E': |
lorevee | 0:1902469bdd2d | 368 | case 'e': |
lorevee | 0:1902469bdd2d | 369 | num = 14; |
lorevee | 0:1902469bdd2d | 370 | break; |
lorevee | 0:1902469bdd2d | 371 | case 'F': |
lorevee | 0:1902469bdd2d | 372 | case 'f': |
lorevee | 0:1902469bdd2d | 373 | num = 15; |
lorevee | 0:1902469bdd2d | 374 | break; |
lorevee | 0:1902469bdd2d | 375 | default: |
lorevee | 0:1902469bdd2d | 376 | num = data_ptr[i] - '0'; |
lorevee | 0:1902469bdd2d | 377 | break; |
lorevee | 0:1902469bdd2d | 378 | } |
lorevee | 0:1902469bdd2d | 379 | if (!(i%2)) { |
lorevee | 0:1902469bdd2d | 380 | even = num << 4; |
lorevee | 0:1902469bdd2d | 381 | } |
lorevee | 0:1902469bdd2d | 382 | else { |
lorevee | 0:1902469bdd2d | 383 | odd = num; |
lorevee | 0:1902469bdd2d | 384 | buffer[(i-2)/2] = even | odd; |
lorevee | 0:1902469bdd2d | 385 | } |
lorevee | 0:1902469bdd2d | 386 | } |
lorevee | 0:1902469bdd2d | 387 | |
lorevee | 0:1902469bdd2d | 388 | createAttribute_Modified_CB_Prototype(handle, (data_length-2)/2, buffer); |
lorevee | 0:1902469bdd2d | 389 | } |
lorevee | 0:1902469bdd2d | 390 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 391 | |
lorevee | 0:1902469bdd2d | 392 | |
lorevee | 0:1902469bdd2d | 393 | /* Function used to call AttributeModified_CB outside the callback call */ |
lorevee | 0:1902469bdd2d | 394 | void createAttribute_Modified_CB_Prototype(uint16_t handle, uint8_t data_length, uint8_t *att_data){ |
lorevee | 0:1902469bdd2d | 395 | |
lorevee | 0:1902469bdd2d | 396 | GattWriteCallbackParams paramStruct, *pointerToParam; |
lorevee | 0:1902469bdd2d | 397 | pointerToParam = ¶mStruct; |
lorevee | 0:1902469bdd2d | 398 | |
lorevee | 0:1902469bdd2d | 399 | pointerToParam->handle = handle; |
lorevee | 0:1902469bdd2d | 400 | pointerToParam->len = data_length; |
lorevee | 0:1902469bdd2d | 401 | pointerToParam->data = att_data; |
lorevee | 0:1902469bdd2d | 402 | |
lorevee | 0:1902469bdd2d | 403 | AttributeModified_CB(pointerToParam); |
lorevee | 0:1902469bdd2d | 404 | } |
lorevee | 0:1902469bdd2d | 405 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 406 | |
lorevee | 0:1902469bdd2d | 407 | |
lorevee | 0:1902469bdd2d | 408 | |
lorevee | 0:1902469bdd2d | 409 | |
lorevee | 0:1902469bdd2d | 410 | /* This function is called when a local attribute gets modified */ |
lorevee | 0:1902469bdd2d | 411 | void AttributeModified_CB(const GattWriteCallbackParams* param){ |
lorevee | 0:1902469bdd2d | 412 | // printf("\r\nAttributeModified_CB (%d)\n", perDevs.status);//DEBUG |
lorevee | 0:1902469bdd2d | 413 | |
lorevee | 0:1902469bdd2d | 414 | |
lorevee | 0:1902469bdd2d | 415 | /* Assign prototype vars */ |
lorevee | 0:1902469bdd2d | 416 | uint16_t handle = param->handle; |
lorevee | 0:1902469bdd2d | 417 | //uint8_t data_length = param->len; //not used |
lorevee | 0:1902469bdd2d | 418 | uint8_t *att_data = (uint8_t *)param->data; |
lorevee | 0:1902469bdd2d | 419 | |
lorevee | 0:1902469bdd2d | 420 | |
lorevee | 0:1902469bdd2d | 421 | uint8_t i; |
lorevee | 0:1902469bdd2d | 422 | uint16_t conn_handle; |
lorevee | 0:1902469bdd2d | 423 | uint16_t attr_handle; |
lorevee | 0:1902469bdd2d | 424 | uint8_t value_len; |
lorevee | 0:1902469bdd2d | 425 | uint8_t attr_value[6]; |
lorevee | 0:1902469bdd2d | 426 | char* mems; |
lorevee | 0:1902469bdd2d | 427 | |
lorevee | 0:1902469bdd2d | 428 | if (handle == slaveDev.star_config_char_handle + 1) { |
lorevee | 0:1902469bdd2d | 429 | |
lorevee | 0:1902469bdd2d | 430 | perDevs.status = ALL_DATA_READ; |
lorevee | 0:1902469bdd2d | 431 | if (att_data[0]==0x01) { |
lorevee | 0:1902469bdd2d | 432 | /* Disabling all previously enabled notifications */ |
lorevee | 0:1902469bdd2d | 433 | disableAllNotifications(); |
lorevee | 0:1902469bdd2d | 434 | }//if |
lorevee | 0:1902469bdd2d | 435 | setNewNodesScanning(att_data[0]); |
lorevee | 0:1902469bdd2d | 436 | |
lorevee | 0:1902469bdd2d | 437 | |
lorevee | 0:1902469bdd2d | 438 | } else if (handle == slaveDev.star_config_char_handle + 2) { |
lorevee | 0:1902469bdd2d | 439 | if (att_data[0]==0x01) { |
lorevee | 0:1902469bdd2d | 440 | //printf("\r\nEnable scanning notification\n"); |
lorevee | 0:1902469bdd2d | 441 | STORE_LE_16(slaveDev.star_config_value,(HAL_GetTick()>>3)); /* Timestamp */ |
lorevee | 0:1902469bdd2d | 442 | slaveDev.star_config_value[2] = perDevs.discovery_enabled; |
lorevee | 0:1902469bdd2d | 443 | slaveDev.star_config_value_len = 3; |
lorevee | 0:1902469bdd2d | 444 | |
lorevee | 0:1902469bdd2d | 445 | /* send the status of the scanning when notifications are enabled */ |
lorevee | 0:1902469bdd2d | 446 | notifyMaster(slaveDev.star_config_value_len, slaveDev.star_config_value, |
lorevee | 0:1902469bdd2d | 447 | slaveDev.star_config_char_handle); |
lorevee | 0:1902469bdd2d | 448 | |
lorevee | 0:1902469bdd2d | 449 | /* enable here the data notifications since sometimes the relative command gets lost (FIXME) */ |
lorevee | 0:1902469bdd2d | 450 | //printf("\r\nEnable data notification (0)\n"); |
lorevee | 0:1902469bdd2d | 451 | slaveDev.star_data_char_notify = 1; |
lorevee | 0:1902469bdd2d | 452 | |
lorevee | 0:1902469bdd2d | 453 | } else if (att_data[0]==0x00) { |
lorevee | 0:1902469bdd2d | 454 | //printf("\r\nDisable scanning notification\n"); |
lorevee | 0:1902469bdd2d | 455 | } |
lorevee | 0:1902469bdd2d | 456 | |
lorevee | 0:1902469bdd2d | 457 | } else if (handle == slaveDev.star_data_char_handle + 2) { |
lorevee | 0:1902469bdd2d | 458 | if (att_data[0]==0x01) { |
lorevee | 0:1902469bdd2d | 459 | //printf("\r\nEnable data notification (1)\n"); |
lorevee | 0:1902469bdd2d | 460 | slaveDev.star_data_char_notify = 1; |
lorevee | 0:1902469bdd2d | 461 | |
lorevee | 0:1902469bdd2d | 462 | |
lorevee | 0:1902469bdd2d | 463 | } else if (att_data[0]==0x00) { |
lorevee | 0:1902469bdd2d | 464 | //printf("\r\nDisable data notification\n"); |
lorevee | 0:1902469bdd2d | 465 | slaveDev.star_data_char_notify = 0; |
lorevee | 0:1902469bdd2d | 466 | |
lorevee | 0:1902469bdd2d | 467 | } |
lorevee | 0:1902469bdd2d | 468 | |
lorevee | 0:1902469bdd2d | 469 | } else if (handle == slaveDev.star_data_char_handle + 1) { |
lorevee | 0:1902469bdd2d | 470 | |
lorevee | 0:1902469bdd2d | 471 | /* |
lorevee | 0:1902469bdd2d | 472 | * Forward the command to the proper peripheral node. |
lorevee | 0:1902469bdd2d | 473 | * It can be: |
lorevee | 0:1902469bdd2d | 474 | * - the ON/OFF of a LED |
lorevee | 0:1902469bdd2d | 475 | * - the notification enabling/disabling for a MIC Level or a Proximity Sensor |
lorevee | 0:1902469bdd2d | 476 | * The coming data are received according to the following format: |
lorevee | 0:1902469bdd2d | 477 | * |Node ID | Type ID | value | |
lorevee | 0:1902469bdd2d | 478 | * |2 bytes | 1 byte | x bytes | |
lorevee | 0:1902469bdd2d | 479 | */ |
lorevee | 0:1902469bdd2d | 480 | |
lorevee | 0:1902469bdd2d | 481 | i = Get_Device_Index_From_Addr(att_data); |
lorevee | 0:1902469bdd2d | 482 | if ((i < MAX_NUM_OF_NODES) && (!perDevs.is_disconnected[i]) && (perDevs.cfg_char_handle[i] != 0)) { |
lorevee | 0:1902469bdd2d | 483 | conn_handle = perDevs.connection_handle[i]; |
lorevee | 0:1902469bdd2d | 484 | |
lorevee | 0:1902469bdd2d | 485 | switch (att_data[2]) { |
lorevee | 0:1902469bdd2d | 486 | |
lorevee | 0:1902469bdd2d | 487 | |
lorevee | 0:1902469bdd2d | 488 | //LED_TYPE_ID |
lorevee | 0:1902469bdd2d | 489 | case LED_TYPE_ID: |
lorevee | 0:1902469bdd2d | 490 | attr_handle = perDevs.cfg_char_handle[i] + 1; |
lorevee | 0:1902469bdd2d | 491 | value_len = 5; /* 4 bytes for the feature mask + 1 byte for the command (0=ON, 1=OFF) */ |
lorevee | 0:1902469bdd2d | 492 | attr_value[0] = (uint8_t)(((uint32_t)FEATURE_MASK_LED_EVENTS) >> 24); |
lorevee | 0:1902469bdd2d | 493 | attr_value[1] = (uint8_t)(((uint32_t)FEATURE_MASK_LED_EVENTS) >> 16); |
lorevee | 0:1902469bdd2d | 494 | attr_value[2] = (uint8_t)(((uint32_t)FEATURE_MASK_LED_EVENTS) >> 8); |
lorevee | 0:1902469bdd2d | 495 | attr_value[3] = (uint8_t)(((uint32_t)FEATURE_MASK_LED_EVENTS)); |
lorevee | 0:1902469bdd2d | 496 | attr_value[4] = att_data[3]; |
lorevee | 0:1902469bdd2d | 497 | |
lorevee | 0:1902469bdd2d | 498 | writeCharacValueWithoutResp(conn_handle, attr_handle, value_len, attr_value); |
lorevee | 0:1902469bdd2d | 499 | |
lorevee | 0:1902469bdd2d | 500 | perDevs.readDeviceIdx = i; |
lorevee | 0:1902469bdd2d | 501 | break; |
lorevee | 0:1902469bdd2d | 502 | |
lorevee | 0:1902469bdd2d | 503 | |
lorevee | 0:1902469bdd2d | 504 | |
lorevee | 0:1902469bdd2d | 505 | //MICLEVEL_TYPE_ID |
lorevee | 0:1902469bdd2d | 506 | case MICLEVEL_TYPE_ID: |
lorevee | 0:1902469bdd2d | 507 | //perDevs.status = CHANGE_NOTIFICATION_STATUS;//47 |
lorevee | 0:1902469bdd2d | 508 | |
lorevee | 0:1902469bdd2d | 509 | if (readCompleted == 0){ |
lorevee | 0:1902469bdd2d | 510 | notificationPending = 1; |
lorevee | 0:1902469bdd2d | 511 | |
lorevee | 0:1902469bdd2d | 512 | /* Fill the temp struct */ |
lorevee | 0:1902469bdd2d | 513 | notifyP->att_data = att_data; |
lorevee | 0:1902469bdd2d | 514 | notifyP->attr_value = attr_value; |
lorevee | 0:1902469bdd2d | 515 | notifyP->conn_handle = conn_handle; |
lorevee | 0:1902469bdd2d | 516 | notifyP->i = i; |
lorevee | 0:1902469bdd2d | 517 | notifyP->feature_mask = FEATURE_MASK_MIC; |
lorevee | 0:1902469bdd2d | 518 | notifyP->frequency = notification_freq; |
lorevee | 0:1902469bdd2d | 519 | |
lorevee | 0:1902469bdd2d | 520 | /* Then, call the Change_Notification_Status from the readCallback with these params */ |
lorevee | 0:1902469bdd2d | 521 | |
lorevee | 0:1902469bdd2d | 522 | }else if (readCompleted == 1) { |
lorevee | 1:110b5e896bc9 | 523 | //notificationPending = 0; |
lorevee | 0:1902469bdd2d | 524 | Change_Notification_Status(att_data, attr_value, conn_handle, i, FEATURE_MASK_MIC, notification_freq); |
lorevee | 0:1902469bdd2d | 525 | } |
lorevee | 0:1902469bdd2d | 526 | perDevs.prx_on[i] = attr_value[0]; |
lorevee | 0:1902469bdd2d | 527 | printf("\r\nMIC notifications [%d] %s (status %d, discovery %d)\n", i, (attr_value[0]==1 ? "ON" : "OFF"), perDevs.status, perDevs.discovery_enabled); |
lorevee | 0:1902469bdd2d | 528 | |
lorevee | 0:1902469bdd2d | 529 | #if SCAN_AFTER_NOTIFICATION |
lorevee | 0:1902469bdd2d | 530 | /* Restart peripheral discovery and notification*/ |
lorevee | 0:1902469bdd2d | 531 | if (attr_value[0]!=1){ |
lorevee | 0:1902469bdd2d | 532 | perDevs.discovery_enabled = 1; |
lorevee | 0:1902469bdd2d | 533 | setNewNodesScanning(0x01); |
lorevee | 0:1902469bdd2d | 534 | //HAL_Delay(300); |
lorevee | 0:1902469bdd2d | 535 | } |
lorevee | 0:1902469bdd2d | 536 | #endif |
lorevee | 0:1902469bdd2d | 537 | break; |
lorevee | 0:1902469bdd2d | 538 | |
lorevee | 0:1902469bdd2d | 539 | |
lorevee | 0:1902469bdd2d | 540 | |
lorevee | 0:1902469bdd2d | 541 | |
lorevee | 0:1902469bdd2d | 542 | |
lorevee | 0:1902469bdd2d | 543 | //PRX_TYPE_ID |
lorevee | 0:1902469bdd2d | 544 | case PRX_TYPE_ID: |
lorevee | 0:1902469bdd2d | 545 | //perDevs.status = CHANGE_NOTIFICATION_STATUS;//47 |
lorevee | 0:1902469bdd2d | 546 | |
lorevee | 0:1902469bdd2d | 547 | if (readCompleted == 0){ |
lorevee | 0:1902469bdd2d | 548 | notificationPending = 1; |
lorevee | 0:1902469bdd2d | 549 | |
lorevee | 0:1902469bdd2d | 550 | /* Fill the temp struct */ |
lorevee | 0:1902469bdd2d | 551 | notifyP->att_data = att_data; |
lorevee | 0:1902469bdd2d | 552 | notifyP->attr_value = attr_value; |
lorevee | 0:1902469bdd2d | 553 | notifyP->conn_handle = conn_handle; |
lorevee | 0:1902469bdd2d | 554 | notifyP->i = i; |
lorevee | 0:1902469bdd2d | 555 | notifyP->feature_mask = FEATURE_MASK_PROX; |
lorevee | 1:110b5e896bc9 | 556 | notifyP->frequency = notification_freq*SENDING_INTERVAL_100MS_MULTIPLE; |
lorevee | 0:1902469bdd2d | 557 | |
lorevee | 0:1902469bdd2d | 558 | /* Then, call the Change_Notification_Status from the readCallback with these params */ |
lorevee | 0:1902469bdd2d | 559 | |
lorevee | 0:1902469bdd2d | 560 | }else if (readCompleted == 1) { |
lorevee | 1:110b5e896bc9 | 561 | //notificationPending = 0; |
lorevee | 1:110b5e896bc9 | 562 | Change_Notification_Status(att_data, attr_value, conn_handle, i, FEATURE_MASK_PROX, notification_freq*SENDING_INTERVAL_100MS_MULTIPLE); |
lorevee | 0:1902469bdd2d | 563 | } |
lorevee | 0:1902469bdd2d | 564 | perDevs.prx_on[i] = attr_value[0]; |
lorevee | 0:1902469bdd2d | 565 | printf("\r\nPRX notifications [%d] %s (status %d)\n", i, (attr_value[0]==1 ? "ON" : "OFF"), perDevs.status); |
lorevee | 0:1902469bdd2d | 566 | |
lorevee | 0:1902469bdd2d | 567 | #if SCAN_AFTER_NOTIFICATION |
lorevee | 0:1902469bdd2d | 568 | /* Restart peripheral discovery and notification*/ |
lorevee | 0:1902469bdd2d | 569 | if (attr_value[0]!=1){ |
lorevee | 0:1902469bdd2d | 570 | perDevs.discovery_enabled = 1; |
lorevee | 0:1902469bdd2d | 571 | setNewNodesScanning(0x01); |
lorevee | 0:1902469bdd2d | 572 | //HAL_Delay(300); |
lorevee | 0:1902469bdd2d | 573 | } |
lorevee | 0:1902469bdd2d | 574 | #endif |
lorevee | 0:1902469bdd2d | 575 | break; |
lorevee | 0:1902469bdd2d | 576 | |
lorevee | 0:1902469bdd2d | 577 | |
lorevee | 0:1902469bdd2d | 578 | |
lorevee | 0:1902469bdd2d | 579 | //ACC_TYPE_ID |
lorevee | 0:1902469bdd2d | 580 | //GYR_TYPE_ID |
lorevee | 0:1902469bdd2d | 581 | //MAG_TYPE_ID |
lorevee | 0:1902469bdd2d | 582 | case ACC_TYPE_ID: |
lorevee | 0:1902469bdd2d | 583 | case GYR_TYPE_ID: |
lorevee | 0:1902469bdd2d | 584 | case MAG_TYPE_ID: |
lorevee | 0:1902469bdd2d | 585 | //perDevs.status = CHANGE_NOTIFICATION_STATUS;//47 |
lorevee | 0:1902469bdd2d | 586 | |
lorevee | 0:1902469bdd2d | 587 | if (readCompleted == 0){ |
lorevee | 0:1902469bdd2d | 588 | notificationPending = 1; |
lorevee | 0:1902469bdd2d | 589 | |
lorevee | 0:1902469bdd2d | 590 | /* Fill the temp struct */ |
lorevee | 0:1902469bdd2d | 591 | notifyP->att_data = att_data; |
lorevee | 0:1902469bdd2d | 592 | notifyP->attr_value = attr_value; |
lorevee | 0:1902469bdd2d | 593 | notifyP->conn_handle = conn_handle; |
lorevee | 0:1902469bdd2d | 594 | notifyP->i = i; |
lorevee | 0:1902469bdd2d | 595 | notifyP->feature_mask = FEATURE_MASK_ACC; |
lorevee | 0:1902469bdd2d | 596 | notifyP->frequency = SENDING_INTERVAL_100MS_MULTIPLE; |
lorevee | 0:1902469bdd2d | 597 | |
lorevee | 0:1902469bdd2d | 598 | |
lorevee | 0:1902469bdd2d | 599 | /* Then, call the Change_Notification_Status from the readCallback with these params */ |
lorevee | 0:1902469bdd2d | 600 | |
lorevee | 0:1902469bdd2d | 601 | }else if (readCompleted == 1) { |
lorevee | 1:110b5e896bc9 | 602 | //notificationPending = 0; |
lorevee | 0:1902469bdd2d | 603 | Change_Notification_Status(att_data, attr_value, conn_handle, i, FEATURE_MASK_ACC, SENDING_INTERVAL_100MS_MULTIPLE); |
lorevee | 0:1902469bdd2d | 604 | } |
lorevee | 0:1902469bdd2d | 605 | perDevs.agm_on[i] = attr_value[0]; |
lorevee | 0:1902469bdd2d | 606 | |
lorevee | 0:1902469bdd2d | 607 | if (att_data[2] == 0x09) { |
lorevee | 0:1902469bdd2d | 608 | perDevs.acc_event_enabled = attr_value[0]; |
lorevee | 0:1902469bdd2d | 609 | mems = "ACC"; |
lorevee | 0:1902469bdd2d | 610 | |
lorevee | 0:1902469bdd2d | 611 | } else if (att_data[2] == 0x0A) { |
lorevee | 0:1902469bdd2d | 612 | perDevs.gyr_event_enabled = attr_value[0]; |
lorevee | 0:1902469bdd2d | 613 | mems = "GYR"; |
lorevee | 0:1902469bdd2d | 614 | |
lorevee | 0:1902469bdd2d | 615 | } else if (att_data[2] == 0x0B) { |
lorevee | 0:1902469bdd2d | 616 | perDevs.mag_event_enabled = attr_value[0]; |
lorevee | 0:1902469bdd2d | 617 | mems = "MAG"; |
lorevee | 0:1902469bdd2d | 618 | } |
lorevee | 0:1902469bdd2d | 619 | |
lorevee | 0:1902469bdd2d | 620 | printf("\r\nAGM notifications [%d] %s (%s) (status %d)\n", i, (attr_value[0]==1 ? "ON" : "OFF"), mems, perDevs.status); |
lorevee | 0:1902469bdd2d | 621 | #if SCAN_AFTER_NOTIFICATION |
lorevee | 0:1902469bdd2d | 622 | /* Restart peripheral discovery and notification*/ |
lorevee | 0:1902469bdd2d | 623 | if (attr_value[0]!=1){ |
lorevee | 0:1902469bdd2d | 624 | perDevs.discovery_enabled = 1; |
lorevee | 0:1902469bdd2d | 625 | setNewNodesScanning(0x01); |
lorevee | 0:1902469bdd2d | 626 | //HAL_Delay(300); |
lorevee | 0:1902469bdd2d | 627 | } |
lorevee | 0:1902469bdd2d | 628 | #endif |
lorevee | 0:1902469bdd2d | 629 | break; |
lorevee | 0:1902469bdd2d | 630 | |
lorevee | 0:1902469bdd2d | 631 | |
lorevee | 0:1902469bdd2d | 632 | |
lorevee | 0:1902469bdd2d | 633 | //SFUSION_TYPE_ID |
lorevee | 0:1902469bdd2d | 634 | case SFUSION_TYPE_ID: |
lorevee | 0:1902469bdd2d | 635 | //perDevs.status = CHANGE_NOTIFICATION_STATUS;//47 |
lorevee | 0:1902469bdd2d | 636 | |
lorevee | 0:1902469bdd2d | 637 | if (readCompleted == 0){ |
lorevee | 0:1902469bdd2d | 638 | notificationPending = 1; |
lorevee | 0:1902469bdd2d | 639 | |
lorevee | 0:1902469bdd2d | 640 | /* Fill the temp struct */ |
lorevee | 0:1902469bdd2d | 641 | notifyP->att_data = att_data; |
lorevee | 0:1902469bdd2d | 642 | notifyP->attr_value = attr_value; |
lorevee | 0:1902469bdd2d | 643 | notifyP->conn_handle = conn_handle; |
lorevee | 0:1902469bdd2d | 644 | notifyP->i = i; |
lorevee | 0:1902469bdd2d | 645 | notifyP->feature_mask = FEATURE_MASK_SENSORFUSION; |
lorevee | 0:1902469bdd2d | 646 | notifyP->frequency = SENDING_INTERVAL_100MS_MULTIPLE; |
lorevee | 0:1902469bdd2d | 647 | |
lorevee | 0:1902469bdd2d | 648 | /* Then, call the Change_Notification_Status from the readCallback with these params */ |
lorevee | 0:1902469bdd2d | 649 | |
lorevee | 0:1902469bdd2d | 650 | }else if (readCompleted == 1) { |
lorevee | 1:110b5e896bc9 | 651 | //notificationPending = 0; |
lorevee | 0:1902469bdd2d | 652 | Change_Notification_Status(att_data, attr_value, conn_handle, i, FEATURE_MASK_SENSORFUSION, SENDING_INTERVAL_100MS_MULTIPLE); |
lorevee | 0:1902469bdd2d | 653 | } |
lorevee | 0:1902469bdd2d | 654 | |
lorevee | 0:1902469bdd2d | 655 | perDevs.sfusion_on[i] = attr_value[0]; |
lorevee | 0:1902469bdd2d | 656 | printf("\r\nSFUSION notifications [%d] %s (status %d)\n", i, (attr_value[0]==1 ? "ON" : "OFF"), perDevs.status); |
lorevee | 0:1902469bdd2d | 657 | |
lorevee | 0:1902469bdd2d | 658 | #if SCAN_AFTER_NOTIFICATION |
lorevee | 0:1902469bdd2d | 659 | /* Restart peripheral discovery and notification*/ |
lorevee | 0:1902469bdd2d | 660 | if (attr_value[0]!=1){ |
lorevee | 0:1902469bdd2d | 661 | perDevs.discovery_enabled = 1; |
lorevee | 0:1902469bdd2d | 662 | setNewNodesScanning(0x01); |
lorevee | 0:1902469bdd2d | 663 | //HAL_Delay(300); |
lorevee | 0:1902469bdd2d | 664 | |
lorevee | 0:1902469bdd2d | 665 | } |
lorevee | 0:1902469bdd2d | 666 | #endif |
lorevee | 0:1902469bdd2d | 667 | break; |
lorevee | 0:1902469bdd2d | 668 | } |
lorevee | 0:1902469bdd2d | 669 | }//if |
lorevee | 0:1902469bdd2d | 670 | }//if-main |
lorevee | 0:1902469bdd2d | 671 | |
lorevee | 0:1902469bdd2d | 672 | |
lorevee | 0:1902469bdd2d | 673 | } |
lorevee | 0:1902469bdd2d | 674 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 675 | |
lorevee | 0:1902469bdd2d | 676 | |
lorevee | 0:1902469bdd2d | 677 | |
lorevee | 0:1902469bdd2d | 678 | |
lorevee | 0:1902469bdd2d | 679 | /* Retrieve the device index from the peripheral device address */ |
lorevee | 0:1902469bdd2d | 680 | uint8_t Get_Device_Index_From_Addr(uint8_t *addr){ |
lorevee | 0:1902469bdd2d | 681 | |
lorevee | 0:1902469bdd2d | 682 | uint8_t i; |
lorevee | 0:1902469bdd2d | 683 | |
lorevee | 0:1902469bdd2d | 684 | for (i=0; i<MAX_NUM_OF_NODES; i++) { |
lorevee | 0:1902469bdd2d | 685 | |
lorevee | 0:1902469bdd2d | 686 | if ((perDevs.devInfo[i].bdaddr[NODE_ID_B2] == addr[0]) && (perDevs.devInfo[i].bdaddr[NODE_ID_B1] == addr[1])) { |
lorevee | 0:1902469bdd2d | 687 | return i; |
lorevee | 0:1902469bdd2d | 688 | } |
lorevee | 0:1902469bdd2d | 689 | } |
lorevee | 0:1902469bdd2d | 690 | return MAX_NUM_OF_NODES; |
lorevee | 0:1902469bdd2d | 691 | } |
lorevee | 0:1902469bdd2d | 692 | /*----------------------------------------------------------------------------*/ |
lorevee | 0:1902469bdd2d | 693 | |
lorevee | 0:1902469bdd2d | 694 | |
lorevee | 0:1902469bdd2d | 695 | |
lorevee | 0:1902469bdd2d | 696 | |
lorevee | 0:1902469bdd2d | 697 | /** |
lorevee | 0:1902469bdd2d | 698 | * @brief This function is called to Enable/Disable MIC/PRX/AGM/SFusion notifications |
lorevee | 0:1902469bdd2d | 699 | * @param att_data : pointer to the modified attribute data |
lorevee | 0:1902469bdd2d | 700 | * @param connection handle |
lorevee | 0:1902469bdd2d | 701 | * @param peripheral device index |
lorevee | 0:1902469bdd2d | 702 | * @param feature mask |
lorevee | 0:1902469bdd2d | 703 | * @param notification frequency |
lorevee | 0:1902469bdd2d | 704 | * @retval None |
lorevee | 0:1902469bdd2d | 705 | */ |
lorevee | 0:1902469bdd2d | 706 | void Change_Notification_Status(uint8_t *att_data, uint8_t *attr_value, uint16_t conn_handle, uint8_t i, |
lorevee | 0:1902469bdd2d | 707 | uint32_t feature_mask, uint8_t frequency) { |
lorevee | 1:110b5e896bc9 | 708 | //printf("\r\nChange_Notification_Status (status: %d) (read: %s) (write: %s)\n", perDevs.status, (readCompleted == 1 ? "completed" : "pending"),(writeDescriptorCompleted == 1 ? "completed" : "pending"));//DEBUG |
lorevee | 1:110b5e896bc9 | 709 | |
lorevee | 0:1902469bdd2d | 710 | |
lorevee | 0:1902469bdd2d | 711 | uint8_t value_len; |
lorevee | 0:1902469bdd2d | 712 | uint16_t attr_handle; |
lorevee | 0:1902469bdd2d | 713 | |
lorevee | 0:1902469bdd2d | 714 | |
lorevee | 0:1902469bdd2d | 715 | if (att_data[3] == 1) { |
lorevee | 0:1902469bdd2d | 716 | |
lorevee | 0:1902469bdd2d | 717 | /* Setting notification frequency (wait of 2s for writing op)*/ |
lorevee | 0:1902469bdd2d | 718 | setNotificationProperty(conn_handle, i, feature_mask, NOTIFICATION_FREQ_CMD, frequency); |
lorevee | 0:1902469bdd2d | 719 | |
lorevee | 0:1902469bdd2d | 720 | /* Stopping the scanning for new peripheral nodes */ |
lorevee | 0:1902469bdd2d | 721 | if (perDevs.discovery_enabled) { |
lorevee | 0:1902469bdd2d | 722 | //Disable scanning when notification is enabled |
lorevee | 0:1902469bdd2d | 723 | setNewNodesScanning(0x02); |
lorevee | 0:1902469bdd2d | 724 | } |
lorevee | 0:1902469bdd2d | 725 | |
lorevee | 0:1902469bdd2d | 726 | /* Disabling all previously enabled notifications */ |
lorevee | 0:1902469bdd2d | 727 | disableAllNotifications(); |
lorevee | 0:1902469bdd2d | 728 | |
lorevee | 0:1902469bdd2d | 729 | }//if |
lorevee | 0:1902469bdd2d | 730 | |
lorevee | 0:1902469bdd2d | 731 | |
lorevee | 0:1902469bdd2d | 732 | |
lorevee | 0:1902469bdd2d | 733 | |
lorevee | 0:1902469bdd2d | 734 | /* Enabling/Disabling notifications */ |
lorevee | 0:1902469bdd2d | 735 | value_len = 2; |
lorevee | 0:1902469bdd2d | 736 | attr_value[0] = att_data[3]; |
lorevee | 0:1902469bdd2d | 737 | |
lorevee | 0:1902469bdd2d | 738 | if (feature_mask==FEATURE_MASK_MIC){ |
lorevee | 0:1902469bdd2d | 739 | attr_handle = perDevs.mic_char_handle[i] + 2; |
lorevee | 0:1902469bdd2d | 740 | perDevs.mic_event_enabled = attr_value[0]; |
lorevee | 0:1902469bdd2d | 741 | |
lorevee | 0:1902469bdd2d | 742 | } else if (feature_mask==FEATURE_MASK_PROX){ |
lorevee | 0:1902469bdd2d | 743 | attr_handle = perDevs.prx_char_handle[i] + 2; |
lorevee | 0:1902469bdd2d | 744 | perDevs.prx_event_enabled = attr_value[0]; |
lorevee | 0:1902469bdd2d | 745 | |
lorevee | 0:1902469bdd2d | 746 | } else if (feature_mask==FEATURE_MASK_ACC){ |
lorevee | 0:1902469bdd2d | 747 | attr_handle = perDevs.agm_char_handle[i] + 2; |
lorevee | 0:1902469bdd2d | 748 | perDevs.agm_event_enabled = attr_value[0]; |
lorevee | 0:1902469bdd2d | 749 | |
lorevee | 0:1902469bdd2d | 750 | } else if (feature_mask==FEATURE_MASK_SENSORFUSION){ |
lorevee | 0:1902469bdd2d | 751 | attr_handle = perDevs.sfusion_char_handle[i] + 2; |
lorevee | 0:1902469bdd2d | 752 | perDevs.sfusion_event_enabled = attr_value[0]; |
lorevee | 0:1902469bdd2d | 753 | } |
lorevee | 0:1902469bdd2d | 754 | |
lorevee | 0:1902469bdd2d | 755 | |
lorevee | 0:1902469bdd2d | 756 | // if ((discoveryCompleted == 1)){ |
lorevee | 0:1902469bdd2d | 757 | |
lorevee | 0:1902469bdd2d | 758 | ble_error_t err; |
lorevee | 0:1902469bdd2d | 759 | |
lorevee | 0:1902469bdd2d | 760 | writeDescriptorCompleted=0; |
lorevee | 0:1902469bdd2d | 761 | err = writeCharacDescriptorWithError(conn_handle, attr_handle, value_len, attr_value); |
lorevee | 0:1902469bdd2d | 762 | |
lorevee | 0:1902469bdd2d | 763 | if (err != BLE_ERROR_NONE){ |
lorevee | 0:1902469bdd2d | 764 | writeDescriptorCompleted=1; |
lorevee | 0:1902469bdd2d | 765 | printf("\r\nERROR Enabling/Disabling Notification (err: %d) (stat: %d)\n", err, perDevs.status); |
lorevee | 1:110b5e896bc9 | 766 | |
lorevee | 0:1902469bdd2d | 767 | } |
lorevee | 0:1902469bdd2d | 768 | |
lorevee | 0:1902469bdd2d | 769 | |
lorevee | 0:1902469bdd2d | 770 | |
lorevee | 0:1902469bdd2d | 771 | |
lorevee | 0:1902469bdd2d | 772 | |
lorevee | 0:1902469bdd2d | 773 | /* WUP notification enable/disable */ |
lorevee | 1:110b5e896bc9 | 774 | if(attr_value[0]==0x00){ |
lorevee | 0:1902469bdd2d | 775 | // for (uint8_t j=0; j<(perDevs.connDevices+perDevs.discDevices); j++) { |
lorevee | 0:1902469bdd2d | 776 | // if (!perDevs.wup_event[j] && perDevs.devInfo[j].dev_v == NODE_ME1 && perDevs.is_connected[j]) { |
lorevee | 0:1902469bdd2d | 777 | // attr_handle = perDevs.wup_char_handle[j] + 2; |
lorevee | 0:1902469bdd2d | 778 | // attr_value[0] = 0x01; |
lorevee | 0:1902469bdd2d | 779 | // |
lorevee | 0:1902469bdd2d | 780 | // setNotificationProperty(perDevs.connection_handle[j], j, FEATURE_MASK_WAKEUP_EVENTS, WAKEUP_NOTIFICATION_CMD, 1); |
lorevee | 0:1902469bdd2d | 781 | // |
lorevee | 0:1902469bdd2d | 782 | // if (discoveryCompleted == 1){ |
lorevee | 0:1902469bdd2d | 783 | // |
lorevee | 0:1902469bdd2d | 784 | // writeDescriptorCompleted=0; |
lorevee | 0:1902469bdd2d | 785 | // ble_error_t wupErrOn = writeCharacDescriptorWithError(perDevs.connection_handle[j], attr_handle, value_len, attr_value); |
lorevee | 0:1902469bdd2d | 786 | // |
lorevee | 0:1902469bdd2d | 787 | // if (wupErrOn == BLE_ERROR_NONE){ |
lorevee | 0:1902469bdd2d | 788 | // perDevs.wup_event_enabled = 1; |
lorevee | 0:1902469bdd2d | 789 | // perDevs.wup_event[j] = 1; |
lorevee | 0:1902469bdd2d | 790 | // printf("\r\nWUP notification on node [%d] ON\n", j); |
lorevee | 0:1902469bdd2d | 791 | // |
lorevee | 0:1902469bdd2d | 792 | // } else { |
lorevee | 0:1902469bdd2d | 793 | // printf("\r\nWrite WUP char descriptor failed! (%d)\n", wupErrOn); |
lorevee | 0:1902469bdd2d | 794 | // |
lorevee | 0:1902469bdd2d | 795 | // }//if-else |
lorevee | 0:1902469bdd2d | 796 | // writeDescriptorCompleted=1; |
lorevee | 0:1902469bdd2d | 797 | // |
lorevee | 0:1902469bdd2d | 798 | // }//if-else-discovery-completed |
lorevee | 0:1902469bdd2d | 799 | // }//if |
lorevee | 0:1902469bdd2d | 800 | // }//for |
lorevee | 0:1902469bdd2d | 801 | // |
lorevee | 0:1902469bdd2d | 802 | // |
lorevee | 0:1902469bdd2d | 803 | // if (perDevs.wup_event_enabled == 1) |
lorevee | 0:1902469bdd2d | 804 | // //printf("\r\nAll WUP notifications turned ON\n");//DEBUG |
lorevee | 0:1902469bdd2d | 805 | // perDevs.status = ALL_DATA_READ; |
lorevee | 1:110b5e896bc9 | 806 | |
lorevee | 1:110b5e896bc9 | 807 | |
lorevee | 1:110b5e896bc9 | 808 | } else{ |
lorevee | 1:110b5e896bc9 | 809 | for (uint8_t j=0; j<(perDevs.connDevices+perDevs.discDevices); j++) { |
lorevee | 1:110b5e896bc9 | 810 | if ((perDevs.wup_event[j]) && (perDevs.devInfo[j].dev_v == NODE_ME1) && (perDevs.is_connected[j])) { |
lorevee | 1:110b5e896bc9 | 811 | attr_handle = perDevs.wup_char_handle[j] + 2; |
lorevee | 1:110b5e896bc9 | 812 | attr_value[0] = 0x00; |
lorevee | 1:110b5e896bc9 | 813 | |
lorevee | 1:110b5e896bc9 | 814 | |
lorevee | 1:110b5e896bc9 | 815 | if (discoveryCompleted == 1){ |
lorevee | 1:110b5e896bc9 | 816 | |
lorevee | 1:110b5e896bc9 | 817 | writeDescriptorCompleted=0; |
lorevee | 1:110b5e896bc9 | 818 | ble_error_t wupErrOff = writeCharacDescriptorWithError(perDevs.connection_handle[j], attr_handle, value_len, attr_value); |
lorevee | 1:110b5e896bc9 | 819 | |
lorevee | 1:110b5e896bc9 | 820 | if (wupErrOff == BLE_ERROR_NONE){ |
lorevee | 1:110b5e896bc9 | 821 | perDevs.wup_event_enabled = 0; |
lorevee | 1:110b5e896bc9 | 822 | perDevs.wup_event[j] = 0; |
lorevee | 1:110b5e896bc9 | 823 | printf("\r\nWUP notification on node [%d] OFF\n", j); |
lorevee | 1:110b5e896bc9 | 824 | |
lorevee | 1:110b5e896bc9 | 825 | } else { |
lorevee | 1:110b5e896bc9 | 826 | printf("\r\nWrite WUP char descriptor failed! (%d)\n", wupErrOff); |
lorevee | 1:110b5e896bc9 | 827 | |
lorevee | 1:110b5e896bc9 | 828 | } |
lorevee | 1:110b5e896bc9 | 829 | writeDescriptorCompleted=1; |
lorevee | 1:110b5e896bc9 | 830 | |
lorevee | 1:110b5e896bc9 | 831 | }//if-discovery-completed |
lorevee | 1:110b5e896bc9 | 832 | }//if |
lorevee | 1:110b5e896bc9 | 833 | }//for |
lorevee | 1:110b5e896bc9 | 834 | |
lorevee | 1:110b5e896bc9 | 835 | perDevs.status = NOTIFICATIONS_DATA_READ; |
lorevee | 1:110b5e896bc9 | 836 | |
lorevee | 1:110b5e896bc9 | 837 | }//if-else-wup |
lorevee | 0:1902469bdd2d | 838 | |
lorevee | 0:1902469bdd2d | 839 | attr_value[0] = att_data[3]; |
lorevee | 0:1902469bdd2d | 840 | perDevs.readDeviceIdx = i; |
lorevee | 0:1902469bdd2d | 841 | |
lorevee | 0:1902469bdd2d | 842 | notificationPending = 0; |
lorevee | 0:1902469bdd2d | 843 | |
lorevee | 0:1902469bdd2d | 844 | //Return to connectionProcess |
lorevee | 0:1902469bdd2d | 845 | perDevs.status = CONN_INIT; |
lorevee | 0:1902469bdd2d | 846 | |
lorevee | 0:1902469bdd2d | 847 | |
lorevee | 0:1902469bdd2d | 848 | |
lorevee | 0:1902469bdd2d | 849 | |
lorevee | 0:1902469bdd2d | 850 | } |
lorevee | 0:1902469bdd2d | 851 | /*----------------------------------------------------------------------------*/ |