468 lines
13 KiB
C
468 lines
13 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: lightduer_dcs_system.c
|
|
* Auth: Gang Chen (chengang12@baidu.com)
|
|
* Desc: apply APIs to support DCS audio system interface.
|
|
*/
|
|
|
|
#include "lightduer_dcs.h"
|
|
#include "lightduer_dcs_local.h"
|
|
#include "lightduer_log.h"
|
|
#include "lightduer_ca.h"
|
|
#include "lightduer_event_emitter.h"
|
|
#include "lightduer_dcs_router.h"
|
|
#include "lightduer_timers.h"
|
|
#include "lightduer_connagent.h"
|
|
#include "lightduer_timestamp.h"
|
|
#include "lightduer_ds_log_dcs.h"
|
|
|
|
static duer_timer_handler s_activity_timer;
|
|
static const int INACTIVIRY_REPORT_PERIOD = 3600 * 1000; // 1 hour
|
|
static volatile int s_last_activity_time; // latest user activity time in seconds
|
|
static const char *SYSTEM_INTERFACE_NAMESPACE = "ai.dueros.device_interface.system";
|
|
static duer_bool s_is_initialed;
|
|
static const char *TTS_PROTOCAL_KEY = "tts_protocol";
|
|
static const char *HTTPS_PROTOCAL = "https";
|
|
static const char *WECHAT_VERSION_KEY = "wechat_version";
|
|
static const char *WECHAT_VERSION = "1";
|
|
|
|
extern const char *duer_engine_get_uuid(void);
|
|
|
|
int duer_dcs_sync_state(void)
|
|
{
|
|
baidu_json *event = NULL;
|
|
baidu_json *data = NULL;
|
|
baidu_json *payload = NULL;
|
|
baidu_json *deviceInfo = NULL;
|
|
baidu_json *client_context = NULL;
|
|
duer_status_t ret = DUER_OK;
|
|
|
|
DUER_DCS_CRITICAL_ENTER();
|
|
if (!s_is_initialed) {
|
|
DUER_LOGW("DCS has not been initialized");
|
|
ret = DUER_ERR_FAILED;
|
|
goto RET;
|
|
}
|
|
|
|
data = baidu_json_CreateObject();
|
|
if (data == NULL) {
|
|
DUER_DS_LOG_REPORT_DCS_MEMORY_ERROR();
|
|
ret = DUER_ERR_MEMORY_OVERFLOW;
|
|
goto RET;
|
|
}
|
|
|
|
client_context = duer_get_client_context_internal();
|
|
if (client_context) {
|
|
baidu_json_AddItemToObjectCS(data, DCS_CLIENT_CONTEXT_KEY, client_context);
|
|
}
|
|
|
|
event = duer_create_dcs_event(SYSTEM_INTERFACE_NAMESPACE,
|
|
DCS_SYNCHRONIZE_STATE_NAME,
|
|
DUER_TRUE);
|
|
if (event == NULL) {
|
|
ret = DUER_ERR_FAILED;
|
|
goto RET;
|
|
}
|
|
|
|
baidu_json_AddItemToObjectCS(data, DCS_EVENT_KEY, event);
|
|
|
|
payload = baidu_json_GetObjectItem(event, DCS_PAYLOAD_KEY);
|
|
if (!payload) {
|
|
ret = DUER_ERR_FAILED;
|
|
goto RET;
|
|
}
|
|
|
|
// sys_info_ops_t *ops = g_sys_info.ops;
|
|
// ops->get_sys_info(&g_sys_info);
|
|
|
|
deviceInfo = baidu_json_CreateObject();
|
|
if (!deviceInfo) {
|
|
ret = DUER_ERR_FAILED;
|
|
goto RET;
|
|
}
|
|
|
|
baidu_json_AddItemToObjectCS(payload, "_deviceInfo", deviceInfo);
|
|
|
|
baidu_json_AddStringToObjectCS(deviceInfo, "sn", duer_engine_get_uuid());
|
|
|
|
// localAreaNetworkInfo_array = baidu_json_CreateArray();
|
|
// if (!localAreaNetworkInfo_array) {
|
|
// ret = DUER_ERR_FAILED;
|
|
// goto RET;
|
|
// }
|
|
|
|
// baidu_json_AddItemToObjectCS(payload, "_localAreaNetworkInfos", localAreaNetworkInfo_array);
|
|
|
|
// localAreaNetworkInfo = baidu_json_CreateObject();
|
|
// if (!localAreaNetworkInfo) {
|
|
// ret = DUER_ERR_FAILED;
|
|
// goto RET;
|
|
// }
|
|
// baidu_json_AddItemToArray(localAreaNetworkInfo_array, localAreaNetworkInfo);
|
|
|
|
// baidu_json_AddStringToObjectCS(localAreaNetworkInfo, "deviceMac", g_sys_info.mac);
|
|
// baidu_json_AddStringToObjectCS(localAreaNetworkInfo, "routerMac", g_sys_info.router_mac);
|
|
|
|
// char ipv4_addr[20] = {'\0'};
|
|
// snprintf(ipv4_addr, sizeof(ipv4_addr), "%d.%d.%d.%d",
|
|
// g_sys_info.sta_ip & 0xFF,
|
|
// (g_sys_info.sta_ip >> 8) & 0xFF,
|
|
// (g_sys_info.sta_ip >> 16) & 0xFF,
|
|
// (g_sys_info.sta_ip >> 24) & 0xFF);
|
|
// baidu_json_AddStringToObjectCS(localAreaNetworkInfo, "ipAddress", ipv4_addr);
|
|
// baidu_json_AddStringToObjectCS(localAreaNetworkInfo, "ssid", g_sys_info.ssid);
|
|
|
|
ret = duer_dcs_data_report_internal(data, DUER_TRUE);
|
|
|
|
RET:
|
|
DUER_DCS_CRITICAL_EXIT();
|
|
|
|
if (ret != DUER_OK) {
|
|
duer_ds_log_dcs_event_report_fail(DCS_SYNCHRONIZE_STATE_NAME);
|
|
}
|
|
|
|
if (data) {
|
|
baidu_json_Delete(data);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// get report bjson
|
|
baidu_json *duer_get_exception_internal(const char *directive, size_t directive_len,
|
|
const char *type, const char *msg)
|
|
{
|
|
baidu_json *event = NULL;
|
|
baidu_json *data = NULL;
|
|
baidu_json *payload = NULL;
|
|
baidu_json *error = NULL;
|
|
baidu_json *client_context = NULL;
|
|
duer_status_t ret = DUER_OK;
|
|
|
|
if (!directive || !type || !msg) {
|
|
DUER_DS_LOG_REPORT_DCS_PARAM_ERROR();
|
|
ret = DUER_ERR_INVALID_PARAMETER;
|
|
goto RET;
|
|
}
|
|
|
|
data = baidu_json_CreateObject();
|
|
if (data == NULL) {
|
|
DUER_DS_LOG_REPORT_DCS_MEMORY_ERROR();
|
|
ret = DUER_ERR_MEMORY_OVERFLOW;
|
|
goto RET;
|
|
}
|
|
|
|
client_context = duer_get_client_context_internal();
|
|
if (client_context) {
|
|
baidu_json_AddItemToObjectCS(data, DCS_CLIENT_CONTEXT_KEY, client_context);
|
|
}
|
|
|
|
event = duer_create_dcs_event(SYSTEM_INTERFACE_NAMESPACE,
|
|
DCS_EXCEPTION_ENCOUNTERED_NAME,
|
|
DUER_TRUE);
|
|
if (event == NULL) {
|
|
ret = DUER_ERR_FAILED;
|
|
goto RET;
|
|
}
|
|
baidu_json_AddItemToObjectCS(data, DCS_EVENT_KEY, event);
|
|
|
|
payload = baidu_json_GetObjectItem(event, DCS_PAYLOAD_KEY);
|
|
if (!payload) {
|
|
ret = DUER_ERR_FAILED;
|
|
goto RET;
|
|
}
|
|
baidu_json_AddStringToObjectCSWithLength(
|
|
payload, DCS_UNPARSED_DIRECTIVE_KEY, directive, directive_len);
|
|
|
|
error = baidu_json_CreateObject();
|
|
if (!error) {
|
|
DUER_DS_LOG_REPORT_DCS_MEMORY_ERROR();
|
|
ret = DUER_ERR_MEMORY_OVERFLOW;
|
|
goto RET;
|
|
}
|
|
baidu_json_AddItemToObjectCS(payload, DCS_ERROR_KEY, error);
|
|
baidu_json_AddStringToObjectCS(error, DCS_TYPE_KEY, type);
|
|
baidu_json_AddStringToObjectCS(error, DCS_MESSAGE_KEY, msg);
|
|
|
|
RET:
|
|
if (ret != DUER_OK) {
|
|
if (data) {
|
|
baidu_json_Delete(data);
|
|
}
|
|
data = NULL;
|
|
}
|
|
return data;
|
|
}
|
|
|
|
int duer_report_exception_internal(const char *directive, size_t directive_len,
|
|
const char *type, const char *msg)
|
|
{
|
|
duer_status_t ret = DUER_OK;
|
|
baidu_json *data = duer_get_exception_internal(directive, directive_len, type, msg);
|
|
if (!data) {
|
|
ret = DUER_ERR_FAILED;
|
|
goto RET;
|
|
}
|
|
ret = duer_dcs_data_report_internal(data, DUER_TRUE);
|
|
|
|
RET:
|
|
if (ret != DUER_OK) {
|
|
duer_ds_log_dcs_event_report_fail(DCS_EXCEPTION_ENCOUNTERED_NAME);
|
|
}
|
|
|
|
if (data) {
|
|
baidu_json_Delete(data);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int duer_dcs_sys_exit_internal(void)
|
|
{
|
|
baidu_json *event = NULL;
|
|
baidu_json *data = NULL;
|
|
int rs = DUER_OK;
|
|
|
|
do {
|
|
data = baidu_json_CreateObject();
|
|
if (data == NULL) {
|
|
DUER_DS_LOG_REPORT_DCS_MEMORY_ERROR();
|
|
rs = DUER_ERR_FAILED;
|
|
break;
|
|
}
|
|
|
|
event = duer_create_dcs_event(SYSTEM_INTERFACE_NAMESPACE, DCS_EXITED_NAME, DUER_TRUE);
|
|
if (event == NULL) {
|
|
rs = DUER_ERR_FAILED;
|
|
break;
|
|
}
|
|
|
|
baidu_json_AddItemToObjectCS(data, DCS_EVENT_KEY, event);
|
|
rs = duer_dcs_data_report_internal(data, DUER_TRUE);
|
|
} while (0);
|
|
|
|
if (rs != DUER_OK) {
|
|
duer_ds_log_dcs_event_report_fail(DCS_EXITED_NAME);
|
|
}
|
|
|
|
if (data) {
|
|
baidu_json_Delete(data);
|
|
}
|
|
|
|
return rs;
|
|
}
|
|
|
|
int duer_dcs_close_multi_dialog(void)
|
|
{
|
|
return duer_dcs_sys_exit_internal();
|
|
}
|
|
|
|
duer_status_t duer_dcs_capability_declare(duer_u32_t capability)
|
|
{
|
|
baidu_json *event = NULL;
|
|
baidu_json *payload = NULL;
|
|
baidu_json *data = NULL;
|
|
baidu_json *iotcloud_event = NULL;
|
|
duer_status_t rs = DUER_OK;
|
|
|
|
do {
|
|
if (capability == 0) {
|
|
break;
|
|
}
|
|
|
|
data = baidu_json_CreateObject();
|
|
if (data == NULL) {
|
|
DUER_DS_LOG_REPORT_DCS_MEMORY_ERROR();
|
|
rs = DUER_ERR_MEMORY_OVERFLOW;
|
|
break;
|
|
}
|
|
|
|
iotcloud_event = baidu_json_CreateObject();
|
|
if (iotcloud_event == NULL) {
|
|
DUER_DS_LOG_REPORT_DCS_MEMORY_ERROR();
|
|
rs = DUER_ERR_MEMORY_OVERFLOW;
|
|
break;
|
|
}
|
|
baidu_json_AddItemToObjectCS(data, DCS_IOTCLOUD_EVENT_PATH, iotcloud_event);
|
|
|
|
event = duer_create_dcs_event(DCS_IOT_CLOUD_SYSTEM_NAMESPACE,
|
|
DCS_IOT_CLOUD_CONTEXT,
|
|
DUER_TRUE);
|
|
if (!event) {
|
|
DUER_LOGE("Failed to create Context event");
|
|
rs = DUER_ERR_FAILED;
|
|
break;
|
|
}
|
|
baidu_json_AddItemToObjectCS(iotcloud_event, DCS_EVENT_KEY, event);
|
|
|
|
payload = baidu_json_GetObjectItem(event, "payload");
|
|
if (!payload) {
|
|
rs = DUER_ERR_FAILED;
|
|
break;
|
|
}
|
|
|
|
if (DCS_TTS_HTTPS_PROTOCAL_SUPPORTED & capability) {
|
|
baidu_json_AddStringToObjectCS(payload, TTS_PROTOCAL_KEY, HTTPS_PROTOCAL);
|
|
}
|
|
|
|
if (DCS_WECHAT_SUPPORTED & capability) {
|
|
baidu_json_AddStringToObjectCS(payload, WECHAT_VERSION_KEY, WECHAT_VERSION);
|
|
}
|
|
|
|
rs = duer_dcs_data_report_internal(data, DUER_TRUE);
|
|
} while (0);
|
|
|
|
if (data) {
|
|
baidu_json_Delete(data);
|
|
}
|
|
|
|
return rs;
|
|
}
|
|
|
|
static duer_status_t duer_exception_cb(const baidu_json *directive)
|
|
{
|
|
baidu_json *payload = NULL;
|
|
baidu_json *error_code = NULL;
|
|
baidu_json *description = NULL;
|
|
duer_status_t ret = DUER_OK;
|
|
|
|
payload = baidu_json_GetObjectItem(directive, DCS_PAYLOAD_KEY);
|
|
if (!payload) {
|
|
DUER_LOGE("Failed to parse payload\n");
|
|
ret = DUER_MSG_RSP_BAD_REQUEST;
|
|
goto RET;
|
|
}
|
|
|
|
error_code = baidu_json_GetObjectItem(payload, DCS_CODE_KEY);
|
|
if (!error_code) {
|
|
DUER_LOGE("Failed to get erorr code\n");
|
|
ret = DUER_MSG_RSP_BAD_REQUEST;
|
|
goto RET;
|
|
}
|
|
|
|
description = baidu_json_GetObjectItem(payload, DCS_DESCRIPTION_KEY);
|
|
if (!description || !description->valuestring) {
|
|
DUER_LOGE("Failed to get erorr description\n");
|
|
ret = DUER_MSG_RSP_BAD_REQUEST;
|
|
goto RET;
|
|
}
|
|
|
|
DUER_LOGE("error code: %s", error_code->valuestring);
|
|
DUER_LOGE("error: %s", description->valuestring);
|
|
|
|
if (DUER_STRCMP(description->valuestring, "BDUSS invalid") == 0) {
|
|
duer_dcs_system_invalid_bduss_handler();
|
|
}
|
|
|
|
RET:
|
|
return ret;
|
|
}
|
|
|
|
static void duer_inactivity_report_handler(int what, void *param)
|
|
{
|
|
int inactivity_time = 0;
|
|
baidu_json *event = NULL;
|
|
baidu_json *data = NULL;
|
|
baidu_json *payload = NULL;
|
|
|
|
data = baidu_json_CreateObject();
|
|
if (data == NULL) {
|
|
DUER_DS_LOG_REPORT_DCS_MEMORY_ERROR();
|
|
goto RET;
|
|
}
|
|
|
|
event = duer_create_dcs_event(SYSTEM_INTERFACE_NAMESPACE,
|
|
DCS_SYNCHRONIZE_STATE_NAME,
|
|
DUER_TRUE);
|
|
if (event == NULL) {
|
|
goto RET;
|
|
}
|
|
|
|
baidu_json_AddItemToObjectCS(data, DCS_EVENT_KEY, event);
|
|
payload = baidu_json_GetObjectItem(event, DCS_PAYLOAD_KEY);
|
|
if (!payload) {
|
|
goto RET;
|
|
}
|
|
|
|
inactivity_time = duer_timestamp() / 1000 - s_last_activity_time;
|
|
|
|
inactivity_time = inactivity_time > 0 ? inactivity_time : 0;
|
|
baidu_json_AddNumberToObjectCS(payload, DCS_INACTIVE_TIME_IN_SECONDS_KEY, inactivity_time);
|
|
|
|
duer_dcs_data_report_internal(data, DUER_TRUE);
|
|
|
|
RET:
|
|
if (data) {
|
|
baidu_json_Delete(data);
|
|
}
|
|
}
|
|
|
|
static void duer_inactivity_report(void *param)
|
|
{
|
|
duer_emitter_emit(duer_inactivity_report_handler, 0, NULL);
|
|
}
|
|
|
|
void duer_user_activity_internal(void)
|
|
{
|
|
s_last_activity_time = duer_timestamp() / 1000;
|
|
}
|
|
|
|
static duer_status_t duer_inactivity_reset_cb(const baidu_json *directive)
|
|
{
|
|
duer_user_activity_internal();
|
|
return DUER_OK;
|
|
}
|
|
|
|
static duer_status_t duer_nop_cb(const baidu_json *directive)
|
|
{
|
|
DUER_LOGI("Nop directive received");
|
|
return DUER_OK;
|
|
}
|
|
|
|
void duer_declare_sys_interface_internal(void)
|
|
{
|
|
if (s_is_initialed) {
|
|
return;
|
|
}
|
|
|
|
s_activity_timer = duer_timer_acquire(duer_inactivity_report, NULL, DUER_TIMER_PERIODIC);
|
|
duer_timer_start(s_activity_timer, INACTIVIRY_REPORT_PERIOD);
|
|
|
|
duer_directive_list res[] = {
|
|
{DCS_THROW_EXCEPTION_NAME, duer_exception_cb},
|
|
{DCS_RESET_USER_INACTIVITY_NAME, duer_inactivity_reset_cb},
|
|
{DCS_NOP_NAME, duer_nop_cb},
|
|
};
|
|
|
|
duer_add_dcs_directive_internal(res, sizeof(res) / sizeof(res[0]), SYSTEM_INTERFACE_NAMESPACE);
|
|
s_is_initialed = DUER_TRUE;
|
|
}
|
|
|
|
void duer_sys_interface_uninitialize_internal(void)
|
|
{
|
|
if (!s_is_initialed) {
|
|
return;
|
|
}
|
|
|
|
if (s_activity_timer) {
|
|
duer_timer_release(s_activity_timer);
|
|
s_activity_timer = NULL;
|
|
}
|
|
s_is_initialed = DUER_FALSE;
|
|
}
|
|
|