Android对接科大讯飞AIUI语音转文字装置(魔飞)串口开发
#對接科大訊飛的魔飛裝置有一段時間了,現在來總結一下遇到的一些問題以及踩過的一些坑:
1.參考科大訊飛給的串口開發文檔
? https://doc.iflyos.cn/aiui/sdk/smart_doc/serial_port_sdk.html#串口協議實現參考
里面有科大訊飛語音裝置串口線具體連接方式,并且要注意的一點是此語音裝置串口是TTL的并非是485和232,這點要注意一下,
當時就因為這個原因一度以為是自己串口讀寫代碼有問題。
2.協議解析
根據訊飛串口開發的協議來看,在android端這邊來實現的話是會提供一個UARTKitCtrDemo是上位機(Android平臺)集成AIUI串口協議的sdk開發包的,奈何找了在官網找了很久都沒有找到相關的開發包,只能自己解析串口協議,讀取串口的數據以及向串口發送數據這一部分我就不做過多的講解了,網上有很多只要設置了對的波特率,以及你接線的正確串口節點就可以,現在就android端實現提供部分協議解析:
? ? 1.根據協議文檔,我們首先要區分的是握手消息,確認消息,以及控制消息。
?
?
? ?
?
握手消息和確認消息基本是固定的,文檔有明確說明,在接收到握手消息的時候,要給裝置回復確認消息,以下就是握手確認消息構建:
/*** 構造握手確認消息* @param b 握手數據* @param size 數據長度*/ 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;}用上面方面來判斷是否是握手消息,如果是握手消息,就要發送握手確認消息,不然語音裝置會一直給你發送握手消息。
?? 2.下面就是重點,非握手消息的拼接部分代碼:
/*** 拼接串口消息* @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: 過濾消息");}}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;}? ? 定義的消息接收對象代碼:
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;} }這里面我自己定義了一個對象來存儲串口讀出來的數據,因為有的數據可能一次性讀不完,所以要將消息拼接起來解析。
? 3.通過串口發送控制消息給語音裝置這里我就簡單的構建了一個例子出來:
/*** 構建控制消息* @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, "發送控制消息: "+s1);} catch (Exception e) {Log.d(TAG, "buildTTSMessage Exception: "+e);} }發送控制消息的這里要特別注意一點,就是消息id不能夠亂填,要根據上一條的消息id加1,來確定下一條消息id,亂填id會導致你發送的命令不生效,這里你可以根據語音裝置給過來的id進行保存,然后發送消息的時候加1就好了,確認消息的id是不遵循這個規則的。
這些就是我這段時間弄魔飛語音裝置的一些總結,可能有不好的地方,后續會做優化,修改。
?
?
?
? ? ?
?
總結
以上是生活随笔為你收集整理的Android对接科大讯飞AIUI语音转文字装置(魔飞)串口开发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python课程设计博客网_python
- 下一篇: 公司人事管理系统