Java使用modbus-master-tcp實(shí)現(xiàn)modbus tcp通訊
引言
modbus tcp通訊Java的方案之前已經(jīng)講解過(guò)一種,modbus4j實(shí)現(xiàn)Java語(yǔ)言的modbus tcp協(xié)議通訊。從上一個(gè)方案中我們不難發(fā)現(xiàn)modbus4j的通訊實(shí)現(xiàn)方式是同步的。實(shí)際應(yīng)用中可能會(huì)讀取大量的數(shù)據(jù)。同步處理對(duì)于應(yīng)用的響應(yīng)還是不太友好的。本博客主要講解另外一種Java語(yǔ)言的modbux tcp通訊方案。那就是modbus-master-tcp。
一、創(chuàng)建一個(gè)demo項(xiàng)目
創(chuàng)建一個(gè)簡(jiǎn)單的maven項(xiàng)目,項(xiàng)目結(jié)構(gòu)圖如下:
二、pom.xml maven依賴(lài)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.leftso.demo.modbus</groupId> <artifactId>demo-modbus-master-slave</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>com.digitalpetri.modbus</groupId> <artifactId>modbus-master-tcp</artifactId> <version>1.1.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
pom.xml注意,需要將java的編譯版本指定到1.8.因?yàn)橹挥?.8以后才支持lambda表達(dá)式。
配置完成后,我們觀察引入的依賴(lài)包:
觀察可以發(fā)現(xiàn),modbus-master-tcp項(xiàng)目的底層是基于netty框架開(kāi)發(fā)。天然的支持異步處理。在性能方面有很好的提升。
三、編寫(xiě)modbus tcp讀取案例
package com.leftso.demo.modbus; 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協(xié)議Java通訊讀取例子 * * @author xqlee * */ public class SimpleMasterExample { static ModbusTcpMaster master; /** * 獲取TCP協(xié)議的Master * * @return */ public static void initModbusTcpMaster() { if (master == null) { // 創(chuàng)建配置 ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost").setPort(502).build(); master = new ModbusTcpMaster(config); } } /*** * 釋放資源 */ public static void release() { if (master != null) { master.disconnect(); } Modbus.releaseSharedResources(); } /** * 讀取HoldingRegister數(shù)據(jù) * * @param address * 寄存器地址 * @param quantity * 寄存器數(shù)量 * @param unitId * id * @return 讀取結(jié)果 * @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();// 工具類(lèi)做的同步返回.實(shí)際使用推薦結(jié)合業(yè)務(wù)進(jìn)行異步處理 if (readHoldingRegistersResponse != null) { ByteBuf buf = readHoldingRegistersResponse.getRegisters(); result = buf.readFloat(); ReferenceCountUtil.release(readHoldingRegistersResponse); } return result; } /** * 讀取InputRegisters模擬量數(shù)據(jù) * * @param address * 寄存器開(kāi)始地址 * @param quantity * 數(shù)量 * @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();// 工具類(lèi)做的同步返回.實(shí)際使用推薦結(jié)合業(yè)務(wù)進(jìn)行異步處理 if (readInputRegistersResponse != null) { ByteBuf buf = readInputRegistersResponse.getRegisters(); result = buf.readFloat(); ReferenceCountUtil.release(readInputRegistersResponse); } return result; } /** * 讀取Coils開(kāi)關(guān)量 * * @param address * 寄存器開(kāi)始地址 * @param quantity * 數(shù)量 * @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();// 工具類(lèi)做的同步返回.實(shí)際使用推薦結(jié)合業(yè)務(wù)進(jìn)行異步處理 if (readCoilsResponse != null) { ByteBuf buf = readCoilsResponse.getCoilStatus(); result = buf.readBoolean(); ReferenceCountUtil.release(readCoilsResponse); } return result; } /** * 讀取readDiscreteInputs開(kāi)關(guān)量 * * @param address * 寄存器開(kāi)始地址 * @param quantity * 數(shù)量 * @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();// 工具類(lèi)做的同步返回.實(shí)際使用推薦結(jié)合業(yè)務(wù)進(jìn)行異步處理 if (discreteInputsResponse != null) { ByteBuf buf = discreteInputsResponse.getInputStatus(); result = buf.readBoolean(); ReferenceCountUtil.release(discreteInputsResponse); } return result; } public static void main(String[] args) { try { // 初始化資源 initModbusTcpMaster(); // 執(zhí)行操作 // 讀取模擬量 System.out.println(readHoldingRegisters(0, 4, 1)); System.out.println(readInputRegisters(0, 4, 1)); // 讀取開(kāi)關(guān)量 System.out.println(readCoils(0, 1, 1)); System.out.println(readDiscreteInputs(0, 1, 1)); System.out.println(readDiscreteInputs(2, 1, 1)); // 釋放資源 release(); } catch (Exception e) { e.printStackTrace(); } } }
上面的代碼中模擬量的讀取需要注意,根據(jù)實(shí)際類(lèi)型來(lái)讀取相應(yīng)的類(lèi)型,例子中讀取的double類(lèi)型數(shù)據(jù)
四、運(yùn)行上面的案例演示modbus tcp數(shù)據(jù)讀取
首先打開(kāi)軟件Modbus Slave(沒(méi)有的可以百度下載)。啟動(dòng)連接:
連接完成后,創(chuàng)建四個(gè)文檔如下圖所示:
好了,現(xiàn)在運(yùn)行我們剛才編寫(xiě)的Java demo程序,SimpleMasterExample:
通過(guò)執(zhí)行結(jié)果可以看到與Modbus Slave軟件中的文檔數(shù)據(jù)一致。
以上就是Java使用modbus-master-tcp實(shí)現(xiàn)modbus tcp通訊的詳細(xì)內(nèi)容,更多關(guān)于Java modbustcp通訊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java微服務(wù)Filter過(guò)濾器集成Sentinel實(shí)現(xiàn)網(wǎng)關(guān)限流過(guò)程詳解
這篇文章主要介紹了Java微服務(wù)Filter過(guò)濾器集成Sentinel實(shí)現(xiàn)網(wǎng)關(guān)限流過(guò)程,首先Sentinel規(guī)則的存儲(chǔ)默認(rèn)是存儲(chǔ)在內(nèi)存的,應(yīng)用重啟之后規(guī)則會(huì)丟失。因此我們通過(guò)配置中心Nacos保存規(guī)則,然后通過(guò)定時(shí)拉取Nacos數(shù)據(jù)來(lái)獲取規(guī)則配置,可以做到動(dòng)態(tài)實(shí)時(shí)的刷新規(guī)則2023-02-02詳解使用JavaCV/OpenCV抓取并存儲(chǔ)攝像頭圖像
本篇文章主要介紹了使用JavaCV/OpenCV抓取并存儲(chǔ)攝像頭圖像,實(shí)例分析了使用JavaCV/OpenCV抓取并存儲(chǔ)攝像頭圖像的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-04-04Java調(diào)用ChatGPT(基于SpringBoot和Vue)實(shí)現(xiàn)可連續(xù)對(duì)話和流式輸出的ChatGPT API
這篇文章主要介紹了Java調(diào)用ChatGPT(基于SpringBoot和Vue),實(shí)現(xiàn)可連續(xù)對(duì)話和流式輸出的ChatGPT API(可自定義實(shí)現(xiàn)AI助手),文中代碼示例介紹的非常詳細(xì),感興趣的朋友可以參考下2023-04-04Java如何用一個(gè)統(tǒng)一結(jié)構(gòu)接收成員名稱(chēng)不固定的數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了Java如何用一個(gè)統(tǒng)一結(jié)構(gòu)接收成員名稱(chēng)不固定的數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-11-11Java Caledar類(lèi)(日歷類(lèi))如何判斷本周周數(shù)
這篇文章主要介紹了Java Caledar類(lèi)(日歷類(lèi))如何判斷本周周數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06利用Stream聚合函數(shù)如何對(duì)BigDecimal求和
這篇文章主要介紹了利用Stream聚合函數(shù)如何對(duì)BigDecimal求和問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05Java中args參數(shù)數(shù)組的用法說(shuō)明
這篇文章主要介紹了Java中args參數(shù)數(shù)組的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02