/*---------------------------------------------------------------------------- * Copyright (c) Fenda Technologies Co., Ltd. 2021. All rights reserved. * * Description: ble_exercise_server.h * * Author: shey.tanxiaoyu * * Create: 2022-04-20 *--------------------------------------------------------------------------*/ #include "ble_exercise_server.h" #include "ble_data_transmission.h" #include "exercise_api.h" #include "health_api.h" #include "ui_event.h" #include "task_ui.h" #define ENABLE_STATIC_PRINT 0 extern uint32_t am_util_stdio_printf(const char *pcFmt, ...); #define static_print_error(...) am_util_stdio_printf(__VA_ARGS__)//错误打印一般常开 #if ENABLE_STATIC_PRINT #define static_print_info(...) am_util_stdio_printf(__VA_ARGS__)//一般信息打印宏控制 #else #define static_print_info(...) #endif //static void debug_printf(protocol_data_info_t data_info) //{ // uint32_t i; // // static_print_info("%02x ", data_info.len + 2); // static_print_info("%02x ", data_info.type); // for (i = 0; i < data_info.len; i++) { // static_print_info("%02x ", data_info.p_data[i]); // } // static_print_info("\n"); //} #define NUMBER_OF_EXERCISE_RECORD_OBTAINED 20 #define NUMBER_OF_EXERCISE_DETAIL_ITEM_EACH_FRAME 20 #define NUMBER_OF_EXERCISE_PACE_ITEM_EACH_FRAME 20 #define NUMBER_OF_EXERCISE_GPS_ITEM_EACH_FRAME 20 #define NUMBER_OF_EXERCISE_SPEED_ITEM_EACH_FRAME 20 static exercise_record_frame_info_t_t record_info_list[NUMBER_OF_EXERCISE_RECORD_OBTAINED]; static exercise_record_frame_info_t_t *record_info_find(uint16_t record_id) { uint32_t i; uint8_t idx = 0; for (i = 0; i < NUMBER_OF_EXERCISE_RECORD_OBTAINED; i++) { if (record_info_list[i].record_id == record_id) { idx = i; break; } } return &record_info_list[idx]; } /* 4.9.1 APP同步运动状态 */ void ble_app_sync_exercise_state(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { protocol_data_info_t data_info = {0}; uint32_t temp_val = 0; uint16_t write_idx = 0; uint8_t exercise_state = 0; uint8_t start_mode = 0; uint8_t exercise_type = 0; WorkoutSyncStatus tmpStatus = {0}; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch (data_info.type & 0x7F) { case 0x01: exercise_state = data_info.p_data[0]; break; case 0x02: start_mode = data_info.p_data[0]; break; case 0x03: exercise_type = data_info.p_data[0]; break; case 0x04: temp_val = data_info.p_data[0]; break; case 0x05: temp_val += data_info.p_data[0] << 24; temp_val += data_info.p_data[1] << 16; temp_val += data_info.p_data[2] << 8; temp_val += data_info.p_data[3]; break; case 0x06: temp_val += data_info.p_data[0] << 24; temp_val += data_info.p_data[1] << 16; temp_val += data_info.p_data[2] << 8; temp_val += data_info.p_data[3]; break; case 0x07: temp_val += data_info.p_data[0] << 24; temp_val += data_info.p_data[1] << 16; temp_val += data_info.p_data[2] << 8; temp_val += data_info.p_data[3]; break; case 0x08: temp_val += data_info.p_data[0] << 24; temp_val += data_info.p_data[1] << 16; temp_val += data_info.p_data[2] << 8; temp_val += data_info.p_data[3]; break; case 0x09: temp_val += data_info.p_data[0] << 24; temp_val += data_info.p_data[1] << 16; temp_val += data_info.p_data[2] << 8; temp_val += data_info.p_data[3]; break; default: data_info.error = PARAM_ERROR; 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); tmpStatus.workoutSub.workoutOperator = exercise_state; tmpStatus.workoutSub.workoutSport = start_mode; tmpStatus.workoutSub.workoutType = exercise_type; if (data_info.error == FENDA_SUCCESS) { task_ui_notify(EVENT_WORKOUT_SYNC,tmpStatus.workout,NULL,0); } write_idx = user_set_protocol_error(out_data, EXERCISE_SERVER, data_info.error); *out_len = write_idx; } /* 4.9.2 设备主动上报执行状态 */ void ble_exercise_state_report(void *p_buf) { uint16_t write_idx = 0; uint8_t send_buf[16] = {0}; send_buf[write_idx++] = 0x03; send_buf[write_idx++] = 0x01; send_buf[write_idx++] = exercise_api_exercise_state_get(); send_buf[write_idx++] = 0x03; send_buf[write_idx++] = 0x02; send_buf[write_idx++] = exercise_api_start_mode_get(); send_buf[write_idx++] = 0x03; send_buf[write_idx++] = 0x03; send_buf[write_idx++] = exercise_api_exercise_type_get(); send_buf[write_idx++] = 0x06; send_buf[write_idx++] = 0x04; send_buf[write_idx++] = (exercise_api_start_timestamp_get() >> 24) & 0xFF; send_buf[write_idx++] = (exercise_api_start_timestamp_get() >> 16) & 0xFF; send_buf[write_idx++] = (exercise_api_start_timestamp_get() >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_start_timestamp_get() & 0xFF; BLE_SendFrameById(EXERCISE_SERVER, EXERCISE_STATE_REPORT_ID, send_buf, write_idx); } /* 4.9.3 查询设备运动状态 */ void ble_get_exercise_state(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { protocol_data_info_t data_info = {0}; uint16_t write_idx = 0; uint8_t send_buf[16] = {0}; uint8_t exercise_state = 0; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch (data_info.type & 0x7F) { case 0x05: if ((health_api_get_bp_measure_sw() == 1) || (exercise_api_exercise_state_get() == 1) || (exercise_api_exercise_state_get() == 2) || (exercise_api_exercise_state_get() == 3)) { exercise_state = 0; } else if ((exercise_api_exercise_state_get() == 0) || (exercise_api_exercise_state_get() == 4)) { exercise_state = 4; } send_buf[write_idx++] = 0x03; send_buf[write_idx++] = 0x01; send_buf[write_idx++] = exercise_state; send_buf[write_idx++] = 0x03; send_buf[write_idx++] = 0x02; send_buf[write_idx++] = exercise_api_start_mode_get(); send_buf[write_idx++] = 0x03; send_buf[write_idx++] = 0x03; send_buf[write_idx++] = exercise_api_exercise_type_get(); send_buf[write_idx++] = 0x06; send_buf[write_idx++] = 0x04; send_buf[write_idx++] = (exercise_api_start_timestamp_get() >> 24) & 0xFF; send_buf[write_idx++] = (exercise_api_start_timestamp_get() >> 16) & 0xFF; send_buf[write_idx++] = (exercise_api_start_timestamp_get() >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_start_timestamp_get() & 0xFF; break; default: data_info.error = PARAM_ERROR; 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); if (data_info.error == FENDA_SUCCESS) { BLE_SendFrameById(EXERCISE_SERVER, GET_EXERCISE_STATE_ID, send_buf, write_idx); } *out_len = 0; } /* 4.9.4 通知设备开启关闭运动数据上报 */ void ble_set_exercise_state_report_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}; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch (data_info.type & 0x7F) { case 0x01: static_print_info("ble_set_exercise_state_report_switch = %d\n", data_info.p_data[0]); /* 运动数据上报: 0=关闭; 1=开启 */ 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, EXERCISE_SERVER, data_info.error); *out_len = write_idx; } /* 4.9.5 设备主动上报实时运动数据信息 */ void ble_exercise_real_info_report(void *p_buf) { uint16_t write_idx = 0; uint8_t send_buf[57] = {0}; send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x01; send_buf[write_idx++] = (exercise_api_total_time_get() >> 24) & 0xFF; send_buf[write_idx++] = (exercise_api_total_time_get() >> 16) & 0xFF; send_buf[write_idx++] = (exercise_api_total_time_get() >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_total_time_get() & 0xFF; send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x02; send_buf[write_idx++] = (exercise_api_total_distance_get() * 10 >> 24) & 0xFF; send_buf[write_idx++] = (exercise_api_total_distance_get() * 10 >> 16) & 0xFF; send_buf[write_idx++] = (exercise_api_total_distance_get() * 10 >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_total_distance_get() * 10 & 0xFF; send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x03; send_buf[write_idx++] = (exercise_api_total_calorie_get() >> 24) & 0xFF; send_buf[write_idx++] = (exercise_api_total_calorie_get() >> 16) & 0xFF; send_buf[write_idx++] = (exercise_api_total_calorie_get() >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_total_calorie_get() & 0xFF; send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x04; send_buf[write_idx++] = (exercise_api_step_freq_real_get() >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_step_freq_real_get() & 0xFF; send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x05; send_buf[write_idx++] = exercise_api_hr_real_get(); send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x06; send_buf[write_idx++] = exercise_api_hr_zone_get(); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x07; send_buf[write_idx++] = (exercise_api_pace_real_get() >> 24) & 0xFF; send_buf[write_idx++] = (exercise_api_pace_real_get() >> 16) & 0xFF; send_buf[write_idx++] = (exercise_api_pace_real_get() >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_pace_real_get() & 0xFF; send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x08; send_buf[write_idx++] = (exercise_api_real_timestamp_get() >> 24) & 0xFF; send_buf[write_idx++] = (exercise_api_real_timestamp_get() >> 16) & 0xFF; send_buf[write_idx++] = (exercise_api_real_timestamp_get() >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_real_timestamp_get() & 0xFF; send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x09; send_buf[write_idx++] = exercise_api_exercise_state_get(); send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x10; send_buf[write_idx++] = exercise_api_exercise_type_get(); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x11; send_buf[write_idx++] = (exercise_api_total_step_get() >> 24) & 0xFF; send_buf[write_idx++] = (exercise_api_total_step_get() >> 16) & 0xFF; send_buf[write_idx++] = (exercise_api_total_step_get() >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_total_step_get() & 0xFF; send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x12; send_buf[write_idx++] = (exercise_api_speed_real_get() >> 8) & 0xFF; send_buf[write_idx++] = exercise_api_speed_real_get() & 0xFF; BLE_SendFrameById(EXERCISE_SERVER, EXERCISE_REAL_INFO_REPORT_ID, send_buf, write_idx); } /* 4.9.6 获取单次运动记录帧数信息 */ void ble_get_exercise_record_frame_info(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { protocol_data_info_t data_info = {0}; uint32_t start_timestamp = 0; uint32_t end_timestamp = 0; uint32_t item_num = 0; uint32_t frame_num = 0; uint32_t i; uint16_t write_idx = 0; uint8_t send_buf[512] = {0}; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch (data_info.type & 0x7F) { case 0x01: break; case 0x02: start_timestamp += data_info.p_data[0] << 24; start_timestamp += data_info.p_data[1] << 16; start_timestamp += data_info.p_data[2] << 8; start_timestamp += data_info.p_data[3]; break; case 0x03: end_timestamp += data_info.p_data[0] << 24; end_timestamp += data_info.p_data[1] << 16; end_timestamp += data_info.p_data[2] << 8; end_timestamp += data_info.p_data[3]; exercise_api_exercise_record_frame_info_get(NUMBER_OF_EXERCISE_RECORD_OBTAINED, start_timestamp, end_timestamp, &item_num, record_info_list); static_print_info("start_timestamp %d, end_timestamp %d, item_num %d\n", start_timestamp, end_timestamp, item_num); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x04; send_buf[write_idx++] = (item_num >> 8) & 0xFF; send_buf[write_idx++] = item_num & 0xFF; for (i = 0; i < item_num; i++) { send_buf[write_idx++] = 3; send_buf[write_idx++] = 0xFE; send_buf[write_idx++] = 20; send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x05; send_buf[write_idx++] = record_info_list[i].record_id >> 8; send_buf[write_idx++] = record_info_list[i].record_id; static_print_info("record_id = %d\n", record_info_list[i].record_id); frame_num = record_info_list[i].item_num_detail / NUMBER_OF_EXERCISE_DETAIL_ITEM_EACH_FRAME; if (record_info_list[i].item_num_detail % NUMBER_OF_EXERCISE_DETAIL_ITEM_EACH_FRAME) { frame_num++; } static_print_info("item_num_detail = %d\n", frame_num); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x06; send_buf[write_idx++] = frame_num >> 8; send_buf[write_idx++] = frame_num; frame_num = record_info_list[i].item_num_pace / NUMBER_OF_EXERCISE_PACE_ITEM_EACH_FRAME; if (record_info_list[i].item_num_pace % NUMBER_OF_EXERCISE_PACE_ITEM_EACH_FRAME) { frame_num++; } static_print_info("item_num_pace = %d\n", frame_num); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x07; send_buf[write_idx++] = frame_num >> 8; send_buf[write_idx++] = frame_num; frame_num = record_info_list[i].item_num_gps / NUMBER_OF_EXERCISE_GPS_ITEM_EACH_FRAME; if (record_info_list[i].item_num_gps % NUMBER_OF_EXERCISE_GPS_ITEM_EACH_FRAME) { frame_num++; } static_print_info("item_num_gps = %d\n", frame_num); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x10; send_buf[write_idx++] = frame_num >> 8; send_buf[write_idx++] = frame_num; frame_num = record_info_list[i].item_num_speed / NUMBER_OF_EXERCISE_SPEED_ITEM_EACH_FRAME; if (record_info_list[i].item_num_speed % NUMBER_OF_EXERCISE_SPEED_ITEM_EACH_FRAME) { frame_num++; } static_print_info("item_num_speed = %d\n", frame_num); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x11; send_buf[write_idx++] = frame_num >> 8; send_buf[write_idx++] = frame_num; } static_print_info("ble_get_exercise_record_frame_info ***write_idx %d\n", write_idx); BLE_SendFrameById(EXERCISE_SERVER, GET_EXERCISE_RECORD_FRAME_INFO_ID, send_buf, write_idx); 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_len = 0; } /* 4.9.7 获取单次运动记录统计值信息 */ void ble_get_exercise_record_stats(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { protocol_data_info_t data_info = {0}; uint16_t record_id = 0; exercise_record_frame_info_t_t *exercise_record_frame_info_t = NULL; struct tm *convert_date_time = {0}; exercise_stats_data_t record_stats = {0}; uint16_t write_idx = 0; uint8_t send_buf[512] = {0}; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch (data_info.type & 0x7F) { case 0x01: record_id += data_info.p_data[0] << 8; record_id += data_info.p_data[1]; static_print_info("!!!!!!!!!record_id %d\n", record_id); exercise_record_frame_info_t = record_info_find(record_id); static_print_info( "record_id %d\n" "start_timestamp %d\n" "end_timestamp %d\n" "item_num_gps %d\n" "item_num_detail %d\n" "item_num_pace %d\n" "item_num_speed %d\n", exercise_record_frame_info_t->record_id, exercise_record_frame_info_t->start_timestamp, exercise_record_frame_info_t->end_timestamp, exercise_record_frame_info_t->item_num_gps, exercise_record_frame_info_t->item_num_detail, exercise_record_frame_info_t->item_num_pace, exercise_record_frame_info_t->item_num_speed); convert_date_time = rtc_api_get_datetime_by_timestamp(exercise_record_frame_info_t->start_timestamp); exercise_api_exercise_record_stats_get(convert_date_time, record_id, &record_stats); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x01; send_buf[write_idx++] = record_id >> 8; send_buf[write_idx++] = record_id; static_print_info("record_stats: record_id = %d\n", record_id); send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x02; send_buf[write_idx++] = record_stats.finish_state; static_print_info("record_stats: finish_state = %d\n", record_stats.finish_state); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x03; send_buf[write_idx++] = record_stats.start_timestamp >> 24; send_buf[write_idx++] = record_stats.start_timestamp >> 16; send_buf[write_idx++] = record_stats.start_timestamp >> 8; send_buf[write_idx++] = record_stats.start_timestamp; static_print_info("record_stats: start_timestamp = %d\n", record_stats.start_timestamp); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x04; send_buf[write_idx++] = record_stats.end_timestamp >> 24; send_buf[write_idx++] = record_stats.end_timestamp >> 16; send_buf[write_idx++] = record_stats.end_timestamp >> 8; send_buf[write_idx++] = record_stats.end_timestamp; static_print_info("record_stats: end_timestamp = %d\n", record_stats.end_timestamp); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x05; send_buf[write_idx++] = record_stats.total_calorie >> 24; send_buf[write_idx++] = record_stats.total_calorie >> 16; send_buf[write_idx++] = record_stats.total_calorie >> 8; send_buf[write_idx++] = record_stats.total_calorie; static_print_info("record_stats: total_calorie = %d\n", record_stats.total_calorie); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x06; send_buf[write_idx++] = record_stats.total_distance >> 24; send_buf[write_idx++] = record_stats.total_distance >> 16; send_buf[write_idx++] = record_stats.total_distance >> 8; send_buf[write_idx++] = record_stats.total_distance; static_print_info("record_stats: total_distance = %d\n", record_stats.total_distance); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x07; send_buf[write_idx++] = record_stats.total_step >> 24; send_buf[write_idx++] = record_stats.total_step >> 16; send_buf[write_idx++] = record_stats.total_step >> 8; send_buf[write_idx++] = record_stats.total_step; static_print_info("record_stats: total_step = %d\n", record_stats.total_step); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x08; send_buf[write_idx++] = record_stats.total_time >> 24; send_buf[write_idx++] = record_stats.total_time >> 16; send_buf[write_idx++] = record_stats.total_time >> 8; send_buf[write_idx++] = record_stats.total_time; static_print_info("record_stats: total_time = %d\n", record_stats.total_time); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x09; send_buf[write_idx++] = record_stats.speed_avg >> 8; send_buf[write_idx++] = record_stats.speed_avg; static_print_info("record_stats: speed_avg = %d\n", record_stats.speed_avg); send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x10; send_buf[write_idx++] = record_stats.hr_max; static_print_info("record_stats: hr_max = %d\n", record_stats.hr_max); send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x11; send_buf[write_idx++] = record_stats.hr_min; static_print_info("record_stats: hr_min = %d\n", record_stats.hr_min); send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x12; send_buf[write_idx++] = record_stats.exercise_type; static_print_info("record_stats: exercise_type = %d\n", record_stats.exercise_type); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x13; send_buf[write_idx++] = record_stats.speed_max >> 8; send_buf[write_idx++] = record_stats.speed_max; static_print_info("record_stats: speed_max = %d\n", record_stats.speed_max); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x14; send_buf[write_idx++] = record_stats.speed_min >> 8; send_buf[write_idx++] = record_stats.speed_min; static_print_info("record_stats: speed_min = %d\n", record_stats.speed_min); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x15; send_buf[write_idx++] = record_stats.hr_zone_extremity_time >> 24; send_buf[write_idx++] = record_stats.hr_zone_extremity_time >> 16; send_buf[write_idx++] = record_stats.hr_zone_extremity_time >> 8; send_buf[write_idx++] = record_stats.hr_zone_extremity_time; static_print_info("record_stats: hr_zone_extremity_time = %d\n", record_stats.hr_zone_extremity_time); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x16; send_buf[write_idx++] = record_stats.hr_zone_anaerobic_time >> 24; send_buf[write_idx++] = record_stats.hr_zone_anaerobic_time >> 16; send_buf[write_idx++] = record_stats.hr_zone_anaerobic_time >> 8; send_buf[write_idx++] = record_stats.hr_zone_anaerobic_time; static_print_info("record_stats: hr_zone_anaerobic_time = %d\n", record_stats.hr_zone_anaerobic_time); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x17; send_buf[write_idx++] = record_stats.hr_zone_aerobic_time >> 24; send_buf[write_idx++] = record_stats.hr_zone_aerobic_time >> 16; send_buf[write_idx++] = record_stats.hr_zone_aerobic_time >> 8; send_buf[write_idx++] = record_stats.hr_zone_aerobic_time; static_print_info("record_stats: hr_zone_aerobic_time = %d\n", record_stats.hr_zone_aerobic_time); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x18; send_buf[write_idx++] = record_stats.hr_zone_fat_time >> 24; send_buf[write_idx++] = record_stats.hr_zone_fat_time >> 16; send_buf[write_idx++] = record_stats.hr_zone_fat_time >> 8; send_buf[write_idx++] = record_stats.hr_zone_fat_time; static_print_info("record_stats: hr_zone_fat_time = %d\n", record_stats.hr_zone_fat_time); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x19; send_buf[write_idx++] = record_stats.hr_zone_warm_time >> 24; send_buf[write_idx++] = record_stats.hr_zone_warm_time >> 16; send_buf[write_idx++] = record_stats.hr_zone_warm_time >> 8; send_buf[write_idx++] = record_stats.hr_zone_warm_time; static_print_info("record_stats: hr_zone_warm_time = %d\n", record_stats.hr_zone_warm_time); send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x20; send_buf[write_idx++] = record_stats.hr_avg; static_print_info("record_stats: hr_avg = %d\n", record_stats.hr_avg); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x21; send_buf[write_idx++] = record_stats.pace_avg >> 24; send_buf[write_idx++] = record_stats.pace_avg >> 16; send_buf[write_idx++] = record_stats.pace_avg >> 8; send_buf[write_idx++] = record_stats.pace_avg; static_print_info("record_stats: pace_avg = %d\n", record_stats.pace_avg); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x22; send_buf[write_idx++] = record_stats.step_freq_avg >> 8; send_buf[write_idx++] = record_stats.step_freq_avg; static_print_info("record_stats: step_freq_avg = %d\n", record_stats.step_freq_avg); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x23; send_buf[write_idx++] = record_stats.step_freq_max >> 8; send_buf[write_idx++] = record_stats.step_freq_max; static_print_info("record_stats: step_freq_max = %d\n", record_stats.step_freq_max); send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x24; send_buf[write_idx++] = record_stats.pace_min >> 24; send_buf[write_idx++] = record_stats.pace_min >> 16; send_buf[write_idx++] = record_stats.pace_min >> 8; send_buf[write_idx++] = record_stats.pace_min; static_print_info("record_stats: pace_min = %d\n", record_stats.pace_min); static_print_info("ble_get_exercise_record_stats ***write_idx %d\n", write_idx); BLE_SendFrameById(EXERCISE_SERVER, GET_EXERCISE_RECORD_STATS_ID, send_buf, write_idx); 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_len = 0; } /* 4.9.8 获取单次运动记录详情值信息 */ void ble_get_exercise_record_detail(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { protocol_data_info_t data_info = {0}; uint16_t record_id = 0; uint16_t frame_index = 0; exercise_record_frame_info_t_t *exercise_record_frame_info_t = NULL; struct tm *convert_date_time = {0}; uint32_t item_num = 0; exercise_detail_data_t item_buf[NUMBER_OF_EXERCISE_DETAIL_ITEM_EACH_FRAME]; uint16_t exercise_data_len = 0; uint32_t i; uint16_t write_idx = 0; uint8_t send_buf[512] = {0}; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch (data_info.type & 0x7F) { case 0x01: record_id += data_info.p_data[0] << 8; record_id += data_info.p_data[1]; break; case 0x02: frame_index += data_info.p_data[0] << 8; frame_index += data_info.p_data[1]; static_print_info("ble_get_exercise_record_detail record_id = %d; frame_index = %d\n", record_id, frame_index); exercise_record_frame_info_t = record_info_find(record_id); convert_date_time = rtc_api_get_datetime_by_timestamp(exercise_record_frame_info_t->start_timestamp); exercise_api_exercise_record_detail_get(NUMBER_OF_EXERCISE_DETAIL_ITEM_EACH_FRAME, convert_date_time, record_id, frame_index, &item_num, item_buf); static_print_info("detail_item_num %d\n", item_num); send_buf[write_idx++] = 15; send_buf[write_idx++] = 0x03; send_buf[write_idx++] = record_id >> 8; send_buf[write_idx++] = record_id; send_buf[write_idx++] = frame_index >> 8; send_buf[write_idx++] = frame_index; send_buf[write_idx++] = item_buf[0].timestamp >> 24; send_buf[write_idx++] = item_buf[0].timestamp >> 16; send_buf[write_idx++] = item_buf[0].timestamp >> 8; send_buf[write_idx++] = item_buf[0].timestamp; send_buf[write_idx++] = item_buf[1].timestamp - item_buf[0].timestamp; send_buf[write_idx++] = item_num >> 8; send_buf[write_idx++] = item_num; send_buf[write_idx++] = 9; send_buf[write_idx++] = 0x2F; exercise_data_len = 2 + 9 * item_num; if (exercise_data_len <= 127) { send_buf[write_idx++] = exercise_data_len; } else { exercise_data_len += 1; send_buf[write_idx++] = 0x80 | (exercise_data_len >> 7); send_buf[write_idx++] = exercise_data_len & 0x7F; } send_buf[write_idx++] = 0x04; for (i = 0; i < item_num; i++) { send_buf[write_idx++] = item_buf[i].hr_real; send_buf[write_idx++] = item_buf[i].speed_real >> 8; send_buf[write_idx++] = item_buf[i].speed_real; send_buf[write_idx++] = item_buf[i].pace_real >> 8; send_buf[write_idx++] = item_buf[i].pace_real; send_buf[write_idx++] = item_buf[i].calorie >> 8; send_buf[write_idx++] = item_buf[i].calorie; send_buf[write_idx++] = item_buf[i].step_freq_real >> 8; send_buf[write_idx++] = item_buf[i].step_freq_real; } static_print_info("ble_get_exercise_record_detail ***write_idx %d\n", write_idx); BLE_SendFrameById(EXERCISE_SERVER, GET_EXERCISE_RECORD_DETAIL_ID, send_buf, write_idx); 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_len = 0; } /* 4.9.9 获取配速列表 */ void ble_get_exercise_record_pace(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { protocol_data_info_t data_info = {0}; uint16_t record_id = 0; uint16_t frame_index = 0; exercise_record_frame_info_t_t *exercise_record_frame_info_t = NULL; struct tm *convert_date_time = {0}; uint32_t item_num = 0; exercise_pace_data_t item_buf[NUMBER_OF_EXERCISE_PACE_ITEM_EACH_FRAME]; uint32_t i; uint16_t write_idx = 0; uint8_t send_buf[512] = {0}; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch (data_info.type & 0x7F) { case 0x01: record_id += data_info.p_data[0] << 8; record_id += data_info.p_data[1]; break; case 0x02: frame_index += data_info.p_data[0] << 8; frame_index += data_info.p_data[1]; static_print_info("ble_get_exercise_record_pace record_id = %d; frame_index = %d\n", record_id, frame_index); exercise_record_frame_info_t = record_info_find(record_id); convert_date_time = rtc_api_get_datetime_by_timestamp(exercise_record_frame_info_t->start_timestamp); exercise_api_exercise_record_pace_get(NUMBER_OF_EXERCISE_PACE_ITEM_EACH_FRAME, convert_date_time, record_id, frame_index, &item_num, item_buf); static_print_info("pace_item_num %d\n", item_num); send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x01; send_buf[write_idx++] = record_id >> 8; send_buf[write_idx++] = record_id; send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x02; send_buf[write_idx++] = frame_index >> 8; send_buf[write_idx++] = frame_index; for (i = 0; i < item_num; i++) { if (item_buf[i].incomplete_pace) { send_buf[write_idx++] = 3; send_buf[write_idx++] = 0xFE; send_buf[write_idx++] = 15; } else { send_buf[write_idx++] = 3; send_buf[write_idx++] = 0xFE; send_buf[write_idx++] = 17; } send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x03; send_buf[write_idx++] = item_buf[i].pace_idx >> 8; send_buf[write_idx++] = item_buf[i].pace_idx; send_buf[write_idx++] = 3; send_buf[write_idx++] = 0x04; send_buf[write_idx++] = item_buf[i].unit; if (item_buf[i].incomplete_pace) { send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x06; send_buf[write_idx++] = item_buf[i].incomplete_pace >> 8; send_buf[write_idx++] = item_buf[i].incomplete_pace; } else { send_buf[write_idx++] = 6; send_buf[write_idx++] = 0x05; send_buf[write_idx++] = item_buf[i].complete_pace >> 24; send_buf[write_idx++] = item_buf[i].complete_pace >> 16; send_buf[write_idx++] = item_buf[i].complete_pace >> 8; send_buf[write_idx++] = item_buf[i].complete_pace; } send_buf[write_idx++] = 4; send_buf[write_idx++] = 0x07; send_buf[write_idx++] = item_buf[i].gps_idx >> 8; send_buf[write_idx++] = item_buf[i].gps_idx; } static_print_info("ble_get_exercise_record_pace ***write_idx %d\n", write_idx); BLE_SendFrameById(EXERCISE_SERVER, GET_EXERCISE_RECORD_PACE_ID, send_buf, write_idx); 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_len = 0; } /* 4.9.10 获取运动分段列表 */ void ble_get_exercise_section_info(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { } /* 4.9.11 运动提醒 */ void ble_exercise_remind_report(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { } /* 4.9.12 获取 GPS 轨迹点数据 */ void ble_get_exercise_record_gps(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { protocol_data_info_t data_info = {0}; uint16_t record_id = 0; uint16_t frame_index = 0; exercise_record_frame_info_t_t *exercise_record_frame_info_t = NULL; struct tm *convert_date_time = {0}; uint32_t item_num = 0; exercise_gps_data_t item_buf[NUMBER_OF_EXERCISE_GPS_ITEM_EACH_FRAME]; uint16_t exercise_data_len = 0; uint32_t i; uint16_t time_offset = 0; uint16_t write_idx = 0; uint8_t send_buf[512] = {0}; data_info.error = FENDA_SUCCESS; do { user_get_data_info(&data_info, &in_data, &in_len); switch (data_info.type & 0x7F) { case 0x01: record_id += data_info.p_data[0] << 8; record_id += data_info.p_data[1]; break; case 0x02: frame_index += data_info.p_data[0] << 8; frame_index += data_info.p_data[1]; static_print_info("ble_get_exercise_record_gps record_id = %d; frame_index = %d\n", record_id, frame_index); exercise_record_frame_info_t = record_info_find(record_id); convert_date_time = rtc_api_get_datetime_by_timestamp(exercise_record_frame_info_t->start_timestamp); exercise_api_exercise_record_gps_get(NUMBER_OF_EXERCISE_GPS_ITEM_EACH_FRAME, convert_date_time, record_id, frame_index, &item_num, item_buf); static_print_info("gps_item_num %d\n", item_num); send_buf[write_idx++] = 14; send_buf[write_idx++] = 0x03; send_buf[write_idx++] = record_id >> 8; send_buf[write_idx++] = record_id; send_buf[write_idx++] = frame_index >> 8; send_buf[write_idx++] = frame_index; send_buf[write_idx++] = item_buf[0].timestamp >> 24; send_buf[write_idx++] = item_buf[0].timestamp >> 16; send_buf[write_idx++] = item_buf[0].timestamp >> 8; send_buf[write_idx++] = item_buf[0].timestamp; send_buf[write_idx++] = item_num >> 8; send_buf[write_idx++] = item_num; send_buf[write_idx++] = 13; send_buf[write_idx++] = 0x1F; exercise_data_len = 2 + 13 * item_num; if (exercise_data_len <= 127) { send_buf[write_idx++] = exercise_data_len; } else { exercise_data_len += 1; send_buf[write_idx++] = 0x80 | (exercise_data_len >> 7); send_buf[write_idx++] = exercise_data_len & 0x7F; } send_buf[write_idx++] = 0x04; for (i = 0; i < item_num; i++) { send_buf[write_idx++] = item_buf[i].gps_longtitude >> 24; send_buf[write_idx++] = item_buf[i].gps_longtitude >> 16; send_buf[write_idx++] = item_buf[i].gps_longtitude >> 8; send_buf[write_idx++] = item_buf[i].gps_longtitude; send_buf[write_idx++] = item_buf[i].gps_latitude >> 24; send_buf[write_idx++] = item_buf[i].gps_latitude >> 16; send_buf[write_idx++] = item_buf[i].gps_latitude >> 8; send_buf[write_idx++] = item_buf[i].gps_latitude; send_buf[write_idx++] = item_buf[i].speed_real >> 8; send_buf[write_idx++] = item_buf[i].speed_real; time_offset = item_buf[i].timestamp - item_buf[0].timestamp; send_buf[write_idx++] = time_offset >> 8; send_buf[write_idx++] = time_offset; send_buf[write_idx++] = item_buf[i].gps_point_type; } static_print_info("ble_get_exercise_record_gps ***write_idx %d\n", write_idx); BLE_SendFrameById(EXERCISE_SERVER, GET_EXERCISE_RECORD_GPS_ID, send_buf, write_idx); 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_len = 0; } /* 4.9.13 设备端上报实时详情点 */ void ble_get_exercise_real_info_detail(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { } /* 4.9.14 获取速度列表 */ void ble_get_exercise_speed_info(uint8_t *in_data, uint16_t in_len, uint8_t *out_data, uint16_t *out_len) { } const p_func_t exercise_server_func[EXERCISE_SERVER_MAX_ID] = { user_null_func, ble_app_sync_exercise_state, //4.9.1 APP同步运动状态 user_null_func, //4.9.2 设备主动上报执行状态 ble_get_exercise_state, //4.9.3 查询设备运动状态 ble_set_exercise_state_report_switch, //4.9.4 通知设备开启关闭运动数据上报 user_null_func, //4.9.5 设备主动上报实时运动数据信息 ble_get_exercise_record_frame_info, //4.9.6 获取单次运动记录帧数信息 ble_get_exercise_record_stats, //4.9.7 获取单次运动记录统计值信息 ble_get_exercise_record_detail, //4.9.8 获取单次运动记录详情值信息 ble_get_exercise_record_pace, //4.9.9 获取配速列表 user_null_func, //4.9.a user_null_func, //4.9.b user_null_func, //4.9.c user_null_func, //4.9.d user_null_func, //4.9.e user_null_func, //4.9.f user_null_func, //4.9.10 获取运动分段列表 user_null_func, //4.9.11 运动提醒 ble_get_exercise_record_gps, //4.9.12 获取GPS轨迹点数据 user_null_func, //4.9.13 设备端上报实时详情点 user_null_func, //4.9.14 获取速度列表 };