Filippo Casamassima / Nucleo_blueNRG

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sensor_service.c Source File

sensor_service.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    sensor_service.c
00004   * @author  MCD Application Team
00005   * @version V1.0.0
00006   * @date    04-July-2014
00007   * @brief   Add a sample service using a vendor specific profile.
00008   ******************************************************************************
00009   * @attention
00010   *
00011   * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
00012   *
00013   * Redistribution and use in source and binary forms, with or without modification,
00014   * are permitted provided that the following conditions are met:
00015   *   1. Redistributions of source code must retain the above copyright notice,
00016   *      this list of conditions and the following disclaimer.
00017   *   2. Redistributions in binary form must reproduce the above copyright notice,
00018   *      this list of conditions and the following disclaimer in the documentation
00019   *      and/or other materials provided with the distribution.
00020   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00021   *      may be used to endorse or promote products derived from this software
00022   *      without specific prior written permission.
00023   *
00024   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00025   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00026   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00028   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00029   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00030   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00032   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034   *
00035   ******************************************************************************
00036   */
00037 #include "sensor_service.h "
00038 
00039 /* Private variables ---------------------------------------------------------*/
00040 volatile int connected = FALSE;
00041 volatile uint8_t set_connectable = 1;
00042 volatile uint16_t connection_handle = 0;
00043 volatile uint8_t notification_enabled = FALSE;
00044 volatile AxesRaw_t axes_data = {0, 0, 0};
00045 uint16_t sampleServHandle, TXCharHandle, RXCharHandle;
00046 uint16_t accServHandle, freeFallCharHandle, accCharHandle;
00047 uint16_t envSensServHandle, tempCharHandle, pressCharHandle, humidityCharHandle;
00048 
00049 #define COPY_UUID_128(uuid_struct, uuid_15, uuid_14, uuid_13, uuid_12, uuid_11, uuid_10, uuid_9, uuid_8, uuid_7, uuid_6, uuid_5, uuid_4, uuid_3, uuid_2, uuid_1, uuid_0) \
00050 do {\
00051     uuid_struct[0] = uuid_0; uuid_struct[1] = uuid_1; uuid_struct[2] = uuid_2; uuid_struct[3] = uuid_3; \
00052         uuid_struct[4] = uuid_4; uuid_struct[5] = uuid_5; uuid_struct[6] = uuid_6; uuid_struct[7] = uuid_7; \
00053             uuid_struct[8] = uuid_8; uuid_struct[9] = uuid_9; uuid_struct[10] = uuid_10; uuid_struct[11] = uuid_11; \
00054                 uuid_struct[12] = uuid_12; uuid_struct[13] = uuid_13; uuid_struct[14] = uuid_14; uuid_struct[15] = uuid_15; \
00055 }while(0)
00056 
00057 #define COPY_ACC_SERVICE_UUID(uuid_struct)  COPY_UUID_128(uuid_struct,0x02,0x36,0x6e,0x80, 0xcf,0x3a, 0x11,0xe1, 0x9a,0xb4, 0x00,0x02,0xa5,0xd5,0xc5,0x1b)
00058 #define COPY_FREE_FALL_UUID(uuid_struct)    COPY_UUID_128(uuid_struct,0xe2,0x3e,0x78,0xa0, 0xcf,0x4a, 0x11,0xe1, 0x8f,0xfc, 0x00,0x02,0xa5,0xd5,0xc5,0x1b)
00059 #define COPY_ACC_UUID(uuid_struct)          COPY_UUID_128(uuid_struct,0x34,0x0a,0x1b,0x80, 0xcf,0x4b, 0x11,0xe1, 0xac,0x36, 0x00,0x02,0xa5,0xd5,0xc5,0x1b)
00060 
00061 #define COPY_ENV_SENS_SERVICE_UUID(uuid_struct)  COPY_UUID_128(uuid_struct,0x42,0x82,0x1a,0x40, 0xe4,0x77, 0x11,0xe2, 0x82,0xd0, 0x00,0x02,0xa5,0xd5,0xc5,0x1b)
00062 #define COPY_TEMP_CHAR_UUID(uuid_struct)         COPY_UUID_128(uuid_struct,0xa3,0x2e,0x55,0x20, 0xe4,0x77, 0x11,0xe2, 0xa9,0xe3, 0x00,0x02,0xa5,0xd5,0xc5,0x1b)
00063 #define COPY_PRESS_CHAR_UUID(uuid_struct)        COPY_UUID_128(uuid_struct,0xcd,0x20,0xc4,0x80, 0xe4,0x8b, 0x11,0xe2, 0x84,0x0b, 0x00,0x02,0xa5,0xd5,0xc5,0x1b)
00064 #define COPY_HUMIDITY_CHAR_UUID(uuid_struct)     COPY_UUID_128(uuid_struct,0x01,0xc5,0x0b,0x60, 0xe4,0x8c, 0x11,0xe2, 0xa0,0x73, 0x00,0x02,0xa5,0xd5,0xc5,0x1b)
00065 
00066 /* Store Value into a buffer in Little Endian Format */
00067 #define STORE_LE_16(buf, val)    ( ((buf)[0] =  (uint8_t) (val)    ) , \
00068                                    ((buf)[1] =  (uint8_t) (val>>8) ) )
00069 
00070 /**
00071  * @brief  Add an accelerometer service using a vendor specific profile.
00072  *
00073  * @param  None
00074  * @retval tBleStatus Status
00075  */
00076 tBleStatus Add_Acc_Service(void)
00077 {
00078   tBleStatus ret;
00079 
00080   uint8_t uuid[16];
00081   
00082   COPY_ACC_SERVICE_UUID(uuid);
00083   ret = aci_gatt_add_serv(UUID_TYPE_128,  uuid, PRIMARY_SERVICE, 7,
00084                           &accServHandle);
00085   if (ret != BLE_STATUS_SUCCESS) goto fail;    
00086   
00087   COPY_FREE_FALL_UUID(uuid);
00088   ret =  aci_gatt_add_char(accServHandle, UUID_TYPE_128, uuid, 1,
00089                            CHAR_PROP_NOTIFY, ATTR_PERMISSION_NONE, 0,
00090                            16, 0, &freeFallCharHandle);
00091   if (ret != BLE_STATUS_SUCCESS) goto fail;
00092   
00093   COPY_ACC_UUID(uuid);  
00094   ret =  aci_gatt_add_char(accServHandle, UUID_TYPE_128, uuid, 6,
00095                            CHAR_PROP_NOTIFY|CHAR_PROP_READ,
00096                            ATTR_PERMISSION_NONE,
00097                            GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP,
00098                            16, 0, &accCharHandle);
00099   if (ret != BLE_STATUS_SUCCESS) goto fail;
00100   
00101   PRINTF("Service ACC added. Handle 0x%04X, Free fall Charac handle: 0x%04X, Acc Charac handle: 0x%04X\n",accServHandle, freeFallCharHandle, accCharHandle);    
00102   return BLE_STATUS_SUCCESS; 
00103   
00104 fail:
00105   PRINTF("Error while adding ACC service.\n");
00106   return BLE_STATUS_ERROR ;
00107     
00108 }
00109 
00110 /**
00111  * @brief  Send a notification for a Free Fall detection.
00112  *
00113  * @param  None
00114  * @retval tBleStatus Status
00115  */
00116 tBleStatus Free_Fall_Notify(void)
00117 {  
00118   uint8_t val;
00119   tBleStatus ret;
00120     
00121   val = 0x01;   
00122   ret = aci_gatt_update_char_value(accServHandle, freeFallCharHandle, 0, 1,
00123                                    &val);
00124     
00125   if (ret != BLE_STATUS_SUCCESS){
00126     PRINTF("Error while updating ACC characteristic.\n") ;
00127     return BLE_STATUS_ERROR ;
00128   }
00129   return BLE_STATUS_SUCCESS;    
00130 }
00131 
00132 /**
00133  * @brief  Update acceleration characteristic value.
00134  *
00135  * @param  Structure containing acceleration value in mg
00136  * @retval Status
00137  */
00138 tBleStatus Acc_Update(AxesRaw_t *data)
00139 {  
00140   tBleStatus ret;    
00141   uint8_t buff[6];
00142     
00143   STORE_LE_16(buff,data->AXIS_X);
00144   STORE_LE_16(buff+2,data->AXIS_Y);
00145   STORE_LE_16(buff+4,data->AXIS_Z);
00146     
00147   ret = aci_gatt_update_char_value(accServHandle, accCharHandle, 0, 6, buff);
00148     
00149   if (ret != BLE_STATUS_SUCCESS){
00150     PRINTF("Error while updating ACC characteristic.\n") ;
00151     return BLE_STATUS_ERROR ;
00152   }
00153   return BLE_STATUS_SUCCESS;    
00154 }
00155 
00156 /**
00157  * @brief  Add the Environmental Sensor service.
00158  *
00159  * @param  None
00160  * @retval Status
00161  */
00162 tBleStatus Add_Environmental_Sensor_Service(void)
00163 {
00164   tBleStatus ret;
00165   uint8_t uuid[16];
00166   uint16_t uuid16;
00167   charactFormat charFormat;
00168   uint16_t descHandle;
00169   
00170   COPY_ENV_SENS_SERVICE_UUID(uuid);
00171   ret = aci_gatt_add_serv(UUID_TYPE_128,  uuid, PRIMARY_SERVICE, 10,
00172                           &envSensServHandle);
00173   if (ret != BLE_STATUS_SUCCESS) goto fail;
00174   
00175   /* Temperature Characteristic */
00176   COPY_TEMP_CHAR_UUID(uuid);  
00177   ret =  aci_gatt_add_char(envSensServHandle, UUID_TYPE_128, uuid, 2,
00178                            CHAR_PROP_READ, ATTR_PERMISSION_NONE,
00179                            GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP,
00180                            16, 0, &tempCharHandle);
00181   if (ret != BLE_STATUS_SUCCESS) goto fail;
00182   
00183   charFormat.format = FORMAT_SINT16;
00184   charFormat.exp = -1;
00185   charFormat.unit = UNIT_TEMP_CELSIUS;
00186   charFormat.name_space = 0;
00187   charFormat.desc = 0;
00188   
00189   uuid16 = CHAR_FORMAT_DESC_UUID;
00190   
00191   ret = aci_gatt_add_char_desc(envSensServHandle,
00192                                tempCharHandle,
00193                                UUID_TYPE_16,
00194                                (uint8_t *)&uuid16, 
00195                                7,
00196                                7,
00197                                (void *)&charFormat, 
00198                                ATTR_PERMISSION_NONE,
00199                                ATTR_ACCESS_READ_ONLY,
00200                                0,
00201                                16,
00202                                FALSE,
00203                                &descHandle);
00204   if (ret != BLE_STATUS_SUCCESS) goto fail;
00205   
00206   /* Pressure Characteristic */
00207   if(1){ //FIXME
00208     COPY_PRESS_CHAR_UUID(uuid);  
00209     ret =  aci_gatt_add_char(envSensServHandle, UUID_TYPE_128, uuid, 3,
00210                              CHAR_PROP_READ, ATTR_PERMISSION_NONE,
00211                              GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP,
00212                              16, 0, &pressCharHandle);
00213     if (ret != BLE_STATUS_SUCCESS) goto fail;
00214     
00215     charFormat.format = FORMAT_SINT24;
00216     charFormat.exp = -5;
00217     charFormat.unit = UNIT_PRESSURE_BAR;
00218     charFormat.name_space = 0;
00219     charFormat.desc = 0;
00220     
00221     uuid16 = CHAR_FORMAT_DESC_UUID;
00222     
00223     ret = aci_gatt_add_char_desc(envSensServHandle,
00224                                  pressCharHandle,
00225                                  UUID_TYPE_16,
00226                                  (uint8_t *)&uuid16, 
00227                                  7,
00228                                  7,
00229                                  (void *)&charFormat, 
00230                                  ATTR_PERMISSION_NONE,
00231                                  ATTR_ACCESS_READ_ONLY,
00232                                  0,
00233                                  16,
00234                                  FALSE,
00235                                  &descHandle);
00236     if (ret != BLE_STATUS_SUCCESS) goto fail;
00237   }    
00238   /* Humidity Characteristic */
00239   if(1){   //FIXME
00240     COPY_HUMIDITY_CHAR_UUID(uuid);  
00241     ret =  aci_gatt_add_char(envSensServHandle, UUID_TYPE_128, uuid, 2,
00242                              CHAR_PROP_READ, ATTR_PERMISSION_NONE,
00243                              GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP,
00244                              16, 0, &humidityCharHandle);
00245     if (ret != BLE_STATUS_SUCCESS) goto fail;
00246     
00247     charFormat.format = FORMAT_UINT16;
00248     charFormat.exp = -1;
00249     charFormat.unit = UNIT_UNITLESS;
00250     charFormat.name_space = 0;
00251     charFormat.desc = 0;
00252     
00253     uuid16 = CHAR_FORMAT_DESC_UUID;
00254     
00255     ret = aci_gatt_add_char_desc(envSensServHandle,
00256                                  humidityCharHandle,
00257                                  UUID_TYPE_16,
00258                                  (uint8_t *)&uuid16, 
00259                                  7,
00260                                  7,
00261                                  (void *)&charFormat, 
00262                                  ATTR_PERMISSION_NONE,
00263                                  ATTR_ACCESS_READ_ONLY,
00264                                  0,
00265                                  16,
00266                                  FALSE,
00267                                  &descHandle);
00268     if (ret != BLE_STATUS_SUCCESS) goto fail;
00269   } 
00270   PRINTF("Service ENV_SENS added. Handle 0x%04X, TEMP Charac handle: 0x%04X, PRESS Charac handle: 0x%04X, HUMID Charac handle: 0x%04X\n",envSensServHandle, tempCharHandle, pressCharHandle, humidityCharHandle);   
00271   return BLE_STATUS_SUCCESS; 
00272   
00273 fail:
00274   PRINTF("Error while adding ENV_SENS service.\n");
00275   return BLE_STATUS_ERROR ;
00276   
00277 }
00278 
00279 /**
00280  * @brief  Update temperature characteristic value.
00281  * @param  Temperature in tenths of degree 
00282  * @retval Status
00283  */
00284 tBleStatus Temp_Update(int16_t temp)
00285 {  
00286   tBleStatus ret;
00287   
00288   ret = aci_gatt_update_char_value(envSensServHandle, tempCharHandle, 0, 2,
00289                                    (uint8_t*)&temp);
00290   
00291   if (ret != BLE_STATUS_SUCCESS){
00292     PRINTF("Error while updating TEMP characteristic.\n") ;
00293     return BLE_STATUS_ERROR ;
00294   }
00295   return BLE_STATUS_SUCCESS;
00296     
00297 }
00298 
00299 /**
00300  * @brief  Update pressure characteristic value.
00301  * @param  int32_t Pressure in mbar 
00302  * @retval tBleStatus Status
00303  */
00304 tBleStatus Press_Update(int32_t press)
00305 {  
00306   tBleStatus ret;
00307   
00308   ret = aci_gatt_update_char_value(envSensServHandle, pressCharHandle, 0, 3,
00309                                    (uint8_t*)&press);
00310   
00311   if (ret != BLE_STATUS_SUCCESS){
00312     PRINTF("Error while updating TEMP characteristic.\n") ;
00313     return BLE_STATUS_ERROR ;
00314   }
00315   return BLE_STATUS_SUCCESS;
00316     
00317 }
00318 
00319 /**
00320  * @brief  Update humidity characteristic value.
00321  * @param  uint16_thumidity RH (Relative Humidity) in thenths of %
00322  * @retval tBleStatus      Status
00323  */
00324 tBleStatus Humidity_Update(uint16_t humidity)
00325 {  
00326   tBleStatus ret;
00327   
00328   ret = aci_gatt_update_char_value(envSensServHandle, humidityCharHandle, 0, 2,
00329                                    (uint8_t*)&humidity);
00330   
00331   if (ret != BLE_STATUS_SUCCESS){
00332     PRINTF("Error while updating TEMP characteristic.\n") ;
00333     return BLE_STATUS_ERROR ;
00334   }
00335   return BLE_STATUS_SUCCESS;
00336   
00337 }
00338 
00339 /**
00340  * @brief  Puts the device in connectable mode.
00341  *         If you want to specify a UUID list in the advertising data, those data can
00342  *         be specified as a parameter in aci_gap_set_discoverable().
00343  *         For manufacture data, aci_gap_update_adv_data must be called.
00344  * @param  None 
00345  * @retval None
00346  */
00347 /* Ex.:
00348  *
00349  *  tBleStatus ret;    
00350  *  const char local_name[] = {AD_TYPE_COMPLETE_LOCAL_NAME,'B','l','u','e','N','R','G'};    
00351  *  const uint8_t serviceUUIDList[] = {AD_TYPE_16_BIT_SERV_UUID,0x34,0x12};    
00352  *  const uint8_t manuf_data[] = {4, AD_TYPE_MANUFACTURER_SPECIFIC_DATA, 0x05, 0x02, 0x01};
00353  *  
00354  *  ret = aci_gap_set_discoverable(ADV_IND, 0, 0, PUBLIC_ADDR, NO_WHITE_LIST_USE,
00355  *                                 8, local_name, 3, serviceUUIDList, 0, 0);    
00356  *  ret = aci_gap_update_adv_data(5, manuf_data);
00357  *
00358  */
00359 void setConnectable(void)
00360 {  
00361   tBleStatus ret;
00362   
00363   const char local_name[] = {AD_TYPE_COMPLETE_LOCAL_NAME,'B','l','u','e','N','R','G'};
00364   
00365   /* disable scan response */
00366   hci_le_set_scan_resp_data(0,NULL);
00367   PRINTF("General Discoverable Mode.\n");
00368   
00369   ret = aci_gap_set_discoverable(ADV_IND, 0, 0, PUBLIC_ADDR, NO_WHITE_LIST_USE,
00370                                  sizeof(local_name), local_name, 0, NULL, 0, 0);
00371   PRINTF("%d\n",ret);
00372 }
00373 
00374 /**
00375  * @brief  This function is called when there is a LE Connection Complete event.
00376  * @param  uint8_t Address of peer device
00377  * @param  uint16_t Connection handle
00378  * @retval None
00379  */
00380 void GAP_ConnectionComplete_CB(uint8_t addr[6], uint16_t handle)
00381 {  
00382   connected = TRUE;
00383   connection_handle = handle;
00384   
00385   PRINTF("Connected to device:");
00386   for(int i = 5; i > 0; i--){
00387     PRINTF("%02X-", addr[i]);
00388   }
00389   PRINTF("%02X\n", addr[0]);
00390 }
00391 
00392 /**
00393  * @brief  This function is called when the peer device get disconnected.
00394  * @param  None 
00395  * @retval None
00396  */
00397 void GAP_DisconnectionComplete_CB(void)
00398 {
00399   connected = FALSE;
00400   PRINTF("Disconnected\n");
00401   /* Make the device connectable again. */
00402   set_connectable = TRUE;
00403   notification_enabled = FALSE;
00404 }
00405 
00406 /**
00407  * @brief  Read request callback.
00408  * @param  uint16_t Handle of the attribute
00409  * @retval None
00410  */
00411 void Read_Request_CB(uint16_t handle)
00412 {
00413   //signed short refvalue;
00414   
00415   if(handle == accCharHandle + 1){
00416     Acc_Update((AxesRaw_t*)&axes_data);
00417   }  
00418   else if(handle == tempCharHandle + 1){
00419     int16_t data;
00420     data = 270 + ((uint64_t)rand()*15)/RAND_MAX; //sensor emulation        
00421     Acc_Update((AxesRaw_t*)&axes_data); //FIXME: to overcome issue on Android App
00422                                         // If the user button is not pressed within
00423                                         // a short time after the connection,
00424                                         // a pop-up reports a "No valid characteristics found" error.
00425     Temp_Update(data);
00426   }
00427   else if(handle == pressCharHandle + 1){
00428     int32_t data;
00429     struct timer t;  
00430     Timer_Set(&t, CLOCK_SECOND/10);
00431     data = 100000 + ((uint64_t)rand()*1000)/RAND_MAX;
00432     Press_Update(data);
00433   }
00434   else if(handle == humidityCharHandle + 1){
00435     uint16_t data;
00436     
00437     data = 450 + ((uint64_t)rand()*100)/RAND_MAX;
00438     
00439     Humidity_Update(data);
00440   }  
00441   
00442   //EXIT:
00443   if(connection_handle != 0)
00444     aci_gatt_allow_read(connection_handle);
00445 }
00446 
00447 /**
00448  * @brief  Callback processing the ACI events.
00449  * @note   Inside this function each event must be identified and correctly
00450  *         parsed.
00451  * @param  void* Pointer to the ACI packet
00452  * @retval None
00453  */
00454 void HCI_Event_CB(void *pckt)
00455 {
00456   hci_uart_pckt *hci_pckt = pckt;
00457   /* obtain event packet */
00458   hci_event_pckt *event_pckt = (hci_event_pckt*)hci_pckt->data;
00459   
00460   if(hci_pckt->type != HCI_EVENT_PKT)
00461     return;
00462   
00463   switch(event_pckt->evt){
00464     
00465   case EVT_DISCONN_COMPLETE:
00466     {
00467       GAP_DisconnectionComplete_CB();
00468     }
00469     break;
00470     
00471   case EVT_LE_META_EVENT:
00472     {
00473       evt_le_meta_event *evt = (void *)event_pckt->data;
00474       
00475       switch(evt->subevent){
00476       case EVT_LE_CONN_COMPLETE:
00477         {
00478           evt_le_connection_complete *cc = (void *)evt->data;
00479           GAP_ConnectionComplete_CB(cc->peer_bdaddr, cc->handle);
00480         }
00481         break;
00482       }
00483     }
00484     break;
00485     
00486   case EVT_VENDOR:
00487     {
00488       evt_blue_aci *blue_evt = (void*)event_pckt->data;
00489       switch(blue_evt->ecode){
00490 
00491       case EVT_BLUE_GATT_READ_PERMIT_REQ:
00492         {
00493           evt_gatt_read_permit_req *pr = (void*)blue_evt->data;                    
00494           Read_Request_CB(pr->attr_handle);                    
00495         }
00496         break;
00497       }
00498     }
00499     break;
00500   }    
00501 }
00502 
00503 /**
00504  * @}
00505  */
00506 
00507 /**
00508  * @}
00509  */
00510 
00511 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
00512