|
#include <string.h> |
|
#include <sys/param.h> |
|
#include <stdlib.h> |
|
#include <ctype.h> |
|
#include "esp_log.h" |
|
#include "esp_event.h" |
|
|
|
#include "esp_system.h" |
|
#include "cJSON.h" |
|
|
|
#include "esp_http_client.h" |
|
#include "common.h" |
|
|
|
|
|
#define JSON_URL_LEN 128 |
|
#define REQ_JSON_LEN 512 |
|
#define MAX_HTTP_OUTPUT_BUFFER 2048 |
|
|
|
|
|
#define TENAI_AGENT_GENERATE "token/generate" |
|
#define TENAI_AGENT_START "start" |
|
#define TENAI_AGENT_STOP "stop" |
|
#define TENAI_AGENT_PING "ping" |
|
|
|
|
|
static int _parse_resp_data(const char *resp_data, const int data_len) |
|
{ |
|
if (data_len == 0) { |
|
return -1; |
|
} |
|
|
|
|
|
cJSON *root_json = cJSON_Parse(resp_data); |
|
if (root_json == NULL) { |
|
const char *error_ptr = cJSON_GetErrorPtr(); |
|
if (error_ptr != NULL) { |
|
printf("Error before: %s\n", error_ptr); |
|
} |
|
return -1; |
|
} |
|
|
|
|
|
cJSON *code = cJSON_GetObjectItemCaseSensitive(root_json, "code"); |
|
|
|
if (cJSON_IsString(code) && (code->valuestring != NULL)) { |
|
printf("code: %s\n", code->valuestring); |
|
} |
|
|
|
cJSON *msg = cJSON_GetObjectItemCaseSensitive(root_json, "msg"); |
|
|
|
if (cJSON_IsString(msg) && (msg->valuestring != NULL)) { |
|
printf("msg: %s\n", msg->valuestring); |
|
} |
|
|
|
|
|
if (strcmp(code->valuestring, "0") != 0 || strcmp(msg->valuestring, "success") != 0) { |
|
printf("ai agent is not ok\n"); |
|
cJSON_Delete(root_json); |
|
return -1; |
|
} |
|
|
|
if (g_app.b_ai_agent_generated) { |
|
cJSON_Delete(root_json); |
|
return 0; |
|
} |
|
|
|
cJSON *data = cJSON_GetObjectItemCaseSensitive(root_json, "data"); |
|
|
|
|
|
if (data != NULL && cJSON_IsNull(data)) { |
|
printf("The 'data' field is null.\n"); |
|
cJSON_Delete(root_json); |
|
return 0; |
|
} |
|
|
|
cJSON *app_id = cJSON_GetObjectItemCaseSensitive(data, "appId"); |
|
|
|
|
|
if (cJSON_IsString(app_id) && (app_id->valuestring != NULL)) { |
|
printf("appId: %s\n", app_id->valuestring); |
|
memcpy(g_app.app_id, app_id->valuestring, RTC_APP_ID_LEN); |
|
} |
|
|
|
cJSON *token = cJSON_GetObjectItemCaseSensitive(data, "token"); |
|
|
|
|
|
if (cJSON_IsString(token) && (token->valuestring != NULL)) { |
|
printf("token: %s\n", token->valuestring); |
|
memcpy(g_app.token, token->valuestring, RTC_TOKEN_LEN); |
|
} |
|
|
|
g_app.b_ai_agent_generated = true; |
|
|
|
cJSON_Delete(root_json); |
|
return 0; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static esp_err_t _http_event_handler(esp_http_client_event_t *evt) |
|
{ |
|
static char *output_buffer; |
|
static int output_len; |
|
switch(evt->event_id) { |
|
case HTTP_EVENT_ERROR: |
|
printf("HTTP_EVENT_ERROR\n"); |
|
break; |
|
case HTTP_EVENT_ON_CONNECTED: |
|
printf("HTTP_EVENT_ON_CONNECTED\n"); |
|
break; |
|
case HTTP_EVENT_HEADER_SENT: |
|
printf("HTTP_EVENT_HEADER_SENT\n"); |
|
break; |
|
case HTTP_EVENT_ON_HEADER: |
|
printf("HTTP_EVENT_ON_HEADER, key=%s, value=%s\n", evt->header_key, evt->header_value); |
|
break; |
|
case HTTP_EVENT_ON_DATA: |
|
printf("HTTP_EVENT_ON_DATA, len=%d, data=%s\n", evt->data_len, (char *)evt->data); |
|
|
|
if (output_len == 0 && evt->user_data) { |
|
|
|
memset(evt->user_data, 0, MAX_HTTP_OUTPUT_BUFFER); |
|
} |
|
|
|
|
|
|
|
|
|
if (!esp_http_client_is_chunked_response(evt->client)) { |
|
|
|
int copy_len = 0; |
|
if (evt->user_data) { |
|
|
|
copy_len = MIN(evt->data_len, (MAX_HTTP_OUTPUT_BUFFER - output_len)); |
|
if (copy_len) { |
|
memcpy(evt->user_data + output_len, evt->data, copy_len); |
|
} |
|
} else { |
|
int content_len = esp_http_client_get_content_length(evt->client); |
|
if (output_buffer == NULL) { |
|
|
|
output_buffer = (char *) calloc(content_len + 1, sizeof(char)); |
|
output_len = 0; |
|
if (output_buffer == NULL) { |
|
printf("Failed to allocate memory for output buffer\n"); |
|
return ESP_FAIL; |
|
} |
|
} |
|
copy_len = MIN(evt->data_len, (content_len - output_len)); |
|
if (copy_len) { |
|
memcpy(output_buffer + output_len, evt->data, copy_len); |
|
} |
|
} |
|
output_len += copy_len; |
|
} |
|
break; |
|
case HTTP_EVENT_ON_FINISH: |
|
printf("HTTP_EVENT_ON_FINISH\n"); |
|
_parse_resp_data(output_buffer, output_len); |
|
|
|
if (output_buffer != NULL) { |
|
|
|
free(output_buffer); |
|
output_buffer = NULL; |
|
} |
|
output_len = 0; |
|
|
|
break; |
|
case HTTP_EVENT_DISCONNECTED: |
|
printf("HTTP_EVENT_DISCONNECTED\n"); |
|
if (output_buffer != NULL) { |
|
free(output_buffer); |
|
output_buffer = NULL; |
|
} |
|
output_len = 0; |
|
break; |
|
default: |
|
break; |
|
} |
|
return ESP_OK; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *_build_generate_json(void) |
|
{ |
|
char *json_ptr = NULL; |
|
|
|
cJSON *root = cJSON_CreateObject(); |
|
if (root == NULL) { |
|
goto BUILD_END; |
|
} |
|
|
|
cJSON_AddItemToObject(root, "request_id", cJSON_CreateString(AI_AGENT_NAME)); |
|
cJSON_AddNumberToObject(root, "uid", AI_AGENT_USER_ID); |
|
cJSON_AddItemToObject(root, "channel_name", cJSON_CreateString(AI_AGENT_CHANNEL_NAME)); |
|
|
|
json_ptr = cJSON_Print(root); |
|
|
|
BUILD_END: |
|
cJSON_Delete(root); |
|
|
|
return json_ptr; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *_build_start_json(void) |
|
{ |
|
char *json_ptr = NULL; |
|
|
|
cJSON *root = cJSON_CreateObject(); |
|
if (root == NULL) { |
|
goto BUILD_END; |
|
} |
|
|
|
cJSON_AddItemToObject(root, "request_id", cJSON_CreateString(AI_AGENT_NAME)); |
|
cJSON_AddItemToObject(root, "channel_name", cJSON_CreateString(AI_AGENT_CHANNEL_NAME)); |
|
cJSON_AddNumberToObject(root, "user_uid", AI_AGENT_USER_ID); |
|
cJSON_AddItemToObject(root, "graph_name", cJSON_CreateString(GRAPH_NAME)); |
|
|
|
cJSON *properties = cJSON_CreateObject(); |
|
cJSON_AddItemToObject(root, "properties", properties); |
|
|
|
cJSON *agora_rtc = cJSON_CreateObject(); |
|
cJSON_AddItemToObject(properties, "agora_rtc", agora_rtc); |
|
cJSON_AddItemToObject(agora_rtc, "sdk_params", cJSON_CreateString(TENAI_AUDIO_CODEC)); |
|
|
|
cJSON *custom_llm = cJSON_CreateObject(); |
|
cJSON_AddItemToObject(properties, "v2v", custom_llm); |
|
cJSON_AddItemToObject(custom_llm, "model", cJSON_CreateString(V2V_MODEL)); |
|
cJSON_AddItemToObject(custom_llm, "voice", cJSON_CreateString(VOICE)); |
|
cJSON_AddItemToObject(custom_llm, "language", cJSON_CreateString(LANGUAGE)); |
|
cJSON_AddItemToObject(custom_llm, "greeting", cJSON_CreateString(GREETING)); |
|
cJSON_AddItemToObject(custom_llm, "prompt", cJSON_CreateString(PROMPT)); |
|
|
|
json_ptr = cJSON_Print(root); |
|
|
|
BUILD_END: |
|
cJSON_Delete(root); |
|
|
|
return json_ptr; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *_build_common_json(void) |
|
{ |
|
char *json_ptr = NULL; |
|
|
|
cJSON *root = cJSON_CreateObject(); |
|
if (root == NULL) { |
|
goto BUILD_END; |
|
} |
|
|
|
cJSON_AddItemToObject(root, "request_id", cJSON_CreateString(AI_AGENT_NAME)); |
|
cJSON_AddItemToObject(root, "channel_name", cJSON_CreateString(AI_AGENT_CHANNEL_NAME)); |
|
|
|
json_ptr = cJSON_Print(root); |
|
|
|
BUILD_END: |
|
cJSON_Delete(root); |
|
|
|
return json_ptr; |
|
} |
|
|
|
|
|
|
|
void ai_agent_generate(void) |
|
{ |
|
char request[REQ_JSON_LEN] = {'\0'}; |
|
|
|
char generate_url[JSON_URL_LEN] = { 0 }; |
|
snprintf(generate_url, JSON_URL_LEN, "%s/%s", TENAI_AGENT_URL, TENAI_AGENT_GENERATE); |
|
|
|
esp_event_loop_create_default(); |
|
|
|
esp_http_client_config_t config = { |
|
.url = generate_url, |
|
.event_handler = _http_event_handler, |
|
}; |
|
esp_http_client_handle_t client = esp_http_client_init(&config); |
|
esp_http_client_set_method(client, HTTP_METHOD_POST); |
|
esp_http_client_set_header(client, "Content-Type", "application/json"); |
|
|
|
char *json_buff = _build_generate_json(); |
|
snprintf(request, REQ_JSON_LEN, "%s", json_buff); |
|
free(json_buff); |
|
|
|
esp_err_t err = esp_http_client_open(client, strlen(request)); |
|
printf("http_with_url request =%s\n",request); |
|
if (err != ESP_OK) { |
|
printf("Failed to open HTTP connection: %s\n", esp_err_to_name(err)); |
|
} else { |
|
int wlen = esp_http_client_write(client, request, strlen(request)); |
|
if (wlen < 0) { |
|
printf("https client write failed\n"); |
|
} |
|
|
|
esp_err_t err = esp_http_client_perform(client); |
|
if (err == ESP_OK) { |
|
printf("HTTPS Status = %d, content_length = %lld\n", |
|
esp_http_client_get_status_code(client), |
|
esp_http_client_get_content_length(client)); |
|
} else { |
|
printf("Error perform http request %s\n", esp_err_to_name(err)); |
|
} |
|
} |
|
|
|
esp_http_client_cleanup(client); |
|
} |
|
|
|
|
|
void ai_agent_start(void) |
|
{ |
|
char request[REQ_JSON_LEN] = {'\0'}; |
|
|
|
char start_url[JSON_URL_LEN] = { 0 }; |
|
snprintf(start_url, JSON_URL_LEN, "%s/%s", TENAI_AGENT_URL, TENAI_AGENT_START); |
|
|
|
esp_event_loop_create_default(); |
|
|
|
esp_http_client_config_t config = { |
|
.url = start_url, |
|
.event_handler = _http_event_handler, |
|
}; |
|
esp_http_client_handle_t client = esp_http_client_init(&config); |
|
esp_http_client_set_method(client, HTTP_METHOD_POST); |
|
esp_http_client_set_header(client, "Content-Type", "application/json"); |
|
|
|
char *json_buff = _build_start_json(); |
|
snprintf(request, REQ_JSON_LEN, "%s", json_buff); |
|
free(json_buff); |
|
|
|
esp_err_t err = esp_http_client_open(client, strlen(request)); |
|
printf("http_with_url request =%s\n",request); |
|
if (err != ESP_OK) { |
|
printf("Failed to open HTTP connection: %s\n", esp_err_to_name(err)); |
|
} else { |
|
int wlen = esp_http_client_write(client, request, strlen(request)); |
|
if (wlen < 0) { |
|
printf("https client write failed\n"); |
|
} |
|
|
|
esp_err_t err = esp_http_client_perform(client); |
|
if (err == ESP_OK) { |
|
printf("HTTPS Status = %d, content_length = %lld\n", |
|
esp_http_client_get_status_code(client), |
|
esp_http_client_get_content_length(client)); |
|
} else { |
|
printf("Error perform http request %s\n", esp_err_to_name(err)); |
|
} |
|
} |
|
|
|
esp_http_client_cleanup(client); |
|
} |
|
|
|
|
|
void ai_agent_ping(void) |
|
{ |
|
char request[REQ_JSON_LEN] = {'\0'}; |
|
|
|
char ping_url[JSON_URL_LEN] = { 0 }; |
|
|
|
snprintf(ping_url, JSON_URL_LEN, "%s/%s", TENAI_AGENT_URL, TENAI_AGENT_PING); |
|
|
|
esp_http_client_config_t config = { |
|
.url = ping_url, |
|
.event_handler = _http_event_handler, |
|
}; |
|
esp_http_client_handle_t client = esp_http_client_init(&config); |
|
esp_http_client_set_method(client, HTTP_METHOD_POST); |
|
esp_http_client_set_header(client, "Content-Type", "application/json"); |
|
|
|
char *json_buff = _build_common_json(); |
|
snprintf(request, REQ_JSON_LEN, "%s", json_buff); |
|
free(json_buff); |
|
|
|
esp_err_t err = esp_http_client_open(client, strlen(request)); |
|
printf("http_with_url request =%s\n",request); |
|
if (err != ESP_OK) { |
|
printf("Failed to open HTTP connection: %s\n", esp_err_to_name(err)); |
|
} else { |
|
int wlen = esp_http_client_write(client, request, strlen(request)); |
|
if (wlen < 0) { |
|
printf("https client write failed\n"); |
|
} |
|
|
|
esp_err_t err = esp_http_client_perform(client); |
|
if (err == ESP_OK) { |
|
printf("HTTPS Status = %d, content_length = %lld\n", |
|
esp_http_client_get_status_code(client), |
|
esp_http_client_get_content_length(client)); |
|
} else { |
|
printf("Error perform http request %s\n", esp_err_to_name(err)); |
|
} |
|
} |
|
|
|
esp_http_client_cleanup(client); |
|
} |
|
|
|
|
|
void ai_agent_stop(void) |
|
{ |
|
char request[REQ_JSON_LEN] = {'\0'}; |
|
|
|
char stop_url[JSON_URL_LEN] = { 0 }; |
|
|
|
snprintf(stop_url, JSON_URL_LEN, "%s/%s", TENAI_AGENT_URL, TENAI_AGENT_STOP); |
|
|
|
esp_http_client_config_t config = { |
|
.url = stop_url, |
|
.event_handler = _http_event_handler, |
|
}; |
|
esp_http_client_handle_t client = esp_http_client_init(&config); |
|
esp_http_client_set_method(client, HTTP_METHOD_POST); |
|
esp_http_client_set_header(client, "Content-Type", "application/json"); |
|
|
|
char *json_buff = _build_common_json(); |
|
snprintf(request, REQ_JSON_LEN, "%s", json_buff); |
|
free(json_buff); |
|
|
|
esp_err_t err = esp_http_client_open(client, strlen(request)); |
|
printf("http_with_url request =%s\n",request); |
|
if (err != ESP_OK) { |
|
printf("Failed to open HTTP connection: %s\n", esp_err_to_name(err)); |
|
} else { |
|
int wlen = esp_http_client_write(client, request, strlen(request)); |
|
if (wlen < 0) { |
|
printf("https client write failed\n"); |
|
} |
|
|
|
esp_err_t err = esp_http_client_perform(client); |
|
if (err == ESP_OK) { |
|
printf("HTTPS Status = %d, content_length = %lld\n", |
|
esp_http_client_get_status_code(client), |
|
esp_http_client_get_content_length(client)); |
|
} else { |
|
printf("Error perform http request %s\n", esp_err_to_name(err)); |
|
} |
|
} |
|
|
|
esp_http_client_cleanup(client); |
|
} |
|
|