package com.bg7yoz.ft8cn.x6100; import static com.bg7yoz.ft8cn.flex.VITA.XIEGU_METER_CLASS_ID; import static com.bg7yoz.ft8cn.flex.VITA.XIEGU_METER_Stream_Id; import static com.bg7yoz.ft8cn.flex.VITA.XIEGU_PING_CLASS_ID; import static com.bg7yoz.ft8cn.flex.VITA.XIEGU_PING_Stream_Id; import static com.bg7yoz.ft8cn.flex.VITA.byteToStr; import static com.bg7yoz.ft8cn.flex.VITA.readShortData; import static com.bg7yoz.ft8cn.x6100.X6100Radio.XieguResponseStyle.RESPONSE; import android.annotation.SuppressLint; import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioTrack; import android.util.Log; import androidx.lifecycle.MutableLiveData; import com.bg7yoz.ft8cn.GeneralVariables; import com.bg7yoz.ft8cn.R; import com.bg7yoz.ft8cn.flex.FlexCommand; import com.bg7yoz.ft8cn.flex.FlexRadio; import com.bg7yoz.ft8cn.flex.FlexResponseStyle; import com.bg7yoz.ft8cn.flex.RadioTcpClient; import com.bg7yoz.ft8cn.flex.RadioUdpClient; import com.bg7yoz.ft8cn.flex.VITA; import com.bg7yoz.ft8cn.flex.VitaPacketType; import com.bg7yoz.ft8cn.flex.VitaTSF; import com.bg7yoz.ft8cn.flex.VitaTSI; import com.bg7yoz.ft8cn.rigs.BaseRig; import com.bg7yoz.ft8cn.ui.ToastMessage; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Arrays; import java.util.Iterator; import java.util.Timer; import java.util.TimerTask; public class X6100Radio { public enum XieguCommand { UNKNOW,//未知指令 AUDIO,//音频指令 STREAM,//数据流指令 SUB,//订阅仪表 UNSUB,//取消订阅仪表 A91,//ft8符号 ATU,//自动天调 TUNE,//设置频率 MODE,//操作模式 PTT,//PTT操作 SET//设置操作 } public enum XieguResponseStyle { STATUS,//状态信息,S+HANDLE RESPONSE,//命令的响应,R+客户端命令序列号 HANDLE,//电台给定的句柄,H+句柄(32位的16进制表示) VERSION,//版本号,V+版本号 COMMAND,//发送命令,C+序列号|命令 UNKNOW//未知的回复类型 } private static final String TAG = "X6100Radio"; private static int lossCount = 0; private static int currentCount = -1; private String modelName;//电台型号 private String version;//电台版本号 private String rig_ip;//电台的IP private String mac;//mac地址 public boolean isPttOn = false; private int control_port = 7002;//电台的控制端口 private int stream_port = 7003;//电台端流数据的端口 private int discovery_port = 7001;//发现协议的端口 private long lastSeen;//最后一次消息的时间 private boolean isAvailable = true;//电台是不是有效 private final StringBuilder buffer = new StringBuilder();//指令的缓存 private final RadioTcpClient tcpClient = new RadioTcpClient(); private RadioUdpClient streamClient; private int commandSeq = 1;//指令的序列 private XieguCommand xieguCommand; private int handle = 0; private String commandStr; private int frames = 768;//每个周期的帧数 private int period = 64;//每个周期的时长,毫秒 //************************事件处理接口******************************* private OnReceiveDataListener onReceiveDataListener;//当前接收到的数据事件 private OnTcpConnectStatus onTcpConnectStatus;//当TCP连接状态变化的事件 private OnReceiveStreamData onReceiveStreamData;//当接收到流数据后的处理事件 private OnCommandListener onCommandListener;//触发命令事件 private OnStatusListener onStatusListener;//触发状态事件 //***************************************************************** private AudioTrack audioTrack = null; ///******************用于仪表信息显示************* public MutableLiveData mutablePing = new MutableLiveData<>();//ping值 public MutableLiveData mutableLossPackets = new MutableLiveData<>();//丢失的包数量 public MutableLiveData mutableMeters = new MutableLiveData<>(); private X6100Meters meters = new X6100Meters(); private boolean swrAlert = false; private boolean alcAlert = false; private Timer pingTimer = new Timer(); private TimerTask pingTask() { return new TimerTask() { @Override public void run() { try { if (!streamClient.isActivated() || !isConnect()) { pingTimer.cancel(); pingTimer.purge(); pingTimer = null; return; } VITA vita = new VITA(VitaPacketType.EXT_DATA_WITH_STREAM , VitaTSI.TSI_OTHER , VitaTSF.TSF_REALTIME , 0 , XIEGU_PING_Stream_Id , XIEGU_PING_CLASS_ID); vita.packetCount = 0; vita.packetSize = 7; vita.integerTimestamp = 0;//0是发送包,1是接收包 vita.fracTimeStamp = System.currentTimeMillis(); streamClient.sendData(vita.pingDataToVita(), rig_ip, stream_port); } catch (Exception e) { Log.e(TAG, "ping timer error:" + e.getMessage()); } } }; } /** * 更新最后看到的时间 */ public void updateLastSeen() { this.lastSeen = System.currentTimeMillis(); } public X6100Radio() { updateLastSeen(); } public X6100Radio(String s, String ip) { mutableLossPackets.postValue(0); update(s, ip); } public void update(String discoverStr, String ip) { Log.d(TAG, discoverStr); rig_ip = ip; String[] paras = discoverStr.replace("\0", " ").split(" "); version = getParameterStr(paras, "ft8cn_server_version"); modelName = getParameterStr(paras, "model"); mac = getParameterStr(paras, "mac"); control_port = getParameterInt(paras, "control_port"); stream_port = getParameterInt(paras, "stream_port"); discovery_port = getParameterInt(paras, "discovery_port"); updateLastSeen(); } /** * 到参数列表中找指定的字符类型参数 * * @param parameters 参数列表 * @param prefix 参数名前缀 * @return 参数 */ private String getParameterStr(String[] parameters, String prefix) { for (int i = 0; i < parameters.length; i++) { if (parameters[i].toLowerCase().startsWith(prefix.toLowerCase() + "=")) { return parameters[i].substring(prefix.length() + 1); } } //如果没找到,返回空字符串 return ""; } /** * 到参数列表中找指定的int类型参数 * * @param parameters 参数列表 * @param prefix 参数名前缀 * @return 参数 */ private int getParameterInt(String[] parameters, String prefix) { for (int i = 0; i < parameters.length; i++) { if (parameters[i].toLowerCase().startsWith(prefix.toLowerCase() + "=")) { try { return Integer.parseInt(parameters[i].substring(prefix.length() + 1)); } catch (NumberFormatException e) { e.printStackTrace(); Log.e(TAG, "getParameterInt exception: " + e.getMessage()); return 0; } } } //如果没找到,返回0 return 0; } /** * 检查是不是 刚刚 离线,离线条件:5秒内没有收到电台的广播数据包 * * @return 是否 */ public boolean isInvalidNow() { if (isAvailable) {//如果标记在线,而大于5秒的时间没有收到数据包,就视为刚刚离线。 isAvailable = System.currentTimeMillis() - lastSeen < 1000 * 5;//小于5秒,就视为在线 return !isAvailable; } else {//如果已经标记不在线了,就不是刚刚离线的。 return false; } } public String getModelName() { return modelName; } public void setModelName(String modelName) { this.modelName = modelName; } public String getVersion() { return version; } public String getRig_ip() { return rig_ip; } public void setRig_ip(String rig_ip) { this.rig_ip = rig_ip; } public String getMac() { return mac; } public boolean isEqual(String madAddress) { return this.mac.equalsIgnoreCase(madAddress); } /** * 连接到控制电台 */ public void connect() { this.connect(this.rig_ip, this.control_port); } /** * 连接控制到电台,TCP * * @param ip 地址 * @param port 端口 */ public void connect(String ip, int port) { if (tcpClient.isConnect()) { tcpClient.disconnect(); } //Tcp连接触发的事件 tcpClient.setOnDataReceiveListener(new RadioTcpClient.OnDataReceiveListener() { @Override public void onConnectSuccess() { if (onTcpConnectStatus != null) { onTcpConnectStatus.onConnectSuccess(tcpClient); } } @Override public void onConnectFail() { if (onTcpConnectStatus != null) { onTcpConnectStatus.onConnectFail(tcpClient); } } @Override public void onDataReceive(byte[] buffer) { if (onReceiveDataListener != null) {//此处把数据传递给XieGu6100NetRig onReceiveDataListener.onDataReceive(buffer); } onReceiveData(buffer); } @Override public void onConnectionClosed() { tcpClient.disconnect(); ToastMessage.show(GeneralVariables.getStringFromResource(R.string.tcp_connect_closed)); if (onTcpConnectStatus != null){ onTcpConnectStatus.onConnectionClosed(tcpClient); } } }); clearBufferData();//清除一下缓存的指令数据 tcpClient.connect(ip, port);//连接TCP } /** * 关闭接收数据流的端口 */ public synchronized void closeStreamPort() { if (streamClient != null) { if (streamClient.isActivated()) { try { streamClient.setActivated(false); } catch (Exception e) { e.printStackTrace(); } } } streamClient = null; } @SuppressLint("DefaultLocale") public synchronized void commandAtuOn() { sendCommand(XieguCommand.ATU, "atu on"); } @SuppressLint("DefaultLocale") public synchronized void commandAtuOff() { sendCommand(XieguCommand.ATU, "atu off"); } @SuppressLint("DefaultLocale") public synchronized void commandAtuStart() { sendCommand(XieguCommand.ATU, "atu start"); } @SuppressLint("DefaultLocale") public synchronized void commandOpenStream() { sendCommand(XieguCommand.STREAM, String.format("stream on %d", stream_port)); } @SuppressLint("DefaultLocale") public synchronized void commandSendA91(byte[] a91, float vol, float freq) { sendCommand(XieguCommand.A91, String.format("a91 %.2f %.0f %s", vol, freq, BaseRig.byteToStr(a91))); } @SuppressLint("DefaultLocale") public synchronized void commandGetAudioInfo() { sendCommand(XieguCommand.AUDIO, "audio get all"); } @SuppressLint("DefaultLocale") public synchronized void commandGetStreamInfo() { sendCommand(XieguCommand.STREAM, "stream get"); } @SuppressLint("DefaultLocale") public synchronized void commandSubAllMeter() { sendCommand(XieguCommand.SUB, "sub all"); } @SuppressLint("DefaultLocale") public synchronized void commandSubGetMeter() { sendCommand(XieguCommand.SUB, "sub get"); } @SuppressLint("DefaultLocale") public synchronized void commandUnubMeter() { sendCommand(XieguCommand.UNSUB, "unsub"); } @SuppressLint("DefaultLocale") public synchronized void commandTuneFreq(long freq) { sendCommand(XieguCommand.TUNE, String.format("tune %d", freq)); } @SuppressLint("DefaultLocale") public synchronized void commandSetMode(String mode, int filter) { sendCommand(XieguCommand.TUNE, String.format("mode %s %d", mode, filter)); } @SuppressLint("DefaultLocale") public synchronized void commandSetTxPower(int power) { sendCommand(XieguCommand.SET, String.format("set tx %d", power)); } @SuppressLint("DefaultLocale") public synchronized void commandSetTxVol(int volume) { sendCommand(XieguCommand.SET, String.format("set tx_vol %d", volume)); } private void showAlert() { Log.e(TAG, String.format("ALC:%f", meters.alc)); if (meters.swr >= 5) { if (!swrAlert) { swrAlert = true; ToastMessage.show(GeneralVariables.getStringFromResource(R.string.swr_high_alert)); } } else { swrAlert = false; } if (meters.alc > 50 || meters.alc < 20) { if (!alcAlert) { alcAlert = true; if (meters.alc > 50) { ToastMessage.show(GeneralVariables.getStringFromResource(R.string.alc_high_alert)); } else { ToastMessage.show(GeneralVariables.getStringFromResource(R.string.alc_low_alert)); } } } else { alcAlert = false; } } /** * 打开接收数据流的端口 */ public void openStreamPort() { if (streamClient != null) { if (streamClient.isActivated()) { try { streamClient.setActivated(false); } catch (Exception e) { ToastMessage.show(e.getMessage()); e.printStackTrace(); } } } RadioUdpClient.OnUdpEvents onUdpEvents = new RadioUdpClient.OnUdpEvents() { @SuppressLint("DefaultLocale") @Override public void OnReceiveData(DatagramSocket socket, DatagramPacket packet, byte[] data) { VITA vita = new VITA(data); if (vita.classId64 == VITA.XIEGU_AUDIO_CLASS_ID) {//音频数据 //判断数据包丢失情况 int temp = lossCount; if (currentCount <= -1) { currentCount = vita.packetCount; } if (currentCount > vita.packetCount) { lossCount = lossCount + vita.packetCount + 16 - currentCount - 1; } else if (currentCount < vita.packetCount) { lossCount = lossCount + vita.packetCount - currentCount - 1; } currentCount = vita.packetCount; if (lossCount > temp) { Log.e(TAG, String.format("丢包数量:%d", lossCount)); for (int i = 0; i < (lossCount - temp); i++) { Log.d(TAG, String.format("补发数据,%d,size:%d", i, vita.payload.length)); sendReceivedAudio(vita.payload);//把当前的数据补发给录音对象 } mutableLossPackets.postValue(lossCount); } sendReceivedAudio(vita.payload);//把音频发给录音对象 playReceiveAudio(vita.payload);//发送当前的音频数据 } else if (vita.classId64 == XIEGU_PING_CLASS_ID//ping数据 && vita.streamId == XIEGU_PING_Stream_Id && vita.integerTimestamp == 1) {//ping的回包 mutablePing.postValue(System.currentTimeMillis() - vita.fracTimeStamp); } else if (vita.classId64 == XIEGU_METER_CLASS_ID//仪表数据 && vita.streamId == XIEGU_METER_Stream_Id) { new Thread(new Runnable() { @Override public void run() { meters.update(vita.payload); mutableMeters.postValue(meters); if (isPttOn) { showAlert(); } else { alcAlert = false; swrAlert = false; } if (onReceiveStreamData != null){ onReceiveStreamData.onReceiveMeter(meters); } } }).start(); } } }; //此处要确定stream的udp端口 streamClient = new RadioUdpClient(stream_port); streamClient.setOnUdpEvents(onUdpEvents); try { streamClient.setActivated(true); pingTimer.schedule(pingTask(), 1000, 1000);//启动ping计时器 } catch (SocketException e) { ToastMessage.show(e.getMessage()); e.printStackTrace(); Log.d(TAG, "streamClient: " + e.getMessage()); } } /** * 当接收到音频数据后,发送给录音对象的操作 * * @param data 音频数据 */ private void sendReceivedAudio(byte[] data) { if (onReceiveStreamData != null) { onReceiveStreamData.onReceiveAudio(data); } } /** * 当接收到音频数据时的处理 * * @param data 音频数据 */ private void playReceiveAudio(byte[] data) { if (audioTrack != null) {//如果音频播放已经打开,就写音频流数据 audioTrack.write(data, 0, data.length, AudioTrack.WRITE_NON_BLOCKING); } } /** * 断开与电台的连接 */ public synchronized void disConnect() { if (tcpClient.isConnect()) { tcpClient.disconnect(); } if (pingTimer != null) { pingTimer.cancel(); pingTimer.purge(); pingTimer = null; } } /** * 电台是否连接 * * @return 是否 */ public boolean isConnect() { return tcpClient.isConnect(); } /** * 关闭音频 */ public void closeAudio() { if (audioTrack != null) { audioTrack.stop(); audioTrack = null; } } /** * 当接收到数据时触发的事件,此处是TCP连接得到的数据 * * @param data 数据 */ private void onReceiveData(byte[] data) { if (data.length > 4) {//判断是不是老式的icom指令 if ((data[0] == (byte) 0xfe) && (data[1] == (byte) 0xfe) && ((data[2] == (byte) 0xe0) || data[3] == (byte) 0xe0)) { clearBufferData(); return; } } String s = new String(data); if (!s.contains("\n")) {//不包含换行符,说明命令行没有接受完。 buffer.append(s); } else {//说明已经有命令行了。可能不止一个哦。在此部分要触发OnReceiveLine String[] commands = s.split("\n"); if (commands.length > 0) {//把收到数据的第一行,追加到之前接收的命令数据上 buffer.append(commands[0]); } //先把缓存中的数据触发出来 doReceiveLineEvent(buffer.toString()); clearBufferData(); //从第二行开始触发,最后一行不触发,最后一行要看是不是换行结尾 for (int i = 1; i < commands.length - 1; i++) { doReceiveLineEvent(commands[i]); } if (commands.length > 1) {//当数据是多行的时候,最后一行的处理 if (s.endsWith("\n")) {//如果是以换行结尾,或者缓冲区没满(接收完全了),就触发事件 doReceiveLineEvent(commands[commands.length - 1]); } else {//如果不是以换行结尾,说明指令没有接收完全 buffer.append(commands[commands.length - 1]); } } } } /** * 当接收到数据行时,触发的事件。可以触发两种事件: * 1.行数据事件onReceiveLineListener; * 2.命令事件onCommandListener。 *

* //* @param line 数据行 */ private void doReceiveLineEvent(String line) { XieguResponse response = new XieguResponse(line); //更新一下句柄 switch (response.responseStyle) { case VERSION: this.version = response.head.substring(1); break; case HANDLE: this.handle = Integer.parseInt(response.head.substring(1), 16); break; case RESPONSE: if (XieguCommand.AUDIO == response.xieguCommand) {//是音频指令回复的信息 setAudioInfo(response.resultContent); } if (onCommandListener != null) { onCommandListener.onResponse(response); } break; case STATUS: if (response.resultCode == 0) {//说明是电台状态变化了 String status[] = response.resultContent.split(" "); for (int i = 0; i < status.length; i++) {//找出ptt的状体,设置ptt if (status[i].startsWith("ptt")) {//判断PTT String temp[] = status[i].split("="); isPttOn = temp[1].equalsIgnoreCase("on"); } if (status[i].startsWith("play_volume")) {//判断PTT String temp[] = status[i].split("="); float vol = Integer.parseInt(temp[1].trim())*1.0f/100f; GeneralVariables.volumePercent = vol; GeneralVariables.mutableVolumePercent.postValue(vol); } } } if (onStatusListener != null) { onStatusListener.onStatus(response); } break; } } /** * 获取电台的音频信息 * * @param result 返回信息 */ private void setAudioInfo(String result) { String[] keys = result.split(" "); for (int i = 0; i < keys.length; i++) { String[] val = keys[i].split("="); if (val[0].equalsIgnoreCase("period")) period = Integer.parseInt(val[1]) / 1000; if (val[0].equalsIgnoreCase("frames")) frames = Integer.parseInt(val[1]); } Log.d(TAG, String.format("set audio para:frames=%d,period=%d", frames, period)); } public synchronized void sendData(byte[] data) { tcpClient.sendByte(data); } /** * 制作命令,命令序号规则:后3位是命令的种类,序号除1000,是命令的真正序号 * * @param command 命令的种类 * @param cmdContent 命令的具体内容 */ @SuppressLint("DefaultLocale") public void sendCommand(XieguCommand command, String cmdContent) { if (tcpClient.isConnect()) { commandSeq++; xieguCommand = command; commandStr = String.format("C%05d%03d|%s\n", commandSeq, command.ordinal() , cmdContent); tcpClient.sendByte(commandStr.getBytes()); Log.d(TAG, "sendCommand: " + commandStr); } } public synchronized void commandPTTOnOff(boolean on) { if (on) { sendCommand(XieguCommand.PTT, "ptt on"); } else { sendCommand(XieguCommand.PTT, "ptt off"); } } /** * 发射的采样率为12000采样率,单声道,16位 * * @param data 音频 */ public void sendWaveData(float[] data) { Log.d(TAG, String.format("send wav data,len:%d....", data.length)); short[] temp = new short[data.length]; //传递过来的音频是LPCM,32 float,12000Hz //x6100的音频格式是LPCM 16 Int,12000Hz //要做一下浮点到16位int的转换 for (int i = 0; i < data.length; i++) { float x = data[i]; if (x > 1.0) x = 1.0f; else if (x < -1.0) x = -1.0f; temp[i] = (short) (x * 32767.0); } short[] payload = new short[frames]; VITA vita = new VITA(VitaPacketType.EXT_DATA_WITH_STREAM , VitaTSI.TSI_OTHER , VitaTSF.TSF_SAMPLE_COUNT , 0 , 0x84000001 , 0x584945475500A1L); vita.packetCount = 0; vita.integerTimestamp = 0; vita.fracTimeStamp = payload.length * 2L; try { int count = 0; int a = 0; while (count < temp.length) { long now = System.currentTimeMillis();//获取当前时间 Arrays.fill(payload, (short) 0);//数组清零 if (!isPttOn) break; if (data.length - count > frames) { System.arraycopy(temp, count, payload, 0, frames); count = count + frames; } else { System.arraycopy(temp, count, payload, 0, temp.length - count); count = temp.length; } streamClient.sendData(vita.audioShortDataToVita(vita.packetCount, payload), rig_ip, stream_port); while (isPttOn) { if (System.currentTimeMillis() - now >= period) {//64毫秒一个周期 break; } } a++; } } catch (UnknownHostException e) { throw new RuntimeException(e); } } /** * 清空缓存数据 */ private void clearBufferData() { buffer.setLength(0); } /** * 打开音频,流方式。当收到音频流的时候,播放数据 */ public void openAudio() { AudioAttributes attributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build(); AudioFormat myFormat = new AudioFormat.Builder().setSampleRate(12000) .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_MONO).build(); int mySession = 0; audioTrack = new AudioTrack(attributes, myFormat //, 12000 * 4, AudioTrack.MODE_STREAM , 768 * 2 * 4, AudioTrack.MODE_STREAM//x6100一个声音周期是64毫秒,共计768*2个字节 , mySession); audioTrack.play(); } public OnTcpConnectStatus getOnTcpConnectStatus() { return onTcpConnectStatus; } public void setOnTcpConnectStatus(OnTcpConnectStatus onTcpConnectStatus) { this.onTcpConnectStatus = onTcpConnectStatus; } public OnReceiveStreamData getOnReceiveStreamData() { return onReceiveStreamData; } public void setOnReceiveStreamData(OnReceiveStreamData onReceiveStreamData) { this.onReceiveStreamData = onReceiveStreamData; } public OnStatusListener getOnStatusListener() { return onStatusListener; } public void setOnStatusListener(OnStatusListener onStatusListener) { this.onStatusListener = onStatusListener; } public OnCommandListener getOnCommandListener() { return onCommandListener; } public void setOnCommandListener(OnCommandListener onCommandListener) { this.onCommandListener = onCommandListener; } public OnReceiveDataListener getOnReceiveDataListener() { return onReceiveDataListener; } public void setOnReceiveDataListener(OnReceiveDataListener onReceiveDataListener) { this.onReceiveDataListener = onReceiveDataListener; } //**************各种接口********************** /** * 当TCP接收到数据 */ public interface OnReceiveDataListener { void onDataReceive(byte[] data); } /** * 当TCP连接状态变化 */ public interface OnTcpConnectStatus { void onConnectSuccess(RadioTcpClient tcpClient); void onConnectFail(RadioTcpClient tcpClient); void onConnectionClosed(RadioTcpClient tcpClient); } /** * 当接收到流数据时的事件 */ public interface OnReceiveStreamData { void onReceiveAudio(byte[] data);//音频数据 void onReceiveIQ(byte[] data);//IQ数据 void onReceiveFFT(VITA vita);//频谱数据 void onReceiveMeter(X6100Meters meters);//仪表数据 void onReceiveUnKnow(byte[] data);//未知数据 } /** * 当接收到指令回复 */ public interface OnCommandListener { void onResponse(XieguResponse response); } public interface OnStatusListener { void onStatus(XieguResponse response); } //******************************************* /** * 电台TCP回复数据的基础类 */ public static class XieguResponse { private static final String TAG = "XieguResponse"; public XieguResponseStyle responseStyle; public String head;//消息头 public int resultCode;//消息代码 public String resultContent;//扩展消息,有的返回消息分为3段,取第3段消息 public String rawData;//原始数据 public int seq_number;//32位int,指令序号 public XieguCommand xieguCommand = XieguCommand.UNKNOW; public XieguResponse(String line) { rawData = line; char header; if (line.length() > 0) { header = line.toUpperCase().charAt(0); } else { header = 0; } switch (header) { case 'S': responseStyle = XieguResponseStyle.STATUS; getHeadAndContent(line, "\\|");//获取指令的头、值、内容 break; case 'R': responseStyle = RESPONSE; getHeadAndContent(line, "\\|"); try { seq_number = Integer.parseInt(head.substring(1));//解析指令序号 xieguCommand = XieguCommand.values()[seq_number % 1000]; } catch (NumberFormatException e) { e.printStackTrace(); Log.e(TAG, "XieguResponse parseInt seq_number exception: " + e.getMessage()); } break; case 'H': responseStyle = XieguResponseStyle.HANDLE; head = line; resultContent = line; Log.d(TAG, "XieguResponse: handle:" + line.substring(1)); break; case 'V': responseStyle = XieguResponseStyle.VERSION; head = line; resultContent = line; break; case 0: default: responseStyle = XieguResponseStyle.UNKNOW; break; } } /** * 分割消息的头和内容,并分别负值给head和content * * @param line 消息 * @param split 分隔符 */ private void getHeadAndContent(String line, String split) { String[] temp = line.split(split); if (temp.length > 1) { head = temp[0]; resultCode = Integer.parseInt(temp[1]); } else { head = ""; } if (temp.length > 2) { resultContent = temp[2]; } else { resultContent = ""; } } } }