bluenrg_interface
Diff: sensor_service.c
- Revision:
- 0:fb1547f2354e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensor_service.c Mon Nov 12 18:36:18 2018 +0000 @@ -0,0 +1,793 @@ +/** + ****************************************************************************** + * @file sensor_service.c + * @author MCD Application Team + * @version V1.0.0 + * @date 04-July-2014 + * @brief Add a sample service using a vendor specific profile. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2> + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +#include "sensor_service.h" + +/** @addtogroup X-CUBE-BLE1_Applications + * @{ + */ + +/** @addtogroup SensorDemo + * @{ + */ + +/** @defgroup SENSOR_SERVICE + * @{ + */ + +/** @defgroup SENSOR_SERVICE_Private_Variables + * @{ + */ +/* Private variables ---------------------------------------------------------*/ +volatile int connected = FALSE; +volatile uint8_t set_connectable = 1; +volatile uint16_t connection_handle = 0; +volatile uint8_t notification_enabled = FALSE; +volatile AxesRaw_t axes_data = {0, 0, 0}; +uint16_t sampleServHandle, TXCharHandle, RXCharHandle; +uint16_t accServHandle, freeFallCharHandle, accCharHandle; +uint16_t envSensServHandle, tempCharHandle, pressCharHandle, humidityCharHandle; + +#if NEW_SERVICES + uint16_t timeServHandle, secondsCharHandle, minuteCharHandle; + uint16_t ledServHandle, ledButtonCharHandle; + uint8_t ledState = 0; + int previousMinuteValue = -1; + extern uint8_t bnrg_expansion_board; +#endif +/** + * @} + */ + +/** @defgroup SENSOR_SERVICE_Private_Macros + * @{ + */ +/* Private macros ------------------------------------------------------------*/ +#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) \ +do {\ + uuid_struct[0] = uuid_0; uuid_struct[1] = uuid_1; uuid_struct[2] = uuid_2; uuid_struct[3] = uuid_3; \ + uuid_struct[4] = uuid_4; uuid_struct[5] = uuid_5; uuid_struct[6] = uuid_6; uuid_struct[7] = uuid_7; \ + uuid_struct[8] = uuid_8; uuid_struct[9] = uuid_9; uuid_struct[10] = uuid_10; uuid_struct[11] = uuid_11; \ + uuid_struct[12] = uuid_12; uuid_struct[13] = uuid_13; uuid_struct[14] = uuid_14; uuid_struct[15] = uuid_15; \ +}while(0) + +#if NEW_SERVICES + #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) + #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) + #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) + + #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) + #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) + #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) + #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) + + // Time service: uuid = 0x08, 0x36, 0x6e, 0x80, 0xcf, 0x3a, 0x11, 0xe1, 0x9a, 0xb4, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b + // straight uuid = 0x08366e80cf3a11e19ab40002a5d5c51b + #define COPY_TIME_SERVICE_UUID(uuid_struct) COPY_UUID_128(uuid_struct,0x08,0x36,0x6e,0x80, 0xcf,0x3a, 0x11,0xe1, 0x9a,0xb4, 0x00,0x02,0xa5,0xd5,0xc5,0x1b) + #define COPY_TIME_UUID(uuid_struct) COPY_UUID_128(uuid_struct,0x09,0x36,0x6e,0x80, 0xcf,0x3a, 0x11,0xe1, 0x9a,0xb4, 0x00,0x02,0xa5,0xd5,0xc5,0x1b) + #define COPY_MINUTE_UUID(uuid_struct) COPY_UUID_128(uuid_struct,0x0a,0x36,0x6e,0x80, 0xcf,0x3a, 0x11,0xe1, 0x9a,0xb4, 0x00,0x02,0xa5,0xd5,0xc5,0x1b) + + // LED service + #define COPY_LED_SERVICE_UUID(uuid_struct) COPY_UUID_128(uuid_struct,0x0b,0x36,0x6e,0x80, 0xcf,0x3a, 0x11,0xe1, 0x9a,0xb4, 0x00,0x02,0xa5,0xd5,0xc5,0x1b) + #define COPY_LED_UUID(uuid_struct) COPY_UUID_128(uuid_struct,0x0c,0x36,0x6e,0x80, 0xcf,0x3a, 0x11,0xe1, 0x9a,0xb4, 0x00,0x02,0xa5,0xd5,0xc5,0x1b) +#else + #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) + #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) + #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) + + #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) + #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) + #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) + #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) +#endif + +/* Store Value into a buffer in Little Endian Format */ +#define STORE_LE_16(buf, val) ( ((buf)[0] = (uint8_t) (val) ) , \ + ((buf)[1] = (uint8_t) (val>>8) ) ) +/** + * @} + */ + +/** @defgroup SENSOR_SERVICE_Exported_Functions + * @{ + */ +/** + * @brief Add an accelerometer service using a vendor specific profile. + * + * @param None + * @retval tBleStatus Status + */ +tBleStatus Add_Acc_Service(void) +{ + tBleStatus ret; + + uint8_t uuid[16]; + + COPY_ACC_SERVICE_UUID(uuid); + ret = aci_gatt_add_serv(UUID_TYPE_128, uuid, PRIMARY_SERVICE, 7, + &accServHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + COPY_FREE_FALL_UUID(uuid); + ret = aci_gatt_add_char(accServHandle, UUID_TYPE_128, uuid, 1, + CHAR_PROP_NOTIFY, ATTR_PERMISSION_NONE, 0, + 16, 0, &freeFallCharHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + COPY_ACC_UUID(uuid); + ret = aci_gatt_add_char(accServHandle, UUID_TYPE_128, uuid, 6, + CHAR_PROP_NOTIFY|CHAR_PROP_READ, + ATTR_PERMISSION_NONE, + GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP, + 16, 0, &accCharHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + PRINTF("Service ACC added. Handle 0x%04X, Free fall Charac handle: 0x%04X, Acc Charac handle: 0x%04X\n",accServHandle, freeFallCharHandle, accCharHandle); + return BLE_STATUS_SUCCESS; + +fail: + PRINTF("Error while adding ACC service.\n"); + return BLE_STATUS_ERROR ; + +} + +/** + * @brief Send a notification for a Free Fall detection. + * + * @param None + * @retval tBleStatus Status + */ +tBleStatus Free_Fall_Notify(void) +{ + uint8_t val; + tBleStatus ret; + + val = 0x01; + ret = aci_gatt_update_char_value(accServHandle, freeFallCharHandle, 0, 1, + &val); + + if (ret != BLE_STATUS_SUCCESS){ + PRINTF("Error while updating FFall characteristic.\n") ; + return BLE_STATUS_ERROR ; + } + return BLE_STATUS_SUCCESS; +} + +/** + * @brief Update acceleration characteristic value. + * + * @param Structure containing acceleration value in mg + * @retval Status + */ +tBleStatus Acc_Update(AxesRaw_t *data) +{ + tBleStatus ret; + uint8_t buff[6]; + + STORE_LE_16(buff,data->AXIS_X); + STORE_LE_16(buff+2,data->AXIS_Y); + STORE_LE_16(buff+4,data->AXIS_Z); + + ret = aci_gatt_update_char_value(accServHandle, accCharHandle, 0, 6, buff); + + if (ret != BLE_STATUS_SUCCESS){ + PRINTF("Error while updating ACC characteristic.\n") ; + return BLE_STATUS_ERROR ; + } + return BLE_STATUS_SUCCESS; +} + +/** + * @brief Add the Environmental Sensor service. + * + * @param None + * @retval Status + */ +tBleStatus Add_Environmental_Sensor_Service(void) +{ + tBleStatus ret; + uint8_t uuid[16]; + uint16_t uuid16; + charactFormat charFormat; + uint16_t descHandle; + + COPY_ENV_SENS_SERVICE_UUID(uuid); + ret = aci_gatt_add_serv(UUID_TYPE_128, uuid, PRIMARY_SERVICE, 10, + &envSensServHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + /* Temperature Characteristic */ + COPY_TEMP_CHAR_UUID(uuid); + ret = aci_gatt_add_char(envSensServHandle, UUID_TYPE_128, uuid, 2, + CHAR_PROP_READ, ATTR_PERMISSION_NONE, + GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP, + 16, 0, &tempCharHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + charFormat.format = FORMAT_SINT16; + charFormat.exp = -1; + charFormat.unit = UNIT_TEMP_CELSIUS; + charFormat.name_space = 0; + charFormat.desc = 0; + + uuid16 = CHAR_FORMAT_DESC_UUID; + + ret = aci_gatt_add_char_desc(envSensServHandle, + tempCharHandle, + UUID_TYPE_16, + (uint8_t *)&uuid16, + 7, + 7, + (void *)&charFormat, + ATTR_PERMISSION_NONE, + ATTR_ACCESS_READ_ONLY, + 0, + 16, + FALSE, + &descHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + /* Pressure Characteristic */ + if(1){ //FIXME + COPY_PRESS_CHAR_UUID(uuid); + ret = aci_gatt_add_char(envSensServHandle, UUID_TYPE_128, uuid, 3, + CHAR_PROP_READ, ATTR_PERMISSION_NONE, + GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP, + 16, 0, &pressCharHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + charFormat.format = FORMAT_SINT24; + charFormat.exp = -5; + charFormat.unit = UNIT_PRESSURE_BAR; + charFormat.name_space = 0; + charFormat.desc = 0; + + uuid16 = CHAR_FORMAT_DESC_UUID; + + ret = aci_gatt_add_char_desc(envSensServHandle, + pressCharHandle, + UUID_TYPE_16, + (uint8_t *)&uuid16, + 7, + 7, + (void *)&charFormat, + ATTR_PERMISSION_NONE, + ATTR_ACCESS_READ_ONLY, + 0, + 16, + FALSE, + &descHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + } + /* Humidity Characteristic */ + if(1){ //FIXME + COPY_HUMIDITY_CHAR_UUID(uuid); + ret = aci_gatt_add_char(envSensServHandle, UUID_TYPE_128, uuid, 2, + CHAR_PROP_READ, ATTR_PERMISSION_NONE, + GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP, + 16, 0, &humidityCharHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + charFormat.format = FORMAT_UINT16; + charFormat.exp = -1; + charFormat.unit = UNIT_UNITLESS; + charFormat.name_space = 0; + charFormat.desc = 0; + + uuid16 = CHAR_FORMAT_DESC_UUID; + + ret = aci_gatt_add_char_desc(envSensServHandle, + humidityCharHandle, + UUID_TYPE_16, + (uint8_t *)&uuid16, + 7, + 7, + (void *)&charFormat, + ATTR_PERMISSION_NONE, + ATTR_ACCESS_READ_ONLY, + 0, + 16, + FALSE, + &descHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + } + 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); + return BLE_STATUS_SUCCESS; + +fail: + PRINTF("Error while adding ENV_SENS service.\n"); + return BLE_STATUS_ERROR ; + +} + +/** + * @brief Update temperature characteristic value. + * @param Temperature in tenths of degree + * @retval Status + */ +tBleStatus Temp_Update(int16_t temp) +{ + tBleStatus ret; + + ret = aci_gatt_update_char_value(envSensServHandle, tempCharHandle, 0, 2, + (uint8_t*)&temp); + + if (ret != BLE_STATUS_SUCCESS){ + PRINTF("Error while updating TEMP characteristic.\n") ; + return BLE_STATUS_ERROR ; + } + return BLE_STATUS_SUCCESS; + +} + +/** + * @brief Update pressure characteristic value. + * @param int32_t Pressure in mbar + * @retval tBleStatus Status + */ +tBleStatus Press_Update(int32_t press) +{ + tBleStatus ret; + + ret = aci_gatt_update_char_value(envSensServHandle, pressCharHandle, 0, 3, + (uint8_t*)&press); + + if (ret != BLE_STATUS_SUCCESS){ + PRINTF("Error while updating TEMP characteristic.\n") ; + return BLE_STATUS_ERROR ; + } + return BLE_STATUS_SUCCESS; + +} + +/** + * @brief Update humidity characteristic value. + * @param uint16_thumidity RH (Relative Humidity) in thenths of % + * @retval tBleStatus Status + */ +tBleStatus Humidity_Update(uint16_t humidity) +{ + tBleStatus ret; + + ret = aci_gatt_update_char_value(envSensServHandle, humidityCharHandle, 0, 2, + (uint8_t*)&humidity); + + if (ret != BLE_STATUS_SUCCESS){ + PRINTF("Error while updating TEMP characteristic.\n") ; + return BLE_STATUS_ERROR ; + } + return BLE_STATUS_SUCCESS; + +} + +/** + * @brief Puts the device in connectable mode. + * If you want to specify a UUID list in the advertising data, those data can + * be specified as a parameter in aci_gap_set_discoverable(). + * For manufacture data, aci_gap_update_adv_data must be called. + * @param None + * @retval None + */ +/* Ex.: + * + * tBleStatus ret; + * const char local_name[] = {AD_TYPE_COMPLETE_LOCAL_NAME,'B','l','u','e','N','R','G'}; + * const uint8_t serviceUUIDList[] = {AD_TYPE_16_BIT_SERV_UUID,0x34,0x12}; + * const uint8_t manuf_data[] = {4, AD_TYPE_MANUFACTURER_SPECIFIC_DATA, 0x05, 0x02, 0x01}; + * + * ret = aci_gap_set_discoverable(ADV_IND, 0, 0, PUBLIC_ADDR, NO_WHITE_LIST_USE, + * 8, local_name, 3, serviceUUIDList, 0, 0); + * ret = aci_gap_update_adv_data(5, manuf_data); + * + */ +void setConnectable(void) +{ + tBleStatus ret; + + const char local_name[] = {AD_TYPE_COMPLETE_LOCAL_NAME,'B','l','u','e','N','R','G'}; + + /* disable scan response */ + hci_le_set_scan_resp_data(0,NULL); + PRINTF("General Discoverable Mode.\n"); + + ret = aci_gap_set_discoverable(ADV_IND, 0, 0, PUBLIC_ADDR, NO_WHITE_LIST_USE, + sizeof(local_name), local_name, 0, NULL, 0, 0); + if (ret != BLE_STATUS_SUCCESS) { + PRINTF("Error while setting discoverable mode (%d)\n", ret); + } +} + +/** + * @brief This function is called when there is a LE Connection Complete event. + * @param uint8_t Address of peer device + * @param uint16_t Connection handle + * @retval None + */ +void GAP_ConnectionComplete_CB(uint8_t addr[6], uint16_t handle) +{ + connected = TRUE; + connection_handle = handle; + + PRINTF("Connected to device:"); + for(int i = 5; i > 0; i--){ + PRINTF("%02X-", addr[i]); + } + PRINTF("%02X\n", addr[0]); +} + +/** + * @brief This function is called when the peer device gets disconnected. + * @param None + * @retval None + */ +void GAP_DisconnectionComplete_CB(void) +{ + connected = FALSE; + PRINTF("Disconnected\n"); + /* Make the device connectable again. */ + set_connectable = TRUE; + notification_enabled = FALSE; +} + +/** + * @brief Read request callback. + * @param uint16_t Handle of the attribute + * @retval None + */ +void Read_Request_CB(uint16_t handle) +{ + if(handle == accCharHandle + 1){ + Acc_Update((AxesRaw_t*)&axes_data); + } + else if(handle == tempCharHandle + 1){ + int16_t data; + data = 270 + ((uint64_t)rand()*15)/RAND_MAX; //sensor emulation + Acc_Update((AxesRaw_t*)&axes_data); //FIXME: to overcome issue on Android App + // If the user button is not pressed within + // a short time after the connection, + // a pop-up reports a "No valid characteristics found" error. + Temp_Update(data); + } + else if(handle == pressCharHandle + 1){ + int32_t data; + struct timer t; + Timer_Set(&t, CLOCK_SECOND/10); + data = 100000 + ((uint64_t)rand()*1000)/RAND_MAX; + Press_Update(data); + } + else if(handle == humidityCharHandle + 1){ + uint16_t data; + + data = 450 + ((uint64_t)rand()*100)/RAND_MAX; + + Humidity_Update(data); + } + + //EXIT: + if(connection_handle != 0) + aci_gatt_allow_read(connection_handle); +} + +/** + * @brief Callback processing the ACI events. + * @note Inside this function each event must be identified and correctly + * parsed. + * @param void* Pointer to the ACI packet + * @retval None + */ +void HCI_Event_CB(void *pckt) +{ + hci_uart_pckt *hci_pckt = pckt; + /* obtain event packet */ + hci_event_pckt *event_pckt = (hci_event_pckt*)hci_pckt->data; + + if(hci_pckt->type != HCI_EVENT_PKT) + return; + + switch(event_pckt->evt){ + + case EVT_DISCONN_COMPLETE: + { + GAP_DisconnectionComplete_CB(); + } + break; + + case EVT_LE_META_EVENT: + { + evt_le_meta_event *evt = (void *)event_pckt->data; + + switch(evt->subevent){ + case EVT_LE_CONN_COMPLETE: + { + evt_le_connection_complete *cc = (void *)evt->data; + GAP_ConnectionComplete_CB(cc->peer_bdaddr, cc->handle); + } + break; + } + } + break; + + case EVT_VENDOR: + { + evt_blue_aci *blue_evt = (void*)event_pckt->data; + switch(blue_evt->ecode){ + +#if NEW_SERVICES + case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED: + { + /* this callback is invoked when a GATT attribute is modified + extract callback data and pass to suitable handler function */ + if (bnrg_expansion_board == IDB05A1) { + evt_gatt_attr_modified_IDB05A1 *evt = (evt_gatt_attr_modified_IDB05A1*)blue_evt->data; + Attribute_Modified_CB(evt->attr_handle, evt->data_length, evt->att_data); + } + else { + evt_gatt_attr_modified_IDB04A1 *evt = (evt_gatt_attr_modified_IDB04A1*)blue_evt->data; + Attribute_Modified_CB(evt->attr_handle, evt->data_length, evt->att_data); + } + } + break; +#endif + + case EVT_BLUE_GATT_READ_PERMIT_REQ: + { + evt_gatt_read_permit_req *pr = (void*)blue_evt->data; + Read_Request_CB(pr->attr_handle); + } + break; + } + } + break; + } +} + +#if NEW_SERVICES +/** + * @brief Add a time service using a vendor specific profile + * @param None + * @retval Status + */ +tBleStatus Add_Time_Service(void) +{ + tBleStatus ret; + uint8_t uuid[16]; + + /* copy "Timer service UUID" defined above to 'uuid' local variable */ + COPY_TIME_SERVICE_UUID(uuid); + + /* + * now add "Time service" to GATT server, service handle is returned + * via 'timeServHandle' parameter of aci_gatt_add_serv() API. + * Please refer to 'BlueNRG Application Command Interface.pdf' for detailed + * API description + */ + ret = aci_gatt_add_serv(UUID_TYPE_128, uuid, PRIMARY_SERVICE, 7, + &timeServHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + /* + * now add "Seconds characteristic" to Time service, characteristic handle + * is returned via 'secondsCharHandle' parameter of aci_gatt_add_char() API. + * This characteristic is read only, as specified by CHAR_PROP_READ parameter. + * Please refer to 'BlueNRG Application Command Interface.pdf' for detailed + * API description + */ + COPY_TIME_UUID(uuid); + ret = aci_gatt_add_char(timeServHandle, UUID_TYPE_128, uuid, 4, + CHAR_PROP_READ, ATTR_PERMISSION_NONE, 0, + 16, 0, &secondsCharHandle); + + if (ret != BLE_STATUS_SUCCESS) goto fail; + + COPY_MINUTE_UUID(uuid); + /* + * Add "Minutes characteristic" to "Time service". + * This characteristic is readable as well as notifiable only, as specified + * by CHAR_PROP_NOTIFY|CHAR_PROP_READ parameter below. + */ + ret = aci_gatt_add_char(timeServHandle, UUID_TYPE_128, uuid, 4, + CHAR_PROP_NOTIFY|CHAR_PROP_READ, ATTR_PERMISSION_NONE, 0, + 16, 1, &minuteCharHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + PRINTF("Service TIME added. Handle 0x%04X, TIME Charac handle: 0x%04X\n",timeServHandle, secondsCharHandle); + return BLE_STATUS_SUCCESS; + + /* return BLE_STATUS_ERROR if we reach this tag */ +fail: + PRINTF("Error while adding Time service.\n"); + return BLE_STATUS_ERROR ; +} + +/** + * @brief Update seconds characteristic value of Time service. + * @param None + * @retval Status + */ +tBleStatus Seconds_Update(void) +{ + uint32_t val; + tBleStatus ret; + + /* Obtain system tick value in milliseconds, and convert it to seconds. */ + val = HAL_GetTick(); + val = val/1000; + + /* create a time[] array to pass as last argument of aci_gatt_update_char_value() API*/ + const uint8_t time[4] = {(val >> 24)&0xFF, (val >> 16)&0xFF, (val >> 8)&0xFF, (val)&0xFF}; + + /* + * Update value of "Seconds characteristic" using aci_gatt_update_char_value() API + * Please refer to 'BlueNRG Application Command Interface.pdf' for detailed + * API description + */ + ret = aci_gatt_update_char_value(timeServHandle, secondsCharHandle, 0, 4, + time); + + if (ret != BLE_STATUS_SUCCESS){ + PRINTF("Error while updating TIME characteristic.\n") ; + return BLE_STATUS_ERROR ; + } + return BLE_STATUS_SUCCESS; +} + +/** + * @brief Send a notification for a minute characteristic of time service. + * @param None + * @retval Status + */ +tBleStatus Minutes_Notify(void) +{ + uint32_t val; + uint32_t minuteValue; + tBleStatus ret; + + /* Obtain system tick value in milliseconds */ + val = HAL_GetTick(); + + /* update "Minutes characteristic" value if it has changed w.r.t. previous + * "minute" value. + */ + if((minuteValue=val/(60*1000))!=previousMinuteValue) { + /* memorize this "minute" value for future usage */ + previousMinuteValue = minuteValue; + + /* create a time[] array to pass as last argument of aci_gatt_update_char_value() API*/ + const uint8_t time[4] = {(minuteValue >> 24)&0xFF, (minuteValue >> 16)&0xFF, (minuteValue >> 8)&0xFF, (minuteValue)&0xFF}; + + /* + * Update value of "Minutes characteristic" using aci_gatt_update_char_value() API + * Please refer to 'BlueNRG Application Command Interface.pdf' for detailed + * API description + */ + ret = aci_gatt_update_char_value(timeServHandle, minuteCharHandle, 0, 4, + time); + if (ret != BLE_STATUS_SUCCESS){ + PRINTF("Error while updating TIME characteristic.\n") ; + return BLE_STATUS_ERROR ; + } + } + return BLE_STATUS_SUCCESS; +} + +/** + * @brief Updates "Seconds and Minutes characteristics" values. + * @param None + * @retval None + */ +void Update_Time_Characteristics(void) { + /* update "seconds and minutes characteristics" of time service */ + Seconds_Update(); + Minutes_Notify(); +} + +/* + * @brief Add LED button service using a vendor specific profile. + * @param None + * @retval Status + */ +tBleStatus Add_LED_Service(void) +{ + tBleStatus ret; + uint8_t uuid[16]; + + /* copy "LED service UUID" defined above to 'uuid' local variable */ + COPY_LED_SERVICE_UUID(uuid); + /* + * now add "LED service" to GATT server, service handle is returned + * via 'ledServHandle' parameter of aci_gatt_add_serv() API. + * Please refer to 'BlueNRG Application Command Interface.pdf' for detailed + * API description + */ + ret = aci_gatt_add_serv(UUID_TYPE_128, uuid, PRIMARY_SERVICE, 7, + &ledServHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + /* copy "LED button characteristic UUID" defined above to 'uuid' local variable */ + COPY_LED_UUID(uuid); + /* + * now add "LED button characteristic" to LED service, characteristic handle + * is returned via 'ledButtonCharHandle' parameter of aci_gatt_add_char() API. + * This characteristic is writable, as specified by 'CHAR_PROP_WRITE' parameter. + * Please refer to 'BlueNRG Application Command Interface.pdf' for detailed + * API description + */ + ret = aci_gatt_add_char(ledServHandle, UUID_TYPE_128, uuid, 4, + CHAR_PROP_WRITE | CHAR_PROP_WRITE_WITHOUT_RESP, ATTR_PERMISSION_NONE, GATT_NOTIFY_ATTRIBUTE_WRITE, + 16, 1, &ledButtonCharHandle); + if (ret != BLE_STATUS_SUCCESS) goto fail; + + PRINTF("Service LED BUTTON added. Handle 0x%04X, LED button Charac handle: 0x%04X\n",ledServHandle, ledButtonCharHandle); + return BLE_STATUS_SUCCESS; + +fail: + PRINTF("Error while adding LED service.\n"); + return BLE_STATUS_ERROR; +} + +/** + * @brief This function is called attribute value corresponding to + * ledButtonCharHandle characteristic gets modified. + * @param Handle of the attribute + * @param Size of the modified attribute data + * @param Pointer to the modified attribute data + * @retval None + */ +void Attribute_Modified_CB(uint16_t handle, uint8_t data_length, uint8_t *att_data) +{ + /* If GATT client has modified 'LED button characteristic' value, toggle LED2 */ + if(handle == ledButtonCharHandle + 1){ + BSP_LED_Toggle(LED2); + } +} +#endif /* NEW_SERVICES */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + /** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/