From 44ba605a4e850efa757020da5fb4cf02bdf6e3ab Mon Sep 17 00:00:00 2001
From: wjc <1243177876@qq.com>
Date: 星期一, 08 九月 2025 10:55:18 +0800
Subject: [PATCH] 2025年09月08日10:55:15
---
app/src/main/java/com/hdl/photovoltaic/internet/TcpClient.java | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 328 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/com/hdl/photovoltaic/internet/TcpClient.java b/app/src/main/java/com/hdl/photovoltaic/internet/TcpClient.java
index 47e9e8b..2545b27 100644
--- a/app/src/main/java/com/hdl/photovoltaic/internet/TcpClient.java
+++ b/app/src/main/java/com/hdl/photovoltaic/internet/TcpClient.java
@@ -1,13 +1,38 @@
package com.hdl.photovoltaic.internet;
+import android.text.TextUtils;
import com.hdl.sdk.link.core.callback.HDLLinkCallBack;
+import com.hdl.sdk.link.core.callback.ModbusCallBack;
+import com.hdl.sdk.link.core.connect.HDLModBusConnect;
import com.hdl.sdk.link.gateway.HDLLinkLocalGateway;
+
+import java.nio.ByteBuffer;
+
/**
* 瀹㈡埛绔搷浣滈�昏緫
*/
public class TcpClient {
+
+ private static volatile TcpClient sTcpClient;
+
+ /**
+ * 鑾峰彇褰撳墠瀵硅薄
+ *
+ * @return HdlAccountLogic
+ */
+ public static synchronized TcpClient getInstance() {
+ if (sTcpClient == null) {
+ synchronized (TcpClient.class) {
+ if (sTcpClient == null) {
+ sTcpClient = new TcpClient();
+ }
+ }
+
+ }
+ return sTcpClient;
+ }
/**
* 鍙戦�佹暟鎹埌Link缃戝叧
@@ -18,9 +43,310 @@
* @param jObject 璐熻浇鏁版嵁<娌℃湁濉玭ull></>
* @param sendPath 鍙戦�佽矾寰�<绫诲悕+鏂规硶鍚�>class->methodName</>
*/
- public void sendDataToLinkGateway(String mac, boolean isEncrypt,
- String topic, Object jObject, String sendPath, HDLLinkCallBack callBack) {
+ public void sendDataToLinkGateway(String mac, boolean isEncrypt, String topic, Object jObject, String sendPath, HDLLinkCallBack callBack) {
HDLLinkLocalGateway.getInstance().sendDataToLinkGateway(mac, isEncrypt, topic, jObject, sendPath, callBack);
}
+
+ /**
+ * 鍙戦�佹暟鎹埌Link缃戝叧
+ *
+ * @param mac 缃戝叧mac
+ * @param topic 璇锋眰涓婚
+ * @param jObject 璐熻浇鏁版嵁<娌℃湁濉玭ull></>
+ * @param sendPath 鍙戦�佽矾寰�<绫诲悕+鏂规硶鍚�>class->methodName</>
+ */
+ public void sendDataToLinkGateway(String mac, String topic, Object jObject, String sendPath, HDLLinkCallBack callBack) {
+ HDLLinkLocalGateway.getInstance().sendDataToLinkGateway(mac, topic, jObject, sendPath, callBack);
+
+ }
+
+ /**
+ * 鍙戦�丮odBus鏁版嵁鍒扮綉鍏�
+ * 涓嬪彂涓婚搴曞眰榛樿
+ *
+ * @param mac 缃戝叧mac
+ * @param oidAddresses oid鐗╃悊淇℃伅閲岄潰Addresses鍦板潃
+ * @param functionCode 鍔熻兘鐮併��3=锛堣鍙栧涓瘎瀛樺櫒),6=锛堝啓鍏ュ崟涓瘎瀛樺櫒锛�,16=锛堝啓鍏ュ涓瘎瀛樺櫒锛夈��
+ * @param registerAddress 瀵勫瓨鍣ㄥ湴鍧�(鏍规嵁鏂囨。涓婂~鍗佽繘鍒跺��)
+ * @param contentData 鍐呭鏁版嵁锛堜笉鍚瘎瀛樺櫒鍦板潃锛夈�愭敞鎰忥細鍔熻兘鐮�=3鏃�,鏍规嵁鏂囨。涓婂~鏁版嵁瀛楄妭鏁帮紝渚嬪璇诲彇璁惧澶囨敞锛屽~20Byte銆�
+ */
+ public void sendModBusDataToLinkGateway(String mac, String oidAddresses, FunctionCode functionCode, int registerAddress, String contentData, ModbusCallBack modbusCallBack) {
+ String data = "";
+ switch (functionCode) {
+ case ReadMultipleRegisters: {
+ data = readModbusPassData(oidAddresses, registerAddress, functionCode, contentData);
+ }
+ break;
+ case WriteSingleRegister: {
+ data = writeSingleModbusPassData(oidAddresses, registerAddress, functionCode, contentData);
+ }
+ break;
+ case WriteMultipleRegisters: {
+ data = writeMultipleModbusPassData(oidAddresses, registerAddress, functionCode, contentData);
+ }
+ break;
+ }
+ HDLModBusConnect.getInstance().asyncSend(mac, getDataByteArray(data), modbusCallBack);
+ }
+
+ /**
+ * 鑾峰彇璇诲彇銆恗odbus鍗忚銆戞嫾鎺ラ�忎紶鏁版嵁鐨勫瓧绗︿覆
+ * 涓嬪彂涓婚锛�/user/${gw_id}/custom/native/${driver}/down;
+ * 閫嗗彉鍣ㄥ洖澶嶄富棰橈細/user/${gw_id}/custom/native/${driver}/down_reply;
+ * Modbus ECU鍗忚锛氫簨浠禝D(2涓猙yte)->鍗忚[鍥哄畾:0,0](2涓猙yte)->闀垮害(2byte)->鏍囪瘑绗oid鐨刟ddresses鍊糫(4涓猙yte)->鍔熻兘鐮�(1涓猙yte)->璐熻浇鏁版嵁(N涓猙yte);
+ * 闀垮害(2涓猙yte)=鏍囪瘑绗�(4涓猙yte)+鍔熻兘鐮�(1涓猙yte)+璐熻浇鏁版嵁(N涓猙yte);
+ * 璐熻浇鏁版嵁=瀵勫瓨鍣ㄥ湴鍧�(2涓猙yte)+瀵勫瓨鍣ㄩ暱搴�(2涓猙yte)+鍐呭闀垮害(1涓猙yte)+鍐呭鏁版嵁(鏁版嵁瀛楄妭鏁�->N涓猙yte)銆愭敞鎰�:鍗曚釜鍐欏叆瀵勫瓨鍣�-->鍘绘帀<瀵勫瓨鍣ㄩ暱搴�>鍜�<鍐呭闀垮害>銆�;
+ * 瀵勫瓨鍣ㄩ暱搴�=(鍐呭鏁版嵁/2);
+ * 鍐呭闀垮害=鍐呭鏁版嵁鐨勯暱搴�;
+ * 渚嬪瓙:new byte[]{1,54,0,0,0,9,0,0,200,26,3,1,54,0,1};
+ *
+ * @param oidAddresses oid鐗╃悊淇℃伅閲岄潰Addresses鍦板潃
+ * @param functionCode 鍔熻兘鐮併��3=锛堣鍙栧涓瘎瀛樺櫒)锛�,6=锛堝啓鍏ュ崟涓瘎瀛樺櫒锛�,16=锛堝啓鍏ュ涓瘎瀛樺櫒锛夈��
+ * @param registerAddress 瀵勫瓨鍣ㄥ湴鍧�(鏍规嵁鏂囨。涓婂崄杩涘埗鍊煎~)
+ * @param contentData 鍐呭鏁版嵁锛堜笉鍚瘎瀛樺櫒鍦板潃锛�
+ */
+ private String readModbusPassData(String oidAddresses, int registerAddress, FunctionCode functionCode, String contentData) {
+ String data = "";
+ try {
+ String eventID = to2ByteHexString(registerAddress);//浜嬩欢ID(2byte)
+ String agreement = "0000";//鍗忚锛�2byte锛�
+ String dataByteLength = "";//闀垮害锛圢 byte锛�
+ String oidAddresses_1 = oidAddresses;//鏍囪瘑绗︼紙4byte锛�
+ String functionCode_1 = to1ByteHexString(functionCode.value());//鍔熻兘鐮侊紙1byte锛�
+ String registerAddress_1 = to2ByteHexString(registerAddress);//瀵勫瓨鍣ㄥ湴鍧�锛�2byte锛�
+ String registerLength_1 = to2ByteHexString(Integer.parseInt(contentData) / 2);//瀵勫瓨鍣ㄩ暱搴︼紙2byte锛�
+ byte[] bytes = (oidAddresses_1 + functionCode_1 + registerAddress_1 + registerLength_1).getBytes();
+ dataByteLength = to2ByteHexString(bytes.length / 2);
+ data = eventID + agreement + dataByteLength + oidAddresses_1 + functionCode_1 + registerAddress_1 + registerLength_1;
+ return data;
+ } catch (Exception ignored) {
+ return data;
+ }
+ }
+
+
+ /**
+ * 鑾峰彇鍐欏叆鍗曚釜銆恗odbus鍗忚銆戞嫾鎺ラ�忎紶鏁版嵁鐨勫瓧绗︿覆
+ * 涓嬪彂涓婚锛�/user/${gw_id}/custom/native/${driver}/down;
+ * 閫嗗彉鍣ㄥ洖澶嶄富棰橈細/user/${gw_id}/custom/native/${driver}/down_reply;
+ * Modbus ECU鍗忚锛氫簨浠禝D(2涓猙yte)->鍗忚[鍥哄畾:0,0](2涓猙yte)->闀垮害(2byte)->鏍囪瘑绗oid鐨刟ddresses鍊糫(4涓猙yte)->鍔熻兘鐮�(1涓猙yte)->璐熻浇鏁版嵁(N涓猙yte);
+ * 闀垮害(2涓猙yte)=鏍囪瘑绗�(4涓猙yte)+鍔熻兘鐮�(1涓猙yte)+璐熻浇鏁版嵁(N涓猙yte);
+ * 璐熻浇鏁版嵁=瀵勫瓨鍣ㄥ湴鍧�(2涓猙yte)+瀵勫瓨鍣ㄩ暱搴�(2涓猙yte)+鍐呭闀垮害(1涓猙yte)+鍐呭鏁版嵁(鏁版嵁瀛楄妭鏁�->N涓猙yte)銆愭敞鎰�:鍗曚釜鍐欏叆瀵勫瓨鍣�-->鍘绘帀<瀵勫瓨鍣ㄩ暱搴�>鍜�<鍐呭闀垮害>銆�;
+ * 瀵勫瓨鍣ㄩ暱搴�=(鍐呭鏁版嵁/2);
+ * 鍐呭闀垮害=鍐呭鏁版嵁鐨勯暱搴�;
+ * 渚嬪瓙:new byte[]{199, 112, 0, 0, 0, 9, 0, 0, 0, 26, 6, 0, 31, 0, 1}; bin 00000000 00000001
+ *
+ * @param oidAddresses oid鐗╃悊淇℃伅閲岄潰Addresses鍦板潃
+ * @param functionCode 鍔熻兘鐮併��3=锛堣鍙栧涓瘎瀛樺櫒)锛�,6=锛堝啓鍏ュ崟涓瘎瀛樺櫒锛�,16=锛堝啓鍏ュ涓瘎瀛樺櫒锛夈��
+ * @param registerAddress 瀵勫瓨鍣ㄥ湴鍧�(鏍规嵁鏂囨。涓婂崄杩涘埗鍊煎~)
+ * @param contentData 鍐呭鏁版嵁锛堜笉鍚瘎瀛樺櫒鍦板潃锛�
+ */
+ private String writeSingleModbusPassData(String oidAddresses, int registerAddress, FunctionCode functionCode, String contentData) {
+ String data = "";
+ try {
+ String eventID = to2ByteHexString(registerAddress);//浜嬩欢ID(2byte)
+ String agreement = "0000";//鍗忚锛�2byte锛�
+ String dataByteLength = "";//闀垮害锛圢 byte锛�
+ String oidAddresses_1 = oidAddresses;//鏍囪瘑绗︼紙4byte锛�
+ String functionCode_1 = to1ByteHexString(functionCode.value());//鍔熻兘鐮侊紙1byte锛�
+ String registerAddress_1 = to2ByteHexString(registerAddress);//瀵勫瓨鍣ㄥ湴鍧�锛�2byte锛�
+ String contentData_1 = contentData;//鍐呭鏁版嵁锛圢 byte锛�
+ byte[] bytes = (oidAddresses_1 + functionCode_1 + registerAddress_1 + contentData_1).getBytes();
+ dataByteLength = to2ByteHexString(bytes.length / 2);
+ data = eventID + agreement + dataByteLength + oidAddresses_1 + functionCode_1 + registerAddress_1 + contentData_1;
+ return data;
+ } catch (Exception ignored) {
+ return data;
+ }
+ }
+
+ /**
+ * 鑾峰彇鍐欏叆澶氫釜銆恗odbus鍗忚銆戞嫾鎺ラ�忎紶鏁版嵁鐨勫瓧绗︿覆
+ * 涓嬪彂涓婚锛�/user/${gw_id}/custom/native/${driver}/down;
+ * 閫嗗彉鍣ㄥ洖澶嶄富棰橈細/user/${gw_id}/custom/native/${driver}/down_reply;
+ * Modbus ECU鍗忚锛氫簨浠禝D(2涓猙yte)->鍗忚[鍥哄畾:0,0](2涓猙yte)->闀垮害(2byte)->鏍囪瘑绗oid鐨刟ddresses鍊糫(4涓猙yte)->鍔熻兘鐮�(1涓猙yte)->璐熻浇鏁版嵁(N涓猙yte);
+ * 闀垮害(2涓猙yte)=鏍囪瘑绗�(4涓猙yte)+鍔熻兘鐮�(1涓猙yte)+璐熻浇鏁版嵁(N涓猙yte);
+ * 璐熻浇鏁版嵁=瀵勫瓨鍣ㄥ湴鍧�(2涓猙yte)+瀵勫瓨鍣ㄩ暱搴�(2涓猙yte)+鍐呭闀垮害(1涓猙yte)+鍐呭鏁版嵁(鏁版嵁瀛楄妭鏁�->N涓猙yte)銆愭敞鎰�:鍗曚釜鍐欏叆瀵勫瓨鍣�-->鍘绘帀<瀵勫瓨鍣ㄩ暱搴�>鍜�<鍐呭闀垮害>銆�;
+ * 瀵勫瓨鍣ㄩ暱搴�=(鍐呭鏁版嵁/2);
+ * 鍐呭闀垮害=鍐呭鏁版嵁鐨勯暱搴�;
+ * 渚嬪瓙:new byte[]{[0, 11, 0, 0, 0, 30, 0, 0, 0, 26, 16, 0, 11, 0, 10, 20, 49, 50, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32]};
+ *
+ * @param oidAddresses oid閲岄潰Addresses鐨勫��
+ * @param functionCode 鍔熻兘鐮併��3=锛堣鍙栧涓瘎瀛樺櫒)锛�,6=锛堝啓鍏ュ崟涓瘎瀛樺櫒锛�,16=锛堝啓鍏ュ涓瘎瀛樺櫒锛夈��
+ * @param registerAddress 瀵勫瓨鍣ㄥ湴鍧�(鏍规嵁鏂囨。涓婂崄杩涘埗鍊煎~)
+ * @param contentData 鍐呭鏁版嵁锛堜笉鍚瘎瀛樺櫒鍦板潃锛�
+ */
+ private String writeMultipleModbusPassData(String oidAddresses, int registerAddress, FunctionCode functionCode, String contentData) {
+
+ String data = "";
+ try {
+ String eventID = to2ByteHexString(registerAddress);//浜嬩欢ID(2byte)
+ String agreement = "0000";//鍗忚锛�2byte锛�
+ String dataByteLength = "";//闀垮害锛圢 byte锛�
+ String oidAddresses_1 = oidAddresses;//鏍囪瘑绗︼紙4byte锛�
+ String functionCode_1 = to1ByteHexString(functionCode.value());//鍔熻兘鐮侊紙1byte锛�
+ String registerAddress_1 = to2ByteHexString(registerAddress);//瀵勫瓨鍣ㄥ湴鍧�锛�2byte锛�
+ String registerLength_1 = to2ByteHexString(contentData.length() / 2);//瀵勫瓨鍣ㄩ暱搴︼紙2byte锛�
+ String contentLength_1 = to1ByteHexString(contentData.length());//鍐呭闀垮害锛�1byte锛�
+ String contentData_1 = contentData;//鍐呭鏁版嵁锛圢 byte锛�
+ byte[] bytes = (oidAddresses_1 + functionCode_1 + registerAddress_1 + registerLength_1 + contentLength_1 + contentData_1).getBytes();
+ dataByteLength = to2ByteHexString(bytes.length / 2);
+ data = eventID + agreement + dataByteLength + oidAddresses_1 + functionCode_1 + registerAddress_1 + registerLength_1 + contentLength_1 + contentData_1;
+ return data;
+ } catch (Exception ignored) {
+ return data;
+ }
+ }
+
+ /**
+ * 閫愪釜瑙f瀽涓や釜瀛楃锛屽皢鍏惰浆鎹负瀛楄妭
+ *
+ * @param hexString 16杩涘埗鐨勫瓧绗︿覆
+ * @return 杩斿洖鏁扮粍
+ */
+ private byte[] getDataByteArray(String hexString) {
+ try {
+ if (TextUtils.isEmpty(hexString)) {
+ return new byte[]{};
+ }
+ //鍘婚櫎瀛楃涓插墠鍚庣殑绌烘牸
+ hexString = hexString.trim();
+ // 纭繚瀛楃涓茬殑闀垮害鏄伓鏁�
+ if (hexString.length() % 2 != 0) {
+ //鏃犳晥鐨勫崄鍏繘鍒跺瓧绗︿覆
+ return new byte[]{};
+ }
+ // 璁$畻瀛楄妭鏁扮粍鐨勯暱搴�
+ int byteArrayLength = hexString.length() / 2;
+ byte[] byteArray = new byte[byteArrayLength];
+ //閫愪釜瑙f瀽涓や釜瀛楃锛屽皢鍏惰浆鎹负瀛楄妭
+ for (int i = 0; i < byteArrayLength; i++) {
+ byteArray[i] = (byte) Integer.parseInt(hexString.substring(i * 2, i * 2 + 2), 16);
+ }
+ return byteArray;
+ } catch (Exception ignored) {
+ return new byte[]{};
+ }
+ }
+
+ /**
+ * 鑾峰彇鍗佸叚杩涘埗瀛楃涓�(涓嶅涓や綅鍓嶉潰琛�0)
+ *
+ * @param value 瀵勫瓨鍣ㄥ湴鍧�(鍗佽繘鍒�)
+ * @return (2byte)鍗佸叚杩涘埗瀛楃涓�
+ */
+ private String to2ByteHexString(int value) {
+ String high = "";
+ String low = "";
+ if (value > 255) {
+ high = to1ByteHexString(value / 256);
+
+ low = to1ByteHexString(value % 256);
+ } else {
+ high = "00";
+ low = to1ByteHexString(value);
+ }
+ return high + low;
+ }
+
+ /**
+ * 鑾峰彇鍗佸叚杩涘埗瀛楃涓�(涓嶅涓や綅鍓嶉潰琛�0)
+ *
+ * @param value 鍗佽繘鍒�
+ * @return (1byte)鍗佸叚杩涘埗瀛楃涓�
+ */
+ private String to1ByteHexString(int value) {
+ try {
+ String hexString = Integer.toHexString(value);
+ if (hexString.length() == 1) {
+ return "0" + hexString;
+ }
+ return hexString;
+ } catch (Exception e) {
+ return "00";
+ }
+ }
+
+
+ /**
+ * 鑾峰彇鍗佸叚杩涘埗瀛楃涓�(涓嶅涓や綅鍓嶉潰琛�0)
+ *
+ * @param dataBytes 鏁扮粍
+ * @return -(n byte)鍗佸叚杩涘埗瀛楃涓�
+ */
+ private String toNByteHexString(byte[] dataBytes) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (byte dataByte : dataBytes) {
+ String dataB = Integer.toHexString(dataByte & 0xFF);
+ if (dataB.length() == 1) {
+ dataB = "0" + dataB;
+ }
+ stringBuilder.append(dataB);
+ }
+ return stringBuilder.toString();
+ }
+
+ /**
+ * 鑾峰彇鍗佸叚杩涘埗瀛楃涓�(涓嶅涓や綅鍓嶉潰琛�0)
+ *
+ * @param value 瀵勫瓨鍣ㄥ湴鍧�(鍗佽繘鍒�)
+ * @return (2byte)鍗佸叚杩涘埗瀛楃涓�
+ */
+ private String getByteHexString(int value) {
+ String high = "";
+ String low = "";
+ if (value > 255) {
+ high = to1ByteHexString(value / 256);
+
+ low = to1ByteHexString(value % 256);
+ } else {
+ high = "00";
+ low = to1ByteHexString(value);
+ }
+ return high + low;
+ }
+
+ /**
+ * bytes鏁扮粍杞琁nt鍊�
+ *
+ * @param bytes 鏁版嵁
+ */
+ public int toByteArrayInt(byte[] bytes) {
+ int ans = 0;
+ for (byte b : bytes) {
+ ans <<= 8;
+ ans |= (b & 0xff);
+ }
+ return ans;
+ }
+
+
+ /**
+ * 鍔熻兘鐮�
+ */
+ public enum FunctionCode {
+
+ /**
+ * 璇诲彇鍗曚釜鎴栬�呭涓瘎瀛樺櫒
+ */
+ ReadMultipleRegisters(3),
+ /**
+ * 鍐欏叆鍗曚釜瀵勫瓨鍣�
+ */
+ WriteSingleRegister(6),
+ /**
+ * 鍐欏叆澶氫釜瀵勫瓨鍣�
+ */
+ WriteMultipleRegisters(16);
+ private int mValue;
+
+ FunctionCode(int value) {
+ this.mValue = value;
+ }
+
+ public int value() {
+ return this.mValue;
+ }
+ }
}
--
Gitblit v1.8.0