package com.jg.service.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.jg.common.ValueType; import com.jg.service.ModBusService; import com.jg.util.ModBusUtil; import com.jg.util.WebSocketServer; import com.jg.vo.ShowVo; import com.jg.vo.TagVo; import com.serotonin.modbus4j.BatchRead; import com.serotonin.modbus4j.BatchResults; import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.code.DataType; import com.serotonin.modbus4j.locator.BaseLocator; import jdk.nashorn.internal.ir.annotations.Reference; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.io.IOException; import java.math.BigDecimal; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.*; @Slf4j @Service public class ModBusServiceImpl implements ModBusService { private static final Map MASTER_MAP = new HashMap<>(64); private String show; @Value("${modbus.host}") private String host; @Value("${modbus.port}") private Integer port; @Reference private WebSocketServer webSocketServer; /** * 创建ModBusTCP连接 */ @EventListener(ApplicationReadyEvent.class) private void createConn() { // 创建ModBus连接, 存入MASTER_MAP // List collectModuleInfoList = collectModuleInfoService.findCurrent(); // log.info("[查询采集模块列表]: {}", collectModuleInfoList); // if (!CollectionUtils.isEmpty(collectModuleInfoList)) { // for (CollectModuleInfo collectModuleInfo : collectModuleInfoList) { // Long collectModuleInfoId = collectModuleInfo.getId(); // MODULE_INFO_MAP.put(collectModuleInfoId, collectModuleInfo); // // 循环创建ModBus连接 // ModbusMaster modbusMaster = MASTER_MAP.get(collectModuleInfoId); // if (null == modbusMaster) { // // 创建ModBus连接, 存入Map, key: 采集模块id, value: ModBus连接 // modbusMaster = ModBusUtil.createMaster(collectModuleInfo); // MASTER_MAP.put(collectModuleInfoId, modbusMaster); // } // } // } else { //// throw new BizException("连接失败! 没有查询到ModBus模块信息!"); // } // log.warn("[开始连接采集模块]: {}", JSON.toJSONString(collectModuleInfoList)); ModbusMaster master = ModBusUtil.createMaster(host, port); MASTER_MAP.put(1l, master); try { show = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("tag.json").toURI())), StandardCharsets.UTF_8); } catch (Exception e) { e.printStackTrace(); } } @Scheduled(fixedRate = 1000) private void readTagsValue(){ List tagVos = JSON.parseArray(show, TagVo.class); BatchRead batch = new BatchRead<>(); JSONArray array = new JSONArray(); for (TagVo tagVo: tagVos){ Integer slaveId = tagVo.getSlaveId(); Integer functionCode = tagVo.getFunctionCode(); int offset = tagVo.getOffset(); String tag = tagVo.getTag(); String dataType = tagVo.getDataType(); switch (functionCode) { case 1: batch.addLocator(tag, BaseLocator.coilStatus(slaveId, offset)); break; case 2: batch.addLocator(tag, BaseLocator.inputStatus(slaveId, offset)); break; case 3: batch.addLocator(tag, BaseLocator.holdingRegister(slaveId, offset, getValueType(dataType))); break; case 4: batch.addLocator(tag, BaseLocator.inputRegister(slaveId, offset, getValueType(dataType))); break; default: break; } } batch.setContiguousRequests(false); ModbusMaster modbusMaster = MASTER_MAP.get(1l); try { if (!modbusMaster.isInitialized()) { modbusMaster.init(); } modbusMaster.setTimeout(500); BatchResults results = modbusMaster.send(batch); for (TagVo tagVo: tagVos){ // log.info("采集中文: {}, 值: {}", tagVo.getDesc(), results.getValue(tagVo.getTag())); Object value = results.getValue(tagVo.getTag()); BigDecimal bigDecimalValue = convertToBigDecimal(value); ShowVo showVo = new ShowVo(); showVo.setName(tagVo.getDesc()); showVo.setValue(bigDecimalValue); showVo.setUnit(tagVo.getUnit()); // showVos.add(showVo); array.add(showVo); } log.info(array.toString()); webSocketServer.sendInfo(array.toString(), "push"); modbusMaster.destroy(); } catch (Exception e) { log.error("采集模块Id: {}, 读取失败: {}", 1l, e.getMessage()); } } /** * 获取数据类型 * 说明:此处可根据实际项目情况进行拓展 * 1.swap 交换 * 2.大端/小端,默认是大端 * 3.拓展其他数据类型 * * @param type Value Type * @return Modbus Data Type */ public static int getValueType(String type) { switch (type.toLowerCase()) { case ValueType.LONG: return DataType.FOUR_BYTE_INT_SIGNED; case ValueType.FLOAT: return DataType.FOUR_BYTE_FLOAT; case ValueType.DOUBLE: return DataType.EIGHT_BYTE_FLOAT; default: return DataType.TWO_BYTE_INT_UNSIGNED; } } /** * 将 Object 转换为 BigDecimal **/ private static BigDecimal convertToBigDecimal(Object obj) { // 处理 obj 为 null 的情况,返回 -1 if (obj == null) { return BigDecimal.valueOf(-1); } if (obj instanceof BigDecimal) { return (BigDecimal) obj; } else if (obj instanceof Integer) { return BigDecimal.valueOf((Integer) obj); } else if (obj instanceof Double) { return BigDecimal.valueOf((Double) obj); } else if (obj instanceof String) { return new BigDecimal((String) obj); } else if (obj instanceof Float){ return BigDecimal.valueOf(((Float) obj).doubleValue()); } else if (obj instanceof Boolean) { return BigDecimal.valueOf((Boolean) obj ? 1 : 0); } else { throw new IllegalArgumentException("Unsupported object type: " + obj.getClass()); } } @Override public void startCollect() { createConn(); readTagsValue(); } }