#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
{
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 发送接口 ========== */
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,
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;
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
--- /dev/null
+#include "ln_api.h"
+#include "cJSON.h"
+#include "custom_utils.h"
+#include <string.h>
+
+/* 蓝牙状态枚举值常量 */
+#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;
+}