Page 1 of 1

【技术干货】自定义语音对接demo

Posted: 2023年 Apr 21日 10:24
by 0x1abin

1. 功能接入

1.1 代码导入

include/tuya_ipc_voice_demo.h
include/tuya_ipc_speaker_demo.h
include/tuya_ipc_media_wave_parse.h
include/tuya_ipc_alsa_play_demo.h
src/tuya_ipc_voice_demo.c
src/tuya_ipc_speaker_demo.c
src/tuya_ipc_media_wave_parse.c
src/tuya_ipc_alsa_play_demo.c

tuya_ipc_voice_demo.tar.bz2
(9.35 KiB) Downloaded 110 times

1.2 dp点功能

1.2.1 tuya_ipc_dp_utils.h

Code: Select all

#if defined(DEMO_IPC_VOICE_ENABLE) && (DEMO_IPC_VOICE_ENABLE == 1)
/*自定义语音dp点*/
#define TUYA_DP_VOICE_PLAY                235         /* play cmd */
#define TUYA_DP_VOICE_PLAY_CONTROL        236         /* play control cmd */
#define TUYA_DP_VOICE_PLAY_STATE          237         /* play state */
#define TUYA_DP_VOICE_PLAY_CURRENT        238         /* current playing file */
#define TUYA_DP_VOICE_PLAY_MODE           239         /* play mode */
#define TUYA_DP_VOICE_PLAY_VOLUME         240         /* play volume */
#define TUYA_DP_VOICE_UPGRADE             241         /* voice list update cmd */
#endif

1.2.2 tuya_ipc_dp_utils.c

IPC_APP_upload_all_status函数新增以下dp点的上报

Code: Select all

#ifdef TUYA_DP_VOICE_PLAY_STATE
    respone_dp_enum(TUYA_DP_VOICE_PLAY_STATE, IPC_APP_get_voice_play_state());
#endif

#ifdef TUYA_DP_VOICE_PLAY_MODE
    respone_dp_enum(TUYA_DP_VOICE_PLAY_MODE, IPC_APP_get_voice_play_mode());
#endif

#ifdef TUYA_DP_VOICE_PLAY_VOLUME
    respone_dp_value(TUYA_DP_VOICE_PLAY_VOLUME, IPC_APP_get_voice_play_volume());
#endif

s_dp_table[]变量中添加自定义语音相关的dp点处理函数入口

Code: Select all

#ifdef TUYA_DP_VOICE_PLAY
    {TUYA_DP_VOICE_PLAY,            handle_DP_VOICE_PLAY},
#endif
#ifdef TUYA_DP_VOICE_PLAY_CONTROL
    {TUYA_DP_VOICE_PLAY_CONTROL,    handle_DP_VOICE_PLAY_CONTROL},
#endif
#ifdef TUYA_DP_VOICE_PLAY_MODE
    {TUYA_DP_VOICE_PLAY_MODE,       handle_DP_VOICE_PLAY_MODE},
#endif
#ifdef TUYA_DP_VOICE_PLAY_VOLUME
    {TUYA_DP_VOICE_PLAY_VOLUME,     handle_DP_VOICE_PLAY_VOLUME},
#endif
#ifdef TUYA_DP_VOICE_UPGRADE
    {TUYA_DP_VOICE_UPGRADE,         handle_DP_VOICE_UPGRADE},
#endif

定义dp点处理函数

Code: Select all

#ifdef TUYA_DP_VOICE_PLAY
STATIC VOID handle_DP_VOICE_PLAY(IN TY_OBJ_DP_S *p_obj_dp)
{
    if ( (p_obj_dp == NULL) || (p_obj_dp->type != PROP_STR) )
    {
        PR_ERR("Error!! type invalid %d \r\n", p_obj_dp->type);
        return;
    }

    IPC_APP_set_voice_play((cJSON *)p_obj_dp->value.dp_str);
}
#endif

#ifdef TUYA_DP_VOICE_PLAY_CONTROL
STATIC VOID handle_DP_VOICE_PLAY_CONTROL(IN TY_OBJ_DP_S *p_obj_dp)
{
    if ( (p_obj_dp == NULL) || (p_obj_dp->type != PROP_ENUM) )
    {
        PR_ERR("Error!! type invalid %d \r\n", p_obj_dp->type);
        return;
    }
    
    IPC_APP_set_voice_play_control(p_obj_dp->value.dp_enum);
}
#endif

#ifdef TUYA_DP_VOICE_PLAY_MODE
STATIC VOID handle_DP_VOICE_PLAY_MODE(IN TY_OBJ_DP_S *p_obj_dp)
{
    if ( (p_obj_dp == NULL) || (p_obj_dp->type != PROP_ENUM) )
    {
        PR_ERR("Error!! type invalid %d \r\n", p_obj_dp->type);
        return;
    }

    CHAR_T tmp_str[4] = {0};
    snprintf(tmp_str, 4, "%d", p_obj_dp->value.dp_enum);
    
    IPC_APP_set_voice_play_mode(tmp_str);

    respone_dp_enum(TUYA_DP_VOICE_PLAY_MODE, IPC_APP_get_voice_play_mode());
}
#endif

#ifdef TUYA_DP_VOICE_PLAY_VOLUME
STATIC VOID handle_DP_VOICE_PLAY_VOLUME(IN TY_OBJ_DP_S *p_obj_dp)
{
    if ( (p_obj_dp == NULL) || (p_obj_dp->type != PROP_VALUE) )
    {
        PR_ERR("Error!! type invalid %d \r\n", p_obj_dp->type);
        return;
    }

    IPC_APP_set_voice_play_volume(p_obj_dp->value.dp_value);

    respone_dp_value(TUYA_DP_VOICE_PLAY_VOLUME, IPC_APP_get_voice_play_volume());
}
#endif

#ifdef TUYA_DP_VOICE_UPGRADE
STATIC VOID handle_DP_VOICE_UPGRADE(IN TY_OBJ_DP_S *p_obj_dp)
{
    IPC_APP_set_voice_upgrade();
}
#endif

1.2.2 tuya_ipc_dp_handler.h

Code: Select all

#ifdef TUYA_DP_VOICE_PLAY
VOID IPC_APP_set_voice_play(IN cJSON *p_play_info);
#endif

#ifdef TUYA_DP_VOICE_PLAY_CONTROL
VOID IPC_APP_set_voice_play_control(INT_T play_control);
#endif

#ifdef TUYA_DP_VOICE_PLAY_STATE
CHAR_T *IPC_APP_get_voice_play_state(VOID);
#endif

#ifdef TUYA_DP_VOICE_PLAY_MODE
VOID IPC_APP_set_voice_play_mode(CHAR_T *p_play_mode);
CHAR_T *IPC_APP_get_voice_play_mode(VOID);
#endif

#ifdef TUYA_DP_VOICE_PLAY_VOLUME
VOID IPC_APP_set_voice_play_volume(INT_T play_volume);
INT_T IPC_APP_get_voice_play_volume(VOID);
#endif

#ifdef TUYA_DP_VOICE_UPGRADE
VOID IPC_APP_set_voice_upgrade(VOID);
#endif

1.2.3 tuya_ipc_dp_handler.c

Code: Select all

#ifdef TUYA_DP_VOICE_PLAY
VOID IPC_APP_set_voice_play(IN cJSON *p_play_info)
{
    if (NULL == p_play_info)
    {
        return;
    }

    PR_INFO("%s %d handle_DP_VOICE_PLAY:%s \r\n", __FUNCTION__, __LINE__, (char *)p_play_info);

    cJSON *pJson = cJSON_Parse((CHAR_T *)p_play_info);

    if (NULL == pJson)
    {
        PR_ERR("%s %d step error\n", __FUNCTION__, __LINE__);
        return;
    }

    cJSON *pCode = cJSON_GetObjectItem(pJson, "bizcode");
    if (NULL == pCode)
    {
        PR_ERR("%s %d step error\n", __FUNCTION__, __LINE__);
        cJSON_Delete(pJson);
        return;
    }

    cJSON *pId = cJSON_GetObjectItem(pJson, "id");
    if (NULL == pId)
    {
        PR_ERR("%s %d step error\n", __FUNCTION__, __LINE__);
        cJSON_Delete(pId);
        return;
    }

    if (OPRT_OK == ty_voice_set_play(pCode->valuestring, pId->valueint))
    {
        __tuya_app_write_STR("tuya_play_code", pCode->valuestring);
        __tuya_app_write_INT("tuya_play_id", pId->valueint);
    }

    cJSON_Delete(pJson);
}
#endif

#ifdef TUYA_DP_VOICE_PLAY_CONTROL
VOID IPC_APP_set_voice_play_control(INT_T play_control)
{
    PR_INFO("set voice play control:%d \r\n", play_control);

    ty_voice_set_play_control(play_control);
}
#endif

#ifdef TUYA_DP_VOICE_PLAY_STATE
STATIC CHAR_T s_play_state[2] = {0};//for demo
CHAR_T *IPC_APP_get_voice_play_state(VOID)
{
    INT_T play_state = ty_voice_get_play_state();
    PR_INFO("get voice play state:%d \r\n", play_state);
    snprintf(s_play_state, 2, "%d", play_state);
    return s_play_state;
}
#endif

#ifdef TUYA_DP_VOICE_PLAY_MODE
STATIC CHAR_T s_play_mode[4] = {0};//for demo
VOID IPC_APP_set_voice_play_mode(CHAR_T *p_play_mode)
{
    PR_INFO("set voice play mode:%s \r\n", p_play_mode);

    ty_voice_set_play_mode(atoi(p_play_mode));
}

CHAR_T *IPC_APP_get_voice_play_mode(VOID)
{
    INT_T play_mode = ty_voice_get_play_mode();
    PR_INFO("get voice play mode:%d \r\n", play_mode);
    snprintf(s_play_mode, 4, "%d", play_mode);
    return s_play_mode;
}
#endif

#ifdef TUYA_DP_VOICE_PLAY_VOLUME
VOID IPC_APP_set_voice_play_volume(INT_T play_volume)
{
    PR_INFO("set voice play volume:%d \r\n", play_volume);

    ty_voice_set_play_volume(play_volume);
}

INT_T IPC_APP_get_voice_play_volume(VOID)
{
    INT_T play_volume = ty_voice_get_play_volume();
    PR_INFO("get voice play volume:%d \r\n", play_volume);
    return play_volume;
}
#endif

#ifdef TUYA_DP_VOICE_UPGRADE
VOID IPC_APP_set_voice_upgrade(VOID)
{
    ty_voice_set_update_voice_list();
}
#endif

1.3 初始化

user_main.c中添加头文件包含

Code: Select all

#if defined(DEMO_IPC_VOICE_ENABLE) && (DEMO_IPC_VOICE_ENABLE == 1)
#include "tuya_ipc_voice_demo.h"
#endif

在tuya_ipc_sdk_mqtt_online_proc中添加自定义语音初始化

Code: Select all

#if defined(DEMO_IPC_VOICE_ENABLE) && (DEMO_IPC_VOICE_ENABLE == 1)
    TUYA_APP_Enable_Voice();
#endif

1.4 编译宏

在tuya_ipc_demo_default_cfg.h头文件中添加编译宏定义DEMO_IPC_VOICE_ENABLE

Code: Select all

#define DEMO_IPC_VOICE_ENABLE 1

2. 环境搭建

2.1 工具安装

为了能够在Ubuntu系统中演示自定义语音的播放功能,需要安装alsa-lib库,安装命令:

Code: Select all

sudo apt-get install libasound2-dev

2.2 创建音频缓存文件夹

为了能够缓存下载的音频文件,demo中将下载完的音频文件默认缓存在/tmp/voice文件夹下,用户需手动创建/tmp/voice文件夹。

用户如需更改缓存文件夹,可自行更改tuya_ipc_voice_demo.c中的VOICE_FILE_PATH宏定义。