小度助手服务 DuerOS Service¶
小技巧
如果图片看不清楚。你可以 在图片上点击鼠标右键 –> 在新标签页中打开图片 ,然后你可以放大、缩小、移动图片。
概述¶
小度助手服务 DuerOS Service,是为 音频服务 Audio Service 的子类。
- 前者完全是按后者的框架实现的。
- 后者实现时基本上完全覆盖(或继承)前者的方法。
- 除了创建 Create 与特殊 API 要调用音频子服务的API;一般都调用音频服务的 API。
类图¶
我们用类图的形式,描述小度助手服务 DuerOS Service 的实现(实际上代码是用 C 语言实现的):
结构体
dueros_service_t,是内部私有数据。.duer_que: 与内部任务dueros_task之间通信的消息队列。.duer_state: DuerOS Service 的状态。
private method 部分,是 DuerOS Servcie 内部函数。这些函数的实现大部分都很简单:
dueros_task(): 内部任务。dueros_start(): 启动 DuerOS Service。dueros_stop(): 停止 DuerOS Service。dueros_connect(): 连接 DuerOS Service。dueros_disconnect(): 断开 DuerOS Service。dueros_destroy(): 销毁 DuerOS Service。
public method 部分,是 DuerOS Servcie 的提供的 API 函数。这些函数的实现大部分都很简单:
dueros_service_create()的实现略微复杂一点,看这里 API 。dueros_service_state_get()获得 DuerOS Service 状态。
序列图¶
对像说明:
- esp_dispatcher_dueros_app.c: 某个应用程序
- dueros_service.c: 小度助手音频子服务
- dueros_task(): 音频子服务的内部任务
- audio_service.c:音频服务
流程说明:
- 应用程序 esp_dispatcher_dueros_app.c 调用 DuerOS Service 音频子服务
dueros_service_create()。 - dueros_service.c 调用
audio_service_create(), 并会将.service_destroy,.service_start,.service_stop,.service_connect,.service_disconnect, 等回调函数作为参数的字段传入。 同时也会将自已的地址,作为.user_data参数字段传入。 因 DuerOS Service 音频子服务需要创建内部任务,也会将内部任务函数 dueros_task() 作为.task_func参数字段传入。 - audio_service.c 将上述回调函数和
.user_data保存下来。因为.task_func不为空(实际上是.task_stack > 0),故同时创建内部任务。 - dueros_task() 调用
duer_initialize()初始化 lightduer 。 - dueros_task() 注册事件回调函数
duer_set_event_callback(duer_event_hook)。 duer_init_device_info()。duer_register_device_info_ops()。- dueros_task() 设置状态为
SERVICE_STATE_IDLE。
10. esp_dispatcher_dueros_app.c 注册分发器 esp_dispather 功能
esp_dispatcher_reg_exe_func( ACTION_EXE_TYPE_DUER_CONNECT, dueros_action_connect)。 当收到 ACTION_EXE_TYPE_DUER_CONNECT 指令时,执行 dueros_action_connect() 。
11. esp_dispatcher_dueros_app.c 注册分发器 esp_dispather 功能
esp_dispatcher_reg_exe_func( ACTION_EXE_TYPE_DUER_DISCONNECT, dueros_action_disconnect)。 当收到 ACTION_EXE_TYPE_DUER_DISCONNECT 指令时,执行 dueros_action_disconnect() 。
- esp_dispatcher_dueros_app.c 调用
audio_service_set_callback()设置事件回调函数.callback_func。
- esp_dispatcher_dueros_app.c 接收到事件
wifi_service_cb(WIFI_SERV_EVENT_CONNECTED)。 - esp_dispatcher_dueros_app.c 调用执行分发器功能
esp_dispatcher_execute(ACTION_EXE_TYPE_DUER_CONNECT)。 - esp_dispatcher 发送消息
ESP_DISPCH_EVENT_TYPE_EXE给其内部任务。 - esp_dispatcher 内部任务执行动作, 实际上是调用
dueros_action_connect()。 - dueros_action 调用
audio_service_connect()。 - 因
.service_connect不为空,audio_service.c 会执行.service_connect, 实际上是执行dueros_connect()。 - dueros_server.c 发送
DUER_CMD_LOGIN消息给内部任务。 - dueros_task() 调用
duer_login()。 - dueros_task() 调用
duer_start()启动 lightduer 。 - dueros_task() 设置状态为
SERVICE_STATE_IDLE。 - dueros_task() 调用音频服务事件回调函数
audio_service_callback(SERVICE_STATE_CONNECTING)。 - audio_service.c 调用应用的事件回调函数
duer_callback()。
- audio_service.c 接收到 lightduer 的开始事件
DUER_EVENT_START。 - audio_service.c 通知内部任务已连接
DUER_CMD_CONNECTED。 - dueros_task() 设置状态为
SERVICE_STATE_CONNECTED。 - dueros_task() 调用音频服务事件回调函数
audio_service_callback(SERVICE_STATE_CONNECTED)。 - audio_service.c 调用应用的事件回调函数
duer_callback()。
- esp_dispatcher_dueros_app.c 接收到事件
rec_engine_cb (REC_EVENT_VAD_START)。 - esp_dispatcher_dueros_app.c 调用
audio_service_start()。 .service_start不为空,被执行( 实际上是执行dueros_start())。- audio_service.c 发送消息
DUER_CMD_START给内部任务。 - 内部任务 dueros_task() 调用
duer_voice_start(RECORD_SAMPLE_RATE)。 - 内部任务 dueros_task() 调用
duer_dcs_on_listen_started()。 - dueros_task() 设置状态为
SERVICE_STATE_RUNNING。 - dueros_task() 调用音频服务事件回调函数
audio_service_callback(SERVICE_STATE_CONNECTED)。 - audio_service.c 调用应用的事件回调函数
duer_callback() - dueros_task() 从 rec_engine 读数据
rec_engine_data_read()。 - dueros_task() 调用
duer_voice_send()发送语音 。
- esp_dispatcher_dueros_app.c 接收到事件
rec_engine_cb(), 接收到REC_EVENT_VAD_STOP或REC_EVENT_WAKEUP_END任一事件。 - esp_dispatcher_dueros_app.c 调用
audio_service_stop()。 .service_stop不为空,被执行( 实际上是执行dueros_stop())。- audio_service.c 发送消息
DUER_CMD_STOP给内部任务。 - 内部任务 dueros_task() 调用
duer_voice_stop()。 - dueros_task() 设置状态为
SERVICE_STATE_STOPPED。 - dueros_task() 调用音频服务事件回调函数
audio_service_callback(SERVICE_STATE_STOPPED)。 - audio_service.c 调用应用的事件回调函数
duer_callback()
esp_dispatcher_dueros_app.c 接收到事件
wifi_service_cb(WIFI_SERV_EVENT_DISCONNECTED)。esp_dispatcher_dueros_app.c 调用执行分发器功能
esp_dispatcher_execute(ACTION_EXE_TYPE_DUER_CONNECT)。esp_dispatcher 发送消息
ESP_DISPCH_EVENT_TYPE_EXE给其内部任务。esp_dispatcher 内部任务执行动作, 实际上是调用
dueros_action_disconnect()。dueros_action 调用
audio_service_disconnect()。audio_service.c 接收到 lightduer 的停止事件
DUER_EVENT_STOPPED。dueros_service.c 调用
audio_service_disconnect()。70~74 或 75~76 二者选其一。
因
.service_connect不为空,audio_service.c 会执行.service_connect, 实际上是执行dueros_connect()。dueros_server.c 发送
DUER_CMD_QUIT消息给内部任务。dueros_task() 调用
duer_stop()停止 lightduer 。dueros_task() 设置状态为
SERVICE_STATE_IDLE。dueros_task() 调用音频服务事件回调函数
audio_service_callback(SERVICE_STATE_CONNECTING)。audio_service.c 调用应用的事件回调函数
duer_callback()。
- (实际上没有代码)调用
audio_service_destroy(), 销毁 DuerOS Service音频子服务。 - 因
.service_destroy不为空, 其被 audio_service.c 调用( 实际上是执行dueros_destory())。 - dueros_server.c 发送
DUER_CMD_DESTROY消息给内部任务。 - dueros_task() 调用
duer_voice_stop()。 - dueros_task() 设置状态为
SERVICE_STATE_IDLE。 - dueros_service.c 中止内部任务 dueros_task() 。
API¶
dueros_service_create()
audio_service_create
audio_service_set_callback()
audio_service_connect()
dueros_connect()
audio_service_start()
dueros_start()
audio_service_stop()
dueros_stop()
audio_service_disconnect()
dueros_disconnect()
audio_service_destroy()
dueros_destory()