初版
This commit is contained in:
@@ -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, ¶m);
|
||||
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
|
||||
Reference in New Issue
Block a user