cJSON_AddNumberToObject(outbound_cfg, "volume", 100);
cJSON_AddNumberToObject(outbound_cfg, "speech_rate", 0);
cJSON_AddNumberToObject(outbound_cfg, "chunk_interval_ms", 100);
- cJSON_AddStringToObject(outbound_cfg, "voice", "zh_female_linjianvhai_moon_bigtts");
+ cJSON_AddStringToObject(outbound_cfg, "voice", "7468512265134915635");
cJSON_AddItemToObject(outbound_attributes, "cfg", outbound_cfg);
cJSON_AddItemToObject(payload, "outbound_attributes", outbound_attributes);
//连接服务器
if(AI_client_VC == NULL)
{
- AI_client_VC = init_websocket_client("118.145.158.207","/vc/chat?is_auth=0",22086);
+ AI_client_VC = init_websocket_client("ws://118.145.158.207:22086/vc/coze?is_auth=0",NULL);
}
//创建发送线程
if(AI_VC_send_task_id == 0)
(WebSocketMessageType)AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE);
if(AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE ==AIC_WEBSOCKET_OPCODE_TEXT_FRAME )
bk_printf("VCVC:send text ret=%d,len=%d,str=%s",ret,AI_VC_send_queue_data.len,AI_VC_send_queue_data.data);
- // else if(AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE ==AIC_WEBSOCKET_OPCODE_BINARY_FRAME )
- // bk_printf("VCVC:send bin ret=%d,len=%d",ret,AI_VC_send_queue_data.len);
+ else if(AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE ==AIC_WEBSOCKET_OPCODE_BINARY_FRAME )
+ bk_printf("VCVC:send bin ret=%d,len=%d",ret,AI_VC_send_queue_data.len);
aic_free(AI_VC_send_queue_data.data);
}else
{
}
}
-static u8 recv_buff[10*1024];
+static u8 recv_buff[20*1024];
static void AI_VC_read_task(void *thread_input)//websocket 读线程
{
int result_val=0;
if(ret<=0)
{
bk_printf("AI_VC_record_task continue len = %d,VC_state = %d",ret,VC_state);
+ aos_sleep(1);
continue;
}
if(VC_state == VC_State_None)//开启的时候,先缓存音频
{
AI_VC_put_record_data(vrecord_buf,ret);
- }else if(VC_state >= VC_State_Listening && VC_state<VC_State_TTSStart)//正常录音
+ }else if(VC_state >= VC_State_Listening )//正常录音
{
char count_t = 200;
while(count_t--)
{
bk_printf("AI_key_long_press");
}
-
+void pwk_key_release(void)
+{
+ bk_printf("pwk_key_release");
+ AI_VC_Close();
+}
void AI_VC_start(void)
{
int ret = 0;
case AI_KEY_LONG_PRESS:
AI_key_long_press();
break;
+ case PWK_KEY_RELEASE:
+ pwk_key_release();
+ break;
+
case AI_PRINTF:
if(AI_AMP_msg.data)
uart_write(ai_uart_handle,AI_AMP_msg.data, AI_AMP_msg.len);
{
aos_sleep(time);
}
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// 定义一个结构体来存储解析后的URL部分
+typedef struct {
+ char *protocol;
+ char *host;
+ int port;
+ char *path;
+ char *query;
+ int error;
+ char *error_message;
+} BK_URL;
+
+// 自定义的 strdup 函数,添加错误处理
+char* bk_strdup(const char* str) {
+ if (str == NULL) {
+ return NULL;
+ }
+ size_t len = strlen(str) + 1;
+ char* new_str = (char*)aic_zalloc(len);
+ if (new_str == NULL) {
+ return NULL;
+ }
+ return (char*)memcpy(new_str, str, len);
+}
+
+// 设置错误信息
+void set_url_error(BK_URL *url, const char *error_msg) {
+ url->error = 1;
+ url->error_message = bk_strdup(error_msg);
+ if (!url->error_message) {
+ // 若分配失败,输出提示信息
+ bk_printf("Memory allocation failed for error message.\n");
+ }
+
+}
+
+// 解析URL的函数
+BK_URL parse_url(const char *url) {
+ bk_printf("parse_url url=%s.\n",url);
+ BK_URL result = {NULL, NULL, 0, NULL, NULL, 0, NULL};
+ char *temp_url_t = bk_strdup(url);
+ char *temp_url = temp_url_t;
+ if (!temp_url) {
+ set_url_error(&result, "Failed to allocate memory for temp_url");
+ return result;
+ }
+
+ // 解析协议
+ char *colon = strchr(temp_url, ':');
+ if (!colon) {
+ set_url_error(&result, "Invalid URL: No protocol specified");
+ aic_free(temp_url_t);
+ return result;
+ }
+ *colon = '\0';
+ result.protocol = bk_strdup(temp_url);
+ if (!result.protocol) {
+ set_url_error(&result, "Failed to allocate memory for protocol");
+ aic_free(temp_url_t);
+ return result;
+ }
+ temp_url = colon + 3; // 跳过 "://"
+
+ // 解析主机和端口
+ char *slash = strchr(temp_url, '/');
+ if (!slash) {
+ set_url_error(&result, "Invalid URL: No path specified");
+ aic_free(temp_url_t);
+ return result;
+ }
+ *slash = '\0';
+ char *at = strchr(temp_url, '@');
+ if (at) {
+ temp_url = at + 1; // 跳过用户名和密码部分
+ }
+ char *colon_port = strchr(temp_url, ':');
+ if (colon_port) {
+ *colon_port = '\0';
+ result.host = bk_strdup(temp_url);
+ if (!result.host) {
+ set_url_error(&result, "Failed to allocate memory for host");
+ aic_free(temp_url_t);
+ return result;
+ }
+ result.port = atoi(colon_port + 1);
+ if (!result.port) {
+ set_url_error(&result, "Invalid port number");
+ aic_free(temp_url_t);
+ return result;
+ }
+ } else {
+ result.host = bk_strdup(temp_url);
+ if (!result.host) {
+ set_url_error(&result, "Failed to allocate memory for host");
+ aic_free(temp_url_t);
+ return result;
+ }
+ if (!strcmp(result.protocol, "http") || !strcmp(result.protocol, "ws")) {
+ result.port = 80;
+ } else if (!strcmp(result.protocol, "https")|| !strcmp(result.protocol, "wss")) {
+ result.port = 443;
+ }
+ }
+ temp_url = slash+1;
+ //bk_printf("parse_url slash=%s\n",temp_url);
+ // 解析路径和查询字符串
+ char *question = strchr(temp_url, '?');
+ if (question) {
+ *question = '\0';
+ result.path = bk_strdup(temp_url);
+ if (!result.path) {
+ set_url_error(&result, "Failed to allocate memory for path");
+ aic_free(temp_url_t);
+ return result;
+ }
+ result.query = bk_strdup(question + 1);
+ if (!result.query) {
+ set_url_error(&result, "Failed to allocate memory for query");
+ aic_free(temp_url_t);
+ return result;
+ }
+ } else {
+ result.path = bk_strdup(temp_url);
+ if (!result.path) {
+ set_url_error(&result, "Failed to allocate memory for path");
+ aic_free(temp_url_t);
+ return result;
+ }
+ result.query = NULL;
+ }
+
+ aic_free(temp_url_t);
+
+ return result;
+}
+
+// 释放URL结构体中分配的内存
+void free_url(BK_URL url) {
+
+ // 释放已分配的内存
+
+ if (url.protocol) {
+ aic_free(url.protocol);
+ url.protocol = NULL;
+ }
+ if (url.host) {
+ aic_free(url.host);
+ url.host = NULL;
+ }
+ if (url.path) {
+ aic_free(url.path);
+ url.path = NULL;
+ }
+ if (url.query) {
+ aic_free(url.query);
+ url.query = NULL;
+ }
+ if (url.error_message) {
+ aic_free(url.error_message);
+ url.error_message = NULL;
+ }
+
+}
+
// 仿写 htonl 函数
static uint32_t htonl(uint32_t hostlong) {
// 检查主机是否为大端字节序
}
// 发送 WebSocket 握手请求
-int send_handshake(WebSocketClient *client) {
+int send_handshake(WebSocketClient *client,const char *headers) {
char key[WEBSOCKET_KEY_LEN];
bk_printf("send_handshake1");
generate_websocket_key(key);
generate_accept_key(key, accept_key);
bk_printf("send_handshake2");
char *request =aic_zalloc(BUFFER_SIZE);
- snprintf(request, BUFFER_SIZE,
- "GET %s HTTP/1.1\r\n"
- "Host: %s:%d\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: %s\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "Origin: http://%s:%d\r\n"
- "\r\n",
- client->path, client->host,client->port, accept_key,client->host,client->port);
+ if(headers!= NULL)
+ {
+ snprintf(request, BUFFER_SIZE,
+ "GET /%s?%s HTTP/1.1\r\n"
+ "Host: %s:%d\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Key: %s\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
+ "Origin: http://%s:%d\r\n"
+ "%s\r\n"
+ "\r\n",
+ client->path,client->query ,client->host,client->port, accept_key,client->host,client->port,headers);
+ }else
+ {
+ snprintf(request, BUFFER_SIZE,
+ "GET /%s?%s HTTP/1.1\r\n"
+ "Host: %s:%d\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Key: %s\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
+ "Origin: http://%s:%d\r\n"
+ "\r\n",
+ client->path,client->query , client->host,client->port, accept_key,client->host,client->port);
+ }
+
bk_printf("send_handshake request:\r\n%s",request);
if (send(client->sockfd, request, strlen(request), 0) < 0) {
bk_printf("send handshake failed");
}
if(payload_len>len)
{
- bk_printf("receive_websocket_message:len ERROR");
+ bk_printf("receive_websocket_message:len =%d ERROR",payload_len);
recv(client->sockfd, buf, len, 0);
return -1;
}
}
// 初始化 WebSocket 客户端
-WebSocketClient *init_websocket_client(const char *host, const char *path, int port) {
+WebSocketClient *init_websocket_client(const char *url, const char *headers) {
//bk_printf("init_websocket_client 1\n");
char *buffer = NULL;
- WebSocketClient *client = aic_zalloc(sizeof(WebSocketClient)) ;
+ WebSocketClient *client =NULL;
+ BK_URL parsed_url = {0};
+ parsed_url = parse_url(url);//解析url
+ bk_printf("Error: %x", parsed_url);
+ if (parsed_url.error) {
+ bk_printf("Error: %s", parsed_url.error_message);
+ goto client_ERROR;
+ } else {
+ bk_printf("Protocol: %s", parsed_url.protocol);
+ bk_printf("Host: %s", parsed_url.host);
+ bk_printf("Port: %d", parsed_url.port);
+ bk_printf("Path: %s", parsed_url.path);
+ bk_printf("Query: %s", parsed_url.query);
+
+ }
+ client = aic_zalloc(sizeof(WebSocketClient)) ;
if(!client)
{
bk_printf("init_websocket_client alloc error");
- return NULL;
+ goto client_ERROR;
}
+
client->sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (client->sockfd < 0) {
bk_printf("socket creation failed");
// bk_printf("init_websocket_client 3\n");
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(port);
- inet_pton(AF_INET, host, &server_addr.sin_addr);
+ server_addr.sin_port = htons(parsed_url.port);
+ inet_pton(AF_INET, parsed_url.host, &server_addr.sin_addr);
if (connect(client->sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
bk_printf("connection failed");
}
- strcpy(client->host, host);
- strcpy(client->path, path);
- client->port = port;
- if (send_handshake(client) < 0) {
+ strcpy(client->host, parsed_url.host);
+ strcpy(client->path, parsed_url.path);
+ strcpy(client->query, parsed_url.query);
+ client->port = parsed_url.port;
+ if (send_handshake(client,headers) < 0) { //发送头
close(client->sockfd);
goto client_ERROR;
}
goto client_ERROR;
}
aic_free(buffer);
-
+ free_url(parsed_url);
return client;
client_ERROR:
if(buffer)
aic_free(buffer);
if(client)
aic_free(client);
+ free_url(parsed_url);
return NULL;
}
int bk_websocket_demo(void) {
WebSocketClient *client;
- client = init_websocket_client("127.0.0.1", "/", 8080) ;
+ client = init_websocket_client("ws://118.145.158.207:22086/vc/coze?is_auth=0",NULL);
if (client== NULL) {
return -1;
}