This commit is contained in:
huxi
2025-12-03 11:12:34 +08:00
parent c23ae4f24c
commit bc195654bf
8163 changed files with 3799544 additions and 92 deletions
@@ -0,0 +1,98 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".intelligent_duer_auth.data.bss")
#pragma data_seg(".intelligent_duer_auth.data")
#pragma const_seg(".intelligent_duer_auth.text.const")
#pragma code_seg(".intelligent_duer_auth.text")
#endif
#include "duer_auth_algorithm.h"
#if INTELLIGENT_DUER
#define LOG_TAG_CONST NET_DUER
#define LOG_TAG "[DUER_AUTH]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define CST_OFFSET_SECONDS (28800) // 北京时间时差(秒)
#define UUID_BYTE_LENGTH (16) // UUID字节数
#define STRIPPED_UUID_LEN (32) // 无横杠UUID长度
#define RANDOM_PART_LEN (8) // 随机部分长度
#define CHARSET_SIZE (62) // 字符集大小
#define UUID_BUFFER_SIZE (33) // UUID缓冲区大小
#define REQUEST_ID_BUFFER_SIZE (60) // 请求ID缓冲区大小
#define RANDOM_STRING_LENGTH (6) // 随机字符串长度
// 生成随机字节函数
static void duer_get_random_bytes(unsigned char *buf, int nbytes)
{
while (nbytes--) {
*buf = random32(0);
++buf;
}
}
// 生成UUID字符串函数
static void generate_uuid_string_without_hyphens(char *uuid_buffer)
{
unsigned char rand_bytes[UUID_BYTE_LENGTH];
duer_get_random_bytes(rand_bytes, UUID_BYTE_LENGTH);
snprintf(uuid_buffer, UUID_BUFFER_SIZE,
"%02x%02x%02x%02x%02x%02x%02x%02x"
"%02x%02x%02x%02x%02x%02x%02x%02x",
rand_bytes[0], rand_bytes[1], rand_bytes[2], rand_bytes[3],
rand_bytes[4], rand_bytes[5], rand_bytes[6], rand_bytes[7],
rand_bytes[8], rand_bytes[9], rand_bytes[10], rand_bytes[11],
rand_bytes[12], rand_bytes[13], rand_bytes[14], rand_bytes[15]);
}
// 生成对话请求ID函数
void duer_generate_dialog_request_id(char *request_id)
{
struct sys_time curtime;
net_get_sys_time(&curtime);
// 时间参数日志
log_info("Current Time Parameters:");
log_info("Year: %d", curtime.year);
log_info("Month: %d", curtime.month);
log_info("Day: %d", curtime.day);
log_info("Hour: %d", curtime.hour);
log_info("Minute:%d", curtime.min);
log_info("Second:%d", curtime.sec);
// 时间戳计算
long long utc_seconds = timestamp_mytime_2_utc_sec(&curtime) - CST_OFFSET_SECONDS;
long long milliseconds = utc_seconds * 1000; // 转换为毫秒
log_info(">>>info: %s %d %s utc_s %lld utc_ms %lld \n", __FUNCTION__, __LINE__, __FILE__, utc_seconds, milliseconds);
char stripped_uuid[STRIPPED_UUID_LEN + 1] = {0};
generate_uuid_string_without_hyphens(stripped_uuid);
char random_part[RANDOM_PART_LEN + 1] = {0};
strncpy(random_part, stripped_uuid, RANDOM_PART_LEN);
snprintf(request_id, REQUEST_ID_BUFFER_SIZE, "%lld_%s", milliseconds, random_part);
}
// 生成随机字符串函数
void duer_generate_random_string(char *output, int length)
{
const char charset[] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const int charset_size = sizeof(charset) - 1; // 字符集实际大小
unsigned char rand_bytes[length];
duer_get_random_bytes(rand_bytes, length);
for (int i = 0; i < length; i++) {
output[i] = charset[rand_bytes[i] % charset_size];
}
output[length] = '\0'; // 确保字符串终止符
}
#endif
@@ -0,0 +1,21 @@
#ifndef _DUER_AUTH_ALGORITHM_H_
#define _DUER_AUTH_ALGORITHM_H_
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "sys_time.h"
#include "duer_common.h"
#include "app_config.h"
extern unsigned int random32(int type);
// 生成对话请求ID函数
extern void duer_generate_dialog_request_id(char *request_id);
// 生成6个字符的随机字符串
extern void duer_generate_random_string(char *output, int length);
#endif
@@ -0,0 +1,34 @@
#ifndef _DUER_COMMON_H_
#define _DUER_COMMON_H_
#include "system/includes.h"
#include "duer_auth_algorithm.h"
#include "duer_http_req.h"
#include "duer_socket.h"
#include "duer_json_parse.h"
#include "duer_json_request.h"
#include "duer_task.h"
#include "board_config.h"
#include "cJSON.h"
#include "net_includes.h"
#if TCFG_INTELLIGENT_DUER && TCFG_NETAPPLICATION_ENABLE
#define INTELLIGENT_DUER TCFG_INTELLIGENT_DUER
#else
#define INTELLIGENT_DUER 0
#endif
#define DUER_CLIENT_AK "xxxxxx"
#define DUER_CLIENT_SK "xxxxxx"
#define DUER_APP_PID "xxxxxx"
#define DUER_APP_FORMAT "opus"
#define DUER_APP_SAMPLE 16000
#endif
@@ -0,0 +1,62 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".intelligent_duer_network.data.bss")
#pragma data_seg(".intelligent_duer_network.data")
#pragma const_seg(".intelligent_duer_network.text.const")
#pragma code_seg(".intelligent_duer_network.text")
#endif
#include "duer_common.h"
#if INTELLIGENT_DUER
#define LOG_TAG_CONST NET_DUER
#define LOG_TAG "[DUER_HTTP_REQ]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
static TokenData *duer_get_access_token_child()
{
char url_buffer[256];
snprintf(url_buffer, sizeof(url_buffer),
"https://openapi.baidu.com/oauth/2.0/token?"
"grant_type=client_credentials&"
"client_id=%s&"
"client_secret=%s",
DUER_CLIENT_AK, DUER_CLIENT_SK);
char *response = NULL;
net_http_get_request(url_buffer, &response);
if (!response) {
log_error("API request failed\n");
return NULL;
}
TokenData *token = duer_parse_token_json(response);
net_interface_free(response); // 无论成功与否都要释放响应
if (!token) {
log_error("JSON parsing failed\n");
}
return token;
}
TokenData *duer_get_access_token()
{
TokenData *token = duer_get_access_token_child();
if (!token) {
log_error("Failed to get access token\n");
return NULL;
}
log_debug("refresh_token: %s\n", token->refresh_token);
log_debug("expires_in: %d\n", token->expires_in);
log_debug("session_key: %s\n", token->session_key);
log_debug("access_token: %s\n", token->access_token);
log_debug("scope: %s\n", token->scope);
log_debug("session_secret: %s\n", token->session_secret);
return token;
}
#endif
@@ -0,0 +1,13 @@
#ifndef _DUER_HTTP_REQ_H_
#define _DUER_HTTP_REQ_H_
#include "duer_common.h"
#include "duer_json_parse.h"
#include "time.h"
extern TokenData *duer_get_access_token();
#endif
@@ -0,0 +1,254 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".intelligent_duer_network.data.bss")
#pragma data_seg(".intelligent_duer_network.data")
#pragma const_seg(".intelligent_duer_network.text.const")
#pragma code_seg(".intelligent_duer_network.text")
#endif
#include "duer_socket.h"
#if INTELLIGENT_DUER
#define LOG_TAG_CONST NET_DUER
#define LOG_TAG "[DUER_SOCKET]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define OBJ_URL "ws://duer-kids.baidu.com/sandbox/sota/realtime_asr?sn=%s"
#define CUID_LEN 6
#define MAX_URL_LEN 256
#define MAX_TOKEN_LEN 256
static void task_kill_callback(char *buf);
static u8 force_kill = 0; //结束标志位
static void websockets_callback(u8 *buf, u32 len, u8 type)
{
log_info("wbs recv msg : %s\n", buf);
InsideRCResponse *response = duer_parse_inside_rc_json((char *)buf);
if (response &&
response->data &&
response->data->is_end == 1) {
force_kill = 1;
duer_free_inside_rc_response(response);
duer_netdownload_msg();
}
}
/*******************************************************************************
* Websocket Client api
*******************************************************************************/
static void websockets_client_reg(struct websocket_struct *websockets_info, char mode)
{
memset(websockets_info, 0, sizeof(struct websocket_struct));
websockets_info->_init = websockets_client_socket_init;
websockets_info->_exit = websockets_client_socket_exit;
websockets_info->_handshack = webcockets_client_socket_handshack;
websockets_info->_send = websockets_client_socket_send;
websockets_info->_recv_thread = websockets_client_socket_recv_thread;
websockets_info->_heart_thread = websockets_client_socket_heart_thread;
websockets_info->_recv_cb = websockets_callback;
websockets_info->_recv = NULL;
websockets_info->websocket_mode = mode;
}
static int websockets_client_init(struct websocket_struct *websockets_info, u8 *url, const char *origin_str, const char *user_agent_str)
{
websockets_info->ip_or_url = url;
websockets_info->origin_str = origin_str;
websockets_info->user_agent_str = user_agent_str;
websockets_info->recv_time_out = 1000;
//应用层和库的版本检测,结构体不一样则返回出错
int err = websockets_struct_check(sizeof(struct websocket_struct));
if (err == FALSE) {
return err;
}
return websockets_info->_init(websockets_info);
}
static int websockets_client_handshack(struct websocket_struct *websockets_info)
{
log_info("myurl %s \n", websockets_info->ip_or_url);
return websockets_info->_handshack(websockets_info);
}
static int websockets_client_send(struct websocket_struct *websockets_info, u8 *buf, int len, char type)
{
//SSL加密时一次发送数据不能超过16K,用户需要自己分包
return websockets_info->_send(websockets_info, buf, len, type);
}
static void websockets_client_exit(struct websocket_struct *websockets_info)
{
websockets_info->_exit(websockets_info);
}
/*******************************************************************************
* Websocket Client.c
* Just one example for test
*******************************************************************************/
static void websockets_client_main_thread(void *priv)
{
int err = 0;
char mode = WEBSOCKET_MODE;
char access_token[MAX_TOKEN_LEN] = {0};
char cuid_str[CUID_LEN + 1] = {0};
char url[MAX_URL_LEN] = {0};
duer_generate_random_string(cuid_str, sizeof(cuid_str) - 1);
log_debug("Generated CUID: %s", cuid_str);
if (snprintf(url, sizeof(url), OBJ_URL, cuid_str) >= sizeof(url)) {
log_error("URL buffer overflow");
return;
}
if (snprintf(access_token, sizeof(access_token), "%s", (char *)priv) >= sizeof(access_token)) {
log_error("Token buffer overflow");
return;
}
log_debug("WebSocket URL: %s, Access Token: %s", url, access_token);
const char *origin_str = "http://coolaf.com";
/* 0 . malloc buffer */
struct websocket_struct *websockets_info = net_interface_malloc(sizeof(struct websocket_struct));
if (!websockets_info) {
return;
}
/* 1 . register */
websockets_client_reg(websockets_info, mode);
/* 2 . init */
err = websockets_client_init(websockets_info, (u8 *)url, origin_str, NULL);
if (FALSE == err) {
log_error(" . ! Cilent websocket init error !!!\r\n");
goto exit_ws;
}
/* 3 . hanshack */
err = websockets_client_handshack(websockets_info);
if (FALSE == err) {
log_error(" . ! Handshake error !!!\r\n");
goto exit_ws;
}
log_debug(" . Handshake success \r\n");
/* 4 . CreateThread */
err = os_task_create(websockets_info->_heart_thread,
websockets_info,
19,
512,
0,
"websocket_client_heart");
if (err == 0) {
websockets_info->ping_thread_id = 1;
} else {
websockets_info->ping_thread_id = 0;
}
err = os_task_create(websockets_info->_recv_thread,
websockets_info,
18,
512,
0,
"websocket_client_recv");
if (err == 0) {
websockets_info->recv_thread_id = 1;
} else {
websockets_info->recv_thread_id = 0;
}
os_time_dly(100);
//server_log_id
char dialog_id[60];
duer_generate_dialog_request_id(dialog_id);// 生成对话请求ID
log_debug("Generated Dialog Request ID: %s\n", dialog_id);
//start_frame
char *start_str = duer_start_frame(DUER_CLIENT_AK, DUER_CLIENT_SK, DUER_CLIENT_AK, DUER_APP_PID,
cuid_str, DUER_APP_FORMAT, 1, DUER_APP_SAMPLE,
cuid_str, access_token, 1,
1, dialog_id, 1,
"1");
log_debug(">>>start_str %s \n", start_str);
err = websockets_client_send(websockets_info, (u8 *)start_str, strlen(start_str), WCT_TXTDATA);
if (FALSE == err) {
log_debug(" . ! send err !!!\r\n");
goto exit_ws;
}
os_time_dly(40);
/* char *finish = build_finish_frame(); */
net_rec_start();
u8 send_buf[40];
u32 buf_size = sizeof(send_buf);
while (1) {
int available = net_rec_data_len();
if (available == 0) {
os_time_dly(1);
continue;
}
int bytes_read = net_rec_read_data(send_buf, buf_size);
if (bytes_read == 0) {
os_time_dly(1);
continue;
}
printf("Read %d bytes from cbuf\n", bytes_read);
err = websockets_client_send(websockets_info, send_buf, bytes_read, WCT_BINDATA);
if (false == err) {
log_error(" . ! send err !!!\r\n");
goto exit_ws;
}
if (force_kill) {
goto exit_ws;
}
os_time_dly(10);
}
exit_ws:
/* 6 . exit */
net_record_stop_with_clean();
if (websockets_info->ping_thread_id) {
websockets_info->ping_kill_flag = 1;
}
if (websockets_info->recv_thread_id) {
websockets_info->recv_kill_flag = 1;
}
while (websockets_info->recv_kill_flag || websockets_info->ping_kill_flag) {
os_time_dly(10);
}
websockets_client_exit(websockets_info);
net_interface_free(websockets_info);
net_interface_free(start_str);
/* my_free(finish); */
int msg[5];
msg[0] = (int)task_kill_callback;
msg[1] = 1;
msg[2] = (int)os_current_task();
err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
os_time_dly(-1);
}
static void task_kill_callback(char *buf)
{
log_info("[msg]>>>>>>>>>>>*buf=%s", buf);
task_kill(buf);
}
void duer_websocket_client_thread_create(void *priv)
{
net_url_list_init();
force_kill = 0;
os_task_create(websockets_client_main_thread,
priv,
15,
512 * 5,
0,
"websockets_client_main");
}
#endif
@@ -0,0 +1,16 @@
#ifndef _DUER_SOCKET_H_
#define _DUER_SOCKET_H_
#include "websocket_api.h"
#include "duer_common.h"
extern void duer_websocket_client_thread_create(void *priv);
extern int task_kill(const char *name);
#endif
@@ -0,0 +1,488 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".intelligent_duer_parse.data.bss")
#pragma data_seg(".intelligent_duer_parse.data")
#pragma const_seg(".intelligent_duer_parse.text.const")
#pragma code_seg(".intelligent_duer_parse.text")
#endif
#include "duer_common.h"
#if INTELLIGENT_DUER
#define LOG_TAG_CONST NET_DUER
#define LOG_TAG "[DUER_JSON_PARSE]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
TokenData *duer_parse_token_json(const char *json_str)
{
cJSON *root = cJSON_Parse(json_str);
if (!root) {
log_error("JSON parse error:\n");
return NULL;
}
TokenData *data = (TokenData *)net_interface_malloc(sizeof(TokenData));
if (!data) {
log_error("Memory allocation failed");
cJSON_Delete(root);
return NULL;
}
memset(data, 0, sizeof(TokenData));
cJSON *item;
if ((item = cJSON_GetObjectItem(root, "refresh_token")) && cJSON_IsString(item)) {
data->refresh_token = strdup(item->valuestring);
}
if ((item = cJSON_GetObjectItem(root, "expires_in")) && cJSON_IsNumber(item)) {
data->expires_in = item->valueint;
}
if ((item = cJSON_GetObjectItem(root, "session_key")) && cJSON_IsString(item)) {
data->session_key = strdup(item->valuestring);
}
if ((item = cJSON_GetObjectItem(root, "access_token")) && cJSON_IsString(item)) {
data->access_token = strdup(item->valuestring);
}
if ((item = cJSON_GetObjectItem(root, "scope")) && cJSON_IsString(item)) {
data->scope = strdup(item->valuestring);
}
if ((item = cJSON_GetObjectItem(root, "session_secret")) && cJSON_IsString(item)) {
data->session_secret = strdup(item->valuestring);
}
cJSON_Delete(root);
return data;
}
void duer_free_token_data(TokenData *data)
{
if (data) {
net_interface_free(data->refresh_token);
net_interface_free(data->session_key);
net_interface_free(data->access_token);
net_interface_free(data->scope);
net_interface_free(data->session_secret);
net_interface_free(data);
}
}
InsideRCResponse *duer_parse_inside_rc_json(const char *json_string)
{
InsideRCResponse *response = net_interface_calloc(1, sizeof(InsideRCResponse));
if (!response) {
return NULL;
}
cJSON *root = cJSON_Parse(json_string);
if (!root) {
log_error("Error parsing JSON: %s\n", cJSON_GetErrorPtr());
net_interface_free(response);
return NULL;
}
cJSON *type = cJSON_GetObjectItem(root, "type");
if (cJSON_IsString(type)) {
response->type = strdup(type->valuestring);
}
if (!response->type || strcmp(response->type, "inside_rc") != 0) {
cJSON_Delete(root);
return response;
}
cJSON *status = cJSON_GetObjectItem(root, "status");
if (cJSON_IsString(status)) {
response->status = strdup(status->valuestring);
}
cJSON *sn = cJSON_GetObjectItem(root, "sn");
if (cJSON_IsString(sn)) {
response->sn = strdup(sn->valuestring);
}
cJSON *end = cJSON_GetObjectItem(root, "end");
if (cJSON_IsNumber(end)) {
response->end = end->valueint;
}
cJSON *data_obj = cJSON_GetObjectItem(root, "data");
if (data_obj && cJSON_IsObject(data_obj)) {
response->data = net_interface_calloc(1, sizeof(Data));
if (!response->data) {
cJSON_Delete(root);
duer_free_inside_rc_response(response);
return NULL;
}
cJSON *code = cJSON_GetObjectItem(data_obj, "code");
if (cJSON_IsNumber(code)) {
response->data->code = code->valueint;
}
cJSON *msg = cJSON_GetObjectItem(data_obj, "msg");
if (cJSON_IsString(msg)) {
response->data->msg = strdup(msg->valuestring);
}
cJSON *logid = cJSON_GetObjectItem(data_obj, "logid");
if (cJSON_IsString(logid)) {
response->data->logid = strdup(logid->valuestring);
}
cJSON *qid = cJSON_GetObjectItem(data_obj, "qid");
if (cJSON_IsString(qid)) {
response->data->qid = strdup(qid->valuestring);
}
cJSON *is_end = cJSON_GetObjectItem(data_obj, "is_end");
if (cJSON_IsNumber(is_end)) {
response->data->is_end = is_end->valueint;
}
cJSON *need_clear_history = cJSON_GetObjectItem(data_obj, "need_clear_history");
if (cJSON_IsNumber(need_clear_history)) {
response->data->need_clear_history = need_clear_history->valueint;
}
cJSON *assistant_answer = cJSON_GetObjectItem(data_obj, "assistant_answer");
if (assistant_answer) {
response->data->assistant_answer = net_interface_calloc(1, sizeof(AssistantAnswer));
if (response->data->assistant_answer) {
if (cJSON_IsString(assistant_answer)) {
cJSON *aa_root = cJSON_Parse(assistant_answer->valuestring);
if (aa_root) {
cJSON *content = cJSON_GetObjectItem(aa_root, "content");
if (cJSON_IsString(content)) {
response->data->assistant_answer->content = strdup(content->valuestring);
}
cJSON *nlu = cJSON_GetObjectItem(aa_root, "nlu");
if (cJSON_IsString(nlu)) {
response->data->assistant_answer->nlu = strdup(nlu->valuestring);
}
cJSON *aa_is_end = cJSON_GetObjectItem(aa_root, "is_end");
if (cJSON_IsNumber(aa_is_end)) {
response->data->assistant_answer->is_end = aa_is_end->valueint;
}
cJSON *metadata = cJSON_GetObjectItem(aa_root, "metadata");
if (metadata && cJSON_IsObject(metadata)) {
response->data->assistant_answer->metadata = net_interface_calloc(1, sizeof(Metadata));
if (response->data->assistant_answer->metadata) {
cJSON *multi_round_info = cJSON_GetObjectItem(metadata, "multi_round_info");
if (multi_round_info && cJSON_IsObject(multi_round_info)) {
response->data->assistant_answer->metadata->multi_round_info = net_interface_calloc(1, sizeof(MultiRoundInfo));
if (response->data->assistant_answer->metadata->multi_round_info) {
cJSON *is_in_multi = cJSON_GetObjectItem(multi_round_info, "is_in_multi");
if (cJSON_IsBool(is_in_multi)) {
response->data->assistant_answer->metadata->multi_round_info->is_in_multi = is_in_multi->valueint;
}
cJSON *target_bot_id = cJSON_GetObjectItem(multi_round_info, "target_bot_id");
if (cJSON_IsString(target_bot_id)) {
response->data->assistant_answer->metadata->multi_round_info->target_bot_id = strdup(target_bot_id->valuestring);
}
cJSON *intent = cJSON_GetObjectItem(multi_round_info, "intent");
if (cJSON_IsString(intent)) {
response->data->assistant_answer->metadata->multi_round_info->intent = strdup(intent->valuestring);
}
}
}
}
}
cJSON_Delete(aa_root);
} else {
response->data->assistant_answer->content = strdup(assistant_answer->valuestring);
}
} else if (cJSON_IsObject(assistant_answer)) {
cJSON *content = cJSON_GetObjectItem(assistant_answer, "content");
if (cJSON_IsString(content)) {
response->data->assistant_answer->content = strdup(content->valuestring);
}
cJSON *nlu = cJSON_GetObjectItem(assistant_answer, "nlu");
if (cJSON_IsString(nlu)) {
response->data->assistant_answer->nlu = strdup(nlu->valuestring);
}
cJSON *aa_is_end = cJSON_GetObjectItem(assistant_answer, "is_end");
if (cJSON_IsNumber(aa_is_end)) {
response->data->assistant_answer->is_end = aa_is_end->valueint;
}
cJSON *metadata = cJSON_GetObjectItem(assistant_answer, "metadata");
if (metadata && cJSON_IsObject(metadata)) {
response->data->assistant_answer->metadata = net_interface_calloc(1, sizeof(Metadata));
if (response->data->assistant_answer->metadata) {
cJSON *multi_round_info = cJSON_GetObjectItem(metadata, "multi_round_info");
if (multi_round_info && cJSON_IsObject(multi_round_info)) {
response->data->assistant_answer->metadata->multi_round_info = net_interface_calloc(1, sizeof(MultiRoundInfo));
if (response->data->assistant_answer->metadata->multi_round_info) {
cJSON *is_in_multi = cJSON_GetObjectItem(multi_round_info, "is_in_multi");
if (cJSON_IsBool(is_in_multi)) {
response->data->assistant_answer->metadata->multi_round_info->is_in_multi = is_in_multi->valueint;
}
cJSON *target_bot_id = cJSON_GetObjectItem(multi_round_info, "target_bot_id");
if (cJSON_IsString(target_bot_id)) {
response->data->assistant_answer->metadata->multi_round_info->target_bot_id = strdup(target_bot_id->valuestring);
}
cJSON *intent = cJSON_GetObjectItem(multi_round_info, "intent");
if (cJSON_IsString(intent)) {
response->data->assistant_answer->metadata->multi_round_info->intent = strdup(intent->valuestring);
}
}
}
}
}
}
}
}
cJSON *data_array = cJSON_GetObjectItem(data_obj, "data");
if (data_array && cJSON_IsArray(data_array)) {
int array_size = cJSON_GetArraySize(data_array);
response->data->data_items_count = array_size;
if (array_size > 0) {
response->data->data_items = net_interface_calloc(array_size, sizeof(DataItem *));
if (!response->data->data_items) {
cJSON_Delete(root);
duer_free_inside_rc_response(response);
return NULL;
}
for (int i = 0; i < array_size; i++) {
DataItem *item = net_interface_calloc(1, sizeof(DataItem));
if (!item) {
continue;
}
response->data->data_items[i] = item;
cJSON *array_item = cJSON_GetArrayItem(data_array, i);
cJSON *header = cJSON_GetObjectItem(array_item, "header");
if (header && cJSON_IsObject(header)) {
item->header = net_interface_calloc(1, sizeof(Header));
if (item->header) {
cJSON *namespace = cJSON_GetObjectItem(header, "namespace");
if (cJSON_IsString(namespace)) {
item->header->namespace = strdup(namespace->valuestring);
}
cJSON *name = cJSON_GetObjectItem(header, "name");
if (cJSON_IsString(name)) {
item->header->name = strdup(name->valuestring);
}
cJSON *messageId = cJSON_GetObjectItem(header, "messageId");
if (cJSON_IsString(messageId)) {
item->header->messageId = strdup(messageId->valuestring);
}
cJSON *dialogRequestId = cJSON_GetObjectItem(header, "dialogRequestId");
if (cJSON_IsString(dialogRequestId)) {
item->header->dialogRequestId = strdup(dialogRequestId->valuestring);
}
}
}
cJSON *payload = cJSON_GetObjectItem(array_item, "payload");
if (payload && cJSON_IsObject(payload)) {
item->payload = net_interface_calloc(1, sizeof(Payload));
if (item->payload) {
cJSON *rolling = cJSON_GetObjectItem(payload, "rolling");
if (cJSON_IsBool(rolling)) {
item->payload->rolling = rolling->valueint;
}
cJSON *text = cJSON_GetObjectItem(payload, "text");
if (cJSON_IsString(text)) {
item->payload->text = strdup(text->valuestring);
}
cJSON *content = cJSON_GetObjectItem(payload, "content");
if (cJSON_IsString(content)) {
item->payload->content = strdup(content->valuestring);
}
cJSON *format = cJSON_GetObjectItem(payload, "format");
if (cJSON_IsString(format)) {
item->payload->format = strdup(format->valuestring);
}
cJSON *token = cJSON_GetObjectItem(payload, "token");
if (cJSON_IsString(token)) {
item->payload->token = strdup(token->valuestring);
}
cJSON *url = cJSON_GetObjectItem(payload, "url");
if (cJSON_IsString(url)) {
item->payload->url = strdup(url->valuestring);
net_url_set(item->payload->url);
net_print_urls();
}
cJSON *type = cJSON_GetObjectItem(payload, "type");
if (cJSON_IsString(type)) {
item->payload->type = strdup(type->valuestring);
}
cJSON *answer = cJSON_GetObjectItem(payload, "answer");
if (cJSON_IsString(answer)) {
item->payload->answer = strdup(answer->valuestring);
}
cJSON *id = cJSON_GetObjectItem(payload, "id");
if (cJSON_IsString(id)) {
item->payload->id = strdup(id->valuestring);
}
cJSON *index = cJSON_GetObjectItem(payload, "index");
if (cJSON_IsNumber(index)) {
item->payload->index = index->valueint;
}
cJSON *payload_is_end = cJSON_GetObjectItem(payload, "is_end");
if (cJSON_IsNumber(payload_is_end)) {
item->payload->payload_is_end = payload_is_end->valueint;
}
cJSON *part = cJSON_GetObjectItem(payload, "part");
if (cJSON_IsString(part)) {
item->payload->part = strdup(part->valuestring);
}
cJSON *reasoning_part = cJSON_GetObjectItem(payload, "reasoning_part");
if (cJSON_IsString(reasoning_part)) {
item->payload->reasoning_part = strdup(reasoning_part->valuestring);
}
cJSON *tts = cJSON_GetObjectItem(payload, "tts");
if (cJSON_IsString(tts)) {
item->payload->tts = strdup(tts->valuestring);
}
cJSON *timeoutInMilliseconds = cJSON_GetObjectItem(payload, "timeoutInMilliseconds");
if (cJSON_IsNumber(timeoutInMilliseconds)) {
item->payload->timeoutInMilliseconds = timeoutInMilliseconds->valueint;
}
}
}
cJSON *property = cJSON_GetObjectItem(array_item, "property");
if (property && cJSON_IsObject(property)) {
cJSON *serviceCategory = cJSON_GetObjectItem(property, "serviceCategory");
if (cJSON_IsString(serviceCategory)) {
item->serviceCategory = strdup(serviceCategory->valuestring);
}
}
}
}
}
cJSON *lj_thread_id = cJSON_GetObjectItem(data_obj, "lj_thread_id");
if (cJSON_IsString(lj_thread_id)) {
response->data->lj_thread_id = strdup(lj_thread_id->valuestring);
}
cJSON *ab_conversation_id = cJSON_GetObjectItem(data_obj, "ab_conversation_id");
if (cJSON_IsString(ab_conversation_id)) {
response->data->ab_conversation_id = strdup(ab_conversation_id->valuestring);
}
cJSON *xiaoice_session_id = cJSON_GetObjectItem(data_obj, "xiaoice_session_id");
if (cJSON_IsString(xiaoice_session_id)) {
response->data->xiaoice_session_id = strdup(xiaoice_session_id->valuestring);
}
cJSON *dialog_request_id = cJSON_GetObjectItem(data_obj, "dialog_request_id");
if (cJSON_IsString(dialog_request_id)) {
response->data->dialog_request_id = strdup(dialog_request_id->valuestring);
}
}
cJSON_Delete(root);
return response;
}
void duer_free_inside_rc_response(InsideRCResponse *response)
{
if (!response) {
return;
}
net_interface_free(response->status);
net_interface_free(response->type);
net_interface_free(response->sn);
if (response->data) {
net_interface_free(response->data->msg);
net_interface_free(response->data->logid);
net_interface_free(response->data->qid);
net_interface_free(response->data->lj_thread_id);
net_interface_free(response->data->ab_conversation_id);
net_interface_free(response->data->xiaoice_session_id);
net_interface_free(response->data->dialog_request_id);
if (response->data->assistant_answer) {
net_interface_free(response->data->assistant_answer->content);
net_interface_free(response->data->assistant_answer->nlu);
if (response->data->assistant_answer->metadata) {
if (response->data->assistant_answer->metadata->multi_round_info) {
net_interface_free(response->data->assistant_answer->metadata->multi_round_info->target_bot_id);
net_interface_free(response->data->assistant_answer->metadata->multi_round_info->intent);
net_interface_free(response->data->assistant_answer->metadata->multi_round_info);
}
net_interface_free(response->data->assistant_answer->metadata);
}
net_interface_free(response->data->assistant_answer);
}
if (response->data->data_items) {
for (int i = 0; i < response->data->data_items_count; i++) {
DataItem *item = response->data->data_items[i];
if (!item) {
continue;
}
if (item->header) {
net_interface_free(item->header->namespace);
net_interface_free(item->header->name);
net_interface_free(item->header->messageId);
net_interface_free(item->header->dialogRequestId);
net_interface_free(item->header);
}
if (item->payload) {
net_interface_free(item->payload->text);
net_interface_free(item->payload->content);
net_interface_free(item->payload->format);
net_interface_free(item->payload->token);
net_interface_free(item->payload->url);
net_interface_free(item->payload->type);
net_interface_free(item->payload->answer);
net_interface_free(item->payload->id);
net_interface_free(item->payload->part);
net_interface_free(item->payload->reasoning_part);
net_interface_free(item->payload->tts);
net_interface_free(item->payload);
}
net_interface_free(item->serviceCategory);
net_interface_free(item);
}
net_interface_free(response->data->data_items);
}
net_interface_free(response->data);
}
net_interface_free(response);
}
#endif
@@ -0,0 +1,100 @@
#ifndef _DUER_JSON_PARSE_H_
#define _DUER_JSON_PARSE_H_
#include "duer_common.h"
#include <string.h>
typedef struct {
char *refresh_token;
int expires_in;
char *session_key;
char *access_token;
char *scope;
char *session_secret;
} TokenData;
extern TokenData *duer_parse_token_json(const char *json_str);
extern void duer_free_token_data(TokenData *data);
typedef struct {
char *namespace;
char *name;
char *messageId;
char *dialogRequestId;
} Header;
typedef struct {
char *text;
char *content;
char *format;
char *token;
char *url;
int rolling;
char *type;
char *answer;
char *id;
int index;
int payload_is_end;
char *part;
char *reasoning_part;
char *tts;
int timeoutInMilliseconds;
} Payload;
typedef struct {
Header *header;
Payload *payload;
char *serviceCategory;
} DataItem;
typedef struct {
int is_in_multi;
char *target_bot_id;
char *intent;
} MultiRoundInfo;
typedef struct {
MultiRoundInfo *multi_round_info;
} Metadata;
typedef struct {
char *content;
char *nlu;
Metadata *metadata;
int is_end;
} AssistantAnswer;
typedef struct {
int code;
char *msg;
char *logid;
char *qid;
int is_end;
AssistantAnswer *assistant_answer;
int need_clear_history;
DataItem **data_items;
int data_items_count;
char *lj_thread_id;
char *ab_conversation_id;
char *xiaoice_session_id;
char *dialog_request_id;
} Data;
typedef struct {
char *status;
char *type;
Data *data;
char *sn;
int end;
} InsideRCResponse;
extern InsideRCResponse *duer_parse_inside_rc_json(const char *json_string);
extern void duer_free_inside_rc_response(InsideRCResponse *response);
#endif
@@ -0,0 +1,119 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".intelligent_duer_parse.data.bss")
#pragma data_seg(".intelligent_duer_parse.data")
#pragma const_seg(".intelligent_duer_parse.text.const")
#pragma code_seg(".intelligent_duer_parse.text")
#endif
#include "duer_common.h"
#include "cJSON.h"
#if INTELLIGENT_DUER
char *duer_start_frame(const char *appid, const char *appkey, const char *client_id, const char *pid,
const char *cuid, const char *format, int support_dcs, int sample,
const char *user_id, const char *access_token, int support_tts,
int support_text2dcs, const char *dialog_request_id, int access_rc,
const char *rc_version)
{
cJSON *root = cJSON_CreateObject();
if (root == NULL) {
return NULL;
}
cJSON_AddItemToObject(root, "type", cJSON_CreateString("start"));
cJSON *data = cJSON_CreateObject();
if (data == NULL) {
cJSON_Delete(root);
return NULL;
}
cJSON_AddItemToObject(root, "data", data);
cJSON_AddItemToObject(data, "appid", cJSON_CreateString(appid));
cJSON_AddItemToObject(data, "appkey", cJSON_CreateString(appkey));
cJSON_AddItemToObject(data, "client_id", cJSON_CreateString(client_id));
cJSON_AddItemToObject(data, "pid", cJSON_CreateString(pid));
cJSON_AddItemToObject(data, "cuid", cJSON_CreateString(cuid));
cJSON_AddItemToObject(data, "format", cJSON_CreateString(format));
char support_dcs_str[32];
snprintf(support_dcs_str, sizeof(support_dcs_str), "%d", support_dcs);
cJSON_AddRawToObject(data, "support_dcs", support_dcs_str);
char sample_str[32];
snprintf(sample_str, sizeof(sample_str), "%d", sample);
cJSON_AddRawToObject(data, "sample", sample_str);
cJSON_AddItemToObject(data, "user_id", cJSON_CreateString(user_id));
cJSON_AddItemToObject(data, "access_token", cJSON_CreateString(access_token));
cJSON_AddItemToObject(data, "support_tts", cJSON_CreateBool(support_tts));
cJSON_AddItemToObject(data, "support_text2dcs", cJSON_CreateBool(support_text2dcs));
cJSON_AddItemToObject(data, "dialog_request_id", cJSON_CreateString(dialog_request_id));
cJSON_AddItemToObject(data, "access_rc", cJSON_CreateBool(access_rc));
cJSON_AddItemToObject(data, "rc_version", cJSON_CreateString(rc_version));
char *json_string = cJSON_PrintUnformatted(root);
cJSON_Delete(root);
return json_string;
}
char *build_finish_frame()
{
cJSON *root = cJSON_CreateObject();
if (!root) {
return NULL;
}
cJSON_AddStringToObject(root, "type", "finish");
char *json_str = cJSON_PrintUnformatted(root);
cJSON_Delete(root);
return json_str;
}
char *duer_text_info_frame(const char *CUID,
const char *current_dialog_request_id,
const char *text_query)
{
cJSON *root = cJSON_CreateObject();
if (!root) {
return NULL;
}
cJSON *event = cJSON_CreateObject();
cJSON *header = cJSON_CreateObject();
cJSON *payload = cJSON_CreateObject();
cJSON *initiator = cJSON_CreateObject();
if (!event || !header || !payload || !initiator) {
cJSON_Delete(root);
if (event) {
cJSON_Delete(event);
}
if (header) {
cJSON_Delete(header);
}
if (payload) {
cJSON_Delete(payload);
}
if (initiator) {
cJSON_Delete(initiator);
}
return NULL;
}
cJSON_AddStringToObject(root, "status", "ok");
cJSON_AddStringToObject(root, "type", "dcs_decide");
cJSON_AddStringToObject(root, "sn", CUID ? CUID : "");
cJSON_AddNumberToObject(root, "end", 1);
cJSON_AddItemToObject(root, "event", event);
cJSON_AddItemToObject(event, "header", header);
cJSON_AddItemToObject(event, "payload", payload);
cJSON_AddStringToObject(header, "namespace", "ai.dueros.device_interface.screen");
cJSON_AddStringToObject(header, "name", "LinkClicked");
cJSON_AddStringToObject(header, "dialogRequestId", current_dialog_request_id ? current_dialog_request_id : "");
char url[1024];
if (text_query) {
snprintf(url, sizeof(url), "dueros://server.dueros.ai/query?q=%s", text_query);
} else {
snprintf(url, sizeof(url), "dueros://server.dueros.ai/query");
}
cJSON_AddStringToObject(payload, "url", url);
cJSON_AddItemToObject(payload, "initiator", initiator);
cJSON_AddStringToObject(initiator, "type", "USER_CLICK");
char *json_str = cJSON_Print(root);
cJSON_Delete(root);
return json_str;
}
#endif
@@ -0,0 +1,20 @@
#ifndef _DUER_JSON_REQUEST_H_
#define _DUER_JSON_REQUEST_H_
#include "duer_common.h"
extern char *duer_start_frame(const char *appid, const char *appkey, const char *client_id, const char *pid,
const char *cuid, const char *format, int support_dcs, int sample,
const char *user_id, const char *access_token, int support_tts,
int support_text2dcs, const char *dialog_request_id, int access_rc,
const char *rc_version);
extern char *build_finish_frame() ;
extern char *duer_text_info_frame(const char *CUID,
const char *current_dialog_request_id,
const char *text_query);
#endif
@@ -0,0 +1,140 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".intelligent_duer_task.data.bss")
#pragma data_seg(".intelligent_duer_task.data")
#pragma const_seg(".intelligent_duer_task.text.const")
#pragma code_seg(".intelligent_duer_task.text")
#endif
#include "duer_task.h"
#include "duer_http_req.h"
#include "os_api.h"
#if INTELLIGENT_DUER
#define LOG_TAG_CONST NET_DUER
#define LOG_TAG "[DUER_TASK]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define INTELLIGENT_DUER_NAME "intelligent_duer"
static DUER_DATA *duer = NULL;
static TokenData *token = NULL;
void ntp_sync_callback(int result, const struct tm *sync_time, const char *msg)
{
if (result == 0) {
char time_str[64];
strftime_2(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", sync_time);
log_info("NTP同步成功: %s | %s\n", time_str, msg);
os_taskq_post(INTELLIGENT_DUER_NAME, 1, DUER_TOKEN_GET); //同步时间成功,下一步鉴权
} else {
log_info("NTP同步失败 (错误码: %d): %s\n", result, msg);
os_taskq_post(INTELLIGENT_DUER_NAME, 1, DUER_ERROR);
}
}
static void duer_data_init()
{
if (duer == NULL) {
duer = net_interface_malloc(sizeof(DUER_DATA));
}
}
static void duer_data_destory()
{
if (duer->access_token) {
net_interface_free(duer->access_token);
}
if (duer != NULL) {
net_interface_free(duer);
}
}
static void duer_ask_access_token()
{
token = duer_get_access_token();
if (token) {
size_t len = strlen(token->access_token);
duer->access_token = net_interface_malloc(len + 1);
if (duer->access_token == NULL) {
os_taskq_post(INTELLIGENT_DUER_NAME, 1, DUER_ERROR);
}
snprintf(duer->access_token, len + 1, "%s", token->access_token);
log_info(">>>>>>>>>>duer->access_token %s \n", duer->access_token);
duer_free_token_data(token);
os_taskq_post(INTELLIGENT_DUER_NAME, 1, DUER_WS_CONNECT);
} else {
os_taskq_post(INTELLIGENT_DUER_NAME, 1, DUER_ERROR);
}
}
static void task_kill_callback()
{
task_kill(INTELLIGENT_DUER_NAME);
}
static void intelligent_duer_task(void *priv)
{
int msg[3] = {0};
int res = 0;
while (1) {
res = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
if (res == OS_TASKQ) {
switch (msg[1]) {
case DUER_NTP_SYNC:
ntp_get_time_to_sync_rtc_with_callback();
break;
case DUER_TOKEN_GET:
duer_ask_access_token();
break;
case DUER_WS_CONNECT://ws通信、opus数据交互、url数据接收
duer_websocket_client_thread_create(duer->access_token);
break;
case DUER_NETDOWN://URL索引下载,解码播放
net_url_download();
break;
case DUER_ERROR:
case DUER_CLOSING:
goto err; //error和close都会关闭
break;
}
}
}
err:
duer_data_destory();
msg[0] = (int)task_kill_callback;
msg[1] = 1;
os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
os_time_dly(-1);
}
void intelligent_duer_task_create()
{
duer_data_init();
os_task_create(intelligent_duer_task,
NULL,
30,
512 * 2,
16,
INTELLIGENT_DUER_NAME);
}
void duer_sync_time_msg()
{
os_taskq_post(INTELLIGENT_DUER_NAME, 1, DUER_NTP_SYNC);
}
void duer_netdownload_msg()
{
os_taskq_post(INTELLIGENT_DUER_NAME, 1, DUER_NETDOWN);
}
void duer_netdownload_close_msg()
{
os_taskq_post(INTELLIGENT_DUER_NAME, 1, DUER_CLOSING);
}
#endif
@@ -0,0 +1,47 @@
#ifndef _DUER_TASK
#define _DUER_TASK
#include "duer_common.h"
#include "time.h"
// 状态枚举
typedef enum {
DUER_NTP_SYNC,
DUER_TOKEN_GET,
DUER_WS_CONNECT,
DUER_NETDOWN,
DUER_ERROR,
DUER_CLOSING
} SystemState;
// 错误码枚举
typedef enum {
ERROR_NONE = 0,
ERROR_NTP_FAILED,
ERROR_HTTP_FAILED,
ERROR_TOKEN_INVALID,
ERROR_WS_CONNECT_FAILED,
ERROR_SERVER_REJECT,
ERROR_RECORD_FAILED,
ERROR_UPLOAD_FAILED,
ERROR_TIMEOUT
} ErrorCode;
typedef struct {
char *access_token;
u8 run;
} DUER_DATA;
extern void ntp_get_time_to_sync_rtc_with_callback();
extern int task_kill(const char *name);
extern void intelligent_duer_task_create();
extern void duer_sync_time_msg();
extern void duer_netdownload_msg();
extern size_t strftime_2(char *ptr, size_t maxsize, const char *format, const struct tm *timeptr);
#endif
@@ -0,0 +1,63 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".intelligent_duer_voice.data.bss")
#pragma data_seg(".intelligent_duer_voice.data")
#pragma const_seg(".intelligent_duer_voice.text.const")
#pragma code_seg(".intelligent_duer_voice.text")
#endif
#include "duer_ai_rx_get_frame.h"
#include "ai_rx_player.h"
#include "cpu/includes.h"
#if INTELLIGENT_DUER
#define FIX_LEN 1024
enum stream_node_state ai_rx_get_frame_duer(struct ai_rx_file_handle *hdl, struct stream_frame **pframe)
{
int available = net_cbuf_data_len();
int read_size = MIN(available, FIX_LEN);
if (read_size <= 0) {
*pframe = NULL;
return NODE_STA_RUN;
}
struct stream_frame *frame = jlstream_get_frame(hdl->node->oport, read_size);
if (!frame) {
*pframe = NULL;
return NODE_STA_RUN;
}
int rlen = net_cbuf_read_data(frame->data, read_size);
frame->len = MAX(rlen, 0);
if (rlen != read_size) {
printf("cbuf_read mismatch: req=%d, act=%d\n", read_size, rlen);
}
*pframe = frame;
return NODE_STA_RUN;
}
static void duer_audio_begin(void)
{
struct ai_rx_player_param param = {0};
param.coding_type = AUDIO_CODING_STREAM_MP3;
param.sample_rate = 16000;
param.channel_mode = AUDIO_CH_MIX;
param.type = AI_SERVICE_VOICE;
ai_rx_player_open(NULL, 0, &param);
extern void audio_app_volume_set(u8 state, s16 volume, u8 fade);
audio_app_volume_set(1, 100, 1);
}
static void duer_audio_start(void *arg)
{
duer_audio_begin();
}
void duer_audio_play()
{
duer_audio_start(NULL);
}
void duer_audio_stop(void *arg)
{
ai_rx_player_close(0);
}
#endif
@@ -0,0 +1,18 @@
#ifndef _DUER_AI_GET_FRAME_H_
#define _DUER_AI_GET_FRAME_H_
#include "duer_common.h"
#include "jlstream.h"
#include "ai_rx_player.h"
#if INTELLIGENT_DUER
extern enum stream_node_state ai_rx_get_frame_duer(struct ai_rx_file_handle *hdl, struct stream_frame **pframe);
extern void my_duer_audio_play();
extern void my_duer_audio_stop(void *arg);
#endif
#endif