初版
This commit is contained in:
@@ -0,0 +1,297 @@
|
||||
#include "sparkdesk_main.h"
|
||||
#include "authentication.h"
|
||||
#include "stdlib.h"
|
||||
#include "app_config.h"
|
||||
#include "app_task.h"
|
||||
#include "system/timer.h"
|
||||
#include "app_main.h"
|
||||
#include "init.h"
|
||||
#include "key_event_deal.h"
|
||||
#include "device/device.h"
|
||||
#include "app_power_manage.h"
|
||||
#include "btstack/avctp_user.h"
|
||||
#include "asm/charge.h"
|
||||
#include "cJSON.h"
|
||||
#include "media/includes.h"
|
||||
#include "audio_config.h"
|
||||
#include "ai_interaction/ai_audio.h"
|
||||
#include "websocket_define.h"
|
||||
#include "ifly_socket.h"
|
||||
#include "ui/ui_api.h"
|
||||
#include "ifly_common.h"
|
||||
|
||||
#if TCFG_IFLYTEK_ENABLE
|
||||
|
||||
#define LOG_TAG_CONST NET_IFLY
|
||||
#define LOG_TAG "[IFLY_AI]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#ifdef TCFG_IFLYTEK_APP_ID
|
||||
#define APP_ID TCFG_IFLYTEK_APP_ID
|
||||
#else
|
||||
#define APP_ID "123"
|
||||
#endif
|
||||
|
||||
#define MAX_SPARKDESK_TOKENS ((MAX_SPARKDESK_LEN - 100) / 6) //1个tokens相当于1.5个汉字,1个汉字最大4个byte,即1个tokens约6个byte
|
||||
#define RECV_LAST_FRAME 2
|
||||
|
||||
typedef enum {
|
||||
IFLY_AI_STATUS_NULL = 0,
|
||||
IFLY_AI_STATUS_START, // 启动
|
||||
IFLY_AI_STATUS_SEND, // 数据已经发给socket
|
||||
IFLY_AI_STATUS_RECV, // 有接受到数据
|
||||
IFLY_AI_STATUS_RECV_END,// 接受完成
|
||||
IFLY_AI_STATUS_RECV_ERROR,// 接受错误
|
||||
IFLY_AI_STATUS_EXIT, // 已经退出
|
||||
} ifly_ai_status;
|
||||
|
||||
struct sparkdesk_info_t {
|
||||
u8 force_stop;
|
||||
u8 recv_finish;
|
||||
ifly_ai_status status;
|
||||
ifly_ai_param *param;
|
||||
};
|
||||
|
||||
static struct sparkdesk_info_t sparkdesk_info;
|
||||
static struct ifly_websocket_struct sparkdesk_socket;
|
||||
|
||||
//json解析函数_ai
|
||||
static void ifly_sparkdesk_recv_cb(u8 *j_str, u32 len, u8 type)
|
||||
{
|
||||
if (sparkdesk_info.force_stop) {
|
||||
return;
|
||||
}
|
||||
if (sparkdesk_info.status >= IFLY_AI_STATUS_RECV_END) {
|
||||
return;
|
||||
}
|
||||
cJSON *cjson_root = cJSON_Parse((char *)j_str);
|
||||
if (cjson_root == NULL) {
|
||||
log_error("cjson error...\r\n");
|
||||
if (sparkdesk_info.status <= IFLY_AI_STATUS_RECV_END) {
|
||||
sparkdesk_info.status = IFLY_AI_STATUS_RECV_ERROR;
|
||||
}
|
||||
return;
|
||||
}
|
||||
sparkdesk_info.status = IFLY_AI_STATUS_RECV;
|
||||
|
||||
cJSON *cjson_header = cJSON_GetObjectItem(cjson_root, "header");
|
||||
cJSON *cjson_status = cJSON_GetObjectItem(cjson_header, "status");
|
||||
cJSON *cjson_payload = cJSON_GetObjectItem(cjson_root, "payload");
|
||||
cJSON *cjson_choices = cJSON_GetObjectItem(cjson_payload, "choices");
|
||||
cJSON *cjson_text = cJSON_GetObjectItem(cjson_choices, "text");
|
||||
|
||||
int arr_size = cJSON_GetArraySize(cjson_text);
|
||||
cJSON *arr_item = cjson_text->child;
|
||||
if (!sparkdesk_info.param->ai_res) {
|
||||
return;
|
||||
}
|
||||
u32 ai_res_len = strlen(sparkdesk_info.param->ai_res);
|
||||
for (int i = 0; i < arr_size; i++) {
|
||||
cJSON *cjson_content = cJSON_GetObjectItem(arr_item, "content");
|
||||
char *cjson_str = cJSON_Print(cjson_content);
|
||||
u32 json_len = strlen(cjson_str);
|
||||
if ((ai_res_len + json_len + 1) > sparkdesk_info.param->ai_res_len) {
|
||||
log_error("len error\n");
|
||||
} else {
|
||||
strcpy(&sparkdesk_info.param->ai_res[ai_res_len], cjson_str);
|
||||
ai_res_len += json_len;
|
||||
}
|
||||
arr_item = arr_item->next;
|
||||
cJSON_free(cjson_str);
|
||||
}
|
||||
|
||||
int res_len = strlen(sparkdesk_info.param->ai_res);
|
||||
|
||||
str_remove_quote(sparkdesk_info.param->ai_res, res_len);
|
||||
|
||||
log_info("final res:%s\n", sparkdesk_info.param->ai_res);
|
||||
|
||||
if (cjson_status->valueint == RECV_LAST_FRAME) {
|
||||
sparkdesk_info.status = IFLY_AI_STATUS_RECV_END;
|
||||
sparkdesk_info.recv_finish = 1;
|
||||
sparkdesk_info.param->event_cb(IFLY_AI_EVT_RECV_OK, sparkdesk_info.param);
|
||||
}
|
||||
|
||||
cJSON_Delete(cjson_root);
|
||||
}
|
||||
|
||||
|
||||
//ai数据模块
|
||||
static char *ifly_sparkdesk_format_audio_data(void)
|
||||
{
|
||||
char *data_str = NULL;
|
||||
cJSON *cjson_test = NULL;
|
||||
cJSON *cjson_header = NULL;
|
||||
cJSON *cjson_parameter = NULL;
|
||||
cJSON *cjson_payload = NULL;
|
||||
cJSON *cjson_chat = NULL;
|
||||
cJSON *cjson_message = NULL;
|
||||
cJSON *cjson_text = NULL;
|
||||
cJSON *cjson_texts = NULL;
|
||||
|
||||
cjson_test = cJSON_CreateObject();
|
||||
cjson_header = cJSON_CreateObject();
|
||||
cjson_parameter = cJSON_CreateObject();
|
||||
cjson_payload = cJSON_CreateObject();
|
||||
cjson_chat = cJSON_CreateObject();
|
||||
cjson_message = cJSON_CreateObject();
|
||||
cjson_text = cJSON_CreateObject();
|
||||
|
||||
cJSON_AddStringToObject(cjson_header, "app_id", APP_ID);
|
||||
cJSON_AddItemToObject(cjson_test, "header", cjson_header);
|
||||
|
||||
cJSON_AddStringToObject(cjson_chat, "domain", "generalv3");
|
||||
cJSON_AddNumberToObject(cjson_chat, "max_tokens", MAX_SPARKDESK_TOKENS);
|
||||
cJSON_AddItemToObject(cjson_parameter, "chat", cjson_chat);
|
||||
cJSON_AddItemToObject(cjson_test, "parameter", cjson_parameter);
|
||||
|
||||
cjson_texts = cJSON_AddArrayToObject(cjson_message, "text");
|
||||
cJSON_AddStringToObject(cjson_text, "role", "user");
|
||||
cJSON_AddStringToObject(cjson_text, "content", sparkdesk_info.param->content);
|
||||
cJSON_AddItemToArray(cjson_texts, cjson_text);
|
||||
cJSON_AddItemToObject(cjson_payload, "message", cjson_message);
|
||||
cJSON_AddItemToObject(cjson_test, "payload", cjson_payload);
|
||||
|
||||
data_str = cJSON_Print(cjson_test);
|
||||
|
||||
cJSON_Delete(cjson_test);
|
||||
|
||||
return data_str;
|
||||
}
|
||||
|
||||
static bool ifly_sparkdesk_get_send(u8 **buf, u32 *len)
|
||||
{
|
||||
if (sparkdesk_info.force_stop) {
|
||||
log_info("ai task kill!\n");
|
||||
return false;
|
||||
}
|
||||
if (sparkdesk_info.status >= IFLY_AI_STATUS_RECV_END) {
|
||||
log_info("ai task kill!\n");
|
||||
return false;
|
||||
}
|
||||
if (sparkdesk_info.status < IFLY_AI_STATUS_SEND) {
|
||||
sparkdesk_info.status = IFLY_AI_STATUS_SEND;
|
||||
char *input_src_json = ifly_sparkdesk_format_audio_data();
|
||||
if (input_src_json == NULL) {
|
||||
log_error("get json err \n");
|
||||
return false;
|
||||
}
|
||||
*buf = (u8 *)input_src_json;
|
||||
*len = strlen(input_src_json);
|
||||
return true;
|
||||
}
|
||||
os_time_dly(2);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ifly_sparkdesk_event_cb(ifly_socket_event_enum evt, void *param)
|
||||
{
|
||||
switch (evt) {
|
||||
case IFLY_SOCKET_EVT_SEND_OK:
|
||||
cJSON_free(param);
|
||||
os_time_dly(5);
|
||||
break;
|
||||
case IFLY_SOCKET_EVT_SEND_ERROR:
|
||||
cJSON_free(param);
|
||||
break;
|
||||
case IFLY_SOCKET_EVT_INIT_OK:
|
||||
break;
|
||||
case IFLY_SOCKET_EVT_INIT_ERROR:
|
||||
case IFLY_SOCKET_EVT_HANSHACK_ERROR:
|
||||
case IFLY_SOCKET_EVT_ACCIDENT_END:
|
||||
case IFLY_SOCKET_EVT_END:
|
||||
case IFLY_SOCKET_EVT_FORCE_END:
|
||||
if ((evt != IFLY_SOCKET_EVT_END) && (evt != IFLY_SOCKET_EVT_FORCE_END)) {
|
||||
if (!sparkdesk_info.recv_finish) {
|
||||
sparkdesk_info.param->event_cb(IFLY_AI_EVT_NETWORK_FAIL, sparkdesk_info.param);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IFLY_SOCKET_EVT_EXIT:
|
||||
sparkdesk_info.status = IFLY_AI_STATUS_EXIT;
|
||||
sparkdesk_info.param->event_cb(IFLY_AI_EVT_EXIT, sparkdesk_info.param);
|
||||
if (sparkdesk_socket.auth) {
|
||||
printf("@@@@@@ free sparkdesk auth!!!\n");
|
||||
net_iflytek_free(sparkdesk_socket.auth);
|
||||
sparkdesk_socket.auth = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ifly_sparkdesk_start(ifly_ai_param *param)
|
||||
{
|
||||
memset(&sparkdesk_info, 0, sizeof(struct sparkdesk_info_t));
|
||||
memset(&sparkdesk_socket, 0, sizeof(struct ifly_websocket_struct));
|
||||
|
||||
#if TCFG_IFLYTEK_USE_PSRAM
|
||||
cJSON_Hooks hooks;
|
||||
hooks.malloc_fn = net_iflytek_malloc;
|
||||
hooks.free_fn = net_iflytek_free;
|
||||
cJSON_InitHooks(&hooks);
|
||||
#endif
|
||||
|
||||
sparkdesk_info.param = param;
|
||||
sparkdesk_socket.auth = (u8 *)ifly_authentication("wss://spark-api.xf-yun.com/v3.1/chat",
|
||||
"spark-api.xf-yun.com",
|
||||
"GET /v3.1/chat HTTP/1.1", 20);
|
||||
if (!sparkdesk_socket.auth) {
|
||||
sparkdesk_info.param->event_cb(IFLY_AI_EVT_NETWORK_FAIL, sparkdesk_info.param);
|
||||
return false;
|
||||
}
|
||||
|
||||
sparkdesk_socket.task_name = "ifly_ai";
|
||||
sparkdesk_socket.socket_mode = WEBSOCKET_MODE;
|
||||
sparkdesk_socket.recv_cb = ifly_sparkdesk_recv_cb;
|
||||
sparkdesk_socket.get_send = ifly_sparkdesk_get_send;
|
||||
sparkdesk_socket.event_cb = ifly_sparkdesk_event_cb;
|
||||
|
||||
sparkdesk_info.status = IFLY_AI_STATUS_START;
|
||||
|
||||
//创建链接
|
||||
bool ret = ifly_websocket_client_create(&sparkdesk_socket);
|
||||
if (ret == false) {
|
||||
sparkdesk_info.status = IFLY_AI_STATUS_NULL;
|
||||
net_iflytek_free(sparkdesk_socket.auth);
|
||||
sparkdesk_socket.auth = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ifly_sparkdesk_stop(u8 force_stop, u32 to_ms)
|
||||
{
|
||||
log_info("ai stop!\n");
|
||||
sparkdesk_info.force_stop = force_stop;
|
||||
while (sparkdesk_socket.auth) { // 结束时auth会自动释放
|
||||
os_time_dly(1);
|
||||
if (to_ms <= 10) {
|
||||
break;
|
||||
}
|
||||
to_ms -= 10;
|
||||
}
|
||||
if (to_ms < 1000) {
|
||||
to_ms = 1000;
|
||||
}
|
||||
sparkdesk_info.force_stop = 1;
|
||||
ifly_websocket_client_release(&sparkdesk_socket, to_ms);
|
||||
}
|
||||
|
||||
bool ifly_sparkdesk_is_work()
|
||||
{
|
||||
if ((sparkdesk_info.status != IFLY_AI_STATUS_NULL) && (sparkdesk_info.status != IFLY_AI_STATUS_EXIT)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user