import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Environment;
import android.telephony.TelephonyManager;
+import com.enqualcomm.support.Config;
+import com.enqualcomm.support.bean.Content;
import com.enqualcomm.support.bean.Runtime;
import com.enqualcomm.support.bean.StringMessage;
+import com.enqualcomm.support.bean.VoiceContent;
+import com.enqualcomm.support.bean.voicePacket;
import com.enqualcomm.support.utils.Connection;
import com.enqualcomm.support.utils.ICLogger;
import com.enqualcomm.support.utils.TimeUtil;
+import com.enqualcomm.support.utils.Util;
+import java.io.File;
import java.util.HashMap;
import java.util.Locale;
+import static com.enqualcomm.support.bean.Contact.GROUP_ALL;
import static java.lang.Math.abs;
/**
BPFD/*交好友响应*/,
BP07/*语音上行响应*/,
BP95/*语音上行给好友响应*/,
+ BP28/*语音下行*/,
+ AP28/*语音反馈*/,
+ AP16/*立即定位*/,
+ AP17/*恢复出厂设置*/,
+ AP18/*重启上行*/,
+ AP31/*关机上行*/
}
cmdMap.put(CMD_TYPE.APFD, "APFD");
/* 服务器发起*/
cmdMap.put(CMD_TYPE.BP12, "BP12");
+ cmdMap.put(CMD_TYPE.AP16, "AP16");
cmdMap.put(CMD_TYPE.BP14, "BP14");
cmdMap.put(CMD_TYPE.BP07, "BP07");
cmdMap.put(CMD_TYPE.BP44, "BP44");
cmdMap.put(CMD_TYPE.BP99, "BP99");
cmdMap.put(CMD_TYPE.BPSW, "BPSW");
cmdMap.put(CMD_TYPE.BP95, "BP95");
+ cmdMap.put(CMD_TYPE.BP28, "BP28");
+ cmdMap.put(CMD_TYPE.AP28, "AP28");
+ cmdMap.put(CMD_TYPE.AP17, "AP17");
+ cmdMap.put(CMD_TYPE.AP18, "AP18");
}
}
public static byte[] AP07(String packetTime, int count, int index, int datalen, byte[] amrdata) {
-//IWAP07,20140818064408,6,1,1024,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX#
-//说明:
-//IW:标识符
-//AP07 : 命令字符
-//20140818064408 :yyyyMMddHHmmss 格式的年月日时分秒,设备录音时间
-//6:语音包分包总数
-//1 :当前包数,第一包为1,第二包为2,。。。。。。同一个语音包的语音时间相同
-//1024 :语音包长度
-//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:当前音频数据, 每个音频数据包大小为1024字节,最后一包不足1024的取实际字节数
-//语音包上传规则:
-//按包次序依次上传,上传后如果没有收到服务器的响应包,则继续上传该语音包。
-//收到设备回复确认数据包接收成功状态后,继续开始依次上传下一个数据包。。。。。。
-//如果设备回复确认数据包接收失败状态,则重复发送上一个数据包
+ //IWAP07,20140818064408,6,1,1024,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX#
+ //说明:
+ //IW:标识符
+ //AP07 : 命令字符
+ //20140818064408 :yyyyMMddHHmmss 格式的年月日时分秒,设备录音时间
+ //6:语音包分包总数
+ //1 :当前包数,第一包为1,第二包为2,。。。。。。同一个语音包的语音时间相同
+ //1024 :语音包长度
+ //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:当前音频数据, 每个音频数据包大小为1024字节,最后一包不足1024的取实际字节数
+ //语音包上传规则:
+ //按包次序依次上传,上传后如果没有收到服务器的响应包,则继续上传该语音包。
+ //收到设备回复确认数据包接收成功状态后,继续开始依次上传下一个数据包。。。。。。
+ //如果设备回复确认数据包接收失败状态,则重复发送上一个数据包
String sb = new StringBuffer(CMDHEADER).append(cmdMap.get(CMD_TYPE.AP07))
return sm;
}
+ private int dataPart = 1;
+
+ private static final String CMD_HEADER = "[";
+ private static final String CMD_COMPANY = "IC";
+ private static final String CMD_END = "]";
+ private static final String CMD_HEADER_SPLIT = "*";
+ private static final String CMD_SPLIT = ",";
+ private byte[] totalByte;
+
+ private StringBuffer cmdbuf = new StringBuffer();
//指令解析
- public void parseCmd(String cmd_type, byte[] bytes) {
- ICLogger.d("cmd_type == > " + cmd_type);
- ICLogger.d("byte == > " + new String(bytes));
+ public void parseCmd(byte[] bytes) {
+ boolean iscmdComplete = false;
+ boolean ret = true;
+ String last_inCompletecmd = "";
+ String cmd_msgbuf = new String(bytes);
+ ICLogger.d("bytes.size " + bytes.length);
+// cmdbuf.append(cmd_msgbuf);
+ cmdbuf.append(cmd_msgbuf);
+ ICLogger.d("cmdbuf.size " + cmdbuf.length() + " " + cmdbuf.toString());
+ /*
+ 如果不是 #结尾,就认为 接收数据不全,置位。
+ */
+ if (cmdbuf.toString().endsWith(CMDEND)) {
+ iscmdComplete = true;
+ }
+ String[] cmdlist = cmd_msgbuf.split(CMDEND);
+ int listLen = cmdlist.length;
+ ICLogger.d("listLen " + listLen);
+ /*
+ 如果解析出来的cmdlist不是空,且数据不是完整cmd则保留 最后一条数据到last_inCompletecmd
+ */
+ if (cmdlist.length > 0 && !iscmdComplete) {
+ listLen -= 1;
+ last_inCompletecmd = cmdlist[listLen];
+ ICLogger.d("cmd not complete , " + last_inCompletecmd);
+ }
+ for (int i = 0; i < listLen; i++) {
+ for (CMD_TYPE key : cmdMap.keySet()) {
+ if (cmdlist[i].startsWith(CMDHEADER + cmdMap.get(key))) {
+ ICLogger.d("found cmd keyid=" + key +
+ " ,keyname=" + cmdMap.get(key)
+ + " , " + cmdlist[i]);
+ if (key == CMD_TYPE.BP28) {
+ //如果是BP28则 后面的数据是音频,需要保留
+ int amrLen = getBP28Amrlen(cmdlist[i]);
+ if (bytes.length > amrLen) {
+ handleCmd(key, cmdlist[i], bytes);
+ }
+ } else {
+ handleCmd(key, cmdlist[i]);
+ }
+ }
+ }
+ }
+
+ cmdbuf = new StringBuffer().append(last_inCompletecmd);
+ }
+
+ public void handleCmd(CMD_TYPE type, String cmd) {
+ //普通非二进制命令用此函数处理
+ boolean ret = true;
+ ICLogger.i("handleCmd " + type.name() + " strLen=" + cmd.length());
+ if (Config.LOG_TOFILE) ICLogger.logToFile("APILog", " recv " + cmd);
+ switch (type) {
+ case BP16:
+ //立即定位指令(长链接有效)
+ handleBP16(mConnection, mRuntime, cmd);
+ mConnection.DeliverCMDMessageToSystem("StartLocate", cmd);//通知下面线程状态变化
+ break;
+ case BP17:
+ //收到恢复出厂设置
+ handleBP17(mConnection, cmd);
+ ICLogger.i("收到服务器恢复出厂设置命令BP17");
+ mConnection.DeliverCMDMessageToSystem("FactoryReset", cmd);//通知下面线程状态变化
+ break;
+ case BP18:
+ //收到重启
+ handleBP18(mConnection, cmd);
+ ICLogger.i("收到服务器重启命令BP18");
+ mConnection.DeliverCMDMessageToSystem("Reboot", cmd);//通知下面线程状态变化
+ break;
+ case BP31:
+ //收到关机
+ handleBP31(mConnection, cmd);
+ ICLogger.i("收到服务器关机命令BP31");
+ mConnection.DeliverCMDMessageToSystem("poweroff", cmd);//通知下面线程状态变化
+ break;
+ }
+ }
+
+
+ public void handleBP31(Connection connection, String cmd) {
+
+ // IWBP31,867155030001063,161723
+ String[] cmdlist = cmd.split(CMDSPLIT);
+ if (cmdlist.length == 3) {
+
+ connection.send(AP31(cmdlist[2]));
+
+ }
}
+
+
+ public static StringMessage AP31(String index) {
+ return genStringMessage(cmdMap.get(CMD_TYPE.AP31),
+ new StringBuffer(CMDHEADER).append(cmdMap.get(CMD_TYPE.AP31))
+ .append(CMDSPLIT).append(index)
+ .append(CMDEND).toString());
+ }
+
+ public void handleBP18(Connection connection, String cmd) {
+
+ // IWBP18,867155030001063,161723
+ String[] cmdlist = cmd.split(CMDSPLIT);
+ if (cmdlist.length == 3) {
+
+ connection.send(AP18(cmdlist[2]));
+
+ }
+ }
+
+
+ public static StringMessage AP18(String index) {
+ return genStringMessage("AP18", new StringBuffer(CMDHEADER).append(cmdMap.get(CMD_TYPE.AP18))
+ .append(CMDSPLIT).append(index)
+ .append(CMDEND).toString());
+ }
+
+ public void handleBP17(Connection connection, String cmd) {
+
+ //IWBP17,867155030001063,161723
+ String[] cmdlist = cmd.split(CMDSPLIT);
+ if (cmdlist.length == 3) {
+ connection.send(AP17(cmdlist[2]));
+ }
+ }
+
+ //恢复出厂设置
+ public static StringMessage AP17(String index) {
+ return genStringMessage("AP17",
+ new StringBuffer(CMDHEADER).append(cmdMap.get(CMD_TYPE.AP17))
+ .append(CMDSPLIT).append(index)
+ .append(CMDEND).toString());
+ }
+
+ // 立即定位指令(长链接有效)
+ public void handleBP16(Connection connection, Runtime runtime, String cmd) {
+ //示例数据:IWBP16,867155030001063,335386
+// IWBP16,353456789012345,080835#
+// 说明:
+// IW:标识符
+// BP16 : 命令字符
+// 353456789012345:IMEI号,设备唯一ID
+// 080835 :指令流水号
+ String[] cmdlist = cmd.split(",");
+ if (cmdlist.length == 3) {
+ ICLogger.d("imei " + cmdlist[1] + ", cmdindex " + cmdlist[2]);
+
+ connection.send(AP16(cmdlist[2]));
+ } else {
+ ICLogger.d("error BP16 format");
+ }
+ }
+
+ //立即定位反馈
+ public static StringMessage AP16(String cmdindex) {
+ //IWAP16,080835#
+ //080835:指令流水号
+ return genStringMessage("AP16",
+ new StringBuffer(CMDHEADER).append(cmdMap.get(CMD_TYPE.AP16))
+ .append(CMDSPLIT).append(cmdindex)
+ .append(CMDEND).toString());
+ }
+
+ public boolean handleCmd(CMD_TYPE type, String cmd, byte[] bytes) {
+
+ //只有需要传递二级制数据的才需要这个函数,目前只有BP28需要
+
+ boolean ret = true;
+ ICLogger.i("handleCmd " + type.name() + " " + cmd + " bytelen=" + bytes.length);
+ if (Config.LOG_TOFILE) ICLogger.logToFile("APILog", " recv " + new String(bytes));
+ switch (type) {
+ case BP28:
+ handleBP28(mConnection, cmd, mRuntime, bytes);
+ ICLogger.i("收到服务器语音BP28");
+ mConnection.DeliverCMDMessageToSystem("BP28", "");//通知下面线程状态变化
+ break;
+ }
+ return ret;
+ }
+
+
+ //处理 BP28 语音消息
+ public void handleBP28(Connection connection, String cmd, Runtime runtime, byte[] bytes) {
+ //log("handleBP28 msg"+cmd);
+ /**
+ * IWBP28, D3590D54,XXXX,6,1,1024,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX#
+ * 说明:
+ * IW:标识符
+ * BP28 : 命令字符
+ * D3590D54:UNICODE编码,发送者名称
+ * XXXX: 附加信息,在响应数据包时,将附加信息原样响应,类似流水号
+ * 6:语音包分包总数
+ * 1 :当前包数,第一包为1,第二包为2,。。。。。。同一个语音包的语音时间相同
+ * 1024 :语音包长度
+ * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:当前音频数据, 每个音频数据包大小为1024字节,最后一包不足1024的取实际字节数
+ * 语音包上传规则:
+ * 按包次序依次上传,上传后如果没有收到服务器的响应包,则继续上传该语音包。
+ * 收到设备回复确认数据包接收成功状态后,继续开始依次上传下一个数据包。。。。。。
+ * 如果设备回复确认数据包接收失败状态,则重复发送上一个数据包
+ * 设备响应: IWAP28,D3590D54,XXXX,6,1,1#
+ * D3590D54:UNICODE编码,发送者名称
+ * XXXX: 附加信息,原样返回
+ * 6:语音包分包总数
+ * 1:当前设备收到的是第几个包
+ * 1:表示设备接受数据成功,0表示设备接受数据失败
+ */
+ String Name;
+ String appendIndex;
+ int packetCount;
+ int currentId;
+ int packetLen;
+ byte[] packetData;
+
+ String[] msg = cmd.split(CMDSPLIT);
+ if (msg.length >= 6) {
+ try {
+ Name = msg[1];
+ appendIndex = msg[2];
+ packetCount = Integer.parseInt(msg[3]);
+ currentId = Integer.parseInt(msg[4]);
+ packetLen = Integer.parseInt(msg[5]);
+ packetData = Util.subArray(bytes,
+ msg[0].length() + msg[1].length() + msg[2].length() + msg[3].length() + msg[4].length() + msg[5].length() + 6, bytes.length - 1);
+
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append("recv BP28 name = ").append(Name)
+ .append(",appendIndex = ").append(appendIndex)
+ .append(",packetCount = ").append(packetCount)
+ .append(",currentId = ").append(currentId)
+ .append(",packetLen = ").append(packetLen)
+ .append(",packetDatalen = ").append(packetData.length);
+
+ ICLogger.d(stringBuffer.toString());
+ connection.send(AP28(Name, appendIndex, packetCount, currentId, 1));
+ voicePacket.getInstance().appendVoice(Name,
+ appendIndex, packetCount, currentId, packetLen, packetData);
+ ICLogger.d("================" + voicePacket.getInstance().toString());
+ if (voicePacket.getInstance().isFinished()) {
+
+ String dir = Environment.getExternalStorageDirectory() + "/Android/VoiceCache";
+ String amrFilepath = Util.saveFile(voicePacket.getInstance().getVoicePacketBytes(), 0, voicePacket.getInstance().getVoicePacketLen(), new File(dir), "receive_" + voicePacket.getInstance().getPacketTime() + ".amr");
+ ICLogger.i("save Amr file to " + amrFilepath);
+ voicePacket.getInstance().clearPacket();
+ VoiceContent voiceContent = VoiceContent.placeHolderIn(Content.CONTACT_CATEGORY_GROUP, GROUP_ALL, amrFilepath);
+
+
+ final Uri uri2 = runtime.getDbHelper().insertMessage(voiceContent);
+
+ //回复UI消息,表示已经接收到
+ voiceContent.status = 3;
+ voiceContent.serverTime = TimeUtil.getSystemTime3();
+ voiceContent.preview = String.valueOf(Util.getDuration(voiceContent.content));
+ runtime.getDbHelper().updateMessage(voiceContent, uri2);
+
+// runtime.getContextProxy().sendBroadcast(ACTION_IMESSAGE, runtime);
+
+ connection.DeliverCMDMessageToSystem("NewVoice", amrFilepath);//通知下面线程状态变化
+ }
+ } catch (Exception e) {
+ ICLogger.e(e.getMessage(), e);
+ }
+ } else {
+ ICLogger.d("handleBP28 format Error");
+// connection.send(genStringMessage("AP28",AP28(Name,appendIndex,packetCount,currentId,0)));
+
+ }
+
+ }
+
+ /*语音下行反馈*/
+ public static StringMessage AP28(String name, String msg, int packagecount, int currentpackageindex, int received_success) {
+ //示例数据:IWAP28,D3590D54,xxxx,6,1,1#
+ return genStringMessage("AP28", new StringBuffer(CMDHEADER).append(cmdMap.get(CMD_TYPE.AP28))
+ .append(CMDSPLIT).append(name)
+ .append(CMDSPLIT).append(msg)
+ .append(CMDSPLIT).append(packagecount)
+ .append(CMDSPLIT).append(currentpackageindex)
+ .append(CMDSPLIT).append(received_success)
+ .append(CMDEND).toString());
+ }
+
+
+ public int getBP28Amrlen(String cmd) {
+
+ String Name;
+ String appendIndex;
+ int packetCount;
+ int currentId;
+ int packetLen;
+
+
+ String[] msg = cmd.split(CMDSPLIT);
+ if (msg.length >= 6) {
+
+ try {
+ Name = msg[1];
+ appendIndex = msg[2];
+ packetCount = Integer.parseInt(msg[3]);
+ currentId = Integer.parseInt(msg[4]);
+ packetLen = Integer.parseInt(msg[5]);
+
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append("getBP28AmrLen name = ").append(Name)
+ .append(",appendIndex = ").append(appendIndex)
+ .append(",packetCount = ").append(packetCount)
+ .append(",currentId = ").append(currentId)
+ .append(",packetLen = ").append(packetLen);
+
+ ICLogger.d(stringBuffer.toString());
+ return packetLen;
+ } catch (Exception e) {
+ ICLogger.e(e.getMessage(), e);
+ }
+ } else {
+ ICLogger.d("getBP28AmrLen format Error");
+
+ }
+ return -1;
+ }
+
}