mcu_hi3321_watch/tjd/ble/protocol/ble_sleep_server.c
2025-05-26 20:15:20 +08:00

192 lines
7.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*----------------------------------------------------------------------------
* 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 睡眠检测开关
};