From e08dbd06a7fd918d49da940d821040d7f1a75372 Mon Sep 17 00:00:00 2001 From: luozheng <1732036298@qq.com> Date: Sat, 22 Nov 2025 10:44:51 +0800 Subject: [PATCH] =?utf8?q?ln=EF=BC=9A=E6=B7=BB=E5=8A=A0=E4=B8=8E=E8=93=9D?= =?utf8?q?=E7=89=99=E8=AE=BE=E5=A4=87=E8=BF=9E=E6=8E=A5=E7=8A=B6=E6=80=81?= =?utf8?q?=E4=B8=8A=E6=8A=A5=E7=9B=B8=E5=85=B3=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../sdk/zhihui/leiniao/imsl_ln/CMakeLists.txt | 1 + .../zhihui/leiniao/imsl_ln/leiniao_api_at.c | 16 + code/sdk/zhihui/leiniao/imsl_ln/ln_api.c | 58 +++- code/sdk/zhihui/leiniao/imsl_ln/ln_api.h | 29 ++ .../zhihui/leiniao/imsl_ln/ln_api_web_ack.c | 98 ++++++ .../zhihui/leiniao/imsl_ln/ln_api_websocket.c | 6 + .../zhihui/leiniao/imsl_ln/ln_bluetooth_api.c | 318 ++++++++++++++++++ 7 files changed, 524 insertions(+), 2 deletions(-) create mode 100644 code/sdk/zhihui/leiniao/imsl_ln/ln_bluetooth_api.c diff --git a/code/sdk/zhihui/leiniao/imsl_ln/CMakeLists.txt b/code/sdk/zhihui/leiniao/imsl_ln/CMakeLists.txt index e6c09ec5d..83db0ffc7 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/CMakeLists.txt +++ b/code/sdk/zhihui/leiniao/imsl_ln/CMakeLists.txt @@ -22,6 +22,7 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/ln_api_timeline_activities.c ${CMAKE_CURRENT_SOURCE_DIR}/ln_api_web_ack.c ${CMAKE_CURRENT_SOURCE_DIR}/ln_file_recv_task.c + ${CMAKE_CURRENT_SOURCE_DIR}/ln_bluetooth_api.c ) # 公共头文件路径(供其他模块引用) diff --git a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c index 8bacb6d08..b28cb2352 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c @@ -1647,6 +1647,19 @@ static uint32_t ln_debug_popup_at(uint8_t *para, uint32_t paraLen, char *strComm printf("+LN_DEBUG_POPUP: OK\n"); return ERRCODE_SUCC; } + +//蓝牙状态上报 +static uint32_t ln_bluetooth_status_report_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + char *bluetoothStatus = NULL; + if (para != NULL && paraLen > 0) { + bluetoothStatus = (char*)para; + } + printf("+LN_BLUETOOTH_STATUS_REPORT: OK\n"); + printf("[LN][BLUETOOTH_STATUS_REPORT] bluetoothStatus=%s\n", bluetoothStatus); + do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT, bluetoothStatus, strlen(bluetoothStatus)); + return ERRCODE_SUCC; +} static const at_cmd_table_t g_ln_api_cmd[] = { /* ---------------------------------- 雷鸟API --------------------------------- */ {(char *)"AT^LN_GET_TOKEN", ln_get_device_token_at, (char *)"获取雷鸟设备Token: AT^LN_GET_TOKEN[=deviceId,deviceIccid,deviceModel,deviceVersion]"}, @@ -1733,6 +1746,9 @@ static const at_cmd_table_t g_ln_api_cmd[] = { //WS状态和网络参数显示 {(char *)"AT^LN_SHOW_WS_NET", ln_show_ws_net_at, (char *)"显示WS连接状态和网络参数: AT^LN_SHOW_WS_NET[=-p x,y]"}, {(char *)"AT^LN_HIDE_WS_NET", ln_hide_ws_net_at, (char *)"隐藏WS连接状态和网络参数显示: AT^LN_HIDE_WS_NET"}, + + //蓝牙相关 + {(char *)"AT^LN_BLUETOOTH_STATUS_REPORT", ln_bluetooth_status_report_at, (char *)"蓝牙状态上报: AT^LN_BLUETOOTH_STATUS_REPORT[=bluetoothStatus]"}, }; diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c index 45010ff5d..0bd797fce 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c @@ -457,7 +457,7 @@ void uapi_ln_remove_vote(void) uint8_t cnt = pm_veto_get_id_cnt(PM_ID_DEBUG); if (cnt == 1) { - uapi_ln_remove_vote(); + uapi_pm_add_sleep_veto(PM_ID_DEBUG); } } void uapi_ln_add_vote(void) @@ -465,7 +465,7 @@ void uapi_ln_add_vote(void) uint8_t cnt = pm_veto_get_id_cnt(PM_ID_DEBUG); if (cnt == 0) { - uapi_ln_add_vote(); + uapi_pm_add_sleep_veto(PM_ID_DEBUG); } } @@ -921,6 +921,44 @@ void ln_ws_process_message(const ws_data_msg_t *data_msg, ws_command_t type) } break; } + case WS_CMD_BLUETOOTH_CONNECT: + { + printf("[WS] BluetoothConnect:蓝牙连接\n"); + if (json_str) + { + ln_parse_bluetooth_connect(json_str, (int)strlen(json_str)); + /* 发送蓝牙连接应答 */ + ln_ws_send_bluetooth_connect_ack(true, "蓝牙连接中"); + /* TODO: 这里应该调用实际的蓝牙连接接口,执行搜索和连接操作 */ + /* 连接完成后,通过BluetoothStatusReport命令上报最终状态 */ + } + break; + } + case WS_CMD_BLUETOOTH_UNBIND: + { + printf("[WS] BluetoothUnbind:蓝牙解绑\n"); + if (json_str) + { + ln_parse_bluetooth_unbind(json_str, (int)strlen(json_str)); + const ln_bluetooth_unbind_data_t *unbind_data = ln_get_bluetooth_unbind_data(); + /* 发送蓝牙解绑应答 */ + ln_ws_send_bluetooth_unbind_ack( + unbind_data->bluetooth_address, + unbind_data->bluetooth_name, + true, + "蓝牙解绑中" + ); + /* TODO: 这里应该调用实际的蓝牙解绑接口,执行解绑操作 */ + /* 解绑完成后,通过BluetoothStatusReport命令上报最终状态 */ + } + break; + } + case WS_CMD_BLUETOOTH_STATUS_REPORT_ACK: + { + printf("[WS] BluetoothStatusReportAck:蓝牙状态上报应答\n"); + /* 服务端对设备蓝牙状态上报的应答,设备端可以记录或处理 */ + break; + } case WS_CMD_PING: { printf("[WS] Ping\n"); @@ -1127,6 +1165,22 @@ static void ln_http_server_send_task(void const *arg) WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_HTTP_SERVICE_CMD_WS_EXIT_SLEEP] 退出休眠"); ln_ws_exit_sleep(); } + else if(mail.cmd == LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT] 蓝牙状态上报"); + if (mail.data && mail.len > 0) + { + /* 确保字符串以\0结尾,避免乱码 */ + char *bluetooth_status = (char *)malloc(mail.len + 1); + if (bluetooth_status) + { + memcpy(bluetooth_status, mail.data, mail.len); + bluetooth_status[mail.len] = '\0'; + ln_send_bluetooth_status_report(bluetooth_status); + free(bluetooth_status); + } + } + } if (mail.data != NULL) { printf("free(mail.data)\n"); diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h index 1c226ea93..72633fd17 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h @@ -135,6 +135,9 @@ typedef struct #define LN_HTTP_SERVICE_CMD_WS_ENTER_SLEEP 0x1013 /* 进入休眠 */ #define LN_HTTP_SERVICE_CMD_WS_EXIT_SLEEP 0x1014 /* 退出休眠 */ +//蓝牙状态上报相关命令 +#define LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT 0x1015 /* 蓝牙状态上报 */ + /* 下载文件相关结构体 */ typedef struct { @@ -326,6 +329,27 @@ void ln_parse_delete_emoji(const char *json_str, int json_len); void ln_emoji_report_status(char *data); /* 解析设备升级 */ void ln_parse_device_upgrade(const char *json_str, int json_len); +/* 解析蓝牙连接命令 */ +void ln_parse_bluetooth_connect(const char *json_str, int json_len); +/* 解析蓝牙解绑命令 */ +void ln_parse_bluetooth_unbind(const char *json_str, int json_len); +/* 发送蓝牙状态上报(使用消息队列方式) */ +void ln_send_bluetooth_status_report(const char *bluetooth_status); +/* 蓝牙连接命令数据结构 */ +typedef struct { + char user_id[64]; + char bluetooth_address[32]; +} ln_bluetooth_connect_data_t; +/* 蓝牙解绑命令数据结构 */ +typedef struct { + char user_id[64]; + char bluetooth_address[32]; + char bluetooth_name[128]; +} ln_bluetooth_unbind_data_t; +/* 获取蓝牙连接命令数据 */ +const ln_bluetooth_connect_data_t* ln_get_bluetooth_connect_data(void); +/* 获取蓝牙解绑命令数据 */ +const ln_bluetooth_unbind_data_t* ln_get_bluetooth_unbind_data(void); /* 从下发JSON中提取userId */ void ln_ws_ack_user_id_from_json(const char *json_str); /* ========== Ack 发送接口 ========== */ @@ -338,6 +362,8 @@ int ln_ws_send_schedule_reminder_config_ack(int schedule_id, bool success, const int ln_ws_send_delete_emoji_ack(const char *character_id, const char *eyesColor, const char *eyesShape, bool success, const char *msg); int ln_ws_send_download_emoji_ack(const char *character_id, const char *eyesColor, const char *eyesShape, bool success, const char *msg); int ln_ws_send_device_upgrade_ack(const char *update_id, const char *target_version, bool success, const char *msg); +int ln_ws_send_bluetooth_connect_ack(bool success, const char *msg); +int ln_ws_send_bluetooth_unbind_ack(const char *bluetooth_address, const char *bluetooth_name, bool success, const char *msg); /* =================== 时间线状态(Timeline getStatus) =================== */ /* 查询时间线状态(GET /v1/timeline/getStatus)*/ uint32_t ln_timeline_get_status_http(const char *device_id, @@ -417,6 +443,9 @@ typedef enum { WS_CMD_AUDIO_RECORDING_END, /* 结束录音上传 */ WS_CMD_SENTENCE_PLAYBACK_COMPLETE, /* 单句语音播放完成 */ WS_CMD_DEVICE_UPGRADE, /* 设备升级(DeviceUpgrade) */ + WS_CMD_BLUETOOTH_CONNECT, /* 蓝牙连接(BluetoothConnect) */ + WS_CMD_BLUETOOTH_UNBIND, /* 蓝牙解绑(BluetoothUnbind) */ + WS_CMD_BLUETOOTH_STATUS_REPORT_ACK, /* 蓝牙状态上报应答(BluetoothStatusReportAck) */ WS_CMD_MAX /* 最大命令 */ } ws_command_t; diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_web_ack.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_web_ack.c index 7b92553ab..4b88ff4c0 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_web_ack.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_web_ack.c @@ -568,4 +568,102 @@ int ln_ws_send_device_upgrade_ack(const char *update_id, const char *target_vers cJSON_free(json_string); cJSON_Delete(json); return ret; +} + +/* 发送蓝牙连接应答消息,确认设备已收到连接命令并开始处理 */ +int ln_ws_send_bluetooth_connect_ack(bool success, const char *msg) +{ + if (ln_ws_get_connection_state() != 2) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Cannot send BluetoothConnectAck, connection state: %d\n", ln_ws_get_connection_state()); + return -1; + } + + uint32_t timestamp; + uapi_get_timestampe_ss(×tamp); + + cJSON *json = cJSON_CreateObject(); + if (!json) + return -1; + + cJSON_AddStringToObject(json, "deviceId", uapi_ln_get_device_id()); + cJSON_AddNumberToObject(json, "timestamp", (double)timestamp); + + char message_id[64]; + snprintf(message_id, sizeof(message_id), "ack_bt_connect_%u", timestamp); + cJSON_AddStringToObject(json, "messageId", message_id); + cJSON_AddStringToObject(json, "command", "BluetoothConnectAck"); + + cJSON *data = cJSON_CreateObject(); + if (!data) + { + cJSON_Delete(json); + return -1; + } + cJSON_AddBoolToObject(data, "success", success); + cJSON_AddStringToObject(data, "message", msg ? msg : (success ? "蓝牙连接中" : "蓝牙连接失败")); + cJSON_AddItemToObject(json, "data", data); + + char *json_string = cJSON_Print(json); + if (!json_string) + { + cJSON_Delete(json); + return -1; + } + + int ret = uapi_ws_send_text(json_string); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Sent BluetoothConnectAck: %s\n", json_string); + cJSON_free(json_string); + cJSON_Delete(json); + return ret; +} + +/* 发送蓝牙解绑应答消息,确认设备已收到解绑命令并开始处理 */ +int ln_ws_send_bluetooth_unbind_ack(const char *bluetooth_address, const char *bluetooth_name, bool success, const char *msg) +{ + if (ln_ws_get_connection_state() != 2) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Cannot send BluetoothUnbindAck, connection state: %d\n", ln_ws_get_connection_state()); + return -1; + } + + uint32_t timestamp; + uapi_get_timestampe_ss(×tamp); + + cJSON *json = cJSON_CreateObject(); + if (!json) + return -1; + + cJSON_AddStringToObject(json, "deviceId", uapi_ln_get_device_id()); + cJSON_AddNumberToObject(json, "timestamp", (double)timestamp); + + char message_id[64]; + snprintf(message_id, sizeof(message_id), "ack_bt_unbind_%u", timestamp); + cJSON_AddStringToObject(json, "messageId", message_id); + cJSON_AddStringToObject(json, "command", "BluetoothUnbindAck"); + + cJSON *data = cJSON_CreateObject(); + if (!data) + { + cJSON_Delete(json); + return -1; + } + cJSON_AddStringToObject(data, "bluetoothAddress", (bluetooth_address && bluetooth_address[0]) ? bluetooth_address : ""); + cJSON_AddStringToObject(data, "bluetoothName", (bluetooth_name && bluetooth_name[0]) ? bluetooth_name : ""); + cJSON_AddBoolToObject(data, "success", success); + cJSON_AddStringToObject(data, "message", msg ? msg : (success ? "蓝牙解绑中" : "蓝牙解绑失败")); + cJSON_AddItemToObject(json, "data", data); + + char *json_string = cJSON_Print(json); + if (!json_string) + { + cJSON_Delete(json); + return -1; + } + + int ret = uapi_ws_send_text(json_string); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Sent BluetoothUnbindAck: %s\n", json_string); + cJSON_free(json_string); + cJSON_Delete(json); + return ret; } \ No newline at end of file diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c index 000168063..35272dd78 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c @@ -1620,6 +1620,12 @@ static ws_command_t ln_ws_parse_command_string(const char *command_str) return WS_CMD_RANDOM_STORY_RESPONSE; } else if (strcmp(command_str, "DeviceUpgrade") == 0) { return WS_CMD_DEVICE_UPGRADE; + } else if (strcmp(command_str, "BluetoothConnect") == 0) { + return WS_CMD_BLUETOOTH_CONNECT; + } else if (strcmp(command_str, "BluetoothUnbind") == 0) { + return WS_CMD_BLUETOOTH_UNBIND; + } else if (strcmp(command_str, "BluetoothStatusReportAck") == 0) { + return WS_CMD_BLUETOOTH_STATUS_REPORT_ACK; } else { return WS_CMD_UNKNOWN; } diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_bluetooth_api.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_bluetooth_api.c new file mode 100644 index 000000000..e48b1a8fc --- /dev/null +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_bluetooth_api.c @@ -0,0 +1,318 @@ +#include "ln_api.h" +#include "cJSON.h" +#include "custom_utils.h" +#include + +/* 蓝牙状态枚举值常量 */ +#define BT_STATUS_CONNECTED "CONNECTED" /* 蓝牙已连接 */ +#define BT_STATUS_DISCONNECTED "DISCONNECTED" /* 蓝牙已断开 */ +#define BT_STATUS_CONNECTING "CONNECTING" /* 蓝牙连接中 */ +#define BT_STATUS_CONNECT_FAILED "CONNECT_FAILED" /* 蓝牙连接失败 */ +#define BT_STATUS_UNBINDING "UNBINDING" /* 蓝牙解绑中 */ +#define BT_STATUS_UNBIND_FAILED "UNBIND_FAILED" /* 蓝牙解绑失败 */ +#define BT_STATUS_UNBIND_SUCCESS "UNBIND_SUCCESS" /* 蓝牙解绑成功 */ + +/* 全局变量存储蓝牙命令数据 */ +static ln_bluetooth_connect_data_t g_bluetooth_connect_data = {0}; +static ln_bluetooth_unbind_data_t g_bluetooth_unbind_data = {0}; +static char bluetooth_address[32]; /* 蓝牙设备MAC地址 */ +static char bluetooth_name[128]; /* 蓝牙设备名称 */ +static int battery_level; /* 电池电量百分比,范围0-100 */ + +/*获取已经绑定的耳机蓝牙设备MAC地址:"bluetoothAddress": "AA:BB:CC:DD:EE:FF"*/ +char *ln_get_bluetooth_device_mac(void) +{ + bluetooth_address[0] = '\0'; + // errcode_t res = bluetooth_get_bound_device_mac(bluetooth_address, sizeof(bluetooth_address)); + // if (res != ERRCODE_SUCCESS) + // { + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备MAC地址失败"); + // return NULL; + // } + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备MAC地址成功:%s", bluetooth_address); + strncpy(bluetooth_address, "AA:BB:CC:DD:EE:FF", sizeof(bluetooth_address) - 1); + bluetooth_address[sizeof(bluetooth_address) - 1] = '\0'; + return bluetooth_address; +} + +/* 获取已绑定的耳机蓝牙设备名称:"bluetoothName": "AirPods Pro"*/ +char *ln_get_bluetooth_device_name(void) +{ + bluetooth_name[0] = '\0'; + // errcode_t res = bluetooth_get_bound_device_name(bluetooth_name, sizeof(bluetooth_name)); + // if (res != ERRCODE_SUCCESS) + // { + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备名称失败"); + // return NULL; + // } + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备名称成功:%s", bluetooth_name); + strncpy(bluetooth_name, "AirPods Pro", sizeof(bluetooth_name) - 1); + bluetooth_name[sizeof(bluetooth_name) - 1] = '\0'; + return bluetooth_name; +} + +/* 获取已绑定的耳机蓝牙设备电池电量:"batteryLevel": 80 */ +int ln_get_bluetooth_device_battery_level(void) +{ + battery_level = 80; + // errcode_t res = bluetooth_get_battery_level(&battery_level); + // if (res != ERRCODE_SUCCESS) + // { + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取耳机蓝牙设备电池电量失败"); + // return 0; + // } + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取耳机蓝牙设备电池电量成功:%d", battery_level); + return battery_level; +} + +/* 发送蓝牙状态上报 BluetoothStatusReport(内部实现,通过WebSocket发送) */ +static int ln_ws_send_bluetooth_status_report(const char *bluetooth_address, const char *bluetooth_name, + int battery_level, const char *bluetooth_status, const char *msg) +{ + if (ln_ws_get_connection_state() != 2) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Cannot send BluetoothStatusReport, connection state: %d\n", ln_ws_get_connection_state()); + return -1; + } + + uint32_t timestamp; + uapi_get_timestampe_ss(×tamp); + + cJSON *json = cJSON_CreateObject(); + if (!json) + return -1; + + cJSON_AddStringToObject(json, "deviceId", uapi_ln_get_device_id()); + cJSON_AddNumberToObject(json, "timestamp", (double)timestamp); + + char message_id[64]; + snprintf(message_id, sizeof(message_id), "bt_status_%u", timestamp); + cJSON_AddStringToObject(json, "messageId", message_id); + cJSON_AddStringToObject(json, "command", "BluetoothStatusReport"); + + cJSON *data = cJSON_CreateObject(); + if (!data) + { + cJSON_Delete(json); + return -1; + } + cJSON_AddStringToObject(data, "bluetoothAddress", (bluetooth_address && bluetooth_address[0]) ? bluetooth_address : ""); + cJSON_AddStringToObject(data, "bluetoothName", (bluetooth_name && bluetooth_name[0]) ? bluetooth_name : ""); + + /* 限制电池电量范围在0-100之间 */ + int battery = battery_level; + if (battery_level < 0 || battery_level > 100) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 电池电量范围不在0-100之间"); + } + if (battery < 0) + battery = 0; + if (battery > 100) + battery = 100; + cJSON_AddNumberToObject(data, "batteryLevel", battery); + + cJSON_AddStringToObject(data, "bluetoothStatus", (bluetooth_status && bluetooth_status[0]) ? bluetooth_status : ""); + cJSON_AddStringToObject(data, "message", msg ? msg : ""); + cJSON_AddItemToObject(json, "data", data); + + char *json_string = cJSON_Print(json); + if (!json_string) + { + cJSON_Delete(json); + return -1; + } + + int ret = uapi_ws_send_text(json_string); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Sent BluetoothStatusReport: %s\n", json_string); + cJSON_free(json_string); + cJSON_Delete(json); + return ret; +} + +/* 发送蓝牙状态上报(使用消息队列方式) */ +void ln_send_bluetooth_status_report(const char *bluetooth_status) +{ + if (!bluetooth_status || !bluetooth_status[0]) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 蓝牙状态为空"); + return; + } + char *msg = NULL; + if(strcmp(bluetooth_status, BT_STATUS_CONNECTED) == 0) + { + msg = "蓝牙已连接"; + } + else if(strcmp(bluetooth_status, BT_STATUS_CONNECTING) == 0) + { + msg = "蓝牙连接中"; + } + else if(strcmp(bluetooth_status, BT_STATUS_CONNECT_FAILED) == 0) + { + msg = "蓝牙已连接失败"; + } + else if(strcmp(bluetooth_status, BT_STATUS_DISCONNECTED) == 0) + { + msg = "蓝牙断开连接"; + } + else if(strcmp(bluetooth_status, BT_STATUS_UNBINDING) == 0) + { + msg = "蓝牙解绑中"; + } + else if(strcmp(bluetooth_status, BT_STATUS_UNBIND_FAILED) == 0) + { + msg = "蓝牙解绑失败"; + } + else if(strcmp(bluetooth_status, BT_STATUS_UNBIND_SUCCESS) == 0) + { + msg = "蓝牙解绑成功"; + } + else + { + msg = NULL; + } + ln_ws_send_bluetooth_status_report( + ln_get_bluetooth_device_mac(), + ln_get_bluetooth_device_name(), + ln_get_bluetooth_device_battery_level(), + bluetooth_status, + msg); +} + +/* 解析蓝牙连接命令 BluetoothConnect */ +void ln_parse_bluetooth_connect(const char *json_str, int json_len) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 解析蓝牙连接命令"); + if (!json_str || json_len <= 0) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] parse connect command: invalid json"); + return; + } + + char *text = (char *)malloc((size_t)json_len + 1); + if (!text) + return; + memcpy(text, json_str, (size_t)json_len); + text[json_len] = '\0'; + + cJSON *root = cJSON_Parse(text); + if (!root) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] parse connect command: json parse failed"); + free(text); + return; + } + + cJSON *data = cJSON_GetObjectItem(root, "data"); + if (!data || !cJSON_IsObject(data)) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] connect command data missing"); + cJSON_Delete(root); + free(text); + return; + } + + /* 解析data字段 */ + memset(&g_bluetooth_connect_data, 0, sizeof(g_bluetooth_connect_data)); + + cJSON *userId = cJSON_GetObjectItem(data, "userId"); + if (userId && cJSON_IsString(userId) && userId->valuestring) + { + strncpy(g_bluetooth_connect_data.user_id, userId->valuestring, + sizeof(g_bluetooth_connect_data.user_id) - 1); + g_bluetooth_connect_data.user_id[sizeof(g_bluetooth_connect_data.user_id) - 1] = '\0'; + } + + cJSON *bluetoothAddress = cJSON_GetObjectItem(data, "bluetoothAddress"); + if (bluetoothAddress && cJSON_IsString(bluetoothAddress) && bluetoothAddress->valuestring) + { + strncpy(g_bluetooth_connect_data.bluetooth_address, bluetoothAddress->valuestring, + sizeof(g_bluetooth_connect_data.bluetooth_address) - 1); + g_bluetooth_connect_data.bluetooth_address[sizeof(g_bluetooth_connect_data.bluetooth_address) - 1] = '\0'; + } + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] BluetoothConnect - userId: %s, bluetoothAddress: %s", + g_bluetooth_connect_data.user_id, g_bluetooth_connect_data.bluetooth_address); + + cJSON_Delete(root); + free(text); +} + +/* 解析蓝牙解绑命令 BluetoothUnbind */ +void ln_parse_bluetooth_unbind(const char *json_str, int json_len) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 解析蓝牙解绑命令"); + if (!json_str || json_len <= 0) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] parse unbind command: invalid json"); + return; + } + + char *text = (char *)malloc((size_t)json_len + 1); + if (!text) + return; + memcpy(text, json_str, (size_t)json_len); + text[json_len] = '\0'; + + cJSON *root = cJSON_Parse(text); + if (!root) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] parse unbind command: json parse failed"); + free(text); + return; + } + + cJSON *data = cJSON_GetObjectItem(root, "data"); + if (!data || !cJSON_IsObject(data)) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] unbind command data missing"); + cJSON_Delete(root); + free(text); + return; + } + + /* 解析data字段 */ + memset(&g_bluetooth_unbind_data, 0, sizeof(g_bluetooth_unbind_data)); + + cJSON *userId = cJSON_GetObjectItem(data, "userId"); + if (userId && cJSON_IsString(userId) && userId->valuestring) + { + strncpy(g_bluetooth_unbind_data.user_id, userId->valuestring, + sizeof(g_bluetooth_unbind_data.user_id) - 1); + g_bluetooth_unbind_data.user_id[sizeof(g_bluetooth_unbind_data.user_id) - 1] = '\0'; + } + + cJSON *bluetoothAddress = cJSON_GetObjectItem(data, "bluetoothAddress"); + if (bluetoothAddress && cJSON_IsString(bluetoothAddress) && bluetoothAddress->valuestring) + { + strncpy(g_bluetooth_unbind_data.bluetooth_address, bluetoothAddress->valuestring, + sizeof(g_bluetooth_unbind_data.bluetooth_address) - 1); + g_bluetooth_unbind_data.bluetooth_address[sizeof(g_bluetooth_unbind_data.bluetooth_address) - 1] = '\0'; + } + + cJSON *bluetoothName = cJSON_GetObjectItem(data, "bluetoothName"); + if (bluetoothName && cJSON_IsString(bluetoothName) && bluetoothName->valuestring) + { + strncpy(g_bluetooth_unbind_data.bluetooth_name, bluetoothName->valuestring, + sizeof(g_bluetooth_unbind_data.bluetooth_name) - 1); + g_bluetooth_unbind_data.bluetooth_name[sizeof(g_bluetooth_unbind_data.bluetooth_name) - 1] = '\0'; + } + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] BluetoothUnbind - userId: %s, bluetoothAddress: %s, bluetoothName: %s", + g_bluetooth_unbind_data.user_id, g_bluetooth_unbind_data.bluetooth_address, + g_bluetooth_unbind_data.bluetooth_name); + + cJSON_Delete(root); + free(text); +} + +/* 获取蓝牙连接命令数据 */ +const ln_bluetooth_connect_data_t *ln_get_bluetooth_connect_data(void) +{ + return &g_bluetooth_connect_data; +} + +/* 获取蓝牙解绑命令数据 */ +const ln_bluetooth_unbind_data_t *ln_get_bluetooth_unbind_data(void) +{ + return &g_bluetooth_unbind_data; +} -- 2.17.1