物联网---02.Modbus协议
一、简介
Modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP。
Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。
标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。
Modbus和RS485的关系:Modbus是协议,物理层接口有RS232、RS422、RS485和以太网接口几种
二、案例
1.使用jlibmodbus
maven配置
1 2 3 4 5 | <dependency> <groupId>com.intelligt.modbus</groupId> <artifactId>jlibmodbus</artifactId> <version> 1.2 . 9.7 </version> </dependency> |
java代码从Modbus读取数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import java.net.InetAddress; import com.intelligt.modbus.jlibmodbus.Modbus; import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException; import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException; import com.intelligt.modbus.jlibmodbus.exception.ModbusProtocolException; import com.intelligt.modbus.jlibmodbus.master.ModbusMaster; import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory; import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters; /** * 使用jlibmodbus完成ModbusTCP协议 * */ public class App { public static void main(String[] args) { try { // 设置主机TCP参数 TcpParameters tcpParameters = new TcpParameters(); // 设置TCP的ip地址 InetAddress adress = InetAddress.getByName( "192.168.3.16" ); // TCP参数设置ip地址 // tcpParameters.setHost(InetAddress.getLocalHost()); tcpParameters.setHost(adress); // TCP设置长连接 tcpParameters.setKeepAlive( true ); // TCP设置端口,这里设置是默认端口502 tcpParameters.setPort(Modbus.TCP_PORT); // 创建一个主机 ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters); Modbus.setAutoIncrementTransactionId( true ); int slaveId = 1 ; //从机地址 int offset = 0 ; //寄存器读取开始地址 int quantity = 10 ; //读取的寄存器数量 try { if (!master.isConnected()) { master.connect(); // 开启连接 } // 读取对应从机的数据,readInputRegisters读取的写寄存器,功能码04 int [] registerValues = master.readInputRegisters(slaveId, offset, quantity); // 控制台输出 for ( int value : registerValues) { System.out.println( "Address: " + offset++ + ", Value: " + value); } } catch (ModbusProtocolException e) { e.printStackTrace(); } catch (ModbusNumberException e) { e.printStackTrace(); } catch (ModbusIOException e) { e.printStackTrace(); } finally { try { master.disconnect(); } catch (ModbusIOException e) { e.printStackTrace(); } } } catch (RuntimeException e) { throw e; } catch (Exception e) { e.printStackTrace(); } } } |
2.使用modbus4j
maven配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version> 4.13 -beta- 3 </version> <scope>test</scope> </dependency> <dependency> <groupId>com.infiniteautomation</groupId> <artifactId>modbus4j</artifactId> <version> 3.0 . 3 </version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version> 3.9 </version> </dependency> <!-- 若想引用modbus4j需要引入下列repository id:ias-snapshots id:ias-releases 两个 ,使用默认仓库下载,不要使用阿里云仓库--> <repositories> <repository> <releases> <enabled> false </enabled> </releases> <snapshots> <enabled> true </enabled> </snapshots> <id>ias-snapshots</id> <name>Infinite Automation Snapshot Repository</name> <url>https: //maven.mangoautomation.net/repository/ias-snapshot/</url> </repository> <repository> <releases> <enabled> true </enabled> </releases> <snapshots> <enabled> false </enabled> </snapshots> <id>ias-releases</id> <name>Infinite Automation Release Repository</name> <url>https: //maven.mangoautomation.net/repository/ias-release/</url> </repository> </repositories> |
java使用modbus4j读取数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | 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实现 * */ 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( "10.211.55.4" ); 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 Coil Status 0x]类型 开关数据 * * @param slaveId * slaveId * @param offset * 位置 * @return 读取值 * @throws ModbusTransportException * 异常 * @throws ErrorResponseException * 异常 * @throws ModbusInitException * 异常 */ public static Boolean readCoilStatus( int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 01 Coil Status BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset); Boolean value = getMaster().getValue(loc); return value; } /** * 读取[02 Input Status 1x]类型 开关数据 * * @param slaveId * @param offset * @return * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ 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 Holding Register类型 2x]模拟量数据 * * @param slaveId * slave Id * @param offset * 位置 * @param dataType * 数据类型,来自com.serotonin.modbus4j.code.DataType * @return * @throws ModbusTransportException * 异常 * @throws ErrorResponseException * 异常 * @throws ModbusInitException * 异常 */ public static Number readHoldingRegister( int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 03 Holding Register类型数据读取 BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 读取[04 Input Registers 3x]类型 模拟量数据 * * @param slaveId * slaveId * @param offset * 位置 * @param dataType * 数据类型,来自com.serotonin.modbus4j.code.DataType * @return 返回结果 * @throws ModbusTransportException * 异常 * @throws ErrorResponseException * 异常 * @throws ModbusInitException * 异常 */ public static Number readInputRegisters( int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 04 Input Registers类型数据读取 BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 批量读取使用方法 * * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException { BatchRead<Integer> batch = new BatchRead<Integer>(); batch.addLocator( 0 , BaseLocator.holdingRegister( 1 , 1 , DataType.FOUR_BYTE_FLOAT)); batch.addLocator( 1 , BaseLocator.inputStatus( 1 , 0 )); 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 { // 01测试 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); // 02测试 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); // 03测试 Number v031 = readHoldingRegister( 1 , 1 , DataType.FOUR_BYTE_FLOAT); // 注意,float Number v032 = readHoldingRegister( 1 , 3 , DataType.FOUR_BYTE_FLOAT); // 同上 System.out.println( "v031:" + v031); System.out.println( "v032:" + v032); // 04测试 Number v041 = readInputRegisters( 1 , 0 , DataType.FOUR_BYTE_FLOAT); // 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(); } } } |
java通过modbus4j对数据的写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; 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; import com.serotonin.modbus4j.msg.ModbusResponse; import com.serotonin.modbus4j.msg.WriteCoilRequest; import com.serotonin.modbus4j.msg.WriteCoilResponse; import com.serotonin.modbus4j.msg.WriteCoilsRequest; import com.serotonin.modbus4j.msg.WriteCoilsResponse; import com.serotonin.modbus4j.msg.WriteRegisterRequest; import com.serotonin.modbus4j.msg.WriteRegisterResponse; import com.serotonin.modbus4j.msg.WriteRegistersRequest; /** * modbus4j写入数据 * */ public class Modbus4jWriteUtils { static Log log = LogFactory.getLog(Modbus4jWriteUtils. class ); /** * 工厂。 */ static ModbusFactory modbusFactory; static { if (modbusFactory == null ) { modbusFactory = new ModbusFactory(); } } /** * 获取tcpMaster * * @return * @throws ModbusInitException */ public static ModbusMaster getMaster() throws ModbusInitException { IpParameters params = new IpParameters(); params.setHost( "10.211.55.4" ); params.setPort( 502 ); ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false ); tcpMaster.init(); return tcpMaster; } /** * 写 [01 Coil Status(0x)]写一个 function ID = 5 * * @param slaveId * slave的ID * @param writeOffset * 位置 * @param writeValue * 值 * @return 是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeCoil( int slaveId, int writeOffset, boolean writeValue) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求 WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue); // 发送请求并获取响应对象 WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request); if (response.isException()) { return false ; } else { return true ; } } /** * 写[01 Coil Status(0x)] 写多个 function ID = 15 * * @param slaveId * slaveId * @param startOffset * 开始位置 * @param bdata * 写入的数据 * @return 是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeCoils( int slaveId, int startOffset, boolean [] bdata) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求 WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata); // 发送请求并获取响应对象 WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request); if (response.isException()) { return false ; } else { return true ; } } /*** * 写[03 Holding Register(4x)] 写一个 function ID = 6 * * @param slaveId * @param writeOffset * @param writeValue * @return * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeRegister( int slaveId, int writeOffset, short writeValue) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求对象 WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue); WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request); if (response.isException()) { log.error(response.getExceptionMessage()); return false ; } else { return true ; } } /** * * 写入[03 Holding Register(4x)]写多个 function ID=16 * * @param slaveId * modbus的slaveID * @param startOffset * 起始位置偏移量值 * @param sdata * 写入的数据 * @return 返回是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeRegisters( int slaveId, int startOffset, short [] sdata) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求对象 WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata); // 发送请求并获取响应对象 ModbusResponse response = tcpMaster.send(request); if (response.isException()) { log.error(response.getExceptionMessage()); return false ; } else { return true ; } } /** * 写入数字类型的模拟量(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long) * * @param slaveId * @param offset * @param value * 写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long * @param registerCount * ,com.serotonin.modbus4j.code.DataType * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static void writeHoldingRegister( int slaveId, int offset, Number value, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 类型 BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType); tcpMaster.setValue(locator, value); } public static void main(String[] args) { try { //@formatter:off // 测试01 // boolean t01 = writeCoil(1, 0, true); // System.out.println("T01:" + t01); // 测试02 // boolean t02 = writeCoils(1, 0, new boolean[] { true, false, true }); // System.out.println("T02:" + t02); // 测试03 // short v = -3; // boolean t03 = writeRegister(1, 0, v); // System.out.println("T03:" + t03); // 测试04 // boolean t04 = writeRegisters(1, 0, new short[] { -3, 3, 9 }); // System.out.println("t04:" + t04); //写模拟量 writeHoldingRegister( 1 , 0 , 10 .1f, DataType.FOUR_BYTE_FLOAT); //@formatter:on } catch (Exception e) { e.printStackTrace(); } } } |
3.使用modbus-master-tcp
modbus-master-tcp项目的底层是基于netty框架开发。天然的支持异步处理。在性能方面有很好的提升。
maven配置
1 2 3 4 5 | <dependency> <groupId>com.digitalpetri.modbus</groupId> <artifactId>modbus-master-tcp</artifactId> <version> 1.1 . 0 </version> </dependency> |
java使用modbus-master-tcp读取数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import com.digitalpetri.modbus.codec.Modbus; import com.digitalpetri.modbus.master.ModbusTcpMaster; import com.digitalpetri.modbus.master.ModbusTcpMasterConfig; import com.digitalpetri.modbus.requests.ReadCoilsRequest; import com.digitalpetri.modbus.requests.ReadDiscreteInputsRequest; import com.digitalpetri.modbus.requests.ReadHoldingRegistersRequest; import com.digitalpetri.modbus.requests.ReadInputRegistersRequest; import com.digitalpetri.modbus.responses.ReadCoilsResponse; import com.digitalpetri.modbus.responses.ReadDiscreteInputsResponse; import com.digitalpetri.modbus.responses.ReadHoldingRegistersResponse; import com.digitalpetri.modbus.responses.ReadInputRegistersResponse; import io.netty.buffer.ByteBuf; import io.netty.util.ReferenceCountUtil; /*** * modbus TCP协议Java通讯读取例子 * * */ public class ModbusMasterTCPDemo { static ModbusTcpMaster master; /** * 获取TCP协议的Master * * @return */ public static void initModbusTcpMaster() { if (master == null ) { // 创建配置 ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder( "10.211.55.4" ).setPort( 502 ).build(); master = new ModbusTcpMaster(config); } } /*** * 释放资源 */ public static void release() { if (master != null ) { master.disconnect(); } Modbus.releaseSharedResources(); } /** * 读取Coils开关量 * * @param address * 寄存器开始地址 * @param quantity * 数量 * @param unitId * ID * @return 读取值 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Boolean readCoils( int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Boolean result = null ; CompletableFuture<ReadCoilsResponse> future = master.sendRequest( new ReadCoilsRequest(address, quantity), unitId); ReadCoilsResponse readCoilsResponse = future.get(); // 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (readCoilsResponse != null ) { ByteBuf buf = readCoilsResponse.getCoilStatus(); result = buf.readBoolean(); ReferenceCountUtil.release(readCoilsResponse); } return result; } /** * 读取readDiscreteInputs开关量 * * @param address * 寄存器开始地址 * @param quantity * 数量 * @param unitId * ID * @return 读取值 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Boolean readDiscreteInputs( int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Boolean result = null ; CompletableFuture<ReadDiscreteInputsResponse> future = master .sendRequest( new ReadDiscreteInputsRequest(address, quantity), unitId); ReadDiscreteInputsResponse discreteInputsResponse = future.get(); // 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (discreteInputsResponse != null ) { ByteBuf buf = discreteInputsResponse.getInputStatus(); result = buf.readBoolean(); ReferenceCountUtil.release(discreteInputsResponse); } return result; } /** * 读取HoldingRegister数据 * * @param address * 寄存器地址 * @param quantity * 寄存器数量 * @param unitId * id * @return 读取结果 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Number readHoldingRegisters( int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Number result = null ; CompletableFuture<ReadHoldingRegistersResponse> future = master .sendRequest( new ReadHoldingRegistersRequest(address, quantity), unitId); ReadHoldingRegistersResponse readHoldingRegistersResponse = future.get(); // 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (readHoldingRegistersResponse != null ) { ByteBuf buf = readHoldingRegistersResponse.getRegisters(); result = buf.readFloat(); ReferenceCountUtil.release(readHoldingRegistersResponse); } return result; } /** * 读取InputRegisters模拟量数据 * * @param address * 寄存器开始地址 * @param quantity * 数量 * @param unitId * ID * @return 读取值 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Number readInputRegisters( int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Number result = null ; CompletableFuture<ReadInputRegistersResponse> future = master .sendRequest( new ReadInputRegistersRequest(address, quantity), unitId); ReadInputRegistersResponse readInputRegistersResponse = future.get(); // 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (readInputRegistersResponse != null ) { ByteBuf buf = readInputRegistersResponse.getRegisters(); result = buf.readDouble(); ReferenceCountUtil.release(readInputRegistersResponse); } return result; } public static void main(String[] args) { try { // 初始化资源 initModbusTcpMaster(); // 执行操作 // 读取开关量 System.out.println(readCoils( 0 , 1 , 1 )); System.out.println(readDiscreteInputs( 0 , 1 , 1 )); System.out.println(readDiscreteInputs( 1 , 1 , 1 )); // 读取模拟量 System.out.println(readHoldingRegisters( 0 , 2 , 1 )); System.out.println(readHoldingRegisters( 2 , 2 , 1 )); System.out.println(readHoldingRegisters( 4 , 2 , 1 )); System.out.println(readInputRegisters( 2 , 4 , 1 )); System.out.println(readInputRegisters( 6 , 4 , 1 )); // 释放资源 release(); } catch (Exception e) { e.printStackTrace(); } } } |
总结
- jlibmodbus:集成多个串口通信开源库,有意思
- modbus4j:很有名
- modbus-master-tcp:底层netty,支持异步
- Jamod:Github上安卓开发modbus通信用的多
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?