doubao_chat/lib/net/libduer-device/examples/dcs3.0-demo/duerapp.c

568 lines
14 KiB
C

/**
* Copyright (2017) Baidu Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* File: duerapp.c
* Auth: Renhe Zhang (v_zhangrenhe@baidu.com)
* Desc: Duer Application Main.
*/
#include <string.h>
#include <stdlib.h>
#include "printf.h"
#include "typedef.h"
#include "duerapp_config.h"
#include "lightduer_connagent.h"
#include "lightduer_voice.h"
#include "lightduer_dcs.h"
#include "lightduer_timestamp.h"
#include "lightduer_dcs_alert.h"
#include "lightduer_memory.h"
#include "lightduer_timers.h"
#include "duerapp_recorder.h"
#include "duerapp_media.h"
#include "duerapp_event.h"
#include "duerapp_alert.h"
#include "duerapp.h"
#include "os/os_api.h"
#include "lightduer_system_info.h"
#include "lightduer_bind_device.h"
#include "net_timer.h"
duer_system_static_info_t g_system_static_info = {
.os_version = "FreeRTOS",
.sw_version = "DCS3.0",
.brand = "Baidu",
.hardware_version = "1.0.0",
.equipment_type = "AC521x",
.ram_size = 2 * 1024,
.rom_size = 4 * 1024,
};
void set_duer_system_static_info(const char *os_version,
const char *sw_version,
const char *brand,
const char *hardware_version,
const char *equipment_type,
u32 ram_KB,
u32 rom_KB)
{
strncpy(g_system_static_info.os_version, os_version, OS_VERSION_LEN);
g_system_static_info.os_version[OS_VERSION_LEN] = 0;
strncpy(g_system_static_info.sw_version, sw_version, SW_VERSION_LEN);
g_system_static_info.os_version[SW_VERSION_LEN] = 0;
strncpy(g_system_static_info.brand, brand, BRAND_LEN);
g_system_static_info.os_version[BRAND_LEN] = 0;
strncpy(g_system_static_info.hardware_version, hardware_version, HARDWARE_VERSION_LEN);
g_system_static_info.os_version[HARDWARE_VERSION_LEN] = 0;
strncpy(g_system_static_info.equipment_type, equipment_type, EQUIPMENT_TYPE_LEN);
g_system_static_info.os_version[EQUIPMENT_TYPE_LEN] = 0;
g_system_static_info.ram_size = ram_KB;
g_system_static_info.rom_size = rom_KB;
}
__attribute__((weak)) int ai_platform_if_support_poweron_recommend(void)
{
return 1;
}
static duer_bool s_is_initialized;
static duer_bool s_is_binded;
static volatile duer_bool s_started = false;
static duer_bool duer_app_init_flag = false;
static duer_timer_handler g_duer_timer = NULL;
static duer_u16_t g_duer_start_timeout = DUER_RESTART_TIMEOUT;
static duer_bool s_is_not_first;
static int duer_app_task_pid;
static duer_status_t duer_app_test_control_point(duer_context ctx, duer_msg_t *msg, duer_addr_t *addr)
{
DUER_LOGI("duer_app_test_control_point");
if (msg) {
duer_response(msg, DUER_MSG_RSP_INVALID, NULL, 0);
} else {
return DUER_ERR_FAILED;
}
printf("token:0x");
for (int i = 0; i < msg->token_len; ++i) {
printf("%x", msg->token[i]);
}
printf("\n");
duer_u8_t *cachedToken = DUER_MALLOC(msg->token_len);
DUER_MEMCPY(cachedToken, msg->token, msg->token_len);
printf("token:0x");
for (int i = 0; i < msg->token_len; ++i) {
printf("%x", cachedToken[i]);
}
printf("\n");
baidu_json *payload = baidu_json_CreateObject();
baidu_json_AddStringToObject(payload, "result", "OK");
baidu_json_AddNumberToObject(payload, "timestamp", duer_timestamp());
duer_seperate_response((const char *)cachedToken, msg->token_len, DUER_MSG_RSP_CONTENT, payload);
if (payload) {
baidu_json_Delete(payload);
}
DUER_FREE(cachedToken);
return DUER_OK;
}
static void duer_app_test_control_point_init()
{
duer_res_t res[] = {
{
DUER_RES_MODE_DYNAMIC,
DUER_RES_OP_PUT,
"duer_app_test_cp",
.res.f_res = duer_app_test_control_point
},
};
duer_add_resources(res, sizeof(res) / sizeof(res[0]));
}
static int duer_dcs_recommend_request_iftt(void)
{
baidu_json *data = NULL;
data = baidu_json_CreateObject();
if (!data) {
DUER_LOGE("Memory not enough");
return DUER_ERR_FAILED;
}
baidu_json_AddNumberToObject(data, "dueros_boot_remind_dcs", 3);
duer_data_report(data);
baidu_json_Delete(data);
return DUER_OK;
}
#ifdef DUER_WECHAT_SUPPORT
#include "lightduer_dcs_local.h"
#define DCS_WECHAT_SPEAK_OUTPUT_NAME "Speak"
#define DCS_WECHAT_NAMESPACE "ai.dueros.device_interface.iot_cloud.wechat"
extern void duer_wechat_speak_play(const char *url);
static void duer_dcs_wechat_speak_handler(const char *url)
{
duer_wechat_speak_play(url);
}
static duer_status_t duer_wechat_speak_output_cb(const baidu_json *directive)
{
baidu_json *payload = NULL;
baidu_json *url = NULL;
duer_status_t ret = DUER_OK;
payload = baidu_json_GetObjectItem(directive, DCS_PAYLOAD_KEY);
if (!payload) {
return DUER_MSG_RSP_BAD_REQUEST;
}
url = baidu_json_GetObjectItem(payload, DCS_URL_KEY);
if (!url) {
return DUER_MSG_RSP_BAD_REQUEST;
}
duer_dcs_wechat_speak_handler(url->valuestring);
return ret;
}
static void duer_dcs_wechat_init(void)
{
DUER_DCS_CRITICAL_ENTER();
if (s_is_initialized) {
DUER_DCS_CRITICAL_EXIT();
return;
}
duer_directive_list res[] = {
{DCS_WECHAT_SPEAK_OUTPUT_NAME, duer_wechat_speak_output_cb},
};
duer_add_dcs_directive_internal(res, sizeof(res) / sizeof(res[0]), DCS_WECHAT_NAMESPACE);
s_is_initialized = DUER_TRUE;
DUER_DCS_CRITICAL_EXIT();
}
static void duer_dcs_wechat_uninitialize(void)
{
s_is_initialized = DUER_FALSE;
}
#endif
static void duer_app_dcs_init()
{
duer_dcs_framework_init();
duer_dcs_voice_input_init();
duer_dcs_voice_output_init();
duer_dcs_speaker_control_init();
duer_dcs_audio_player_init();
duer_dcs_screen_init();
duer_dcs_alert_init();
#ifdef DUER_WECHAT_SUPPORT
duer_dcs_wechat_init();
#endif
duer_dcs_sync_state();
duer_app_test_control_point_init();
#ifdef OTA_REG_UPDATE
duer_app_ota_init();
#endif
/* duer_my_dcs_init(); */
#ifdef DUER_WECHAT_SUPPORT
#ifdef DUER_HTTPS_SUPPORT
duer_dcs_capability_declare(DCS_TTS_HTTPS_PROTOCAL_SUPPORTED | DCS_WECHAT_SUPPORTED);
#else
duer_dcs_capability_declare(DCS_WECHAT_SUPPORTED);
#endif
/* duer_dcs_recommend_request(0); */
#endif
if (!s_is_not_first) {
if (ai_platform_if_support_poweron_recommend()) {
duer_dcs_recommend_request_iftt();
}
s_is_not_first = DUER_TRUE;
}
}
static void duer_app_dcs_uninitialize()
{
duer_dcs_uninitialize();
#ifdef DUER_WECHAT_SUPPORT
duer_dcs_wechat_uninitialize();
#endif
}
static void duer_test_start(const char *profile)
{
const char *data = duer_load_profile(profile);
if (data == NULL) {
DUER_LOGE("load profile failed!");
if (g_duer_timer != NULL) {
duer_timer_stop(g_duer_timer);
g_duer_start_timeout = DUER_RESTART_TIMEOUT * 2;
duer_timer_start(g_duer_timer, g_duer_start_timeout);
}
return;
}
DUER_LOGD("profile: \n%s", data);
// We start the duer with duer_start(), when network connected.
duer_start(data, strlen(data));
#ifndef LOAD_PROFILE_BY_FLASH
DUER_FREE((void *)data);
#endif
#ifdef DUER_WECHAT_SUPPORT
if (s_is_binded == DUER_FALSE) {
s_is_binded = DUER_TRUE;
duer_start_bind_device_task(90);
}
#endif
}
static void duer_app_timer_expired(void *param)
{
int msg[3];
msg[0] = (int)duer_test_start;
msg[1] = 1;
msg[2] = (int)DUER_PROFILE_PATH;;
if (os_taskq_post_type("duer_app_task", Q_CALLBACK, 3, msg)) {
DUER_LOGE("duer_test_start restart os_taskq_post error\n");
}
}
static void duer_event_hook(duer_event_t *event)
{
if (!event) {
DUER_LOGE("NULL event!!!");
}
DUER_LOGD("event: %d", event->_event);
switch (event->_event) {
case DUER_EVENT_STARTED:
duer_app_dcs_init();
s_started = true;
if (g_duer_timer != NULL) {
duer_timer_stop(g_duer_timer);
g_duer_start_timeout = DUER_RESTART_TIMEOUT;
}
break;
case DUER_EVENT_STOPPED:
s_started = false;
if (duer_app_init_flag) {
if (g_duer_timer != NULL) {
DUER_LOGI("timerout:%d \n", g_duer_start_timeout);
duer_timer_stop(g_duer_timer);
duer_timer_start(g_duer_timer, g_duer_start_timeout);
if (g_duer_start_timeout < 1000 * 8) {
g_duer_start_timeout <<= 1;
}
}
}
break;
default:
break;
}
}
static void duer_app_task(void *priv)
{
s_is_binded = DUER_FALSE;
//init timer task
net_timer_init();
// init CA
duer_initialize();
// Set the Duer Event Callback
duer_set_event_callback(duer_event_hook);
//init recorder
/* duer_recorder_init(); */
//init alarm
/* duer_init_alarm(); */
// init media
duer_media_init();
if (g_duer_timer == NULL) {
g_duer_timer = duer_timer_acquire(duer_app_timer_expired, NULL, DUER_TIMER_ONCE);
}
// try conntect baidu cloud
duer_test_start(DUER_PROFILE_PATH);
duer_event_loop();
#ifdef OTA_REG_UPDATE
duer_app_ota_uninitialize();
#endif
duer_stop_bind_device_task();
net_timer_uninit();
DUER_LOGI("DUER OS GOOD BYE !!!");
s_is_not_first = DUER_FALSE;
}
void duer_dcs_speak_handler(const char *url)
{
if (DUER_VOICE_MODE_DEFAULT != duer_voice_get_mode()
&& RECORDER_START == duer_get_recorder_state()) {
duer_dcs_stop_listen_handler();
}
duer_media_speak_play(url);
DUER_LOGI("SPEAK url:%s", url);
}
void duer_dcs_audio_play_handler(const duer_dcs_audio_info_t *audio_info)
{
DUER_LOGI("Audio paly offset:%d url:%s", audio_info->offset, audio_info->url);
if (audio_info->offset && audio_info->offset != 1) {
duer_media_audio_resume(audio_info->url, audio_info->offset);
} else {
duer_media_audio_start(audio_info->url);
}
}
void duer_dcs_get_speaker_state(int *volume, duer_bool *is_mute)
{
if (volume) {
*volume = duer_media_get_volume();
}
if (is_mute) {
*is_mute = duer_media_get_mute();
}
}
void duer_dcs_volume_set_handler(int volume)
{
duer_media_set_volume(volume);
}
void duer_dcs_volume_adjust_handler(int volume)
{
duer_media_volume_change(volume);
}
void duer_dcs_mute_handler(duer_bool is_mute)
{
duer_media_set_mute(is_mute);
}
void duer_dcs_audio_stop_handler(void)
{
if (MEDIA_AUDIO_PLAY == duer_media_audio_state()) {
extern void JL_duer_media_audio_pause(const char *url);
JL_duer_media_audio_pause(NULL);
duer_media_audio_pause();
}
}
void duer_dcs_audio_resume_handler(const duer_dcs_audio_info_t *audio_info)
{
duer_media_audio_resume(audio_info->url, audio_info->offset);
DUER_LOGI("Audio resume offset:%d url:%s", audio_info->offset, audio_info->url);
}
void duer_dcs_audio_pause_handler(void)
{
duer_media_audio_pause();
}
int duer_dcs_audio_get_play_progress(void)
{
int pos = duer_media_audio_get_position();
DUER_LOGI("PAUSE offset : %d", pos);
return pos;
}
void duer_dcs_listen_handler(void)
{
do {
if (OS_Q_FULL != os_taskq_post("duer_app_task", 2, DUER_RECORD_START, 0)) {
break;
}
DUER_LOGW("duer_app_task send msg DUER_RECORD_START timeout ");
msleep(20);
} while (1);
}
void duer_dcs_stop_listen_handler(void)
{
OS_SEM sem;
os_sem_create(&sem, 0);
do {
if (OS_Q_FULL != os_taskq_post("duer_app_task", 2, DUER_RECORD_STOP, (int)&sem)) {
break;
}
DUER_LOGW("duer_app_task send msg DUER_RECORD_STOP timeout ");
msleep(20);
} while (1);
os_sem_pend(&sem, 0); //等待麦克风关闭
os_sem_del(&sem, 1);
}
bool duer_app_get_connect_state()
{
return s_started;
}
duer_status_t duer_dcs_render_card_handler(baidu_json *payload)
{
baidu_json *type = NULL;
baidu_json *content = NULL;
duer_status_t ret = DUER_OK;
do {
if (!payload) {
ret = DUER_ERR_FAILED;
break;
}
type = baidu_json_GetObjectItem(payload, "type");
if (!type) {
ret = DUER_ERR_FAILED;
break;
}
if (strcmp("TextCard", type->valuestring) == 0) {
content = baidu_json_GetObjectItem(payload, "content");
if (!content) {
ret = DUER_ERR_FAILED;
break;
}
DUER_LOGI("Render card content: %s", content->valuestring);
}
} while (0);
return ret;
}
duer_status_t duer_dcs_input_text_handler(const char *text, const char *type)
{
DUER_LOGI("ASR result: %s", text);
return DUER_OK;
}
void duer_dcs_stop_speak_handler(void)
{
DUER_LOGI("stop speak");
duer_media_speak_stop();
}
int duer_app_init(void)
{
if (!duer_app_init_flag) {
duer_app_init_flag = 1;
return thread_fork("duer_app_task", 26, 768, 128, &duer_app_task_pid, duer_app_task, NULL);
}
return -1;
}
void duer_app_uninit(void)
{
if (duer_app_init_flag) {
duer_app_init_flag = 0;
if (g_duer_timer) {
duer_timer_stop(g_duer_timer);
duer_timer_release(g_duer_timer);
g_duer_timer = NULL;
}
duer_dcs_del_all_alert();
duer_app_dcs_uninitialize();
do {
if (OS_Q_FULL != os_taskq_post("duer_app_task", 1, DUER_QUIT)) {
break;
}
DUER_LOGW("duer_app_task send msg DUER_QUIT timeout ");
msleep(20);
} while (1);
thread_kill(&duer_app_task_pid, KILL_WAIT);
}
}