Android对接科大讯飞AIUI语音转文字装置(魔飞)串口开发
#對(duì)接科大訊飛的魔飛裝置有一段時(shí)間了,現(xiàn)在來(lái)總結(jié)一下遇到的一些問(wèn)題以及踩過(guò)的一些坑:
1.參考科大訊飛給的串口開(kāi)發(fā)文檔
? https://doc.iflyos.cn/aiui/sdk/smart_doc/serial_port_sdk.html#串口協(xié)議實(shí)現(xiàn)參考
里面有科大訊飛語(yǔ)音裝置串口線具體連接方式,并且要注意的一點(diǎn)是此語(yǔ)音裝置串口是TTL的并非是485和232,這點(diǎn)要注意一下,
當(dāng)時(shí)就因?yàn)檫@個(gè)原因一度以為是自己串口讀寫(xiě)代碼有問(wèn)題。
2.協(xié)議解析
根據(jù)訊飛串口開(kāi)發(fā)的協(xié)議來(lái)看,在android端這邊來(lái)實(shí)現(xiàn)的話是會(huì)提供一個(gè)UARTKitCtrDemo是上位機(jī)(Android平臺(tái))集成AIUI串口協(xié)議的sdk開(kāi)發(fā)包的,奈何找了在官網(wǎng)找了很久都沒(méi)有找到相關(guān)的開(kāi)發(fā)包,只能自己解析串口協(xié)議,讀取串口的數(shù)據(jù)以及向串口發(fā)送數(shù)據(jù)這一部分我就不做過(guò)多的講解了,網(wǎng)上有很多只要設(shè)置了對(duì)的波特率,以及你接線的正確串口節(jié)點(diǎn)就可以,現(xiàn)在就android端實(shí)現(xiàn)提供部分協(xié)議解析:
? ? 1.根據(jù)協(xié)議文檔,我們首先要區(qū)分的是握手消息,確認(rèn)消息,以及控制消息。
?
?
? ?
?
握手消息和確認(rèn)消息基本是固定的,文檔有明確說(shuō)明,在接收到握手消息的時(shí)候,要給裝置回復(fù)確認(rèn)消息,以下就是握手確認(rèn)消息構(gòu)建:
/*** 構(gòu)造握手確認(rèn)消息* @param b 握手?jǐn)?shù)據(jù)* @param size 數(shù)據(jù)長(zhǎng)度*/ public boolean bulidRevMessage(byte[] b,int size){boolean isRev = false;byte[] rev = new byte[12];if (size == 12){if ((b[0] & 0xFF) == 165 && (b[1] & 0xff) == 1 && (b[2] & 0xff) == 1){isRev = true;for (int i = 0;i < size-1;i++){if (i == 2){rev[i] = (byte) 0xff;}else {rev[i] = b[i];}}short messageid = IntegerUtils.getShort(b, 5);messageId = messageid;byte checkSum = (byte) LockerSerialportUtil.check(rev, 12);rev[11] = checkSum;sendParams(rev);}}return isRev;}用上面方面來(lái)判斷是否是握手消息,如果是握手消息,就要發(fā)送握手確認(rèn)消息,不然語(yǔ)音裝置會(huì)一直給你發(fā)送握手消息。
?? 2.下面就是重點(diǎn),非握手消息的拼接部分代碼:
/*** 拼接串口消息* @param bytes* @param size*/public void analysisMessage(byte[] bytes,int size){if (size > 2){if ((bytes[0] & 0xFF) == 165 && (bytes[1] & 0xff) == 1 ){if (size>7){if ((bytes[2] & 0xff) == 255){return;}message = new AIUIMessage();message.setHead(bytes[0]);message.setmId(bytes[1]);message.setmType(bytes[2]);short messLen = IntegerUtils.getShort(bytes, 3);short messageid = IntegerUtils.getShort(bytes, 5);message.setmMessageLen(messLen);message.setmMessageId(messageid);messageId = messageid;bulidRevMessage(message);int p = messLen + 3 + 2 + 2 + 1;if (size == p){byte[] body = Arrays.copyOfRange(bytes, 7, messLen+7);message.setmBody(body);}else {byte[] body = Arrays.copyOfRange(bytes, 7, size);message.setmBody(body);}}else {Log.d(TAG, "analysisMessage: 過(guò)濾消息");}}else {if (message != null && message.getmMessageLen() > message.getmBody().length){ // Log.d(TAG, "analysisMessage: "+message.getmMessageLen()+"__"+ message.getmBody().length);message.setmBody(getBody(bytes,size));}}}else if (message != null){if (message.getmMessageLen() > message.getmBody().length){message.setmBody(getBody(bytes,size));}}}private byte[] getBody(byte[] bytes,int size){byte[] bytes1 = message.getmBody();byte[] bytes2;short messageLen = message.getmMessageLen();int bodyLen = message.getmBody().length;if (size> (messageLen-bodyLen+1)){bytes2 = Arrays.copyOfRange(bytes, 0, messageLen-bodyLen);}else {bytes2 = Arrays.copyOfRange(bytes, 0, size);}byte[] bytes3 = Utils.byteMerger(bytes1, bytes2);return bytes3;}? ? 定義的消息接收對(duì)象代碼:
public class AIUIMessage{private byte head;private byte mId;private byte mType;private short mMessageLen;private short mMessageId;private byte[] mBody;private byte sn;public byte getHead() {return head;}public void setHead(byte head) {this.head = head;}public byte getmType() {return mType;}public void setmType(byte mType) {this.mType = mType;}public byte getmId() {return mId;}public void setmId(byte mId) {this.mId = mId;}public short getmMessageId() {return mMessageId;}public void setmMessageId(short mMessageId) {this.mMessageId = mMessageId;}public short getmMessageLen() {return mMessageLen;}public void setmMessageLen(short mMessageLen) {this.mMessageLen = mMessageLen;}public byte[] getmBody() {return mBody;}public void setmBody(byte[] mBody) {this.mBody = mBody;}public byte getSn() {return sn;}public void setSn(byte sn) {this.sn = sn;} }這里面我自己定義了一個(gè)對(duì)象來(lái)存儲(chǔ)串口讀出來(lái)的數(shù)據(jù),因?yàn)橛械臄?shù)據(jù)可能一次性讀不完,所以要將消息拼接起來(lái)解析。
? 3.通過(guò)串口發(fā)送控制消息給語(yǔ)音裝置這里我就簡(jiǎn)單的構(gòu)建了一個(gè)例子出來(lái):
/*** 構(gòu)建控制消息* @param messagId 消息id*/ private void buildTTSMessage(short messagId, AIUIBase aiuiBase){Gson gson = new Gson();String s = gson.toJson(aiuiBase);try {messageId++;byte[] strByte = s.getBytes("UTF-8");int len = 8 + strByte.length;byte[] sendTTs = new byte[len];sendTTs[0] = (byte) 0xA5;sendTTs[1] = (byte) 0x01;sendTTs[2] = (byte) 0x05;byte[] bytes = IntegerUtils.shortToBytes((short) strByte.length);byte[] bytes1 = IntegerUtils.shortToBytes(messagId);sendTTs[3] = bytes[0];sendTTs[4] = bytes[1];sendTTs[5] = bytes1[0];sendTTs[6] = bytes1[1];for (int i=0;i<strByte.length;i++){sendTTs[i+7] = strByte[i];}byte checkSum = (byte) LockerSerialportUtil.check(sendTTs, len);sendTTs[len-1] = checkSum;sendParams(sendTTs);String s1 = LockerSerialportUtil.byteToStr(sendTTs, len);Log.d(TAG, "發(fā)送控制消息: "+s1);} catch (Exception e) {Log.d(TAG, "buildTTSMessage Exception: "+e);} }發(fā)送控制消息的這里要特別注意一點(diǎn),就是消息id不能夠亂填,要根據(jù)上一條的消息id加1,來(lái)確定下一條消息id,亂填id會(huì)導(dǎo)致你發(fā)送的命令不生效,這里你可以根據(jù)語(yǔ)音裝置給過(guò)來(lái)的id進(jìn)行保存,然后發(fā)送消息的時(shí)候加1就好了,確認(rèn)消息的id是不遵循這個(gè)規(guī)則的。
這些就是我這段時(shí)間弄魔飛語(yǔ)音裝置的一些總結(jié),可能有不好的地方,后續(xù)會(huì)做優(yōu)化,修改。
?
?
?
? ? ?
?
總結(jié)
以上是生活随笔為你收集整理的Android对接科大讯飞AIUI语音转文字装置(魔飞)串口开发的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python课程设计博客网_python
- 下一篇: Android指南针程序的实现