From 134209ad70f82051da3ce63471df0cc8f778e57d Mon Sep 17 00:00:00 2001 From: panlili2024 <14743743+panlili2024@user.noreply.gitee.com> Date: 星期三, 05 三月 2025 14:30:19 +0800 Subject: [PATCH] 增加source屏扫码绑定住宅接口 --- HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java | 375 +++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 303 insertions(+), 72 deletions(-) diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java index 4cc8a8f..38438d9 100644 --- a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java +++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java @@ -1,17 +1,21 @@ package com.hdl.sdk.connect.protocol; -import com.hdl.sdk.common.utils.LogUtils; -import com.hdl.sdk.connect.config.HDLLinkConfig; +import android.os.Build; +import android.text.TextUtils; + +import androidx.annotation.RequiresApi; + import com.hdl.sdk.common.event.EventDispatcher; -import com.hdl.sdk.common.utils.ByteUtils; +import com.hdl.sdk.common.utils.LogUtils; import com.hdl.sdk.connect.bean.LinkResponse; +import com.hdl.sdk.connect.config.HDLLinkConfig; import com.hdl.sdk.connect.utils.AesUtil; -import com.hdl.sdk.connect.utils.ProtocolParse; +import com.hdl.sdk.connect.utils.ByteBufferUtils; import com.hdl.sdk.socket.codec.ByteToMessageDecoder; -import java.util.ArrayList; -import java.util.List; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; /** * Created by Tong on 2021/9/22. @@ -19,82 +23,309 @@ */ public class LinkMessageDecoder extends ByteToMessageDecoder<LinkResponse> { - private final List<Byte> bytes; + private static final String TAG = LinkMessageDecoder.class.getName(); + //instance + private volatile static LinkMessageDecoder instance; - private final byte[] head = "Topic:".getBytes(); - private final byte[] body = "\r\n\r\n".getBytes(); - - public LinkMessageDecoder() { - this.bytes = new ArrayList<>(); + //getInstance + public static synchronized LinkMessageDecoder getInstance() { + if (instance == null) { + synchronized (LinkMessageDecoder.class) { + if (instance == null) { + instance = new LinkMessageDecoder(); + } + } + } + return instance; } - @Override - protected LinkResponse decoder(Object msg) throws Exception { - LinkResponse response = new LinkResponse(); - if (msg instanceof byte[]) { - //瑙f瀽娴� - byte[] data = (byte[]) msg; - bytes.addAll(ByteUtils.toByteList(data)); + /** + * 鎺ユ敹鏁版嵁缂撳啿鍖� + */ + private final ByteBuffer byteBuffer; - byte[] byteArray = ByteUtils.toByteArray(bytes); - int headIndex = ByteUtils.getByteIndexOf(byteArray, head); - if (headIndex > 0) { - //绉诲姩鍒癶ead 寮�濮嬩綅缃� - bytes.subList(0, headIndex).clear(); - byteArray = ByteUtils.toByteArray(bytes); - } + private final byte[] head = "Topic:".getBytes(); - int bodyIndex = ByteUtils.getByteIndexOf(byteArray, body); - if (bodyIndex < 0) { - //澶撮儴鏈幏鍙栧畬鎴� - return null; - } - int bodyStartIndex = bodyIndex + body.length; + public LinkMessageDecoder() { + byteBuffer = ByteBuffer.allocate(1024 * 200);//100K + } - //瑙f瀽澶撮儴 - ProtocolParse parse = new ProtocolParse(byteArray); - response.setTopic(parse.getTopic()); - - int bodyLength = parse.getLength(); - if (bodyLength > 0) { - if (byteArray.length >= bodyLength + bodyStartIndex) { - byte[] body = ByteUtils.getRangeBytes(bytes, bodyStartIndex, bodyStartIndex + bodyLength); - - if (HDLLinkConfig.getInstance().ifNeedEncrypt(response.getTopic())) { - //闇�瑕佽В瀵� - byte[] bodyBytes = AesUtil.aesDecrypt(body, HDLLinkConfig.getInstance().getLocalSecret()); -// byte[] bodyBytes = AESUtils.decryptAES(body,AuthenticateConfig.getInstance().getLocalSecret()); - if (bodyBytes != null) { - response.setData(new String(bodyBytes, "utf-8")); -// LogUtils.i("TAG", "瑙e瘑 涓婚锛�"+response.getTopic()+ " body: "+response.getData()); - } else { - //瑙e瘑澶辫触锛岃繑鍥炲師鏁版嵁 - response.setData(new String(body, "utf-8")); - LogUtils.e( "瑙e瘑澶辫触"); - } - - } else { - response.setData(new String(body, "utf-8")); - } - - if (byteArray.length >= bodyLength + bodyStartIndex) { - //淇濆瓨浣欑暀 - byte[] remaining = ByteUtils.getRangeBytes(bytes, bodyStartIndex + bodyLength, byteArray.length); - bytes.clear(); - for (byte b : remaining) { - bytes.add(b); - } - } - //瑙f瀽瀹屾垚,topic鍙戦�佷竴娆� - EventDispatcher.getInstance().post(response.getTopic(), response); - return response; + /// <summary> + /// 鑾峰彇鍐呭闀垮害 + /// </summary> + /// <param name="topMsgs"></param> + /// <returns></returns> + int getLenght(String[] topMsgs) { + try { + for (int i = 0; i < topMsgs.length; i++) { + String topMsg = topMsgs[i].trim(); + if (topMsg.startsWith("Length:")) { + return Integer.parseInt(topMsg.replace("Length:", "").trim()); } - } else if (bodyLength == 0) { - //body涓虹┖ - return response; } + } catch (Exception e) { + LogUtils.e("寮傚父鏁版嵁锛�" + topMsgs[0] + "\r\n" + topMsgs[1]); + return -1; + } + //鎵句笉鍒伴暱搴� + return -1; + } + /// <summary> + /// 鑾峰彇涓婚 + /// </summary> + /// <param name="topMsgs"></param> + /// <returns></returns> + private String getTopic(String[] topMsgs) { + for (int i = 0; i < topMsgs.length; i++) { + String topMsg = topMsgs[i].trim(); + if (topMsg.startsWith("Topic:")) { + return topMsg.replace("Topic:", ""); + } + } + //鎵句笉鍒颁富棰� + return null; + } + + /** + * 鑾峰彇鏁版嵁鐨勫紑濮嬩綅缃� + * + * @return 鏁版嵁浣嶇殑寮�濮嬬储寮� + */ + int getBodyIndex() { + byte r = (byte) '\r'; + byte n = (byte) '\n'; + for (int i = 0; i < byteBuffer.position(); i++) { + //鎵惧嚭鏁版嵁鍐呭鍓嶉潰鐨勪袱涓崲琛� + if (3 <= i && byteBuffer.get(i - 3) == r && byteBuffer.get(i - 2) == n && byteBuffer.get(i - 1) == r && byteBuffer.get(i) == n) { + //鍓╀綑鐨勬暟鎹� + return i + 1; + } + } + return -1; + } + + /** + * 鑾峰彇澶撮儴鏁版嵁 + * + * @return + */ + String getHeader() { + int bodyIndex = getBodyIndex(); + if (bodyIndex < 0) { + //娌℃湁鎵惧埌澶撮儴鏁版嵁 + return null; + } else { + byte bodyBytes[] = ByteBufferUtils.copyBytes(byteBuffer, bodyIndex); + return new String(bodyBytes); + } + } + + /** + * 鑾峰彇鏁版嵁鍐呭 + * + * @param lenght + * @return + */ + byte[] getBody(int index, int lenght) { + //鏄惁宸茬粡鑾峰彇瀹屾暣鎵�鏈夌殑鏁版嵁 + byte[] bodyBytes = new byte[lenght]; + if (index < 0 || byteBuffer.position() < index + lenght) { + //褰撳墠鏁版嵁杩樻病鏈夋帴鏀跺畬鎴� + return null; + } + + for (int i = 0; i < bodyBytes.length; i++) { + bodyBytes[i] = byteBuffer.get(index + i); + } + return bodyBytes; + } + + + /** + * 杩欒竟澶勭悊浜嗙紦瀛樻暟鎹矘鍖呯殑鎯呭喌锛屾瘡娆¤姹傞兘闇�瑕佸惂褰撳墠瀹屾暣鐨勬枃浠堕櫎鍘� 浠ヤ究浜庝笅娆$殑杩斿洖 + * tempList鐢ㄤ簬瀛樺偍澶氫綑鐨勬暟鎹� + * contentList鐢ㄤ簬鏈鏁版嵁鐨勫瓨鍌紙鍙戦�佺粰璁㈤槄鐨勬暟鎹級 + */ + byte[] geBody() { + int len = 3 + 4 + 4 + ((byteBuffer.get(7) & 0xFF) * 256 * 256 * 256) + ((byteBuffer.get(8) & 0xFF) * 256 * 256) + ((byteBuffer.get(9) * 256) & 0xFF) + (byteBuffer.get(10) & 0xFf); + byte[] bodyBytes = new byte[len]; + for (int i = 0; i < len; i++) { + bodyBytes[i] = byteBuffer.get(i); + } + + int endIndex = byteBuffer.position(); + byteBuffer.clear(); + for (int i = len; i < endIndex; i++) { + byteBuffer.put(byteBuffer.get(i)); + } + return bodyBytes; + } + + /** + * 绉婚櫎鍙兘瀛樺湪鐨勬棤鏁堟暟鎹� + */ + void removeInVoidBytes() { + int index = 0; + boolean isMatch = false; + for (; index < byteBuffer.position() - head.length; index++) { + isMatch = true; + for (int j = 0, k = 0; j < head.length; j++, k++) { + if (head[j] != byteBuffer.get(index + k)) { + isMatch = false; + break; + } + } + if (isMatch) { + break; + } + } + + if (0 < index && isMatch) { + int endIndex = byteBuffer.position(); + byteBuffer.clear(); + for (int i = index; i < endIndex; i++) { + byteBuffer.put(byteBuffer.get(i)); + } + } + } + + /** + * 绉婚櫎鍒版寚瀹氫綅缃墠闈㈢殑鏁版嵁 + * + * @param position 鎸囧畾浣嶇疆 + */ + void remove(int position) { + int endIndex = byteBuffer.position(); + byteBuffer.clear(); + for (int i = position; i < endIndex; i++) { + byteBuffer.put(byteBuffer.get(i)); + } + } + + + int bytes2int(byte[] bytes) { + int result = 0; + if (bytes.length == 2) { + int c = (bytes[0] & 0xff) << 8; + int d = (bytes[1] & 0xff); + result = c | d; + } else if (bytes.length == 4) { + return bytes[3] & 0xFF | // + (bytes[2] & 0xFF) << 8 | // + (bytes[1] & 0xFF) << 16 | // + (bytes[0] & 0xFF) << 24; // + } + return result; + } + + public String byte2hex(byte[] bytes) { + StringBuilder sb = new StringBuilder(); + String tmp = null; + for (byte b : bytes) { + //灏嗘瘡涓瓧鑺備笌0xFF杩涜涓庤繍绠楋紝鐒跺悗杞寲涓�10杩涘埗锛岀劧鍚庡�熷姪浜嶪nteger鍐嶈浆鍖栦负16杩涘埗 + tmp = Integer.toHexString(0xFF & b); + if (tmp.length() == 1) { + tmp = "0" + tmp; + } + sb.append(tmp + " "); + } + return sb.toString(); + } + + + @RequiresApi(api = Build.VERSION_CODES.O) + @Override + protected synchronized LinkResponse decoder(Object msg, String ipaddress) throws Exception { + if (msg == null || !(msg instanceof byte[])) { + return null; + } + + byte[] bytes = (byte[]) msg; + try { + byteBuffer.put(bytes); + } catch (Exception e) { + LogUtils.e("鎺ユ敹鍒版暟鎹紓甯�:\r\n" + e.getMessage()); + byteBuffer.flip(); + byteBuffer.clear(); + } + + try { + //濡傛灉澶氭潯鍛戒护鎵撳寘鍦ㄤ竴鏉℃暟鎹腑锛岄兘闇�瑕佸鐞嗗畬 + while (true) { + removeInVoidBytes();//绉婚櫎鍙兘瀛樺湪鐨勬棤鏁堟暟鎹� + + //澶撮儴鏁版嵁 + String header = getHeader(); + + if (header == null) { + break; + } + String[] topMsgs = header.split("\r\n"); + + String topic = getTopic(topMsgs); + int lenght = getLenght(topMsgs); + if (topic == null || lenght <= 0) { + //鑾峰彇涓嶅埌涓婚鎴栬�呭ご閮ㄦ暟鎹繕娌℃湁鎺ユ敹瀹屾垚 + break; + } + + int bodyIndex = getBodyIndex(); + //鏄惁宸茬粡鑾峰彇瀹屾暣鎵�鏈夌殑鏁版嵁 + byte[] body = getBody(bodyIndex, lenght); + + if (body == null) { + //褰撳墠鏁版嵁杩樻病鏈夋帴鏀跺畬鎴� + break; + } + + remove(bodyIndex + lenght); + + if (topic.contains("heartbeat_reply")) { +// if (packet.getSocket() != null) { +// packet.getSocket().setSoTimeout(10 * 1000); +// } + continue; + } + + LinkResponse response = new LinkResponse(); + response.setSource_ipAddress(ipaddress); + response.setTopic(topic); + + if (encrypt(body)) { + //闇�瑕佽В瀵� + if (!TextUtils.isEmpty(HDLLinkConfig.getInstance().getLocalSecret())) { + byte[] bodyBytes = AesUtil.aesDecrypt(body, HDLLinkConfig.getInstance().getLocalSecret()); + if (bodyBytes != null) { + response.setData(new String(bodyBytes, StandardCharsets.UTF_8)); + } else { + LogUtils.e("瑙e瘑澶辫触\r\n" + topic); + response.setData(new String(body, "utf-8")); + continue; + } + } + } else { + response.setData(new String(body, "utf-8")); + } + + LogUtils.i("鏈湴鎺ユ敹鍒版暟鎹�:\r\n" + response.getTopic() + "\r\n" + response.getData() + "\r\n" + response.getData().length()); + + //瑙f瀽瀹屾垚,topic鍙戦�佷竴娆� + EventDispatcher.getInstance().post(response.getTopic(), response); + } + } catch (Exception ee) { + LogUtils.e("澶勭悊鎺ユ敹鐨勬暟鎹紓甯�:\r\n" + ee.getMessage()); } return null; } + + //鏄惁鍔犲瘑 + private boolean encrypt(byte[] bytes) { + if (bytes[0] == '{' && bytes[bytes.length - 1] == '}' || (bytes[0] == '[' && bytes[bytes.length - 1] == ']')) { + return false; + } + return true; + } } + + -- Gitblit v1.8.0