doubao_chat/lib/net/EchoCloud/echo_cloud_api.c

910 lines
29 KiB
C

#include "server/ai_server.h"
#include "system/os/os_api.h"
#include "server/server_core.h"
#include "version.h"
#include "echo_cloud.h"
#include "generic/circular_buf.h"
#include "server/upgrade_server.h"
#include "sock_api/sock_api.h"
#ifdef ECHO_CLOUD_SDK_VERSION
MODULE_VERSION_EXPORT(echo_cloud_sdk, ECHO_CLOUD_SDK_VERSION);
#endif
const struct ai_sdk_api echo_cloud_sdk_api;
static const int events[][2] = {
{ AI_EVENT_SPEAK_END, ECHO_CLOUD_SPEAK_END },
{ AI_EVENT_MEDIA_END, ECHO_CLOUD_MEDIA_END },
{ AI_EVENT_MEDIA_STOP, ECHO_CLOUD_MEDIA_STOP },
{ AI_EVENT_PREVIOUS_SONG, ECHO_CLOUD_PREVIOUS_SONG },
{ AI_EVENT_NEXT_SONG, ECHO_CLOUD_NEXT_SONG },
{ AI_EVENT_RECORD_START, ECHO_CLOUD_RECORD_START },
{ AI_EVENT_RECORD_STOP, ECHO_CLOUD_RECORD_STOP },
{ AI_EVENT_VOLUME_CHANGE, ECHO_CLOUD_VOLUME_CHANGE },
{ AI_EVENT_PLAY_PAUSE, ECHO_CLOUD_PLAY_PAUSE },
{ AI_EVENT_COLLECT_RES, ECHO_CLOUD_COLLECT_RESOURCE },
{ AI_EVENT_CHILD_LOCK, ECHO_CLOUD_CHILD_LOCK_CHANGE },
{ AI_EVENT_CUSTOM_FUN, ECHO_CLOUD_DEVICE_CODE_REPORT },
{ AI_EVENT_QUIT , ECHO_CLOUD_QUIT },
};
enum {
ECHO_CLOUD_SPEEK_URL,
ECHO_CLOUD_MEDIA_URL,
};
typedef enum {
RECORDER_STOP = 0,
RECORDER_START,
} echo_cloud_rec_state_t;
#define WECHAT_ENC_MAX_DURATION (60) //s
#define WECHAT_ENC_BUFFER_MIN_LEN (1600 + 6)
#if 1
#define ONE_CACHE_BUF_LEN 800 //MSS=1300
#define CACHE_BUF_LEN (4 * ONE_CACHE_BUF_LEN) //vad_buf 占用一半
#else
#define ONE_CACHE_BUF_LEN 1200 //MSS=1300
#define CACHE_BUF_LEN ONE_CACHE_BUF_LEN
#endif
static struct {
struct server *enc_server;
struct echo_cloud_hdl hdl;
echo_cloud_rec_state_t rec_state;
OS_SEM sem;
OS_MUTEX mutex;
cbuffer_t vad_cbuf;
int app_task_pid;
volatile u8 exit_flag;
u8 voice_mode;
u8 connect_status;
u8 vad_status;
u8 vad_enable;
u8 curr_url_type;
u8 msg_notify_disable;
u16 curr_offset;
u32 rec_total_len;
u8 enc_buffer[CACHE_BUF_LEN + 6];
} echo_cloud_api_hdl;
#define __this (&echo_cloud_api_hdl)
static int event2echo_cloud(int event)
{
for (int i = 0; i < ARRAY_SIZE(events); i++) {
if (events[i][0] == event) {
return events[i][1];
}
}
return -1;
}
static int echo_cloud_sdk_do_event(int event, int arg)
{
int err;
int argc = 2;
int argv[4];
int echo_cloud_event;
echo_cloud_event = event2echo_cloud(event);
if (echo_cloud_event == -1) {
return 0;
}
printf("echo_cloud_event: %x\n", echo_cloud_event);
if (!__this->connect_status) {
return 0;
}
if (echo_cloud_event == ECHO_CLOUD_RECORD_START) {
if (__this->rec_state == RECORDER_START) {
return 0;
}
} else if (echo_cloud_event == ECHO_CLOUD_MEDIA_END) {
if (__this->curr_url_type == ECHO_CLOUD_SPEEK_URL) {
echo_cloud_event = ECHO_CLOUD_SPEAK_END;
}
}
if (echo_cloud_event != ECHO_CLOUD_RECORD_STOP &&
echo_cloud_event != ECHO_CLOUD_CHILD_LOCK_CHANGE &&
__this->msg_notify_disable) {
return 0;
}
argv[0] = echo_cloud_event;
argv[1] = arg;
err = os_taskq_post_type("echo_cloud_app_task", Q_USER, argc, argv);
if (err != OS_NO_ERR) {
printf("send msg to echo_cloud_app_task fail, event : %d\n", echo_cloud_event);
}
return 0;
}
static int echo_cloud_vfs_fwrite(void *file, void *data, u32 len)
{
u32 remain = 0;
u32 cplen = 0;
int err = 0;
u32 ret_len = len;
u8 *p = (u8 *)data;
u8 vad_status = __this->vad_status;
if (len == 6) {
return len; //跳过头部
}
if (__this->rec_state == RECORDER_STOP) {
return 0;
}
__this->rec_total_len += len;
if (__this->vad_enable) {
if (0 == vad_status) {
if (0 == cbuf_is_write_able(&__this->vad_cbuf, len)) {
if (len != cbuf_read(&__this->vad_cbuf, __this->enc_buffer + 6, len)) {
return 0;
}
}
cbuf_write(&__this->vad_cbuf, data, len);
return len;
}
u32 cbuf_data_len = cbuf_get_data_size(&__this->vad_cbuf);
while (cbuf_data_len > 0) {
if (cbuf_data_len > ONE_CACHE_BUF_LEN) {
__this->curr_offset = cbuf_read(&__this->vad_cbuf, __this->enc_buffer + 6, ONE_CACHE_BUF_LEN);
} else {
__this->curr_offset = cbuf_read(&__this->vad_cbuf, __this->enc_buffer + 6, cbuf_data_len);
}
cbuf_data_len -= __this->curr_offset;
//echo_cloud的服务器限制了每次发800个字节,加上头部是806个字节
if (__this->curr_offset == ONE_CACHE_BUF_LEN) {
if (__this->rec_state != RECORDER_START) {
return 0;
}
if (__this->enc_buffer[0]) {
err = os_taskq_post("echo_cloud_app_task", 4, ECHO_CLOUD_RECORD_SEND, (int)__this->enc_buffer,
ONE_CACHE_BUF_LEN + 6, &__this->sem);
} else {
err = os_taskq_post("echo_cloud_app_task", 4, ECHO_CLOUD_RECORD_SEND, (int)(__this->enc_buffer + 6),
ONE_CACHE_BUF_LEN, &__this->sem);
}
if (err != OS_NO_ERR) {
puts("echo_cloud_app_task msg full\n");
return 0;
}
if (OS_TIMEOUT == os_sem_pend(&__this->sem, 450)) {
return 0;
}
__this->enc_buffer[0] = 0;
__this->curr_offset = 0;
}
}
if (2 == vad_status) {
if (OS_NO_ERR != os_taskq_post("echo_cloud_app_task", 1, ECHO_CLOUD_RECORD_STOP)) {
puts("echo_cloud_app_task send msg ECHO_CLOUD_RECORD_STOP timeout ");
}
return ret_len;
}
}
do {
remain = ONE_CACHE_BUF_LEN - __this->curr_offset;
cplen = remain < len ? remain : len;
if (cplen == 0) {
if (__this->rec_state != RECORDER_START) {
return 0;
}
if (__this->enc_buffer[0]) {
err = os_taskq_post("echo_cloud_app_task", 4, ECHO_CLOUD_RECORD_SEND, (int)__this->enc_buffer,
ONE_CACHE_BUF_LEN + 6, &__this->sem);
} else {
err = os_taskq_post("echo_cloud_app_task", 4, ECHO_CLOUD_RECORD_SEND, (int)(__this->enc_buffer + 6),
ONE_CACHE_BUF_LEN, &__this->sem);
}
if (err != OS_NO_ERR) {
puts("echo_cloud_app_task msg full\n");
return 0;
}
if (OS_TIMEOUT == os_sem_pend(&__this->sem, 450)) {
return 0;
}
__this->enc_buffer[0] = 0;
__this->curr_offset = 0;
} else {
memcpy(__this->enc_buffer + __this->curr_offset + 6, p, cplen);
__this->curr_offset += cplen;
p += cplen;
len -= cplen;
}
} while (len);
return ret_len;
}
static int echo_cloud_vfs_fclose(void *file)
{
return 0;
}
static const struct audio_vfs_ops echo_cloud_vfs_ops = {
.fwrite = echo_cloud_vfs_fwrite,
.fclose = echo_cloud_vfs_fclose,
};
static void enc_server_event_handler(void *priv, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_SERVER_EVENT_ERR:
case AUDIO_SERVER_EVENT_END:
puts("echo_cloud rec: AUDIO_SERVER_EVENT_END\n");
if (__this->rec_state == RECORDER_START) {
if (OS_NO_ERR != os_taskq_post("echo_cloud_app_task", 1, ECHO_CLOUD_RECORD_ERR)) {
puts("echo_cloud_app_task send msg ECHO_CLOUD_RECORD_ERR timeout ");
}
}
break;
case AUDIO_SERVER_EVENT_SPEAK_START:
__this->vad_status = 1;
puts("speak start ! \n");
break;
case AUDIO_SERVER_EVENT_SPEAK_STOP:
__this->vad_status = 2;
puts("speak stop ! \n");
break;
default:
break;
}
}
static int echo_cloud_send_last_packet(struct echo_cloud_http_hdl *p)
{
int err = 0;
if ((__this->vad_enable && !__this->vad_status) || (WECHAT_MODE != __this->voice_mode && !__this->rec_total_len)) {
ai_server_event_notify(&echo_cloud_sdk_api, NULL, AI_SERVER_EVENT_REC_ERR);
return 0;
}
if (__this->curr_offset > 0) {
if (__this->enc_buffer[0]) {
err = echo_cloud_enc_http_send(p, __this->enc_buffer, __this->curr_offset + 6);
__this->enc_buffer[0] = 0;
} else {
err = echo_cloud_enc_http_send(p, __this->enc_buffer + 6, __this->curr_offset);
}
__this->curr_offset = 0;
}
if (!err) {
err = echo_cloud_enc_http_send(p, NULL, 0);
}
return err;
}
static int echo_cloud_recorder_start(u16 sample_rate, u8 __voice_mode, u8 enable_vad)
{
int err;
union audio_req req = {0};
OS_SEM mic_sem;
puts("echo_cloud_recorder_start\n");
if (__this->rec_state == RECORDER_START) {
return -1;
}
if (!__this->enc_server) {
__this->enc_server = server_open("audio_server", "enc");
}
server_register_event_handler(__this->enc_server, NULL, enc_server_event_handler);
u8 voice_mode = __voice_mode & 0x3;
__this->voice_mode = voice_mode;
__this->vad_enable = enable_vad;
__this->vad_status = 0;
__this->curr_offset = 0;
__this->rec_total_len = 0;
memcpy(__this->enc_buffer, "#!AMR\n", 6);
cbuf_init(&__this->vad_cbuf, __this->enc_buffer + 6 + 2 * ONE_CACHE_BUF_LEN, 2 * ONE_CACHE_BUF_LEN);
os_sem_set(&__this->sem, 0);
req.enc.cmd = AUDIO_ENC_OPEN;
req.enc.channel = 1;
req.enc.volume = 100;
req.enc.priority = 0;
req.enc.output_buf = NULL;
req.enc.output_buf_len = 6 * 1024;
if (voice_mode == WECHAT_MODE) {
req.enc.msec = WECHAT_ENC_MAX_DURATION * 1000;
} else {
req.enc.msec = 15 * 1000;
}
req.enc.sample_rate = sample_rate;
req.enc.format = "amr";
req.enc.frame_size = 4 * 1024;
req.enc.sample_source = "mic";
req.enc.vfs_ops = &echo_cloud_vfs_ops;
req.enc.channel_bit_map = (__voice_mode & 0x70) ? BIT(((__voice_mode & 0x70) >> 4) - 1) : 0;
if (voice_mode != WECHAT_MODE && enable_vad) {
req.enc.use_vad = 1;
}
os_sem_create(&mic_sem, 0);
ai_server_event_notify(&echo_cloud_sdk_api, &mic_sem, AI_SERVER_EVENT_MIC_OPEN);
os_sem_pend(&mic_sem, 0);
os_sem_del(&mic_sem, 1);
__this->rec_state = RECORDER_START;
err = server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
if (err == 0) {
puts("--------echo_cloud_start_rec: exit\n");
return 0;
}
return -1;
}
static int echo_cloud_recorder_stop(void)
{
int err;
union audio_req req;
if (!__this->enc_server || __this->rec_state == RECORDER_STOP) {
return 0;
}
__this->rec_state = RECORDER_STOP;
os_sem_post(&__this->sem);
req.enc.cmd = AUDIO_ENC_CLOSE;
err = server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
if (err == 0) {
ai_server_event_notify(&echo_cloud_sdk_api, NULL, AI_SERVER_EVENT_MIC_CLOSE);
}
if (__this->voice_mode == WECHAT_MODE && __this->rec_total_len < WECHAT_ENC_BUFFER_MIN_LEN) {
ai_server_event_notify(&echo_cloud_sdk_api, NULL, AI_SERVER_EVENT_REC_TOO_SHORT);
}
return 0;
}
void JL_echo_cloud_media_speak_play(const char *url)
{
__this->curr_url_type = ECHO_CLOUD_SPEEK_URL;
ai_server_event_url(&echo_cloud_sdk_api, url, AI_SERVER_EVENT_URL);
}
void JL_echo_cloud_wechat_speak_play(const char *url)
{
char *save_url = NULL;
if (url && strlen(url) > 0) {
save_url = (char *)malloc(strlen(url) + 1);
if (!save_url) {
return;
}
strcpy(save_url, url);
if (ai_server_event_notify(&echo_cloud_sdk_api, save_url, AI_SERVER_EVENT_RECV_CHAT)) {
free(save_url);
}
}
}
void JL_echo_cloud_media_audio_play(const char *url)
{
__this->curr_url_type = ECHO_CLOUD_MEDIA_URL;
ai_server_event_url(&echo_cloud_sdk_api, url, AI_SERVER_EVENT_URL);
}
void JL_echo_cloud_media_audio_continue(const char *url)
{
ai_server_event_url(&echo_cloud_sdk_api, url, AI_SERVER_EVENT_CONTINUE);
}
void JL_echo_cloud_media_audio_pause(const char *url)
{
ai_server_event_url(&echo_cloud_sdk_api, url, AI_SERVER_EVENT_PAUSE);
}
void JL_echo_cloud_upgrade_notify(int event, void *arg)
{
ai_server_event_notify(&echo_cloud_sdk_api, arg, event);
}
void JL_echo_cloud_volume_change_notify(int volume)
{
ai_server_event_notify(&echo_cloud_sdk_api, (void *)volume, AI_SERVER_EVENT_VOLUME_CHANGE);
}
void JL_echo_cloud_child_lock_change_notify(int value)
{
ai_server_event_notify(&echo_cloud_sdk_api, (void *)value, AI_SERVER_EVENT_CHILD_LOCK_CHANGE);
}
void JL_echo_cloud_light_change_notify(int value)
{
ai_server_event_notify(&echo_cloud_sdk_api, (void *)value, AI_SERVER_EVENT_LIGHT_CHANGE);
}
__attribute__((weak)) int get_echo_cloud_device_id(char *device_id, u32 len)
{
return -1;
}
__attribute__((weak)) int get_echo_cloud_hash_key(char *hash_key, u32 len)
{
return -1;
}
__attribute__((weak)) int get_echo_cloud_uuid(char *uuid, u32 len)
{
return -1;
}
__attribute__((weak)) const char *get_echo_cloud_firmware_version(void)
{
return "0.0.0.0";
}
__attribute__((weak)) int check_echo_cloud_firmware_version(const char *url, const char *new_ver, const char *checksum)
{
return 0;
}
__attribute__((weak)) int get_app_music_volume(void)
{
return 100;
}
__attribute__((weak)) int get_app_music_playtime(void)
{
return 0;
}
__attribute__((weak)) int get_app_music_light_intensity(void)
{
return 100;
}
__attribute__((weak)) int get_app_music_battery_power(void)
{
return 100;
}
__attribute__((weak)) int ai_platform_if_support_poweron_recommend(void)
{
return 1;
}
static int get_echo_cloud_profile(struct echo_cloud_hdl *echo)
{
int ret = 0;
ret = get_echo_cloud_device_id(echo->auth.device_id, DEVICE_ID_LEN + 1);
if (ret) {
return ret;
}
ret = get_echo_cloud_hash_key(echo->auth.hash, HASH_LEN + 1);
if (ret) {
return ret;
}
ret = get_echo_cloud_uuid(echo->auth.channel_uuid, UUID_LEN + 1);
if (ret) {
return ret;
}
return ret;
}
static void echo_cloud_heart_beat(void *priv)
{
struct echo_cloud_hdl *p = (struct echo_cloud_hdl *)priv;
json_object *cmd_data = NULL;
if (p->media_play_state != ECHO_CLOUD_MEDIA_STATE_STOP) {
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "token", json_object_new_string(p->token.media_play_token));
json_object_object_add(cmd_data, "offset", json_object_new_int(get_app_music_playtime() * 1000));
echo_cloud_msg_http_req(&p->http, MEDIA_PLAYER_PROGRESS_CHANGER, cmd_data);
return;
}
if (!p->is_record) {
cmd_data = json_object_new_object();
echo_cloud_msg_http_req(&p->http, DEVICE_HEARTBEAT, cmd_data);
}
}
static void echo_cloud_device_status_sync(void *priv)
{
struct echo_cloud_hdl *p = (struct echo_cloud_hdl *)priv;
json_object *cmd_data = NULL;
if (!p->is_record) {
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "light", json_object_new_int(get_app_music_light_intensity()));
echo_cloud_msg_http_req(&p->http, LIGHT_CHANGED, cmd_data);
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "battery", json_object_new_int(get_app_music_battery_power()));
echo_cloud_msg_http_req(&p->http, BATTERY_CHANGED, cmd_data);
}
}
static void get_device_mac_address(char *mac_address, u32 str_len)
{
char *p = mac_address;
char mac_addr[6];
extern int wifi_get_mac(char *mac_addr);
wifi_get_mac(mac_addr);
for (int i = 0; i < 6 && i < str_len / 3; i++) {
*(p++) = *((char *)"0123456789ABCDEF" + ((mac_addr[i] >> 4) & 0x0f));
*(p++) = *((char *)"0123456789ABCDEF" + (mac_addr[i] & 0x0f));
*(p++) = ':';
}
*(--p) = '\0';
}
static void echo_cloud_media_stop_notify(struct echo_cloud_hdl *p, int offset)
{
if (p->media_play_state != ECHO_CLOUD_MEDIA_STATE_STOP) {
json_object *cmd_data = json_object_new_object();
p->media_play_state = ECHO_CLOUD_MEDIA_STATE_STOP;
json_object_object_add(cmd_data, "token", json_object_new_string(p->token.media_play_token));
json_object_object_add(cmd_data, "offset", json_object_new_int(offset * 1000));
echo_cloud_msg_http_req(&p->http, MEDIA_PLAYER_STOPPED, cmd_data);
}
}
static void echo_cloud_update_info(struct echo_cloud_hdl *p)
{
json_object *cmd_data = NULL;
char mac_address[18];
get_device_mac_address(mac_address, 18);
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "firmware_version", json_object_new_string(get_echo_cloud_firmware_version()));
json_object_object_add(cmd_data, "mac_address", json_object_new_string(mac_address));
json_object_object_add(cmd_data, "reconnect", json_object_new_boolean(true));
echo_cloud_msg_http_req(&p->http, DEVICE_ONLINE, cmd_data);
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "volume", json_object_new_int(get_app_music_volume()));
echo_cloud_msg_http_req(&p->http, VOLUME_CHANGED, cmd_data);
static const char input_text[] = {
0xE6, 0x92, 0xAD, 0xE6, 0x94, 0xBE, 0xE5, 0x84, 0xBF, 0xE6, 0xAD, 0x8C, 0x00
};
if (ai_platform_if_support_poweron_recommend()) {
cmd_data = json_object_new_object();
/* json_object_object_add(cmd_data, "text", json_object_new_string("播放黄凯芹的歌")); */
json_object_object_add(cmd_data, "text", json_object_new_string(input_text));
p->media_play_opt = MEDIA_IGNORE_SPEEK;
echo_cloud_msg_http_req(&p->http, AI_DIALOG_INPUT, cmd_data);
p->media_play_opt = MEDIA_HAS_PALY;
}
p->heartbeat_timer = sys_timer_add(p, echo_cloud_heart_beat, 5000);
p->sync_timer = sys_timer_add(p, echo_cloud_device_status_sync, 90000);
echo_cloud_device_status_sync(p);
}
static void echo_cloud_app_task(void *priv)
{
struct echo_cloud_hdl *p = (struct echo_cloud_hdl *)priv;
int msg[32];
int err;
json_object *cmd_data = NULL;
memset(p, 0, sizeof(struct echo_cloud_hdl));
#if 0
strcpy(p->auth.device_id, "AI000000000000000000000000000000");
strcpy(p->auth.channel_uuid, "2900a1f8-d1d0-41ad-90af-b59779210b28");
strcpy(p->auth.hash, "BKsY0nCiD6tpng4sldALH1kjWuV3BnfysuVzypbC");
#else
while (0 != get_echo_cloud_profile(p)) {
puts("echo_cloud get profile fail ! \n");
os_time_dly(50);
if (__this->exit_flag) {
__this->exit_flag = 0;
return;
}
}
#endif
p->http.auth = &p->auth;
p->http.priv = p;
p->http.timeout_ms = 5000;
p->http.out_cb = echo_cloud_rcv_json_handler;
p->media_play_opt = MEDIA_HAS_PALY;
p->media_play_state = ECHO_CLOUD_MEDIA_STATE_STOP;
os_mutex_pend(&__this->mutex, 0);
if (__this->exit_flag || echo_cloud_mqtt_init(&p->auth)) {
os_mutex_post(&__this->mutex);
__this->exit_flag = 0;
return;
}
os_mutex_post(&__this->mutex);
echo_cloud_update_info(p);
__this->connect_status = 1;
while (1) {
err = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
if (err != OS_TASKQ || msg[0] != Q_USER) {
continue;
}
if (__this->exit_flag) {
if (msg[1] == ECHO_CLOUD_MQTT_MSG_DEAL) {
free((void *)msg[2]);
continue;
} else if (msg[1] != ECHO_CLOUD_QUIT) {
continue;
}
}
switch (msg[1]) {
case ECHO_CLOUD_RECORD_START:
if (!p->is_record) {
u8 voice_mode = msg[2] & 0x3;
if (0 == echo_cloud_enc_http_start(&p->http, voice_mode)) {
echo_cloud_recorder_start(8000, msg[2], msg[2] & VAD_ENABLE);
__this->msg_notify_disable = 1;
p->is_record = true;
}
}
break;
case ECHO_CLOUD_RECORD_SEND:
if (p->is_record) {
err = echo_cloud_enc_http_send(&p->http, (void *)msg[2], msg[3]);
os_sem_post((OS_SEM *)msg[4]);
if (err) {
echo_cloud_recorder_stop();
echo_cloud_enc_http_close(&p->http);
p->is_record = false;
__this->msg_notify_disable = 0;
}
}
break;
case ECHO_CLOUD_RECORD_STOP:
if (p->is_record) {
echo_cloud_recorder_stop();
echo_cloud_send_last_packet(&p->http);
echo_cloud_enc_http_close(&p->http);
p->is_record = false;
__this->msg_notify_disable = 0;
}
break;
case ECHO_CLOUD_RECORD_ERR:
if (p->is_record) {
echo_cloud_recorder_stop();
echo_cloud_enc_http_close(&p->http);
p->is_record = false;
__this->msg_notify_disable = 0;
if (__this->voice_mode != WECHAT_MODE) {
ai_server_event_notify(&echo_cloud_sdk_api, NULL, AI_SERVER_EVENT_REC_ERR);
}
}
break;
case ECHO_CLOUD_PREVIOUS_SONG:
puts("===========ECHO_CLOUD_PREVIOUS_SONG\n");
p->media_play_state = ECHO_CLOUD_MEDIA_STATE_STOP;
p->media_play_opt = MEDIA_PLAY_IMMEDIATELY;
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "token", json_object_new_string(p->token.media_play_token));
echo_cloud_msg_http_req(&p->http, MEDIA_PLAYER_PREVIOUS_DEVICE, cmd_data);
p->media_play_opt = MEDIA_HAS_PALY;
break;
case ECHO_CLOUD_MEDIA_END:
case ECHO_CLOUD_NEXT_SONG:
puts("===========ECHO_CLOUD_NEXT_SONG\n");
p->media_play_state = ECHO_CLOUD_MEDIA_STATE_STOP;
p->media_play_opt = MEDIA_PLAY_IMMEDIATELY;
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "token", json_object_new_string(p->token.media_play_token));
echo_cloud_msg_http_req(&p->http, MEDIA_PLAYER_NEXT_DEVICE, cmd_data);
p->media_play_opt = MEDIA_HAS_PALY;
break;
case ECHO_CLOUD_MEDIA_STOP:
echo_cloud_media_stop_notify(p, msg[2]);
break;
case ECHO_CLOUD_SPEAK_END:
puts("===========ECHO_CLOUD_SPEAK_END\n");
/* cmd_data = json_object_new_object(); */
/* json_object_object_add(cmd_data, "token", json_object_new_string(p->token.ai_dialog_token)); */
/* echo_cloud_msg_http_req(&p->http, AI_DIALOG_FINISHED, cmd_data); */
if (MEDIA_WAIT_PLAY == p->media_play_opt && p->media_url) {
p->media_play_opt = MEDIA_HAS_PALY;
JL_echo_cloud_media_audio_play(p->media_url);
p->media_play_state = ECHO_CLOUD_MEDIA_STATE_START;
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "token", json_object_new_string(p->token.media_play_token));
echo_cloud_msg_http_req(&p->http, MEDIA_PLAYER_STARTED, cmd_data);
}
break;
case ECHO_CLOUD_PLAY_PAUSE:
if (p->media_play_state != ECHO_CLOUD_MEDIA_STATE_STOP) {
int is_pause = msg[2];
cmd_data = json_object_new_object();
if (is_pause) {
p->media_play_state = ECHO_CLOUD_MEDIA_STATE_PAUSE;
json_object_object_add(cmd_data, "token", json_object_new_string(p->token.media_play_token));
json_object_object_add(cmd_data, "offset", json_object_new_int(1000 * get_app_music_playtime()));
echo_cloud_msg_http_req(&p->http, MEDIA_PLAYER_PAUSED, cmd_data);
} else {
p->media_play_state = ECHO_CLOUD_MEDIA_STATE_START;
echo_cloud_msg_http_req(&p->http, MEDIA_PLAYER_RESUMED, cmd_data);
}
}
break;
case ECHO_CLOUD_VOLUME_CHANGE:
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "volume", json_object_new_int(msg[2]));
echo_cloud_msg_http_req(&p->http, VOLUME_CHANGED, cmd_data);
break;
case ECHO_CLOUD_COLLECT_RESOURCE:
;
int is_play_collect = msg[2];
if (!is_play_collect && p->media_url) {
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "token", json_object_new_string(p->token.media_play_token));
echo_cloud_msg_http_req(&p->http, MEDIA_PLAYER_FAVORITE_DEVICE, cmd_data);
}
if (is_play_collect) {
p->media_play_state = ECHO_CLOUD_MEDIA_STATE_STOP;
p->media_play_opt = MEDIA_PLAY_IMMEDIATELY;
cmd_data = json_object_new_object();
echo_cloud_msg_http_req(&p->http, MEDIA_PLAYER_PLAY_FAVORITE_DEVICE, cmd_data);
p->media_play_opt = MEDIA_HAS_PALY;
}
break;
case ECHO_CLOUD_CHILD_LOCK_CHANGE:
cmd_data = json_object_new_object();
json_object_object_add(cmd_data, "child_lock", json_object_new_boolean(msg[2]));
echo_cloud_msg_http_req(&p->http, CHILD_LOCK_CHANGED, cmd_data);
break;
case ECHO_CLOUD_DEVICE_CODE_REPORT:
echo_cloud_media_stop_notify(p, msg[2]);
cmd_data = json_object_new_object();
echo_cloud_msg_http_req(&p->http, DEVICE_REQUEST_CODE, cmd_data);
break;
case ECHO_CLOUD_MQTT_MSG_DEAL:
if (p->media_play_opt != MEDIA_WAIT_PLAY) {
p->media_play_opt = MEDIA_PLAY_IMMEDIATELY;
p->http.out_cb(p, (const char *)msg[2]);
p->media_play_opt = MEDIA_HAS_PALY;
} else {
p->http.out_cb(p, (const char *)msg[2]);
}
free((void *)msg[2]);
break;
case ECHO_CLOUD_QUIT:
sys_timer_del(p->heartbeat_timer);
sys_timer_del(p->sync_timer);
if (p->is_record) {
echo_cloud_recorder_stop();
echo_cloud_enc_http_close(&p->http);
p->is_record = false;
}
echo_cloud_msg_http_close(&p->http);
/* p->http.timeout_ms = 1000; */
/* cmd_data = json_object_new_object(); */
/* echo_cloud_msg_http_req(&p->http, DEVICE_OFFLINE, cmd_data); */
free(p->media_url);
__this->msg_notify_disable = 0;
__this->exit_flag = 0;
return;
default:
break;
}
}
}
static int echo_cloud_app_init(void)
{
__this->exit_flag = 0;
__this->connect_status = 0;
return thread_fork("echo_cloud_app_task", 22, 1024, 128, &__this->app_task_pid, echo_cloud_app_task, &__this->hdl);
}
static void echo_cloud_app_uninit(void)
{
__this->exit_flag = 1;
__this->connect_status = 0;
os_mutex_pend(&__this->mutex, 0);
echo_cloud_mqtt_uninit();
os_mutex_post(&__this->mutex);
do {
if (OS_Q_FULL != os_taskq_post("echo_cloud_app_task", 1, ECHO_CLOUD_QUIT)) {
break;
}
puts("echo_cloud_app_task send msg QUIT timeout \n");
http_cancel_dns(&__this->hdl.http.ctx);
http_cancel_dns(&__this->hdl.http.rec_ctx);
os_time_dly(2);
} while (1);
while (__this->exit_flag) {
http_cancel_dns(&__this->hdl.http.ctx);
http_cancel_dns(&__this->hdl.http.rec_ctx);
}
thread_kill(&__this->app_task_pid, KILL_WAIT);
}
static int echo_cloud_sdk_open(void)
{
os_sem_create(&__this->sem, 0);
os_mutex_create(&__this->mutex);
return echo_cloud_app_init();
}
static int echo_cloud_sdk_check(void)
{
if (__this->connect_status) {
return AI_STAT_CONNECTED;
}
return AI_STAT_DISCONNECTED;
}
static int echo_cloud_sdk_disconnect(void)
{
echo_cloud_recorder_stop();
echo_cloud_app_uninit();
if (__this->enc_server) {
server_close(__this->enc_server);
__this->enc_server = NULL;
}
os_sem_del(&__this->sem, 1);
os_mutex_del(&__this->mutex, 1);
return 0;
}
REGISTER_AI_SDK(echo_cloud_sdk_api) = {
.name = "echo_cloud",
.connect = echo_cloud_sdk_open,
.state_check = echo_cloud_sdk_check,
.do_event = echo_cloud_sdk_do_event,
.disconnect = echo_cloud_sdk_disconnect,
};