package com.huaheng.api.dianqi; import com.serotonin.modbus4j.BatchRead; import com.serotonin.modbus4j.BatchResults; import com.serotonin.modbus4j.ModbusFactory; import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.code.DataType; import com.serotonin.modbus4j.exception.ErrorResponseException; import com.serotonin.modbus4j.exception.ModbusInitException; import com.serotonin.modbus4j.exception.ModbusTransportException; import com.serotonin.modbus4j.ip.IpParameters; import com.serotonin.modbus4j.locator.BaseLocator; /** * modbus通讯工具类,采用modbus4j实现 * @author lxq * @dependencies modbus4j-3.0.3.jar * @website https://github.com/infiniteautomation/modbus4j */ public class Modbus4jUtils { /** * 工厂。 */ static ModbusFactory modbusFactory; static { if (modbusFactory == null) { modbusFactory = new ModbusFactory(); } } /** * 获取master * @return * @throws ModbusInitException */ public static ModbusMaster getMaster() throws ModbusInitException { IpParameters params = new IpParameters(); params.setHost("localhost"); params.setPort(502); // modbusFactory.createRtuMaster(wapper); //RTU 协议 // modbusFactory.createUdpMaster(params);//UDP 协议 // modbusFactory.createAsciiMaster(wrapper);//ASCII 协议 ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 master.init(); return master; } /** * 读取线圈 功能码01 [01 Coil Status 0x]类型 开关数据 true/false * @param slaveId 从站地址 * @param offset 偏移量 * @return 读取值 true/false */ public static Boolean readCoilStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException { BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset); Boolean value = getMaster().getValue(loc); return value; } /** * 读取离散量 功能码02 [02 Input Status 1x]类型 开关数据 true/false * @param slaveId 从站地址 * @param offset 偏移量 * @return 读取值 true/false */ public static Boolean readInputStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 02 Input Status BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset); Boolean value = getMaster().getValue(loc); return value; } /** * 读取保持寄存器 功能码03 [03 Holding Register类型 2x] 模拟量数据 * * @param slaveId 从站地址 * @param offset 偏移量 * @param dataType 数据类型,来自com.serotonin.modbus4j.code.DataType * @return 返回结果 */ public static Number readHoldingRegister(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 读取输入寄存器 功能码04 [04 Input Registers 3x]类型 模拟量数据 * @param slaveId 从站地址 * @param offset 偏移量 * @param dataType 数据类型,来自com.serotonin.modbus4j.code.DataType * @return 返回结果 */ public static Number readInputRegisters(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 批量读取使用方法 */ public static void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException { BatchRead<Integer> batch = new BatchRead<Integer>(); //slaveId 从站地址 offset 偏移量 DataType.FOUR_BYTE_FLOAT 读取四个字节的float类型 batch.addLocator(0, BaseLocator.holdingRegister(1, 0, DataType.FOUR_BYTE_FLOAT)); batch.addLocator(1, BaseLocator.inputStatus(1, 5)); ModbusMaster master = getMaster(); batch.setContiguousRequests(false); BatchResults<Integer> results = master.send(batch); System.out.println(results.getValue(0)); System.out.println(results.getValue(1)); } /** * 测试 * * @param args */ public static void main(String[] args) { try { // 读线圈 从站地址1 偏移量 0 1 6 三个 Boolean v011 = readCoilStatus(1, 0); Boolean v012 = readCoilStatus(1, 1); Boolean v013 = readCoilStatus(1, 6); System.out.println("v011:" + v011); System.out.println("v012:" + v012); System.out.println("v013:" + v013); // 读偏移量 从站地址1 偏移量 0 1 2 三个 Boolean v021 = readInputStatus(1, 0); Boolean v022 = readInputStatus(1, 1); Boolean v023 = readInputStatus(1, 2); System.out.println("v021:" + v021); System.out.println("v022:" + v022); System.out.println("v023:" + v023); // 读保持寄存器 从站地址1 偏移量 0 1 类型四个字节的float类型 Number v031 = readHoldingRegister(1, 0, DataType.FOUR_BYTE_FLOAT);// 注意,float Number v032 = readHoldingRegister(1, 1, DataType.FOUR_BYTE_FLOAT);// 同上 System.out.println("v031:" + v031); System.out.println("v032:" + v032); // 读输入寄存器 类型两个字节的int无符号 Number v041 = readInputRegisters(1, 0, DataType.TWO_BYTE_INT_SIGNED);// Number v042 = readInputRegisters(1, 2, DataType.FOUR_BYTE_FLOAT);// System.out.println("v041:" + v041); System.out.println("v042:" + v042); // 批量读取 batchRead(); } catch (Exception e) { e.printStackTrace(); } } }