/*---------------------------------------------------------------------------- * Copyright (c) Fenda Technologies Co., Ltd. 2021. All rights reserved. * * Description: ble_sleep_server.c * * Author: shey.tanxiaoyu * * Create: 2021-09-13 *--------------------------------------------------------------------------*/ #include "ble_sleep_server.h" #include "ble_data_transmission.h" #include "health_api.h" #include "FreeRTOS.h" #define SLEEP_DATA_BUFF_SIZE 3072 // 3k 空间用于7天睡眠数据发送 #define SLEEP_DATA_FRAME_NUMBER_MAX 190 // 根据 SLEEP_DATA_BUFF_SIZE - 回复固定部分(4)) / 睡眠数据片段数组(16) // 由于睡眠数据未分帧,目前采取大缓存的发送方式,若睡眠数据大于190条,会死机 /* 4.6.1 APP获取睡眠帧数 */ void ble_get_sleep_measure_frame_number(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { uint16_t write_idx = 0; protocol_data_info_t data_info = {0}; uint32_t start_timestamp = 0; uint32_t end_timestamp = 0; uint32_t frame_num = 0; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch(data_info.type & 0x7F) { case SLEEP_FRAME_START_TIME_TYPE: start_timestamp += (*in_data++) << 24; start_timestamp += (*in_data++) << 16; start_timestamp += (*in_data++) << 8; start_timestamp += (*in_data); break; case SLEEP_FRAME_END_TIME_TYPE: end_timestamp += (*in_data++) << 24; end_timestamp += (*in_data++) << 16; end_timestamp += (*in_data++) << 8; end_timestamp += (*in_data); health_api_sleep_frame_number_get(SLEEP_DATA_FRAME_NUMBER_MAX, start_timestamp, end_timestamp, &frame_num); break; default: break; } in_data = data_info.p_data; in_data += (data_info.len); in_len -= (2 + data_info.len); if (in_len > FRAM_MAX_SIZ) { in_len = 0; } } while (in_len); out_data[write_idx++] = 4; out_data[write_idx++] = SLEEP_FRAME_COUNT_TYPE; out_data[write_idx++] = frame_num >> 8; out_data[write_idx++] = frame_num; *out_len = write_idx; } /* 4.6.2 设备主动通知APP获取睡眠数据 */ void ble_sleep_measure_report(void) { uint16_t write_idx = 0; uint8_t buf_temp[TEMP_NUM_MAX] = {0}; buf_temp[write_idx++] = 0x03; //LTV L buf_temp[write_idx++] = SLEEP_ACTIVE_NOTIFY_TYPE; //type buf_temp[write_idx++] = 0; BLE_SendFrameById(SLEEP_SERVER, SLEEP_MEASURE_REPORT_ID, buf_temp, write_idx); } /* 4.6.3 APP获取睡眠详情片段数据 */ void ble_get_sleep_measure_frame_detail(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { uint16_t write_idx = 0; protocol_data_info_t data_info = {0}; uint32_t frame_index = 0; uint32_t item_num = 0; health_sleep_item_t* item_buf = (health_sleep_item_t*)pvPortMalloc(SLEEP_DATA_FRAME_NUMBER_MAX * sizeof(health_sleep_item_t)); uint8_t* send_data = pvPortMalloc(SLEEP_DATA_BUFF_SIZE); data_info.error = FENDA_SUCCESS; if(send_data == NULL || item_buf == NULL) { data_info.error = REQ_MEMORY_ERROR; write_idx = user_set_protocol_error(out_data, SLEEP_SERVER, data_info.error); *out_len = write_idx; return; } do { user_get_data_info(&data_info, &in_data, &in_len); switch(data_info.type & 0x7F) { case SLEEP_FRAME_INDEX_TYPE: frame_index += (*in_data++) << 8; frame_index += (*in_data); health_api_sleep_frame_detail_get(SLEEP_DATA_FRAME_NUMBER_MAX, frame_index, &item_num, item_buf); break; default: break; } in_data = data_info.p_data; in_data += (data_info.len); in_len -= (2 + data_info.len); if (in_len > FRAM_MAX_SIZ) { in_len = 0; } } while (in_len); send_data[write_idx++] = 0x04;//DIAL_NUM LTV send_data[write_idx++] = SLEEP_FRAME_INDEX_TYPE; send_data[write_idx++] = frame_index / 0x100; send_data[write_idx++] = frame_index % 0x100; for(uint16_t i = 0; i < item_num; i++) { send_data[write_idx++] = 3; send_data[write_idx++] = SLEEP_FRAME_LIST_TYPE; send_data[write_idx++] = 3 + 6 + 4; // SLEEP_TYPE len + SLEEP_START_TIME_TYPE len + SLEEP_TIME_OFFSET_TYPE len send_data[write_idx++] = 3; send_data[write_idx++] = SLEEP_TYPE_TYPE; send_data[write_idx++] = item_buf[i].sleep_type; send_data[write_idx++] = 6; send_data[write_idx++] = SLEEP_START_TIME_TYPE; send_data[write_idx++] = (item_buf[i].timestamp & 0xff000000) >> 24; send_data[write_idx++] = (item_buf[i].timestamp & 0x00ff0000) >> 16; send_data[write_idx++] = (item_buf[i].timestamp & 0x0000ff00) >> 8; send_data[write_idx++] = item_buf[i].timestamp & 0xff; send_data[write_idx++] = 4; send_data[write_idx++] = SLEEP_TIME_OFFSET_TYPE; send_data[write_idx++] = item_buf[i].duration / 0x100; send_data[write_idx++] = item_buf[i].duration % 0x100; } BLE_SendFrameById(SLEEP_SERVER, GET_SLEEP_MEASURE_FRAME_DETAIL_ID, send_data, write_idx); vPortFree(item_buf); vPortFree(send_data); *out_len = 0; } /* 4.6.4 睡眠检测开关 */ void ble_set_sleep_measure_switch(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { uint16_t write_idx = 0; protocol_data_info_t data_info = {0}; uint8_t sleep_measure_switch = 0; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch ((data_info.type & 0x7F)) { case SET_SLEEP_MEASURING_SWITCH_TYPE: sleep_measure_switch = *in_data; health_api_set_sleep_measure_sw(sleep_measure_switch); break; default: break; } in_data = data_info.p_data; in_data += (data_info.len); in_len -= (2 + data_info.len); if (in_len > FRAM_MAX_SIZ) { in_len = 0; } } while (in_len); write_idx = user_set_protocol_error(out_data, SLEEP_SERVER, data_info.error); *out_len = write_idx; } const p_func_t sleep_server_func[SLEEP_SERVERE_MAX_ID] = { user_null_func, ble_get_sleep_measure_frame_number, //4.6.1 APP获取睡眠帧数 user_null_func, //4.6.2 设备主动通知APP获取睡眠数据 ble_get_sleep_measure_frame_detail, //4.6.3 APP获取睡眠详情片段数据 ble_set_sleep_measure_switch, //4.6.4 睡眠检测开关 };