/*---------------------------------------------------------------------------- * Copyright (c) Fenda Technologies Co., Ltd. 2022. All rights reserved. * * Description: ble_port_protocol.c * * Author: lzc * * Create: 2024-05-27 *--------------------------------------------------------------------------*/ #include "ble_port_protocol.h" #include "ble_api.h" #include "ble_port.h" #include "bts_br_gap.h" #include "bts_gatt_server.h" #include "bts_le_gap.h" #include "ctype.h" #include "osal_addr.h" #include "rtc_api.h" #include "securec.h" #include "sql_all.h" #include "stdlib.h" #include "string.h" #include "sys_config.h" #include "sys_typedef.h" #include "time.h" // #include "TjdUiMessagePopUpPage.h" #include "fcntl.h" #include "fs_api_ext.h" #include "fs_user_common.h" #include "linux/crc32.h" #include "los_ringbuf.h" #include "sys/statfs.h" #include "unistd.h" #include #include #include "power_display_service.h" #include "service_bt.h" #include "thread_init.h" // #include "semaphore.h" #include "upg_porting.h" #include "osal_task.h" #include "osal_semaphore.h" #include "soc_osal.h" #include #include "service_lucky_clover.h" #include "broadcast_feature.h" #include "service_charger.h" #include "service_sleep.h" #include "ble_protocol_file_download.h" #include "ble_protocol_file_upload.h" #include "bundle_install_msg.h" #include "TjdAppStore.h" #include "parameter.h" #ifdef __cplusplus extern "C" { #endif #include "TjdUiAppCameraToC.h" // #include "TjdUiWatchFaceCtrl.h" #include "service_gps.h" #ifdef __cplusplus } #endif #define ENABLE_STATIC_PRINT 0 #define static_print_error(...) sys_bt_log_e(__VA_ARGS__) //错误信息打印一般常开 #define static_print_warn(...) sys_bt_log_w(__VA_ARGS__) //警告信息打印一般常开 #if ENABLE_STATIC_PRINT #define static_print_debug(...) sys_bt_log_d(__VA_ARGS__) #define static_print_info(...) sys_bt_log_i(__VA_ARGS__) #else #define static_print_debug(...) #define static_print_info(...) #endif // #ifdef __cplusplus // extern "C" // { // #endif #define ENABLE_SWITCH 1 #define DISABLE_SWITCH 0 #define PROTOCOL_FRAME_HEAD 0xAB #define PROTOCOL_FRAME_HEAD_2 0xAC #define PROTOCOL_MAX_LEN 23 #define PROTOCOL_DATA_LEN 16 #define PROTOCOL_BUFFER_MAX_LEN 256 #define BT_MAC_ADDR_LEN 6 #define Day_Hours 24 #define MAX_CONTACTS 50 #define PACKET_DATA_SIZE 517 #define FILE_TRAN_RINGBUFFER_SIZE 5000 #define TJD_MAX_FILE_PATH_LEN 128 #define TJD_DEFAULT_FILE_PATH_LEN 64 #define F_OK 0 #define MTU_SIZE 517 #define FS_VOLUMES_NUM 4 #define FS_VOLUME_STRS "/system/", "/update/", "/music/", "/user/" #define FS_VOLUME_USER "/user/" #define FS_VOLUME_UPDATE "/update/" #define FS_NODE_INFO_SPACE 16 #define CONTACTS_DATA_LEN 20 #define TJD_FS_DIR_GPS_BAT TJD_FS_DIR_GPS"bat" #define PATH_MAX 4096 #define TJD_ADDRESS_BOOK_PATH "/user/tjd_phone/addressbook.bin" #define TJD_SCREEN_RESOLUTION_HEIGHT 466 #define TJD_SCREEN_RESOLUTION_WEIGHT 466 #define TJD_QRCODE_TYPE_QQ 0x0c // 宏定义用于设置分辨率 #define SET_RESOLUTION(data, index, resolution) \ do { \ (data)[(index)++] = (resolution >> 8) & 0xFF; \ (data)[(index)++] = (resolution) & 0xFF; \ } while (0) // 宏定义用于设置分辨率的一半 #define SET_HALF_RESOLUTION(data, index, resolution) \ do { \ uint16_t half_resolution = (resolution) / 2; \ (data)[(index)++] = (half_resolution >> 8) & 0xFF; \ (data)[(index)++] = (half_resolution) & 0xFF; \ } while (0) //宏定义用于数据拷贝 #define PROCESS_DATA(ctx, write_cb_para, data_index, write_len, remaining_size, rec_offset, total_len, cmd_id, server_id, conn_id) \ do { \ size_t copy_len = (remaining_size > write_len) ? write_len : remaining_size; \ memcpy_s((ctx).buffer + (rec_offset), (remaining_size), &(write_cb_para)[(data_index) + 2], (copy_len)); \ if ((ctx).buffer_offset != (rec_offset)) { \ static_print_error("ctx.buffer_offset != rec_offset"); \ free((ctx).buffer); \ (ctx).buffer = NULL; \ uint8_t data[2] = {0x00, (ctx).buffer_offset}; \ tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), (cmd_id), (server_id), (conn_id)); \ (ctx).buffer_offset = 0; \ return; \ } \ (ctx).buffer_offset += copy_len; \ } while (0) extern void TjdUiMsgCenterMessagePopUpTrigger(void); extern void TjdUiMsgCenterFindDeviceTrigger(void); extern uint32_t TjdUiWfGetNumberMax(void); extern uint32_t* TjdUiWfGetIDList(uint32_t* len); extern bool TjdUiWfGeUninstallbyID(uint32_t id); //表盘可卸载查询。=true,可卸载;=false,不可卸载。 extern bool TjdUiWfDeletebyID(uint32_t id); //表盘删除通过ID extern bool TjdUiWfInstallBeforNotify(uint32_t id); //表盘安装前通知 extern bool TjdUiWfInstallAfterNotify(uint32_t id); extern bool TjdUiWfUninstallBeforNotify(uint32_t id); //表盘卸载前通知 extern bool TjdUiWfUninstallAfterNotify(uint32_t id); //表盘卸载后通知 extern bool TjdUiWfIsLocalID(uint32_t id); //表盘是否是本地表盘 extern DirDescriptionInfo_t *tjd_ble_get_dir_description(void); extern FileTransferInfo_t *tjd_ble_get_transfer_info(void); void tjd_ble_loop_send_data(uint8_t * pack_head_, uint8_t *data, uint16_t len, uint8_t cmd); typedef struct { uint8_t year; uint8_t month; uint8_t dateth; uint8_t hour; uint8_t minute; uint8_t second; } TimeData; typedef struct { service_sleep_time_t time; sleep_status_t status; } sleep_status_dada; typedef struct { uint8_t flag; //0x00: 读 0x01: 写 uint16_t switch_data; } set_read_function_switch_dada; enum { SHORT_PROTOCOL = 0, LONG_PROTOCOL = 1, MAX_PROTOCOL }; typedef void (*BLECreateQueueFunction_t)(void); typedef struct { osThreadAttr_t attr; osThreadFunc_t func; uint32_t *task_handle; BLECreateQueueFunction_t create_queue_handle; uint32_t use_mem; } ble_task_definition_t; // ble_task_definition_t g_ble_thread_upload_file_data = { { "thread_upload_file_data", 0, NULL, 0, NULL, (0x1000), (osPriority_t)(32), 0, 0 }, // (osThreadFunc_t)upload_file_data, NULL, NULL, USE_DTCM_MEM }; extern uint16_t gatt_server_id; extern uint16_t g_server_conn_id; extern uint16_t g_server_handle; extern const bd_addr_t g_conn_addr; extern bool g_tjd_ble_into_camera_flag; bool g_tjd_ble_ai_audio_trans_flag = false; uint8_t g_res_protoclo_title = 0; uint8_t g_tjd_ble_data_flow_id = 0; static uint16_t g_dial_push_data_pkg = 0; static uint16_t g_wallpaper_push_data_pkg = 0; static uint16_t g_contacts_push_data_pkg = 0; static uint16_t g_qrcode_push_data_pkg = 0; static uint8_t g_dial_push_data_mask = 0; // 表盘推送数据标志位 static uint8_t g_wallpaper_push_data_mask = 0; // 壁纸推送数据标志位 static uint8_t g_contacts_push_data_mask = 0; // 壁纸推送数据标志位 static uint8_t g_qrcode_push_data_mask = 0; // 二维码推送数据标志位 static bool g_fiel_decription_push_data_mask = false; // 文件描述数据推送标志位 static bool g_weather_data_mask = false; // 天气数据推送标志位 static bool g_weather_today_synchronization_data_mask = false; // 天气今日同步数据标志位 static bool g_dial_parameters_data_mask = false; // 表盘数据推送标志位 // uint8_t * ota_upgrade_data_pkg = NULL; UpgradeContext upgrade_context; UpgradeContext dial_context; UpgradeContext wallpaper_context; UpgradeContext contacts_context; UpgradeContext addr_context; UpgradeContext message_context; UpgradeContext qrcode_context; UpgradeContext lucky_flover_context; UpgradeContext weather_data_context; UpgradeContext dial_parameters_data_context; uint32_t g_upload_breakpoint_resume_offset = 0; // 文件上传断点续传切换偏移值 static uint16_t g_file_trasmit_breakpoint_len = 0; custom_dial_parameter_t dial_param = {0}; static lefun_ai_data_callback_t g_lefun_ai_data_callback = NULL; static lefun_ai_data_callback_t g_lefun_ai_data_end_callback = NULL; static fine_phone_end_callback_t g_fine_phone_end_callback = NULL; static play_dial_original_callback_t g_play_dial_original_callback = NULL; static play_dial_preview_callback_t g_play_dial_preview_callback = NULL; static play_dial_request_generate_picture_callback_t g_play_dial_request_generate_picture_callback = NULL; struct data_flow g_data_flow = { .data_flow_id = 0, .data_flow_type = 0, .data = NULL, .len = 0, }; uint8_t pack_data[64] = {0}; Packet g_packet_data = { .pck_data = pack_data, .pck_len = 0, }; // Ringbuf g_file_transport_ringbuf_ctrl = {0}; // static char *g_file_transport_ringbuf = NULL; // static char g_file_transport_ringbuf[FILE_TRAN_RINGBUFFER_SIZE] = {0}; static uint16_t ring_buffer_size = 0; static const char * const g_volume_names[FS_VOLUMES_NUM] = { FS_VOLUME_STRS }; Contact contacts[MAX_CONTACTS]; file_append_data_t file_append_data = {0}; // breakpoint_info_t g_ota_breakpoint_info = {0}; // static const uint8_t g_ble_send_protocol_cmd[][2] = { // [0] = {0x5A, 0x04, 0x8C, 0x05}, // // [1] = {0x5B, 0x5A} // }; // CRC-8 查表 static const uint8_t crc8_table[256] = { 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 }; // 查表计算法计算crc uint8_t do_crc(uint8_t *ptr, uint32_t len) { uint8_t i; uint8_t crc = 0x00; while (len--) { crc = crc8_table[(crc ^ *ptr++) & 0xFF]; } return crc; } // 分块读取文件并计算CRC32值的函数 uint32_t calculateFileCRC32(const char *filename, size_t fileSize) { const size_t bufferSize = 4096; // 缓冲区大小,可根据实际情况调整 uint8_t *buffer = malloc(bufferSize); if (buffer == NULL) { static_print_error("malloc failed"); return 0; // 或者返回一个错误CRC32值 } memset_s(buffer, bufferSize, 0, bufferSize); uint32_t crc32Value = 0xffffffff; // 初始CRC32值 size_t offset = 0; // 当前读取位置 int32_t fd = open(filename, O_RDONLY); if (fd < 0) { static_print_error("open file failed"); free(buffer); buffer = NULL; return 0; // 或者返回一个错误CRC32值 } int ret = 0; while (offset < fileSize) { size_t bytesToRead = (fileSize - offset > bufferSize) ? bufferSize : (fileSize - offset); ret = lseek(fd, offset, SEEK_SET); size_t bytesRead = read(fd, buffer, bytesToRead); if(bytesRead == 0){ break; } // 更新CRC32 crc32Value = crc32(crc32Value, buffer, bytesRead); offset += bytesRead; // static_print_debug("offset : %d, bytesToRead : %d, bytesRead : %d, crc32Value : %8x", offset, bytesToRead, bytesRead, crc32Value); } close(fd); // 释放内存 free(buffer); buffer = NULL; return crc32Value; } // 文件装载 uint32_t tjd_ble_load_file_data(const char *path, uint32_t oft, void *buffer, uint32_t size) { int ret = RET_SUCCESS; // int len; static_print_debug("tjd_fs_api_file_load_1:%s-%d-%d\r\n",path,oft,size); FILE * fp = fopen(path, "rb"); if(fp == NULL) { static_print_error("fopen %s failed!", path); return ret; } if(oft >= 0) { ret = fseek(fp, oft, SEEK_SET); if(ret != 0) { static_print_error("fseek %d oft file data failed! ret : %d" , oft , ret); fclose(fp); fp = NULL; return ret; } } if(size > 0) { ret = fread(buffer, size, 1 , fp); if(ret != 1){ static_print_error("fread %d size file data failed! ret : %d" , size , ret); fclose(fp); fp = NULL; return ret; } } fclose(fp); return ret; } static char *hex_to_string(const char *hex_str) { size_t len = strlen(hex_str); if (len % 3 != 0) { static_print_error("Error: Hex string length must be odd number."); return NULL; } size_t str_len = len / 3; char *decoded_str = (char *)malloc(str_len + 1); // +1 for null terminator if (decoded_str == NULL) { static_print_error("Error: Failed to allocate memory for decoded string."); return NULL; } decoded_str[str_len] = '\0'; for (size_t i = 0, j = 0; i < len; i += 2, ++j) { char byte[3] = {hex_str[i], hex_str[i + 1], '\0'}; decoded_str[j] = strtol(byte, NULL, 16); } return decoded_str; } //获取文件大小 int tjd_ble_get_file_size(const char *filename) { int len = 0; // FILE *fp = fopen(filename, "rb"); // if (fp == NULL) { // static_print_error("fopen %s failed", filename); // return 0; // } // fseek(fp, 0, SEEK_END); // len = ftell(fp); // fseek(fp, 0, SEEK_SET); // fclose(fp); struct stat fileStat = {0}; int ret = stat(filename,&fileStat); if(ret == 0){ len = fileStat.st_size; } static_print_debug(" %s len:%d", filename ,len); return len; } //删除文件 int tjd_remove_rsvd_part(char *base_dir, char *filename) { char file_path[TJD_MAX_FILE_PATH_LEN] = {0}; int size = sprintf_s(file_path, sizeof(file_path), "%s/%s", base_dir, filename); if (size < 0) { return -1; } int ret = unlink(file_path); if (ret < 0) { return -1; } else { return 0; } } // 安全地拼接路径 char* safe_path_join(const char *path, const char *name) { char *result = malloc(PATH_MAX); if (result == NULL) { static_print_error("malloc error"); return NULL; } snprintf(result, PATH_MAX, "%s/%s", path, name); return result; } // 删除单个文件或目录 int delete_file_or_directory(const char *path) { struct stat st; if (stat(path, &st) == -1) { static_print_error("stat error"); return -1; } if (S_ISREG(st.st_mode)) { if (remove(path) == -1) { static_print_error("remove error"); return -1; } } else if (S_ISDIR(st.st_mode)) { if (rmdir(path) == -1) { static_print_error("rmdir error"); return -1; } } else { fprintf(stderr, "Unsupported file type: %s\n", path); return -1; } return 0; } // 递归删除目录 int delete_directory(const char *path) { DIR *dir; struct dirent *entry; if ((dir = opendir(path)) == NULL) { static_print_error("opendir error"); return -1; } while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } char *fullPath = safe_path_join(path, entry->d_name); if (fullPath == NULL) { closedir(dir); return -1; } if (delete_file_or_directory(fullPath) == -1) { free(fullPath); closedir(dir); return -1; } free(fullPath); } closedir(dir); // 最后删除当前目录 if (rmdir(path) == -1) { static_print_error("rmdir error"); return -1; } return 0; } // 应答封包 static Packet *tjd_ble_protocol_pack_data(uint8_t pack_head,uint8_t *data, uint16_t len, uint8_t cmd_id) { uint8_t res_data[PROTOCOL_MAX_LEN] = {0}; uint16_t res_data_len = 0; res_data[0] = pack_head; if (res_data[0] == PROTOCOL_RES_FRAME_HEAD) { res_data_len = 0x04 + len; res_data[1] = 0x04 + len; res_data[2] = cmd_id; memcpy_s(&res_data[3], PROTOCOL_DATA_LEN, data, (size_t)len); } else if (res_data[0] == PROTOCOL_RES_FRAME_HEAD_2) { res_data_len = 0x05 + len; res_data[1] = res_data_len >> 8; res_data[2] = res_data_len & 0xff; res_data[3] = cmd_id; memcpy_s(&res_data[4], PROTOCOL_DATA_LEN, data, (size_t)len); } res_data[res_data_len - 1] = do_crc(res_data, res_data_len - 1); memset(g_packet_data.pck_data, 0, PROTOCOL_MAX_LEN); memcpy_s(g_packet_data.pck_data, PROTOCOL_MAX_LEN, res_data, res_data_len); g_packet_data.pck_len = res_data_len; // static_print_debug("pack data len: %d", pkt->pck_len); return &g_packet_data; } // 主动封包 static Packet *tjd_ble_protocol_pack_data_with_malloc(uint8_t * pack_head , uint8_t *data, uint16_t len, uint8_t cmd_id) { uint8_t res_data[PROTOCOL_BUFFER_MAX_LEN] = {0}; uint16_t res_data_len = 0; res_data[0] = *pack_head; if (res_data[0] == PROTOCOL_RES_FRAME_HEAD) { res_data_len = 0x04 + len; res_data[1] = 0x04 + len; res_data[2] = cmd_id; memcpy(&res_data[3], data, (size_t)len); } else if (res_data[0] == PROTOCOL_RES_FRAME_HEAD_2) { res_data_len = 0x05 + len; res_data[1] = res_data_len >> 8; res_data[2] = res_data_len & 0xff; res_data[3] = cmd_id; memcpy(&res_data[4], data, (size_t)len); } res_data[res_data_len - 1] = do_crc(res_data, res_data_len - 1); Packet *pkt = malloc(sizeof(Packet)); if (pkt == NULL) { static_print_error("pkt is NULL"); return NULL; } pkt->pck_data = malloc(res_data_len); if (pkt->pck_data == NULL) { static_print_error("pkt.pck_data is NULL"); return NULL; } memcpy(pkt->pck_data, res_data, res_data_len); pkt->pck_len = res_data_len; // static_print_debug("pack data len: %d", pkt->pck_len); return pkt; } void gatt_send_response(uint8_t *res_value, uint16_t res_len, uint8_t server_id, uint16_t conn_id) { gatts_ntf_ind_t param = {0}; param.attr_handle = g_server_handle; param.value = (uint16_t *)malloc(res_len); if (param.value == NULL) { static_print_error("param.value is NULL"); return; } memcpy_s(param.value, res_len, res_value, res_len); // param.value = res_value; param.value_len = res_len; static_print_debug("gatt_send_response(server_id:%d,conn_id:%d),res_len=%d", server_id, conn_id, res_len); for (int i = 0; i < param.value_len;) { static_print_info("%02x", param.value[i]); i++; if(i % 10 == 0){ static_print_info("\r\n"); } if(i >= 30) {break;} } static_print_info("\r\n"); errcode_t ret; ret = gatts_notify_indicate(server_id, conn_id, ¶m); static_print_info("gatts_notify_indicate()=%d\r\n", ret); free(param.value); return; } // 封包,发送数据 void tjd_ble_protocol_send_data(uint8_t pack_head,uint8_t *data, uint16_t len, uint8_t cmd_id, uint8_t server_id, uint16_t conn_id) { Packet *notify_data = tjd_ble_protocol_pack_data(pack_head, data, len, cmd_id); if (notify_data == NULL) { static_print_error("pkt is NULL"); return; } gatt_send_response(notify_data->pck_data, notify_data->pck_len, server_id, conn_id); // free(notify_data->pck_data); // free(notify_data); return; } // 封包,发送数据,释放堆内存 void tjd_ble_protocol_send_lefun_data(uint8_t *pack_head, uint8_t *data, uint16_t len, uint8_t cmd_id) { Packet *notify_data = tjd_ble_protocol_pack_data_with_malloc(pack_head, data, len, cmd_id); if (notify_data == NULL) { static_print_error("pkt is NULL"); return; } gatt_send_response(notify_data->pck_data, notify_data->pck_len,gatt_server_id,g_server_conn_id); free(notify_data->pck_data); free(notify_data); return; } void handle_device_dial_information_cmd(uint8_t server_id, uint16_t conn_id, uint8_t * write_cb_para, uint16_t len, uint8_t cmd_id) { static_print_debug("upload device_dial_information"); uint32_t device_dial_support_num = TjdUiWfGetNumberMax(); uint32_t device_dial_cur_num = 0; uint32_t * watchfaceidarray = TjdUiWfGetIDList(&device_dial_cur_num); // device_dial_cur_num--; uint8_t ltv_type_num = 2; static_print_info("watchfaceidarray data "); for(int i = 0; i < device_dial_cur_num; i++){ static_print_info("%d ", watchfaceidarray[i]); if(i % 4 == 0){ static_print_info("\n"); } static_print_info("\n"); } static_print_debug("device_dial_support_num: %d , cur_num: %d", device_dial_support_num, device_dial_cur_num); uint8_t lt_len = 2 * ((device_dial_cur_num * ltv_type_num) + 1); // 2 : type + len 6: FileDescriptionPacket的字段个数 uint16_t data_len = lt_len + 1 + ((sizeof(uint32_t) + sizeof(uint8_t)) * device_dial_cur_num); uint8_t *device_dial_info_data = malloc(data_len); memset_s(device_dial_info_data, data_len, 0, data_len); int data_index = 0; device_dial_info_data[data_index++] = sizeof(uint8_t) + 2; device_dial_info_data[data_index++] = 0x01; device_dial_info_data[data_index++] = device_dial_support_num; for(int i = 0 ; i < device_dial_cur_num; i++){ // static_print_debug("%s , line is %d", __FUNCTION__, __LINE__); device_dial_info_data[data_index++] = sizeof(watchfaceidarray[i]) + 2; device_dial_info_data[data_index++] = 0x10; // memcpy_s(&device_dial_info_data[data_index], 4, &watchfaceidarray[i], 4); device_dial_info_data[data_index++] = (watchfaceidarray[i] >> 24) & 0xFF; device_dial_info_data[data_index++] = (watchfaceidarray[i] >> 16) & 0xFF; device_dial_info_data[data_index++] = (watchfaceidarray[i] >> 8) & 0xFF; device_dial_info_data[data_index++] = watchfaceidarray[i] & 0xFF; device_dial_info_data[data_index++] = 0x03; device_dial_info_data[data_index++] = 0x11; device_dial_info_data[data_index++] = TjdUiWfGeUninstallbyID(watchfaceidarray[i]) ? 0x01 : 0x00; } uint8_t *sub_package_data = malloc(data_len + 5); int index = 0; sub_package_data[index++] = PROTOCOL_RES_FRAME_HEAD_2; sub_package_data[index++] = (data_len + 5) >> 8; sub_package_data[index++] = (data_len + 5) & 0xff; sub_package_data[index++] = cmd_id; memcpy_s(&sub_package_data[index], data_len, &device_dial_info_data[0], data_len); index += data_len; sub_package_data[index] = do_crc(sub_package_data, data_len + 4); gatt_send_response(sub_package_data, data_len + 5,gatt_server_id,g_server_conn_id); free(sub_package_data); sub_package_data = NULL; free(device_dial_info_data); device_dial_info_data = NULL; } void handle_app_issue_dial_parameters_cmd(uint8_t server_id, uint16_t conn_id, uint8_t * write_cb_para, uint16_t len, uint8_t cmd_id) { static_print_debug("app issue dial parameters data"); for(int i = 0 ; i < len; i++){ static_print_info("%02x", write_cb_para[i]); if( i % 10 == 0){ static_print_info("\r\n"); } } static_print_info("\r\n"); uint8_t data_index = 4; uint8_t dial_parameters_data_total_len = write_cb_para[data_index]; uint8_t rec_dial_parameters_data_offset = write_cb_para[data_index + 1]; uint16_t write_len = len - 7; uint16_t remaining_size = dial_parameters_data_total_len - rec_dial_parameters_data_offset; if (!g_dial_parameters_data_mask) { // static_print_debug("%s , line is %d", __FUNCTION__, __LINE__); memset_s(&dial_parameters_data_context, sizeof(dial_parameters_data_context), 0, sizeof(dial_parameters_data_context)); dial_parameters_data_context.buffer_offset = 0; dial_parameters_data_context.buffer = (uint8_t *)malloc(dial_parameters_data_total_len); memset_s(dial_parameters_data_context.buffer, dial_parameters_data_total_len, 0, dial_parameters_data_total_len); static_print_debug("weather_data_total_len : %d, rec_weather_data_offset : %d", dial_parameters_data_total_len, rec_dial_parameters_data_offset); PROCESS_DATA(dial_parameters_data_context,write_cb_para,data_index,write_len,remaining_size, rec_dial_parameters_data_offset,dial_parameters_data_total_len,cmd_id,server_id,conn_id); g_dial_parameters_data_mask = true; } else { PROCESS_DATA(dial_parameters_data_context,write_cb_para,data_index,write_len,remaining_size, rec_dial_parameters_data_offset,dial_parameters_data_total_len,cmd_id,server_id,conn_id); } if (dial_parameters_data_context.buffer_offset == dial_parameters_data_total_len) { g_dial_parameters_data_mask = false; // uint8_t setting_pattern = 0; // uint8_t images_number = 0; // uint8_t switching_mode = 0; static_print_info("dial_parameters_data : \n"); for(int i = 0; i < dial_parameters_data_total_len ; i++){ static_print_info(" %02x",dial_parameters_data_context.buffer[i]); } static_print_info("\n"); for (int i = 0; i < dial_parameters_data_total_len;) { // 遍历表盘参数数据 uint8_t len = dial_parameters_data_context.buffer[i]; uint8_t type = dial_parameters_data_context.buffer[i + 1]; // static_print_debug("i : %u, type : %u, len : %u", i, type, len); switch (type) { case 0x83: { // (uint8_t)设置模式 // setting_pattern = dial_parameters_data_context.buffer[i + 2]; // static_print_debug("setting_pattern : %u", setting_pattern); dial_param.setting_mode = dial_parameters_data_context.buffer[i + 2]; static_print_debug("setting_mode : %u",dial_param.setting_mode); break; } case 0x84: { // (uint8_t)多图文件中图片数量 // images_number = dial_parameters_data_context.buffer[i + 2]; // static_print_debug("images_number : %u", images_number); dial_param.images_number = dial_parameters_data_context.buffer[i + 2]; static_print_debug("images_number : %u",dial_param.images_number); break; } case 0x85: { // (uint8_t)多图切换方式 // switching_mode = dial_parameters_data_context.buffer[i + 2]; // static_print_debug("switching_mode : %u", switching_mode); dial_param.switching_mode = dial_parameters_data_context.buffer[i + 2]; static_print_debug("switching_mode : %u",dial_param.switching_mode); break; } default: { static_print_error("unknown type : %u", type); break; } } i += len; } free(dial_parameters_data_context.buffer); uint8_t data[2] ={0}; data[0] = 0x02; data[1] = dial_parameters_data_context.buffer_offset & 0xFF; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); dial_parameters_data_context.buffer = NULL; dial_parameters_data_context.buffer_offset = 0; dial_parameters_data_context.expected_seq = 0; return; } else { uint8_t data[2] ={0}; data[0] = 0x01; data[1] = dial_parameters_data_context.buffer_offset & 0xFF; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); return; } } void handle_weather_data_cmd(uint8_t server_id, uint16_t conn_id, uint8_t * write_cb_para, uint16_t len, uint8_t cmd_id) { // uint8_t weather_data_total_len = write_cb_para[4]; // uint8_t cur_offest = write_cb_para[5]; // uint16_t data_len = len - 7; static_print_debug("weather data :"); for(int i = 0 ; i < len; i++){ static_print_info("%02x", write_cb_para[i]); if( i % 10 == 0){ static_print_info("\r\n"); } } static_print_info("\r\n"); uint8_t data_index = 4; uint16_t weather_data_total_len = write_cb_para[data_index] << 8 | write_cb_para[data_index + 1]; uint16_t rec_weather_data_offset = write_cb_para[data_index + 2] << 8| write_cb_para[data_index + 3]; uint16_t write_len = len - 7; uint16_t remaining_size = weather_data_total_len - rec_weather_data_offset; if (!g_weather_data_mask) { // static_print_debug("%s , line is %d", __FUNCTION__, __LINE__); memset_s(&weather_data_context, sizeof(weather_data_context), 0, sizeof(weather_data_context)); weather_data_context.buffer_offset = 0; weather_data_context.buffer = (uint8_t *)malloc(weather_data_total_len); memset_s(weather_data_context.buffer, weather_data_total_len, 0, weather_data_total_len); static_print_debug("weather_data_total_len : %d, rec_weather_data_offset : %d", weather_data_total_len, rec_weather_data_offset); if(remaining_size > write_len){ memcpy_s(weather_data_context.buffer + rec_weather_data_offset, weather_data_total_len - rec_weather_data_offset, &write_cb_para[data_index + 4], write_len); }else{ memcpy_s(weather_data_context.buffer + rec_weather_data_offset, weather_data_total_len - rec_weather_data_offset, &write_cb_para[data_index + 4], weather_data_total_len - rec_weather_data_offset); } if (weather_data_context.buffer_offset != rec_weather_data_offset) { static_print_error("weather_data_context.buffer_offset != rec_weather_data_offset"); free(weather_data_context.buffer); weather_data_context.buffer = NULL; uint8_t data[2] = {0x00 , weather_data_context.buffer_offset}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); weather_data_context.buffer_offset = 0; return; } weather_data_context.buffer_offset += weather_data_total_len - rec_weather_data_offset; g_weather_data_mask = true; } else { // static_print_debug("%s , line is %d", __FUNCTION__, __LINE__); if(remaining_size > write_len){ memcpy_s(weather_data_context.buffer + rec_weather_data_offset, remaining_size, &write_cb_para[data_index + 4], write_len); }else{ memcpy_s(weather_data_context.buffer + rec_weather_data_offset, remaining_size, &write_cb_para[data_index + 4], remaining_size); } if (weather_data_context.buffer_offset != rec_weather_data_offset) { static_print_error("weather_data_context.buffer_offset != rec_weather_data_offset"); free(weather_data_context.buffer); weather_data_context.buffer = NULL; uint8_t data[2] = {0x00 , weather_data_context.buffer_offset}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); weather_data_context.buffer_offset = 0; return; } weather_data_context.buffer_offset += weather_data_total_len - rec_weather_data_offset; } if (weather_data_context.buffer_offset == weather_data_total_len) { static uint8_t cur_date = 0; g_weather_data_mask = false; // for(int i = 0; i < file_description_len; i++){ // static_print_debug("file_description_buffer[%d] : %02x", i,file_decription_context.buffer[i]); // } // 表盘LTV文件描述如 0301040602123456780603F1F1F1F10804313233343536 // 0301040602123456780603F1F1F1F10804313233343536 // for(int i = 0 ; i < weather_data_total_len; i++){ // static_print_debug("weather_data_buffer[%d] : %02x", i,weather_data_context.buffer[i]); // } for (int i = 0; i < weather_data_total_len;) { // 遍历天气数据 uint8_t len = weather_data_context.buffer[i]; uint8_t type = weather_data_context.buffer[i + 1]; // static_print_debug("i : %u, type : %u, len : %u", i, type, len); switch (type) { case 0x01: { // 天气时间类型 cur_date = weather_data_context.buffer[i + 2]; static_print_debug("cur_date : %u", cur_date); break; } case 0x02: { // 和风天气类型 // memcpy_s(&g_file_description_packet.file_size, sizeof(g_file_description_packet.file_size), // &file_decription_context.buffer[i + 2], len - 2); sql_weather_set_forecast_protocol_value(cur_date, weather_data_context.buffer[i + 2]); static_print_debug("set_forecast_protocol_value : %u ", weather_data_context.buffer[i + 2]); break; } case 0x03: { // 当前温度 // memcpy_s(&g_file_description_packet.file_crc32, sizeof(g_file_description_packet.file_crc32), // &file_decription_context.buffer[i + 2], len - 2); if(cur_date == 0){ sql_weather_set_now_temperature(weather_data_context.buffer[i + 2]); static_print_debug("set_now_temperature : %u", weather_data_context.buffer[i + 2]); } break; } case 0x04: { // 最高温度 sql_weather_set_forecast_temperature_max(cur_date, weather_data_context.buffer[i + 2]); static_print_debug("set_forecast_temperature_max : %u", weather_data_context.buffer[i + 2]); break; } case 0x05: { // 最低温度 sql_weather_set_forecast_temperature_min(cur_date, weather_data_context.buffer[i + 2]); static_print_debug("set_forecast_temperature_min : %u", weather_data_context.buffer[i + 2]); break; } case 0x06: { // 湿度 if(cur_date == 0){ sql_weather_set_humidity(weather_data_context.buffer[i + 2]); static_print_debug("humidity : %u", weather_data_context.buffer[i + 2]); } break; } case 0x07: { // 风速 if(cur_date == 0){ sql_weather_set_wind_speed(weather_data_context.buffer[i + 2]); static_print_debug("wind_speed : %u", weather_data_context.buffer[i + 2]); } break; } case 0x08: { //位置信息 // sql_weather_set_location(write_cb_para[i + 2]); char location[32] = {0}; memcpy_s(location, sizeof(location), &weather_data_context.buffer[i + 2], len - 2); static_print_debug("location : %s", location); break; } case 0x09: { //降雨量 int16_t rain_value = weather_data_context.buffer[i + 2] << 8 | weather_data_context.buffer[i + 3]; // memcpy_s(&rain_value, sizeof(rain_value), &weather_data_context.buffer[i + 2], len - 2); static_print_debug("rain_value : %u", rain_value); break; } case 0x10: { //日出时间 日落时间 int16_t sunrise_time = weather_data_context.buffer[i + 2] << 8 | weather_data_context.buffer[i + 3]; // memcpy_s(&sunrise_time, sizeof(sunrise_time), &weather_data_context.buffer[i + 2], sizeof(sunrise_time)); int16_t sunset_time = weather_data_context.buffer[i + 4] << 8 | weather_data_context.buffer[i + 5]; // memcpy_s(&sunset_time, sizeof(sunset_time), &weather_data_context.buffer[i + 2 + sizeof(sunrise_time)],sizeof(sunset_time)); static_print_debug("sunrise_time : %u , sunset_time : %u ", sunrise_time , sunset_time); if(cur_date == 0){ sql_weather_set_sunrise_time(sunrise_time); sql_weather_set_sunset_time(sunset_time); } break; } case 0x11: { //气压 int16_t pressure = weather_data_context.buffer[i + 2] << 8 | weather_data_context.buffer[i + 3]; // memcpy_s(&pressure, sizeof(pressure), &weather_data_context.buffer[i + 2], len - 2); static_print_debug("pressure : %u", pressure); break; } case 0x12: { //海拔 int16_t altitude = weather_data_context.buffer[i + 2] << 8 | weather_data_context.buffer[i + 3]; // memcpy_s(&altitude, sizeof(altitude), &weather_data_context.buffer[i + 2], len - 2); static_print_debug("altitude : %u", altitude); break; } default: { static_print_error("unknown type : %u", type); break; } } i += len; } free(weather_data_context.buffer); uint8_t data[3] ={0}; data[0] = 0x02; data[1] = weather_data_context.buffer_offset << 8; data[2] = weather_data_context.buffer_offset & 0xFF; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); weather_data_context.buffer = NULL; weather_data_context.buffer_offset = 0; weather_data_context.expected_seq = 0; g_weather_today_synchronization_data_mask = true; struct rtc_class_ops *rtc_api = tjd_driver_rtc_get_ops(); struct rtc_time tm_info = {0}; rtc_api->get_rtc_time(&tm_info); sql_weather_set_update_hour(tm_info.tm_hour); sql_weather_set_update_minute(tm_info.tm_min); return; } else { uint8_t data[3] ={0}; data[0] = 0x01; data[1] = weather_data_context.buffer_offset << 8; data[2] = weather_data_context.buffer_offset & 0xFF; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); return; } } static void handle_push_data_cmd(UpgradeContext *upgrade_context, uint8_t cmd, uint16_t * push_data_pkg, uint8_t *write_cb_para, uint16_t len ,uint8_t server_id, uint8_t conn_id) { // TODO: 接收表盘推送数据 uint16_t received_seq = (write_cb_para[2] << 8) | write_cb_para[3]; if (received_seq != upgrade_context->expected_seq) { // 错误处理:包序号不匹配 static_print_debug("received_seq(%d) != expected_seq(%d)", received_seq, upgrade_context->expected_seq); // 通知app接收表盘推送失败 // uint8_t data[6] = {0}; // data[0] = 0x5A; // data[1] = cmd; // data[2] = (received_seq >> 8) & 0xFF; // data[3] = received_seq & 0xFF; // data[4] = 0x00; // data[5] = do_crc(data, 5); // gatt_send_response(data, sizeof(data), server_id, conn_id); } memcpy_s(upgrade_context->buffer + upgrade_context->buffer_offset, PACKET_DATA_SIZE, &write_cb_para[4], len - 4); upgrade_context->buffer_offset += (len - 4); upgrade_context->expected_seq++; // 回复app接收壁纸推送成功 // uint8_t data[5] = {0}; // data[0] = 0x5A; // data[1] = cmd; // data[2] = (received_seq >> 8) & 0xFF; // data[3] = received_seq & 0xFF; // data[4] = 0x01; // // data[5] = do_crc(data, 5); // gatt_send_response(data, sizeof(data), server_id, conn_id); static_print_debug("receive data success, prepare to send next data ! expected seq: %d , push_data_pkg : %d " , upgrade_context->expected_seq , *push_data_pkg); if (*push_data_pkg == upgrade_context->expected_seq) { // push_data_mask = 0; // if (g_contacts_push_data_mask) { static_print_debug("contacts push data mask is true, prepare to analyze data"); for(int i = 0; i < upgrade_context->buffer_offset; i++){ static_print_debug("contacts data : %02x", upgrade_context->buffer[i]); } // TODO: 解析contacts推送数据 if(cmd == CONTACTS_PUSH_DATA_COMMAND){ memset(contacts, 0 , sizeof(contacts)); int num_contacts = 0; // Check start and end markers if (strncmp((const char *)upgrade_context->buffer, "{*$#", 4) != 0 || strstr((const char *)upgrade_context->buffer, "#$*}") == NULL) { static_print_debug("Invalid data format"); return; } char *token = strtok((char *)upgrade_context->buffer + 4, "[@"); while (token != NULL && num_contacts < MAX_CONTACTS) { if (sscanf(token, "%hhu%49[^%&]%*[^&]&%14s", &contacts[num_contacts].id, contacts[num_contacts].name, contacts[num_contacts].phone) != 3) { printf("Failed to parse contact data"); return; } // 去除phone字段末尾的特殊字符 char *end = contacts[num_contacts].phone + strlen(contacts[num_contacts].phone) - 1; while (end >= contacts[num_contacts].phone && !isdigit(*end)) { *end = '\0'; // 将非数字字符替换为字符串结束符 end--; } num_contacts++; token = strtok(NULL, "[@"); } for (int i = 0; i < num_contacts; ++i) { static_print_debug("Contact %d: ID=%d, Name=%s, Phone=%s", i + 1, contacts[i].id, contacts[i].name, contacts[i].phone); } static_print_debug("receive all data, exit dial push data mask"); static_print_debug("upgrade_context.buffer_offset: %d, push_data_pkg: %d, upgrade_context.expected_seq: %d", upgrade_context->buffer_offset, *push_data_pkg, upgrade_context->expected_seq); file_append_data.buffer = contacts; file_append_data.size = num_contacts; tjd_service_contact_append(&file_append_data); } free(upgrade_context->buffer); upgrade_context->buffer = NULL; upgrade_context->buffer_offset = 0; upgrade_context->expected_seq = 0; *push_data_pkg = 0; } return; } static void get_addrbook_cnt(uint8_t cmd, uint8_t server_id, uint8_t conn_id) { uint8_t data[6] = {0}; uint16_t free_num = MAX_CONTACTS; long long file_size = 0; struct stat fileStat = {0}; int ret = stat(TJD_ADDRESS_BOOK_PATH,&fileStat); static_print_debug("access ret is %d", ret); if(ret == 0){ file_size = fileStat.st_size; static_print_debug("file size is %lld", file_size); uint8_t contact_num = file_size/sizeof(Contact); if(contact_num > MAX_CONTACTS){ free_num = 0; }else{ free_num = MAX_CONTACTS - contact_num; } } data[0] = PROTOCOL_FRAME_RSP_HEAD; data[1] = 0x08; data[2] = cmd; data[3] = (free_num >> 8) & 0xFF; data[4] = free_num & 0xFF; data[5] = do_crc(data, sizeof(data) - 1); gatt_send_response(data, sizeof(data), server_id, conn_id); } static void handle_push_addrbook_data_cmd(UpgradeContext *upgrade_context, uint8_t cmd, uint16_t * push_data_pkg, uint8_t *write_cb_para, uint16_t len ,uint8_t server_id, uint8_t conn_id) { uint8_t ret = true; uint8_t data[8] = {0}; // TODO: 接收表盘推送数据 uint16_t received_seq = (write_cb_para[2] << 8) | write_cb_para[3]; if (received_seq != upgrade_context->expected_seq) { // 错误处理:包序号不匹配 static_print_debug("received_seq(%d) != expected_seq(%d)", received_seq, upgrade_context->expected_seq); received_seq = upgrade_context->expected_seq; ret = false; goto __exit; }else if (received_seq >= *push_data_pkg) { printf("[%s %d][total exceed(%d-MAX:%d)]\n", __func__, __LINE__, received_seq, *push_data_pkg); return; } memcpy_s(upgrade_context->buffer + upgrade_context->buffer_offset, PACKET_DATA_SIZE, &write_cb_para[4], len - 4); upgrade_context->buffer_offset += (len - 4); upgrade_context->expected_seq++; static_print_debug("receive data success, prepare to send next data ! expected seq: %d , push_data_pkg : %d " , upgrade_context->expected_seq , *push_data_pkg); if (*push_data_pkg == upgrade_context->expected_seq) { static_print_debug("contacts push data mask is true, prepare to analyze data"); for(int i = 0; i < upgrade_context->buffer_offset; i++){ static_print_debug("contacts data : %02x", upgrade_context->buffer[i]); } // TODO: 解析contacts推送数据 if(cmd == CONTACTS_PUSH_DATA_COMMAND){ int num_contacts = 0; memset(contacts, 0 , sizeof(contacts)); // 检测数据有效性 if (strncmp((const char *)upgrade_context->buffer, "{*$#", 4) != 0 || strstr((const char *)upgrade_context->buffer, "#$*}") == NULL) { static_print_debug("Invalid data format"); goto __analyze_end; } char *token = strtok((char *)upgrade_context->buffer + 4, "[@"); while (token != NULL && num_contacts < MAX_CONTACTS) { if (sscanf(token, "%hhu%49[^%&]%*[^&]&%14s", &contacts[num_contacts].id, contacts[num_contacts].name, contacts[num_contacts].phone) != 3) { printf("Failed to parse contact data"); return; } // 去除phone字段末尾的特殊字符 char *end = contacts[num_contacts].phone + strlen(contacts[num_contacts].phone) - 1; while (end >= contacts[num_contacts].phone && !isdigit(*end)) { *end = '\0'; // 将非数字字符替换为字符串结束符 end--; } num_contacts++; token = strtok(NULL, "[@"); } for (int i = 0; i < num_contacts; ++i) { static_print_debug("Contact %d: ID=%d, Name=%s, Phone=%s", i + 1, contacts[i].id, contacts[i].name, contacts[i].phone); } static_print_debug("receive all data, exit dial push data mask"); static_print_debug("upgrade_context.buffer_offset: %d, push_data_pkg: %d, upgrade_context.expected_seq: %d", upgrade_context->buffer_offset, *push_data_pkg, upgrade_context->expected_seq); file_append_data.buffer = contacts; file_append_data.size = num_contacts; tjd_service_contact_append(&file_append_data); } __analyze_end: free(upgrade_context->buffer); upgrade_context->buffer = NULL; upgrade_context->buffer_offset = 0; upgrade_context->expected_seq = 0; *push_data_pkg = 0; } __exit: /* 回复当前包序号 */ data[0] = PROTOCOL_FRAME_RSP_HEAD; data[1] = 0x08; data[2] = cmd; data[3] = (received_seq >> 8) & 0xFF; data[4] = received_seq & 0xFF; data[5] = (ret >> 8) & 0xFF; data[6] = ret & 0xFF; data[7] = do_crc(data, sizeof(data) - 1); gatt_send_response(data, sizeof(data), server_id, conn_id); return; } void tjd_ble_rec_lucky_clover_data(uint8_t server_id, uint16_t conn_id, uint8_t *write_cb_para, uint16_t len ,uint8_t cmd_id) { // TODO: app下发四叶草数据 static_print_debug("rec ltv file description"); uint8_t data_index = 4; uint16_t lucky_clover_len = (write_cb_para[data_index] << 8) | write_cb_para[data_index + 1]; // uint16_t rec_lucky_clover_offset = 0; uint16_t write_len = write_cb_para[1] << 8 | write_cb_para[2]; uint16_t remaining_size = lucky_clover_len - lucky_flover_context.buffer_offset; if (!g_qrcode_push_data_mask) { memset_s(&lucky_flover_context, sizeof(lucky_flover_context), 0, sizeof(lucky_flover_context)); lucky_flover_context.buffer_offset = 0; lucky_flover_context.expected_seq = lucky_clover_len; lucky_flover_context.buffer = (uint8_t *)malloc(lucky_clover_len); // rec_lucky_clover_offset = // (write_cb_para[data_index + 2] << 8) | write_cb_para[data_index + 3]; memset_s(lucky_flover_context.buffer, lucky_clover_len, 0, lucky_clover_len); static_print_debug("lucky_clover_len : %d, lucky_flover_context.buffer_offset : %d", lucky_clover_len, lucky_flover_context.buffer_offset); if(remaining_size > write_len - 7){ memcpy_s(lucky_flover_context.buffer + lucky_flover_context.buffer_offset, lucky_clover_len - lucky_flover_context.buffer_offset, &write_cb_para[data_index + 2], write_len - 7); lucky_flover_context.buffer_offset += write_len - 7; }else{ memcpy_s(lucky_flover_context.buffer + lucky_flover_context.buffer_offset, lucky_clover_len - lucky_flover_context.buffer_offset, &write_cb_para[data_index + 2], remaining_size); lucky_flover_context.buffer_offset += remaining_size; } g_qrcode_push_data_mask = true; } else { if(remaining_size > write_len - 7){ memcpy_s(lucky_flover_context.buffer + lucky_flover_context.buffer_offset, lucky_clover_len - lucky_flover_context.buffer_offset, &write_cb_para[data_index + 2], write_len - 7); lucky_flover_context.buffer_offset += write_len - 7; }else{ memcpy_s(lucky_flover_context.buffer + lucky_flover_context.buffer_offset, lucky_clover_len - lucky_flover_context.buffer_offset, &write_cb_para[data_index + 2], remaining_size); lucky_flover_context.buffer_offset += remaining_size; } } if (lucky_flover_context.buffer_offset == lucky_clover_len) { g_qrcode_push_data_mask = false; // for(int i = 0; i < file_description_len; i++){ // static_print_debug("file_description_buffer[%d] : %02x", i,file_decription_context.buffer[i]); // } static_print_info("lucky_flover_context.buffer_offset : %d , lucky_flover_context.buffer : \r\n",lucky_flover_context.buffer_offset); for(int i = 0; i < lucky_flover_context.buffer_offset; i++){ static_print_info("%02x ",lucky_flover_context.buffer[i]); if(i % 10 == 0){ static_print_info("\r\n"); } } static_print_info("\r\n"); // 表盘LTV文件描述如 0301040602123456780603F1F1F1F10804313233343536 // 0301040602123456780603F1F1F1F10804313233343536 uint8_t cur_task_num = 0; uint8_t goal_task_num = 0; // lucky_clover_msg_t lucky_clover_msg = {0}; for (int i = 0; i < lucky_flover_context.buffer_offset;) { // 遍历文件描述 uint8_t len = lucky_flover_context.buffer[i]; uint8_t type = lucky_flover_context.buffer[i + 1]; static_print_debug("i : %u, type : %u, len : %u", i, type, len); switch (type) { case 0x01: { // 站立活动 goal_task_num++; uint8_t standing_activity_cur = lucky_flover_context.buffer[i + 2]; uint8_t standing_activity_goal = lucky_flover_context.buffer[i + 3]; // lucky_clover_msg.lucky_clover_data.currentStandNum = standing_activity_cur; // lucky_clover_msg.lucky_clover_data.goalStandNum = standing_activity_goal; if(standing_activity_cur >= standing_activity_goal){ cur_task_num++; } uint16_t standing_activity_reminder_time = (lucky_flover_context.buffer[i + 4] << 8) | lucky_flover_context.buffer[i + 5]; sql_fit_set_currentStandNum_data(standing_activity_cur); sql_fit_set_goalStandNum_data(standing_activity_goal); static_print_warn("standing activity cur : %u, standing activity goal : %u, standing activity reminder time : %u", standing_activity_cur, standing_activity_goal, standing_activity_reminder_time); break; } case 0x02: { // 活动热量 goal_task_num++; uint16_t activity_heat_cur = (lucky_flover_context.buffer[i + 2] << 8) | lucky_flover_context.buffer[i + 3]; uint16_t activity_heat_goal = (lucky_flover_context.buffer[i + 4] << 8) | lucky_flover_context.buffer[i + 5]; // lucky_clover_msg.lucky_clover_data.currentCalorieNum = activity_heat_cur; // lucky_clover_msg.lucky_clover_data.goalCalorieNum = activity_heat_goal; if(activity_heat_cur >= activity_heat_goal){ cur_task_num++; } uint16_t activity_heat_reminder_time = (lucky_flover_context.buffer[i + 6] << 8) | lucky_flover_context.buffer[i + 7]; sql_fit_set_currentCalorieNum_data(activity_heat_cur); sql_fit_set_goalCalorieNum_data(activity_heat_goal); static_print_debug("activity heat cur : %u, activity heat goal : %u, activity heat reminder time : %u", activity_heat_cur, activity_heat_goal, activity_heat_reminder_time); tjd_service_handle_calorie_data(); break; } case 0x03: { // 中高强度 goal_task_num++; uint8_t high_intensity_cur = lucky_flover_context.buffer[i + 2]; uint8_t high_intensity_goal = lucky_flover_context.buffer[i + 3]; // lucky_clover_msg.lucky_clover_data.currentStrengthTime = high_intensity_cur; // lucky_clover_msg.lucky_clover_data.goalStrengthTime = high_intensity_goal; if(high_intensity_cur >= high_intensity_goal){ cur_task_num++; } uint16_t high_intensity_reminder_time = (lucky_flover_context.buffer[i + 4] << 8) | lucky_flover_context.buffer[i + 5]; sql_fit_set_currentStrengthTime_data(high_intensity_cur); sql_fit_set_goalStrengthTime_data(high_intensity_goal); static_print_debug("high intensity cur : %u, high intensity goal : %u, high intensity reminder time : %u", high_intensity_cur, high_intensity_goal, high_intensity_reminder_time); tjd_service_handle_excise_data(); break; } case 0x04: { // 步数 goal_task_num++; uint16_t step_cur = (lucky_flover_context.buffer[i + 2] << 8) | lucky_flover_context.buffer[i + 3]; uint16_t step_goal = (lucky_flover_context.buffer[i + 4] << 8) | lucky_flover_context.buffer[i + 5]; // lucky_clover_msg.lucky_clover_data.currentStepNum = step_cur; // lucky_clover_msg.lucky_clover_data.goalStepNum = step_goal; if(step_cur >= step_goal){ cur_task_num++; } uint16_t step_reminder_time = (lucky_flover_context.buffer[i + 6] << 8) | lucky_flover_context.buffer[i + 7]; sql_fit_set_currentStepNum_data(step_cur); sql_fit_set_goalStepNum_data(step_goal); static_print_debug("step cur : %u, step goal : %u, step reminder time : %u", step_cur, step_goal, step_reminder_time); tjd_service_handle_step_data(); break; } case 0x05: { // 每日喝水 goal_task_num++; uint16_t drink_water_cur = (lucky_flover_context.buffer[i + 2] << 8) | lucky_flover_context.buffer[i + 3]; uint16_t drink_water_goal = (lucky_flover_context.buffer[i + 4] << 8) | lucky_flover_context.buffer[i + 5]; // lucky_clover_msg.lucky_clover_data.currentDrinkNum = drink_water_cur; // lucky_clover_msg.lucky_clover_data.goalDrinkNum = drink_water_goal; if(drink_water_cur >= drink_water_goal){ cur_task_num++; } uint8_t is_drink_water_reminder_on = lucky_flover_context.buffer[i + 6]; uint16_t drink_water_reminder_time_start = (lucky_flover_context.buffer[i + 7] << 8) | lucky_flover_context.buffer[i + 8]; uint16_t drink_water_reminder_time_end = (lucky_flover_context.buffer[i + 9] << 8) | lucky_flover_context.buffer[i + 10]; sql_fit_set_currentDrinkNum_data(drink_water_cur); sql_fit_set_goalDrinkNum_data(drink_water_goal); static_print_debug("drink water cur : %u, drink water goal : %u, drink water reminder on : %u, drink water reminder time start : %u, drink water reminder time end : %u", drink_water_cur, drink_water_goal, is_drink_water_reminder_on, drink_water_reminder_time_start, drink_water_reminder_time_end); break; } case 0x06: { // 早睡 goal_task_num++; uint8_t is_early_sleep_reminder_on = lucky_flover_context.buffer[i + 2]; if(is_early_sleep_reminder_on){ cur_task_num++; } uint16_t early_sleep_cur_time = (lucky_flover_context.buffer[i + 3] << 8) | lucky_flover_context.buffer[i + 4]; uint16_t early_sleep_goal_time = (lucky_flover_context.buffer[i + 5] << 8) | lucky_flover_context.buffer[i + 6]; uint16_t early_sleep_reminder_time = (lucky_flover_context.buffer[i + 7] << 8) | lucky_flover_context.buffer[i + 8]; sql_fit_set_curEarlySleepTime_data(early_sleep_cur_time); sql_fit_set_goalEarlySleepTime_data(early_sleep_goal_time); // lucky_clover_msg.lucky_clover_data.sleepEarly = is_early_sleep_reminder_on == 0 ? false : true; sql_fit_set_sleepEarly_data(is_early_sleep_reminder_on); static_print_debug("is early sleep reminder on : %u, early_sleep_cur_time : %u, early sleep goal time : %u, early sleep reminder time : %u", is_early_sleep_reminder_on, early_sleep_cur_time ,early_sleep_goal_time, early_sleep_reminder_time); break; } case 0x07: { // 睡眠时长 goal_task_num++; uint16_t sleep_duration_cur = (lucky_flover_context.buffer[i + 2] << 8) | lucky_flover_context.buffer[i + 3]; uint16_t sleep_duration_goal = (lucky_flover_context.buffer[i + 4] << 8) | lucky_flover_context.buffer[i + 5]; // lucky_clover_msg.lucky_clover_data.currentSleepTime = sleep_duration_cur; // lucky_clover_msg.lucky_clover_data.goalSleepTime = sleep_duration_goal; if(sleep_duration_cur >= sleep_duration_goal){ cur_task_num++; } sql_fit_set_currentSleepTime_data(sleep_duration_cur); sql_fit_set_goalSleepTime_data(sleep_duration_goal); static_print_debug("sleep duration cur : %u, sleep duration goal : %u", sleep_duration_cur, sleep_duration_goal); break; } case 0x08: { //血压测量时间 goal_task_num++; uint8_t current_punch_clock_time = lucky_flover_context.buffer[i + 2]; uint8_t goal_punch_clock_time = lucky_flover_context.buffer[i + 3]; if(current_punch_clock_time >= goal_punch_clock_time){ cur_task_num++; } sql_fit_set_curBloodPressureMeasurTime_data(current_punch_clock_time); sql_fit_set_goalBloodPressureMeasurTime_data(goal_punch_clock_time); // lucky_clover_msg.lucky_clover_data.curBloodPressureMeasurTime = current_punch_clock_time; // lucky_clover_msg.lucky_clover_data.goalBloodPressureMeasurTime = goal_punch_clock_time; uint16_t blood_pressure_matinal_measure_time = (lucky_flover_context.buffer[i + 4] << 8) | lucky_flover_context.buffer[i + 5]; uint16_t blood_pressure_before_sleep_measure_time = (lucky_flover_context.buffer[i + 6] << 8) | lucky_flover_context.buffer[i + 7]; static_print_debug("current_punch_clock_time : %u, goal_punch_clock_time : %u, blood pressure matinal measure time : %u, blood pressure before sleep measure time : %u", current_punch_clock_time,goal_punch_clock_time,blood_pressure_matinal_measure_time,blood_pressure_before_sleep_measure_time); uint8_t custom_measure_tiemrs = (len - 8); for(uint8_t j = 0; j < custom_measure_tiemrs; j++){ uint16_t custom_measure_time = (lucky_flover_context.buffer[i + 8 + (j * 2)] << 8) | lucky_flover_context.buffer[i + 9 + (j * 2)]; static_print_debug("custom measure time : %u", custom_measure_time); } break; } case 0x09: { // 自定义打卡任务 //data .eg : 150902 E7A4BCE4BD9B250000 E7A5B7E5918A250000 //len : 0x15 type : 0x09 //自定义任务名与提醒时间以 “%” 作分隔 即 0x25 uint8_t custom_task_name_len = 0; uint8_t custom_task_num = lucky_flover_context.buffer[i + 2]; custom_task_num == 0 ? sql_fit_set_has_custom_task(false) : sql_fit_set_has_custom_task(true); uint8_t k = i; goal_task_num += custom_task_num; static_print_debug("custom task num : %u", custom_task_num); for(uint8_t j = 0; j < custom_task_num; j++){ uint8_t custom_task_name[32] = {0}; char * custom_task_name_ptr = strchr((char *)lucky_flover_context.buffer + k + 3, 0x25); if(custom_task_name_ptr == NULL){ continue; } custom_task_name_len = custom_task_name_ptr - (char *)(lucky_flover_context.buffer + i + 3); memcpy(custom_task_name, lucky_flover_context.buffer + k + 3, custom_task_name_len); uint16_t custom_task_reminder_time = (lucky_flover_context.buffer[k + 3 + custom_task_name_len + 1 ] << 8) | lucky_flover_context.buffer[k + 3 + custom_task_name_len + 2]; bool is_custom_task_punch_clock = lucky_flover_context.buffer[k + 3 + custom_task_name_len + 3]; if(is_custom_task_punch_clock){ cur_task_num++; } k += custom_task_name_len + 4; sql_fit_set_custom_task(j, (char *)custom_task_name, is_custom_task_punch_clock ,custom_task_reminder_time); static_print_debug("custom task name : %s, custom task reminder time : %u, is_custom_task_punch_clock : %u", custom_task_name, custom_task_reminder_time, is_custom_task_punch_clock); } break; } default: { static_print_error("unknown type : %u", type); break; } } i += len; } // for(int i = 0 ; i < cur_task_num; i++){ // lucky_clover_msg.msg_type = i; // TjdUiMsgEventPublish(TJDUI_TOPIC_EVENT_LUCKY_CLOVER, &lucky_clover_msg, sizeof(lucky_clover_msg)); // } sql_fit_set_currentTaskNum_data(cur_task_num); sql_fit_set_goalTaskNum_data(goal_task_num); free(lucky_flover_context.buffer); lucky_flover_context.buffer = NULL; lucky_flover_context.buffer_offset = 0; lucky_flover_context.expected_seq = 0; return; } } //AC XXXX CB XXXX LTV(030101 1202xxxxxxxxxxxxxxxxxxxx 0402xxxx)CRC #define OPRATION_INSTALL 0x01 #define OPRATION_UNINSTALL 0x00 #define LTV_DEFAULT_LEN 10 #define LTV_OFFSET_LEN 2 #define PACKAGE_DEFAULT_LEN 7 bool uninstall_by_protocol = false; void tjd_ble_uninstall_js_app(uint8_t server_id, uint16_t conn_id, uint8_t *write_cb_para, uint16_t len ,uint8_t cmd_id) { uint8_t operation = write_cb_para[8]; uint16_t package_len = (write_cb_para[1] << 8) | write_cb_para[2]; uint16_t ltv_len = (write_cb_para[4] << 8) | write_cb_para[5]; uint8_t bundleName_len = write_cb_para[9] - LTV_OFFSET_LEN; uint8_t lable_len = write_cb_para[11 + bundleName_len] - LTV_OFFSET_LEN; char bundleName[PROTOCOL_BUFFER_MAX_LEN] = {0}; char lable[PROTOCOL_BUFFER_MAX_LEN] = {0}; char pkg_path[PROTOCOL_BUFFER_MAX_LEN] = {0}; memcpy_s(bundleName,bundleName_len,&write_cb_para[11],bundleName_len); memcpy_s(lable,lable_len,&write_cb_para[11+bundleName_len],lable_len); printf("uninstall bundleName_len:%d lable_len:%d\r\n",bundleName_len,lable_len); printf("uninstall bundleName:%s lable:%s\r\n",bundleName,lable); if(operation == OPRATION_UNINSTALL){ // TODO: 删除安装包 // sprintf_s(pkg_path, PROTOCOL_BUFFER_MAX_LEN, "%s/%s.bin", TJD_FS_DIR_JS, (char *)bundleName); // printf("uninstall pkg_path:%s\r\n",pkg_path); // if(access((char *)pkg_path, 0) == 0){ // tjd_fs_api_path_remove((char *)pkg_path); // } // TODO: 卸载JS应用 uninstall_by_protocol = true; TjdAppStorePkgOperation(PKG_OPERATION_TYPE_UNINSTALL,(const char *)bundleName,false); } } void tjd_ble_protocol_get_openharmony_version(uint8_t server_id, uint16_t conn_id, uint8_t *write_cb_para, uint16_t len, uint8_t cmd_id) { int version = GetSdkApiVersion(); uint8_t data[] = {(uint8_t)version}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); } void tjd_ble_protocol_ctrlcmd_ab(uint8_t server_id, uint16_t conn_id, uint8_t *write_cb_para , uint16_t len) { static_print_info(" tjd_ble_protocol_ctrlcmd_ab(len:%d):\r\n",len); for(int i = 0 ; i < len ; ){ static_print_info("%02x", write_cb_para[i]); i++; if(i % 10 == 0){ static_print_info("\r\n"); } if(i>=20){ break;} } static_print_info("\r\n"); switch (write_cb_para[1]) { case DIAL_PUSH_DIAL_DATA_COMMAND: { static_print_debug("dial push data mask is true, prepare to receive data"); handle_push_data_cmd(&dial_context, DIAL_PUSH_DIAL_DATA_COMMAND, g_dial_push_data_pkg, write_cb_para, CONTACTS_DATA_LEN, server_id, conn_id); return; } case WALLPAPER_PUSH_DATA_COMMAND: { static_print_debug("wallpaper push data mask is true, prepare to receive data"); handle_push_data_cmd(&wallpaper_context, WALLPAPER_PUSH_DATA_COMMAND, g_wallpaper_push_data_pkg, write_cb_para, CONTACTS_DATA_LEN, server_id, conn_id); return; } case CONTACTS_PUSH_DATA_COMMAND: { static_print_debug("CONTACTS_PUSH_DATA_COMMAND prepare to receive data"); handle_push_addrbook_data_cmd(&contacts_context, CONTACTS_PUSH_DATA_COMMAND, &g_contacts_push_data_pkg, write_cb_para, CONTACTS_DATA_LEN, server_id, conn_id); return; } default: break; } uint8_t crc = write_cb_para[len - 1]; uint8_t crc_cal = do_crc(write_cb_para, len - 1); uint8_t cmd_id = write_cb_para[2]; if (crc != crc_cal && cmd_id != REC_QR_CODE_INFORMATION) { static_print_error("control command crc error! crc : %d, crc_cal : %d", crc, crc_cal); uint8_t data = 0x00; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, &data, sizeof(data), cmd_id, server_id, conn_id); return; } switch (cmd_id) { case READ_DEVICE_INFO: { static_print_debug("Read basic device information"); uint8_t data[] = {0xFF, 0xE7, 0x00, 0x50, 0x48, 0x31, 0x38, 0x00, DEVICE_HARD_VERSION_H, DEVICE_HARD_VERSION_L, DEVICE_SOFT_VERSION_H, DEVICE_SOFT_VERSION_L, 0x54, 0x4a, 0x44, 0x50}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), READ_DEVICE_INFO, server_id, conn_id); break; } case 0x01: { static_print_debug("turn on led"); break; } case SET_READ_DEVICE_FORMAT: { if(write_cb_para[3] == 0x01){ static_print_debug("set device format"); // TODO: 设置设备制式 sql_setting_set_language(write_cb_para[4]); sql_setting_set_time_format(write_cb_para[5]); sql_setting_set_distance_unit(write_cb_para[6]); // language_enum lanuage = sql_setting_get_language(); // uint8_t time_format = sql_setting_get_time_format(); // uint8_t distance_unit = sql_setting_get_distance_unit(); // static_print_debug("language: %d, time_format: %d, distance_unit: %d", lanuage, // time_format,distance_unit); uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_DEVICE_FORMAT, server_id, conn_id); break; }else if(write_cb_para[3] == 0x00){ static_print_debug("read device format"); // TODO: 读取设备制式 uint8_t language = sql_setting_get_language(); uint8_t time_format = sql_setting_get_time_format(); uint8_t distance_unit = sql_setting_get_distance_unit(); uint8_t data[] = {0x00, language, time_format, distance_unit}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_DEVICE_FORMAT, server_id, conn_id); break; } } case POWER_SYNCHRONIZATION: { static_print_debug("power synchronization"); // TODO: 电源同步 // uint32_t utc_timestamp = 0; // uint8_t charge_status = 0; // uint8_t percent = tjd_service_charger_get_battery(); uint8_t percent = 100; static_print_debug("battery percent: %d", percent); // uint16_t voltage = 0; // sql_setting_get_battery_info(&utc_timestamp, &charge_status, &percent, &voltage); // uint8_t hex_num = 0; // sprintf(hex_num, "%02X", percent); tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, &percent, sizeof(percent), POWER_SYNCHRONIZATION, server_id, conn_id); break; } case TIME_SETTING_READ: { struct rtc_class_ops *rtc_api = tjd_driver_rtc_get_ops(); struct rtc_time *time_info; switch (write_cb_para[3]) { case 0x00: { // 读取设备时间 static_print_debug("read device time"); // TODO: 读取设备时间 uint64_t time_stamp = 0; sql_setting_get_system_time(&time_stamp); rtc_api->get_rtc_time(time_info); uint8_t data[6] = {0}; data[0] = time_info->tm_year & 0xFF; data[1] = time_info->tm_mon; data[2] = time_info->tm_mday; data[3] = time_info->tm_hour; data[4] = time_info->tm_min; data[5] = time_info->tm_sec; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), TIME_SETTING_READ, server_id, conn_id); break; } case 0x01: { // 设置设备时间 static_print_debug("set device time"); // TODO: 设置设备时间 tjd_driver_rtc_sync_bt_time(write_cb_para, len); uint64_t time_stamp = 0; rtc_api->get_timestamp(&time_stamp); static_print_debug("time_stamp: %lld", time_stamp); sql_setting_set_system_time(time_stamp); tjd_service_timing_init(); uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), TIME_SETTING_READ, server_id, conn_id); break; } default: static_print_error("unknown time setting read"); break; } break; } case SET_READ_DEVICE_ALARM: { switch (write_cb_para[3]) { case 0x00: { // 读取设备闹钟 static_print_debug("read device alarm"); // 获取设备闹钟相关信息 bool is_alarm_full = false; uint8_t alarm_number = sql_alarm_get_alarm_number(&is_alarm_full); for (uint8_t i = 0; i < alarm_number; i++) { uint8_t alarm_enable = sql_alarm_get_switch(i); uint8_t alarm_hour = 0; uint8_t alarm_minute = 0; sql_alarm_get_time(i, &alarm_hour, &alarm_minute); uint8_t alarm_cycle = sql_alarm_get_cycle(i); uint8_t alarm_repeat_times = sql_alarm_get_repeat_times(i); uint8_t alarm_repeat_interval = sql_alarm_get_repeat_interval(i); uint8_t data[8] = {0}; data[0] = 0x00; data[1] = i; data[2] = alarm_enable; data[3] = alarm_repeat_times; data[4] = alarm_repeat_interval; data[5] = alarm_cycle; data[6] = alarm_hour; data[7] = alarm_minute; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_DEVICE_ALARM, server_id, conn_id); } break; } case 0x01: { // 设置设备闹钟 static_print_debug("set device time"); // TODO: 设置设备时间 sql_alarm_set_switch(write_cb_para[4], write_cb_para[5]); sql_alarm_set_repeat_times(write_cb_para[4], write_cb_para[6]); sql_alarm_set_repeat_interval(write_cb_para[4], write_cb_para[7]); sql_alarm_set_cycle(write_cb_para[4], write_cb_para[8]); sql_alarm_set_time(write_cb_para[4], write_cb_para[9], write_cb_para[10]); uint8_t data[] = {0x01, write_cb_para[4], 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_DEVICE_ALARM, server_id, conn_id); break; } default: static_print_error("unknown time setting read"); break; } break; } case SET_READ_USER_PARAMETERS: { if (write_cb_para[3] == 0x00) { static_print_debug("read user parameters success"); // 通知app读取用户参数成功 uint8_t data[] = {0x00, 0x01, 0xAA, 0x3C, 0x12, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_USER_PARAMETERS, server_id, conn_id); } else if (write_cb_para[3] == 0x01) { static_print_debug("set read user parameters"); // TODO: 设置用户参数 sql_fit_set_user_gender(write_cb_para[4]); sql_fit_set_user_height(write_cb_para[5]); sql_fit_set_user_weight(write_cb_para[6]); sql_fit_set_user_age(write_cb_para[7]); // uint8_t sex = sql_fit_get_user_gender(); // uint8_t height = sql_fit_get_user_height(); // uint8_t weight = sql_fit_get_user_weight(); // uint8_t age = sql_fit_get_user_age(); // static_print_debug("sex: %d, height: %d, weight: %d, age: %d", sex, height, weight, age); // 通知app设置用户参数成功 uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_USER_PARAMETERS, server_id, conn_id); } break; } // case SET_READ_UI_INTERFACE_DISPLAYED: { // switch (write_cb_para[3]) { // case 0x00: { // 读取要显示的UI界面 // static_print_debug("read device alarm"); // uint8_t data[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // tjd_ble_protocol_send_data(data, sizeof(data), SET_READ_UI_INTERFACE_DISPLAYED, server_id, // conn_id); break; // } // case 0x01: { // 设置要显示的UI界面 // static_print_debug("set device time"); // TimeData time_data = {0}; // time_data.year = write_cb_para[4]; // time_data.month = write_cb_para[5]; // time_data.dateth = write_cb_para[6]; // time_data.hour = write_cb_para[7]; // time_data.minute = write_cb_para[8]; // time_data.second = write_cb_para[9]; // static_print_debug("year: %d, month: %d, dateth: %d, hour: %d, minute: %d, second: %d", // time_data.year, // time_data.month, time_data.dateth, time_data.hour, time_data.minute, // time_data.second); // uint8_t data[] = {0x01, 0x01}; // tjd_ble_protocol_send_data(data, sizeof(data), SET_READ_UI_INTERFACE_DISPLAYED, server_id, // conn_id); break; // } // default: // static_print_error("unknown time setting read"); // break; // } // break; // } case FIND_DEVICE:{ TjdUiMsgCenterFindDeviceTrigger(); break; } case SET_READ_FUNCTION_SWITCH:{ switch (write_cb_para[3]){ case 0x00:{ //读取功能开关 static_print_debug("read function switch"); set_read_function_switch_dada data = {0}; if(sql_fit_get_switch_bright_screen()){ data.switch_data |= 0x01; } if(sql_fit_get_switch_sedentary_remind_sw()){ data.switch_data |= 0x02; } tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, (uint8_t *)&data, 3, SET_READ_FUNCTION_SWITCH, server_id, conn_id); break; } case 0x01:{ //设置功能开关 static_print_debug("set function switch"); uint16 _value = write_cb_para[4] << 8 | write_cb_para[5]; // 注3:设备功能开关 // 0x01 抬手亮屏 // 0x02 久坐提醒 // 0x04 喝水提醒 // 0x08 拍照 // 0x10 电话挂断 // 0x20 防丢 if(_value & 0x01){ static_print_debug("set bright screen switch enable"); sql_fit_set_switch_bright_screen(ENABLE_SWITCH); }else{ static_print_debug("set bright screen switch disable"); sql_fit_set_switch_bright_screen(DISABLE_SWITCH); } if(_value & 0x02){ static_print_debug("set sedentary remind switch enable"); sql_fit_set_switch_sedentary_remind_sw(ENABLE_SWITCH); }else{ static_print_debug("set sedentary remind switch disable"); sql_fit_set_switch_sedentary_remind_sw(DISABLE_SWITCH); } uint8_t data[2] = {0x01,0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_FUNCTION_SWITCH, server_id, conn_id); break; } default: static_print_error("unknown time setting read"); break; } break; } case FIND_MOBILE_PHONE: { switch (write_cb_para[3]) { case 0x00: { static_print_debug("find mobile phone faile"); break; } case 0x01: { static_print_debug("find mobile phone success"); break; } case 0x02: { static_print_debug("find mobile phone end"); if(g_fine_phone_end_callback != NULL){ g_fine_phone_end_callback(); } break; } } break; } case SET_READ_SEDENTARY_REMINDER_PARAMETERS: { switch (write_cb_para[3]) { case 0x00: { // 读取久坐提醒功能参数 static_print_debug("read sedentary reminder parameters"); uint8_t data[] = {0x00, 0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_SEDENTARY_REMINDER_PARAMETERS, server_id, conn_id); break; } case 0x01: { // 设置久坐提醒功能参数 static_print_debug("set sedentary reminder parameters"); uint8_t sedentary_reminder_parameters = write_cb_para[4]; static_print_debug("sedentary_reminder_parameters: %d", sedentary_reminder_parameters); uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_SEDENTARY_REMINDER_PARAMETERS, server_id, conn_id); break; } default: static_print_error("unknown sedentary reminder parameters setting read"); break; } break; } case SET_READ_WATER_DRINKING_REMINDER_PARAMETERS: { switch (write_cb_para[3]) { case 0x00: { // 读取喝水提醒功能参数 static_print_debug("read sedentary reminder parameters"); uint8_t data[] = {0x00, 0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_WATER_DRINKING_REMINDER_PARAMETERS, server_id, conn_id); break; } case 0x01: { // 设置喝水提醒功能参数 static_print_debug("set sedentary reminder parameters"); uint8_t sedentary_reminder_parameters = write_cb_para[4]; static_print_debug("sedentary_reminder_parameters: %d", sedentary_reminder_parameters); uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_WATER_DRINKING_REMINDER_PARAMETERS, server_id, conn_id); break; } default: static_print_error("unknown sedentary reminder parameters setting read"); break; } break; } case ENTER_PHOTO_MODE: { static_print_debug("enter photo mode"); // TODO: 进入拍照模式 switch (write_cb_para[3]) { case 0x00: { // 退出相机 uint8_t data = 0x01; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, &data, sizeof(data), ENTER_PHOTO_MODE, server_id, conn_id); g_tjd_ble_into_camera_flag = false; tjd_exit_app_view(); break; } case 0x01: { // 进入相机 uint8_t data = 0x01; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, &data, sizeof(data), ENTER_PHOTO_MODE, server_id, conn_id); g_tjd_ble_into_camera_flag = true; tjd_into_photo(); break; } default: break; } break; } case RESPOND_PHOTO_COMMAND: { static_print_debug("respond photo command"); // TODO: 响应拍照命令 switch (write_cb_para[3]) { } break; } case MEASUREMENT_DATA_SYNCHRONIZATION: { static_print_debug("measurement data synchronization"); // TODO: 同步测量数据 switch (write_cb_para[3]) { case 0x01: { // App读取设备心率测量数据 tjd_service_send_hr_measurement_data(); break; } case 0x04: { // App读取设备血氧测量数据 tjd_service_send_measurement_data(); break; } case 0x82: { // App读取设备压力测量数据 static_print_debug("read device stress measurement data"); // uint8_t stress_array[STRESS_DAY_MAX_NUM] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}; uint8_t *stress_array = NULL; sql_fit_get_sterss_daydata(&stress_array); //获取当日时间 struct rtc_class_ops *rtc_api = tjd_driver_rtc_get_ops(); struct rtc_time time_info = {0}; uint64_t time_stamp = 0; rtc_api->get_rtc_time(&time_info); uint16_t total_number = STRESS_DAY_MAX_NUM; uint16_t cur_number = 0; int time_year = time_info.tm_year; int time_month = time_info.tm_mon; int time_day = time_info.tm_mday; uint8_t time_hour = 0; uint8_t time_minute = 0; uint8_t time_second = 0; for(int i = 0; i < STRESS_DAY_MAX_NUM; i++){ if(stress_array[cur_number] != 0){ uint8_t data[10] = {0}; data[0] = 0x82; data[1] = total_number & 0xFF; data[2] = cur_number & 0xFF; data[3] = (time_year - 2000) & 0xFF; data[4] = time_month & 0xFF; data[5] = time_day & 0xFF; data[6] = time_hour; data[7] = time_minute; data[8] = time_second; data[9] = stress_array[cur_number]; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data),MEASUREMENT_DATA_SYNCHRONIZATION, server_id, conn_id); } time_hour += 1; if(time_hour >= 24){ time_hour = 0; time_day += 1; } cur_number += 1; } break; } } break; } case READ_DETAILED_MOTION_DATA: { static_print_debug("read detailed motion data"); // TODO: 读取详细运动数据 // 获取当天时间 // struct rtc_class_ops *rtc_api = tjd_driver_rtc_get_ops(); // struct rtc_time *time_info; // uint64_t time_stamp = 0; // rtc_api->get_rtc_time(time_info); // uint32_t step_daydata[Day_Hours] = {0}; // uint16_t distance_daydata[Day_Hours] = {0}; // uint16_t calorie_daydata[Day_Hours] = {0}; // sql_fit_get_step_daydata(step_daydata); // sql_fit_get_distance_daydata(distance_daydata); // sql_fit_get_calorie_daydata(calorie_daydata); // for (uint8_t i = 0; i < Day_Hours; i++) { // // 获取当天详细运动数据 // uint8_t data[] = {0x00,0x18,i,time_info->tm_year,time_info->tm_mon,time_info->tm_mday,i,0x00, // step_daydata[i] & (0xFF << 8),step_daydata[i] & 0xFF, // distance_daydata[i] & (0xFF << 8),distance_daydata[i] & 0xFF, // calorie_daydata[i] & (0xFF << 8),calorie_daydata[i] & 0xFF}; // tjd_ble_protocol_send_data(data, sizeof(data), READ_DETAILED_MOTION_DATA, server_id, conn_id); // } // uint8_t pack_head = 0x5B; // tjd_ble_protocol_send_lefun_data(&pack_head,NULL,0,REQUEST_LUCKY_CLOVER_DATA); // static_print_debug("ble_request_flover"); break; } case READ_TOTAL_SLEEP_DATA: { static_print_debug("read total sleep data"); // TODO: 读取指定日期睡眠总数据 switch (write_cb_para[3]) { case 0x00: { // 读取当天睡眠总数据 //获取当日时间 // struct rtc_class_ops *rtc_api = tjd_driver_rtc_get_ops(); // struct rtc_time time_info = {0}; // uint64_t time_stamp = 0; // rtc_api->get_rtc_time(&time_info); // uint16_t total_number = STRESS_DAY_MAX_NUM; // uint16_t cur_number = 0; // int time_year = time_info.tm_year; // int time_month = time_info.tm_mon; // int time_day = time_info.tm_mday; // uint8_t data[6] = {0}; // data[0] = 0x00; // data[1] = (time_year - 2000) & 0xFF; // data[2] = time_month & 0xFF; // data[3] = time_day & 0xFF; // tjd_ble_protocol_send_data(data, sizeof(data), READ_TOTAL_SLEEP_DATA, server_id, conn_id); break; } default: break; } break; } case READ_SLEEP_DATA: { static_print_debug("read sleep data "); switch (write_cb_para[3]) { case 0x00: { // 读取当天详细睡眠数据 //获取当日时间 struct rtc_class_ops *rtc_api = tjd_driver_rtc_get_ops(); struct tm time_in = {0}; rtc_api->get_standard_time(&time_in); time_t time_sec = mktime(&time_in); // 将时间转换为日历时间 if (time_sec == -1) { static_print_error("Error: unable to make time using mktime"); } struct tm *time_out = localtime(&time_sec); // return time_out->tm_wday; // 返回星期几(0-6,分别代表周日到周六) sleep_status_dada_t null_head; memset(&null_head, 0, sizeof(sleep_status_dada_t)); // load_sleep_data_from_json(&null_head, time_out->tm_wday); load_sleep_data_from_json(&null_head, 4); sleep_status_dada_t *p = &null_head; uint16 total_number = 0; sleep_status_dada *data_buf = malloc(sizeof(sleep_status_dada) * 100); while(p->next != NULL) { p = p->next; if((p->status != SLEEP_LIGHT) && (p->status != SLEEP_DEEP) && (p->status != SLEEP_WAKE)) continue; static_print_debug("sleep_status_daydata:%d %d %d %d %d %d", p->status, p->time.year, p->time.mon, p->time.day, p->time.hour, p->time.min); // if(p->time.day == time_out->tm_mday){ memcpy(&data_buf[total_number], p, sizeof(sleep_status_dada)); total_number++; // }else if(p->time.day > time_out->tm_mday){ // static_print_debug("sleep_status_daydata is not match"); // break; // } } if(total_number > 100) total_number = 100; static_print_debug("total_number:%d", total_number); for(int i = 0; i < total_number; i++){ uint8_t data[11] = {0}; int index = 0; data[index++] = 0x00; data[index++] = total_number >> 8 & 0xFF; data[index++] = total_number & 0xFF; data[index++] = (i + 1) >> 8 & 0xFF; data[index++] = (i + 1) & 0xFF; data[index++] = (data_buf[i].time.year - 2000) & 0xFF; data[index++] = data_buf[i].time.mon & 0xFF; data[index++] = data_buf[i].time.day & 0xFF; data[index++] = data_buf[i].time.hour; data[index++] = data_buf[i].time.min; data[index++] = data_buf[i].status; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), READ_SLEEP_DATA, server_id, conn_id); } sleep_status_dada_t *current = null_head.next; while (current != NULL) { sleep_status_dada_t *temp = current; current = current->next; free(temp); } free(data_buf); // uint8_t sleep_data[5][15] = { // [0] = {0x5A,0x0F,0x15,0x00,0x00,0x05,0x00,0x01,0x18,0x09,0x1e,0x16,0x1e,0x02,0x00}, // [1] = {0x5A,0x0F,0x15,0x00,0x00,0x05,0x00,0x02,0x18,0x09,0x1e,0x17,0x1e,0x03,0x00}, // [2] = {0x5A,0x0F,0x15,0x00,0x00,0x05,0x00,0x03,0x18,0x0A,0x01,0x00,0x1e,0x02,0x00}, // [3] = {0x5A,0x0F,0x15,0x00,0x00,0x05,0x00,0x04,0x18,0x0A,0x01,0x01,0x1e,0x03,0x00}, // [4] = {0x5A,0x0F,0x15,0x00,0x00,0x05,0x00,0x05,0x18,0x0A,0x01,0x02,0x1e,0x01,0x00} // }; // for(int i = 0; i < 5; i++){ // sleep_data[i][14] = do_crc(sleep_data[i],14); // gatt_send_response(sleep_data[i],sizeof(sleep_data[i]),server_id,conn_id); // } break; } } break; // TODO: 读取指定日期详细睡眠数据 } case TOTAL_NUMBER_ANDROID_PUSH_MESSAGES: { // 通知app获取消息总数成功 uint8_t message_type = write_cb_para[3]; uint8_t total_number_android_push_messages = write_cb_para[4]; static_print_debug("total number of android push messages : %d , message type : %d", total_number_android_push_messages, message_type); uint8_t data[] = {0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), TOTAL_NUMBER_ANDROID_PUSH_MESSAGES, server_id, conn_id); break; } case ANDROID_PUSH_MESSAGES: { // app开始分包发送消息,我要接收分包数据 static_print_debug("android push messages"); message_enum message_type = 0; uint16_t message_len = len - 7; switch (write_cb_para[3]) { case 0x01: message_type = MESSAGE_TELEPHONE; break; case 0x02: message_type = MESSAGE_SHORT_MESSAGE; break; case 0x04: message_type = MESSAGE_QQ2; break; case 0x08: message_type = MESSAGE_WECHAT2; break; case 0x10: { message_len = len - 8; switch (write_cb_para[6]) { case 0x01: message_type = MESSAGE_FACEBOOK; break; case 0x02: message_type = MESSAGE_TWITTER; break; case 0x03: message_type = MESSAGE_LINKEDIN; break; case 0x04: message_type = MESSAGE_WHATSAPP; break; case 0x05: message_type = MESSAGE_LINE; break; case 0x06: message_type = MESSAGE_KAKAOTALK; break; case 0x07: message_type = MESSAGE_FACEBOOK_MESSENGER; break; case 0x08: message_type = MESSAGE_INSTAGRAM; break; case 0x09: message_type = MESSAGE_WHATSAPP_BUSINESS; break; case 0x0A: message_type = MESSAGE_VIBER; break; case 0x0B: message_type = MESSAGE_TELEGRAM; break; case 0x0C: message_type = MESSAGE_SNAPCHAT; break; case 0x0D: message_type = MESSAGE_ZALO; break; case 0x0E: message_type = MESSAGE_OUTLOOK; break; case 0x0F: message_type = MESSAGE_SINA_WEIBO; break; case 0x10: message_type = MESSAGE_VK; break; case 0x11: message_type = MESSAGE_END_CALL; break; case 0x12: message_type = MESSAGE_YOUTUBE; break; case 0x13: message_type = MESSAGE_TIKTOK; break; default: break; } } break; default: break; } static uint8_t index = 0; uint8_t message_all_index = write_cb_para[4]; uint8_t message_index = write_cb_para[5]; if (message_index == 0x01) { index = sql_message_new_message(); message_context.buffer_offset = 0; message_context.expected_seq = 1; message_context.buffer = malloc(message_len * message_all_index); if (message_context.buffer == NULL) { static_print_error("malloc message buffer error"); return; } memset_s(message_context.buffer, message_len * message_all_index, 0, message_len * message_all_index); } static_print_debug("message_type: %d, message_all_index: %d, message_index: %d", message_type, message_all_index, message_index); if (message_index == message_context.expected_seq++ && message_all_index != message_index) { if (message_context.buffer_offset + message_len > PROTOCOL_BUFFER_MAX_LEN) { static_print_error("message buffer overflow"); return; } memcpy_s(message_context.buffer + message_context.buffer_offset, message_len * message_all_index, write_cb_para[3] == 0x10 ? &write_cb_para[7] : &write_cb_para[6], message_len); message_context.buffer_offset += message_len; } else if (message_all_index == message_index) { if (message_context.buffer_offset + message_len < PROTOCOL_BUFFER_MAX_LEN) { memcpy_s(message_context.buffer + message_context.buffer_offset, message_len * message_all_index, write_cb_para[3] == 0x10 ? &write_cb_para[7] : &write_cb_para[6], message_len); message_context.buffer_offset += message_len; } static_print_debug("message_data:"); for (uint32_t i = 0; i < message_context.buffer_offset; i++) { static_print_info("%02x ", message_context.buffer[i]); if(i != 0 && i % 10 == 0){ static_print_info("\r\n"); } } static_print_info("\r\n"); static_print_debug("message_context.buffer_offset = %d", message_context.buffer_offset); int mask_i = strchr((const char *)message_context.buffer, ':') - (char *)message_context.buffer; int mask_j = mask_i; if(strchr((const char *)message_context.buffer + mask_i + 1, ':') != NULL){ mask_j = strchr((const char *)message_context.buffer + mask_i + 1, ':') - (char *)message_context.buffer; } static_print_debug("mask_i = %d, mask_j = %d", mask_i, mask_j); char *buff = malloc(mask_i + 2); memset_s(buff, mask_i + 2, 0, mask_i + 2); memcpy_s(buff, mask_i + 1, message_context.buffer, mask_i); buff[mask_i + 1] = '\0'; if (sql_message_set_type(index, message_type) == RET_ERROR) { static_print_error("set message type error"); return; } if (sql_message_set_user_name(index, buff) == RET_ERROR) { static_print_error("set message name error"); return; } char *detail_info = malloc(message_context.buffer_offset - mask_j + 1); memset_s(detail_info, message_context.buffer_offset - mask_j + 1, 0, message_context.buffer_offset - mask_j + 1); if(detail_info == NULL){ static_print_error("detail_info malloc error"); return; } memcpy_s(detail_info, message_context.buffer_offset - mask_j, message_context.buffer + mask_j + 1, message_context.buffer_offset - mask_j); detail_info[message_context.buffer_offset - mask_j] = '\0'; // printf("origin hex text:\r\n"); // uint8_t originlen = message_context.buffer_offset - mask_j + 1; // for (int i = 0; i < originlen; i++) // { // printf("--0x%02x",(uint8_t)detail_info[i]); // } // printf("\r\n"); // 保存消息到数据库 static_print_debug("save message [%d] to database ", index); static_print_debug("detail info: %s", detail_info); static_print_debug("orignal hex data:"); for(uint8_t i = 0; i < message_context.buffer_offset - mask_j; i++) { static_print_info("--%02x",detail_info[i]); if(i != 0 && i % 10 == 0){ static_print_info("\r\n"); } } static_print_info("\r\n"); if (sql_message_set_detail_info(index, detail_info) == RET_ERROR) { static_print_error("set message detail info error"); return; } struct rtc_class_ops *rtc_api = tjd_driver_rtc_get_ops(); uint64_t time_stamp = 0; rtc_api->get_timestamp(&time_stamp); if (sql_message_set_timestamp(index, time_stamp) == RET_ERROR) { static_print_error("set message timestamp error"); return; } if (sql_message_set_valid(index, true) == RET_ERROR) { static_print_error("set message valid error"); return; } message_context.buffer_offset = 0; message_context.expected_seq = 1; free(detail_info); detail_info = NULL; free(buff); buff = NULL; free(message_context.buffer); message_context.buffer = NULL; #if 1 // 从数据库读取消息 // char txt[100] = {0}; char * txt = NULL; if (sql_message_get_detail_info(index, &txt) == RET_ERROR) { static_print_error("get message detail info error"); return; } static_print_debug("message [%d] detail info: %s", index, txt); // memset_s(txt, 100, 0, 100); if (sql_message_get_user_name(index, &txt) == RET_ERROR) { static_print_error("get message name error"); return; } static_print_debug("message [%d] name: %s", index, txt); #endif // 通知app获取消息成功 uint8_t data[] = {0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), ANDROID_PUSH_MESSAGES, server_id, conn_id); TjdUiMsgCenterMessagePopUpTrigger(); } break; } case READ_MOBILE_PHONE_STEP_DATA: { static_print_debug("read mobile phone step data"); // TODO: 读取手机APP步数数据 uint32_t step_data = write_cb_para[3] << 24 | write_cb_para[4] << 16 | write_cb_para[5] << 8 | write_cb_para[6]; static_print_debug("step data: %d", step_data); uint8_t data[] = {0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), READ_MOBILE_PHONE_STEP_DATA, server_id, conn_id); break; } case READ_SET_SYSTEM_LANGUAGE: { static_print_debug("set system language"); sql_setting_set_language(write_cb_para[3]); uint8_t system_language = sql_setting_get_language(); static_print_debug("system language: %d", system_language); uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), READ_SET_SYSTEM_LANGUAGE, server_id, conn_id); break; } case READ_SET_IOS_PUSH_SWITCH: { switch (write_cb_para[3]) { case 0x00: { // 读取ios推送开关 static_print_debug("read ios push switch"); uint8_t data[] = {0x00, 0x00, 0x00, 0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), READ_SET_IOS_PUSH_SWITCH, server_id, conn_id); break; } case 0x01: { // 设置ios推送开关 static_print_debug("set ios push switch"); uint32_t ios_push_switch = write_cb_para[4] << 24 | write_cb_para[5] << 16 | write_cb_para[6] << 8 | write_cb_para[7]; static_print_debug("ios push switch: %d", ios_push_switch); uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), READ_SET_IOS_PUSH_SWITCH, server_id, conn_id); break; } default: static_print_error("unknown ios push switch setting read"); break; } break; } case SET_READ_STEP_GOAL: { switch (write_cb_para[3]) { case 0x00: { // 读取步数目标 static_print_debug("read step goal"); uint32_t step_goal_th = sql_fit_get_goal_step_th(); uint8_t data[] = {0x00, (step_goal_th >> 24) & 0xff, (step_goal_th >> 16) & 0xff, (step_goal_th >> 8) & 0xff , step_goal_th & 0xff}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_STEP_GOAL, server_id, conn_id); break; } case 0x01: { // 设置步数目标 static_print_debug("set step goal"); uint32_t step_goal = write_cb_para[4] << 24 | write_cb_para[5] << 16 | write_cb_para[6] << 8 | write_cb_para[7]; sql_fit_set_goal_step_th(step_goal); uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READ_STEP_GOAL, server_id, conn_id); break; } default: static_print_error("unknown step goal setting read"); break; } break; } case SET_READING_SCREEN_BRIGHTNESS_LEVEL: { switch (write_cb_para[3]) { case 0x00: { // 读取屏幕亮度等级 static_print_debug("read screen brightness level"); uint8_t data[] = {0x00, 0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READING_SCREEN_BRIGHTNESS_LEVEL, server_id, conn_id); break; } case 0x01: { // 设置屏幕亮度等级 static_print_debug("set screen brightness level"); uint8_t sedentary_reminder_parameters = write_cb_para[4]; static_print_debug("screen brightness level: %d", sedentary_reminder_parameters); uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), SET_READING_SCREEN_BRIGHTNESS_LEVEL, server_id, conn_id); break; } default: static_print_error("unknown screen brightness level setting read"); break; } break; } case DIAL_PUSH_DIAL_START_COMMAND: { static_print_debug("dial push dial start command"); // 表盘数据推送开始命令 g_dial_push_data_pkg = write_cb_para[3] << 8 | write_cb_para[4]; static_print_debug("dial push data pkg: %d", g_dial_push_data_pkg); // 电量检测 // 空间检测 // 更改MTU大小 dial_context.buffer_offset = 0; dial_context.expected_seq = 0; dial_context.buffer = malloc(517 * g_dial_push_data_pkg); if (dial_context.buffer == NULL) { static_print_error("malloc failed"); return; } memset_s(dial_context.buffer, 517 * g_dial_push_data_pkg, 0, 517 * g_dial_push_data_pkg); uint8_t data[] = {0x01, 0x02, 0x05}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), DIAL_PUSH_DIAL_START_COMMAND, server_id, conn_id); g_dial_push_data_mask = 1; break; } case GET_WEATHER_DATA: { static_print_debug("get weather data"); // 从 app 获取天气数据 switch (write_cb_para[7]) { case 0x00: { // 今天 sql_weather_set_now_temperature(write_cb_para[4]); sql_weather_set_forecast_protocol_value(write_cb_para[7], write_cb_para[3]); sql_weather_set_forecast_temperature_max(write_cb_para[7], write_cb_para[5]); sql_weather_set_forecast_temperature_min(write_cb_para[7], write_cb_para[6]); break; } case 0x01: { // 明天 sql_weather_set_forecast_protocol_value(write_cb_para[7], write_cb_para[3]); sql_weather_set_forecast_temperature_max(write_cb_para[7], write_cb_para[5]); sql_weather_set_forecast_temperature_min(write_cb_para[7], write_cb_para[6]); break; } case 0x02: { // 后天 sql_weather_set_forecast_protocol_value(write_cb_para[7], write_cb_para[3]); sql_weather_set_forecast_temperature_max(write_cb_para[7], write_cb_para[5]); sql_weather_set_forecast_temperature_min(write_cb_para[7], write_cb_para[6]); struct rtc_class_ops *rtc_api = tjd_driver_rtc_get_ops(); struct rtc_time tm_info = {0}; rtc_api->get_rtc_time(&tm_info); sql_weather_set_update_hour(tm_info.tm_hour); sql_weather_set_update_minute(tm_info.tm_min); uint8_t data[] = {0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), GET_WEATHER_DATA, server_id, conn_id); break; } default: break; } break; } case WALLPAPER_PUSH_START_COMMAND: { static_print_debug("wallpaper push start command"); // 壁纸数据推送开始命令 g_wallpaper_push_data_pkg = write_cb_para[3] << 8 | write_cb_para[4]; static_print_debug("dial push data pkg: %d", g_wallpaper_push_data_pkg); // 电量检测 // 空间检测 // 更改MTU大小 wallpaper_context.buffer_offset = 0; wallpaper_context.expected_seq = 0; wallpaper_context.buffer = malloc(517 * g_wallpaper_push_data_pkg); if (wallpaper_context.buffer == NULL) { static_print_error("malloc failed"); return; } memset_s(wallpaper_context.buffer, 517 * g_wallpaper_push_data_pkg, 0, 517 * g_wallpaper_push_data_pkg); uint8_t data[] = {0x01, 0x02, 0x05}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), WALLPAPER_PUSH_START_COMMAND, server_id, conn_id); g_wallpaper_push_data_mask = 1; break; } case DO_NOT_DISTURB_MODE: { switch (write_cb_para[3]) { case 0x00: { // 读取勿扰模式设置 static_print_debug("read do not disturb mode"); uint8_t data[] = {0x00, 0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), DO_NOT_DISTURB_MODE, server_id, conn_id); break; } case 0x01: { // 设置勿扰模式 static_print_debug("set do not disturb mode"); uint8_t sedentary_reminder_parameters = write_cb_para[4]; static_print_debug("screen brightness level: %d", sedentary_reminder_parameters); uint8_t data[] = {0x01, 0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), DO_NOT_DISTURB_MODE, server_id, conn_id); break; } default: static_print_error("unknown screen brightness level setting read"); break; } break; } case CONTACTS_PUSH_START_COMMAND: { static_print_debug("contacts push start command"); // 通讯录数据推送开始命令 g_contacts_push_data_pkg = write_cb_para[3] << 8 | write_cb_para[4]; static_print_debug("dial push data pkg: %d", g_contacts_push_data_pkg); // 电量检测 uint8_t vbat_present = tjd_service_charger_get_battery(); if (vbat_present <= 20){ static_print_debug("battery is low cant rev addressbook data"); uint8_t data[] = {0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), CONTACTS_PUSH_START_COMMAND, server_id, conn_id); return; } // 空间检测 // 更改MTU大小 // 获取通讯录文件目前储存的通讯录条数 struct stat fileStat = {0}; int ret = stat(TJD_ADDRESS_BOOK_PATH,&fileStat); static_print_debug("access ret is %d", ret); if(ret == 0){ static_print_debug("file exist"); //获取文件大小 FILE *fp = NULL; size_t ret; fp = fopen(TJD_ADDRESS_BOOK_PATH, "a+"); if (fp == NULL) { static_print_error("fopen %s failed!", TJD_ADDRESS_BOOK_PATH); // return -1; } long long file_size = 0; file_size = fileStat.st_size; static_print_debug("file size is %lld", file_size); Contact contact_buffer = {0}; uint8_t contact_num = file_size/sizeof(Contact); static_print_debug("addressbook has %d numbers contact data", contact_num); if(contact_num >= MAX_CONTACTS){ static_print_debug("addressbook has more than MAX_CONTACTS numbers contact data, so we only use MAX_CONTACTS numbers"); uint8_t data[] = {0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), CONTACTS_PUSH_START_COMMAND, server_id, conn_id); }else{ contacts_context.buffer_offset = 0; contacts_context.expected_seq = 0; contacts_context.buffer = malloc(23 * g_contacts_push_data_pkg); if (contacts_context.buffer == NULL) { static_print_error("malloc failed"); return; } memset_s(contacts_context.buffer, 23 * g_contacts_push_data_pkg, 0, 23 * g_contacts_push_data_pkg); // uint8_t data[] = {0x01, 0x02, 0x05}; uint8_t data[] = {0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), CONTACTS_PUSH_START_COMMAND, server_id, conn_id); g_contacts_push_data_mask = 1; } fclose(fp); }else if (ret == -1){ //通讯录文件不存在 contacts_context.buffer_offset = 0; contacts_context.expected_seq = 0; contacts_context.buffer = malloc(23 * g_contacts_push_data_pkg); if (contacts_context.buffer == NULL) { static_print_error("malloc failed"); return; } memset_s(contacts_context.buffer, 23 * g_contacts_push_data_pkg, 0, 23 * g_contacts_push_data_pkg); // uint8_t data[] = {0x01, 0x02, 0x05}; uint8_t data[] = {0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), CONTACTS_PUSH_START_COMMAND, server_id, conn_id); g_contacts_push_data_mask = 1; } break; } case GET_BLUETOOTH_MAC_ADDRESS: { static_print_debug("get bluetooth mac address"); // 获取蓝牙地址 uint8_t *mac_addr = sql_bt_get_mac_addr(); tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, mac_addr, BT_MAC_ADDR_LEN, GET_BLUETOOTH_MAC_ADDRESS, server_id, conn_id); // errcode_t ret = gap_ble_set_ctkd_enable(false); // static_print_debug("gap_ble_set_ctkd_enable ret = %u", ret); break; } case REC_QR_CODE_INFORMATION: { // app开始分包发送消息,我要接收分包数据 static_print_debug("android push qrcode information"); uint8_t qrcode_all_index = write_cb_para[4]; uint8_t qrcode_index = write_cb_para[5]; uint8_t qrcode_len = len - 6; uint8_t qrcode_type = write_cb_para[3]; // if (qrcode_type > 10) { // static_print_error("unknown qrcode type"); // return; // } if(qrcode_type == TJD_QRCODE_TYPE_QQ){ qrcode_type = QRCODE_QQ; } if (qrcode_index == 0x01) { qrcode_context.buffer_offset = 0; qrcode_context.expected_seq = 1; qrcode_context.buffer = malloc(qrcode_len * qrcode_all_index); if (qrcode_context.buffer == NULL) { static_print_error("malloc qrcode buffer error"); return; } memset_s(qrcode_context.buffer, qrcode_len * qrcode_all_index, 0, qrcode_len * qrcode_all_index); } static_print_debug("qrcode_type: %d, qrcode_all_index: %d, qrcode_index: %d", qrcode_type, qrcode_all_index, qrcode_index); if (qrcode_index == qrcode_context.expected_seq++ && qrcode_all_index != qrcode_index) { if (qrcode_context.buffer_offset + qrcode_len > PROTOCOL_BUFFER_MAX_LEN) { static_print_error("qrcode buffer overflow"); return; } memcpy_s(qrcode_context.buffer + qrcode_context.buffer_offset, qrcode_len * qrcode_all_index, &write_cb_para[6], qrcode_len); qrcode_context.buffer_offset += qrcode_len; } else if (qrcode_all_index == qrcode_index) { if (qrcode_context.buffer_offset + qrcode_len < PROTOCOL_BUFFER_MAX_LEN) { memcpy_s(qrcode_context.buffer + qrcode_context.buffer_offset, qrcode_len * qrcode_all_index, &write_cb_para[6], qrcode_len); qrcode_context.buffer_offset += qrcode_len; } static_print_debug("qrcode_data:"); for (uint32_t i = 0; i < qrcode_context.buffer_offset; i++) { static_print_debug("%02x", qrcode_context.buffer[i]); } static_print_debug("qrcode_context.buffer_offset = %d", qrcode_context.buffer_offset); // 保存消息到数据库 static_print_debug("save qrcode info [%d] to database ", qrcode_type); if (sql_bt_set_qrcode_exist(true, qrcode_type) == RET_ERROR) { static_print_error("set qrcode exist error"); return; } if (sql_bt_set_qrcode_info(qrcode_type, qrcode_context.buffer, qrcode_context.buffer_offset) == RET_ERROR) { static_print_error("set qrcode detail info error"); return; } qrcode_context.buffer_offset = 0; qrcode_context.expected_seq = 1; free(qrcode_context.buffer); qrcode_context.buffer = NULL; #if 0 // 从数据库读取二维码信息 uint8_t qrcode_data[256] = {0}; uint16_t qrcode_len = 0; if (sql_bt_get_qrcode_info(qrcode_type, qrcode_data, &qrcode_len) == RET_ERROR) { static_print_error("get qrcode detail info error"); return; } static_print_debug("qrcode [%d] detail info: %s", qrcode_type, qrcode_data); #endif // 通知app获取消息成功 uint8_t data[] = {0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), REC_QR_CODE_INFORMATION, server_id, conn_id); } break; } case IOS_GETS_DEV_BLUETOOTH_CONNEC_STATUS: { static_print_debug("ios gets dev bluetooth connec status"); // 通知app获取蓝牙连接状态 bool aclConnected = bt_is_acl_connected(&g_conn_addr); uint8_t data[] = {0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), IOS_GETS_DEV_BLUETOOTH_CONNEC_STATUS, server_id, conn_id); break; } case APP_READS_DIAL_PARAMETERS: { static_print_debug("app reads dial parameters"); // 通知app表盘推送参数 uint8_t data[] = {0x02, 0x01, 0xd2, 0x01, 0xD2, 0x03, 0xE8}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), APP_READS_DIAL_PARAMETERS, server_id, conn_id); break; } // case MODIFY_BLUETOOTH_NAME: { // static_print_debug("modify bluetooth name"); // static_print_debug("set local name: %s", &write_cb_para[3]); // errcode_t ret = gap_ble_set_local_name(&write_cb_para[3],len - 4); // if(ret != ERRCODE_SUCC){ // static_print_error("set local name error"); // uint8_t data[] = {0x00}; // tjd_ble_protocol_send_data(data, sizeof(data), MODIFY_BLUETOOTH_NAME, server_id, conn_id); // }else{ // uint8_t data[] = {0x01}; // tjd_ble_protocol_send_data(data, sizeof(data), MODIFY_BLUETOOTH_NAME, server_id, conn_id); // } // } case DEVICE_OTHER_FUNCTION_EXTENSION: { static_print_debug("device other function extension"); // 通知app设备其他功能扩展 uint8_t data[] = {0x40, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), DEVICE_OTHER_FUNCTION_EXTENSION, server_id, conn_id); break; } case FIRST_CONNECTION_RESPONSE: { static_print_debug("first connection response"); // 通知app首次连接成功 uint8_t data = 0x01; // uint8_t *send_data = malloc(sizeof(data)); // if (send_data == NULL) { // static_print_debug("malloc send_data fail"); // return; // } // memcpy_s(send_data, sizeof(data), data, sizeof(data)); // static_print_debug("send_data: %02x ", send_data[0]); tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, &data, sizeof(uint8_t), FIRST_CONNECTION_RESPONSE, server_id, conn_id); break; } case GET_DEVICE_ID: { static_print_debug("get device id"); // 获取设备id uint8_t data[] = {0x34, 0xe6}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), GET_DEVICE_ID, server_id, conn_id); break; } case APP_GETS_SPORT_DATA: { static_print_debug("app gets sport data"); //app获取运动记录数据 tjd_service_send_sport_record_data(); break; } case APP_SENDING_ADDRESS: { static_print_debug("app sending address"); // TODO: 接收app下发的地址 uint8_t received_seq = write_cb_para[4]; if (received_seq != addr_context.expected_seq) { // 错误处理:包序号不匹配 static_print_debug("received_seq(%d) != expected_seq(%d)", received_seq, addr_context.expected_seq); } if (received_seq == 0x00) { addr_context.buffer_offset = 0; addr_context.expected_seq = 0x00; addr_context.buffer = malloc(PROTOCOL_DATA_LEN * write_cb_para[3]); if (addr_context.buffer == NULL) { static_print_error("malloc failed"); return; } } memcpy_s(addr_context.buffer + addr_context.buffer_offset, PROTOCOL_MAX_LEN, &write_cb_para[5], len - 6); addr_context.buffer_offset += (len - 6); addr_context.expected_seq++; if (write_cb_para[3] == addr_context.expected_seq) { static_print_debug("receive all data"); static_print_debug("addr_context.buffer_offset: %d, push_data_pkg: %d, addr_context.expected_seq: %d", addr_context.buffer_offset, write_cb_para[3], addr_context.expected_seq); uint8_t mask_i = 0; uint8_t mask_j = 0; char *decode_str = NULL; for (uint32_t i = 0; i < addr_context.buffer_offset; i += 3) { if (addr_context.buffer[i] == 0xe7 && addr_context.buffer[i + 1] == 0x9c && addr_context.buffer[i + 2] == 0x81) { mask_i = i + 3; } else if (addr_context.buffer[i] == 0xe5 && addr_context.buffer[i + 1] == 0xb8 && addr_context.buffer[i + 2] == 0x82) { mask_j = i; decode_str = (char *)malloc(mask_j - mask_i + 3 + 1); // 多加1是为了解码后字符串末尾加上\0 if (decode_str == NULL) { static_print_error("decode_str malloc failed"); return; } memcpy(decode_str, addr_context.buffer + mask_i, mask_j - mask_i + 3); decode_str[mask_j - mask_i + 3] = '\0'; for (int j = 0; j < mask_j - mask_i + 3; j++) { static_print_debug("decode_str[%d]: %02x ", j, decode_str[j]); } break; } } sql_weather_set_location_txt((char *)decode_str, mask_j - mask_i + 3); free(decode_str); // char * location_txt = sql_weather_get_location_txt(); // static_print_debug("location_txt: %s",location_txt); free(addr_context.buffer); addr_context.buffer = NULL; addr_context.buffer_offset = 0; addr_context.expected_seq = 0; uint8_t data1[] = {0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data1, sizeof(data1), APP_SENDING_ADDRESS, server_id, conn_id); } break; } case MS_GAME_MODE: { static_print_debug("ms game mode"); // 通知app进入游戏模式 if(write_cb_para[3] == 0x03){ tjd_into_msgame_view(); }else if(write_cb_para[3] == 0x04){ tjd_exit_app_view(); } uint8_t data = 0x01; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(uint8_t), MS_GAME_MODE, server_id, conn_id); break; } case SEND_GSENSOR_DATA:{ static_print_debug("send gsensor data station"); if(write_cb_para[3] == 0x01){ static_print_debug("send gsensor data station success"); }else{ static_print_debug("send gsensor data station faile"); } } case APP_SENDING_DEVICE_TYPE:{ static_print_debug("send deveice type"); gap_ble_set_ctkd_enable(true); gap_ble_pair_remote_device(tjd_get_lastconned_addr()); break; } case GET_MTU_SIZE: { static_print_debug("get mtu size"); // app获取mtu大小 uint32_t mtu_size = tjd_ble_get_mtu_size() - 3 > 509 ? 509 : tjd_ble_get_mtu_size() - 3; // 减去协议头长度 uint8_t data[2] = {(uint8_t)(mtu_size), (uint8_t)(mtu_size >> 8)}; // uint8_t data[2] = {(uint8_t)(mtu_size >> 8), (uint8_t)(mtu_size)}; static_print_debug("mtu_size: %d, data: %02x %02x", mtu_size, data[0], data[1]); tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), GET_MTU_SIZE, server_id, conn_id); break; } case GET_MAILLIST_FREE_NUM:{ static_print_debug("get maillist free num"); get_addrbook_cnt(GET_MAILLIST_FREE_NUM,server_id, conn_id); break; } case GET_USER_NAME: { static_print_debug("get user name"); // 获取用户名 char user_name[32] = {0}; memcpy_s(user_name, 32 ,write_cb_para + 3 ,len - 4); static_print_debug("user name: %s", user_name); sql_fit_set_user_name(user_name); #if 1 char user_name_get[32] = {0}; sql_fit_get_user_name(user_name_get); static_print_debug("user name get: %s", user_name_get); #endif // uint8_t data_len = strlen(user_name) + 1; uint8_t data = 0x01; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(uint8_t), GET_USER_NAME, server_id, conn_id); tjd_service_gps_sync_ephemeris_event(); // tjd_ble_request_gps(); break; } case GET_BLE_NAME: { static_print_debug("get ble name"); char local_name[13] = {0}; memcpy_s(local_name, 13, &write_cb_para[3],len - 4); static_print_debug("set local name: %s , len : %d", local_name, strlen(local_name)); errcode_t bt_ret = bluetooth_set_local_name((const unsigned char *)local_name, strlen(local_name) + 1); static_print_debug("bt_set_local_name ret(errcode_t): %x ", bt_ret); uint8_t local_bt_name[32] = {0}; uint8 local_name_len = 0; bt_ret = bluetooth_get_local_name(local_bt_name,&local_name_len); static_print_debug("bluetooth_get_local_name ret : %x ,local_name: %s, local_name_len:%d",bt_ret, local_bt_name, local_name_len); errcode_t ret = gap_ble_set_local_name((const uint8_t *)local_name,strlen(local_name) + 1); if(ret != ERRCODE_SUCC || bt_ret != ERRCODE_SUCC){ static_print_error("set local name error"); uint8_t data[] = {0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), GET_BLE_NAME, server_id, conn_id); }else{ static_print_debug("set local name success"); sql_bt_set_ble_name((const uint8_t *)local_name,strlen(local_name)); uint8_t data[] = {0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD, data, sizeof(data), GET_BLE_NAME, server_id, conn_id); } ret = gap_ble_disconnect_remote_device(tjd_get_lastconned_addr()); if(ret != ERRCODE_SUCC){ static_print_debug("disconnect remote device faile ret: %x", ret); }else{ static_print_debug("disconnect remote device success"); } break; } default: static_print_debug("unknown control command"); break; } } void tjd_ble_upload_ai_func_attribute(void) { uint8 send_data[32] = {0}; int index = 0; send_data[index++] = 0x0C; send_data[index++] = 0x00; send_data[index++] = 0x06; send_data[index++] = 0x01; // 设置屏幕分辨率 SET_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_WEIGHT); SET_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_HEIGHT); send_data[index++] = 0x03; send_data[index++] = 0x02; send_data[index++] = 0x00; send_data[index++] = 0x03; send_data[index++] = 0x03; send_data[index++] = 0x03; uint8_t pack_head = 0x5B; tjd_ble_protocol_send_lefun_data(&pack_head,send_data,index,REPORT_AI_FUNCTION_ATTRIBUTES); } void tjd_ble_loop_send_data(uint8_t * pack_head_, uint8_t *data, uint16_t len, uint8_t cmd) { uint8_t pack_head = *pack_head_; uint8_t head_tail_len = 0; uint32_t mtu_size = tjd_ble_get_mtu_size() - 3 > 509 ? 509 : tjd_ble_get_mtu_size() - 3; uint8_t cur_offset = 0; uint8_t cur_pack_num = 0; uint8_t total_pack_num = 0; uint32_t total_data_len = 0; if(pack_head == PROTOCOL_RES_FRAME_HEAD){ head_tail_len = 4; }else if(pack_head == PROTOCOL_RES_FRAME_HEAD_2){ head_tail_len = 5; } total_data_len = len + head_tail_len; total_pack_num = total_data_len / mtu_size; uint8_t * send_data_buf_head = (uint8_t *)malloc(mtu_size); memset(send_data_buf_head, 0, mtu_size); uint16_t send_buffer_len = mtu_size; while(cur_pack_num <= total_pack_num){ if(cur_pack_num == total_pack_num){ send_buffer_len = total_data_len - cur_offset; } memset_s(send_data_buf_head, mtu_size, 0, mtu_size); int index = 0; send_data_buf_head[index++] = pack_head; if(head_tail_len == 4){ send_data_buf_head[index++] = send_buffer_len & 0xFF; }else{ send_data_buf_head[index++] = send_buffer_len >> 8 & 0xFF; send_data_buf_head[index++] = send_buffer_len & 0xFF; } send_data_buf_head[index++] = cmd; memcpy_s(send_data_buf_head + head_tail_len - 1, mtu_size - head_tail_len, data + cur_offset, send_buffer_len - head_tail_len); index+= send_buffer_len - head_tail_len; send_data_buf_head[index] = do_crc(send_data_buf_head, index); cur_offset += send_buffer_len - head_tail_len; cur_pack_num++; gatt_send_response(send_data_buf_head, send_buffer_len,gatt_server_id,g_server_conn_id); } } void tjd_ble_upload_custom_dial_attribute(void) { uint8 send_data[32] = {0}; int index = 0; //设置数据长度 send_data[index++] = 0x18; // 设置固定值 send_data[index++] = 0x00; send_data[index++] = 0x06; send_data[index++] = 0x01; // 设置屏幕分辨率 SET_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_WEIGHT); SET_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_HEIGHT); // 设置固定值 send_data[index++] = 0x06; send_data[index++] = 0x02; // 设置屏幕分辨率的一半 SET_HALF_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_WEIGHT); SET_HALF_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_WEIGHT); // 设置支持的背景模式 send_data[index++] = 0x05; send_data[index++] = 0x03; send_data[index++] = 0x01; send_data[index++] = 0x02; send_data[index++] = 0x03; // 设置多图模式的最大图片数 send_data[index++] = 0x03; send_data[index++] = 0x04; //支持多图模式最大图片数 type send_data[index++] = 0x05; //支持多图模式最大图片数 value // 设置切换方式 send_data[index++] = 0x04; send_data[index++] = 0x05; send_data[index++] = 0x01; //切换方式 : 00 自动 01 手动 02 抬腕切图 send_data[index++] = 0x02; //切换方式 : 00 自动 01 手动 02 抬腕切图 uint8_t pack_head = 0x5B; // tjd_ble_protocol_send_lefun_data(&pack_head,send_data,index,REPORTED_CUSTOM_DIAL_PROPERTIES); tjd_ble_loop_send_data(&pack_head, send_data, index,REPORTED_CUSTOM_DIAL_PROPERTIES); } void tjd_ble_cpy_utf8_data(uint8_t *dest, uint16_t *len , uint8_t *data_type) { if(g_data_flow.data == NULL) return; *len = g_data_flow.len; *data_type = g_data_flow.data_flow_type; memcpy_s(dest, g_data_flow.len, g_data_flow.data, g_data_flow.len); } void tjd_ble_protocol_ctrlcmd_ac(uint8_t server_id, uint16_t conn_id, uint8_t *write_cb_para , uint16_t len) { static_print_info(" tjd_ble_protocol_ctrlcmd_ac(len:%d):\r\n",len); for(int i = 0 ; i < len ; ){ static_print_info("%02x", write_cb_para[i]); i++; if(i % 10 == 0){ static_print_info("\r\n"); } if(i>=60){ break;} } static_print_info("\r\n"); uint8_t crc = write_cb_para[len - 1]; uint8_t crc_cal = do_crc(write_cb_para, len - 1); uint8_t cmd_id = write_cb_para[3]; if (crc != crc_cal) { static_print_error("control command crc error"); if(cmd_id == 0xB3){ uint8_t data[9] = {0}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, &data, sizeof(data), cmd_id, server_id, conn_id); }else{ uint8_t data = 0x00; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, &data, sizeof(data), cmd_id, server_id, conn_id); } return; } switch (cmd_id) { case CUSTOM_DIAL_REQUEST: { static_print_debug("custom dial request"); if(write_cb_para[4] == 0x01){ //APP主动下发请求 if(write_cb_para[5] == 0x00){ //APP请求属性 //回复请求属性 static_print_debug("custom dial request, app request attribute"); uint8_t data[3] = {0x00,0x00,0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); tjd_ble_upload_custom_dial_attribute(); //设备上报自定义表盘属性 }else if(write_cb_para[5] == 0x01){ //APP请求进入自定义表盘模式 static_print_debug("custom dial request, app request enter custom dial mode"); uint8_t data[3] = {0x00,0x01,0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); //待实现 ChangeSlice 到自定义表盘页面 }else if(write_cb_para[5] == 0x02){ //APP请求退出自定义表盘模式 static_print_debug("custom dial request, app request exit custom dial mode"); uint8_t data[3] = {0x00,0x02,0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), cmd_id, server_id, conn_id); tjd_exit_app_view(); } }else if(write_cb_para[4] == 0x00){ //APP回复设备请求 if(write_cb_para[5] == 0x00){ //APP回复设备请求属性 if(write_cb_para[6] == 0x00){ static_print_debug("app reply device request property failed"); }else{ static_print_debug("app reply device request property success"); } }else if(write_cb_para[5] == 0x01){ //APP回复设备进入自定义表盘模式 if(write_cb_para[6] == 0x00){ static_print_debug("app reply device request enter custom watch face mode failed"); }else{ static_print_debug("app reply device request enter custom watch face mode success"); } }else if(write_cb_para[5] == 0x02){ //APP回复设备退出自定义表盘模式 if(write_cb_para[6] == 0x00){ static_print_debug("app reply device request exit custom watch face mode failed"); }else{ static_print_debug("app reply device request exit custom watch face mode success"); } } } break; } case REPORTED_CUSTOM_DIAL_PROPERTIES: { if(write_cb_para[4] == 0x00){ //App回复设备上报自定义表盘参数失败 static_print_debug("app reply device report custom dial properties failed"); }else if(write_cb_para[4] == 0x01){ //App回复设备上报自定义表盘参数成功 static_print_debug("app reply device report custom dial properties success"); }else if(write_cb_para[4] == 0x02){ //App回复设备上报自定义表盘参数接收完成 static_print_debug("app reply device report custom dial properties complete"); } break; } case ISSUE_DIAL_PARAMETERS: { handle_app_issue_dial_parameters_cmd(server_id,conn_id,write_cb_para,len,ISSUE_DIAL_PARAMETERS); break; } case AI_FUNCTION_REQUEST: { static_print_debug("ai function request"); if(write_cb_para[5] == 0xF1){ if(write_cb_para[6] == 0x00){ //请求属性 }else if(write_cb_para[6] == 0x01){ //请求进入音生文模式 if(write_cb_para[7] == 0x00){ //失败 static_print_debug("Request to enter voice mode failed!"); }else if(write_cb_para[7] == 0x01){ //成功 static_print_debug("Request to enter voice mode success!"); } }else if(write_cb_para[6] == 0x02){ //请求退出音生文模式 if(write_cb_para[7] == 0x00){ //失败 static_print_debug("Request to exit voice mode failed!"); }else if(write_cb_para[7] == 0x01){ //成功 static_print_debug("Request to exit voice mode success!"); } } }else if(write_cb_para[5] == 0xF2){ if(write_cb_para[6] == 0x00){ //请求属性 }else if(write_cb_para[6] == 0x01){ //请求进入AI文生图模式 if(write_cb_para[7] == 0x00){ //失败 static_print_debug("Request to enter AI Vincennes diagram mode failed!"); }else if(write_cb_para[7] == 0x01){ //成功 static_print_debug("Request to enter AI Vincennes diagram mode success!"); } }else if(write_cb_para[6] == 0x02){ //请求退出AI文生图模式 } } break; } case REPORT_AI_FUNCTION_ATTRIBUTES: { static_print_debug("report ai function attributes"); if(write_cb_para[4] == 0x00){ static_print_debug("report ai function attributes failed"); }else if(write_cb_para[4] == 0x01){ static_print_debug("report ai function attributes success"); }else if(write_cb_para[4] == 0x02){ static_print_debug("report ai function attributes received complete"); } break; } case AI_AUDIO_TRANSMISSION_MANAGEMENT: { static_print_debug("ai audio transmission management"); //App回复设备 请求进入 音源传输管理 if(write_cb_para[6] == 0x00){ //失败 g_tjd_ble_ai_audio_trans_flag = false; static_print_debug("ai audio transmission management fail"); }else if(write_cb_para[6] == 0x01){ //成功 g_tjd_ble_ai_audio_trans_flag = true; static_print_debug("ai audio transmission management success"); } break; } case REQUEST_DIAGRAM_GENERATION: { static_print_debug("request diagram generation"); uint8_t data_flow_id = write_cb_para[4]; static_print_debug("data flow id: %d", data_flow_id); bool is_success = false; if(write_cb_para[5] == 0x00){ if(write_cb_para[6] == 0x00){ static_print_debug("first request diagram generation failed"); }else if(write_cb_para[6] == 0x01){ //成功 static_print_debug("first request diagram generation success"); is_success = true; } }else if(write_cb_para[5] == 0x01){ if(write_cb_para[6] == 0x00){ static_print_debug("retry request diagram generation failed"); }else if(write_cb_para[6] == 0x01){ //成功 static_print_debug("retry request diagram generation success"); is_success = true; } } if(g_play_dial_request_generate_picture_callback != NULL){ g_play_dial_request_generate_picture_callback(is_success); } break; } case REPORT_DIAGRAM_TRANSMIT: { static_print_debug("request diagram transmit"); if(write_cb_para[4] == 0x00){ if(write_cb_para[5] == 0x00){ static_print_debug("request background diagram transmit failed"); }else if(write_cb_para[5] == 0x01){ static_print_debug("request background diagram transmit success"); // if(g_file_description_packet.file_type == TYPE_AIDIAL_PREVIEW && g_play_dial_preview_callback != NULL){ // g_play_dial_preview_callback((char *)g_file_description_packet.file_name); // } } }else if(write_cb_para[4] == 0x01){ if(write_cb_para[5] == 0x00){ static_print_debug("request background thumbnail diagram transmit failed"); }else if(write_cb_para[5] == 0x01){ static_print_debug("request background thumbnail diagram transmit success"); } } break; } case REQUEST_DEVICE_DIAL_INFORMATION: { static_print_debug("request device dial information"); //获取表盘信息 handle_device_dial_information_cmd(server_id, conn_id, write_cb_para,len,REQUEST_DEVICE_DIAL_INFORMATION); break; } case REQUEST_TO_DELETE_DIAL: { static_print_debug("request to delete dial"); //删除表盘 uint32_t id = write_cb_para[4] << 24 | (write_cb_para[5] << 16) | (write_cb_para[6] << 8) | write_cb_para[7]; if(TjdUiWfUninstallBeforNotify(id)){ static_print_debug("delete dial before notify success"); }else{ static_print_debug("delete dial before notify fail"); } uint8_t data[5] = {0}; if(TjdUiWfUninstallBeforNotify(id)){ static_print_debug("delete dial before notify success"); }else{ static_print_debug("delete dial before notify fail"); } if(TjdUiWfDeletebyID(id)){ static_print_debug("delete dial success"); data[0] = 0x01; if(TjdUiWfUninstallAfterNotify(id)){ static_print_debug("delete dial after notify success"); }else{ static_print_debug("delete dial after notify fail"); } }else{ static_print_debug("delete dial fail"); data[0] = 0x00; } data[1] = (id >> 24) & 0xFF; data[2] = (id >> 16) & 0xFF; data[3] = (id >> 8) & 0xFF; data[4] = id & 0xFF; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, &data, sizeof(data), cmd_id, server_id, conn_id); break; } case REQUEST_WEATHER_DATA: { static_print_debug("request weather data"); handle_weather_data_cmd(server_id, conn_id, write_cb_para,len,REQUEST_WEATHER_DATA); break; } case OTA_MODE_SWITCH_NEW: { static_print_debug("OTA mode switch new"); tjd_ble_protocol_switch_ota(server_id, conn_id, write_cb_para,len,OTA_MODE_SWITCH_NEW); break; } case DOWNLOAD_FILE_DESCRIPTION: { static_print_debug("send file description"); tjd_ble_protocol_file_description(server_id, conn_id, write_cb_para, len, cmd_id); break; } case DOWNLOAD_FILE_SRART: { static_print_debug("send file start"); tjd_ble_protocol_file_start(server_id, conn_id, write_cb_para, len, cmd_id); break; } case DOWNLOAD_FILE_END_DATA: { static_print_debug("send file end data"); tjd_ble_protocol_file_end(server_id, conn_id, write_cb_para, len, cmd_id); break; } case DOWNLOAD_FILE_DATA: { // static_print_debug("download file data"); tjd_ble_protocol_file_data(server_id, conn_id, write_cb_para, len , cmd_id); break; } case UPLOAD_FILE_DESCRIPTION: { static_print_debug("upload file description"); tjd_ble_protocol_file_upload_description_recover_handle(server_id, conn_id, write_cb_para, len , cmd_id); break; } case UPLOAD_FILE_SRART: { static_print_debug("upload file start"); tjd_ble_protocol_file_upload_start_recover_handle(server_id, conn_id, write_cb_para, len , cmd_id); break; } case UPLOAD_FILE_END_DATA: { static_print_debug("upload file end data"); tjd_ble_protocol_file_upload_end_recover_handle(server_id, conn_id, write_cb_para, len , cmd_id); break; } case UPLOAD_FILE_DATA: { static_print_debug("upload file data"); tjd_ble_protocol_file_upload_data_recover_handle(server_id, conn_id, write_cb_para, len , cmd_id); break; } case DATA_FLOW_DOWNLOAD_STARTS: { static_print_debug("data flow download starts"); uint8_t data_flow_type = write_cb_para[5]; // memset(&g_data_flow, 0, sizeof(g_data_flow)); if(g_data_flow.data_flow_id + 1 == write_cb_para[4]){ g_data_flow.data_flow_id++; g_data_flow.data_flow_type = 1; }else{ g_data_flow.data_flow_id = write_cb_para[4]; g_data_flow.data_flow_type = 0; } if(g_data_flow.data == NULL){ g_data_flow.data = (uint8_t *)malloc(512); if(g_data_flow.data == NULL){ static_print_error("malloc data flow data fail"); free(g_data_flow.data); g_data_flow.data = NULL; uint8_t data[] = {write_cb_para[4],data_flow_type,0x00}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), DATA_FLOW_DOWNLOAD_STARTS, server_id, conn_id); return; } memset(g_data_flow.data, 0, 512); static_print_debug("malloc data flow data success"); } uint8_t data[] = {write_cb_para[4],data_flow_type,0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), DATA_FLOW_DOWNLOAD_STARTS, server_id, conn_id); // if(write_cb_para[5] == 0x00){ // //文本UTF-8 数据流类型 // static_print_debug("text utf-8 data flow starts"); // // 回复app 数据流下发开始 // }else if(write_cb_para[5] == 0x10){ // //音频 数据流类型 // static_print_debug("audio data flow starts"); // // 回复app 数据流下发开始 // g_data_flow.data_flow_id = write_cb_para[4]; // uint8_t data[] = {g_data_flow.data_flow_id,0x10,0x01}; // tjd_ble_protocol_send_data(data, sizeof(data), DATA_FLOW_STARTS, server_id, conn_id); // }else if(write_cb_para[5] == 0x20){ // //视频 数据流类型 // static_print_debug("video data flow starts"); // // 回复app 数据流下发开始 // g_data_flow.data_flow_id = write_cb_para[4]; // uint8_t data[] = {g_data_flow.data_flow_id,0x20,0x01}; // tjd_ble_protocol_send_data(data, sizeof(data), DATA_FLOW_STARTS, server_id, conn_id); // } break; } case DATA_FLOW_DOWNLOAD_ENDS: { static_print_debug("data flow download ends"); //回复app 数据流下发成功结束 if(g_data_flow.data != NULL){ // static_print_debug("g_data_flow.data : %s",g_data_flow.data); if(g_lefun_ai_data_end_callback != NULL){ g_lefun_ai_data_end_callback(&g_data_flow); } } uint8_t data[] = {write_cb_para[4],0x01}; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), DATA_FLOW_DOWNLOAD_ENDS, server_id, conn_id); break; } case DATA_FLOW_DOWNLOAD_SENDS_DATA: { static_print_debug("data flow download sends data"); if(g_data_flow.data != NULL){ uint16_t data_len = write_cb_para[1] << 8 | write_cb_para[2]; memset(g_data_flow.data, 0 , 512); memcpy_s(g_data_flow.data, data_len - 7, &write_cb_para[6], data_len - 7); g_data_flow.len += data_len - 7; static_print_debug("g_data_flow.data : %s",g_data_flow.data); if(g_lefun_ai_data_callback != NULL){ g_lefun_ai_data_callback(&g_data_flow); } uint8_t data[3] = {0}; data[0] = write_cb_para[4]; data[1] = write_cb_para[5]; data[2] = 0x01; tjd_ble_protocol_send_data(PROTOCOL_FRAME_RSP_HEAD_2, data, sizeof(data), DATA_FLOW_DOWNLOAD_SENDS_DATA, server_id, conn_id); } break; } case DATA_FLOW_UPLOAD_STARTS: { static_print_debug("data flow upload starts"); if(write_cb_para[6] == 0x10){ static_print_debug("data flow type is audio..."); if(write_cb_para[7] == 0x01){ static_print_debug("data flow is start..."); }else if(write_cb_para[7] == 0x00){ static_print_debug("data flow is failed..."); } } break; } case DATA_FLOW_UPLOAD_ENDS: { static_print_debug("data flow upload ends"); // tjd_lefun_ai_request_exit_audio_transmit(); break; } case REQUEST_LUCKY_CLOVER_DATA: { static_print_debug("request lucky clover data"); tjd_ble_rec_lucky_clover_data(server_id, conn_id, write_cb_para, len , REQUEST_LUCKY_CLOVER_DATA); // uint8_t data[] = {0x01}; // tjd_ble_protocol_send_data(data, sizeof(data), REQUEST_LUCKY_CLOVER_DATA, server_id, conn_id); break; } case REQUEST_GPS_INFORMATION: { static_print_debug("request gps information"); uint8_t pgs_file_num = write_cb_para[5]; uint32_t gps_file_size = write_cb_para[6] << 24 | write_cb_para[7] << 16 | write_cb_para[8] << 8 | write_cb_para[9]; tjd_ble_protocol_dir_transfer_enter_handle(TYPE_GPS, pgs_file_num, gps_file_size); static_print_debug("g_gps_file_all_num: %d, g_gps_file_all_size: %d", pgs_file_num, gps_file_size); break; } case REQUEST_SYNCHRONOUS_DATA: { static_print_debug("request synchronous data"); switch(write_cb_para[4]){ case 0x00: static_print_debug("request synchronous data failed"); break; case 0x01: static_print_debug("request synchronous data success"); break; default: static_print_debug("request synchronous data unknown"); break; } } case REPORTED_JS_APP_INSTALL_STATUS: { static_print_debug("reported js app uninstall"); tjd_ble_uninstall_js_app(server_id, conn_id, write_cb_para, len , REPORTED_JS_APP_INSTALL_STATUS); break; } case GET_JS_APP_LIST: { static_print_debug("get js app list"); bool ret = TjdAppStorePkgUpdateList(); tjd_service_send_js_app_list(); break; } case GET_DEVICE_CRASH_LOG: { static_print_debug("get device crash log"); tjd_service_send_crash_log(); break; } case GET_SLEEP_WEEK_DATA: { static_print_debug("get sleep js list"); tjd_service_send_sleep_week_data(); } case GET_OPENHARMONY_VERSION: { static_print_debug("get openharmony version"); tjd_ble_protocol_get_openharmony_version(server_id, conn_id, write_cb_para, len, GET_OPENHARMONY_VERSION); } default: static_print_debug("unknown control command"); break; } } void upload_file_end(uint8_t server_id, uint8_t conn_id) { static_print_debug("upload file end"); uint8_t data[4] = {0}; data[0] = 0x5A; data[1] = 0x04; data[2] = 0xB6; data[3] = do_crc(data, 3); gatt_send_response(data, sizeof(data), server_id, conn_id); } void register_lefun_ai_data_callback(lefun_ai_data_callback_t callback) { g_lefun_ai_data_callback = callback; } void unregister_lefun_ai_data_callback(void) { g_lefun_ai_data_callback = NULL; } void register_lefun_ai_data_end_callback(lefun_ai_data_callback_t callback) { g_lefun_ai_data_end_callback = callback; } void unregister_lefun_ai_data_end_callback(void) { g_lefun_ai_data_end_callback = NULL; } void register_find_phone_end_callback(fine_phone_end_callback_t callback) { g_fine_phone_end_callback = callback; } void unregister_find_phone_end_callback(void) { g_fine_phone_end_callback = NULL; } play_dial_original_callback_t get_play_dial_original_callback(void) { return g_play_dial_original_callback; } void register_play_dial_original_callback(play_dial_original_callback_t callback) { g_play_dial_original_callback = callback; } void unregister_play_dial_original_callback(void) { g_play_dial_original_callback = NULL; } void register_play_dial_preview_callback(play_dial_preview_callback_t callback) { g_play_dial_preview_callback = callback; } void unregister_play_dial_preview_callback(void) { g_play_dial_preview_callback = NULL; } void register_play_dial_request_generate_picture_callback(play_dial_request_generate_picture_callback_t callback) { g_play_dial_request_generate_picture_callback = callback; } void unregister_play_dial_request_generate_picture_callback(void) { g_play_dial_request_generate_picture_callback = NULL; } void tjd_msgame_send_gesensor_data(uint8_t *data, uint8_t len) { static_print_debug("send gesensor data"); uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD; tjd_ble_protocol_send_lefun_data(&pack_head, data, len, SEND_GSENSOR_DATA); } void tjd_msgame_into(void) { static_print_debug("into msgame"); uint8_t data = 0x01; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD; tjd_ble_protocol_send_lefun_data(&pack_head, &data,sizeof(uint8_t), MS_GAME_MODE); } void tjd_msgame_exit(void) { static_print_debug("exit msgame"); uint8_t data = 0x02; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD; tjd_ble_protocol_send_lefun_data(&pack_head, &data,sizeof(uint8_t), MS_GAME_MODE); } /*Lefun AI相关接口*/ void tjd_lefun_ai_request_into_lefun_ai(void) { static_print_debug("request into lefun ai"); uint8_t data[3] = {0x01,0xF1,0x01}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; tjd_ble_protocol_send_lefun_data(&pack_head, &data,sizeof(data), AI_FUNCTION_REQUEST); } void tjd_lefun_ai_request_exit_lefun_ai(void) { static_print_debug("request into lefun ai"); uint8_t data[3] = {0x01,0xF1,0x02}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; tjd_ble_protocol_send_lefun_data(&pack_head, &data,sizeof(data), AI_FUNCTION_REQUEST); } void tjd_lefun_ai_request_start_audio_transmit(void) { static_print_debug("into lefun ai audio transmit"); uint8_t data[2] = {g_tjd_ble_data_flow_id,0x10}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; tjd_ble_protocol_send_lefun_data(&pack_head, data, sizeof(data), DATA_FLOW_UPLOAD_STARTS); } void tjd_lefun_ai_request_end_audio_transmit(void) { static_print_debug("end lefun ai audio transmit"); uint8_t data = g_tjd_ble_data_flow_id; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; tjd_ble_protocol_send_lefun_data(&pack_head, &data, sizeof(data), DATA_FLOW_UPLOAD_ENDS); g_tjd_ble_data_flow_id++; if(g_tjd_ble_data_flow_id == 0xff){ g_tjd_ble_data_flow_id = 0; } } void tjd_lefun_ai_request_into_audio_transmit(void) { static_print_debug("into lefun ai audio transmit"); uint8_t data[2] = {0x01,0x01}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; tjd_ble_protocol_send_lefun_data(&pack_head, data, sizeof(data), AI_AUDIO_TRANSMISSION_MANAGEMENT); } void tjd_lefun_ai_request_exit_audio_transmit(void) { static_print_debug("exit lefun ai audio transmit"); uint8_t data[2] = {0x01,0x00}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; tjd_ble_protocol_send_lefun_data(&pack_head, data, sizeof(data), AI_AUDIO_TRANSMISSION_MANAGEMENT); } void tjd_lefun_request_weather_data(void) { static_print_debug("request weather data"); uint8_t data[2] = {0x10,0x01}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; tjd_ble_protocol_send_lefun_data(&pack_head, data, sizeof(data), REQUEST_WEATHER_DATA); } void tjd_lefun_request_find_phone(void) { static_print_debug("request_find_phone"); // uint8_t data[2] = {0x10,0x01}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD; tjd_ble_protocol_send_lefun_data(&pack_head, NULL, 0, FIND_MOBILE_PHONE); } void tjd_lefun_request_find_phone_cancel(void) { static_print_debug("request_find_phone_cancel"); // uint8_t data[2] = {0x10,0x01}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD; tjd_ble_protocol_send_lefun_data(&pack_head, NULL, 0, STOP_FINE_PHONE); } bool tjd_ble_get_weather_today_synchronization(void) { return g_weather_today_synchronization_data_mask; } void tjd_ble_set_weather_today_synchronization(bool flag) { if(g_weather_today_synchronization_data_mask != flag){ g_weather_today_synchronization_data_mask = flag; } } void tjd_ble_transmit_audio_data(uint8_t *data, uint16_t len) { uint16_t mtu_size = 167; uint8_t all_package_num = len / (mtu_size - 7); uint8_t cur_package_num = 0; // uint8_t * send_buffer = malloc(mtu_size); uint8_t send_buffer[167] = {0}; uint16_t send_buffer_len = mtu_size; uint16_t cur_offset = 0; // if(send_buffer == NULL){ // static_print_error("ble_transmit_audio_malloc_fail"); // return; // } while(cur_package_num < all_package_num){ // if(cur_package_num == all_package_num){//最后一包 // send_buffer_len = (len % (mtu_size - 6 - 1)) + 6 + 1; // } memset_s(send_buffer, mtu_size, 0, mtu_size); int index = 0; send_buffer[index++] = PROTOCOL_RES_FRAME_HEAD_2; send_buffer[index++] = send_buffer_len >> 8 & 0xFF; send_buffer[index++] = send_buffer_len & 0xFF; send_buffer[index++] = DATA_FLOW_UPLOAD_SENDS_DATA; send_buffer[index++] = g_tjd_ble_data_flow_id; send_buffer[index++] = cur_package_num; memcpy_s(send_buffer + 6, mtu_size - 7, data + cur_offset, send_buffer_len - 7); index+= send_buffer_len - 7; send_buffer[index] = do_crc(send_buffer, index); cur_offset += send_buffer_len - 7; cur_package_num++; gatt_send_response(send_buffer, send_buffer_len,gatt_server_id,g_server_conn_id); osDelay(20); } static_print_debug("send lefun ai audio data success!"); // uint8_t send_data = g_tjd_ble_data_flow_id; // uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; // tjd_ble_protocol_send_lefun_data(&pack_head, &send_data, sizeof(uint8_t), DATA_FLOW_UPLOAD_ENDS); // tjd_lefun_ai_request_end_audio_transmit(); } bool tjd_ble_get_ai_audio_trans_flag(void) { return g_tjd_ble_ai_audio_trans_flag; } /*玩转表盘相关接口*/ void tjd_lefun_ai_request_into_play_dial(void) { static_print_debug("request into play dial"); uint8_t data[3] = {0x01,0xF2,0x01}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; tjd_ble_protocol_send_lefun_data(&pack_head, &data,sizeof(data), AI_FUNCTION_REQUEST); } void tjd_lefun_ai_request_exit_play_dial(void) { static_print_debug("request exit play dial"); uint8_t data[3] = {0x01,0xF2,0x02}; uint8_t pack_head = PROTOCOL_RES_FRAME_HEAD_2; tjd_ble_protocol_send_lefun_data(&pack_head, &data,sizeof(data), AI_FUNCTION_REQUEST); } void tjd_ble_upload_play_dial_func_attribute(ai_picture_style_t style_type, uint8_t language_to_translated, uint8_t translation_language) { uint8 send_data[32] = {0}; int index = 0; send_data[index++] = 0x19; send_data[index++] = 0x00; //TYPE : 0x01 上报屏幕分辨率 send_data[index++] = 0x06; send_data[index++] = 0x01; // 设置屏幕分辨率 466 x 466 SET_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_WEIGHT); SET_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_HEIGHT); //TYPE : 0x02 上报固件支持背景模式 0x00:平台自定义bin格式 0x01:单图 send_data[index++] = 0x03; send_data[index++] = 0x02; send_data[index++] = 0x00; //TYPE : 0x03 上报固件支持音源类型 0x01:APP录音源 0x02:BT音源 0x03:BLE音源 send_data[index++] = 0x03; send_data[index++] = 0x03; send_data[index++] = 0x03; //TYPE : 0x04 上报固件所选AI图片风格 send_data[index++] = 0x03; send_data[index++] = 0x04; send_data[index++] = style_type; //TYPE : 0x05 待翻译语言 翻译语言 send_data[index++] = 0x04; send_data[index++] = 0x05; send_data[index++] = language_to_translated; send_data[index++] = translation_language; //TYPE : 0x06 上报预览图分辨率 send_data[index++] = 0x06; send_data[index++] = 0x06; // 设置屏幕分辨率 233 x 233 SET_HALF_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_WEIGHT); SET_HALF_RESOLUTION(send_data, index, TJD_SCREEN_RESOLUTION_HEIGHT); uint8_t pack_head = 0x5B; tjd_ble_protocol_send_lefun_data(&pack_head,&send_data,index,REPORT_AI_FUNCTION_ATTRIBUTES); } void tjd_play_dial_request_diagram_generation(uint8_t data_flow_id, uint8_t isFirstRequest) { uint8_t send_data[4] = {0}; uint8_t index = 0; send_data[index++] = data_flow_id; send_data[index++] = isFirstRequest; uint8_t pack_head = 0x5B; tjd_ble_protocol_send_lefun_data(&pack_head,send_data,index,REQUEST_DIAGRAM_GENERATION); } void tjd_play_dial_request_diagram_transmit(uint8_t background_type) { uint8_t send_data = background_type; uint8_t pack_head = 0x5B; tjd_ble_protocol_send_lefun_data(&pack_head,&send_data,sizeof(uint8_t),REPORT_DIAGRAM_TRANSMIT); } //JS应用相关接口 5B XXXX CB XXXX LTV(030101 1202xxxxxxxxxxxxxxxxxxxx 0402xxxx 030401)CRC void tjd_js_install_status_request(const uint8_t resultCode, const void *resultMessage) { //参数不带bin后缀 包名:cn.weaher 名称:js天气 printf("request bundleName:%s, label:%s uninstall_by_protocol:%d\r\n", ((BundleInstallMsg *)resultMessage)->bundleName, ((BundleInstallMsg *)resultMessage)->label, uninstall_by_protocol); BundleInstallMsg *installMsg = (BundleInstallMsg *)resultMessage; uint8_t send_data[PROTOCOL_BUFFER_MAX_LEN] = {0}; int index = 0; uint8_t status = installMsg->installState; //操作状态 bool send_opration_res = (status <= BUNDLE_INSTALL_FAIL)? true : (uninstall_by_protocol)? true : false; static_print_debug("status:%d, send_opration_res:%d", status, send_opration_res); uint8_t name_len = strlen(installMsg->bundleName); uint8_t lable_len = strlen(installMsg->label); uint16_t ltv_len = LTV_DEFAULT_LEN + name_len + lable_len + (send_opration_res? 0 : -3); uint16_t package_len = PACKAGE_DEFAULT_LEN + ltv_len; send_data[index++] = PROTOCOL_RES_FRAME_HEAD_2; send_data[index++] = (package_len >> 8 ) & 0xFF; send_data[index++] = package_len & 0xFF; send_data[index++] = REPORTED_JS_APP_INSTALL_STATUS; send_data[index++] = (ltv_len >> 8 ) & 0xFF; send_data[index++] = ltv_len & 0xFF; //LTV数据类型: send_data[index++] = 0x03; send_data[index++] = 0x01; send_data[index++] = (status <= BUNDLE_INSTALL_FAIL)? OPRATION_INSTALL : OPRATION_UNINSTALL; //包名: send_data[index++] = LTV_OFFSET_LEN + name_len; send_data[index++] = 0x02; memcpy_s(&send_data[index], name_len, installMsg->bundleName, name_len); index += name_len; //名称: send_data[index++] = LTV_OFFSET_LEN + lable_len; send_data[index++] = 0x03; memcpy_s(&send_data[index], lable_len, installMsg->label, lable_len); index += lable_len; if(send_opration_res){ //状态: send_data[index++] = 0x03; send_data[index++] = 0x04; send_data[index++] = status; } send_data[index] = do_crc(send_data, package_len - 1); // uninstall_by_protocol = false; gatt_send_response(&send_data, package_len,gatt_server_id,g_server_conn_id); } //通用文件下载回调处理 void file_download_callback_start_type_dial_original(FileDescriptionInfo_t *p_description, FileTransferInfo_t *p_transfer) { } void file_download_callback_end_type_dial_original(FileDescriptionInfo_t *p_description, FileTransferInfo_t *p_transfer) { if(p_transfer->operation_file_size == p_description->file_size) { if(get_play_dial_original_callback() != NULL){ get_play_dial_original_callback()((char *)p_description->file_name); } }else{ int ret = unlink((char *)p_description->file_name); } } void file_download_callback_start_type_dial_doc(FileDescriptionInfo_t *p_description, FileTransferInfo_t *p_transfer) { } void file_download_callback_end_type_dial_doc(FileDescriptionInfo_t *p_description, FileTransferInfo_t *p_transfer) { char * token = NULL; char path_copy[64] = {0}; uint32_t dial_id = 0; if(p_transfer->operation_file_size == p_description->file_size) { strcpy(path_copy, (const char *)p_description->file_name); token = strtok(path_copy, "/"); while(token != NULL){ if (strstr(token, "hi_") == token) { // 提取数字部分 dial_id = atoi(token + 3); // 跳过 "hi_" static_print_debug("Extracted ID: %d", dial_id); } token = strtok(NULL, "/"); } if(token == NULL){ static_print_debug("Failed to extract ID"); } if(dial_id) { if(TjdUiWfIsLocalID(dial_id)){ char bakpath[64] = {0}; strcpy(bakpath, (const char *)p_description->file_name); char *dot = strrchr(bakpath, '.'); if (dot != NULL) { strcpy(dot, ".bak"); } if(access((const char*)bakpath, F_OK) == 0){ //备份文件存在,则删除新下载的文件,使用备份文件 unlink((char *)p_description->file_name); rename((const char *)bakpath, (const char *)p_description->file_name); } } TjdUiWfInstallAfterNotify(dial_id); } }else{ int ret = unlink((char *)p_description->file_name); } } void file_download_callback_end_type_dial_custom(FileDescriptionInfo_t *p_description, FileTransferInfo_t *p_transfer) { if(p_transfer->operation_file_size == p_description->file_size) { tjd_service_save_dial_parameter(&dial_param); if(TjdUiWfInstallAfterNotify(0)){ static_print_debug("install after notify success"); }else{ static_print_debug("install after notify failed"); } }else{ int ret = unlink((char *)p_description->file_name); } } void file_download_callback_end_type_gps(FileDescriptionInfo_t *p_description, FileTransferInfo_t *p_transfer) { static_print_debug("total file size is %d-%d,file number:%d-%d", tjd_ble_get_transfer_info()->operation_total_size, tjd_ble_get_dir_description()->file_total_size, tjd_ble_get_transfer_info()->operation_total_number, tjd_ble_get_dir_description()->file_total_number); if(p_transfer->operation_total_number == tjd_ble_get_dir_description()->file_total_number && p_transfer->operation_total_size >= tjd_ble_get_dir_description()->file_total_size){ if(access(TJD_FS_DIR_GPS,0) == 0){ delete_directory(TJD_FS_DIR_GPS); } if(access(TJD_FS_DIR_GPS_BAT,0) == 0){ //重命名 TJD_FS_DIR_GPS_BAT to TJD_FS_DIR_GPS if(rename(TJD_FS_DIR_GPS_BAT,TJD_FS_DIR_GPS) != 0){ static_print_error("rename gps dir fail"); }else{ static_print_debug("rename gps dir success"); } } p_transfer->file_status = FileTransfer_NULL; p_description->file_type = FileType_MAX; tjd_ble_protocol_dir_transfer_exit_handle(); } } void file_download_callback_end_type_js(FileDescriptionInfo_t *p_description, FileTransferInfo_t *p_transfer) { if(p_transfer->file_status == FileTransfer_Timeout){ //目前这种状态控制逻辑不明确,暂定 return; } // /user/tjd_js/xxx.bin char pkg_name[50] = {0}; char *file_name = strrchr((const char *)(p_description->file_name), '/') + 1; char *temp_point = strrchr((const char *)(file_name), '.'); int len = temp_point - file_name; strncpy(pkg_name,file_name,len); pkg_name[len] = '\0'; static_print_debug("file_name:%s",p_description->file_name); static_print_debug("pkg_name:%s",pkg_name); TjdAppStorePkgOperation(PKG_OPERATION_TYPE_INSTALL,(const char *)pkg_name,false); } //通用文件上传回调处理 static upload_file_end_callback_t g_upload_file_recode_end_callback = NULL; upload_file_end_callback_t get_upload_file_recode_end_callback(void) { return g_upload_file_recode_end_callback; } void register_upload_file_recode_end_callback(upload_file_end_callback_t callback) { g_upload_file_recode_end_callback = callback; } void file_upload_callback_start_type_recode(uint8_t cmd_ret) { static_print_debug("file_upload_callback_start_type_recode(cmd_ret=%d):", cmd_ret); if (cmd_ret == 0x02) //文件存在结束 { if(get_upload_file_recode_end_callback() != NULL){ get_upload_file_recode_end_callback()(UPLOAD_END_EXIST); } } } void file_upload_callback_end_type_recode(FileUploadEndEnum value) { static_print_debug("file_upload_callback_end_type_recode(value=%d):", value); if(get_upload_file_recode_end_callback() != NULL){ get_upload_file_recode_end_callback()(value); } } extern osal_event g_sport_record_event; void file_upload_callback_start_type_sport_record(uint8_t cmd_ret) { if (cmd_ret == 0x02) { static_print_debug("upload file start faile! app has exisit file!"); int ret = osal_event_write(&g_sport_record_event, FILE_SEND_SKIP); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_SKIP failed!"); } } else if (cmd_ret == 0x03){ static_print_debug("upload file start faile! app has no enough space!"); int ret = osal_event_write(&g_sport_record_event, FILE_SEND_NOSPACE); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_NOSPACE failed!"); } } else if (cmd_ret == 0x04){ static_print_debug("upload file start faile! app has no support file type!"); int ret = osal_event_write(&g_sport_record_event, FILE_SEND_NOSUPPORT); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_NOSUPPORT failed!"); } } else if(cmd_ret == 0x00){ static_print_debug("upload file start faile!"); int ret = osal_event_write(&g_sport_record_event, FILE_SEND_FAILE); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_NOSUPPORT failed!"); } } } void file_upload_callback_end_type_sport_record(FileUploadEndEnum value) { if(value == UPLOAD_END_SUCCEED) { int ret = osal_event_write(&g_sport_record_event, FILE_SEND_SUCCESS); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_SUCCESS failed!"); } } else{ int ret = osal_event_write(&g_sport_record_event, FILE_SEND_FAILE); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_FAILE failed!"); } } } extern osal_event g_js_app_list_event; void file_upload_callback_start_type_js_app_list(uint8_t cmd_ret) { if (cmd_ret == 0x02) { static_print_debug("upload file start faile! app has exisit file!"); int ret = osal_event_write(&g_js_app_list_event, FILE_SEND_SKIP); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_SKIP failed!"); } } else if (cmd_ret == 0x03){ static_print_debug("upload file start faile! app has no enough space!"); int ret = osal_event_write(&g_js_app_list_event, FILE_SEND_NOSPACE); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_NOSPACE failed!"); } } else if (cmd_ret == 0x04){ static_print_debug("upload file start faile! app has no support file type!"); int ret = osal_event_write(&g_js_app_list_event, FILE_SEND_NOSUPPORT); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_NOSUPPORT failed!"); } } else if(cmd_ret == 0x00){ static_print_debug("upload file start faile!"); int ret = osal_event_write(&g_js_app_list_event, FILE_SEND_FAILE); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_NOSUPPORT failed!"); } } } void file_upload_callback_end_type_js_app_list(FileUploadEndEnum value) { if(value == UPLOAD_END_SUCCEED) { int ret = osal_event_write(&g_js_app_list_event, FILE_SEND_SUCCESS); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_SUCCESS failed!"); } } else{ int ret = osal_event_write(&g_js_app_list_event, FILE_SEND_FAILE); if(ret != OSAL_SUCCESS){ static_print_error("write event FILE_SEND_FAILE failed!"); } } }