192 lines
7.0 KiB
C
192 lines
7.0 KiB
C
/*----------------------------------------------------------------------------
|
||
* 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 睡眠检测开关
|
||
};
|
||
|