添加声纹锁协议,暂未联调
authorluozheng <1732036298@qq.com>
Wed, 3 Dec 2025 08:16:47 +0000 (16:16 +0800)
committerluozheng <1732036298@qq.com>
Wed, 3 Dec 2025 08:16:47 +0000 (16:16 +0800)
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp
code/sdk/zhihui/leiniao/imsl_ln/ln_api.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api.h
code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c

index 028a445..6686451 100644 (file)
@@ -1039,6 +1039,12 @@ namespace OHOS
                 // 条件满足,进入对话模式
                 ThunderBirdModel::GetInstance()->LowFrequence();//减低视频帧率
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "进入对话模式");
+
+                #if LN_VOICE_CHAT_ENABLED
+                //发送开始对话流标志
+                do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_CHAT_SESSION_START, NULL, 0);
+                #endif
+
                 
                 // 音频已初始化,直接跳转界面
                 ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING);
@@ -1086,7 +1092,12 @@ namespace OHOS
             else if(currentView == THUNDERBIRD_DIALOGUEVIEW)
             {
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "退出对话模式,当前子状态: %d", currentSubView);
-              
+
+                #if LN_VOICE_CHAT_ENABLED
+                //发送结束对话流标志
+                do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_CHAT_SESSION_END, NULL, 0);
+                #endif
+                
                 // 先停止定时器,避免在退出过程中继续触发
                 if(currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING)
                 {
index 145e2b3..8756f64 100644 (file)
@@ -984,6 +984,61 @@ void ln_ws_process_message(const ws_data_msg_t *data_msg, ws_command_t type)
         // }
         break;
     }
+    case WS_CMD_CHAT_SESSION_START_ACK:
+    {
+        printf("[WS] ChatSessionStartAck:对话会话开始应答\n");
+        #if 1
+        if (json_str)
+        {
+            cJSON *root = cJSON_Parse(json_str);
+            if (root)
+            {
+                cJSON *data_obj = cJSON_GetObjectItem(root, "data");
+                if (data_obj && cJSON_IsObject(data_obj))
+                {
+                    cJSON *session_id = cJSON_GetObjectItem(data_obj, "sessionId");
+                    cJSON *chat_id = cJSON_GetObjectItem(data_obj, "chatId");
+                    if (session_id && cJSON_IsString(session_id) && session_id->valuestring)
+                    {
+                        // 保存sessionId到全局上下文(需要在ln_api_websocket.c中实现保存函数)
+                        ln_ws_set_session_id(session_id->valuestring);
+                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[WS] ChatSessionStartAck: sessionId=%s, chatId=%s",
+                            session_id->valuestring,
+                            (chat_id && cJSON_IsString(chat_id)) ? chat_id->valuestring : "");
+                    }
+                }
+                cJSON_Delete(root);
+            }
+        }
+        #endif
+        break;
+    }
+    case WS_CMD_CHAT_SESSION_END_ACK:
+    {
+        printf("[WS] ChatSessionEndAck:对话会话结束应答\n");
+        #if 1
+        if (json_str)
+        {
+            cJSON *root = cJSON_Parse(json_str);
+            if (root)
+            {
+                cJSON *data_obj = cJSON_GetObjectItem(root, "data");
+                if (data_obj && cJSON_IsObject(data_obj))
+                {
+                    cJSON *session_id = cJSON_GetObjectItem(data_obj, "sessionId");
+                    cJSON *chat_id = cJSON_GetObjectItem(data_obj, "chatId");
+                    // 清空sessionId(需要在ln_api_websocket.c中实现清空函数)
+                    ln_ws_clear_session_id();
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[WS] ChatSessionEndAck: sessionId=%s, chatId=%s",
+                        (session_id && cJSON_IsString(session_id)) ? session_id->valuestring : "",
+                        (chat_id && cJSON_IsString(chat_id)) ? chat_id->valuestring : "");
+                }
+                cJSON_Delete(root);
+            }
+        }
+        #endif
+        break;
+    }
     case WS_CMD_PING:
     {
         printf("[WS] Ping\n");
@@ -1211,6 +1266,16 @@ static void ln_http_server_send_task(void const *arg)
                 }
             }
         }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_CHAT_SESSION_START)
+        {
+            printf("LN_HTTP_SERVICE_CMD_CHAT_SESSION_START:语音对话流开始\n");
+            ln_ws_send_chat_session_start();
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_CHAT_SESSION_END)
+        {
+            printf("LN_HTTP_SERVICE_CMD_CHAT_SESSION_END:语音对话流结束\n");
+            ln_ws_send_chat_session_end();
+        }
         if (mail.data != NULL)
         {
             printf("free(mail.data)\n");
index 29322fe..48faaaf 100644 (file)
@@ -26,6 +26,7 @@ typedef struct
 } ln_http_data_mail_t;
 
 /* ============================== 公共宏与URL路径 ============================== */
+#define LN_VOICE_CHAT_ENABLED 0  //声纹锁开启宏
 #define LN_ENV_PRODUCTION 0  //正式环境
 /* 接口基础配置 - 如需切换环境/密钥,在此调整 */
 #if LN_ENV_PRODUCTION
@@ -138,6 +139,10 @@ typedef struct
 //蓝牙状态上报相关命令
 #define LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT 0x1015 /* 蓝牙状态上报 */
 
+/* 语音对话流相关命令 */
+#define LN_HTTP_SERVICE_CMD_CHAT_SESSION_START 0x1016 /* 语音对话流开始 */
+#define LN_HTTP_SERVICE_CMD_CHAT_SESSION_END 0x1017 /* 语音对话流结束 */
+
 /* 下载文件相关结构体 */
 typedef struct
 {
@@ -450,6 +455,8 @@ typedef enum {
     WS_CMD_VAD_INITIALIZED,          /* VAD 服务器初始化完成 */
     WS_CMD_DEVICE_UPGRADE,           /* 设备升级(DeviceUpgrade) */
     WS_CMD_DEVICE_UPGRADE_STATUS_REPORT_ACK, /* 设备升级状态上报应答(DeviceUpgradeStatusReportAck) */
+    WS_CMD_CHAT_SESSION_START_ACK,   /* 对话会话开始应答(ChatSessionStartAck) */
+    WS_CMD_CHAT_SESSION_END_ACK,     /* 对话会话结束应答(ChatSessionEndAck) */
     WS_CMD_BLUETOOTH_CONNECT,        /* 蓝牙连接(BluetoothConnect) */
     WS_CMD_BLUETOOTH_UNBIND,         /* 蓝牙解绑(BluetoothUnbind) */
     WS_CMD_BLUETOOTH_STATUS_REPORT_ACK, /* 蓝牙状态上报应答(BluetoothStatusReportAck) */
@@ -497,6 +504,10 @@ int ln_ws_end_audio_chat(void);
 int ln_ws_send_voice_chat_interrupt(const char *reason);
 int ln_ws_send_sleep_mode_inquire(const char *intention);
 const char* ln_ws_get_current_chat_id(void);
+void ln_ws_send_chat_session_start(void);
+void ln_ws_send_chat_session_end(void);
+void ln_ws_set_session_id(const char *session_id);
+void ln_ws_clear_session_id(void);
 int ln_ws_stop(void);
 // int ln_ws_force_reconnect(void);
 int ln_ws_enter_sleep(void);
index 83fbc2c..dc20834 100644 (file)
@@ -173,6 +173,8 @@ static bool g_audio_chat_ending = false;
 // 录音上传状态跟踪
 static bool g_recording_upload_started = false;
 
+static char g_session_id[64] = {0}; // 会话ID,由服务端生成
+
 // 音频数据缓存结构
 typedef struct {
     uint8_t *data;          // 音频数据
@@ -657,6 +659,9 @@ int ln_ws_send_audio_data(const uint8_t *audio_data, uint32_t audio_size, bool f
     
     cJSON_AddStringToObject(data_obj, "audioBase64", audio_base64);
     cJSON_AddStringToObject(data_obj, "chatId", g_audio_chat_ctx.chat_id);
+    #if LN_VOICE_CHAT_ENABLED
+    cJSON_AddStringToObject(data_obj, "sessionId", g_session_id);
+    #endif
     cJSON_AddBoolToObject(data_obj, "finished", finished);
     
     cJSON_AddItemToObject(json, "data", data_obj);
@@ -777,6 +782,117 @@ const char* ln_ws_get_current_chat_id(void)
     return g_audio_chat_ctx.is_active ? g_audio_chat_ctx.chat_id : NULL;
 }
 
+/**
+ * @brief 设置会话ID(由服务端返回)
+ * @param session_id 会话ID字符串
+ */
+void ln_ws_set_session_id(const char *session_id)
+{
+    if (session_id && strlen(session_id) < sizeof(g_session_id)) {
+        strncpy(g_session_id, session_id, sizeof(g_session_id) - 1);
+        g_session_id[sizeof(g_session_id) - 1] = '\0';
+        LN_WS_DEBUG("Session ID set: %s\n", g_session_id);
+    } else {
+        LN_WS_ERROR("Invalid session ID: %s\n", session_id ? session_id : "NULL");
+    }
+}
+
+/**
+ * @brief 清空会话ID并重置会话状态
+ */
+void ln_ws_clear_session_id(void)
+{
+    memset(g_session_id, 0, sizeof(g_session_id));
+    // 同时重置会话的活跃状态,确保会话完整结束
+    g_audio_chat_ctx.is_active = false;
+    g_audio_chat_ctx.finish_state = LN_CHAT_RECEIVED_END;
+    // 重置对话ID匹配标志
+    reset_chat_id_match();
+    LN_WS_DEBUG("Session ID cleared and chat context reset\n");
+}
+
+void ln_ws_send_chat_session_start(void)
+{
+    // 发送ChatSessionStart请求
+    if (g_ws_connected == WS_STATE_CONNECTED || g_session_id[0] == '\0') 
+    {
+        uint32_t timestamp;
+        uapi_get_timestampe_ss(&timestamp);
+        
+        char message_id[128];
+        generate_chat_id(g_audio_chat_ctx.chat_id, sizeof(g_audio_chat_ctx.chat_id));
+        generate_message_id(message_id, sizeof(message_id), g_audio_chat_ctx.chat_id, 0);
+        
+        cJSON *json = cJSON_CreateObject();
+        if (json) {
+            cJSON_AddStringToObject(json, "deviceId", uapi_ln_get_device_id());
+            cJSON_AddNumberToObject(json, "timestamp", (double)timestamp);
+            cJSON_AddStringToObject(json, "messageId", message_id);
+            cJSON_AddStringToObject(json, "command", "ChatSessionStart");
+            
+            cJSON *data = cJSON_CreateObject();
+            if (data) {
+                cJSON_AddStringToObject(data, "chatId", g_audio_chat_ctx.chat_id);
+                cJSON_AddItemToObject(json, "data", data);
+            }
+            
+            char *json_string = cJSON_Print(json);
+            if (json_string) {
+                uapi_ws_send_text(json_string);
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Sent ChatSessionStart: %s\n", json_string);
+                cJSON_free(json_string);
+            }
+            cJSON_Delete(json);
+        }
+    }
+    return;
+}
+
+void ln_ws_send_chat_session_end(void)
+{
+    // 发送ChatSessionEnd请求
+    if (g_session_id[0] != '\0') 
+    {
+        if(g_ws_connected == WS_STATE_CONNECTED)
+        {
+            uint32_t timestamp;
+            uapi_get_timestampe_ss(&timestamp);
+            
+            char message_id[128];
+            generate_chat_id(g_audio_chat_ctx.chat_id, sizeof(g_audio_chat_ctx.chat_id));
+            generate_message_id(message_id, sizeof(message_id), g_audio_chat_ctx.chat_id, g_audio_chat_ctx.message_counter + 1);
+            
+            cJSON *json = cJSON_CreateObject();
+            if (json) {
+                cJSON_AddStringToObject(json, "deviceId", uapi_ln_get_device_id());
+                cJSON_AddNumberToObject(json, "timestamp", (double)timestamp);
+                cJSON_AddStringToObject(json, "messageId", message_id);
+                cJSON_AddStringToObject(json, "command", "ChatSessionEnd");
+                
+                cJSON *data = cJSON_CreateObject();
+                if (data) {
+                    cJSON_AddStringToObject(data, "sessionId", g_session_id);
+                    cJSON_AddStringToObject(data, "chatId", g_audio_chat_ctx.chat_id);
+                    cJSON_AddItemToObject(json, "data", data);
+                }
+                
+                char *json_string = cJSON_Print(json);
+                if (json_string) {
+                    uapi_ws_send_text(json_string);
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Sent ChatSessionEnd: %s\n", json_string);
+                    cJSON_free(json_string);
+                }
+                cJSON_Delete(json);
+            }
+        }
+        else
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ChatSessionEnd: Invalid session ID or chat ID\n");
+        }
+    }
+    return;
+}
+
 static void AIVoiceDataCallback_ln(const uint8_t* data, uint32_t size, void* userData)
 {
     (void)userData;
@@ -1764,6 +1880,10 @@ static ws_command_t ln_ws_parse_command_string(const char *command_str)
         return WS_CMD_DEVICE_UPGRADE;
     } else if (strcmp(command_str, "DeviceUpgradeStatusReportAck") == 0) {
         return WS_CMD_DEVICE_UPGRADE_STATUS_REPORT_ACK;
+    } else if (strcmp(command_str, "ChatSessionStartAck") == 0) {
+        return WS_CMD_CHAT_SESSION_START_ACK;
+    } else if (strcmp(command_str, "ChatSessionEndAck") == 0) {
+        return WS_CMD_CHAT_SESSION_END_ACK;
     } else if (strcmp(command_str, "BluetoothConnect") == 0) {
         return WS_CMD_BLUETOOTH_CONNECT;
     } else if (strcmp(command_str, "BluetoothUnbind") == 0) {