fileschecksum.txt
file.bin
file_tmp.bin
+code/sdk/zhihui/ai/build/
${CMAKE_CURRENT_SOURCE_DIR}/src/ai_connection_manager.c
${CMAKE_CURRENT_SOURCE_DIR}/src/ai_memory_pool.c
${CMAKE_CURRENT_SOURCE_DIR}/src/ai_services.c
+${CMAKE_CURRENT_SOURCE_DIR}/src/ai_asr_service.c
+${CMAKE_CURRENT_SOURCE_DIR}/src/ai_chat_service.c
+${CMAKE_CURRENT_SOURCE_DIR}/src/ai_tts_service.c
${CMAKE_CURRENT_SOURCE_DIR}/example/ai_at_cmd.c
-${CMAKE_CURRENT_SOURCE_DIR}/example/ai_demo.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/example/ai_demo.c
)
set(SOURCES
# 源文件
SOURCES = $(SRC_DIR)/ai_connection_manager.c \
$(SRC_DIR)/ai_memory_pool.c \
- $(SRC_DIR)/ai_services.c
+ $(SRC_DIR)/ai_services.c \
+ $(SRC_DIR)/ai_asr_service.c \
+ $(SRC_DIR)/ai_chat_service.c \
+ $(SRC_DIR)/ai_tts_service.c
# 示例文件
EXAMPLE_SOURCES = $(EXAMPLE_DIR)/ai_demo.c \
#define AI_AT_FAILED (-1)
/* 测试配置常量 */
+#if 0
#define AI_AT_DEMO_ASR_URL "ws://amp.raisound.com/asr/ws"
#define AI_AT_DEMO_CHAT_URL "ws://amp.raisound.com/chat/ws"
#define AI_AT_DEMO_TTS_URL "ws://amp.raisound.com/tts/ws"
+#else
+#define AI_AT_DEMO_ASR_URL "ws://192.168.1.100:8080/asr/ws"
+#define AI_AT_DEMO_CHAT_URL "ws://192.168.1.100:8080/chat/ws"
+#define AI_AT_DEMO_TTS_URL "ws://192.168.1.100:8080/tts/ws"
+#endif
#define AI_AT_DEMO_AUDIO_SIZE 1024
#define AI_AT_DEMO_CHAT_MESSAGE "你好,我是AI助手AT命令测试程序"
#define AI_AT_DEMO_TTS_TEXT "欢迎使用AI语音服务AT命令测试"
}
// 4. 设置回调函数
- g_ai_services_context.asr_result_cb = ai_asr_result_callback;
- g_ai_services_context.chat_response_cb = ai_chat_response_callback;
- g_ai_services_context.tts_result_cb = ai_tts_result_callback;
+ ai_asr_set_callbacks(&g_ai_services_context, ai_asr_result_callback, NULL, NULL, NULL);
+ ai_chat_set_callbacks(&g_ai_services_context, ai_chat_response_callback, NULL, NULL, NULL);
+ ai_tts_set_callbacks(&g_ai_services_context, ai_tts_result_callback, NULL, NULL, NULL);
g_ai_at_initialized = true;
printf("[AI_AT] AI服务初始化成功\n");
printf("[AI_AT] 执行 AT^AICONNECT - 连接AI服务\n");
+ printf("[AI_AT] [DEBUG] Checking initialization status...\n");
if (!g_ai_at_initialized) {
printf("[AI_AT] AI服务未初始化,请先执行 AT^AIINIT\n");
return ERRCODE_FAIL;
}
+ printf("[AI_AT] [DEBUG] Initialization check passed\n");
+
+ /* 启动连接管理器,恢复正常WebSocket连接 */
+ printf("[AI_AT] 启动AI服务连接管理器...\n");
+ printf("[AI_AT] [DEBUG] About to call ai_connection_manager_start_all()...\n");
ai_error_t ret = ai_connection_manager_start_all();
+ printf("[AI_AT] [DEBUG] ai_connection_manager_start_all() returned: %d\n", ret);
if (ret == AI_OK) {
- printf("[AI_AT] 所有AI服务连接启动成功\n");
+ printf("[AI_AT] 连接管理器启动成功\n");
+ printf("[AI_AT] 状态:所有AI服务连接线程已启动\n");
+ printf("[AI_AT] WebSocket连接功能已恢复正常\n");
return ERRCODE_SUCC;
} else {
- printf("[AI_AT] AI服务连接启动失败: %d\n", ret);
+ printf("[AI_AT] 连接管理器启动失败: %d\n", ret);
return ERRCODE_FAIL;
}
}
/* ================================ 演示配置 ================================ */
+#if 0
#define DEMO_ASR_URL "ws://amp.raisound.com/asr/ws"
#define DEMO_CHAT_URL "ws://amp.raisound.com/chat/ws"
#define DEMO_TTS_URL "ws://amp.raisound.com/tts/ws"
+#else
+#define DEMO_ASR_URL "ws://192.168.1.100:8080/asr/ws"
+#define DEMO_CHAT_URL "ws://192.168.1.100:8080/chat/ws"
+#define DEMO_TTS_URL "ws://192.168.1.100:8080/tts/ws"
+#endif
#define DEMO_AUDIO_DATA_SIZE 1024 // 演示音频数据大小
#define DEMO_CHAT_MESSAGE "你好,我是AI助手演示程序"
--- /dev/null
+/**
+ * @file ai_asr_service.h
+ * @brief AI语音识别(ASR)服务接口定义
+ * @version 2.0
+ * @date 2024-01-20
+ */
+
+#ifndef AI_ASR_SERVICE_H
+#define AI_ASR_SERVICE_H
+
+#include "ai_core_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ================================ ASR服务类型定义 ================================ */
+
+/**
+ * @brief ASR状态枚举
+ */
+typedef enum {
+ ASR_STATE_IDLE = 0, // 空闲状态
+ ASR_STATE_LISTENING, // 监听状态
+ ASR_STATE_RECOGNIZING, // 识别中
+ ASR_STATE_COMPLETED, // 识别完成
+ ASR_STATE_ERROR // 错误状态
+} asr_state_t;
+
+/**
+ * @brief ASR配置结构体
+ */
+typedef struct {
+ char language[16]; // 语言代码,如"zh-CN"
+ bool enable_vad; // 是否启用语音活动检测
+ bool enable_punctuation; // 是否启用标点符号
+ bool enable_partial_results; // 是否启用部分结果
+ uint32_t silence_timeout_ms; // 静音超时时间(毫秒)
+ uint32_t max_duration_ms; // 最大录音时长(毫秒)
+} asr_config_t;
+
+/**
+ * @brief ASR识别结果结构体
+ */
+typedef struct {
+ char text[256]; // 识别文本
+ float confidence; // 置信度(0.0-1.0)
+ bool is_final; // 是否为最终结果
+ uint32_t start_time_ms; // 开始时间(毫秒)
+ uint32_t end_time_ms; // 结束时间(毫秒)
+ char session_id[32]; // 会话ID
+} asr_result_t;
+
+/**
+ * @brief ASR服务上下文结构体
+ */
+typedef struct {
+ asr_state_t state; // 当前状态
+ asr_config_t config; // 配置信息
+ char current_session_id[32]; // 当前会话ID
+ uint32_t last_activity_time; // 最后活动时间
+
+ /* 回调函数 */
+ asr_result_callback_t result_cb;
+ asr_error_callback_t error_cb;
+ asr_state_callback_t state_cb;
+ void *user_data;
+} asr_service_context_t;
+
+/* ================================ ASR服务接口 ================================ */
+
+/**
+ * @brief 初始化ASR服务
+ * @param context ASR服务上下文
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_init(asr_service_context_t *context);
+
+/**
+ * @brief 销毁ASR服务
+ * @param context ASR服务上下文
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_destroy(asr_service_context_t *context);
+
+/**
+ * @brief 配置ASR服务
+ * @param context ASR服务上下文
+ * @param config ASR配置
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_configure(asr_service_context_t *context, const asr_config_t *config);
+
+/**
+ * @brief 设置ASR回调函数
+ * @param context ASR服务上下文
+ * @param result_cb 结果回调
+ * @param error_cb 错误回调
+ * @param state_cb 状态回调
+ * @param user_data 用户数据
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_set_callbacks(asr_service_context_t *context,
+ asr_result_callback_t result_cb,
+ asr_error_callback_t error_cb,
+ asr_state_callback_t state_cb,
+ void *user_data);
+
+/**
+ * @brief 启动ASR识别
+ * @param context ASR服务上下文
+ * @param session_id 会话ID(可选,为NULL时使用默认)
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_start(asr_service_context_t *context, const char *session_id);
+
+/**
+ * @brief 发送音频数据
+ * @param context ASR服务上下文
+ * @param audio_data 音频数据
+ * @param data_size 数据大小
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_send_audio(asr_service_context_t *context, const uint8_t *audio_data, uint32_t data_size);
+
+/**
+ * @brief 停止ASR识别
+ * @param context ASR服务上下文
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_stop(asr_service_context_t *context);
+
+/**
+ * @brief 获取ASR状态
+ * @param context ASR服务上下文
+ * @return asr_state_t ASR状态
+ */
+asr_state_t ai_asr_service_get_state(asr_service_context_t *context);
+
+/**
+ * @brief 获取ASR状态名称
+ * @param state ASR状态
+ * @return const char* 状态名称
+ */
+const char* ai_asr_service_get_state_name(asr_state_t state);
+
+/**
+ * @brief 创建默认ASR配置
+ * @param config ASR配置结构体
+ */
+void ai_asr_service_create_default_config(asr_config_t *config);
+
+/**
+ * @brief 处理ASR服务响应
+ * @param context ASR服务上下文
+ * @param json_data JSON响应数据
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_handle_response(asr_service_context_t *context, const char *json_data);
+
+/**
+ * @brief 构建ASR启动消息
+ * @param session_id 会话ID
+ * @param config ASR配置
+ * @param json_buffer JSON缓冲区
+ * @param buffer_size 缓冲区大小
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_build_start_message(const char *session_id, const asr_config_t *config,
+ char *json_buffer, size_t buffer_size);
+
+/**
+ * @brief 构建ASR停止消息
+ * @param session_id 会话ID
+ * @param json_buffer JSON缓冲区
+ * @param buffer_size 缓冲区大小
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_asr_service_build_stop_message(const char *session_id, char *json_buffer, size_t buffer_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AI_ASR_SERVICE_H */
\ No newline at end of file
--- /dev/null
+/**
+ * @file ai_chat_service.h
+ * @brief AI对话(Chat)服务接口定义
+ * @version 2.0
+ * @date 2024-01-20
+ */
+
+#ifndef AI_CHAT_SERVICE_H
+#define AI_CHAT_SERVICE_H
+
+#include "ai_core_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ================================ Chat服务类型定义 ================================ */
+
+/**
+ * @brief Chat状态枚举
+ */
+typedef enum {
+ CHAT_STATE_IDLE = 0, // 空闲状态
+ CHAT_STATE_SENDING, // 发送中
+ CHAT_STATE_WAITING, // 等待响应
+ CHAT_STATE_RECEIVING, // 接收中
+ CHAT_STATE_COMPLETED, // 完成
+ CHAT_STATE_ERROR // 错误状态
+} chat_state_t;
+
+/**
+ * @brief Chat配置结构体
+ */
+typedef struct {
+ char model_name[32]; // 模型名称,如"qwen-plus"
+ float temperature; // 温度参数(0.0-2.0)
+ uint16_t max_tokens; // 最大令牌数
+ float top_p; // Top-p参数
+ bool stream; // 是否流式输出
+ uint32_t timeout_ms; // 超时时间(毫秒)
+} chat_config_t;
+
+/**
+ * @brief Chat消息结构体
+ */
+typedef struct {
+ char role[16]; // 角色:user/assistant/system
+ char content[512]; // 消息内容
+ char message_id[32]; // 消息ID
+ char session_id[32]; // 会话ID
+ uint32_t timestamp; // 时间戳
+ bool is_final; // 是否为最终消息
+} chat_message_t;
+
+/**
+ * @brief Chat服务上下文结构体
+ */
+typedef struct {
+ chat_state_t state; // 当前状态
+ chat_config_t config; // 配置信息
+ char current_session_id[32]; // 当前会话ID
+ uint32_t last_activity_time; // 最后活动时间
+
+ /* 回调函数 */
+ chat_response_callback_t response_cb;
+ chat_error_callback_t error_cb;
+ chat_state_callback_t state_cb;
+ void *user_data;
+} chat_service_context_t;
+
+/* ================================ Chat服务接口 ================================ */
+
+/**
+ * @brief 初始化Chat服务
+ * @param context Chat服务上下文
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_chat_service_init(chat_service_context_t *context);
+
+/**
+ * @brief 销毁Chat服务
+ * @param context Chat服务上下文
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_chat_service_destroy(chat_service_context_t *context);
+
+/**
+ * @brief 配置Chat服务
+ * @param context Chat服务上下文
+ * @param config Chat配置
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_chat_service_configure(chat_service_context_t *context, const chat_config_t *config);
+
+/**
+ * @brief 设置Chat回调函数
+ * @param context Chat服务上下文
+ * @param response_cb 响应回调
+ * @param error_cb 错误回调
+ * @param state_cb 状态回调
+ * @param user_data 用户数据
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_chat_service_set_callbacks(chat_service_context_t *context,
+ chat_response_callback_t response_cb,
+ chat_error_callback_t error_cb,
+ chat_state_callback_t state_cb,
+ void *user_data);
+
+/**
+ * @brief 发送Chat消息
+ * @param context Chat服务上下文
+ * @param message 消息内容
+ * @param session_id 会话ID(可选,为NULL时使用默认)
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_chat_service_send_message(chat_service_context_t *context, const char *message, const char *session_id);
+
+/**
+ * @brief 获取Chat状态
+ * @param context Chat服务上下文
+ * @return chat_state_t Chat状态
+ */
+chat_state_t ai_chat_service_get_state(chat_service_context_t *context);
+
+/**
+ * @brief 获取Chat状态名称
+ * @param state Chat状态
+ * @return const char* 状态名称
+ */
+const char* ai_chat_service_get_state_name(chat_state_t state);
+
+/**
+ * @brief 创建默认Chat配置
+ * @param config Chat配置结构体
+ */
+void ai_chat_service_create_default_config(chat_config_t *config);
+
+/**
+ * @brief 处理Chat服务响应
+ * @param context Chat服务上下文
+ * @param json_data JSON响应数据
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_chat_service_handle_response(chat_service_context_t *context, const char *json_data);
+
+/**
+ * @brief 构建Chat消息
+ * @param message 消息内容
+ * @param session_id 会话ID
+ * @param config Chat配置
+ * @param json_buffer JSON缓冲区
+ * @param buffer_size 缓冲区大小
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_chat_service_build_message(const char *message, const char *session_id, const chat_config_t *config,
+ char *json_buffer, size_t buffer_size);
+
+/**
+ * @brief 生成消息ID
+ * @param message_id 消息ID缓冲区
+ * @param buffer_size 缓冲区大小
+ */
+void ai_chat_service_generate_message_id(char *message_id, size_t buffer_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AI_CHAT_SERVICE_H */
\ No newline at end of file
/* 事件回调函数类型 */
typedef void (*ai_event_callback_t)(const ai_event_t *event, void *user_data);
+/* ================================ 服务回调函数类型 ================================ */
+
+/* 前向声明 */
+struct asr_result;
+struct chat_message;
+struct tts_result;
+
+/* ASR回调函数类型 */
+typedef void (*asr_result_callback_t)(const struct asr_result *result, void *user_data);
+typedef void (*asr_error_callback_t)(int error_code, const char *error_msg, void *user_data);
+typedef void (*asr_state_callback_t)(int old_state, int new_state, void *user_data);
+
+/* Chat回调函数类型 */
+typedef void (*chat_response_callback_t)(const struct chat_message *message, void *user_data);
+typedef void (*chat_error_callback_t)(int error_code, const char *error_msg, void *user_data);
+typedef void (*chat_state_callback_t)(int old_state, int new_state, void *user_data);
+
+/* TTS回调函数类型 */
+typedef void (*tts_result_callback_t)(const struct tts_result *result, void *user_data);
+typedef void (*tts_error_callback_t)(int error_code, const char *error_msg, void *user_data);
+typedef void (*tts_state_callback_t)(int old_state, int new_state, void *user_data);
+
/* ================================ 系统兼容性定义 ================================ */
#ifdef __TEST_MODE__
#endif
#include "ai_core_types.h"
+#include "ai_asr_service.h"
+#include "ai_chat_service.h"
+#include "ai_tts_service.h"
-/* ================================ ASR服务定义 ================================ */
+/* ================================ 统一服务管理定义 ================================ */
-typedef enum {
- ASR_STATE_IDLE = 0, // 空闲状态
- ASR_STATE_LISTENING, // 监听中
- ASR_STATE_RECOGNIZING, // 识别中
- ASR_STATE_COMPLETED, // 识别完成
- ASR_STATE_ERROR // 错误状态
-} asr_state_t;
+/* 注意:ASR、Chat、TTS的具体类型定义现在在各自的独立头文件中 */
-typedef struct {
- char session_id[AI_MAX_SESSION_ID_LENGTH]; // 会话ID
- char text[AI_MAX_TEXT_LENGTH]; // 识别文本
- float confidence; // 置信度 (0.0-1.0)
- bool is_final; // 是否最终结果
- bool is_partial; // 是否部分结果
- uint32_t start_time_ms; // 开始时间
- uint32_t end_time_ms; // 结束时间
- uint32_t duration_ms; // 持续时间
-} asr_result_t;
-
-typedef struct {
- bool enable_vad; // 启用语音活动检测
- bool enable_punctuation; // 启用标点符号
- bool enable_partial_results; // 启用部分结果
- uint16_t silence_timeout_ms; // 静音超时时间
- uint16_t max_duration_ms; // 最大录音时长
- char language[8]; // 语言代码 "zh-CN"
-} asr_config_t;
-
-/* ASR回调函数类型 */
-typedef void (*asr_result_callback_t)(const asr_result_t *result, void *user_data);
-typedef void (*asr_error_callback_t)(int error_code, const char *error_msg, void *user_data);
-typedef void (*asr_state_callback_t)(asr_state_t old_state, asr_state_t new_state, void *user_data);
-
-/* ================================ Chat服务定义 ================================ */
-
-typedef enum {
- CHAT_STATE_IDLE = 0, // 空闲状态
- CHAT_STATE_SENDING, // 发送中
- CHAT_STATE_WAITING, // 等待响应
- CHAT_STATE_RECEIVING, // 接收中
- CHAT_STATE_COMPLETED, // 完成
- CHAT_STATE_ERROR // 错误状态
-} chat_state_t;
-
-typedef enum {
- CHAT_ROLE_USER = 0, // 用户角色
- CHAT_ROLE_ASSISTANT, // 助手角色
- CHAT_ROLE_SYSTEM // 系统角色
-} chat_role_t;
-
-typedef struct {
- char session_id[AI_MAX_SESSION_ID_LENGTH]; // 会话ID
- char message_id[32]; // 消息ID
- chat_role_t role; // 角色
- char content[AI_MAX_TEXT_LENGTH]; // 消息内容
- uint32_t timestamp; // 时间戳
- bool is_streaming; // 是否流式响应
- bool is_final; // 是否最终响应
-} chat_message_t;
-
-typedef struct {
- char model_name[32]; // 模型名称
- float temperature; // 温度参数 (0.0-2.0)
- uint16_t max_tokens; // 最大令牌数
- float top_p; // Top-p参数
- bool stream; // 流式输出
- uint16_t timeout_ms; // 超时时间
-} chat_config_t;
-
-/* Chat回调函数类型 */
-typedef void (*chat_response_callback_t)(const chat_message_t *message, void *user_data);
-typedef void (*chat_error_callback_t)(int error_code, const char *error_msg, void *user_data);
-typedef void (*chat_state_callback_t)(chat_state_t old_state, chat_state_t new_state, void *user_data);
-
-/* ================================ TTS服务定义 ================================ */
-
-typedef enum {
- TTS_STATE_IDLE = 0, // 空闲状态
- TTS_STATE_SYNTHESIZING, // 合成中
- TTS_STATE_PLAYING, // 播放中
- TTS_STATE_COMPLETED, // 完成
- TTS_STATE_ERROR // 错误状态
-} tts_state_t;
-
-typedef enum {
- TTS_VOICE_XIAOYUN = 0, // 小云
- TTS_VOICE_XIAOGANG, // 小刚
- TTS_VOICE_XIAOMEI, // 小美
- TTS_VOICE_XIAOLI, // 小丽
- TTS_VOICE_COUNT // 语音总数
-} tts_voice_type_t;
-typedef struct {
- char session_id[AI_MAX_SESSION_ID_LENGTH]; // 会话ID
- uint8_t *audio_data; // 音频数据
- uint32_t audio_size; // 音频大小
- uint32_t sample_rate; // 采样率
- uint8_t channels; // 声道数
- uint8_t bits_per_sample; // 位深度
- bool is_final; // 是否最终数据
- uint32_t sequence; // 序列号
-} tts_result_t;
-
-typedef struct {
- tts_voice_type_t voice_type; // 语音类型
- uint8_t volume; // 音量 (0-100)
- uint8_t speed; // 语速 (0-100, 50为正常)
- uint8_t pitch; // 音调 (0-100, 50为正常)
- bool auto_play; // 自动播放
- uint16_t timeout_ms; // 超时时间
-} tts_config_t;
-
-/* TTS回调函数类型 */
-typedef void (*tts_result_callback_t)(const tts_result_t *result, void *user_data);
-typedef void (*tts_error_callback_t)(int error_code, const char *error_msg, void *user_data);
-typedef void (*tts_state_callback_t)(tts_state_t old_state, tts_state_t new_state, void *user_data);
/* ================================ 服务上下文结构 ================================ */
typedef struct {
- ai_service_type_t service_type; // 服务类型
- asr_state_t asr_state; // ASR状态
- chat_state_t chat_state; // Chat状态
- tts_state_t tts_state; // TTS状态
-
- asr_config_t asr_config; // ASR配置
- chat_config_t chat_config; // Chat配置
- tts_config_t tts_config; // TTS配置
-
- /* ASR回调 */
- asr_result_callback_t asr_result_cb;
- asr_error_callback_t asr_error_cb;
- asr_state_callback_t asr_state_cb;
-
- /* Chat回调 */
- chat_response_callback_t chat_response_cb;
- chat_error_callback_t chat_error_cb;
- chat_state_callback_t chat_state_cb;
-
- /* TTS回调 */
- tts_result_callback_t tts_result_cb;
- tts_error_callback_t tts_error_cb;
- tts_state_callback_t tts_state_cb;
-
- void *user_data; // 用户数据
+ /* 独立服务上下文 */
+ asr_service_context_t asr_context; // ASR服务上下文
+ chat_service_context_t chat_context; // Chat服务上下文
+ tts_service_context_t tts_context; // TTS服务上下文
- /* 内部状态 */
+ /* 统一管理状态 */
char current_session_id[AI_MAX_SESSION_ID_LENGTH]; // 当前会话ID
uint32_t last_activity_time; // 最后活动时间
bool is_initialized; // 初始化标志
--- /dev/null
+/**
+ * @file ai_tts_service.h
+ * @brief AI语音合成(TTS)服务接口定义
+ * @version 2.0
+ * @date 2024-01-20
+ */
+
+#ifndef AI_TTS_SERVICE_H
+#define AI_TTS_SERVICE_H
+
+#include "ai_core_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ================================ TTS服务类型定义 ================================ */
+
+/**
+ * @brief TTS状态枚举
+ */
+typedef enum {
+ TTS_STATE_IDLE = 0, // 空闲状态
+ TTS_STATE_SYNTHESIZING, // 合成中
+ TTS_STATE_PLAYING, // 播放中
+ TTS_STATE_COMPLETED, // 完成
+ TTS_STATE_ERROR // 错误状态
+} tts_state_t;
+
+/**
+ * @brief TTS语音类型枚举
+ */
+typedef enum {
+ TTS_VOICE_XIAOYUN = 0, // 小云
+ TTS_VOICE_XIAOGANG, // 小刚
+ TTS_VOICE_XIAOMEI, // 小美
+ TTS_VOICE_XIAOLI, // 小丽
+ TTS_VOICE_COUNT // 语音类型数量
+} tts_voice_type_t;
+
+/**
+ * @brief TTS配置结构体
+ */
+typedef struct {
+ tts_voice_type_t voice_type; // 语音类型
+ uint8_t volume; // 音量(0-100)
+ uint8_t speed; // 语速(0-100)
+ uint8_t pitch; // 音调(0-100)
+ bool auto_play; // 是否自动播放
+ uint32_t timeout_ms; // 超时时间(毫秒)
+} tts_config_t;
+
+/**
+ * @brief TTS合成结果结构体
+ */
+typedef struct {
+ char text[256]; // 合成文本
+ uint8_t *audio_data; // 音频数据
+ uint32_t audio_size; // 音频大小
+ uint32_t sample_rate; // 采样率
+ uint16_t channels; // 声道数
+ uint16_t bits_per_sample; // 位深度
+ char session_id[32]; // 会话ID
+ uint32_t duration_ms; // 音频时长(毫秒)
+ bool is_final; // 是否为最终结果
+} tts_result_t;
+
+/**
+ * @brief TTS服务上下文结构体
+ */
+typedef struct {
+ tts_state_t state; // 当前状态
+ tts_config_t config; // 配置信息
+ char current_session_id[32]; // 当前会话ID
+ uint32_t last_activity_time; // 最后活动时间
+
+ /* 回调函数 */
+ tts_result_callback_t result_cb;
+ tts_error_callback_t error_cb;
+ tts_state_callback_t state_cb;
+ void *user_data;
+} tts_service_context_t;
+
+/* ================================ TTS服务接口 ================================ */
+
+/**
+ * @brief 初始化TTS服务
+ * @param context TTS服务上下文
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_tts_service_init(tts_service_context_t *context);
+
+/**
+ * @brief 销毁TTS服务
+ * @param context TTS服务上下文
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_tts_service_destroy(tts_service_context_t *context);
+
+/**
+ * @brief 配置TTS服务
+ * @param context TTS服务上下文
+ * @param config TTS配置
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_tts_service_configure(tts_service_context_t *context, const tts_config_t *config);
+
+/**
+ * @brief 设置TTS回调函数
+ * @param context TTS服务上下文
+ * @param result_cb 结果回调
+ * @param error_cb 错误回调
+ * @param state_cb 状态回调
+ * @param user_data 用户数据
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_tts_service_set_callbacks(tts_service_context_t *context,
+ tts_result_callback_t result_cb,
+ tts_error_callback_t error_cb,
+ tts_state_callback_t state_cb,
+ void *user_data);
+
+/**
+ * @brief 开始TTS合成
+ * @param context TTS服务上下文
+ * @param text 要合成的文本
+ * @param session_id 会话ID(可选,为NULL时使用默认)
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_tts_service_synthesize(tts_service_context_t *context, const char *text, const char *session_id);
+
+/**
+ * @brief 停止TTS合成
+ * @param context TTS服务上下文
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_tts_service_stop(tts_service_context_t *context);
+
+/**
+ * @brief 获取TTS状态
+ * @param context TTS服务上下文
+ * @return tts_state_t TTS状态
+ */
+tts_state_t ai_tts_service_get_state(tts_service_context_t *context);
+
+/**
+ * @brief 获取TTS状态名称
+ * @param state TTS状态
+ * @return const char* 状态名称
+ */
+const char* ai_tts_service_get_state_name(tts_state_t state);
+
+/**
+ * @brief 获取语音类型名称
+ * @param voice_type 语音类型
+ * @return const char* 语音名称
+ */
+const char* ai_tts_service_get_voice_name(tts_voice_type_t voice_type);
+
+/**
+ * @brief 创建默认TTS配置
+ * @param config TTS配置结构体
+ */
+void ai_tts_service_create_default_config(tts_config_t *config);
+
+/**
+ * @brief 处理TTS服务响应
+ * @param context TTS服务上下文
+ * @param json_data JSON响应数据
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_tts_service_handle_response(tts_service_context_t *context, const char *json_data);
+
+/**
+ * @brief 构建TTS请求
+ * @param text 要合成的文本
+ * @param session_id 会话ID
+ * @param config TTS配置
+ * @param json_buffer JSON缓冲区
+ * @param buffer_size 缓冲区大小
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_tts_service_build_request(const char *text, const char *session_id, const tts_config_t *config,
+ char *json_buffer, size_t buffer_size);
+
+/**
+ * @brief 构建TTS停止消息
+ * @param session_id 会话ID
+ * @param json_buffer JSON缓冲区
+ * @param buffer_size 缓冲区大小
+ * @return ai_error_t 错误码
+ */
+ai_error_t ai_tts_service_build_stop_message(const char *session_id, char *json_buffer, size_t buffer_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AI_TTS_SERVICE_H */
\ No newline at end of file
--- /dev/null
+/**
+ * @file ai_asr_service.c
+ * @brief AI语音识别(ASR)服务实现
+ * @version 2.0
+ * @date 2024-01-20
+ */
+
+#include "ai_asr_service.h"
+#include "ai_connection_manager.h"
+#include "ai_memory_pool.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#ifndef __TEST_MODE__
+#include "wearable_log.h"
+#include "dev_authentication.h"
+#define AI_LOG_TAG "AI_ASR"
+#define AI_LOGI(fmt, ...) WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "[%s] " fmt, AI_LOG_TAG, ##__VA_ARGS__)
+#define AI_LOGE(fmt, ...) WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[%s] " fmt, AI_LOG_TAG, ##__VA_ARGS__)
+#define AI_LOGW(fmt, ...) WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "[%s] " fmt, AI_LOG_TAG, ##__VA_ARGS__)
+#else
+#define AI_LOGI(fmt, ...) printf("[AI_ASR] " fmt "\n", ##__VA_ARGS__)
+#define AI_LOGE(fmt, ...) printf("[AI_ASR] ERROR: " fmt "\n", ##__VA_ARGS__)
+#define AI_LOGW(fmt, ...) printf("[AI_ASR] WARN: " fmt "\n", ##__VA_ARGS__)
+#endif
+
+/* ================================ 内部常量定义 ================================ */
+
+#define JSON_BUFFER_SIZE 512 // JSON缓冲区大小
+#define MAX_AUDIO_CHUNK_SIZE 1024 // 最大音频块大小
+
+/* ASR状态名称映射 */
+static const char* g_asr_state_names[] = {
+ "IDLE", "LISTENING", "RECOGNIZING", "COMPLETED", "ERROR"
+};
+
+/* ================================ 内部函数声明 ================================ */
+
+static uint32_t get_current_timestamp(void);
+static ai_error_t change_asr_state(asr_service_context_t *context, asr_state_t new_state);
+static ai_error_t parse_asr_response(const char *json_data, asr_result_t *result);
+
+/* ================================ 公共接口实现 ================================ */
+
+ai_error_t ai_asr_service_init(asr_service_context_t *context)
+{
+ if (context == NULL) {
+ AI_LOGE("Invalid context parameter");
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ AI_LOGI("Initializing ASR service...");
+
+ /* 初始化上下文 */
+ memset(context, 0, sizeof(asr_service_context_t));
+
+ /* 设置默认状态 */
+ context->state = ASR_STATE_IDLE;
+
+ /* 创建默认配置 */
+ ai_asr_service_create_default_config(&context->config);
+
+ /* 生成初始会话ID */
+ uint32_t timestamp = get_current_timestamp();
+ uint32_t random = rand();
+ snprintf(context->current_session_id, sizeof(context->current_session_id),
+ "asr_%08x_%04x", timestamp, random & 0xFFFF);
+
+ context->last_activity_time = get_current_timestamp();
+
+ AI_LOGI("ASR service initialized successfully");
+ return AI_OK;
+}
+
+ai_error_t ai_asr_service_destroy(asr_service_context_t *context)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ AI_LOGI("Destroying ASR service...");
+
+ /* 停止活动服务 */
+ if (context->state != ASR_STATE_IDLE) {
+ ai_asr_service_stop(context);
+ }
+
+ /* 重置上下文 */
+ memset(context, 0, sizeof(asr_service_context_t));
+
+ AI_LOGI("ASR service destroyed");
+ return AI_OK;
+}
+
+ai_error_t ai_asr_service_configure(asr_service_context_t *context, const asr_config_t *config)
+{
+ if (context == NULL || config == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ memcpy(&context->config, config, sizeof(asr_config_t));
+ AI_LOGI("ASR configured: language=%s, vad=%s, punctuation=%s",
+ config->language,
+ config->enable_vad ? "enabled" : "disabled",
+ config->enable_punctuation ? "enabled" : "disabled");
+
+ return AI_OK;
+}
+
+ai_error_t ai_asr_service_set_callbacks(asr_service_context_t *context,
+ asr_result_callback_t result_cb,
+ asr_error_callback_t error_cb,
+ asr_state_callback_t state_cb,
+ void *user_data)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ context->result_cb = result_cb;
+ context->error_cb = error_cb;
+ context->state_cb = state_cb;
+ context->user_data = user_data;
+
+ AI_LOGI("ASR callbacks set");
+ return AI_OK;
+}
+
+ai_error_t ai_asr_service_start(asr_service_context_t *context, const char *session_id)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ if (context->state != ASR_STATE_IDLE) {
+ AI_LOGW("ASR already active, stopping first");
+ ai_asr_service_stop(context);
+ }
+
+ /* 使用提供的会话ID或当前会话ID */
+ const char *use_session_id = session_id ? session_id : context->current_session_id;
+
+ AI_LOGI("Starting ASR with session ID: %s", use_session_id);
+
+ /* 检查ASR连接状态 */
+ ai_connection_state_t conn_state = ai_connection_manager_get_connection_state(AI_SERVICE_ASR);
+ if (conn_state != AI_CONN_STATE_CONNECTED) {
+ AI_LOGE("ASR service not connected");
+ return AI_ERROR_SERVICE_UNAVAILABLE;
+ }
+
+ /* 构建启动消息 */
+ char json_buffer[JSON_BUFFER_SIZE];
+ ai_error_t ret = ai_asr_service_build_start_message(use_session_id, &context->config, json_buffer, sizeof(json_buffer));
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to build ASR start message");
+ return ret;
+ }
+
+ /* 发送启动消息 */
+ ret = ai_connection_manager_send_data(AI_SERVICE_ASR, json_buffer, strlen(json_buffer));
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to send ASR start message");
+ return ret;
+ }
+
+ /* 更新状态 */
+ change_asr_state(context, ASR_STATE_LISTENING);
+ strncpy(context->current_session_id, use_session_id, sizeof(context->current_session_id) - 1);
+ context->last_activity_time = get_current_timestamp();
+
+ return AI_OK;
+}
+
+ai_error_t ai_asr_service_send_audio(asr_service_context_t *context, const uint8_t *audio_data, uint32_t data_size)
+{
+ if (context == NULL || audio_data == NULL || data_size == 0) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ if (context->state != ASR_STATE_LISTENING && context->state != ASR_STATE_RECOGNIZING) {
+ AI_LOGW("ASR not in listening/recognizing state");
+ return AI_ERROR_STATE_INVALID;
+ }
+
+ /* 检查数据大小 */
+ if (data_size > MAX_AUDIO_CHUNK_SIZE) {
+ AI_LOGW("Audio chunk too large: %u bytes, splitting", data_size);
+
+ /* 分块发送 */
+ uint32_t offset = 0;
+ while (offset < data_size) {
+ uint32_t chunk_size = (data_size - offset > MAX_AUDIO_CHUNK_SIZE) ?
+ MAX_AUDIO_CHUNK_SIZE : (data_size - offset);
+
+ ai_error_t ret = ai_asr_service_send_audio(context, audio_data + offset, chunk_size);
+ if (ret != AI_OK) {
+ return ret;
+ }
+ offset += chunk_size;
+ }
+ return AI_OK;
+ }
+
+ /* 构建音频数据消息 */
+ ai_buffer_t *buffer = ai_memory_pool_alloc_network(AI_SERVICE_ASR, data_size + 64);
+ if (buffer == NULL) {
+ AI_LOGE("Failed to allocate network buffer for audio data");
+ return AI_ERROR_MEMORY_ALLOC;
+ }
+
+ /* 简化的二进制数据发送(实际实现中可能需要Base64编码) */
+ memcpy(buffer->buffer, audio_data, data_size);
+ buffer->used = data_size;
+
+ ai_error_t ret = ai_connection_manager_send_data(AI_SERVICE_ASR, (const char*)buffer->buffer, buffer->used);
+
+ ai_memory_pool_free(buffer);
+
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to send audio data");
+ return ret;
+ }
+
+ /* 更新状态 */
+ if (context->state == ASR_STATE_LISTENING) {
+ change_asr_state(context, ASR_STATE_RECOGNIZING);
+ }
+
+ context->last_activity_time = get_current_timestamp();
+
+ return AI_OK;
+}
+
+ai_error_t ai_asr_service_stop(asr_service_context_t *context)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ if (context->state == ASR_STATE_IDLE) {
+ return AI_OK; // 已经停止
+ }
+
+ AI_LOGI("Stopping ASR");
+
+ /* 构建停止消息 */
+ char json_buffer[JSON_BUFFER_SIZE];
+ ai_error_t ret = ai_asr_service_build_stop_message(context->current_session_id, json_buffer, sizeof(json_buffer));
+ if (ret == AI_OK) {
+ ai_connection_manager_send_data(AI_SERVICE_ASR, json_buffer, strlen(json_buffer));
+ }
+
+ /* 更新状态 */
+ change_asr_state(context, ASR_STATE_IDLE);
+
+ return AI_OK;
+}
+
+asr_state_t ai_asr_service_get_state(asr_service_context_t *context)
+{
+ if (context == NULL) {
+ return ASR_STATE_ERROR;
+ }
+
+ return context->state;
+}
+
+const char* ai_asr_service_get_state_name(asr_state_t state)
+{
+ if (state >= sizeof(g_asr_state_names) / sizeof(g_asr_state_names[0])) {
+ return "UNKNOWN";
+ }
+
+ return g_asr_state_names[state];
+}
+
+void ai_asr_service_create_default_config(asr_config_t *config)
+{
+ if (config == NULL) {
+ return;
+ }
+
+ memset(config, 0, sizeof(asr_config_t));
+ config->enable_vad = true;
+ config->enable_punctuation = true;
+ config->enable_partial_results = true;
+ config->silence_timeout_ms = 3000; // 3秒静音超时
+ config->max_duration_ms = 30000; // 30秒最大录音时长
+ strncpy(config->language, "zh-CN", sizeof(config->language) - 1);
+}
+
+ai_error_t ai_asr_service_handle_response(asr_service_context_t *context, const char *json_data)
+{
+ if (context == NULL || json_data == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ AI_LOGI("Handling ASR response: %.100s...", json_data);
+
+ /* 解析ASR响应 */
+ asr_result_t result;
+ ai_error_t ret = parse_asr_response(json_data, &result);
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to parse ASR response");
+ change_asr_state(context, ASR_STATE_ERROR);
+ if (context->error_cb != NULL) {
+ context->error_cb(ret, "Failed to parse ASR response", context->user_data);
+ }
+ return ret;
+ }
+
+ /* 更新状态 */
+ if (result.is_final) {
+ change_asr_state(context, ASR_STATE_COMPLETED);
+ }
+
+ /* 调用结果回调 */
+ if (context->result_cb != NULL) {
+ context->result_cb(&result, context->user_data);
+ }
+
+ context->last_activity_time = get_current_timestamp();
+
+ return AI_OK;
+}
+
+ai_error_t ai_asr_service_build_start_message(const char *session_id, const asr_config_t *config,
+ char *json_buffer, size_t buffer_size)
+{
+ if (session_id == NULL || config == NULL || json_buffer == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ /* 构建ASR启动消息 */
+ int ret = snprintf(json_buffer, buffer_size,
+ "{"
+ "\"type\":\"start\","
+ "\"session_id\":\"%s\","
+ "\"config\":{"
+ "\"language\":\"%s\","
+ "\"enable_vad\":%s,"
+ "\"enable_punctuation\":%s,"
+ "\"enable_partial_results\":%s,"
+ "\"silence_timeout_ms\":%d,"
+ "\"max_duration_ms\":%d"
+ "}"
+ "}",
+ session_id,
+ config->language,
+ config->enable_vad ? "true" : "false",
+ config->enable_punctuation ? "true" : "false",
+ config->enable_partial_results ? "true" : "false",
+ config->silence_timeout_ms,
+ config->max_duration_ms
+ );
+
+ if (ret < 0 || ret >= (int)buffer_size) {
+ AI_LOGE("JSON buffer too small for ASR start message");
+ return AI_ERROR_BUFFER_OVERFLOW;
+ }
+
+ return AI_OK;
+}
+
+ai_error_t ai_asr_service_build_stop_message(const char *session_id, char *json_buffer, size_t buffer_size)
+{
+ if (session_id == NULL || json_buffer == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ int ret = snprintf(json_buffer, buffer_size,
+ "{\"type\":\"stop\",\"session_id\":\"%s\"}", session_id);
+
+ if (ret < 0 || ret >= (int)buffer_size) {
+ AI_LOGE("JSON buffer too small for ASR stop message");
+ return AI_ERROR_BUFFER_OVERFLOW;
+ }
+
+ return AI_OK;
+}
+
+/* ================================ 内部函数实现 ================================ */
+
+static uint32_t get_current_timestamp(void)
+{
+#ifndef __TEST_MODE__
+ return (uint32_t)(osKernelGetTickCount() * 1000 / osKernelGetTickFreq());
+#else
+ return (uint32_t)time(NULL);
+#endif
+}
+
+static ai_error_t change_asr_state(asr_service_context_t *context, asr_state_t new_state)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ asr_state_t old_state = context->state;
+ if (old_state != new_state) {
+ context->state = new_state;
+
+ AI_LOGI("ASR state changed: %s -> %s",
+ g_asr_state_names[old_state],
+ g_asr_state_names[new_state]);
+
+ /* 调用状态回调 */
+ if (context->state_cb != NULL) {
+ context->state_cb(old_state, new_state, context->user_data);
+ }
+ }
+
+ return AI_OK;
+}
+
+static ai_error_t parse_asr_response(const char *json_data, asr_result_t *result)
+{
+ if (json_data == NULL || result == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ /* 简化的JSON解析实现 */
+ memset(result, 0, sizeof(asr_result_t));
+
+ /* 在实际实现中,这里应该使用完整的JSON解析库 */
+ /* 这里只是一个简化的示例 */
+
+ /* 查找文本字段 */
+ const char *text_start = strstr(json_data, "\"text\":\"");
+ if (text_start != NULL) {
+ text_start += 8; // 跳过 "text":"
+ const char *text_end = strchr(text_start, '"');
+ if (text_end != NULL) {
+ size_t text_len = text_end - text_start;
+ if (text_len < sizeof(result->text)) {
+ strncpy(result->text, text_start, text_len);
+ result->text[text_len] = '\0';
+ }
+ }
+ }
+
+ /* 查找置信度字段 */
+ const char *confidence_start = strstr(json_data, "\"confidence\":");
+ if (confidence_start != NULL) {
+ result->confidence = atof(confidence_start + 13);
+ } else {
+ result->confidence = 0.9f; // 默认置信度
+ }
+
+ /* 查找是否为最终结果 */
+ result->is_final = (strstr(json_data, "\"is_final\":true") != NULL);
+
+ /* 设置时间戳 */
+ result->start_time_ms = 0;
+ result->end_time_ms = get_current_timestamp();
+
+ AI_LOGI("Parsed ASR result: text='%s', confidence=%.2f, final=%s",
+ result->text, result->confidence, result->is_final ? "true" : "false");
+
+ return AI_OK;
+}
\ No newline at end of file
--- /dev/null
+/**
+ * @file ai_chat_service.c
+ * @brief AI对话(Chat)服务实现
+ * @version 2.0
+ * @date 2024-01-20
+ */
+
+#include "ai_chat_service.h"
+#include "ai_connection_manager.h"
+#include "ai_memory_pool.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#ifndef __TEST_MODE__
+#include "wearable_log.h"
+#include "dev_authentication.h"
+#define AI_LOG_TAG "AI_CHAT"
+#define AI_LOGI(fmt, ...) WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "[%s] " fmt, AI_LOG_TAG, ##__VA_ARGS__)
+#define AI_LOGE(fmt, ...) WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[%s] " fmt, AI_LOG_TAG, ##__VA_ARGS__)
+#define AI_LOGW(fmt, ...) WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "[%s] " fmt, AI_LOG_TAG, ##__VA_ARGS__)
+#else
+#define AI_LOGI(fmt, ...) printf("[AI_CHAT] " fmt "\n", ##__VA_ARGS__)
+#define AI_LOGE(fmt, ...) printf("[AI_CHAT] ERROR: " fmt "\n", ##__VA_ARGS__)
+#define AI_LOGW(fmt, ...) printf("[AI_CHAT] WARN: " fmt "\n", ##__VA_ARGS__)
+#endif
+
+/* ================================ 内部常量定义 ================================ */
+
+#define JSON_BUFFER_SIZE 512 // JSON缓冲区大小
+#define MESSAGE_ID_LENGTH 16 // 消息ID长度
+
+/* Chat状态名称映射 */
+static const char* g_chat_state_names[] = {
+ "IDLE", "SENDING", "WAITING", "RECEIVING", "COMPLETED", "ERROR"
+};
+
+/* ================================ 内部函数声明 ================================ */
+
+static uint32_t get_current_timestamp(void);
+static ai_error_t change_chat_state(chat_service_context_t *context, chat_state_t new_state);
+static ai_error_t parse_chat_response(const char *json_data, chat_message_t *message);
+
+/* ================================ 公共接口实现 ================================ */
+
+ai_error_t ai_chat_service_init(chat_service_context_t *context)
+{
+ if (context == NULL) {
+ AI_LOGE("Invalid context parameter");
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ AI_LOGI("Initializing Chat service...");
+
+ /* 初始化上下文 */
+ memset(context, 0, sizeof(chat_service_context_t));
+
+ /* 设置默认状态 */
+ context->state = CHAT_STATE_IDLE;
+
+ /* 创建默认配置 */
+ ai_chat_service_create_default_config(&context->config);
+
+ /* 生成初始会话ID */
+ uint32_t timestamp = get_current_timestamp();
+ uint32_t random = rand();
+ snprintf(context->current_session_id, sizeof(context->current_session_id),
+ "chat_%08x_%04x", timestamp, random & 0xFFFF);
+
+ context->last_activity_time = get_current_timestamp();
+
+ AI_LOGI("Chat service initialized successfully");
+ return AI_OK;
+}
+
+ai_error_t ai_chat_service_destroy(chat_service_context_t *context)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ AI_LOGI("Destroying Chat service...");
+
+ /* 重置上下文 */
+ memset(context, 0, sizeof(chat_service_context_t));
+
+ AI_LOGI("Chat service destroyed");
+ return AI_OK;
+}
+
+ai_error_t ai_chat_service_configure(chat_service_context_t *context, const chat_config_t *config)
+{
+ if (context == NULL || config == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ memcpy(&context->config, config, sizeof(chat_config_t));
+ AI_LOGI("Chat configured: model=%s, temperature=%.2f, max_tokens=%d",
+ config->model_name, config->temperature, config->max_tokens);
+
+ return AI_OK;
+}
+
+ai_error_t ai_chat_service_set_callbacks(chat_service_context_t *context,
+ chat_response_callback_t response_cb,
+ chat_error_callback_t error_cb,
+ chat_state_callback_t state_cb,
+ void *user_data)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ context->response_cb = response_cb;
+ context->error_cb = error_cb;
+ context->state_cb = state_cb;
+ context->user_data = user_data;
+
+ AI_LOGI("Chat callbacks set");
+ return AI_OK;
+}
+
+ai_error_t ai_chat_service_send_message(chat_service_context_t *context, const char *message, const char *session_id)
+{
+ if (context == NULL || message == NULL || strlen(message) == 0) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ if (context->state != CHAT_STATE_IDLE) {
+ AI_LOGW("Chat busy, current state: %s", g_chat_state_names[context->state]);
+ return AI_ERROR_STATE_INVALID;
+ }
+
+ /* 使用提供的会话ID或当前会话ID */
+ const char *use_session_id = session_id ? session_id : context->current_session_id;
+
+ AI_LOGI("Sending chat message: %.50s... (session: %s)", message, use_session_id);
+
+ /* 检查Chat连接状态 */
+ ai_connection_state_t conn_state = ai_connection_manager_get_connection_state(AI_SERVICE_CHAT);
+ if (conn_state != AI_CONN_STATE_CONNECTED) {
+ AI_LOGE("Chat service not connected");
+ return AI_ERROR_SERVICE_UNAVAILABLE;
+ }
+
+ /* 构建聊天消息 */
+ char json_buffer[JSON_BUFFER_SIZE];
+ ai_error_t ret = ai_chat_service_build_message(message, use_session_id, &context->config, json_buffer, sizeof(json_buffer));
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to build chat message");
+ return ret;
+ }
+
+ /* 发送消息 */
+ change_chat_state(context, CHAT_STATE_SENDING);
+
+ ret = ai_connection_manager_send_data(AI_SERVICE_CHAT, json_buffer, strlen(json_buffer));
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to send chat message");
+ change_chat_state(context, CHAT_STATE_ERROR);
+ return ret;
+ }
+
+ /* 更新状态 */
+ change_chat_state(context, CHAT_STATE_WAITING);
+ strncpy(context->current_session_id, use_session_id, sizeof(context->current_session_id) - 1);
+ context->last_activity_time = get_current_timestamp();
+
+ return AI_OK;
+}
+
+chat_state_t ai_chat_service_get_state(chat_service_context_t *context)
+{
+ if (context == NULL) {
+ return CHAT_STATE_ERROR;
+ }
+
+ return context->state;
+}
+
+const char* ai_chat_service_get_state_name(chat_state_t state)
+{
+ if (state >= sizeof(g_chat_state_names) / sizeof(g_chat_state_names[0])) {
+ return "UNKNOWN";
+ }
+
+ return g_chat_state_names[state];
+}
+
+void ai_chat_service_create_default_config(chat_config_t *config)
+{
+ if (config == NULL) {
+ return;
+ }
+
+ memset(config, 0, sizeof(chat_config_t));
+ strncpy(config->model_name, "qwen-plus", sizeof(config->model_name) - 1);
+ config->temperature = 0.7f;
+ config->max_tokens = 512; // 适合LiteOS-M的较小值
+ config->top_p = 0.9f;
+ config->stream = true;
+ config->timeout_ms = 15000; // 15秒超时
+}
+
+ai_error_t ai_chat_service_handle_response(chat_service_context_t *context, const char *json_data)
+{
+ if (context == NULL || json_data == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ AI_LOGI("Handling Chat response: %.100s...", json_data);
+
+ /* 解析Chat响应 */
+ chat_message_t message;
+ ai_error_t ret = parse_chat_response(json_data, &message);
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to parse Chat response");
+ change_chat_state(context, CHAT_STATE_ERROR);
+ if (context->error_cb != NULL) {
+ context->error_cb(ret, "Failed to parse Chat response", context->user_data);
+ }
+ return ret;
+ }
+
+ /* 更新状态 */
+ if (message.is_final) {
+ change_chat_state(context, CHAT_STATE_COMPLETED);
+ } else {
+ change_chat_state(context, CHAT_STATE_RECEIVING);
+ }
+
+ /* 调用响应回调 */
+ if (context->response_cb != NULL) {
+ context->response_cb(&message, context->user_data);
+ }
+
+ context->last_activity_time = get_current_timestamp();
+
+ return AI_OK;
+}
+
+ai_error_t ai_chat_service_build_message(const char *message, const char *session_id, const chat_config_t *config,
+ char *json_buffer, size_t buffer_size)
+{
+ if (message == NULL || session_id == NULL || config == NULL || json_buffer == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ /* 生成消息ID */
+ char message_id[MESSAGE_ID_LENGTH + 1];
+ ai_chat_service_generate_message_id(message_id, sizeof(message_id));
+
+ /* 构建Chat消息 */
+ int ret = snprintf(json_buffer, buffer_size,
+ "{"
+ "\"type\":\"chat\","
+ "\"session_id\":\"%s\","
+ "\"message_id\":\"%s\","
+ "\"message\":{"
+ "\"role\":\"user\","
+ "\"content\":\"%s\""
+ "},"
+ "\"config\":{"
+ "\"model\":\"%s\","
+ "\"temperature\":%.2f,"
+ "\"max_tokens\":%d,"
+ "\"top_p\":%.2f,"
+ "\"stream\":%s"
+ "}"
+ "}",
+ session_id,
+ message_id,
+ message,
+ config->model_name,
+ config->temperature,
+ config->max_tokens,
+ config->top_p,
+ config->stream ? "true" : "false"
+ );
+
+ if (ret < 0 || ret >= (int)buffer_size) {
+ AI_LOGE("JSON buffer too small for chat message");
+ return AI_ERROR_BUFFER_OVERFLOW;
+ }
+
+ return AI_OK;
+}
+
+void ai_chat_service_generate_message_id(char *message_id, size_t buffer_size)
+{
+ if (message_id == NULL || buffer_size < MESSAGE_ID_LENGTH + 1) {
+ return;
+ }
+
+ uint32_t timestamp = get_current_timestamp();
+ uint16_t random = rand() & 0xFFFF;
+
+ snprintf(message_id, buffer_size, "msg_%08x_%04x", timestamp, random);
+}
+
+/* ================================ 内部函数实现 ================================ */
+
+static uint32_t get_current_timestamp(void)
+{
+#ifndef __TEST_MODE__
+ return (uint32_t)(osKernelGetTickCount() * 1000 / osKernelGetTickFreq());
+#else
+ return (uint32_t)time(NULL);
+#endif
+}
+
+static ai_error_t change_chat_state(chat_service_context_t *context, chat_state_t new_state)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ chat_state_t old_state = context->state;
+ if (old_state != new_state) {
+ context->state = new_state;
+
+ AI_LOGI("Chat state changed: %s -> %s",
+ g_chat_state_names[old_state],
+ g_chat_state_names[new_state]);
+
+ /* 调用状态回调 */
+ if (context->state_cb != NULL) {
+ context->state_cb(old_state, new_state, context->user_data);
+ }
+ }
+
+ return AI_OK;
+}
+
+static ai_error_t parse_chat_response(const char *json_data, chat_message_t *message)
+{
+ if (json_data == NULL || message == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ /* 简化的JSON解析实现 */
+ memset(message, 0, sizeof(chat_message_t));
+
+ /* 在实际实现中,这里应该使用完整的JSON解析库 */
+ /* 这里只是一个简化的示例 */
+
+ /* 查找角色字段 */
+ const char *role_start = strstr(json_data, "\"role\":\"");
+ if (role_start != NULL) {
+ role_start += 8; // 跳过 "role":"
+ const char *role_end = strchr(role_start, '"');
+ if (role_end != NULL) {
+ size_t role_len = role_end - role_start;
+ if (role_len < sizeof(message->role)) {
+ strncpy(message->role, role_start, role_len);
+ message->role[role_len] = '\0';
+ }
+ }
+ } else {
+ strcpy(message->role, "assistant"); // 默认角色
+ }
+
+ /* 查找内容字段 */
+ const char *content_start = strstr(json_data, "\"content\":\"");
+ if (content_start != NULL) {
+ content_start += 11; // 跳过 "content":"
+ const char *content_end = strchr(content_start, '"');
+ if (content_end != NULL) {
+ size_t content_len = content_end - content_start;
+ if (content_len < sizeof(message->content)) {
+ strncpy(message->content, content_start, content_len);
+ message->content[content_len] = '\0';
+ }
+ }
+ }
+
+ /* 查找消息ID字段 */
+ const char *msg_id_start = strstr(json_data, "\"message_id\":\"");
+ if (msg_id_start != NULL) {
+ msg_id_start += 14; // 跳过 "message_id":"
+ const char *msg_id_end = strchr(msg_id_start, '"');
+ if (msg_id_end != NULL) {
+ size_t msg_id_len = msg_id_end - msg_id_start;
+ if (msg_id_len < sizeof(message->message_id)) {
+ strncpy(message->message_id, msg_id_start, msg_id_len);
+ message->message_id[msg_id_len] = '\0';
+ }
+ }
+ }
+
+ /* 查找会话ID字段 */
+ const char *session_id_start = strstr(json_data, "\"session_id\":\"");
+ if (session_id_start != NULL) {
+ session_id_start += 14; // 跳过 "session_id":"
+ const char *session_id_end = strchr(session_id_start, '"');
+ if (session_id_end != NULL) {
+ size_t session_id_len = session_id_end - session_id_start;
+ if (session_id_len < sizeof(message->session_id)) {
+ strncpy(message->session_id, session_id_start, session_id_len);
+ message->session_id[session_id_len] = '\0';
+ }
+ }
+ }
+
+ /* 查找是否为最终消息 */
+ message->is_final = (strstr(json_data, "\"is_final\":true") != NULL) ||
+ (strstr(json_data, "\"finish_reason\":") != NULL);
+
+ /* 设置时间戳 */
+ message->timestamp = get_current_timestamp();
+
+ AI_LOGI("Parsed Chat message: role='%s', content='%.50s...', final=%s",
+ message->role, message->content, message->is_final ? "true" : "false");
+
+ return AI_OK;
+}
\ No newline at end of file
return AI_ERROR_NOT_INITIALIZED;
}
- AI_LOGI("Starting all connections concurrently...");
+ AI_LOGI("[DEBUG] ai_connection_manager_start_all: Entry point");
+ AI_LOGI("[DEBUG] Setting global state to CONNECTING...");
g_connection_manager.global_state = AI_STATE_CONNECTING;
+ AI_LOGI("[DEBUG] Global state set successfully");
+
+ AI_LOGI("[DEBUG] Setting is_running to true...");
g_connection_manager.is_running = true;
+ AI_LOGI("[DEBUG] is_running set successfully");
/* 记录连接开始时间 */
+ AI_LOGI("[DEBUG] Getting current timestamp...");
uint32_t start_time = get_current_timestamp();
+ AI_LOGI("[DEBUG] Current timestamp: %u", start_time);
+
+ AI_LOGI("[DEBUG] Setting last_connect_timestamp...");
g_connection_manager.metrics.last_connect_timestamp = start_time;
+ AI_LOGI("[DEBUG] last_connect_timestamp set successfully");
/* 并发启动所有连接线程 */
+ AI_LOGI("[DEBUG] Starting connection thread creation loop...");
+ AI_LOGI("[DEBUG] AI_SERVICE_COUNT = %d", AI_SERVICE_COUNT);
+
for (int i = 0; i < AI_SERVICE_COUNT; i++) {
+ AI_LOGI("[DEBUG] Creating thread for service %d (%s)...", i, g_service_names[i]);
+
ai_error_t ret = connection_thread_create((ai_service_type_t)i);
+ AI_LOGI("[DEBUG] connection_thread_create returned: %d", ret);
+
if (ret != AI_OK) {
- AI_LOGE("Failed to create connection thread for service %s", g_service_names[i]);
+ AI_LOGE("[DEBUG] Failed to create connection thread for service %s, error: %d", g_service_names[i], ret);
return ret;
}
+
+ AI_LOGI("[DEBUG] Thread created successfully for service %s", g_service_names[i]);
+
+#ifndef __TEST_MODE__
+ AI_LOGI("[DEBUG] Calling osDelay(100)...");
+ /* 给线程一些时间启动,避免竞态条件 */
+ osDelay(100); // 100ms延迟
+ AI_LOGI("[DEBUG] osDelay(100) completed");
+#endif
}
+ AI_LOGI("[DEBUG] All connection threads created, checking heartbeat timer...");
+
#ifndef __TEST_MODE__
/* 启动心跳定时器 */
+ AI_LOGI("[DEBUG] Checking heartbeat_timer: %p", g_connection_manager.heartbeat_timer);
if (g_connection_manager.heartbeat_timer != NULL) {
+ AI_LOGI("[DEBUG] Starting heartbeat timer with interval %u ms...",
+ g_connection_manager.config.keepalive_interval_ms);
osTimerStart(g_connection_manager.heartbeat_timer,
g_connection_manager.config.keepalive_interval_ms);
+ AI_LOGI("[DEBUG] Heartbeat timer started successfully");
+ } else {
+ AI_LOGI("[DEBUG] Heartbeat timer is NULL, skipping");
}
#endif
+ AI_LOGI("[DEBUG] ai_connection_manager_start_all: About to return AI_OK");
AI_LOGI("All connection threads started");
return AI_OK;
}
static ai_error_t connection_thread_create(ai_service_type_t service_type)
{
+ AI_LOGI("[DEBUG] connection_thread_create: Entry, service_type=%d", service_type);
+
if (service_type >= AI_SERVICE_COUNT) {
+ AI_LOGE("[DEBUG] Invalid service_type: %d >= %d", service_type, AI_SERVICE_COUNT);
return AI_ERROR_INVALID_PARAM;
}
+ AI_LOGI("[DEBUG] Getting connection info for service %d...", service_type);
ai_connection_info_t *conn = &g_connection_manager.connections[service_type];
+ AI_LOGI("[DEBUG] Connection info pointer: %p", conn);
#ifndef __TEST_MODE__
+ AI_LOGI("[DEBUG] Creating osThreadAttr_t structure...");
+
+ /* 使用更保守的线程配置以避免创建失败 */
osThreadAttr_t thread_attr = {
- .stack_size = AI_CONNECTION_STACK_SIZE,
- .priority = g_connection_manager.config.connection_thread_priority
+ .stack_size = 2048, // 减少栈大小到2KB
+ .name = "connection_thread",
+ .priority = osPriorityNormal // 使用标准优先级
};
+ //在psram里分配栈内存
+ if(thread_attr.stack_mem == NULL)
+ {
+ thread_attr.stack_mem = memalign(16,thread_attr.stack_size);
+ if(thread_attr.stack_mem == NULL)
+ {
+ AI_LOGE("[DEBUG] Thread stack memory allocation failed");
+ }
+ }
+
+ AI_LOGI("[DEBUG] Thread attributes: stack_size=%u, priority=%d",
+ thread_attr.stack_size, (int)thread_attr.priority);
+ AI_LOGI("[DEBUG] Original config priority was: %d", g_connection_manager.config.connection_thread_priority);
+
+ AI_LOGI("[DEBUG] Skipping thread name setting to avoid exception...");
+ AI_LOGI("[DEBUG] service_type=%d, service_name=%s", service_type, g_service_names[service_type]);
+
+ /* 临时禁用线程名称设置以避免异常 */
+
+ AI_LOGI("[DEBUG] Calling osThreadNew...");
+ AI_LOGI("[DEBUG] Parameters: entry=%p, argument=%p, attr=%p",
+ connection_thread_entry, (void*)service_type, &thread_attr);
- snprintf((char*)thread_attr.name, sizeof(thread_attr.name), "ai_conn_%s", g_service_names[service_type]);
+ /* 恢复实际线程创建,使用优化的配置 */
+ AI_LOGI("[DEBUG] Creating thread with optimized configuration...");
conn->thread_id = osThreadNew(connection_thread_entry, (void*)service_type, &thread_attr);
+ AI_LOGI("[DEBUG] osThreadNew returned: %p", conn->thread_id);
+
if (conn->thread_id == NULL) {
- AI_LOGE("Failed to create connection thread for service %s", g_service_names[service_type]);
- return AI_ERROR_MEMORY_ALLOC;
+ AI_LOGE("[DEBUG] Thread creation failed, trying with minimal configuration...");
+
+ /* 尝试使用最小配置 */
+ osThreadAttr_t minimal_attr = {
+ .stack_size = 1024, // 最小栈大小1KB
+ .name = "connection_thread_minimal",
+ .priority = osPriorityNormal
+ };
+ //在psram里分配栈内存
+ if(thread_attr.stack_mem == NULL)
+ {
+ thread_attr.stack_mem = memalign(16,thread_attr.stack_size);
+ if(thread_attr.stack_mem == NULL)
+ {
+ AI_LOGE("[DEBUG] Thread stack memory allocation failed");
+ }
+ }
+ conn->thread_id = osThreadNew(connection_thread_entry, (void*)service_type, &minimal_attr);
+ AI_LOGI("[DEBUG] Minimal config osThreadNew returned: %p", conn->thread_id);
+
+ if (conn->thread_id == NULL) {
+ AI_LOGE("[DEBUG] Thread creation failed even with minimal config");
+ return AI_ERROR_MEMORY_ALLOC;
+ } else {
+ AI_LOGW("[DEBUG] Thread created with minimal configuration (1KB stack)");
+ }
+ } else {
+ AI_LOGI("[DEBUG] Thread created successfully with optimized configuration");
}
+
+ /* 设置初始连接状态 */
+ conn->state = AI_CONN_STATE_DISCONNECTED;
+
+ AI_LOGI("[DEBUG] Thread created successfully for service %s, thread_id=%p",
+ g_service_names[service_type], conn->thread_id);
#else
- AI_LOGI("TEST: Created connection thread for service %s", g_service_names[service_type]);
+ AI_LOGI("[DEBUG] TEST MODE: Simulating thread creation for service %s", g_service_names[service_type]);
conn->thread_id = (void*)1; // 模拟线程ID
+ AI_LOGI("[DEBUG] TEST MODE: Thread ID set to %p", conn->thread_id);
#endif
+ AI_LOGI("[DEBUG] connection_thread_create: Returning AI_OK");
return AI_OK;
}
static void connection_thread_entry(void *argument)
{
+ AI_LOGI("[DEBUG] connection_thread_entry: Entry, argument=%p", argument);
+
+ AI_LOGI("[DEBUG] Converting argument to service_type...");
ai_service_type_t service_type = (ai_service_type_t)(uintptr_t)argument;
+ AI_LOGI("[DEBUG] service_type=%d", service_type);
+
+ AI_LOGI("[DEBUG] Getting connection info...");
ai_connection_info_t *conn = &g_connection_manager.connections[service_type];
+ AI_LOGI("[DEBUG] Connection info pointer: %p", conn);
- AI_LOGI("Connection thread started for service %s", g_service_names[service_type]);
+ AI_LOGI("[DEBUG] Connection thread started for service %s", g_service_names[service_type]);
while (g_connection_manager.is_running) {
if (conn->state == AI_CONN_STATE_DISCONNECTED) {
conn->retry_count,
g_connection_manager.config.max_retry_count);
- if (conn->retry_count >= g_connection_manager.config.max_retry_count) {
- AI_LOGE("Service %s connection failed after %d retries",
+ /* 为了安全,限制重试次数为1次 */
+ if (conn->retry_count >= 1) {
+ AI_LOGW("Service %s connection disabled for safety after %d attempts",
g_service_names[service_type], conn->retry_count);
+ /* 设置为永久断开状态,不再重试 */
+ conn->state = AI_CONN_STATE_ERROR;
+
/* 发送连接失败事件 */
send_event(AI_EVENT_ERROR_OCCURRED, service_type, &ret);
break;
return AI_ERROR_INVALID_PARAM;
}
+ /* 验证服务类型有效性 */
+ if (conn_info->service_type >= AI_SERVICE_COUNT) {
+ AI_LOGE("Invalid service type: %d", conn_info->service_type);
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ /* 确保管理器仍然在运行 */
+ if (!g_manager_initialized || !g_connection_manager.is_running) {
+ AI_LOGE("Connection manager not running");
+ return AI_ERROR_NOT_INITIALIZED;
+ }
+
AI_LOGI("Connecting to %s: %s", g_service_names[conn_info->service_type], conn_info->url);
#ifndef __TEST_MODE__
- /* 创建WebSocket客户端 */
+ /* 恢复实际WebSocket连接 */
+ AI_LOGI("Creating WebSocket client for service %s", g_service_names[conn_info->service_type]);
+
conn_info->websocket = WebSocketClientConstructor(websocket_on_connected, websocket_on_message,
websocket_on_error, websocket_on_disconnected);
if (conn_info->websocket < 0) {
return AI_ERROR_MEMORY_ALLOC;
}
- /* 连接到服务器 */
+ AI_LOGI("WebSocket client created successfully, fd=%d", conn_info->websocket);
+ conn_info->state = AI_CONN_STATE_CONNECTING;
+
int ret = WebSocketClientConnect(conn_info->websocket, conn_info->url);
if (ret != 0) {
AI_LOGE("WebSocket connection failed: %d", ret);
WebSocketClientClose(conn_info->websocket);
conn_info->websocket = -1;
+ conn_info->state = AI_CONN_STATE_DISCONNECTED;
return AI_ERROR_CONNECTION_FAILED;
}
+
+ AI_LOGI("WebSocket connection initiated for service %s", g_service_names[conn_info->service_type]);
#else
/* 测试模式下模拟连接成功 */
conn_info->websocket = 1; // 模拟WebSocket文件描述符
static void websocket_on_connected(int client)
{
+ /* 安全检查:确保管理器已初始化 */
+ if (!g_manager_initialized) {
+ AI_LOGE("Connection manager not initialized");
+ return;
+ }
+
ai_connection_info_t *conn_info = find_connection_by_websocket(client);
if (conn_info == NULL) {
AI_LOGE("Cannot find connection info for WebSocket client %d", client);
return;
}
+ /* 验证服务类型有效性 */
+ if (conn_info->service_type >= AI_SERVICE_COUNT) {
+ AI_LOGE("Invalid service type: %d", conn_info->service_type);
+ return;
+ }
+
AI_LOGI("WebSocket connected for service %s", g_service_names[conn_info->service_type]);
#ifndef __TEST_MODE__
static void websocket_on_message(int client, const char *data, size_t length, bool isFinished)
{
(void)isFinished; // 暂时不处理分片消息
+
+ /* 安全检查:确保管理器已初始化 */
+ if (!g_manager_initialized) {
+ return;
+ }
+
ai_connection_info_t *conn_info = find_connection_by_websocket(client);
if (conn_info == NULL || data == NULL || length == 0) {
return;
}
+ /* 验证服务类型有效性 */
+ if (conn_info->service_type >= AI_SERVICE_COUNT) {
+ AI_LOGE("Invalid service type: %d", conn_info->service_type);
+ return;
+ }
+
AI_LOGI("Received %zu bytes from service %s", length, g_service_names[conn_info->service_type]);
/* 更新统计 */
static void websocket_on_error(int client, struct WebSocketErrorResult errorResult)
{
+ /* 安全检查:确保管理器已初始化 */
+ if (!g_manager_initialized) {
+ return;
+ }
+
ai_connection_info_t *conn_info = find_connection_by_websocket(client);
if (conn_info == NULL) {
return;
}
+ /* 验证服务类型有效性 */
+ if (conn_info->service_type >= AI_SERVICE_COUNT) {
+ AI_LOGE("Invalid service type: %d", conn_info->service_type);
+ return;
+ }
+
AI_LOGE("WebSocket error for service %s: %d - %s",
g_service_names[conn_info->service_type], errorResult.errorCode,
errorResult.errorMessage ? errorResult.errorMessage : "Unknown");
static void websocket_on_disconnected(int client)
{
+ /* 安全检查:确保管理器已初始化 */
+ if (!g_manager_initialized) {
+ return;
+ }
+
ai_connection_info_t *conn_info = find_connection_by_websocket(client);
if (conn_info == NULL) {
return;
}
+ /* 验证服务类型有效性 */
+ if (conn_info->service_type >= AI_SERVICE_COUNT) {
+ AI_LOGE("Invalid service type: %d", conn_info->service_type);
+ return;
+ }
+
AI_LOGW("WebSocket disconnected for service %s", g_service_names[conn_info->service_type]);
conn_info->state = AI_CONN_STATE_DISCONNECTED;
{AI_AUDIO_IN_BUFFER_SIZE * 2, AI_AUDIO_IN_BUFFER_SIZE, 2}, // AUDIO_IN: 2个2KB块
{AI_AUDIO_OUT_BUFFER_SIZE * 2, AI_AUDIO_OUT_BUFFER_SIZE, 2}, // AUDIO_OUT: 2个1KB块
{AI_NETWORK_POOL_SIZE, 256, 12}, // NETWORK: 12个256B块
- {AI_CONNECTION_BUFFER_SIZE * 3, AI_CONNECTION_BUFFER_SIZE, 3} // CONNECTION: 3个1KB块
+ {AI_CONNECTION_BUFFER_SIZE * 6, AI_CONNECTION_BUFFER_SIZE, 6} // CONNECTION: 6个1KB块 (3个服务 x 2个缓冲区)
};
/* ================================ 内部函数声明 ================================ */
/**
* @file ai_services.c
- * @brief AI服务统一接口实现 - LiteOS-M优化版v2
+ * @brief AI服务统一管理接口实现 - LiteOS-M优化版v2
* @version 2.0
* @date 2024-01-20
*/
#include "ai_services.h"
+#include "ai_asr_service.h"
+#include "ai_chat_service.h"
+#include "ai_tts_service.h"
#include "ai_connection_manager.h"
#include "ai_memory_pool.h"
#include <string.h>
#define AI_LOGW(fmt, ...) printf("[AI_SERVICES] WARN: " fmt "\n", ##__VA_ARGS__)
#endif
-/* ================================ 内部常量定义 ================================ */
-
-#define JSON_BUFFER_SIZE 512 // JSON缓冲区大小
-#define MESSAGE_ID_LENGTH 16 // 消息ID长度
-#define MAX_AUDIO_CHUNK_SIZE 1024 // 最大音频块大小
-
-/* 语音类型名称映射 */
-static const char* g_voice_names[TTS_VOICE_COUNT] = {
- "xiaoyun", "xiaogang", "xiaomei", "xiaoli"
-};
-
-/* 状态名称映射 */
-static const char* g_asr_state_names[] = {
- "IDLE", "LISTENING", "RECOGNIZING", "COMPLETED", "ERROR"
-};
-
-static const char* g_chat_state_names[] = {
- "IDLE", "SENDING", "WAITING", "RECEIVING", "COMPLETED", "ERROR"
-};
-
-static const char* g_tts_state_names[] = {
- "IDLE", "SYNTHESIZING", "PLAYING", "COMPLETED", "ERROR"
-};
-
/* ================================ 内部函数声明 ================================ */
-static ai_error_t build_asr_start_message(const char *session_id, const asr_config_t *config, char *json_buffer, size_t buffer_size);
-static ai_error_t build_chat_message(const char *message, const char *session_id, const chat_config_t *config, char *json_buffer, size_t buffer_size);
-static ai_error_t build_tts_request(const char *text, const char *session_id, const tts_config_t *config, char *json_buffer, size_t buffer_size);
-static ai_error_t parse_asr_response(const char *json_data, asr_result_t *result);
-static ai_error_t parse_chat_response(const char *json_data, chat_message_t *message);
-static ai_error_t parse_tts_response(const char *json_data, tts_result_t *result);
-static void generate_message_id(char *message_id, size_t buffer_size);
static uint32_t get_current_timestamp(void);
static void connection_event_handler(const ai_event_t *event, void *user_data);
-static ai_error_t change_asr_state(ai_services_context_t *context, asr_state_t new_state);
-static ai_error_t change_chat_state(ai_services_context_t *context, chat_state_t new_state);
-static ai_error_t change_tts_state(ai_services_context_t *context, tts_state_t new_state);
/* ================================ 公共接口实现 ================================ */
/* 初始化上下文 */
memset(context, 0, sizeof(ai_services_context_t));
- /* 设置默认状态 */
- context->asr_state = ASR_STATE_IDLE;
- context->chat_state = CHAT_STATE_IDLE;
- context->tts_state = TTS_STATE_IDLE;
+ /* 初始化各个服务 */
+ ai_error_t ret = ai_asr_service_init(&context->asr_context);
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to initialize ASR service: %d", ret);
+ return ret;
+ }
- /* 创建默认配置 */
- ai_asr_create_default_config(&context->asr_config);
- ai_chat_create_default_config(&context->chat_config);
- ai_tts_create_default_config(&context->tts_config);
+ ret = ai_chat_service_init(&context->chat_context);
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to initialize Chat service: %d", ret);
+ ai_asr_service_destroy(&context->asr_context);
+ return ret;
+ }
- /* 生成初始会话ID */
+ ret = ai_tts_service_init(&context->tts_context);
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to initialize TTS service: %d", ret);
+ ai_asr_service_destroy(&context->asr_context);
+ ai_chat_service_destroy(&context->chat_context);
+ return ret;
+ }
+
+ /* 生成统一会话ID */
ai_services_generate_session_id(context->current_session_id, sizeof(context->current_session_id));
context->last_activity_time = get_current_timestamp();
AI_LOGI("Destroying AI services...");
- /* 停止所有活动服务 */
- if (context->asr_state != ASR_STATE_IDLE) {
- ai_asr_stop(context);
- }
-
- if (context->tts_state != TTS_STATE_IDLE) {
- ai_tts_stop(context);
- }
+ /* 销毁各个服务 */
+ ai_asr_service_destroy(&context->asr_context);
+ ai_chat_service_destroy(&context->chat_context);
+ ai_tts_service_destroy(&context->tts_context);
/* 重置上下文 */
memset(context, 0, sizeof(ai_services_context_t));
return AI_OK;
}
-/* ================================ ASRæ\9c\8då\8a¡æ\8e¥å\8f£å®\9eç\8e° ================================ */
+/* ================================ ASRæ\9c\8då\8a¡æ\8e¥å\8f£å\8c\85è£\85 ================================ */
ai_error_t ai_asr_configure(ai_services_context_t *context, const asr_config_t *config)
{
return AI_ERROR_NOT_INITIALIZED;
}
- memcpy(&context->asr_config, config, sizeof(asr_config_t));
- AI_LOGI("ASR configured: language=%s, vad=%s, punctuation=%s",
- config->language,
- config->enable_vad ? "enabled" : "disabled",
- config->enable_punctuation ? "enabled" : "disabled");
-
- return AI_OK;
+ return ai_asr_service_configure(&context->asr_context, config);
}
ai_error_t ai_asr_set_callbacks(ai_services_context_t *context,
return AI_ERROR_NOT_INITIALIZED;
}
- context->asr_result_cb = result_cb;
- context->asr_error_cb = error_cb;
- context->asr_state_cb = state_cb;
- context->user_data = user_data;
-
- AI_LOGI("ASR callbacks set");
- return AI_OK;
+ return ai_asr_service_set_callbacks(&context->asr_context, result_cb, error_cb, state_cb, user_data);
}
ai_error_t ai_asr_start(ai_services_context_t *context, const char *session_id)
return AI_ERROR_NOT_INITIALIZED;
}
- if (context->asr_state != ASR_STATE_IDLE) {
- AI_LOGW("ASR already active, stopping first");
- ai_asr_stop(context);
- }
-
- /* 使用提供的会话ID或当前会话ID */
+ /* 使用统一会话ID或提供的会话ID */
const char *use_session_id = session_id ? session_id : context->current_session_id;
- AI_LOGI("Starting ASR with session ID: %s", use_session_id);
-
- /* 检查ASR连接状态 */
- ai_connection_state_t conn_state = ai_connection_manager_get_connection_state(AI_SERVICE_ASR);
- if (conn_state != AI_CONN_STATE_CONNECTED) {
- AI_LOGE("ASR service not connected");
- return AI_ERROR_SERVICE_UNAVAILABLE;
- }
-
- /* 构建启动消息 */
- char json_buffer[JSON_BUFFER_SIZE];
- ai_error_t ret = build_asr_start_message(use_session_id, &context->asr_config, json_buffer, sizeof(json_buffer));
- if (ret != AI_OK) {
- AI_LOGE("Failed to build ASR start message");
- return ret;
- }
-
- /* 发送启动消息 */
- ret = ai_connection_manager_send_data(AI_SERVICE_ASR, json_buffer, strlen(json_buffer));
- if (ret != AI_OK) {
- AI_LOGE("Failed to send ASR start message");
- return ret;
- }
-
- /* 更新状态 */
- change_asr_state(context, ASR_STATE_LISTENING);
- strncpy(context->current_session_id, use_session_id, sizeof(context->current_session_id) - 1);
- context->last_activity_time = get_current_timestamp();
-
- return AI_OK;
+ return ai_asr_service_start(&context->asr_context, use_session_id);
}
ai_error_t ai_asr_send_audio(ai_services_context_t *context, const uint8_t *audio_data, uint32_t data_size)
{
- if (context == NULL || audio_data == NULL || data_size == 0) {
+ if (context == NULL) {
return AI_ERROR_INVALID_PARAM;
}
return AI_ERROR_NOT_INITIALIZED;
}
- if (context->asr_state != ASR_STATE_LISTENING && context->asr_state != ASR_STATE_RECOGNIZING) {
- AI_LOGW("ASR not in listening/recognizing state");
- return AI_ERROR_STATE_INVALID;
- }
-
- /* 检查数据大小 */
- if (data_size > MAX_AUDIO_CHUNK_SIZE) {
- AI_LOGW("Audio chunk too large: %u bytes, splitting", data_size);
-
- /* 分块发送 */
- uint32_t offset = 0;
- while (offset < data_size) {
- uint32_t chunk_size = (data_size - offset > MAX_AUDIO_CHUNK_SIZE) ?
- MAX_AUDIO_CHUNK_SIZE : (data_size - offset);
-
- ai_error_t ret = ai_asr_send_audio(context, audio_data + offset, chunk_size);
- if (ret != AI_OK) {
- return ret;
- }
- offset += chunk_size;
- }
- return AI_OK;
- }
-
- /* 构建音频数据消息 */
- ai_buffer_t *buffer = ai_memory_pool_alloc_network(AI_SERVICE_ASR, data_size + 64);
- if (buffer == NULL) {
- AI_LOGE("Failed to allocate network buffer for audio data");
- return AI_ERROR_MEMORY_ALLOC;
- }
-
- /* 简化的二进制数据发送(实际实现中可能需要Base64编码) */
- memcpy(buffer->buffer, audio_data, data_size);
- buffer->used = data_size;
-
- ai_error_t ret = ai_connection_manager_send_data(AI_SERVICE_ASR, (const char*)buffer->buffer, buffer->used);
-
- ai_memory_pool_free(buffer);
-
- if (ret != AI_OK) {
- AI_LOGE("Failed to send audio data");
- return ret;
- }
-
- /* 更新状态 */
- if (context->asr_state == ASR_STATE_LISTENING) {
- change_asr_state(context, ASR_STATE_RECOGNIZING);
- }
-
- context->last_activity_time = get_current_timestamp();
-
- return AI_OK;
+ return ai_asr_service_send_audio(&context->asr_context, audio_data, data_size);
}
ai_error_t ai_asr_stop(ai_services_context_t *context)
return AI_ERROR_NOT_INITIALIZED;
}
- if (context->asr_state == ASR_STATE_IDLE) {
- return AI_OK; // 已经停止
- }
-
- AI_LOGI("Stopping ASR");
-
- /* 发送停止消息 */
- char stop_message[] = "{\"type\":\"stop\",\"session_id\":\"%s\"}";
- char json_buffer[JSON_BUFFER_SIZE];
- snprintf(json_buffer, sizeof(json_buffer), stop_message, context->current_session_id);
-
- ai_connection_manager_send_data(AI_SERVICE_ASR, json_buffer, strlen(json_buffer));
-
- /* 更新状态 */
- change_asr_state(context, ASR_STATE_IDLE);
-
- return AI_OK;
+ return ai_asr_service_stop(&context->asr_context);
}
asr_state_t ai_asr_get_state(ai_services_context_t *context)
return ASR_STATE_ERROR;
}
- return context->asr_state;
+ return ai_asr_service_get_state(&context->asr_context);
}
-/* ================================ Chatæ\9c\8då\8a¡æ\8e¥å\8f£å®\9eç\8e° ================================ */
+/* ================================ Chatæ\9c\8då\8a¡æ\8e¥å\8f£å\8c\85è£\85 ================================ */
ai_error_t ai_chat_configure(ai_services_context_t *context, const chat_config_t *config)
{
return AI_ERROR_NOT_INITIALIZED;
}
- memcpy(&context->chat_config, config, sizeof(chat_config_t));
- AI_LOGI("Chat configured: model=%s, temperature=%.2f, max_tokens=%d",
- config->model_name, config->temperature, config->max_tokens);
-
- return AI_OK;
+ return ai_chat_service_configure(&context->chat_context, config);
}
ai_error_t ai_chat_set_callbacks(ai_services_context_t *context,
return AI_ERROR_NOT_INITIALIZED;
}
- context->chat_response_cb = response_cb;
- context->chat_error_cb = error_cb;
- context->chat_state_cb = state_cb;
- context->user_data = user_data;
-
- AI_LOGI("Chat callbacks set");
- return AI_OK;
+ return ai_chat_service_set_callbacks(&context->chat_context, response_cb, error_cb, state_cb, user_data);
}
ai_error_t ai_chat_send_message(ai_services_context_t *context, const char *message, const char *session_id)
{
- if (context == NULL || message == NULL || strlen(message) == 0) {
+ if (context == NULL) {
return AI_ERROR_INVALID_PARAM;
}
return AI_ERROR_NOT_INITIALIZED;
}
- if (context->chat_state != CHAT_STATE_IDLE) {
- AI_LOGW("Chat busy, current state: %s", g_chat_state_names[context->chat_state]);
- return AI_ERROR_STATE_INVALID;
- }
-
- /* 使用提供的会话ID或当前会话ID */
+ /* 使用统一会话ID或提供的会话ID */
const char *use_session_id = session_id ? session_id : context->current_session_id;
- AI_LOGI("Sending chat message: %.50s... (session: %s)", message, use_session_id);
-
- /* 检查Chat连接状态 */
- ai_connection_state_t conn_state = ai_connection_manager_get_connection_state(AI_SERVICE_CHAT);
- if (conn_state != AI_CONN_STATE_CONNECTED) {
- AI_LOGE("Chat service not connected");
- return AI_ERROR_SERVICE_UNAVAILABLE;
- }
-
- /* 构建聊天消息 */
- char json_buffer[JSON_BUFFER_SIZE];
- ai_error_t ret = build_chat_message(message, use_session_id, &context->chat_config, json_buffer, sizeof(json_buffer));
- if (ret != AI_OK) {
- AI_LOGE("Failed to build chat message");
- return ret;
- }
-
- /* 发送消息 */
- change_chat_state(context, CHAT_STATE_SENDING);
-
- ret = ai_connection_manager_send_data(AI_SERVICE_CHAT, json_buffer, strlen(json_buffer));
- if (ret != AI_OK) {
- AI_LOGE("Failed to send chat message");
- change_chat_state(context, CHAT_STATE_ERROR);
- return ret;
- }
-
- /* 更新状态 */
- change_chat_state(context, CHAT_STATE_WAITING);
- strncpy(context->current_session_id, use_session_id, sizeof(context->current_session_id) - 1);
- context->last_activity_time = get_current_timestamp();
-
- return AI_OK;
+ return ai_chat_service_send_message(&context->chat_context, message, use_session_id);
}
chat_state_t ai_chat_get_state(ai_services_context_t *context)
return CHAT_STATE_ERROR;
}
- return context->chat_state;
+ return ai_chat_service_get_state(&context->chat_context);
}
-/* ================================ TTSæ\9c\8då\8a¡æ\8e¥å\8f£å®\9eç\8e° ================================ */
+/* ================================ TTSæ\9c\8då\8a¡æ\8e¥å\8f£å\8c\85è£\85 ================================ */
ai_error_t ai_tts_configure(ai_services_context_t *context, const tts_config_t *config)
{
return AI_ERROR_NOT_INITIALIZED;
}
- memcpy(&context->tts_config, config, sizeof(tts_config_t));
- AI_LOGI("TTS configured: voice=%s, volume=%d, speed=%d",
- ai_tts_get_voice_name(config->voice_type), config->volume, config->speed);
-
- return AI_OK;
+ return ai_tts_service_configure(&context->tts_context, config);
}
ai_error_t ai_tts_set_callbacks(ai_services_context_t *context,
return AI_ERROR_NOT_INITIALIZED;
}
- context->tts_result_cb = result_cb;
- context->tts_error_cb = error_cb;
- context->tts_state_cb = state_cb;
- context->user_data = user_data;
-
- AI_LOGI("TTS callbacks set");
- return AI_OK;
+ return ai_tts_service_set_callbacks(&context->tts_context, result_cb, error_cb, state_cb, user_data);
}
ai_error_t ai_tts_synthesize(ai_services_context_t *context, const char *text, const char *session_id)
{
- if (context == NULL || text == NULL || strlen(text) == 0) {
+ if (context == NULL) {
return AI_ERROR_INVALID_PARAM;
}
return AI_ERROR_NOT_INITIALIZED;
}
- if (context->tts_state != TTS_STATE_IDLE) {
- AI_LOGW("TTS busy, current state: %s", g_tts_state_names[context->tts_state]);
- return AI_ERROR_STATE_INVALID;
- }
-
- /* 使用提供的会话ID或当前会话ID */
+ /* 使用统一会话ID或提供的会话ID */
const char *use_session_id = session_id ? session_id : context->current_session_id;
- AI_LOGI("Starting TTS synthesis: %.50s... (session: %s)", text, use_session_id);
-
- /* 检查TTS连接状态 */
- ai_connection_state_t conn_state = ai_connection_manager_get_connection_state(AI_SERVICE_TTS);
- if (conn_state != AI_CONN_STATE_CONNECTED) {
- AI_LOGE("TTS service not connected");
- return AI_ERROR_SERVICE_UNAVAILABLE;
- }
-
- /* 构建TTS请求 */
- char json_buffer[JSON_BUFFER_SIZE];
- ai_error_t ret = build_tts_request(text, use_session_id, &context->tts_config, json_buffer, sizeof(json_buffer));
- if (ret != AI_OK) {
- AI_LOGE("Failed to build TTS request");
- return ret;
- }
-
- /* 发送请求 */
- change_tts_state(context, TTS_STATE_SYNTHESIZING);
-
- ret = ai_connection_manager_send_data(AI_SERVICE_TTS, json_buffer, strlen(json_buffer));
- if (ret != AI_OK) {
- AI_LOGE("Failed to send TTS request");
- change_tts_state(context, TTS_STATE_ERROR);
- return ret;
- }
-
- /* 更新状态 */
- strncpy(context->current_session_id, use_session_id, sizeof(context->current_session_id) - 1);
- context->last_activity_time = get_current_timestamp();
-
- return AI_OK;
+ return ai_tts_service_synthesize(&context->tts_context, text, use_session_id);
}
ai_error_t ai_tts_stop(ai_services_context_t *context)
return AI_ERROR_NOT_INITIALIZED;
}
- if (context->tts_state == TTS_STATE_IDLE) {
- return AI_OK; // 已经停止
- }
-
- AI_LOGI("Stopping TTS");
-
- /* 发送停止消息 */
- char stop_message[] = "{\"type\":\"stop\",\"session_id\":\"%s\"}";
- char json_buffer[JSON_BUFFER_SIZE];
- snprintf(json_buffer, sizeof(json_buffer), stop_message, context->current_session_id);
-
- ai_connection_manager_send_data(AI_SERVICE_TTS, json_buffer, strlen(json_buffer));
-
- /* 更新状态 */
- change_tts_state(context, TTS_STATE_IDLE);
-
- return AI_OK;
+ return ai_tts_service_stop(&context->tts_context);
}
tts_state_t ai_tts_get_state(ai_services_context_t *context)
return TTS_STATE_ERROR;
}
- return context->tts_state;
+ return ai_tts_service_get_state(&context->tts_context);
}
/* ================================ 辅助函数实现 ================================ */
void ai_asr_create_default_config(asr_config_t *config)
{
- if (config == NULL) {
- return;
- }
-
- memset(config, 0, sizeof(asr_config_t));
- config->enable_vad = true;
- config->enable_punctuation = true;
- config->enable_partial_results = true;
- config->silence_timeout_ms = 3000; // 3秒静音超时
- config->max_duration_ms = 30000; // 30秒最大录音时长
- strncpy(config->language, "zh-CN", sizeof(config->language) - 1);
+ ai_asr_service_create_default_config(config);
}
void ai_chat_create_default_config(chat_config_t *config)
{
- if (config == NULL) {
- return;
- }
-
- memset(config, 0, sizeof(chat_config_t));
- strncpy(config->model_name, "qwen-plus", sizeof(config->model_name) - 1);
- config->temperature = 0.7f;
- config->max_tokens = 512; // 适合LiteOS-M的较小值
- config->top_p = 0.9f;
- config->stream = true;
- config->timeout_ms = 15000; // 15秒超时
+ ai_chat_service_create_default_config(config);
}
void ai_tts_create_default_config(tts_config_t *config)
{
- if (config == NULL) {
- return;
- }
-
- memset(config, 0, sizeof(tts_config_t));
- config->voice_type = TTS_VOICE_XIAOYUN;
- config->volume = 80; // 80%音量
- config->speed = 50; // 正常语速
- config->pitch = 50; // 正常音调
- config->auto_play = true;
- config->timeout_ms = 10000; // 10秒超时
+ ai_tts_service_create_default_config(config);
}
void ai_services_generate_session_id(char *session_id, size_t buffer_size)
const char* ai_tts_get_voice_name(tts_voice_type_t voice_type)
{
- if (voice_type >= TTS_VOICE_COUNT) {
- return "unknown";
- }
-
- return g_voice_names[voice_type];
+ return ai_tts_service_get_voice_name(voice_type);
}
const char* ai_services_get_state_string(ai_service_type_t service_type, ai_services_context_t *context)
switch (service_type) {
case AI_SERVICE_ASR:
- return (context->asr_state < sizeof(g_asr_state_names)/sizeof(g_asr_state_names[0])) ?
- g_asr_state_names[context->asr_state] : "UNKNOWN";
+ return ai_asr_service_get_state_name(ai_asr_service_get_state(&context->asr_context));
case AI_SERVICE_CHAT:
- return (context->chat_state < sizeof(g_chat_state_names)/sizeof(g_chat_state_names[0])) ?
- g_chat_state_names[context->chat_state] : "UNKNOWN";
+ return ai_chat_service_get_state_name(ai_chat_service_get_state(&context->chat_context));
case AI_SERVICE_TTS:
- return (context->tts_state < sizeof(g_tts_state_names)/sizeof(g_tts_state_names[0])) ?
- g_tts_state_names[context->tts_state] : "UNKNOWN";
+ return ai_tts_service_get_state_name(ai_tts_service_get_state(&context->tts_context));
default:
return "UNKNOWN";
}
/* ================================ 内部函数实现 ================================ */
-static ai_error_t build_asr_start_message(const char *session_id, const asr_config_t *config, char *json_buffer, size_t buffer_size)
-{
- if (session_id == NULL || config == NULL || json_buffer == NULL) {
- return AI_ERROR_INVALID_PARAM;
- }
-
- /* 构建ASR启动消息 */
- int ret = snprintf(json_buffer, buffer_size,
- "{"
- "\"type\":\"start\","
- "\"session_id\":\"%s\","
- "\"config\":{"
- "\"language\":\"%s\","
- "\"enable_vad\":%s,"
- "\"enable_punctuation\":%s,"
- "\"enable_partial_results\":%s,"
- "\"silence_timeout_ms\":%d,"
- "\"max_duration_ms\":%d"
- "}"
- "}",
- session_id,
- config->language,
- config->enable_vad ? "true" : "false",
- config->enable_punctuation ? "true" : "false",
- config->enable_partial_results ? "true" : "false",
- config->silence_timeout_ms,
- config->max_duration_ms
- );
-
- if (ret < 0 || ret >= buffer_size) {
- AI_LOGE("JSON buffer too small for ASR start message");
- return AI_ERROR_BUFFER_OVERFLOW;
- }
-
- return AI_OK;
-}
-
-static ai_error_t build_chat_message(const char *message, const char *session_id, const chat_config_t *config, char *json_buffer, size_t buffer_size)
-{
- if (message == NULL || session_id == NULL || config == NULL || json_buffer == NULL) {
- return AI_ERROR_INVALID_PARAM;
- }
-
- /* 生成消息ID */
- char message_id[MESSAGE_ID_LENGTH + 1];
- generate_message_id(message_id, sizeof(message_id));
-
- /* 构建Chat消息 */
- int ret = snprintf(json_buffer, buffer_size,
- "{"
- "\"type\":\"chat\","
- "\"session_id\":\"%s\","
- "\"message_id\":\"%s\","
- "\"message\":{"
- "\"role\":\"user\","
- "\"content\":\"%s\""
- "},"
- "\"config\":{"
- "\"model\":\"%s\","
- "\"temperature\":%.2f,"
- "\"max_tokens\":%d,"
- "\"top_p\":%.2f,"
- "\"stream\":%s"
- "}"
- "}",
- session_id,
- message_id,
- message,
- config->model_name,
- config->temperature,
- config->max_tokens,
- config->top_p,
- config->stream ? "true" : "false"
- );
-
- if (ret < 0 || ret >= buffer_size) {
- AI_LOGE("JSON buffer too small for chat message");
- return AI_ERROR_BUFFER_OVERFLOW;
- }
-
- return AI_OK;
-}
-
-static ai_error_t build_tts_request(const char *text, const char *session_id, const tts_config_t *config, char *json_buffer, size_t buffer_size)
-{
- if (text == NULL || session_id == NULL || config == NULL || json_buffer == NULL) {
- return AI_ERROR_INVALID_PARAM;
- }
-
- /* 构建TTS请求 */
- int ret = snprintf(json_buffer, buffer_size,
- "{"
- "\"type\":\"synthesize\","
- "\"session_id\":\"%s\","
- "\"text\":\"%s\","
- "\"config\":{"
- "\"voice\":\"%s\","
- "\"volume\":%d,"
- "\"speed\":%d,"
- "\"pitch\":%d,"
- "\"auto_play\":%s"
- "}"
- "}",
- session_id,
- text,
- ai_tts_get_voice_name(config->voice_type),
- config->volume,
- config->speed,
- config->pitch,
- config->auto_play ? "true" : "false"
- );
-
- if (ret < 0 || ret >= buffer_size) {
- AI_LOGE("JSON buffer too small for TTS request");
- return AI_ERROR_BUFFER_OVERFLOW;
- }
-
- return AI_OK;
-}
-
-static void generate_message_id(char *message_id, size_t buffer_size)
-{
- if (message_id == NULL || buffer_size < MESSAGE_ID_LENGTH + 1) {
- return;
- }
-
- uint32_t timestamp = get_current_timestamp();
- uint16_t random = rand() & 0xFFFF;
-
- snprintf(message_id, buffer_size, "msg_%08x_%04x", timestamp, random);
-}
-
static uint32_t get_current_timestamp(void)
{
#ifndef __TEST_MODE__
#endif
}
-static ai_error_t change_asr_state(ai_services_context_t *context, asr_state_t new_state)
-{
- if (context == NULL) {
- return AI_ERROR_INVALID_PARAM;
- }
-
- asr_state_t old_state = context->asr_state;
- if (old_state != new_state) {
- context->asr_state = new_state;
-
- AI_LOGI("ASR state changed: %s -> %s",
- g_asr_state_names[old_state],
- g_asr_state_names[new_state]);
-
- /* 调用状态回调 */
- if (context->asr_state_cb != NULL) {
- context->asr_state_cb(old_state, new_state, context->user_data);
- }
- }
-
- return AI_OK;
-}
-
-static ai_error_t change_chat_state(ai_services_context_t *context, chat_state_t new_state)
+static void connection_event_handler(const ai_event_t *event, void *user_data)
{
- if (context == NULL) {
- return AI_ERROR_INVALID_PARAM;
+ if (event == NULL) {
+ return;
}
- chat_state_t old_state = context->chat_state;
- if (old_state != new_state) {
- context->chat_state = new_state;
-
- AI_LOGI("Chat state changed: %s -> %s",
- g_chat_state_names[old_state],
- g_chat_state_names[new_state]);
-
- /* 调用状态回调 */
- if (context->chat_state_cb != NULL) {
- context->chat_state_cb(old_state, new_state, context->user_data);
- }
+ ai_services_context_t *context = (ai_services_context_t*)user_data;
+ if (context == NULL || !context->is_initialized) {
+ return;
}
- return AI_OK;
-}
-
-static ai_error_t change_tts_state(ai_services_context_t *context, tts_state_t new_state)
-{
- if (context == NULL) {
- return AI_ERROR_INVALID_PARAM;
- }
+ AI_LOGI("Connection event: service=%d, type=%d", event->service, event->type);
- tts_state_t old_state = context->tts_state;
- if (old_state != new_state) {
- context->tts_state = new_state;
-
- AI_LOGI("TTS state changed: %s -> %s",
- g_tts_state_names[old_state],
- g_tts_state_names[new_state]);
-
- /* 调用状态回调 */
- if (context->tts_state_cb != NULL) {
- context->tts_state_cb(old_state, new_state, context->user_data);
- }
+ /* 根据事件类型和服务类型处理响应 */
+ switch (event->service) {
+ case AI_SERVICE_ASR:
+ if (event->type == AI_EVENT_DATA_RECEIVED && event->payload.data.data != NULL) {
+ ai_asr_service_handle_response(&context->asr_context, (const char*)event->payload.data.data);
+ }
+ break;
+
+ case AI_SERVICE_CHAT:
+ if (event->type == AI_EVENT_DATA_RECEIVED && event->payload.data.data != NULL) {
+ ai_chat_service_handle_response(&context->chat_context, (const char*)event->payload.data.data);
+ }
+ break;
+
+ case AI_SERVICE_TTS:
+ if (event->type == AI_EVENT_DATA_RECEIVED && event->payload.data.data != NULL) {
+ ai_tts_service_handle_response(&context->tts_context, (const char*)event->payload.data.data);
+ }
+ break;
+
+ default:
+ AI_LOGW("Unknown service type: %d", event->service);
+ break;
}
-
- return AI_OK;
}
\ No newline at end of file
--- /dev/null
+/**
+ * @file ai_tts_service.c
+ * @brief AI语音合成(TTS)服务实现
+ * @version 2.0
+ * @date 2024-01-20
+ */
+
+#include "ai_tts_service.h"
+#include "ai_connection_manager.h"
+#include "ai_memory_pool.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#ifndef __TEST_MODE__
+#include "wearable_log.h"
+#include "dev_authentication.h"
+#define AI_LOG_TAG "AI_TTS"
+#define AI_LOGI(fmt, ...) WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "[%s] " fmt, AI_LOG_TAG, ##__VA_ARGS__)
+#define AI_LOGE(fmt, ...) WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[%s] " fmt, AI_LOG_TAG, ##__VA_ARGS__)
+#define AI_LOGW(fmt, ...) WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "[%s] " fmt, AI_LOG_TAG, ##__VA_ARGS__)
+#else
+#define AI_LOGI(fmt, ...) printf("[AI_TTS] " fmt "\n", ##__VA_ARGS__)
+#define AI_LOGE(fmt, ...) printf("[AI_TTS] ERROR: " fmt "\n", ##__VA_ARGS__)
+#define AI_LOGW(fmt, ...) printf("[AI_TTS] WARN: " fmt "\n", ##__VA_ARGS__)
+#endif
+
+/* ================================ 内部常量定义 ================================ */
+
+#define JSON_BUFFER_SIZE 512 // JSON缓冲区大小
+
+/* 语音类型名称映射 */
+static const char* g_voice_names[TTS_VOICE_COUNT] = {
+ "xiaoyun", "xiaogang", "xiaomei", "xiaoli"
+};
+
+/* TTS状态名称映射 */
+static const char* g_tts_state_names[] = {
+ "IDLE", "SYNTHESIZING", "PLAYING", "COMPLETED", "ERROR"
+};
+
+/* ================================ 内部函数声明 ================================ */
+
+static uint32_t get_current_timestamp(void);
+static ai_error_t change_tts_state(tts_service_context_t *context, tts_state_t new_state);
+static ai_error_t parse_tts_response(const char *json_data, tts_result_t *result);
+
+/* ================================ 公共接口实现 ================================ */
+
+ai_error_t ai_tts_service_init(tts_service_context_t *context)
+{
+ if (context == NULL) {
+ AI_LOGE("Invalid context parameter");
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ AI_LOGI("Initializing TTS service...");
+
+ /* 初始化上下文 */
+ memset(context, 0, sizeof(tts_service_context_t));
+
+ /* 设置默认状态 */
+ context->state = TTS_STATE_IDLE;
+
+ /* 创建默认配置 */
+ ai_tts_service_create_default_config(&context->config);
+
+ /* 生成初始会话ID */
+ uint32_t timestamp = get_current_timestamp();
+ uint32_t random = rand();
+ snprintf(context->current_session_id, sizeof(context->current_session_id),
+ "tts_%08x_%04x", timestamp, random & 0xFFFF);
+
+ context->last_activity_time = get_current_timestamp();
+
+ AI_LOGI("TTS service initialized successfully");
+ return AI_OK;
+}
+
+ai_error_t ai_tts_service_destroy(tts_service_context_t *context)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ AI_LOGI("Destroying TTS service...");
+
+ /* 停止活动服务 */
+ if (context->state != TTS_STATE_IDLE) {
+ ai_tts_service_stop(context);
+ }
+
+ /* 重置上下文 */
+ memset(context, 0, sizeof(tts_service_context_t));
+
+ AI_LOGI("TTS service destroyed");
+ return AI_OK;
+}
+
+ai_error_t ai_tts_service_configure(tts_service_context_t *context, const tts_config_t *config)
+{
+ if (context == NULL || config == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ memcpy(&context->config, config, sizeof(tts_config_t));
+ AI_LOGI("TTS configured: voice=%s, volume=%d, speed=%d",
+ ai_tts_service_get_voice_name(config->voice_type), config->volume, config->speed);
+
+ return AI_OK;
+}
+
+ai_error_t ai_tts_service_set_callbacks(tts_service_context_t *context,
+ tts_result_callback_t result_cb,
+ tts_error_callback_t error_cb,
+ tts_state_callback_t state_cb,
+ void *user_data)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ context->result_cb = result_cb;
+ context->error_cb = error_cb;
+ context->state_cb = state_cb;
+ context->user_data = user_data;
+
+ AI_LOGI("TTS callbacks set");
+ return AI_OK;
+}
+
+ai_error_t ai_tts_service_synthesize(tts_service_context_t *context, const char *text, const char *session_id)
+{
+ if (context == NULL || text == NULL || strlen(text) == 0) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ if (context->state != TTS_STATE_IDLE) {
+ AI_LOGW("TTS busy, current state: %s", g_tts_state_names[context->state]);
+ return AI_ERROR_STATE_INVALID;
+ }
+
+ /* 使用提供的会话ID或当前会话ID */
+ const char *use_session_id = session_id ? session_id : context->current_session_id;
+
+ AI_LOGI("Starting TTS synthesis: %.50s... (session: %s)", text, use_session_id);
+
+ /* 检查TTS连接状态 */
+ ai_connection_state_t conn_state = ai_connection_manager_get_connection_state(AI_SERVICE_TTS);
+ if (conn_state != AI_CONN_STATE_CONNECTED) {
+ AI_LOGE("TTS service not connected");
+ return AI_ERROR_SERVICE_UNAVAILABLE;
+ }
+
+ /* 构建TTS请求 */
+ char json_buffer[JSON_BUFFER_SIZE];
+ ai_error_t ret = ai_tts_service_build_request(text, use_session_id, &context->config, json_buffer, sizeof(json_buffer));
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to build TTS request");
+ return ret;
+ }
+
+ /* 发送请求 */
+ change_tts_state(context, TTS_STATE_SYNTHESIZING);
+
+ ret = ai_connection_manager_send_data(AI_SERVICE_TTS, json_buffer, strlen(json_buffer));
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to send TTS request");
+ change_tts_state(context, TTS_STATE_ERROR);
+ return ret;
+ }
+
+ /* 更新状态 */
+ strncpy(context->current_session_id, use_session_id, sizeof(context->current_session_id) - 1);
+ context->last_activity_time = get_current_timestamp();
+
+ return AI_OK;
+}
+
+ai_error_t ai_tts_service_stop(tts_service_context_t *context)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ if (context->state == TTS_STATE_IDLE) {
+ return AI_OK; // 已经停止
+ }
+
+ AI_LOGI("Stopping TTS");
+
+ /* 构建停止消息 */
+ char json_buffer[JSON_BUFFER_SIZE];
+ ai_error_t ret = ai_tts_service_build_stop_message(context->current_session_id, json_buffer, sizeof(json_buffer));
+ if (ret == AI_OK) {
+ ai_connection_manager_send_data(AI_SERVICE_TTS, json_buffer, strlen(json_buffer));
+ }
+
+ /* 更新状态 */
+ change_tts_state(context, TTS_STATE_IDLE);
+
+ return AI_OK;
+}
+
+tts_state_t ai_tts_service_get_state(tts_service_context_t *context)
+{
+ if (context == NULL) {
+ return TTS_STATE_ERROR;
+ }
+
+ return context->state;
+}
+
+const char* ai_tts_service_get_state_name(tts_state_t state)
+{
+ if (state >= sizeof(g_tts_state_names) / sizeof(g_tts_state_names[0])) {
+ return "UNKNOWN";
+ }
+
+ return g_tts_state_names[state];
+}
+
+const char* ai_tts_service_get_voice_name(tts_voice_type_t voice_type)
+{
+ if (voice_type >= TTS_VOICE_COUNT) {
+ return "unknown";
+ }
+
+ return g_voice_names[voice_type];
+}
+
+void ai_tts_service_create_default_config(tts_config_t *config)
+{
+ if (config == NULL) {
+ return;
+ }
+
+ memset(config, 0, sizeof(tts_config_t));
+ config->voice_type = TTS_VOICE_XIAOYUN;
+ config->volume = 80; // 80%音量
+ config->speed = 50; // 正常语速
+ config->pitch = 50; // 正常音调
+ config->auto_play = true;
+ config->timeout_ms = 10000; // 10秒超时
+}
+
+ai_error_t ai_tts_service_handle_response(tts_service_context_t *context, const char *json_data)
+{
+ if (context == NULL || json_data == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ AI_LOGI("Handling TTS response: %.100s...", json_data);
+
+ /* 解析TTS响应 */
+ tts_result_t result;
+ ai_error_t ret = parse_tts_response(json_data, &result);
+ if (ret != AI_OK) {
+ AI_LOGE("Failed to parse TTS response");
+ change_tts_state(context, TTS_STATE_ERROR);
+ if (context->error_cb != NULL) {
+ context->error_cb(ret, "Failed to parse TTS response", context->user_data);
+ }
+ return ret;
+ }
+
+ /* 更新状态 */
+ if (result.is_final) {
+ if (context->config.auto_play && result.audio_data != NULL) {
+ change_tts_state(context, TTS_STATE_PLAYING);
+ // 这里应该调用音频播放接口
+ // play_audio(result.audio_data, result.audio_size);
+ change_tts_state(context, TTS_STATE_COMPLETED);
+ } else {
+ change_tts_state(context, TTS_STATE_COMPLETED);
+ }
+ }
+
+ /* 调用结果回调 */
+ if (context->result_cb != NULL) {
+ context->result_cb(&result, context->user_data);
+ }
+
+ context->last_activity_time = get_current_timestamp();
+
+ return AI_OK;
+}
+
+ai_error_t ai_tts_service_build_request(const char *text, const char *session_id, const tts_config_t *config,
+ char *json_buffer, size_t buffer_size)
+{
+ if (text == NULL || session_id == NULL || config == NULL || json_buffer == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ /* 构建TTS请求 */
+ int ret = snprintf(json_buffer, buffer_size,
+ "{"
+ "\"type\":\"synthesize\","
+ "\"session_id\":\"%s\","
+ "\"text\":\"%s\","
+ "\"config\":{"
+ "\"voice\":\"%s\","
+ "\"volume\":%d,"
+ "\"speed\":%d,"
+ "\"pitch\":%d,"
+ "\"auto_play\":%s"
+ "}"
+ "}",
+ session_id,
+ text,
+ ai_tts_service_get_voice_name(config->voice_type),
+ config->volume,
+ config->speed,
+ config->pitch,
+ config->auto_play ? "true" : "false"
+ );
+
+ if (ret < 0 || ret >= (int)buffer_size) {
+ AI_LOGE("JSON buffer too small for TTS request");
+ return AI_ERROR_BUFFER_OVERFLOW;
+ }
+
+ return AI_OK;
+}
+
+ai_error_t ai_tts_service_build_stop_message(const char *session_id, char *json_buffer, size_t buffer_size)
+{
+ if (session_id == NULL || json_buffer == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ int ret = snprintf(json_buffer, buffer_size,
+ "{\"type\":\"stop\",\"session_id\":\"%s\"}", session_id);
+
+ if (ret < 0 || ret >= (int)buffer_size) {
+ AI_LOGE("JSON buffer too small for TTS stop message");
+ return AI_ERROR_BUFFER_OVERFLOW;
+ }
+
+ return AI_OK;
+}
+
+/* ================================ 内部函数实现 ================================ */
+
+static uint32_t get_current_timestamp(void)
+{
+#ifndef __TEST_MODE__
+ return (uint32_t)(osKernelGetTickCount() * 1000 / osKernelGetTickFreq());
+#else
+ return (uint32_t)time(NULL);
+#endif
+}
+
+static ai_error_t change_tts_state(tts_service_context_t *context, tts_state_t new_state)
+{
+ if (context == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ tts_state_t old_state = context->state;
+ if (old_state != new_state) {
+ context->state = new_state;
+
+ AI_LOGI("TTS state changed: %s -> %s",
+ g_tts_state_names[old_state],
+ g_tts_state_names[new_state]);
+
+ /* 调用状态回调 */
+ if (context->state_cb != NULL) {
+ context->state_cb(old_state, new_state, context->user_data);
+ }
+ }
+
+ return AI_OK;
+}
+
+static ai_error_t parse_tts_response(const char *json_data, tts_result_t *result)
+{
+ if (json_data == NULL || result == NULL) {
+ return AI_ERROR_INVALID_PARAM;
+ }
+
+ /* 简化的JSON解析实现 */
+ memset(result, 0, sizeof(tts_result_t));
+
+ /* 在实际实现中,这里应该使用完整的JSON解析库 */
+ /* 这里只是一个简化的示例 */
+
+ /* 查找文本字段 */
+ const char *text_start = strstr(json_data, "\"text\":\"");
+ if (text_start != NULL) {
+ text_start += 8; // 跳过 "text":"
+ const char *text_end = strchr(text_start, '"');
+ if (text_end != NULL) {
+ size_t text_len = text_end - text_start;
+ if (text_len < sizeof(result->text)) {
+ strncpy(result->text, text_start, text_len);
+ result->text[text_len] = '\0';
+ }
+ }
+ }
+
+ /* 查找会话ID字段 */
+ const char *session_id_start = strstr(json_data, "\"session_id\":\"");
+ if (session_id_start != NULL) {
+ session_id_start += 14; // 跳过 "session_id":"
+ const char *session_id_end = strchr(session_id_start, '"');
+ if (session_id_end != NULL) {
+ size_t session_id_len = session_id_end - session_id_start;
+ if (session_id_len < sizeof(result->session_id)) {
+ strncpy(result->session_id, session_id_start, session_id_len);
+ result->session_id[session_id_len] = '\0';
+ }
+ }
+ }
+
+ /* 查找音频数据大小 */
+ const char *audio_size_start = strstr(json_data, "\"audio_size\":");
+ if (audio_size_start != NULL) {
+ result->audio_size = atoi(audio_size_start + 13);
+ }
+
+ /* 查找采样率 */
+ const char *sample_rate_start = strstr(json_data, "\"sample_rate\":");
+ if (sample_rate_start != NULL) {
+ result->sample_rate = atoi(sample_rate_start + 14);
+ } else {
+ result->sample_rate = 16000; // 默认采样率
+ }
+
+ /* 查找声道数 */
+ const char *channels_start = strstr(json_data, "\"channels\":");
+ if (channels_start != NULL) {
+ result->channels = atoi(channels_start + 11);
+ } else {
+ result->channels = 1; // 默认单声道
+ }
+
+ /* 查找位深度 */
+ const char *bits_start = strstr(json_data, "\"bits_per_sample\":");
+ if (bits_start != NULL) {
+ result->bits_per_sample = atoi(bits_start + 18);
+ } else {
+ result->bits_per_sample = 16; // 默认16位
+ }
+
+ /* 查找音频时长 */
+ const char *duration_start = strstr(json_data, "\"duration_ms\":");
+ if (duration_start != NULL) {
+ result->duration_ms = atoi(duration_start + 14);
+ }
+
+ /* 查找是否为最终结果 */
+ result->is_final = (strstr(json_data, "\"is_final\":true") != NULL) ||
+ (strstr(json_data, "\"status\":\"completed\"") != NULL);
+
+ /* 注意:这里没有实际解析音频数据,在实际实现中需要处理Base64编码的音频数据 */
+ result->audio_data = NULL;
+
+ AI_LOGI("Parsed TTS result: text='%s', size=%u, rate=%u, final=%s",
+ result->text, result->audio_size, result->sample_rate,
+ result->is_final ? "true" : "false");
+
+ return AI_OK;
+}
\ No newline at end of file