第一次提交
This commit is contained in:
@ -0,0 +1,117 @@
|
||||
package com.fastbee.modbus.codec;
|
||||
|
||||
import com.fastbee.common.ProtocolColl;
|
||||
import com.fastbee.common.constant.FastBeeConstant;
|
||||
import com.fastbee.common.core.mq.DeviceReport;
|
||||
import com.fastbee.common.core.mq.message.DeviceData;
|
||||
import com.fastbee.common.core.protocol.Message;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.iot.model.ProductCode;
|
||||
import com.fastbee.iot.service.IProductService;
|
||||
import com.fastbee.protocol.base.protocol.IProtocol;
|
||||
import com.fastbee.protocol.service.IProtocolManagerService;
|
||||
import com.fastbee.base.codec.MessageDecoder;
|
||||
import com.fastbee.base.codec.MessageEncoder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 消息编解码适配器
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MessageAdapter implements MessageDecoder, MessageEncoder{
|
||||
|
||||
|
||||
@Autowired
|
||||
private IProtocolManagerService managerService;
|
||||
@Autowired
|
||||
private IProductService productService;
|
||||
|
||||
/**
|
||||
* modbus消息解码
|
||||
*
|
||||
* @param buf 原数据
|
||||
* @param clientId 客户端id
|
||||
* @return 解析后bean
|
||||
*/
|
||||
@Override
|
||||
public DeviceReport decode(ByteBuf buf, String clientId) {
|
||||
IProtocol protocol = null;
|
||||
Long productId = null;
|
||||
String devNum = new String(ByteBufUtil.getBytes(buf));
|
||||
String dump = ByteBufUtil.hexDump(buf);
|
||||
log.info("=>上报hex数据:{}", dump);
|
||||
|
||||
//这里兼容一下TCP整包发送的数据(整包==设备编号,数据一起发送)
|
||||
if (clientId == null){
|
||||
if (StringUtils.isNotEmpty(dump)) {
|
||||
assert dump != null;
|
||||
if (dump.startsWith("68") && dump.endsWith("16")) {
|
||||
protocol = managerService.getProtocolByProtocolCode(FastBeeConstant.PROTOCOL.FlowMeter);
|
||||
}else if (dump.startsWith("7e")&& dump.endsWith("7e")){
|
||||
protocol = managerService.getProtocolByProtocolCode(FastBeeConstant.PROTOCOL.ModbusRtu);
|
||||
}else if (devNum.startsWith("{") && devNum.endsWith("}")){
|
||||
protocol = managerService.getProtocolByProtocolCode(FastBeeConstant.PROTOCOL.SGZ);
|
||||
}else if (devNum.startsWith("[") && devNum.endsWith("]")){
|
||||
protocol = managerService.getProtocolByProtocolCode(FastBeeConstant.PROTOCOL.JsonArray);
|
||||
}else if (dump.startsWith("fedc")){
|
||||
protocol = managerService.getProtocolByProtocolCode(FastBeeConstant.PROTOCOL.CH);
|
||||
}
|
||||
}
|
||||
|
||||
}else {
|
||||
ProtocolColl coll = selectedProtocol(clientId);
|
||||
protocol = coll.getProtocol();
|
||||
productId = coll.getProductId();
|
||||
}
|
||||
DeviceData deviceData = DeviceData.builder()
|
||||
.buf(buf)
|
||||
.productId(productId)
|
||||
.serialNumber(clientId)
|
||||
.data(ByteBufUtil.getBytes(buf))
|
||||
.build();
|
||||
return protocol.decode(deviceData, clientId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* modbus消息编码
|
||||
*
|
||||
* @param message modbusbean
|
||||
* @return 编码指令
|
||||
*/
|
||||
@Override
|
||||
public ByteBuf encode(Message message, String clientId) {
|
||||
String serialNumber = StringUtils.isNotEmpty(clientId) ? clientId : message.getClientId();
|
||||
ProtocolColl protocol = selectedProtocol(serialNumber);
|
||||
IProtocol instance = protocol.getProtocol();
|
||||
DeviceData data = DeviceData.builder().body(message).build();
|
||||
byte[] out = instance.encodeCallBack(data);
|
||||
log.info("应答设备,clientId=[{}],指令=[{}]", serialNumber, ByteBufUtil.hexDump(out));
|
||||
return Unpooled.wrappedBuffer(out);
|
||||
}
|
||||
|
||||
private ProtocolColl selectedProtocol(String serialNumber) {
|
||||
ProtocolColl protocolColl = new ProtocolColl();
|
||||
try {
|
||||
ProductCode protocol = productService.getProtocolBySerialNumber(serialNumber);
|
||||
if (protocol == null || StringUtils.isEmpty(protocol.getProtocolCode())) {
|
||||
protocol.setProtocolCode(FastBeeConstant.PROTOCOL.ModbusRtu);
|
||||
}
|
||||
IProtocol code = managerService.getProtocolByProtocolCode(protocol.getProtocolCode());
|
||||
protocolColl.setProtocol(code);
|
||||
protocolColl.setProductId(protocol.getProductId());
|
||||
return protocolColl;
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package com.fastbee.modbus.codec;
|
||||
|
||||
import com.fastbee.common.core.mq.message.DeviceData;
|
||||
import com.fastbee.common.core.protocol.modbus.ModbusCode;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.gateway.CRC16Utils;
|
||||
import com.fastbee.modbus.pak.TcpDtu;
|
||||
import com.fastbee.modbus.model.ModbusRtu;
|
||||
import com.fastbee.protocol.WModelManager;
|
||||
import com.fastbee.protocol.base.model.ActiveModel;
|
||||
import com.fastbee.protocol.util.ArrayMap;
|
||||
import com.fastbee.protocol.util.ExplainUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
|
||||
/**
|
||||
* modbus-rtu协议解码器
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@NoArgsConstructor
|
||||
public class ModbusDecoder {
|
||||
|
||||
@Resource
|
||||
private WModelManager modelManager;
|
||||
private ArrayMap<ActiveModel> headerSchemaMap;
|
||||
|
||||
public ModbusDecoder(String... basePackages) {
|
||||
this.modelManager = new WModelManager(basePackages);
|
||||
this.headerSchemaMap = this.modelManager.getActiveMap(ModbusRtu.class);
|
||||
}
|
||||
|
||||
public ModbusRtu decode(DeviceData deviceData) {
|
||||
try {
|
||||
this.build();
|
||||
ByteBuf in = deviceData.getBuf();
|
||||
int start = in.getUnsignedByte(0);
|
||||
int messageId = in.getUnsignedByte(1);
|
||||
int currentMessageId = messageId;
|
||||
if (!(start == TcpDtu.起始位 && (messageId == TcpDtu.注册报文 || messageId == TcpDtu.心跳包))) {
|
||||
//03解析
|
||||
currentMessageId = 0;
|
||||
if (deviceData.getCode() == ModbusCode.Write06 || messageId == ModbusCode.Write06.getCode() ||
|
||||
deviceData.getCode() == ModbusCode.Write05 || messageId == ModbusCode.Write05.getCode()) {
|
||||
//设备回复06解析
|
||||
currentMessageId = 2;
|
||||
} else if (deviceData.getCode() == ModbusCode.Read01 || messageId == ModbusCode.Read01.getCode() ||
|
||||
deviceData.getCode() == ModbusCode.Read02 || messageId == ModbusCode.Read02.getCode()) {
|
||||
// 01、02解析
|
||||
currentMessageId = 4;
|
||||
}
|
||||
in = verify(in);
|
||||
}
|
||||
messageId = currentMessageId;
|
||||
ActiveModel<ModbusRtu> activeModel = headerSchemaMap.get(messageId);
|
||||
ModbusRtu message = new ModbusRtu();
|
||||
message.setPayload(in);
|
||||
activeModel.mergeFrom(in, message, null);
|
||||
log.info("=>解析:[{}]", message);
|
||||
return message;
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private ByteBuf verify(ByteBuf in) {
|
||||
ByteBuf copy = in.duplicate();
|
||||
byte[] source = new byte[in.writerIndex()];
|
||||
copy.readBytes(source);
|
||||
byte[] checkBytes = {source[source.length - 2], source[source.length - 1]};
|
||||
byte[] sourceCheck = ArrayUtils.subarray(source, 0, source.length - 2);
|
||||
String crc = CRC16Utils.getCRC(sourceCheck);
|
||||
if (!crc.equalsIgnoreCase(ByteBufUtil.hexDump(checkBytes))) {
|
||||
log.warn("=>CRC校验异常,报文={}", ByteBufUtil.hexDump(source));
|
||||
throw new ServiceException("CRC校验异常");
|
||||
}
|
||||
return Unpooled.wrappedBuffer(sourceCheck);
|
||||
}
|
||||
|
||||
private void build() {
|
||||
if (this.headerSchemaMap == null) {
|
||||
this.headerSchemaMap = this.modelManager.getActiveMap(ModbusRtu.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.fastbee.modbus.codec;
|
||||
|
||||
import com.fastbee.modbus.model.ModbusRtu;
|
||||
import com.fastbee.protocol.WModelManager;
|
||||
import com.fastbee.protocol.base.model.ActiveModel;
|
||||
import com.fastbee.common.core.protocol.modbus.ModbusCode;
|
||||
import com.fastbee.protocol.util.ArrayMap;
|
||||
import com.fastbee.protocol.util.ExplainUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* modbus-rtu协议编码器
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@NoArgsConstructor
|
||||
public class ModbusEncoder {
|
||||
|
||||
private static final ByteBufAllocator ALLOC = PooledByteBufAllocator.DEFAULT;
|
||||
|
||||
@Autowired
|
||||
private WModelManager modelManager;
|
||||
|
||||
private ArrayMap<ActiveModel> headerSchemaMap;
|
||||
|
||||
public ModbusEncoder(String... basePackages) {
|
||||
this.modelManager = new WModelManager(basePackages);
|
||||
this.headerSchemaMap = this.modelManager.getActiveMap(ModbusRtu.class);
|
||||
}
|
||||
|
||||
public ByteBuf encode(ModbusRtu message) {
|
||||
this.build();
|
||||
/*下发读指令*/
|
||||
int version = 1;
|
||||
/*下发写指令*/
|
||||
if (message.getCode() == ModbusCode.Write06.getCode()
|
||||
|| message.getCode() == ModbusCode.Write05.getCode()) {
|
||||
version = 2;
|
||||
}else if (message.getCode() == ModbusCode.Write10.getCode()){
|
||||
version = 16;
|
||||
}else if (message.getCode() == ModbusCode.Write0F.getCode()){
|
||||
version = 15;
|
||||
}
|
||||
ByteBuf buf = ALLOC.buffer(6);
|
||||
ActiveModel activeModel = headerSchemaMap.get(version);
|
||||
activeModel.writeTo(buf, message, null);
|
||||
return buf;
|
||||
}
|
||||
|
||||
private void build() {
|
||||
if (this.headerSchemaMap == null) {
|
||||
this.headerSchemaMap = this.modelManager.getActiveMap(ModbusRtu.class);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,421 @@
|
||||
package com.fastbee.modbus.codec;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fastbee.common.annotation.SysProtocol;
|
||||
import com.fastbee.common.constant.FastBeeConstant;
|
||||
import com.fastbee.common.core.mq.DeviceReport;
|
||||
import com.fastbee.common.core.mq.MQSendMessageBo;
|
||||
import com.fastbee.common.core.mq.SubDeviceBo;
|
||||
import com.fastbee.common.core.mq.message.DeviceData;
|
||||
import com.fastbee.common.core.mq.message.FunctionCallBackBo;
|
||||
import com.fastbee.common.core.protocol.modbus.ModbusCode;
|
||||
import com.fastbee.common.core.redis.RedisCache;
|
||||
import com.fastbee.common.core.redis.RedisKeyBuilder;
|
||||
import com.fastbee.common.core.thingsModel.ThingsModelSimpleItem;
|
||||
import com.fastbee.common.enums.FunctionReplyStatus;
|
||||
import com.fastbee.common.enums.ModbusDataType;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.CaculateUtils;
|
||||
import com.fastbee.common.utils.DateUtils;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.common.utils.gateway.CRC16Utils;
|
||||
import com.fastbee.common.utils.modbus.BitUtils;
|
||||
import com.fastbee.common.utils.modbus.ModbusUtils;
|
||||
import com.fastbee.common.utils.modbus.Mparams;
|
||||
import com.fastbee.iot.cache.IModbusConfigCache;
|
||||
import com.fastbee.iot.domain.ModbusConfig;
|
||||
import com.fastbee.iot.model.ThingsModelItem.Datatype;
|
||||
import com.fastbee.iot.model.ThingsModels.ThingsModelValueItem;
|
||||
import com.fastbee.iot.model.gateWay.SubDeviceListVO;
|
||||
import com.fastbee.iot.service.IDeviceService;
|
||||
import com.fastbee.iot.service.ISubGatewayService;
|
||||
import com.fastbee.iot.service.IThingsModelService;
|
||||
import com.fastbee.modbus.model.ModbusRtu;
|
||||
import com.fastbee.protocol.base.protocol.IProtocol;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author bill
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@SysProtocol(name = "ModbusRtu协议", protocolCode = FastBeeConstant.PROTOCOL.ModbusRtu, description = "系统内置ModbusRtu解析协议")
|
||||
public class ModbusProtocol implements IProtocol {
|
||||
|
||||
|
||||
@Resource
|
||||
private ModbusDecoder messageDecoder;
|
||||
@Resource
|
||||
private ModbusEncoder messageEncoder;
|
||||
@Resource
|
||||
private RedisCache redisCache;
|
||||
@Resource
|
||||
private IModbusConfigCache modbusConfigCache;
|
||||
@Resource
|
||||
private ISubGatewayService subGatewayService;
|
||||
|
||||
@Override
|
||||
public DeviceReport decode(DeviceData deviceData, String clientId) {
|
||||
try {
|
||||
DeviceReport report = new DeviceReport();
|
||||
report.setProductId(deviceData.getProductId());
|
||||
report.setSerialNumber(deviceData.getSerialNumber());
|
||||
//原始报文字符串
|
||||
String hexDump = ByteBufUtil.hexDump(deviceData.getBuf());
|
||||
ModbusRtu message = messageDecoder.decode(deviceData);
|
||||
int slaveId = message.getSlaveId();
|
||||
//获取功能码
|
||||
int code = message.getCode();
|
||||
if (message.getmId() != 0) {
|
||||
report.setClientId(message.getMac());
|
||||
report.setMessageId(String.valueOf(message.getmId()));
|
||||
report.setSources(hexDump);
|
||||
return report;
|
||||
}
|
||||
matchSubDev(report, deviceData.getSerialNumber(), slaveId);
|
||||
String serialNumber = report.getSerialNumber();
|
||||
Long productId = report.getProductId();
|
||||
ModbusCode modbusCode = ModbusCode.getInstance(code);
|
||||
List<ThingsModelSimpleItem> values = new ArrayList<>();
|
||||
switch (modbusCode) {
|
||||
case Read01:
|
||||
case Read02:
|
||||
//起始地址
|
||||
String address0102 = getCacheModbusAddress(deviceData.getSerialNumber(),slaveId,code);
|
||||
//读线圈或读离散型寄存器处理
|
||||
handleRead0102(productId, message, address0102, values);
|
||||
break;
|
||||
case Read03:
|
||||
case Read04:
|
||||
//起始地址
|
||||
String address0304 = getCacheModbusAddress(deviceData.getSerialNumber(),slaveId,code);
|
||||
//读输入、保持寄存器
|
||||
handleRead0304(productId, message, address0304, values, hexDump);
|
||||
break;
|
||||
case Write06:
|
||||
case Write05:
|
||||
//如果返回06编码,说明是设备回复,更新对应寄存器的值,并发送通知前端
|
||||
report.setClientId(serialNumber);
|
||||
report.setSerialNumber(serialNumber);
|
||||
report.setProductId(productId);
|
||||
report.setIsReply(true);
|
||||
report.setSources(hexDump);
|
||||
report.setProtocolCode(FastBeeConstant.PROTOCOL.ModbusRtu);
|
||||
report.setStatus(FunctionReplyStatus.SUCCESS);
|
||||
this.handleMsgReply(message,report,modbusCode);
|
||||
return report;
|
||||
}
|
||||
|
||||
report.setSerialNumber(serialNumber);
|
||||
report.setClientId(serialNumber);
|
||||
report.setProductId(productId);
|
||||
report.setThingsModelSimpleItem(values);
|
||||
report.setSources(hexDump);
|
||||
return report;
|
||||
} catch (Exception e) {
|
||||
log.error("=>解码异常[{}]", e, e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读线圈或读离散型寄存器处理
|
||||
*
|
||||
* @param productId 产品id
|
||||
* @param message 数据集合
|
||||
* @param address 起始地址
|
||||
* @param simpleItemList 返回的物模型值
|
||||
*/
|
||||
private void handleRead0102(Long productId, ModbusRtu message, String address, List<ThingsModelSimpleItem> simpleItemList) {
|
||||
//字节数
|
||||
int bitCount = message.getBitCount();
|
||||
//字节数据集合
|
||||
byte[] byteDatas = message.getBitData();
|
||||
String hexDump = ByteBufUtil.hexDump(byteDatas);
|
||||
//处理多个的情况
|
||||
Map<Integer, List<ModbusConfig>> modbusConfigMap = modbusConfigCache.getModbusConfigCacheByProductId(productId);
|
||||
if (CollectionUtils.isEmpty(modbusConfigMap)) {
|
||||
log.warn("寄存器地址:{},不存在", address);
|
||||
return;
|
||||
}
|
||||
List<ModbusConfig> modbusConfigList = new ArrayList<>();
|
||||
for (Map.Entry<Integer, List<ModbusConfig>> entry : modbusConfigMap.entrySet()) {
|
||||
modbusConfigList.addAll(entry.getValue());
|
||||
}
|
||||
Map<Integer, List<ModbusConfig>> listMap = modbusConfigList.stream().filter(config -> config.getType() == 1).collect(Collectors.groupingBy(ModbusConfig::getAddress));
|
||||
//分割值
|
||||
List<String> values = StringUtils.splitEvenly(hexDump, 2);
|
||||
int ioAd = Integer.parseInt(address);
|
||||
//匹配寄存器,一个字节有8个位需要处理
|
||||
for (int i = 0; i < bitCount * 8; i++) {
|
||||
List<ModbusConfig> configList = listMap.get(ioAd);
|
||||
if (!CollectionUtils.isEmpty(configList) && configList.size() == 1) {
|
||||
ModbusConfig modbusConfig = configList.get(0);
|
||||
String hex = values.get(i / 8);
|
||||
int result = BitUtils.deterHex(hex, i % 8);
|
||||
ThingsModelSimpleItem simpleItem = new ThingsModelSimpleItem();
|
||||
simpleItem.setId(modbusConfig.getIdentifier());
|
||||
simpleItem.setValue(result + "");
|
||||
simpleItem.setTs(DateUtils.getNowDate());
|
||||
simpleItemList.add(simpleItem);
|
||||
}
|
||||
ioAd += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理读保持寄存器/输入寄存器
|
||||
*
|
||||
* @param productId 产品id
|
||||
* @param message 数据
|
||||
* @param address 起始地址
|
||||
* @param simpleItemList 返回的物模型值
|
||||
* @param sourceStr 原始报文字符串
|
||||
*/
|
||||
private void handleRead0304(Long productId, ModbusRtu message, String address, List<ThingsModelSimpleItem> simpleItemList, String sourceStr) {
|
||||
short[] data = message.getData();
|
||||
int length = data.length;
|
||||
if (length == 1) {
|
||||
//单个寄存器上报情况处理
|
||||
List<ModbusConfig> modbusConfig = modbusConfigCache.getSingleModbusConfig(productId, address);
|
||||
if (CollectionUtils.isEmpty(modbusConfig)) {
|
||||
log.warn("寄存器地址:{},不存在", address);
|
||||
return;
|
||||
}
|
||||
Map<Integer, List<ModbusConfig>> listMap = modbusConfig.stream().collect(Collectors.groupingBy(ModbusConfig::getType));
|
||||
//处理IO类型
|
||||
List<ModbusConfig> IOConfigList = listMap.get(1);
|
||||
if (!CollectionUtils.isEmpty(IOConfigList)) {
|
||||
if (IOConfigList.size() > 1) {
|
||||
//03按位运行情况,读寄存器需要将16进制转换为2进制,按位取值
|
||||
// 如1-4个继电器开关情况,寄存器值是0x0007 从右到左,1-4 对应 on-on-on-off
|
||||
for (ModbusConfig config : IOConfigList) {
|
||||
int result = BitUtils.deter(data[0], config.getBitOrder());
|
||||
ThingsModelSimpleItem simpleItem = new ThingsModelSimpleItem();
|
||||
simpleItem.setId(config.getIdentifier());
|
||||
simpleItem.setValue(result + "");
|
||||
simpleItem.setTs(DateUtils.getNowDate());
|
||||
simpleItemList.add(simpleItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
//单个寄存器值
|
||||
List<ModbusConfig> dataConfigList = listMap.get(2);
|
||||
if (!CollectionUtils.isEmpty(dataConfigList)) {
|
||||
ModbusConfig config = dataConfigList.get(0);
|
||||
//普通取值,应该只有一个数据,将identity与address替换
|
||||
ThingsModelSimpleItem simpleItem = new ThingsModelSimpleItem();
|
||||
simpleItem.setId(config.getIdentifier());
|
||||
simpleItem.setValue(CaculateUtils.handleToUnSign16(data[0] + "", config.getDataType()));
|
||||
simpleItem.setTs(DateUtils.getNowDate());
|
||||
simpleItemList.add(simpleItem);
|
||||
}
|
||||
} else {
|
||||
//原数据字符串
|
||||
String dataHex = sourceStr.substring(6, sourceStr.length() - 4);
|
||||
//处理多个情况
|
||||
Map<Integer, List<ModbusConfig>> modbusConfigMap = modbusConfigCache.getModbusConfigCacheByProductId(productId);
|
||||
if (CollectionUtils.isEmpty(modbusConfigMap)) {
|
||||
log.warn("寄存器数据不存在");
|
||||
return;
|
||||
}
|
||||
List<ModbusConfig> modbusConfigList = new ArrayList<>();
|
||||
for (Map.Entry<Integer, List<ModbusConfig>> entry : modbusConfigMap.entrySet()) {
|
||||
modbusConfigList.addAll(entry.getValue());
|
||||
}
|
||||
Map<Integer, ModbusConfig> configMap = modbusConfigList.stream().filter(config -> config.getType() == 2).collect(Collectors.toMap(ModbusConfig::getAddress, Function.identity()));
|
||||
int registerAd = Integer.parseInt(address);
|
||||
for (int i = 0; i < length; i++) {
|
||||
ModbusConfig modbusConfig = configMap.get(registerAd);
|
||||
if (Objects.isNull(modbusConfig)) {
|
||||
//处理可能是 03按位运行情况,判断是否有寄存器,而且寄存器对应物模型多个
|
||||
List<ModbusConfig> dataToIoList = modbusConfigMap.get(registerAd);
|
||||
if (!CollectionUtils.isEmpty(dataToIoList) && dataToIoList.size() > 1) {
|
||||
for (ModbusConfig config : dataToIoList) {
|
||||
int result = BitUtils.deter(data[i], config.getBitOrder());
|
||||
ThingsModelSimpleItem simpleItem = new ThingsModelSimpleItem();
|
||||
simpleItem.setId(config.getIdentifier());
|
||||
simpleItem.setValue(result + "");
|
||||
simpleItem.setTs(DateUtils.getNowDate());
|
||||
simpleItemList.add(simpleItem);
|
||||
}
|
||||
} else {
|
||||
log.warn("寄存器地址:{},不存在", registerAd);
|
||||
}
|
||||
registerAd += 1;
|
||||
continue;
|
||||
}
|
||||
//个数
|
||||
Integer quantity = modbusConfig.getQuantity();
|
||||
ThingsModelSimpleItem simpleItem = new ThingsModelSimpleItem();
|
||||
simpleItem.setId(modbusConfig.getIdentifier());
|
||||
simpleItem.setTs(DateUtils.getNowDate());
|
||||
if (quantity == 1) {
|
||||
//将identity与address替换
|
||||
simpleItem.setValue(CaculateUtils.handleToUnSign16(data[i] + "", modbusConfig.getDataType()));
|
||||
simpleItemList.add(simpleItem);
|
||||
dataHex = dataHex.substring(4);
|
||||
} else if (quantity == 2) {
|
||||
//这里做数据处理
|
||||
String handleHex = dataHex.substring(0, 8);
|
||||
String value = CaculateUtils.parseValue(modbusConfig.getDataType(), handleHex);
|
||||
simpleItem.setValue(value);
|
||||
simpleItemList.add(simpleItem);
|
||||
//处理dataHex
|
||||
dataHex = dataHex.substring(8);
|
||||
//处理quantity ==2的情况,跳过一次循环
|
||||
i += 1;
|
||||
}
|
||||
//寄存器地址+1
|
||||
registerAd += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理下发指令设备回复消息,按照modbus协议约定会返回一样的指令
|
||||
* @param message 解析后数据
|
||||
*/
|
||||
private void handleMsgReply(ModbusRtu message,DeviceReport report,ModbusCode code){
|
||||
//单个寄存器上报情况处理
|
||||
String address = message.getAddress() + "";
|
||||
List<ModbusConfig> modbusConfig = modbusConfigCache.getSingleModbusConfig(report.getProductId(), address);
|
||||
if (CollectionUtils.isEmpty(modbusConfig)) {
|
||||
log.warn("寄存器地址:{},不存在", address);
|
||||
return;
|
||||
}
|
||||
Map<Integer, List<ModbusConfig>> listMap = modbusConfig.stream().collect(Collectors.groupingBy(ModbusConfig::getType));
|
||||
// 1是IO类型,2是寄存器类型
|
||||
int type = code.equals(ModbusCode.Write05) ? 1 : 2;
|
||||
List<ModbusConfig> modbusConfigList = listMap.get(type);
|
||||
ModbusConfig config = modbusConfigList.get(0);
|
||||
List<ThingsModelSimpleItem> values = new ArrayList<>();
|
||||
ThingsModelSimpleItem simpleItem = new ThingsModelSimpleItem();
|
||||
simpleItem.setId(config.getIdentifier());
|
||||
simpleItem.setTs(DateUtils.getNowDate());
|
||||
int data = message.getWriteData();
|
||||
if (type == 1){
|
||||
//对于IO类型的数据做一个数据转换 0x0000 是关 0xff00 是开 对应值 1
|
||||
if (data == 0xff00){
|
||||
data = 1;
|
||||
}
|
||||
}
|
||||
simpleItem.setValue(data +"");
|
||||
values.add(simpleItem);
|
||||
report.setThingsModelSimpleItem(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配子设备编号
|
||||
*/
|
||||
private void matchSubDev(DeviceReport report, String serialNumber, Integer slaveId) {
|
||||
List<SubDeviceBo> subDeviceList = subGatewayService.getSubDeviceListByGw(serialNumber);
|
||||
if (!CollectionUtils.isEmpty(subDeviceList)) {
|
||||
for (SubDeviceBo vo : subDeviceList) {
|
||||
if (vo.getSlaveId().equals(slaveId)) {
|
||||
report.setSubDeviceBo(vo);
|
||||
report.setSerialNumber(vo.getSubDeviceNo());
|
||||
report.setProductId(vo.getSubProductId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionCallBackBo encode(MQSendMessageBo message) {
|
||||
FunctionCallBackBo callBack = new FunctionCallBackBo();
|
||||
ModbusRtu rtu = new ModbusRtu();
|
||||
String thingsModel = message.getThingsModel();
|
||||
ThingsModelValueItem item = JSONObject.parseObject(thingsModel, ThingsModelValueItem.class);
|
||||
ModbusConfig config = item.getConfig();
|
||||
switch (config.getModbusCode()) {
|
||||
case Read01:
|
||||
case Read02:
|
||||
case Read03:
|
||||
case Read04:
|
||||
this.read03(config, rtu);
|
||||
break;
|
||||
case Write05:
|
||||
write05(config,message.getValue(), rtu);
|
||||
break;
|
||||
case Write06:
|
||||
write06(config, message.getValue(), rtu);
|
||||
break;
|
||||
}
|
||||
ByteBuf out = messageEncoder.encode(rtu);
|
||||
byte[] data = new byte[out.writerIndex()];
|
||||
out.readBytes(data);
|
||||
ReferenceCountUtil.release(out);
|
||||
byte[] result = CRC16Utils.AddCRC(data);
|
||||
callBack.setMessage(result);
|
||||
callBack.setSources(ByteBufUtil.hexDump(result));
|
||||
return callBack;
|
||||
}
|
||||
|
||||
/**
|
||||
* read03指令
|
||||
*/
|
||||
private void read03(ModbusConfig modbusConfig, ModbusRtu rtu) {
|
||||
rtu.setSlaveId(modbusConfig.getSlave());
|
||||
rtu.setCount(modbusConfig.getQuantity());
|
||||
rtu.setAddress(modbusConfig.getAddress());
|
||||
rtu.setCode(modbusConfig.getModbusCode().getCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* writ05/06指令配置
|
||||
*/
|
||||
private void write05(ModbusConfig modbusConfig, String value, ModbusRtu rtu) {
|
||||
int data;
|
||||
if (value.contains("0x")) {
|
||||
data = Integer.parseInt(value.substring(2), 16);
|
||||
} else {
|
||||
data = Integer.parseInt(value);
|
||||
}
|
||||
rtu.setWriteData(data == 1 ? 0xFF00 : 0x0000);
|
||||
rtu.setAddress(modbusConfig.getAddress());
|
||||
rtu.setCode(modbusConfig.getModbusCode().getCode());
|
||||
rtu.setSlaveId(modbusConfig.getSlave());
|
||||
}
|
||||
|
||||
/**
|
||||
* writ05/06指令配置
|
||||
*/
|
||||
private void write06(ModbusConfig modbusConfig, String value, ModbusRtu rtu) {
|
||||
rtu.setWriteData(Integer.parseInt(value));
|
||||
rtu.setAddress(modbusConfig.getAddress());
|
||||
rtu.setCode(modbusConfig.getModbusCode().getCode());
|
||||
rtu.setSlaveId(modbusConfig.getSlave());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取modbus地址
|
||||
*/
|
||||
private String getCacheModbusAddress(String serialNumber,int salveId,int code) {
|
||||
String key = RedisKeyBuilder.buildModbusRuntimeCacheKey(serialNumber);
|
||||
Set<String> commandSet = redisCache.zRange(key, 0, -1);
|
||||
if (commandSet.size() == 0) {
|
||||
throw new ServiceException("No cache modbus address found");
|
||||
}
|
||||
for (String command : commandSet) {
|
||||
Mparams params = ModbusUtils.getModbusParams(command);
|
||||
redisCache.zRem(key, command);
|
||||
if (params.getSlaveId() == salveId && params.getCode() == code){
|
||||
return params.getAddress()+"";
|
||||
}
|
||||
}
|
||||
throw new ServiceException("No cache modbus address found");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
package com.fastbee.modbus.model;
|
||||
|
||||
import com.fastbee.protocol.base.annotation.Column;
|
||||
import com.fastbee.common.core.protocol.modbus.ModbusCode;
|
||||
import com.fastbee.protocol.util.ToStringBuilder;
|
||||
import com.fastbee.common.core.protocol.Message;
|
||||
import com.fastbee.base.session.Session;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* modbus采集方式一: 云端轮询方式,报文为标准ModbusRtu
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class ModbusRtu extends Message {
|
||||
/**
|
||||
* version来决定数据
|
||||
* <p>
|
||||
* 0: 读寄存器03/04(批量)上报 {@link ModbusCode}
|
||||
* 例如: |从机地址|功能码|返回字节个数|寄存器40005数据|寄存器40006数据|CRC校验|
|
||||
* |01|03|04|00 00|00 00|21 33|
|
||||
* <p>
|
||||
* 1: 批量读寄存器 {@link ModbusCode}
|
||||
* 例如: |从机地址|功能码|寄存器起始地址|读取寄存器个数|CRC校验|
|
||||
* |01|03|00 04|00 02|85 ca|
|
||||
* <p>
|
||||
* 2: 单个写保持寄存器 0x06 {@link ModbusCode}
|
||||
* 写单个线圈 0x05 {@link ModbusCode}
|
||||
* 例如:
|
||||
* |0x01|06|00 01|00 17|98 04|
|
||||
* |0x01|05|00 01|00 1|98 04|
|
||||
* <p>
|
||||
* 4: 解析读线圈 01/02
|
||||
* <p>
|
||||
* 15: 写多个线圈
|
||||
* <p>
|
||||
* 16: 写多个寄存器
|
||||
* <p>
|
||||
*/
|
||||
@Column(length = 1, version = {0x80, 0x81}, desc = "起始地址")
|
||||
protected int start;
|
||||
@Column(length = 1, version = {0x80, 0x81}, desc = "标识位,实例设备是0x80")
|
||||
protected int mId;
|
||||
@Column(length = 6, version = 0x80, desc = "MAC地址,6个字节")
|
||||
protected String mac;
|
||||
@Column(length = 1, version = {0x80, 0x81}, desc = "结尾,如:7E")
|
||||
protected int end;
|
||||
|
||||
|
||||
|
||||
@Column(length = 1, version = {0, 1, 2,4,15,16}, desc = "从机地址")
|
||||
protected int slaveId;
|
||||
@Column(length = 1, version = {0,1,2,4,15,16}, desc = "功能码")
|
||||
protected int code;
|
||||
@Column(length = 2, desc = "寄存器地址", version = {1,2})
|
||||
protected int address;
|
||||
@Column(length = 2, desc = "寄存器个数", version = {1,15,16})
|
||||
protected int count;
|
||||
@Column(totalUnit = 1, desc = "上报数据", version = 0)
|
||||
protected short[] data;
|
||||
@Column(length = 2, desc = "下发数据", version = 2)
|
||||
protected int writeData;
|
||||
@Column(length = 2 ,version = {15,16} , desc = "寄存器数量")
|
||||
protected int byteCount;
|
||||
@Column(length = 1 ,version = {4,15,16} , desc = "字节数")
|
||||
protected int bitCount;
|
||||
@Column(totalUnit = 0,desc = "多个寄存器",version = 16)
|
||||
protected short[] tenWriteData;
|
||||
@Column(totalUnit = 0,desc = "多个线圈",version = {4,15})
|
||||
protected byte[] bitData;
|
||||
/*原始的bit字符串*/
|
||||
protected String bitString;
|
||||
|
||||
protected transient Session session;
|
||||
|
||||
protected transient ByteBuf payload;
|
||||
|
||||
protected transient String hex;
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public int getmId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public void setmId(int mId) {
|
||||
this.mId = mId;
|
||||
}
|
||||
|
||||
public String getMac() {
|
||||
return mac;
|
||||
}
|
||||
|
||||
public void setMac(String mac) {
|
||||
this.mac = mac;
|
||||
}
|
||||
|
||||
public int getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(int end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public int getSlaveId() {
|
||||
return slaveId;
|
||||
}
|
||||
|
||||
public void setSlaveId(int slaveId) {
|
||||
this.slaveId = slaveId;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(int address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public short[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(short[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getWriteData() {
|
||||
return writeData;
|
||||
}
|
||||
|
||||
public void setWriteData(int writeData) {
|
||||
this.writeData = writeData;
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return byteCount;
|
||||
}
|
||||
|
||||
public void setByteCount(int byteCount) {
|
||||
this.byteCount = byteCount;
|
||||
}
|
||||
|
||||
public int getBitCount() {
|
||||
return bitCount;
|
||||
}
|
||||
|
||||
public void setBitCount(int bitCount) {
|
||||
this.bitCount = bitCount;
|
||||
}
|
||||
|
||||
public short[] getTenWriteData() {
|
||||
return tenWriteData;
|
||||
}
|
||||
|
||||
public void setTenWriteData(short[] tenWriteData) {
|
||||
this.tenWriteData = tenWriteData;
|
||||
}
|
||||
|
||||
public byte[] getBitData() {
|
||||
return bitData;
|
||||
}
|
||||
|
||||
public void setBitData(byte[] bitData) {
|
||||
this.bitData = bitData;
|
||||
}
|
||||
|
||||
public String getBitString() {
|
||||
return bitString;
|
||||
}
|
||||
|
||||
public void setBitString(String bitString) {
|
||||
this.bitString = bitString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
public String getHex() {
|
||||
return hex;
|
||||
}
|
||||
|
||||
public void setHex(String hex) {
|
||||
this.hex = hex;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public void setSession(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public void setPayload(ByteBuf payload) {
|
||||
this.hex = ByteBufUtil.hexDump(payload);
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
protected StringBuilder toStringHead() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
String des = ModbusCode.getDes(this.code);
|
||||
sb.append(des).append(": ");
|
||||
sb.append(";[从机地址]: ").append(slaveId);
|
||||
sb.append(";[功能码]: ").append(code);
|
||||
sb.append(";[返回数据个数]: ").append(data == null ? 0 : data.length);
|
||||
sb.append(";[上报数据]: ").append(Arrays.toString(data));
|
||||
sb.append(";[读取寄存器个数]: ").append(count);
|
||||
sb.append(";[寄存器地址]: ").append(address);
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.toString(toStringHead(), this, true);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package com.fastbee.modbus.pak;
|
||||
|
||||
|
||||
import com.fastbee.common.core.mq.DeviceReport;
|
||||
import com.fastbee.base.core.annotation.Node;
|
||||
import com.fastbee.base.core.annotation.PakMapping;
|
||||
import com.fastbee.base.model.DeviceMsg;
|
||||
import com.fastbee.base.model.SessionKey;
|
||||
import com.fastbee.base.session.Session;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static com.fastbee.modbus.pak.TcpDtu.心跳包;
|
||||
import static com.fastbee.modbus.pak.TcpDtu.注册报文;
|
||||
|
||||
/**
|
||||
* 报文消息映射处理
|
||||
* @author gsb
|
||||
* @date 2022/11/25 14:08
|
||||
*/
|
||||
@Node
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ModbusEndPoint {
|
||||
|
||||
@PakMapping(types = 注册报文)
|
||||
public DeviceReport register(DeviceReport message, Session session){
|
||||
//注册设备
|
||||
session.register(message);
|
||||
//记录设备信息
|
||||
DeviceMsg deviceMsg = new DeviceMsg();
|
||||
deviceMsg.setClientId(message.getClientId());
|
||||
session.setAttribute(SessionKey.DeviceMsg,deviceMsg);
|
||||
String hex = "FE8001FE";
|
||||
message.setBody(hex);
|
||||
return message;
|
||||
}
|
||||
|
||||
@PakMapping(types = 心跳包)
|
||||
public void heartbeat(DeviceReport message, Session session){
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.fastbee.modbus.pak;
|
||||
|
||||
/**
|
||||
* TCP-Dtu协议
|
||||
* @author gsb
|
||||
* @date 2022/11/25 14:12
|
||||
*/
|
||||
public interface TcpDtu {
|
||||
|
||||
int 注册报文 = 0x80;
|
||||
int 心跳包 = 0x81;
|
||||
int 起始位 = 0x7e;
|
||||
int 整包消息 = 0x00;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package com.fastbee.modbus.test;
|
||||
|
||||
import com.fastbee.common.core.mq.message.DeviceData;
|
||||
import com.fastbee.common.core.protocol.modbus.ModbusCode;
|
||||
import com.fastbee.common.utils.CaculateUtils;
|
||||
import com.fastbee.common.utils.gateway.protocol.ByteUtils;
|
||||
import com.fastbee.modbus.codec.ModbusDecoder;
|
||||
import com.fastbee.modbus.codec.ModbusEncoder;
|
||||
import com.fastbee.modbus.model.ModbusRtu;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 协议解析本地测试
|
||||
* @author bill
|
||||
*/
|
||||
@Slf4j
|
||||
public class ModbusTest {
|
||||
|
||||
private static ModbusDecoder decoder = new ModbusDecoder("com.fastbee.modbus");
|
||||
private static ModbusEncoder encoder = new ModbusEncoder("com.fastbee.modbus");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
/*单个03寄存器数据解析*/
|
||||
String hex = "0103020016398a";
|
||||
ByteBuf buf = Unpooled.wrappedBuffer(ByteBufUtil.decodeHexDump(hex));
|
||||
DeviceData data = DeviceData.builder()
|
||||
.buf(buf)
|
||||
.code(ModbusCode.Read03)
|
||||
.build();
|
||||
ModbusRtu message = decoder.decode(data);
|
||||
System.out.println("单个解析="+message);
|
||||
buf.release();
|
||||
/*批量读返回 03数据解析*/
|
||||
String hexMore = "01031000000000000000000000000000000000E459";
|
||||
ByteBuf bufMore = Unpooled.wrappedBuffer(ByteBufUtil.decodeHexDump(hexMore));
|
||||
DeviceData dataMore = DeviceData.builder()
|
||||
.buf(bufMore).build();
|
||||
ModbusRtu messageMore = decoder.decode(dataMore);
|
||||
System.out.println("批量上传报文解析="+messageMore);
|
||||
bufMore.release();
|
||||
|
||||
/*01、02解析*/
|
||||
String hex01 = "110105CD6BB20E1B45E6";
|
||||
ByteBuf buf01 = Unpooled.wrappedBuffer(ByteBufUtil.decodeHexDump(hex01));
|
||||
DeviceData data01 = DeviceData.builder()
|
||||
.buf(buf01)
|
||||
.code(ModbusCode.Read01)
|
||||
.build();
|
||||
ModbusRtu message01 = decoder.decode(data01);
|
||||
log.info("01、02解析=> 字节数:[{}],hex值:[{}]",message01.getBitCount(),ByteBufUtil.hexDump(message01.getBitData()));
|
||||
buf01.release();
|
||||
|
||||
|
||||
ModbusRtu read03 = new ModbusRtu();
|
||||
read03.setSlaveId(1);
|
||||
read03.setAddress(1);
|
||||
read03.setCode(3);
|
||||
read03.setCount(3);
|
||||
ByteBuf out = encoder.encode(read03);
|
||||
System.out.println(ByteBufUtil.hexDump(out));
|
||||
|
||||
ModbusRtu write06 = new ModbusRtu();
|
||||
write06.setSlaveId(1);
|
||||
write06.setAddress(1);
|
||||
write06.setCode(6);
|
||||
write06.setWriteData(17);
|
||||
ByteBuf writeOut = encoder.encode(write06);
|
||||
System.out.println(ByteBufUtil.hexDump(writeOut));
|
||||
|
||||
|
||||
String s = Integer.toHexString(Integer.parseInt("16878"));
|
||||
String s1 = Integer.toHexString(16878);
|
||||
System.out.println(s);
|
||||
String hexToBytes = "41EE8000";
|
||||
byte[] bytes = ByteBufUtil.decodeHexDump(hexToBytes);
|
||||
String v = CaculateUtils.toFloat(bytes);
|
||||
System.out.println(v);
|
||||
|
||||
System.out.println(ByteUtils.intToHex(-32768));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user