package com.hdl.photovoltaic.internet;
|
|
|
import android.text.TextUtils;
|
import android.util.Log;
|
|
import com.hdl.log.utils.PointUtil;
|
import com.hdl.photovoltaic.other.HdlAccountLogic;
|
import com.hdl.sdk.link.common.exception.HDLLinkException;
|
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.lang.reflect.Type;
|
import java.util.Arrays;
|
|
/**
|
* 客户端操作逻辑
|
*/
|
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网关
|
*
|
* @param mac 网关mac
|
* @param isEncrypt 是否加密
|
* @param topic 请求主题
|
* @param jObject 负载数据<没有填null></>
|
* @param sendPath 发送路径<类名+方法名>class->methodName</>
|
*/
|
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 负载数据<没有填null></>
|
* @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);
|
|
}
|
|
/**
|
* 发送ModBus数据到网关
|
* 下发主题底层默认
|
*
|
* @param mac 网关mac
|
* @param oidAddresses oid里面Addresses地址
|
* @param functionCode 功能码【3=(读取多个寄存器)),6=(写入单个寄存器),16=(写入多个寄存器)】
|
* @param registerAddress 寄存器地址
|
* @param contentData 内容数据(不含寄存器地址)【注意:功能码=3时,填数值;实际读多少byte就填多少,例如填"20"】
|
*/
|
public void SendModBusDataToLinkGateway(String mac, String oidAddresses, int functionCode, int registerAddress, String contentData, ModbusCallBack modbusCallBack) {
|
String s = "";
|
switch (functionCode) {
|
case 3: {
|
s = getReadModbusPassData(oidAddresses, registerAddress, functionCode, contentData);
|
}
|
break;
|
case 6: {
|
s = getWriteSingleModbusPassData(oidAddresses, registerAddress, functionCode, contentData);
|
}
|
break;
|
case 16: {
|
s = getWriteMultipleModbusPassData(oidAddresses, registerAddress, functionCode, contentData);
|
}
|
break;
|
}
|
HDLModBusConnect.getInstance().Send(mac, s.getBytes(), modbusCallBack);
|
}
|
|
/**
|
* 获取读取【modbus协议】拼接透传数据的字符串
|
* 下发主题:/user/${gw_id}/custom/native/${driver}/down;
|
* 逆变器回复主题:/user/${gw_id}/custom/native/${driver}/down_reply;
|
* Modbus ECU协议:事件ID(2个byte)->协议[固定:0,0](2个byte)->长度(2byte)->标识符[oid的addresses值](4个byte)->功能码(1个byte)->负载数据(N个byte);
|
* 长度(2个byte)=标识符(4个byte)+功能码(1个byte)+负载数据(N个byte);
|
* 负载数据=寄存器地址(2个byte)+寄存器长度(2个byte)+内容长度(1个byte)+内容数据(N个byte)【注意:单个写入寄存器-->去掉<寄存器长度>和<内容长度>】;
|
* 寄存器长度=(内容数据/2);
|
* 例子:new byte[]{00,01,00,00,00,0x09,00,00,00,01,03,00,00,00,01};
|
*
|
* @param oidAddresses oid里面Addresses的值
|
* @param functionCode 功能码【3=(读取多个寄存器)),6=(写入单个寄存器),16=(写入多个寄存器)】
|
* @param registerAddress 寄存器地址
|
* @param contentData 内容数据(不含寄存器地址)
|
*/
|
public String getReadModbusPassData(String oidAddresses, int functionCode, int registerAddress, String contentData) {
|
String data = "";
|
try {
|
String eventID = to2ByteHexString(registerAddress);//事件ID(2byte)
|
String agreement = "0000";//协议(2byte)
|
String dataByteLength = "";//长度(N byte)
|
String oidAddresses_1 = oidAddresses;//标识符(4byte)
|
String functionCode_1 = to1ByteHexString(functionCode);//功能码(=1byte)
|
String registerAddress_1 = to2ByteHexString(registerAddress);//寄存器地址(2byte)
|
String registerLength_1 = to2ByteHexString(Integer.getInteger(contentData) / 2);//寄存器长度(2byte)
|
byte[] bytes = (oidAddresses_1 + functionCode_1 + registerAddress_1 + registerLength_1).getBytes();
|
dataByteLength = to1ByteHexString(bytes.length / 2);
|
data = eventID + agreement + dataByteLength + oidAddresses_1 + functionCode_1 + registerAddress_1 + registerLength_1;
|
return data;
|
} catch (Exception ignored) {
|
return data;
|
}
|
}
|
|
|
/**
|
* 获取写入单个【modbus协议】拼接透传数据的字符串
|
* 下发主题:/user/${gw_id}/custom/native/${driver}/down;
|
* 逆变器回复主题:/user/${gw_id}/custom/native/${driver}/down_reply;
|
* Modbus ECU协议:事件ID(2个byte)->协议[固定:0,0](2个byte)->长度(2byte)->标识符[oid的addresses值](4个byte)->功能码(1个byte)->负载数据(N个byte);
|
* 长度(2个byte)=标识符(4个byte)+功能码(1个byte)+负载数据(N个byte);
|
* 负载数据=寄存器地址(2个byte)+寄存器长度(2个byte)+内容长度(1个byte)+内容数据(N个byte)【注意:单个写入寄存器-->去掉<寄存器长度>和<内容长度>】;
|
* 寄存器长度=(内容数据/2);
|
* 例子:new byte[]{[0, 11, 0, 0, 0, 30, 0, 0, 0, 26, 6, 0, 11, 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 内容数据(不含寄存器地址)
|
*/
|
public String getWriteSingleModbusPassData(String oidAddresses, int functionCode, int registerAddress, String contentData) {
|
String data = "";
|
try {
|
String eventID = to2ByteHexString(registerAddress);//事件ID(2byte)
|
String agreement = "0000";//协议(2byte)
|
String dataByteLength = "";//长度(N byte)
|
String oidAddresses_1 = oidAddresses;//标识符(4byte)
|
String functionCode_1 = to1ByteHexString(functionCode);//功能码(=1byte)
|
String registerAddress_1 = to2ByteHexString(registerAddress);//寄存器地址(2byte)
|
String contentData_1 = contentData;//内容数据(N byte)
|
byte[] bytes = (oidAddresses_1 + functionCode_1 + registerAddress_1 + contentData_1).getBytes();
|
dataByteLength = to1ByteHexString(bytes.length / 2);
|
data = eventID + agreement + dataByteLength + oidAddresses_1 + functionCode_1 + registerAddress_1 + contentData_1;
|
return data;
|
} catch (Exception ignored) {
|
return data;
|
}
|
}
|
|
/**
|
* 获取写入多个【modbus协议】拼接透传数据的字符串
|
* 下发主题:/user/${gw_id}/custom/native/${driver}/down;
|
* 逆变器回复主题:/user/${gw_id}/custom/native/${driver}/down_reply;
|
* Modbus ECU协议:事件ID(2个byte)->协议[固定:0,0](2个byte)->长度(2byte)->标识符[oid的addresses值](4个byte)->功能码(1个byte)->负载数据(N个byte);
|
* 长度(2个byte)=标识符(4个byte)+功能码(1个byte)+负载数据(N个byte);
|
* 负载数据=寄存器地址(2个byte)+寄存器长度(2个byte)+内容长度(1个byte)+内容数据(N个byte)【注意:单个写入寄存器-->去掉<寄存器长度>和<内容长度>】;
|
* 寄存器长度=(内容数据/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 内容数据(不含寄存器地址)
|
*/
|
public String getWriteMultipleModbusPassData(String oidAddresses, int functionCode, int registerAddress, String contentData) {
|
|
String data = "";
|
try {
|
String eventID = to2ByteHexString(registerAddress);//事件ID(2byte)
|
String agreement = "0000";//协议(2byte)
|
String dataByteLength = "";//长度(N byte)
|
String oidAddresses_1 = oidAddresses;//标识符(4byte)
|
String functionCode_1 = to1ByteHexString(functionCode);//功能码(=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;//内容数据(N byte)
|
byte[] bytes = (oidAddresses_1 + functionCode_1 + registerAddress_1 + registerLength_1 + contentLength_1 + contentData_1).getBytes();
|
dataByteLength = to1ByteHexString(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;
|
}
|
}
|
|
|
/**
|
* 获取十六进制字符串(不够两位前面补0)
|
*
|
* @param value 寄存器地址(十进制)
|
* @return (2byte)十六进制字符串
|
*/
|
public 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)十六进制字符串
|
*/
|
public 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)十六进制字符串
|
*/
|
public 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;
|
}
|
|
|
}
|