机器人超脑平台
平台简介
成为超脑平台用户
讯飞超脑板
产品规格
开发指南
标准协议
使用手册
环境准备
数据采集
应用算法
应用实例
镜像导出
镜像烧录
错误码
算法配置表
机器人多模态交互开发套件
多模态交互套件产品白皮书
多模态交互套件快速体验
多模态套件平台功能使用手册
多模态交互套件开发手册
常见问题与解答
智能语音背包
智能语音背包产品白皮书
智能语音背包产品规格书
智能语音背包产品快速体验
智能语音背包产品开发手册
联系方式
服务条款
超脑平台服务协议
超脑平台隐私政策
本文档使用 MrDoc 发布
-
+
首页
多模态交互套件开发手册
# 一、软件包说明 ### 1.1安装套件包 首先解压缩安装套件包。 解压缩后文件夹包含体验评估板语音交互能力所需的app以及更新app的批处理脚本。 | 应用名称 | 安装载体 | 功能 | | --- | --- | --- | | AIUILauncher | 评估板/核心板 | 系统级应用,安装时应push到/system/app/目录下,其主要功能是发送开机广播(开发者应用可监听此广播实现开机启动)、开机后拉起UARTService、ControlService、SmartConfigService服务。 | | AIUIProductDemo | 评估板/核心板 | AIUI默认播报程序,包含完整的交互处理逻辑。 | | AIUIService | 评估板/核心板 | AIUI核心服务,包含语音唤醒、端点检测、离线命令词识别以及跟AIUI服务端通信等功能。 | | ControlService | 评估板/核心板 | 评估板中给ControlClient提供服务的应用程序。 | | UARTService | 评估板/核心板 | 负责串口通信的服务,作为上位机与评估板之间的通信入口。 | 批处理安装脚本:scripts/ install\_all.bat 批处理卸载脚本:scripts/ uninstall\_all.bat ### 1.2串口DEMO 开发包中提供了windows、Android、Linux平台的demo。 Android:Android\_UART Windows:QT\_UART\_DEMO、Windows\_C\#\_SerialDemo 其他平台也可以参考Linux C:串口历险记(含Simple代码) ### 1.3视频预览DEMO 开发包中提供了Android平台的视频接收端demo。 多模态AndroidSocketVideoDemo。 # 二、程序功能模块 上位机和AIUI模块通过串口通信,适用于有屏幕需求或硬件扩展需求(如机器人,智能家居等)。  如上图所示,为上位机模式的开发结构图,UARTService充当AIUIService和上位机之间的中介,一面负责将AIUI的结果通过串口发送给上位机,一面将上位机通过串口发送的指令发送到AIUI。 AIUIProductDemo是个可选的选项,因为如果在上位机上对结果进行解析播放,那么AIUI模块上的AIUIProductDemo的播报就不必要了。 # 三、串口数据解析 ### 3.1概述 上位机可以通过串口/socket向AIUI语音模块发送握手消息同步状态,例如发送WIFI配置信息。 ### 3.2通信接口及参数 1. **串口方式** - 波特率:115200 - 数据位:8 - 停止位:1 - 奇偶校验:无 - 流控:无 AIUI使用模块上的串口UART1 2. **socket方式** 指定端口:19199 ### 3.3消息格式 <table border="1" class="docutils"> <colgroup> <col width="10%" /> <col width="10%" /> <col width="50%" /> </colgroup> <tbody valign="top"> <tr class="row-odd"><td>字节</td> <td>值</td> <td>含义说明</td> </tr> <tr class="row-even"><td>0</td> <td>0xA5</td> <td>同步头</td> </tr> <tr class="row-odd"><td>1</td> <td>0x01</td> <td>用户ID</td> </tr> <tr class="row-even"><td>2</td> <td>0xXX</td> <td>消息类型</td> </tr> <tr class="row-odd"><td>3~4</td> <td>0xXXXX</td> <td>消息数据长度</td> </tr> <tr class="row-even"><td>5~6</td> <td>0xXXXX</td> <td>消息ID</td> </tr> <tr class="row-odd"><td>7~n</td> <td>消息数据</td> <td>消息数据</td> </tr> <tr class="row-even"><td>n+1</td> <td>0xXX</td> <td>内部校验码</td> </tr> </tbody> </table> ### 3.4通信规则 * 双向通信,进行一问一答式通信; * 不分主从机,双方都可向对方发送请求信息; * 双方发送握手信号,确定与对方串口通信是否正常;在未接收到响应时,可以每隔100ms发送一次握手请求信号; * 接收方接到请求后需在50ms内发送响应; * 除确认消息外发送方发送完成后若超过300ms未得到响应则判定为超时进行重发,重发次数为3次。 ### 3.5通信格式 通信格式定义了握手消息,AIUI配置消息,WIFI配置消息,AIUI消息,主控消息,确认消息。下面将分类详述: <table border="1" class="docutils"> <colgroup> <col width="13%" /> <col width="9%" /> <col width="6%" /> <col width="8%" /> <col width="8%" /> <col width="8%" /> <col width="6%" /> <col width="0%" /> <col width="5%" /> <col width="1%" /> <col width="3%" /> <col width="3%" /> <col width="9%" /> <col width="6%" /> <col width="8%" /> <col width="6%" /> </colgroup> <tbody valign="top"> <tr class="row-odd"><td>分类</td> <td>同步头</td> <td>用户ID</td> <td>消息类型</td> <td>消息长度</td> <td>消息ID</td> <td colspan="9">消息数据</td> <td>校检码</td> </tr> <tr class="row-even"><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~4</td> <td>5~6</td> <td>7</td> <td colspan="3">8</td> <td colspan="2">9</td> <td colspan="3">10</td> <td>11</td> </tr> <tr class="row-odd"><td><strong>握手请求</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x01</td> <td>见下文解释</td> <td>见下文解释</td> <td>0xA5</td> <td colspan="3">0x00</td> <td colspan="2">0x00</td> <td colspan="3">0x00</td> <td>见下文解释</td> </tr> <tr class="row-even"><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~4</td> <td>5~6</td> <td>7</td> <td colspan="3">8</td> <td colspan="2">9</td> <td>10</td> <td>11~m</td> <td>m+1~n</td> <td>n+1</td> </tr> <tr class="row-odd"><td><strong>WIFI配置</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x02</td> <td>同上</td> <td>同上</td> <td>状态</td> <td colspan="3">加密方式</td> <td colspan="2">SSID长度</td> <td>passwd长度</td> <td>SSID</td> <td>passwd</td> <td>同上</td> </tr> <tr class="row-even"><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~4</td> <td>5~6</td> <td colspan="9">7~m</td> <td>m+1</td> </tr> <tr class="row-odd"><td><strong>AIUI配置</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x03</td> <td>同上</td> <td>同上</td> <td colspan="9">AIUI配置</td> <td>同上</td> </tr> <tr class="row-even"><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~4</td> <td>5~6</td> <td colspan="9">7~m</td> <td>m+1</td> </tr> <tr class="row-odd"><td><strong>AIUI消息</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x04</td> <td>同上</td> <td>同上</td> <td colspan="9">AIUI消息(gzip压缩)</td> <td>同上</td> </tr> <tr class="row-even"><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~4</td> <td>5~6</td> <td colspan="9">7~m</td> <td>m+1</td> </tr> <tr class="row-odd"><td><strong>主控消息</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x05</td> <td>同上</td> <td>同上</td> <td colspan="9">主控消息</td> <td>同上</td> </tr> <tr class="row-even"><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~4</td> <td>5~6</td> <td colspan="9">7~m</td> <td>m+1</td> </tr> <tr class="row-odd"><td><strong>设置静态IP</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x06</td> <td>同上</td> <td>同上</td> <td colspan="9">静态IP配置</td> <td>同上</td> </tr> <tr class="row-even"><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~4</td> <td>5~6</td> <td colspan="9">7~m</td> <td>m+1</td> </tr> <tr class="row-odd"><td><strong>自定义消息</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x2A</td> <td>同上</td> <td>同上</td> <td colspan="9">自定义数据</td> <td>同上</td> </tr> <tr class="row-even"><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~4</td> <td>5~6</td> <td colspan="2">7</td> <td colspan="1">8</td> <td colspan="3">9</td> <td colspan="3">10</td> <td>11</td> </tr> <tr class="row-odd"><td><strong>确认消息</strong></td> <td>0xA5</td> <td>0x01</td> <td>0xff</td> <td>同上</td> <td>同上</td> <td colspan="2">0xA5</td> <td colspan="1">0x00</td> <td colspan="3">0x00</td> <td colspan="3">0x00</td> <td>同上</td> </tr> </tbody> </table> **消息长度:** 数据格式中3\~4字节为消息数据长度,消息长度编码为小端模式,即第3字节存储低字节,第4字节存储高字节。如握手请求消息中消息数据有4字节,则消息长度为4,编码到3\~4字节就是0x04 0x00 **消息ID:** 数据格式中5\~6字节为消息ID,与消息长度类似,也是小端模式编码。可以使用消息ID过滤因超时重发导致的重复消息。两字节长度的消息ID取值0-65535,所以在实际使用中需要循环使用,具体实现可以参考Android平台上的源码实现。 **校检码:** 数据格式中每种数据类型的最后一个字节都是校检码,用于检验串口传输的正确性。其计算方式为除校检码字节外所有字节求和取反并加1。公式如下: ~~~ checkcode = ~sum(字节0+字节2+...+字节n) + 1 ~~~ **编码格式:** 消息中字符串类型的数据编码格式为UTF-8。 AIUI消息格式中的数据采用GZIP压缩格式,压缩前的编码格式也是UTF-8格式。 # 四、串口发送控制信息 ### 4.1 确认消息 确认消息是一个特殊的消息类型,它是对其他类型消息的确认,它的消息ID与其要确认的消息的ID相同。 如一个AIUI消息的消息ID为0x9527,那对应的确认消息的消息ID也应该是0x9527。 ### 4.2 WIFI配置 WIFI配置结果中,状态取值: - 0:从机当前与路由连接 加密方式分为三类: - 0:OPEN - 1:WEP - 2:WPA ### 4.3 AIUI配置 AIUI配置的格式为JSON,content中包含配置文件内容,可配置字段参考[AIUI配置文件](https://aiui-doc.xf-yun.com/project-1/doc-13/#配置文件)内容,除AIUI配置文件中的内容外还可以通过launch\_demo配置是否启动AIUIProductDemo。 配置appid,key,场景等示例如下: ~~~ json { "type": "aiui_cfg", "content": { "login":{ "appid":"xxxxxxxx", "key":"xxxxxxxx" }, "launch_demo": false } } ~~~ **注意:AIUI只需配置一次,后面即使重启也会继续生效,AIUI配置生效需要重启服务,所以AIUI配置应尽可能只在首次启动无配置或配置修改的情况下使用。** 注:配置项字段取值参见中[AIUI配置文件](https://aiui-doc.xf-yun.com/project-1/doc-13/#配置文件)部分说明 ### 4.4 主控消息 主控消息是上位机发送给AIUI模块的消息,格式为JSON。 主控消息根据内部字段type的不同,控制AIUI的不同功能。 #### AIUI控制 type为aiui\_msg,发送AIUI控制消息: ~~~ json { "type": "aiui_msg", "content": { "msg_type": 8, //CMD_RESET_WAKEUP 重置AIUI唤醒状态 "arg1": 0, "arg2": 0, "params": "", "data": "" //非必须,值为原数据的base64编码 } } ~~~ 注:各个字段取值具体说明参见[AIUIMessage类型](https://aiui-doc.xf-yun.com/project-1/doc-14/#aiuimessage)说明部分 #### 控制AIUI播放 type为voice,控制AIUI声音播放: ~~~ json { "type": "voice", "content": { "enable_voice":true/false // 是否禁止AIUI声音播放 } } ~~~ #### 设置AIUI音量 type为voice,控制AIUI声音播放: ~~~ json { "type": "voice", "content": { "vol_value": 15 // 设置音量,范围7~15 } } ~~~ #### WIFI状态查询 type为status,通过query字段查询不同状态: ~~~ json { "type": "status", "content": { "query": "wifi" // 查询AIUI WIFI状态信息 } } ~~~ #### 多模态麦克风和摄像头状态查询 type为status,通过query字段查询不同状态: ~~~ json { "type": "status", "content": { "query": "speech_device" // 查询多模态设备状态信息 } } ~~~ #### 音量查询 type为status,通过query字段查询不同状态: ~~~ json { "type": "status", "content": { "query": "volume" // 查询AIUI音量大小 } } ~~~ #### 音频保存 type为save\_audio,控制AIUI保存原始音频,通过save\_len指定保存音频时长,单位为秒: ~~~ json { "type": "save_audio", "content": { "save_len": 10 } } ~~~ #### 文本合成 type为tts,发送文本让AIUI开始合成播放或者停止合成播放: - 开始合成命令(parameters为可选参数): ~~~ json { "type": "tts", "content": { "action": "start", //开始合成 "text": "xxx", //需要合成播放的文本(注意文本的编码格式要为utf-8) "parameters" : { "emot" : "xxx", //emot值为neutral,happy,sorrow中一个 "xxx" : "xxx" // TTS支持设置的其他参数 } } } ~~~ - 暂停合成命令: ~~~ json { "type": "tts", "content": { "action": "pause" //暂停合成 } } ~~~ - 恢复合成命令: ~~~ json { "type": "tts", "content": { "action": "resume" //恢复合成 } } ~~~ - 停止合成命令: ~~~ json { "type": "tts", "content": { "action": "stop" //停止合成 } } ~~~ #### SmartConfig type为smartcfg,控制AIUI模块smartconfig功能开关: - 开始命令: ~~~ json { "type": "smartcfg", "content": { "cmd": "start", "timeout": 60 //接收smartconfig配置的超时时间 } } ~~~ - 停止命令: ~~~ json { "type": "smartcfg", "content": { "cmd": "stop" } } ~~~ #### AIUI结果过滤命令 默认情况下,AIUI会将用户在云端配置的所有语义场景类型的结果都通过串口发送给上位机。 但是可能在某些情况下,比如上位机是单片机,仅仅需要接收操控类的指令,对天气,音乐,故事类的结果仅希望在AIUI模块上播出,而不需要发送到上位机。 在这种情况下,开发者可以通过命令控制过滤选择发送到上位机的AIUI结果的场景类型: ~~~ json { "type": "event_filter", "content": { "type_filter" : { "select" : [], "unselect": [] }, "sub_filter": { "select" : [], "unselect": [] }, "service_filter": { "select" : [], "unselect": [] } } } ~~~ 其中type_filter根据AIUIEvent的eventType来过滤,具体取值请参考[AIUIEvent](https://aiui-doc.xf-yun.com/project-1/doc-14/#aiuievent)小节。select字段为允许发送的类型,unselect字段为不允许发送的类型。注意:取值类型为字符串类型,而不是int类型。如下为过滤唤醒事件示例: ~~~ json { "type": "event_filter", "content": { "type_filter" : { "select" : ["4"] //结果事件对应取值为4 } } } ~~~ sub_filter根据结果事件中的sub字段来过滤,具体取值:iat、nlp、asr、tpp。如下为过滤后处理结果示例: ~~~ json { "type": "event_filter", "content": { "sub_filter" : { "select" : ["tpp"] } } } ~~~ service_filter根据结果事件中的service字段来过滤,如下为过滤天气结果示例: ~~~ json { "type": "event_filter", "content": { "service_filter" : { "select" : ["weather"] } } } ~~~ ### 4.5 设置以太网静态IP 设备默认使用DHCP获取设备IP,切换为静态IP可发送以下消息内容: ~~~ json { "staticIp": true, //设置为静态IP "address": "192.168.1.123", //ip配置 "mask": "255.255.255.0", //子网掩码配置 "gateway": "192.168.1.1", //网关配置 "dns": "192.168.1.1" //DNS配置 } ~~~ #### 合成 type为tts\_event,表示合成事件: - 合成开始事件: ~~~ json { "type": "tts_event", "content": { "eventType": 0 // 合成开始事件 } } ~~~ - 合成结束事件: ~~~ json { "type": "tts_event", "content": { "eventType": 1, //合成结束事件 "error": ttsErrorCode //0表示成功;发生错误时代表合成错误码 } } ~~~ # 五、串口接收AIUI消息 AIUI消息是AIUI模块传递给上位机的消息,表示听写语义数据返回或者主控消息操作的结果。 原始内容格式为JSON,**但是为了传输的效率,实际消息内容采用了GZIP压缩格式**。 AIUI消息根据type字段的不同值解析数据。 ### 5.1 AIUI结果事件 type为aiui\_event,代表AIUI结果返回,总体结构示例: ~~~ json { "type": "aiui_event", "content": { "eventType":1, //事件类型 "arg1":0, //参数1 "arg2":0, //参数2 "info":{}, //描述信息 "result":{} //结果 } } ~~~ 注:具体字段参考[AIUIEvent类型](https://aiui-doc.xf-yun.com/project-1/doc-14/#aiuievent)说明部分。 ### 5.2 WIFI状态 type为wifi\_status,代表WIFI状态查询返回或者当AIUI网络状态变化时主动通知,示例如下: ~~~ json { "type": "wifi_status", "content": { "connected": true/false, //AIUI WIFI查询状态信息 "ssid": "connected_ssid" //当connected为true时,此字段表示当前连接的wifi名称 } } ~~~ ### 5.3 多模态麦克风和摄像头状态 type为speech_device_status,代表当主动查询或者轮训每分钟通知一次多模态硬件状态,示例如下: ~~~ json { "type": "speech_device_status", "content": { "local_ip": "192.168.100.18", //设备当前IP "audio_state": 0, //麦克风硬件状态 "video_state": 0, //摄像头状态 "engine_state": 0, //多模态引擎初始化状态 "mic_test": 0 //运行时mic检测状态 } } ~~~ # 六、多模态交互套件串口通信协议实现参考 ### 6.1 Android实现 根据[通信协议和通信格式](https://aiui-doc.xf-yun.com/project-1/doc-35/#aiui串口协议) ,在Android平台进行了实现以供开发参考。如果上位机平台是Android平台,可以直接集成使用。 开发包中包含串口开发包下的UARTKit是AIUI串口协议实现的Library工程,UARTKitCtrDemo是运行在Android上位机上依赖UARTKit的Application工程,用于UARTKit接口使用的示例,AIUI中串口收发也是使用的UARTKit Library。 Android串口SDK架起了上位机与AIUIService交互的桥梁,通过收发AIUI消息,获取AIUI结果和控制AIUI的运行。 #### 权限 **串口通信需要应用有读写对应串口设备的权限(即对/dev/下的串口设备文件有rw权限)。** #### 调用流程 调用主要接口类是UARTAgent。 在程序首次初始化的地方调用静态方法createAgent创建UARTAgent实例,传入EventListener参数用于接收串口事件,后面调用创建的UARTAgent实例的sendMessage方法发送串口消息,在程序结束前调用UARTAgent实例的destroy方法释放资源。 #### 接口说明 **UARTAgent** 包含如下接口: ~~~ java //创建UARTAgent UARTAgent createAgent(String device, int speed, EventListener listener) //发送串口消息 boolean sendMessage(MsgPacket reqPacket) //销毁串口,释放资源 void destroy() ~~~ **EventListener** 创建UARTAgent传入的listener,用于监听串口的状态和数据回调,定义如下: ~~~ java interface EventListener { void onEvent(UARTEvent event); } ~~~ **UARTEvent** UARTEvent即为串口事件,定义如下: ~~~ java class UARTEvent { int eventType; //串口事件类型 Object data; //串口事件数据 } ~~~ **MsgPacket** MsgPacket是构造发送给AIUI的消息的类型,可以通过PacketBuilder提供的静态工具方法很方便的构造: - 构造AIUI配置请求数据包 ` MsgPacket.obtainAIUIConfPacket(String appid, String key, String sence, boolean launchDemo)` - 构造获取WIFI状态请求数据包 ` MsgPacket.obtainWIFIStatusReqPacket()` - 构造AIUI控制请求数据包 `MsgPacket obtainAIUICtrPacket(int msgType, int arg1, int arg2, String params)` 更多消息类型的构造可以参考源码自行实现。 #### 代码示例 下面代码示例了上位机集成使用的通用流程(更全面的代码参考开发包下的UARTKitCtrDemo): ~~~ java mAgent = UARTAgent.createAgent("/dev/ttyS2", 115200, new EventListener() { @Override public void onEvent(UARTEvent event) { switch (event.eventType) { case UARTConstant.EVENT_INIT_SUCCESS: //处理初始化成功事件 Log.d(TAG, "Init UART Success"); break; case UARTConstant.EVENT_INIT_FAILED: //处理初始化失败事件 Log.d(TAG, "Init UART Failed"); break; case UARTConstant.EVENT_MSG: //消息回调事件 MsgPacket recvPacket = (MsgPacket) event.data; processPacket(recvPacket); break; case UARTConstant.EVENT_SEND_FAILED: //消息发送失败事件 MsgPacket sendPacket = (MsgPacket) event.data; mAgent.sendMessage(sendPacket); break; default: break; } } }); //消息处理 private void processPacket(MsgPacket packet) { switch (packet.getMsgType()) { case MsgPacket.AIUI_PACKET_TYPE: Log.d(TAG, "recv aiui result" + new String(((AIUIPacket) packet).content)); break; default: break; } } //发送AIUI配置信息 mAgent.sendMessage(PacketBuilder.obtainAIUIConfPacket("appid", "key", "scene", false)); ~~~ ### 6.2 其他平台实现 Android平台上位机只需集成开发包中串口SDK UARTKit即可便捷地进行开发。若上位机是其他平台,可以先通过[AIUI串口历险记](http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=17728)熟悉AIUI串口协议的一些具体内容,再参考[串口Android SDK的示例](https://aiui-doc.xf-yun.com/project-1/doc-35/#串口协议实现参考)熟悉处理流程。在Windows上也有分享的AIUI串口工具,参见[AIUI串口调试助手](http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=26336)。 ### 6.3 自定义消息 串口通信格式中定义了网络,配置,控制,接收几类消息,这些消息大部分格式是json文本,接收的AIUI消息的格式还是gzip压缩,对于性能较弱的机器(如单片机)来说,这些消息解析较慢。所以在串口通信格式中加入自定义数据类型,以扩展现有串口的适用性。 ### 格式定义 ### <table border="1" class="docutils"> <colgroup> <col width="11%" /> <col width="9%" /> <col width="9%" /> <col width="11%" /> <col width="11%" /> <col width="9%" /> <col width="27%" /> <col width="14%" /> </colgroup> <tbody valign="top"> <tr class="row-odd"><td>分类</td> <td>同步头</td> <td>用户ID</td> <td>消息类型</td> <td>消息长度</td> <td>消息ID</td> <td>消息数据</td> <td>校检码</td> </tr> <tr class="row-even"><td rowspan="2">自定义消息</td> <td rowspan="2">0xA5</td> <td rowspan="2">0x01</td> <td rowspan="2">0x2A</td> <td rowspan="2">见下文解释</td> <td rowspan="2">见下文解释</td> <td rowspan="2">自定义消息数据</td> <td rowspan="2">见下文解释</td> </tr> <tr class="row-odd"></tr> </tbody> </table> ### 基本流程 ### 自定义数据的基本工作流程: ① AIUI模块上开发者的Android应用发送含数据的特定广播,AIUI会把数据通过串口发送给上位机。 ② 上位机也可以发送自定义数据给AIUI模块,AIUI模块上的开发者应用接收后进行处理即可。 对应上述流程,分别对应如下广播: ① `com.iflytek.aiui.devboard.action.SEND_CUSTOM_DATA` ② `com.iflytek.aiui.devboard.action.RECEIVE_CUSTOM_DATA` 流程示意如下:  ### 代码示例 ### 下列代码演示功能:在AIUI模块中接收上位机发送的自定义消息后自动回复给上位机一串数据为`{1, 1, 2, 3, 5, 8}`的自定义消息。 AIUI模块中开发者应用负责接收自定义消息的Receiver: ~~~ java class CustomDataReceiver extends BroadcastReceiver{ private static final String ACTION_SEND_CUSTOM_DATA = "com.iflytek.aiui.devboard.action.SEND_CUSTOM_DATA"; private static final String CUSTOM_DATA_KEY = "custom_data"; @Override public void onReceive(Context context, Intent intent) { byte[] customData = intent.getByteArrayExtra(CUSTOM_DATA_KEY); Log.d("CustomDataReceiver", "recv custom data " + Arrays.toString(customData)); Intent respAck = new Intent(ACTION_SEND_CUSTOM_DATA); respAck.putExtra(CUSTOM_DATA_KEY, new byte[]{1, 1, 2, 3, 5, 8}); context.sendBroadcast(respAck); } } ~~~ 在manifest中注册如下 ~~~ xml <receiver android:name="com.example.uartcustomdata.CustomDataReceiver"> <intent-filter> <action android:name="com.iflytek.aiui.devboard.action.RECEIVE_CUSTOM_DATA"/> </intent-filter> </receiver> ~~~ # 七、多模态设备视频传输协议 上位机可通过socket与盒子建立视频传输通道,可参照开发包中的Android示例代码实现摄像头视频预览。 ### 7.1 概述 上位机可以通过socket连接盒子来获取到实时图像帧数据,以及人脸检测结果信息。 设备IP:如果盒子为动态ip,可通过[发送串口](#_多模态麦克风和摄像头状态查询)指令来获取ip。 指定端口:9090 ### 7.2 消息格式 消息格式与串口协议类似,唯一不同点为消息数据长度位从2个字节扩充到4个字节。 | 字节 | 值 | 含义说明 | | --- | --- | --- | | 0 | 0xA5 | 同步头 | | 1 | 0x01 | 用户ID | | 2 | 0xXX | 消息类型 | | 3\~6 | 0xXXXXXXXX | 消息数据长度 | | 7\~8 | 0xXXXX | 消息ID | | 9\~n | 消息数据 | 消息数据 | | n\+1 | 0xXX | 内部校验码 | ### 7.3 通信规则 * 半双工通信,进行一问一答式通信; * 语音模组主要负责下发消息,上位机主要负责接收消息及回复确认消息; * 建立socket连接之后,盒子会首先下发图像帧格式消息,上位机获取到图像格式方可进行图像绘制; * 若语音模组未收到上位机的确认消息,会在超时500ms之后再发送最新的图像数据,无重发规则; ### 7.4 通信格式 通信格式定义了图像格式消息、人脸检测消息、图像帧消息、确认消息。下面将分类详述: <table border="1"> <colgroup> <col width="13%" /> <col width="9%" /> <col width="6%" /> <col width="8%" /> <col width="8%" /> <col width="8%" /> <col width="6%" /> <col width="0%" /> <col width="5%" /> <col width="1%" /> <col width="3%" /> <col width="3%" /> <col width="9%" /> <col width="6%" /> <col width="8%" /> <col width="6%" /> </colgroup> <tbody valign="top"> <tr><td>分类</td> <td>同步头</td> <td>用户ID</td> <td>消息类型</td> <td>消息长度</td> <td>消息ID</td> <td colspan="9">消息数据</td> <td>校检码</td> </tr> <tr><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~6</td> <td>7~8</td> <td colspan="9">9~n</td> <td>n+1</td> </tr> <tr><td><strong>图像格式</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x07</td> <td>见下文解释</td> <td>见下文解释</td> <td colspan="9">图像格式json</td> <td>0x00</td> </tr> <tr><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~6</td> <td>7~8</td> <td colspan="9">9~n</td> <td>n+1</td> </tr> <tr><td><strong>图像帧数据</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x08</td> <td>见下文解释</td> <td>见下文解释</td> <td colspan="9">图像二进制</td> <td>0x00</td> </tr> <tr><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~6</td> <td>7~8</td> <td colspan="9">9~n</td> <td>n+1</td> </tr> <tr><td><strong>单人版本人脸检测信息</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x09</td> <td>见下文解释</td> <td>见下文解释</td> <td colspan="9">人脸信息json</td> <td>0x00</td> </tr> <tr><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~6</td> <td>7~8</td> <td colspan="2">9</td> <td colspan="1">10</td> <td colspan="3">11</td> <td colspan="3">12</td> <td>13</td> </tr> <tr><td><strong>多人版本人脸检测信息</strong></td> <td>0xA5</td> <td>0x01</td> <td>0x0b</td> <td>见下文解释</td> <td>见下文解释</td> <td colspan="9">人脸信息json</td> <td>0x00</td> </tr> <tr><td>字节</td> <td>0</td> <td>1</td> <td>2</td> <td>3~6</td> <td>7~8</td> <td colspan="2">9</td> <td colspan="1">10</td> <td colspan="3">11</td> <td colspan="3">12</td> <td>13</td> </tr> <tr><td><strong>确认消息</strong></td> <td>0xA5</td> <td>0x01</td> <td>0xff</td> <td>同上</td> <td>同上</td> <td colspan="2">0xA5</td> <td colspan="1">0x00</td> <td colspan="3">0x00</td> <td colspan="3">0x00</td> <td>0x00</td> </tr> </tbody> </table> #### 消息长度: 数据格式中3-6字节为消息数据长度,消息长度编码为小端模式,即第3字节存储低字节,第6字节存储高字节。如确认消息中消息数据有4字节,则消息长度为4,编码到3-6字节就是0x04 0x00 0x00 0x00 #### 消息ID: 数据格式中7-8字节为消息ID,与消息长度类似,也是小端模式编码。可以使用消息ID过滤因超时重发导致的重复消息。两字节长度的消息ID取值0-65535,所以在实际使用中需要循环使用,具体实现可以参考Android平台上的源码实现。 #### 校检码: 数据格式中每种数据类型的最后一个字节都是校检码,由于图像帧数据较大,校验位固定为0x00 #### 编码格式: 消息中字符串类型的数据编码格式为UTF-8。 图像帧数据为bgr格式的二进制数据 #### 确认消息 确认消息是一个特殊的消息类型,它是对其他类型消息的确认,它的消息ID与其要确认的消息的ID相同。 如一个图像帧消息的消息ID为0x9527,那对应的确认消息的消息ID也应该是0x9527。 ### 7.5 图像格式消息 图像格式的数据为json字符串,包含图像的宽、高、格式信息。 { "format":0, // 0:bgr 1:jpeg "width":500, "height":500 } 注意:图像格式仅在建立socket连接时下发一次 ### 7.6 图像二进制消息 根据图像格式消息获取图像对应的解析格式,默认格式为`JPEG`压缩格式 #### JPEG格式 JPEG格式为有损压缩格式,上位机需对图像进行JPEG解压缩,获取原始位图后再进行屏幕渲染。 #### bgr格式 bgr图像数据为原始图像数据,图像数据传输对网络带宽要求较高,一帧图像的大小为个`width*height*3`字节,帧率最高25fps,色彩通道顺序为RGB RGB ... ### 7.7 单人版本人脸检测消息 人脸检测结果为json字符串,结果中数据仅作为参考使用。 无人脸时: ``` { "hasFace": false, //有无人脸 "wakeup": false, //是否人脸唤醒 "frameIndex": 0 //图像帧id } ``` 有人脸时: ``` { "hasFace": true, //有无人脸 "wakeup": true, //是否人脸唤醒 "frameIndex": 0, //图像帧id "faceInfo":{ "x": 10, //人脸左上角x坐标 "y": 10, //人脸左上角y坐标 "w": 100, //人脸宽度 "h": 100, // 人脸高度 "faceIndex":101, //人脸跟随id "headPitch": -0.2, //头姿上下偏转角 "headYaw":-0.2, //头姿左右偏转角 "mouthOcc":false //true:嘴部遮挡 false:嘴部无遮挡 } } ``` ### 7.8 多人版本人脸检测消息 人脸检测结果为json字符串,结果中数据仅作为参考使用。 无人脸时: ``` { "list":[ { "hasFace": false, //有无人脸 "wakeup": false, //是否人脸唤醒 "frameIndex": 0 //图像帧id } ] } ``` 有人脸时: ``` { "list":[ { "hasFace": true, //有无人脸 "wakeup": true, //是否人脸唤醒 "frameIndex": 0, //图像帧id "body":{ "x": 10, //人体左上角x坐标 "y": 10, //人体左上角y坐标 "w": 100, //人体宽度 "h": 100, //人体高度 "bodyIndex":0 //人体跟踪id,同人脸跟踪id }, "faceInfo":{ "x": 10, //人脸左上角x坐标 "y": 10, //人脸左上角y坐标 "w": 100, //人脸宽度 "h": 100, // 人脸高度 "faceIndex":101, //人脸跟随id "headPitch": -0.2, //头姿上下偏转角 "headYaw":-0.2, //头姿左右偏转角 "mouthOcc":false //true:嘴部遮挡 false:嘴部无遮挡 } } ] } ``` # 八、多模态交互套件音频传输协议 ### 8.1 概述 上位机可以通过建立tcp连接来获取到实时唇形降噪后的音频数据。 设备IP:如果盒子为动态ip,可通过[发送串口](#_多模态麦克风和摄像头状态查询)指令来获取ip。 指定端口:9080 ### 8.2 消息格式 消息格式与串口协议类似,唯一不同点为消息数据长度位从2个字节扩充到4个字节。 | 字节 | 值 | 含义说明 | | --- | --- | --- | | 0 | 0xA5 | 同步头 | | 1 | 0x01 | 用户ID | | 2 | 0xXX | 消息类型 | | 3\~6 | 0xXXXXXXXX | 消息数据长度 | | 7\~8 | 0xXXXX | 消息ID | | 9\~n | 消息数据 | 消息数据 | | n\+1 | 0xXX | 内部校验码 | ### 8.3 通信规则 * 单工通信,盒子连续下发音频帧; * 语音模组下发消息,上位机负责接收解析消息; * 建立socket连接之后,盒子即开始下发音频帧; ### 8.4 通信格式 通信格式定义了音频帧消息,详细如下: | 分类 | 同步头 | 用户ID | 消息类型 | 消息长度 | 消息ID | 消息数据 | | | | | 校检码 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | 字节 | 0 | 1 | 2 | 3\~6 | 7\~8 | 9 | 10 | 11\~12 | 13\~16 | 17\~n | n\+1 | | ****音频帧**** | 0xA5 | 0x01 | 0x0a | 同上 | 同上 | vad | 通道号 | 0x00 | 帧号 | 音频 | 0x00 | 消息长度: 数据格式中3\-6字节为消息数据长度,消息长度编码为小端模式,即第3字节存储低字节,第6字节存储高字节。如确认消息中消息数据有4字节,则消息长度为4,编码到3\-6字节就是0x04 0x00 0x00 0x00 消息ID: 数据格式中7\-8字节为消息ID,与消息长度类似,也是小端模式编码。可以使用消息ID过滤因超时重发导致的重复消息。两字节长度的消息ID取值0\-65535,所以在实际使用中需要循环使用,具体实现可以参考Android平台上的源码实现。 校检码: 校验位固定为0x00 ### 8.5 音频帧消息 消息数据中包含vad状态、音频帧编号、pcm音频 #### vad状态 - 0 静音片段 - 1 开始说话 - 2 持续说话 - 3 结束说话 #### 通道号(仅多人多模版本) 标记当前音频对应哪一路说话人。 #### 音频帧号 编码为小端模式,即第13字节存储低字节,第16字节存储高字节。接收到的音频帧号应为连续递增的数字。 #### 音频数据 音频数据格式为16k 16bit 单通道 RK3588多模态盒子内部集成了AIUI语音交互能力,支持通过串口与上位机通信,如当前协议不能满足的需求,也可以通过协议的自定义数据消息扩展 开发包提供了Android上位机上实现demo,其他平台也可以参考。
admin
2025年6月3日 16:26
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码