Java与Modbus通信
1、引入依赖
<dependency> <groupId>com.intelligt.modbus</groupId> <artifactId>jlibmodbus</artifactId> <!-- 版本号可依照maven仓库迭代升级 --> <version>1.2.9.7</version> </dependency>
2、获取Modbus连接
/** * 获取Modbus连接 * @return */ private Map<String, ModbusMaster> getModbusConn() throws UnknownHostException { ModbusMaster modbusMaster; TcpParameters tcpParameters = new TcpParameters(); List<String> modbusIps = hfyProperties.getIps(); Map<String, ModbusMaster> modbusMasterMap = new HashMap<>(); for(String modbusIp : modbusIps){ // TCP参数设置ip地址 tcpParameters.setHost(InetAddress.getByName(modbusIp)); // TCP设置长连接 tcpParameters.setKeepAlive(true); // TCP设置端口,这里设置是默认端口502 tcpParameters.setPort(Integer.valueOf(hfyProperties.getPort())); // 创建一个主机 modbusMaster = ModbusMasterFactory.createModbusMasterTCP(tcpParameters); Modbus.setAutoIncrementTransactionId(true); modbusMasterMap.put(modbusIp, modbusMaster); } return modbusMasterMap; }
注:我这里是获得了3台modbus连接,因为有三台服务器。
3、根据功能码,实时读取Modbus数据
/** * 批量采集Modbus数据 */ //@RequestMapping("/") @Scheduled(fixedRate = 1, timeUnit = TimeUnit.SECONDS) public void batchReadHfyData() { long startTime = System.nanoTime(); try { // 采集灰分仪数据 Map<String, List<SlaveBlockDto>> slaveBlockDtoList = gatherSlaveData(slaveBlocks); // 发送kafka eventPublisher.publishEvent(new HfyMessageEvent(this, slaveBlockDtoList)); log.info("读取数据耗时:{} 毫秒, 数据量:{}", Duration.ofNanos(System.nanoTime() - startTime).toMillis(), slaveBlockDtoList.size()); } catch (ExecutionException | InterruptedException | UnknownHostException | ModbusIOException | ModbusProtocolException | ModbusNumberException e) { throw new RuntimeException(e); } } /** * 采集灰分仪数据 */ private Map<String, List<SlaveBlockDto>> gatherSlaveData(List<SlaveBlock> slaveBlocks) throws ExecutionException, InterruptedException, UnknownHostException, ModbusIOException, ModbusProtocolException, ModbusNumberException { List<SlaveBlockDto> dtoList; Map<String, ModbusMaster> modbusMasterMap = getModbusConn(); Map<String, List<SlaveBlockDto>> resultMap = new HashMap<>(); // 连接Modbus,实时获取料位仪的数据 for(Map.Entry<String, ModbusMaster> modbusMaster : modbusMasterMap.entrySet()){ ModbusMaster master = modbusMaster.getValue(); String modbusIp = modbusMaster.getKey(); // 开启连接 master.connect(); log.info("modbus, ip:{} 连接成功,连接为:{}", modbusIp, master); // 根据功能码读取实时数据 dtoList = gatherImmDataByFuncCode(master); resultMap.put(modbusIp, dtoList); } return resultMap; } private List<SlaveBlockDto> gatherImmDataByFuncCode(ModbusMaster master) throws ModbusProtocolException, ModbusNumberException, ModbusIOException { List<SlaveBlockDto> dtoList = new ArrayList<>(); int slaveId = hfyProperties.getSlaveId(); int quantity = hfyProperties.getQuantity(); for(SlaveBlock slaveBlock : slaveBlocks){ if(slaveBlock.getFunctionCode().equalsIgnoreCase(FuncCodeEnum.CODE_FIVE.getCode())) continue; SlaveBlockDto slaveBlockDto = new SlaveBlockDto(); // 功能码 String code = slaveBlock.getFunctionCode(); // 偏移地址 int offset = slaveBlock.getOffset(); FuncCodeEnum funcCodeEnum = FuncCodeEnum.fromFuncCodes(code); // 根据不同的功能码读取modbus数据 switch(funcCodeEnum){ case CODE_TWO: boolean[] discreteInputs = master.readDiscreteInputs(slaveId, offset, quantity); slaveBlockDto.setValue(String.valueOf(discreteInputs[0])); break; case CODE_FOUR: int[] inputRegisters = master.readInputRegisters(slaveId, offset, quantity); slaveBlockDto.setValue(String.valueOf(inputRegisters[0])); break; case CODE_FIVE: default: break; } // 封装数据 slaveBlockDto.setName(slaveBlock.getName()); slaveBlockDto.setNameDesc(slaveBlock.getDesc()); dtoList.add(slaveBlockDto); } return dtoList; }