4089 lines
184 KiB
C
4089 lines
184 KiB
C
/*----------------------------------------------------------------------------
|
||
* 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 <stdio.h>
|
||
#include <sys/stat.h>
|
||
#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 <dirent.h>
|
||
#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!");
|
||
}
|
||
}
|
||
} |