Repository: zengfr/easymodbus4j Branch: master Commit: 5749858eb495 Files: 104 Total size: 169.7 KB Directory structure: gitextract_pblhxo4a/ ├── .gitignore ├── LICENSE ├── README.md ├── easymodbus4j-commandclient/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── github/ │ │ │ └── zengfr/ │ │ │ └── easymodbus4j/ │ │ │ └── app/ │ │ │ ├── client/ │ │ │ │ ├── DeviceClient.java │ │ │ │ ├── UdpClient.java │ │ │ │ └── UdpClientHandler.java │ │ │ ├── common/ │ │ │ │ ├── DeviceArg.java │ │ │ │ ├── DeviceCommand.java │ │ │ │ └── FunctionCode.java │ │ │ ├── gprs/ │ │ │ │ └── juheApi.java │ │ │ ├── gps/ │ │ │ │ ├── gprsData.java │ │ │ │ ├── locapiBaiduClientUtil.java │ │ │ │ ├── locapiCellidClientUtil.java │ │ │ │ ├── locapiReq.java │ │ │ │ ├── locapiReqBody.java │ │ │ │ ├── locapiResp.java │ │ │ │ └── locapiRespBody.java │ │ │ ├── repository/ │ │ │ │ ├── access_tokenReq.java │ │ │ │ ├── access_tokenResp.java │ │ │ │ ├── autosend_listReq.java │ │ │ │ ├── autosend_listResp.java │ │ │ │ ├── autosend_listRespItem.java │ │ │ │ ├── mainboard_adressResp.java │ │ │ │ ├── mainboard_adressRespItem.java │ │ │ │ ├── req.java │ │ │ │ ├── resp.java │ │ │ │ ├── update_modbus_valuesReq.java │ │ │ │ ├── update_modbus_valuesReqItem.java │ │ │ │ ├── update_slaveipportReq.java │ │ │ │ └── value.java │ │ │ ├── sender/ │ │ │ │ ├── UdpSender.java │ │ │ │ └── UdpSenderFactory.java │ │ │ └── util/ │ │ │ └── HttpUtil.java │ │ └── resources/ │ │ └── readme.txt │ └── test/ │ └── java/ │ ├── ClientTest.java │ └── CustomUdpClientHandler.java ├── easymodbus4j-example/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── github/ │ │ │ └── zengfr/ │ │ │ └── easymodbus4j/ │ │ │ ├── example/ │ │ │ │ ├── ModbusConfig.java │ │ │ │ ├── ModbusConsoleApp.java │ │ │ │ ├── ModbusSetup.java │ │ │ │ ├── processor/ │ │ │ │ │ ├── ExampleModbusMasterResponseProcessor.java │ │ │ │ │ └── ExampleModbusSlaveRequestProcessor.java │ │ │ │ └── schedule/ │ │ │ │ └── ModbusMasterSchedule4ConfigFile.java │ │ │ ├── example3/ │ │ │ │ ├── Example3.java │ │ │ │ └── Example4.java │ │ │ └── main/ │ │ │ └── Example.java │ │ └── resources/ │ │ ├── autoSend.txt │ │ ├── logback.xml │ │ ├── readme.txt │ │ ├── start0-Server4TcpMaster-Client4TcpSlave.bat │ │ ├── start1-Server4TcpMaster.bat │ │ ├── start2-Client4TcpSlave.bat │ │ ├── start3-Client4TcpMaster.bat │ │ ├── start4-Server4TcpSlave.bat │ │ ├── start5-Server4RtuMaster-Client4RtuSlave.bat │ │ ├── start6-Server4RtuMaster.bat │ │ ├── start7-Client4RtuSlave.bat │ │ ├── start8-Client4RtuMaster.bat │ │ ├── start9-Server4RtuSlave.bat │ │ └── zip.xml │ └── test/ │ └── java/ │ └── com/ │ └── github/ │ └── zengfr/ │ └── easymodbus4j/ │ └── AppTest.java ├── easymodbus4j-example2/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── github/ │ │ │ └── zengfr/ │ │ │ └── easymodbus4j/ │ │ │ ├── app/ │ │ │ │ ├── ModbusServer4MasterApp.java │ │ │ │ ├── cache/ │ │ │ │ │ ├── AbstrctModbusKVCache.java │ │ │ │ │ ├── ModbusDeviceIdVersionIdCache.java │ │ │ │ │ ├── ModbusIpPortDeviceIdCache.java │ │ │ │ │ ├── ModbusKVCacheFactory.java │ │ │ │ │ └── ModbusVersionIdCache.java │ │ │ │ ├── plugin/ │ │ │ │ │ ├── DeviceCommandPlugin.java │ │ │ │ │ ├── DeviceCommandPluginRegister.java │ │ │ │ │ ├── DevicePlugin.java │ │ │ │ │ ├── DeviceRepositoryPlugin.java │ │ │ │ │ ├── DeviceRepositoryPluginRegister.java │ │ │ │ │ └── impl/ │ │ │ │ │ ├── DeviceCommandAbstractPlugin.java │ │ │ │ │ ├── DeviceCommandV1PluginImpl.java │ │ │ │ │ └── DeviceRepositoryV1PluginImpl.java │ │ │ │ ├── processor/ │ │ │ │ │ └── CustomModbusMasterResponseProcessor.java │ │ │ │ ├── repository/ │ │ │ │ │ └── DataRestRepository.java │ │ │ │ ├── schedule/ │ │ │ │ │ ├── ModbusMasterSchedule4All.java │ │ │ │ │ └── ModbusMasterSchedule4DeviceId.java │ │ │ │ ├── server/ │ │ │ │ │ └── udp/ │ │ │ │ │ ├── UdpServer.java │ │ │ │ │ ├── UdpServerHandler.java │ │ │ │ │ └── UdpServerHandler4SendToServer.java │ │ │ │ └── util/ │ │ │ │ └── NetworkUtil.java │ │ │ └── main/ │ │ │ └── Example2.java │ │ └── resources/ │ │ ├── log4j.properties │ │ ├── logback.xml │ │ ├── readme.txt │ │ ├── start0-Server4TcpMaster-UdpServer.bat │ │ ├── start6-Server4RtuMaster-UdpServer.bat │ │ └── zip.xml │ └── test/ │ └── java/ │ └── com/ │ └── github/ │ └── zengfr/ │ └── easymodbus4j/ │ ├── RegistersUtilTest.java │ └── app/ │ ├── A.java │ ├── AppTest.java │ ├── CaseTest.java │ └── PrimeTest.java └── easymodbus4j-extension/ ├── pom.xml └── src/ └── main/ └── java/ └── com/ └── github/ └── zengfr/ └── easymodbus4j/ ├── handle/ │ └── impl/ │ ├── ModbusMasterResponseHandler.java │ └── ModbusSlaveRequestHandler.java └── processor/ ├── AbstractModbusProcessor.java ├── ModbusMasterResponseProcessor.java ├── ModbusProcessor.java └── ModbusSlaveRequestProcessor.java ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Compiled class file *.class # Log file *.log # BlueJ files *.ctxt # Mobile Tools for Java (J2ME) .mtj.tmp/ # Package Files # *.jar *.war *.nar *.ear *.zip *.tar.gz *.rar *.iml dbg/ target/ .settings/ .idea/ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2021 zengfr https://github.com/zengfr Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ![easymodbus4j运行效果图截屏](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture.PNG?raw=true) # easymodbus4j [chs] easymodbus4j是一个高性能和易用的 Modbus 协议的 Java 实现,基于 Netty 开发,可用于 Modbus协议的Java客户端和服务器开发. # easymodbus4j [en] A high-performance and ease-of-use implementation of the Modbus protocol written in Java netty support for modbus 8 mode client/server and master/slave. ### easymodbus4j features 特点: - 1、Netty NIO high performance高性能. - 2、Modbus Function sync/aync 同步/异步非阻塞。 - 3、Modbus IoT Data Connector Supports工业物联网平台IoT支持。 - 4、支持Modbus TCP\Modbus RTU protocol两种通信协议. - 5、灵活架构,支持8种生产部署模式,自由组合,满足不同生产要求. - 6、通用组件包,支持高度自定义接口. - 7、完全支持Modbus TCP 4种部署模式: TCP服务器master,TCP客户端slave,TCP服务器slave,TCP客户端master。 - 8、完全支持Modbus RTU 4种部署模式: RTU服务器master,RTU客户端slave,RTU服务器slave,RTU客户端master。 - 9、友好的调试以及日志支持bit\bitset\byte\short\int\float\double。 - 10、Supports Function Codes: * Read Coils (FC1) * Read Discrete Inputs (FC2) * Read Holding Registers (FC3) * Read Input Registers (FC4) * Write Single Coil (FC5) * Write Single Register (FC6) * Write Multiple Coils (FC15) * Write Multiple Registers (FC16) * Read/Write Multiple Registers (FC23) ### repositories - Project Example Code : https://github.com/zengfr/easymodbus4j - Mvnrepository Repositories: [Repositories Central Sonatype Mvnrepository easymodbus4j](https://mvnrepository.com/artifact/com.github.zengfr/easymodbus4j) ``` artifactId/jar: easymodbus4j-core.jar Modbus protocol协议 easymodbus4j-codec.jar Modbus 通用编码器解码器 easymodbus4j.jar Modbus General/Common公共通用包 easymodbus4j-client.jar Modbus client客户端 easymodbus4j-server.jar Modbus server服务器端 easymodbus4j-extension.jar Modbus extension扩展包 ModbusMasterResponseProcessor/ModbusSlaveRequestProcessor interface ``` ### quick Start快速开发: #### 第一步step1 ,import jar: - 1.1 maven: ``` com.github.zengfr easymodbus4j-client 0.0.5 com.github.zengfr easymodbus4j-server 0.0.5 com.github.zengfr easymodbus4j-extension 0.0.5 ``` #### 第二步step2,implement handler: - 2.1 if master * 实现implement ResponseHandler接口 see easymodbus4j-example:ModbusMasterResponseHandler.java * or 实现implement ModbusMasterResponseProcessor 接口 use new ModbusMasterResponseHandler(responseProcessor); - 2.2 if slave * 实现implement RequestHandler接口 see easymodbus4j-example:ModbusSlaveRequestHandler.java * or 实现implement ModbusSlaveRequestProcessor 接口 use new ModbusSlaveRequestHandler(reqProcessor); #### 第三步step3, - 3.1 select one master/slave and client/server mode: ```java modbusServer = ModbusServerTcpFactory.getInstance().createServer4Master(port, responseHandler); modbusClient = ModbusClientTcpFactory.getInstance().createClient4Slave(host,port, requestHandler); modbusClient = ModbusClientTcpFactory.getInstance().createClient4Master(host, port, responseHandler); modbusServer = ModbusServerTcpFactory.getInstance().createServer4Slave(port, requestHandler); modbusServer = ModbusServerRtuFactory.getInstance().createServer4Master(port, responseHandler); modbusClient = ModbusClientRtuFactory.getInstance().createClient4Slave(host,port, requestHandler); modbusClient = ModbusClientRtuFactory.getInstance().createClient4Master(host, port, responseHandler); modbusServer = ModbusServerRtuFactory.getInstance().createServer4Slave(port, requestHandler); ``` #### 第四步step4 ,FAQs and advanced extensions: - 4.1 how to send a request ? to send data ```java Thread.sleep(3*1000);// sleep 3s before,when client or server open connection is async; Channel channel = client.getChannel()); Channel channel = server.getChannelsBy(...)); ChannelSender sender = ChannelSenderFactory.getInstance().get(channel); ChannelSender sender2 = new ChannelSender(channel,unitId,protocolIdentifier); sender.readCoils(...) sender.readDiscreteInputs(...) sender.writeSingleRegister(...) ``` - 4.2 how to process request/response? to receive data see code in processResponseFrame mothod in ModbusMasterResponseHandler.java or ModbusMasterResponseProcessor.java ```java public void processResponseFrame(Channel channel, int unitId, AbstractFunction reqFunc, ModbusFunction respFunc) { if (respFunc instanceof ReadCoilsResponse) { ReadCoilsResponse resp = (ReadCoilsResponse) respFunc; ReadCoilsRequest req = (ReadCoilsRequest) reqFunc; //process business logic for req/resp } }; ``` - 4.3 how to get response to byteArray for custom decode by yourself? see code in processResponseFrame mothod in ModbusMasterResponseHandler.java or ModbusMasterResponseProcessor.java ```java public void processResponseFrame(Channel channel, int unitId, AbstractFunction reqFunc, ModbusFunction respFunc) { if (respFunc instanceof ReadDiscreteInputsResponse) { ReadDiscreteInputsResponse resp = (ReadDiscreteInputsResponse) respFunc; byte[] resutArray = resp.getInputStatus().toByteArray(); } }; ``` - 4.4 how to show log? see ModbusMasterResponseHandler.java in example project. ```java ModbusFrameUtil.showFrameLog(logger, channel, frame); ``` - 4.5 how to custom a client/server advance by yourself? ```java ModbusChannelInitializer modbusChannelInitializer=...; ModbusServerTcpFactory.getInstance().createServer4Master(port,modbusChannelInitializer); ``` #### Example Project Code - example1 [example1](https://github.com/zengfr/easymodbus4j/tree/master/easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example) - example3 [example3](https://github.com/zengfr/easymodbus4j/tree/master/easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example3) - other example1 [other example1](https://gitee.com/zengfr/easymodbus4j/tree/master/easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example) - other example3 [other example3](https://gitee.com/zengfr/easymodbus4j/tree/master/easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example3) - client4Master demo:[client4Master demo]( https://gitee.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example3/Example3.java) [最佳简单快速参考实例][Best simple quick demo] - server4Master demo:[server4Master demo]( https://gitee.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example3/Example4.java)[最佳简单快速参考实例][Best simple quick demo] #### Example run startup: - 1、unzip file easymodbus4j-example-0.0.5-release.zip. - 2、for modbus master mode:open autosend.txt file in dir or autosend.txt rsourcefile in easymodbus4j-example-0.0.5.jar - 3、for modbus master mode:edit autosend.txt file - 4、start startup.bat. - 5、you also can edit *.bat for modbus master/salve mode: . #### Example实例说明: - 1、解压缩zip文件到文件夹 - 2、java程序 运行不了 则安装jdk8. - 3、解压后8个bat文件 对应TCP/RTU 服务器master,客户端slave,服务器slave,客户端master 8种模式. - 4、Master模式 可以设置autosend.txt文件,定时发送读写请求。 - 5、记事本打开bat文件可以编辑相关参数,如定时延时发送时间以及详细日志开关。 #### 开发实例系列教程Develop a series of tutorial examples [easymodbus4j 开发实例系列教程之1----客户端master模式](https://my.oschina.net/zengfr/blog/4304442)
[easymodbus4j 开发实例系列教程之2----服务端master模式](https://my.oschina.net/zengfr/blog/4305723)
#### capture demo 运行效果图截屏: ![easymodbus4j运行效果图截屏1](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture.PNG?raw=true) ![easymodbus4j运行效果图截屏2](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture2.PNG?raw=true) ![easymodbus4j运行效果图截屏3](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture3.PNG?raw=true) ![easymodbus4j运行效果图截屏4](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture4.PNG?raw=true) #### capture demo 运行效果图截屏2: ![easymodbus4j运行效果图截屏1](https://gitee.com/zengfr/easymodbus4j/raw/master/easymodbus4j-example/src/main/resources/capture.PNG?raw=true) ![easymodbus4j运行效果图截屏2](https://gitee.com/zengfr/easymodbus4j/raw/master/easymodbus4j-example/src/main/resources/capture2.PNG?raw=true) ![easymodbus4j运行效果图截屏3](https://gitee.com/zengfr/easymodbus4j/raw/master/easymodbus4j-example/src/main/resources/capture3.PNG?raw=true) ![easymodbus4j运行效果图截屏4](https://gitee.com/zengfr/easymodbus4j/raw/master/easymodbus4j-example/src/main/resources/capture4.PNG?raw=true) ================================================ FILE: easymodbus4j-commandclient/pom.xml ================================================ 4.0.0 com.github.zengfr easymodbus4j-commandclient 0.0.5 easymodbus4j-commandclient true 1.8 com.github.zengfr.project parent 0.0.2 ../parent/pom.xml junit junit test io.netty netty-all org.apache.httpcomponents httpclient commons-logging commons-logging org.slf4j jcl-over-slf4j ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/client/DeviceClient.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.client; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.Random; import com.github.zengfr.easymodbus4j.app.common.DeviceCommand; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class DeviceClient extends UdpClient { private static final int MAX = 10000 * 999; private static final int MIN = 10000 * 100; private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"); private static Random rnd = new Random(); private static class DeviceClientHolder { private static final DeviceClient INSTANCE = new DeviceClient(); } public static DeviceClient getInstance() { return DeviceClientHolder.INSTANCE; } private DeviceClient() { } public String sendCommand(String host, int port, DeviceCommand cmd) throws InterruptedException { String uuid = getUUID(); getSender().send(host, port, buildCommandMessage(uuid, cmd)); return uuid; } public String sendCommand(String host, int port, String msg) throws InterruptedException { String uuid = getUUID(); getSender().send(host, port, buildCommandMessage(uuid, msg)); return uuid; } protected String buildCommandMessage(String uuid, DeviceCommand cmd) { return buildCommandMessage(uuid, cmd.toString()); } protected String buildCommandMessage(String uuid, String cmd) { return String.format("%s;%s", uuid, cmd); } protected String getUUID() { int randNumber = rnd.nextInt(MAX - MIN + 1) + MIN; return String.format("%s%s", LocalDateTime.now(ZoneOffset.of("+8")).format(formatter), randNumber); } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/client/UdpClient.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.client; import com.github.zengfr.easymodbus4j.app.sender.UdpSender; import com.github.zengfr.easymodbus4j.app.sender.UdpSenderFactory; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioDatagramChannel; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class UdpClient { protected Channel channel; protected UdpSender sender; protected boolean isInit = false; public void setup(UdpClientHandler handler) throws InterruptedException { setup(handler, false); } public void setup(UdpClientHandler handler, boolean wait) throws InterruptedException { if (!isInit) { EventLoopGroup group = new NioEventLoopGroup(); Bootstrap b = new Bootstrap(); b.option(ChannelOption.SO_BROADCAST, true); b.group(group).channel(NioDatagramChannel.class).handler(handler); channel = b.bind(0).sync().channel(); sender = UdpSenderFactory.getInstance().get(channel); isInit = true; if (wait) { channel.closeFuture().await(); } } } public UdpSender getSender() { return this.sender; } public Channel getChannel() { return channel; } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/client/UdpClientHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.client; import org.apache.commons.lang3.StringUtils; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.socket.DatagramPacket; import io.netty.util.CharsetUtil; import io.netty.channel.ChannelHandler.Sharable; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ @Sharable public abstract class UdpClientHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception { if(isDoReceived()) { messageReceived(ctx, packet.content().toString(CharsetUtil.UTF_8)); } } protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception { if (StringUtils.isNotEmpty(msg)) { String[] args = msg.split(";"); if (args.length >= 11) { int success = Integer.valueOf(args[0]); String uuid = args[1]; String deviceId = args[2]; String ip = args[3]; Integer port = Integer.valueOf(args[4]); String version = args[5]; Integer functionCode = Integer.valueOf(args[6]); Integer address = Integer.valueOf(args[7]); String valueType = args[8]; String value = args[9]; String[] values = args[10].split(","); channelRead0(uuid, deviceId, ip, port, version, functionCode, address, valueType, value, values, success); values=null; } args=null; } } protected abstract boolean isDoReceived(); protected abstract void channelRead0(String uuid, String deviceId, String ip, Integer port, String version, Integer functionCode, Integer address, String valueType, String value, String[] values, int success) throws Exception; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/common/DeviceArg.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.common; public class DeviceArg { public String deviceId; public String ip; public int port; public String version; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/common/DeviceCommand.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.common; import org.apache.commons.lang3.StringUtils; public class DeviceCommand { /** 设备标识id(必选) */ private String deviceId; /** 设备ip(可选) */ private String ip; /** 设备port(可选) */ private int port; /** 设备型号(可选) */ private String version; /** 见classFunctionCode */ private int functionCode; /** 寄存器地址 */ private int address; /** 寄存器地址值 */ private T value; /** 寄存器地址值 */ private T[] values; /** 值类型 */ private String valueType; public String getDeviceId() { return this.deviceId; } public void setDeviceId(String deviceId) { this.deviceId = deviceId; } public String getIp() { return this.ip; } public void setIp(String ip) { this.ip = ip; } public int getPort() { return this.port; } public void setPort(int port) { this.port = port; } public String getVersion() { return this.version; } public void setVersion(String version) { this.version = version; } public int getFunctionCode() { return this.functionCode; } public void setFunctionCode(int functionCode) { this.functionCode = functionCode; } public int getAddress() { return this.address; } public void setAddress(int address) { this.address = address; } public T getValue() { return this.value; } public void setValue(T value) { this.value = value; syncValueType(); } public T[] getValues() { return this.values; } public void setValues(T[] values) { this.values = values; syncValueType(); } public void setValueType(String valueType) { this.valueType = valueType; } public String getValueType() { return valueType; } public void syncValueType() { setValueType(getValueType(this.value, this.values)); } @Override public String toString() { return String.format("%s;%s;%s;%s;%s;%s;%s;%s;%s", deviceId, ip, port, version, functionCode, address, getValueType(), value, StringUtils.join(values, ',')); } private static String getValueType(T v, T[] vv) { if (v != null && !v.toString().isEmpty()) { return v.getClass().getSimpleName(); } else if (vv != null && vv.length > 0) { return vv[0].getClass().getSimpleName(); } return ""; } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/common/FunctionCode.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.common; public class FunctionCode { public static final short READ_COILS = 0x01; public static final short READ_DISCRETE_INPUTS = 0x02; public static final short READ_HOLDING_REGISTERS = 0x03; public static final short READ_INPUT_REGISTERS = 0x04; public static final short WRITE_SINGLE_COIL = 0x05; public static final short WRITE_SINGLE_REGISTER = 0x06; public static final short READ_EXCEPTION_STATUS = 0x07; public static final short DIAGNOSTICS = 0x08; public static final short GET_COMM_EVENT_COUNTER = 0x0B; public static final short GET_COMM_EVENT_LOG = 0x0C; public static final short WRITE_MULTIPLE_COILS = 0x0F; public static final short WRITE_MULTIPLE_REGISTERS = 0x10; public static final short REPORT_SLAVEID = 0x11; public static final short READ_FILE_RECORD = 0x14; public static final short WRITE_FILE_RECORD = 0x15; public static final short MASK_WRITE_REGISTER = 0x16; public static final short READ_WRITE_MULTIPLE_REGISTERS = 0x17; public static final short READ_FIFO_QUEUE = 0x18; public static final short ENCAPSULATED_INTERFACE_TRANSPORT = 0x2B; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/gprs/juheApi.java ================================================ package com.github.zengfr.easymodbus4j.app.gprs; import com.alibaba.fastjson.JSON; import com.github.zengfr.easymodbus4j.app.util.HttpUtil; import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created by zengfr on 2020/11/26. */ public class juheApi { public static class Resp { public String mcc; public String mnc; public String lac; public String ci; public String lat; public String lon; public String address; public String radius; public String rcontent; } private final static String api = "https://v.juhe.cn/cell/Triangulation/query.php"; private final static String homePage = "https://www.juhe.cn/docs/api/id/8?bd_vid=7081628664865556502"; public static void main(String... args) throws IOException { for (int i = 0; i < 10; i++) { test(); } } public static void test() throws IOException { Resp resp = getGprs("4163", "21297934"); System.out.println(JSON.toJSONString(resp)); } public static Resp getGprs(String lac, String cId) throws IOException { return getGprs(lac, cId, false, "UTF-8"); } public static Resp getGprs(String lac, String cId, boolean isHex, String charest) throws IOException { String data = String.format("mcc=460&mnc=0&lac=%s&ci=%s&hex=%s", lac, cId, isHex ? 16 : 10); String org = "https://v.juhe.cn"; String contentString = HttpUtil.post(api, homePage, org, data, charest); String pat = "\"result\":(.*?)}"; Matcher m = Pattern.compile(pat).matcher(contentString); String result; Resp resp = new Resp(); if (m.find()) { result = m.group(1); if (result != null && !result.startsWith("null")) { resp = JSON.parseObject(result + "}", Resp.class); } } if (StringUtils.isEmpty(resp.address)) { resp.rcontent = contentString; } return resp; } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/gps/gprsData.java ================================================ package com.github.zengfr.easymodbus4j.app.gps; /** 基站信息结构体 */ public class gprsData{ public int MCC; public int MNC; public int LAC; public int CID; public int signal; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/gps/locapiBaiduClientUtil.java ================================================ package com.github.zengfr.easymodbus4j.app.gps; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.time.LocalDateTime; import java.time.ZoneOffset; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import com.alibaba.fastjson.JSON; import com.google.common.collect.Lists; /** * 智能硬件定位 可以通过蓝牙、WI-FI等获取用户定位数据 利用蓝牙、WI-FI等信息,传给服务端进行处理,获取定位信息,完成地图、路线规划、轨迹等功能 * http://lbsyun.baidu.com/index.php?title=webapi/intel-hardware-api * https://api.map.baidu.com/locapi/v2 根据mcc, mnc,lac,cellid访问百度接口 -gprs移动定位 * 适用于室内、室外多种定位场景,覆盖智能可穿戴设备、车载设备等。 */ public class locapiBaiduClientUtil { private static String api = "https://api.map.baidu.com/locapi/v2"; private static String apiKey = "z4Xg8Va4P2u1on5kjrU6ATGn2niaELgg"; public static void main(String... args) throws IOException { test(); } public static void test() throws IOException { String bts = "460,0,4163,21297934,-124"; parse(bts); gprsData r = new gprsData(); r.MCC = 0; r.MNC = 0; r.LAC = 0; r.CID = 0; r.signal = -1; parse(r); } public static locapiRespBody parse(gprsData r) throws IOException { String bts = String.format("%s,%s,%s,%s,%s", r.MCC, r.MNC, r.LAC, r.CID, r.signal); return parse(bts); } public static locapiRespBody parse(String bts) throws IOException { locapiReqBody body = new locapiReqBody(); body.setAccesstype(0);// 移动接入网络:0 wifi接入网络:1 仅gps坐标转换:2 body.setCdma(0);// 非cdma:0; cdma:1 默认值为:0 body.setNetwork("GPRS");// 无线网络类型 GSM/GPRS/EDGE/HSUPA/HSDPA/WCDMA (注意大写) body.setImei("18701966811"); body.setBts(bts); //非CDMA格式为:mcc, mnc,lac,cellid,signal //CDMA格式为:sid,nid,bid,lon,lat,signal 其中lon,lat可为空,格式为:sid,nid,bid,,,signal body.setNeed_rgc("Y");// 返回地址信息,默认不返回 Y : 返回rgc结果 N : 不返回rgc结果 body.setCtime("" + LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()); body.setOutput("JSON"); locapiReq req = new locapiReq(); req.setVer("1.0"); req.setTrace(false); req.setSrc("bdl"); req.setProd("bdl"); req.setKey(apiKey); req.setBody(Lists.newArrayList(body)); return parse(req); } protected static locapiRespBody parse(locapiReq req) throws IOException { StringBuffer sb = new StringBuffer(); HttpClient client = HttpClientBuilder.create().build(); HttpPost post = new HttpPost(api); String reqStr = JSON.toJSONString(req); StringEntity se = new StringEntity(reqStr); System.out.println(reqStr); post.setEntity(se); HttpResponse resp = client.execute(post); HttpEntity entity = resp.getEntity(); BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent())); String line = br.readLine(); while (line != null) { sb.append(line); line = br.readLine(); } System.out.println(sb);//740 Failed to authenticate for api loc is forbidden.(服务被禁用,一般不会出现) return JSON.parseObject(sb.toString(), locapiRespBody.class); } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/gps/locapiCellidClientUtil.java ================================================ package com.github.zengfr.easymodbus4j.app.gps; import com.alibaba.fastjson.JSON; import com.github.zengfr.easymodbus4j.app.util.HttpUtil; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.HttpClientBuilder; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; public class locapiCellidClientUtil { public static class Resp { public String lat; public String lng; public String title; } private final static String api = "http://www.cellid.cn/cidInfo.php?lac=%s&cell_id=%s&hex=false&flag=%s"; private final static String homePage = "http://www.cellid.cn/"; public static void main(String... args) throws IOException { test(); } public static void test() throws IOException { Resp resp = parseResp("13876", "1285714605", "UTF-8"); System.out.println(JSON.toJSONString(resp)); } public static Resp parseResp(String lac, String cId, String charest) throws IOException { // cidMap(39.941548,116.352661,'(4163,21297934) // 39.941548,116.352661
北京市西城区西外大街1号') String flag = getFlag(charest); String contentString = parse(lac, cId, flag, charest); Resp resp = new Resp(); String pat = "\\((.*?),(.*?),'(.*?)
(.*?)'"; Matcher m = Pattern.compile(pat).matcher(contentString); if (m.find()) { resp.lat = m.group(1); resp.lng = m.group(2); resp.title = m.group(4); } return resp; } protected static String getFlag(String charest) throws ClientProtocolException, IOException { String urlString = homePage; String contentString = HttpUtil.get(urlString,homePage,homePage,charest); Matcher m = Pattern.compile("").matcher(contentString); if (m.find()) { return m.group(1); } return ""; } protected static String parse(String lac, String cId, String flag, String charest) throws IOException { String urlString = String.format(api, lac, cId, flag); String content=HttpUtil.post (urlString,homePage,null,null,charest); return content; } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/gps/locapiReq.java ================================================ package com.github.zengfr.easymodbus4j.app.gps; import java.util.List; public class locapiReq { private String ver; private boolean trace; private String prod; private String src; private String key; private List body; public void setVer(String ver) { this.ver = ver; } public String getVer() { return ver; } public void setTrace(boolean trace) { this.trace = trace; } public boolean getTrace() { return trace; } public void setProd(String prod) { this.prod = prod; } public String getProd() { return prod; } public void setSrc(String src) { this.src = src; } public String getSrc() { return src; } public void setKey(String key) { this.key = key; } public String getKey() { return key; } public void setBody(List body) { this.body = body; } public List getBody() { return body; } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/gps/locapiReqBody.java ================================================ package com.github.zengfr.easymodbus4j.app.gps; public class locapiReqBody { private String bts; private String output; private int accesstype; private String macs; private String imei; private String ctime; private String nearbts; private int cdma; private String need_rgc; private String network; public void setBts(String bts) { this.bts = bts; } public String getBts() { return bts; } public void setOutput(String output) { this.output = output; } public String getOutput() { return output; } public void setAccesstype(int accesstype) { this.accesstype = accesstype; } public int getAccesstype() { return accesstype; } public void setMacs(String macs) { this.macs = macs; } public String getMacs() { return macs; } public void setImei(String imei) { this.imei = imei; } public String getImei() { return imei; } public void setCtime(String ctime) { this.ctime = ctime; } public String getCtime() { return ctime; } public void setNearbts(String nearbts) { this.nearbts = nearbts; } public String getNearbts() { return nearbts; } public void setCdma(int cdma) { this.cdma = cdma; } public int getCdma() { return cdma; } public void setNeed_rgc(String need_rgc) { this.need_rgc = need_rgc; } public String getNeed_rgc() { return need_rgc; } public void setNetwork(String network) { this.network = network; } public String getNetwork() { return network; } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/gps/locapiResp.java ================================================ package com.github.zengfr.easymodbus4j.app.gps; import java.util.List; public class locapiResp { private int errcode; private String msg; private List body; public void setErrcode(int errcode) { this.errcode = errcode; } public int getErrcode() { return errcode; } public void setMsg(String msg) { this.msg = msg; } public String getMsg() { return msg; } public void setBody(List body) { this.body = body; } public List getBody() { return body; } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/gps/locapiRespBody.java ================================================ package com.github.zengfr.easymodbus4j.app.gps; public class locapiRespBody { private int type; private String location; private int radius; private String country; private String province; private String city; private String citycode; private String district; private String road; private String ctime; private String indoor; private int error; public void setType(int type) { this.type = type; } public int getType() { return type; } public void setLocation(String location) { this.location = location; } public String getLocation() { return location; } public void setRadius(int radius) { this.radius = radius; } public int getRadius() { return radius; } public void setCountry(String country) { this.country = country; } public String getCountry() { return country; } public void setProvince(String province) { this.province = province; } public String getProvince() { return province; } public void setCity(String city) { this.city = city; } public String getCity() { return city; } public void setCitycode(String citycode) { this.citycode = citycode; } public String getCitycode() { return citycode; } public void setDistrict(String district) { this.district = district; } public String getDistrict() { return district; } public void setRoad(String road) { this.road = road; } public String getRoad() { return road; } public void setCtime(String ctime) { this.ctime = ctime; } public String getCtime() { return ctime; } public void setIndoor(String indoor) { this.indoor = indoor; } public String getIndoor() { return indoor; } public void setError(int error) { this.error = error; } public int getError() { return error; } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/access_tokenReq.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class access_tokenReq extends req { public String client_id; public String client_secret; public String grant_type; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/access_tokenResp.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class access_tokenResp { public String access_token; public String token_type; public String expires_in; public String scope; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/autosend_listReq.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class autosend_listReq extends req{ } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/autosend_listResp.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class autosend_listResp extends resp { } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/autosend_listRespItem.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class autosend_listRespItem { public String function; public Integer address; public Integer quantity; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/mainboard_adressResp.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class mainboard_adressResp extends resp { } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/mainboard_adressRespItem.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class mainboard_adressRespItem { public String model_no; public String function; public Integer address; public Integer quantity; public String datatype; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/req.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class req { public String access_token = ""; public String remotIp = ""; public String ip = ""; public Integer port = 0; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/resp.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; import java.util.List; public class resp { public String msg; public Integer status; public List results; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/update_modbus_valuesReq.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; import java.util.List; public class update_modbus_valuesReq extends req { public String mainboard_no; public Long time_stamp; public List items; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/update_modbus_valuesReqItem.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class update_modbus_valuesReqItem { public String function; public String address; /**hex*/ public String value; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/update_slaveipportReq.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class update_slaveipportReq extends req { public String mainboard_no; public String ip; public Integer port; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/repository/value.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; public class value { public String hex; public String bitset; public String byteStr; public String shortStr; public String longb; public String floatb; public String doubleb; public String charb; public String longl; public String floatl; public String doublel; public String charl; } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/sender/UdpSender.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.sender; import java.net.InetSocketAddress; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.socket.DatagramPacket; import io.netty.util.CharsetUtil; public class UdpSender { protected Channel channel; public UdpSender(Channel channel) { this.channel = channel; } public void send(DatagramPacket packet) throws InterruptedException { channel.writeAndFlush(packet).sync(); } public void send(String host, int port, String msg) throws InterruptedException { send(new InetSocketAddress(host, port), msg); } public void send(InetSocketAddress address, String msg) throws InterruptedException { send(address, Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8)); } public void send(String host, int port, ByteBuf byteBuf) throws InterruptedException { send(new InetSocketAddress(host, port), byteBuf); } public void send(InetSocketAddress address, ByteBuf byteBuf) throws InterruptedException { send(new DatagramPacket(byteBuf, address)); } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/sender/UdpSenderFactory.java ================================================ package com.github.zengfr.easymodbus4j.app.sender; import java.util.Map; import com.google.common.collect.Maps; import io.netty.channel.Channel; public class UdpSenderFactory { private static class UdpSenderFactoryHolder { private static final UdpSenderFactory INSTANCE = new UdpSenderFactory(); } public static UdpSenderFactory getInstance() { return UdpSenderFactoryHolder.INSTANCE; } private Map channelSendersMap = Maps.newHashMap(); public UdpSender get(Channel channel) { String key = channel.toString(); if (!channelSendersMap.containsKey(key)) { channelSendersMap.put(key, new UdpSender(channel)); } return channelSendersMap.get(key); } } ================================================ FILE: easymodbus4j-commandclient/src/main/java/com/github/zengfr/easymodbus4j/app/util/HttpUtil.java ================================================ package com.github.zengfr.easymodbus4j.app.util; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.*; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.util.EntityUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * Created by zengfr on 2020/11/26. */ public class HttpUtil { private static final CloseableHttpClient client ; private final static String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0"; static { PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setMaxTotal(500); connectionManager.setDefaultMaxPerRoute(255); connectionManager.setValidateAfterInactivity(10000); client = HttpClients.custom().setConnectionManager(connectionManager).build(); } public static String get(String urlString, String referer, String origin, String charest) throws IOException { HttpGet httpGet = new HttpGet(urlString); return exec( httpGet, referer, origin, null, charest); } public static String post(String urlString, String referer, String origin, String data, String charest) throws IOException { HttpPost post = new HttpPost(urlString); return exec( post, referer, origin, data, charest); } protected static String exec( HttpRequestBase req, String referer, String origin, String data, String charest) throws IOException { req.setHeader("User-Agent", userAgent); req.setHeader("Referer", referer); req.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=" + charest); req.setHeader("Sec-Fetch-Dest", "empty"); req.setHeader("Sec-Fetch-Mode", "cors"); req.setHeader("Sec-Fetch-Site", "same-origin"); if (origin != null) req.setHeader("Origin", origin); if (data != null) ((HttpEntityEnclosingRequest)req).setEntity(new StringEntity(data)); CloseableHttpResponse resp = client.execute(req); String content=getContent(resp, charest); EntityUtils.consume(resp.getEntity()); resp.close(); return content; } public static String getContent(HttpResponse resp, String charest) throws IOException { StringBuffer sb = new StringBuffer(); HttpEntity entity = resp.getEntity(); BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent(), charest)); String line = br.readLine(); while (line != null) { sb.append(line); line = br.readLine(); } return sb.toString(); } } ================================================ FILE: easymodbus4j-commandclient/src/main/resources/readme.txt ================================================ quick start client api 1: DeviceClient.sendCommand(String host, int port, DeviceCommand cmd); client api 2(when functionCode: WRITE_MULTIPLE_COILS = 0x0F; WRITE_MULTIPLE_REGISTERS = 0x10; DeviceClient.sendCommand2(String host, int port, DeviceCommand cmd); public class DeviceCommand { /** 设备标识id(必选) */ public String deviceId; /** 设备ip(可选) */ public String ip; /** 设备port(可选) */ public int port; /** 设备型号(可选) */ public String version; /** 见class FunctionCode */ public int functionCode; /** 寄存器地址 */ public int address; /** 寄存器地址值 */ public T value; /** 寄存器地址值 */ public T[] values; } ================================================ FILE: easymodbus4j-commandclient/src/test/java/ClientTest.java ================================================ import org.junit.BeforeClass; import org.junit.Test; import com.github.zengfr.easymodbus4j.app.client.DeviceClient; import com.github.zengfr.easymodbus4j.app.client.UdpClientHandler; import com.github.zengfr.easymodbus4j.app.common.DeviceCommand; import com.github.zengfr.easymodbus4j.app.common.FunctionCode; public class ClientTest { static UdpClientHandler handler = new CustomUdpClientHandler(); static DeviceClient client = DeviceClient.getInstance(); @BeforeClass public static void init() throws Exception { client.setup(handler); } @Test public void test() throws Exception { for (int i = 0; i < Integer.MAX_VALUE; i++) { System.out.println(i); Thread.sleep(111); for (int j = 0; j < 111; j++) { DeviceCommand cmd = new DeviceCommand<>(); cmd.setIp("11.22.33.44"); cmd.setPort(4199); cmd.setAddress(1); cmd.setFunctionCode(FunctionCode.WRITE_MULTIPLE_REGISTERS); cmd.setValue(Float.valueOf("12.6")); client.sendCommand("192.168.77.88", 54321, cmd); } } } } ================================================ FILE: easymodbus4j-commandclient/src/test/java/CustomUdpClientHandler.java ================================================ import com.github.zengfr.easymodbus4j.app.client.UdpClientHandler; public class CustomUdpClientHandler extends UdpClientHandler { @Override protected void channelRead0(String uuid, String deviceId, String ip, Integer port, String version, Integer functionCode, Integer address, String valueType, String value, String[] values, int success) throws Exception { } @Override protected boolean isDoReceived() { return false; } } ================================================ FILE: easymodbus4j-example/pom.xml ================================================ 4.0.0 com.github.zengfr easymodbus4j-example 0.0.5 easymodbus4j-example false com.github.zengfr.project parent 0.0.2 ../parent/pom.xml easymodbus4j-client com.github.zengfr 0.0.5 easymodbus4j-server com.github.zengfr 0.0.5 easymodbus4j-extension com.github.zengfr 0.0.5 net.logstash.logback logstash-logback-encoder 6.2 org.apache.maven.plugins maven-jar-plugin 1.8 1.8 com.github.zengfr.easymodbus4j.main.Example true libs/ org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 UTF-8 false ================================================ FILE: easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example/ModbusConfig.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.example; import com.alibaba.fastjson.JSON; import com.github.zengfr.easymodbus4j.ModbusConsts; import com.github.zengfr.easymodbus4j.common.util.ParseStringUtil; import com.github.zengfr.easymodbus4j.ModbusConfs; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class ModbusConfig { private static final InternalLogger logger = InternalLoggerFactory.getInstance(ModbusConfig.class); public int type; public String host; public int port; public boolean showDebugLog; public boolean autoSend; public int idleTimeOut; public int sleep; public short unit_IDENTIFIER; public short transactionIdentifierOffset; public int ignoreLengthThreshold; public String heartbeat; public int scheduleFixedDelay; public int udpPort; public static ModbusConfig parse(String[] argsArray) { ModbusConfig cfg = new ModbusConfig(); cfg.type = ParseStringUtil.parseInt(argsArray, 0, 0); cfg.host = ParseStringUtil.parseString(argsArray, 1, ModbusConsts.DEFAULT_HOTST_IP); cfg.port = ParseStringUtil.parseInt(argsArray, 2, ModbusConfs.DEFAULT_MODBUS_PORT); cfg.unit_IDENTIFIER = ParseStringUtil.parseShort(argsArray, 3, ModbusConsts.DEFAULT_UNIT_IDENTIFIER); cfg.transactionIdentifierOffset = ParseStringUtil.parseShort(argsArray, 4, (short) 0); cfg.showDebugLog = ParseStringUtil.parseBoolean(argsArray, 5, true); cfg.idleTimeOut = ParseStringUtil.parseInt(argsArray, 6, ModbusConfs.IDLE_TIMEOUT_SECOND); cfg.autoSend = ParseStringUtil.parseBoolean(argsArray, 7, true); cfg.sleep = ParseStringUtil.parseInt(argsArray, 8, 1000 * 15); cfg.heartbeat = ParseStringUtil.parseString(argsArray, 9, ModbusConsts.HEARTBEAT); cfg.ignoreLengthThreshold = ParseStringUtil.parseInt(argsArray, 10, ModbusConfs.RESPONS_EFRAME_IGNORE_LENGTH_THRESHOLD); cfg.udpPort = ParseStringUtil.parseInt(argsArray, 11, ModbusConfs.DEFAULT_MODBUS_PORT5); logger.info(JSON.toJSONString(cfg)); return cfg; } } ================================================ FILE: easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example/ModbusConsoleApp.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.example; import java.util.Collection; import io.netty.channel.Channel; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import com.github.zengfr.easymodbus4j.ModbusConsts; import com.github.zengfr.easymodbus4j.common.util.ConsoleUtil; import com.github.zengfr.easymodbus4j.common.util.ScheduledUtil; import com.github.zengfr.easymodbus4j.ModbusConfs; import com.github.zengfr.easymodbus4j.processor.ModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.processor.ModbusSlaveRequestProcessor; import com.github.zengfr.easymodbus4j.example.processor.ExampleModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.example.processor.ExampleModbusSlaveRequestProcessor; import com.github.zengfr.easymodbus4j.example.schedule.ModbusMasterSchedule4ConfigFile; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class ModbusConsoleApp { private static final InternalLogger logger = InternalLoggerFactory.getInstance(ModbusConsoleApp.class); public static void initAndStart(String[] argsArray) throws Exception { ModbusConfig config = ModbusConfig.parse(argsArray); start(config); } public static void start(ModbusConfig cfg) throws Exception { ModbusConsts.DEFAULT_UNIT_IDENTIFIER = cfg.unit_IDENTIFIER; ModbusConsts.HEARTBEAT=cfg.heartbeat; ModbusConfs.MASTER_SHOW_DEBUG_LOG = cfg.showDebugLog; ModbusConfs.SLAVE_SHOW_DEBUG_LOG = cfg.showDebugLog; ModbusConfs.IDLE_TIMEOUT_SECOND = cfg.idleTimeOut; ModbusConfs.RESPONS_EFRAME_IGNORE_LENGTH_THRESHOLD= cfg.ignoreLengthThreshold; ModbusMasterResponseProcessor masterProcessor = new ExampleModbusMasterResponseProcessor(cfg.transactionIdentifierOffset); ModbusSlaveRequestProcessor slaveProcessor = new ExampleModbusSlaveRequestProcessor(cfg.transactionIdentifierOffset); ModbusSetup setup = new ModbusSetup(); setup.initProperties(); setup.initHandler(masterProcessor, slaveProcessor); int port = cfg.port; boolean autoSend = cfg.autoSend; String host = cfg.host; int sleep = cfg.sleep; switch (cfg.type) { case 6: setup.setupServer4RtuMaster(port); sendRequests4Auto(autoSend, sleep, setup.getModbusServer().getChannels()); break; case 7: setup.setupClient4RtuSlave(host, port); break; case 8: setup.setupClient4RtuMaster(host, port); sendRequests4Auto(autoSend, sleep, setup.getModbusClient().getChannels()); break; case 9: setup.setupServer4RtuSlave(port); break; case 5: ModbusConfs.SLAVE_SHOW_DEBUG_LOG = false; setup.setupServer4RtuMaster(port); setup.setupClient4RtuSlave(host, port); sendRequests4Auto(autoSend, sleep, setup.getModbusServer().getChannels()); break; case 1: setup.setupServer4TcpMaster(port); sendRequests4Auto(autoSend, sleep, setup.getModbusServer().getChannels()); break; case 2: setup.setupClient4TcpSlave(host, port); break; case 3: setup.setupClient4TcpMaster(host, port); sendRequests4Auto(autoSend, sleep, setup.getModbusClient().getChannels()); break; case 4: setup.setupServer4TcpSlave(port); break; default: ModbusConfs.SLAVE_SHOW_DEBUG_LOG = false; setup.setupServer4TcpMaster(port); setup.setupClient4TcpSlave(host, port); sendRequests4Auto(autoSend, sleep, setup.getModbusServer().getChannels()); break; } Runnable runnable = () -> ConsoleUtil.clearConsole(true); ScheduledUtil.getInstance().scheduleAtFixedRate(runnable, sleep * 5); } protected static void sendRequests4Auto(boolean autoSend, int sleep, Collection channels) throws InterruptedException { if (autoSend) { ModbusMasterSchedule4ConfigFile modbusMasterAutoSender4ConfigFile = new ModbusMasterSchedule4ConfigFile(); modbusMasterAutoSender4ConfigFile.schedule(channels, sleep); } } } ================================================ FILE: easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example/ModbusSetup.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.example; import com.github.zengfr.easymodbus4j.client.ModbusClient; import com.github.zengfr.easymodbus4j.client.ModbusClientRtuFactory; import com.github.zengfr.easymodbus4j.client.ModbusClientTcpFactory; import com.github.zengfr.easymodbus4j.handle.impl.ModbusMasterResponseHandler; import com.github.zengfr.easymodbus4j.handle.impl.ModbusSlaveRequestHandler; import com.github.zengfr.easymodbus4j.handler.ModbusRequestHandler; import com.github.zengfr.easymodbus4j.handler.ModbusResponseHandler; import com.github.zengfr.easymodbus4j.processor.ModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.processor.ModbusSlaveRequestProcessor; import com.github.zengfr.easymodbus4j.server.ModbusServer; import com.github.zengfr.easymodbus4j.server.ModbusServerRtuFactory; import com.github.zengfr.easymodbus4j.server.ModbusServerTcpFactory; import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.Slf4JLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class ModbusSetup { private static final int sleep = 1000; private ModbusClient modbusClient; private ModbusServer modbusServer; private ModbusRequestHandler requestHandler; private ModbusResponseHandler responseHandler; public ModbusSetup() { } public ModbusClient getModbusClient() { return this.modbusClient; } public ModbusServer getModbusServer() { return this.modbusServer; } public void initProperties() throws Exception { InternalLoggerFactory.setDefaultFactory(Slf4JLoggerFactory.INSTANCE); System.setProperty("io.netty.tryReflectionSetAccessible", "true"); // System.setProperty("io.netty.noUnsafe", "false"); // ReferenceCountUtil.release(byteBuf); // ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED); } public void initHandler(ModbusResponseHandler responseHandler, ModbusRequestHandler requestHandler) throws Exception { this.requestHandler = requestHandler; this.responseHandler = responseHandler; } public void initHandler(ModbusMasterResponseProcessor masterProcessor, ModbusSlaveRequestProcessor slaveProcessor) throws Exception { this.requestHandler = new ModbusSlaveRequestHandler(slaveProcessor); this.responseHandler = new ModbusMasterResponseHandler(masterProcessor); } public void setupServer4TcpMaster(int port) throws Exception { modbusServer = ModbusServerTcpFactory.getInstance().createServer4Master(port, responseHandler); } public void setupServer4TcpSlave(int port) throws Exception { modbusServer = ModbusServerTcpFactory.getInstance().createServer4Slave(port, requestHandler); } public void setupClient4TcpSlave(String host, int port) throws Exception { Thread.sleep(sleep); modbusClient = ModbusClientTcpFactory.getInstance().createClient4Slave(host, port, requestHandler); } public void setupClient4TcpMaster(String host, int port) throws Exception { Thread.sleep(sleep); modbusClient = ModbusClientTcpFactory.getInstance().createClient4Master(host, port, responseHandler); } public void setupServer4RtuMaster(int port) throws Exception { modbusServer = ModbusServerRtuFactory.getInstance().createServer4Master(port, responseHandler); } public void setupServer4RtuSlave(int port) throws Exception { modbusServer = ModbusServerRtuFactory.getInstance().createServer4Slave(port, requestHandler); } public void setupClient4RtuSlave(String host, int port) throws Exception { Thread.sleep(sleep); modbusClient = ModbusClientRtuFactory.getInstance().createClient4Slave(host, port, requestHandler); } public void setupClient4RtuMaster(String host, int port) throws Exception { Thread.sleep(sleep); modbusClient = ModbusClientRtuFactory.getInstance().createClient4Master(host, port, responseHandler); } } ================================================ FILE: easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example/processor/ExampleModbusMasterResponseProcessor.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.github.zengfr.easymodbus4j.example.processor; import com.github.zengfr.easymodbus4j.func.AbstractRequest; import com.github.zengfr.easymodbus4j.func.request.ReadCoilsRequest; import com.github.zengfr.easymodbus4j.func.request.ReadDiscreteInputsRequest; import com.github.zengfr.easymodbus4j.func.response.ReadCoilsResponse; import com.github.zengfr.easymodbus4j.func.response.ReadDiscreteInputsResponse; import com.github.zengfr.easymodbus4j.handle.impl.ModbusMasterResponseHandler; import com.github.zengfr.easymodbus4j.processor.AbstractModbusProcessor; import com.github.zengfr.easymodbus4j.processor.ModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.protocol.ModbusFunction; import com.github.zengfr.easymodbus4j.util.ModbusFunctionUtil; import io.netty.channel.Channel; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class ExampleModbusMasterResponseProcessor extends AbstractModbusProcessor implements ModbusMasterResponseProcessor { private static final InternalLogger logger = InternalLoggerFactory.getInstance(ExampleModbusMasterResponseProcessor.class); public ExampleModbusMasterResponseProcessor(short transactionIdentifierOffset) { super(transactionIdentifierOffset, true); } public boolean processResponseFrame(Channel channel, int unitId, AbstractRequest reqFunc, ModbusFunction respFunc) { boolean success=this.isRequestResponseMatch(reqFunc, respFunc); if (respFunc instanceof ReadCoilsResponse) { ReadCoilsResponse resp = (ReadCoilsResponse) respFunc; if (reqFunc instanceof ReadCoilsRequest) { ReadCoilsRequest req = (ReadCoilsRequest) reqFunc; // process business logic success=true; } } if (respFunc instanceof ReadDiscreteInputsResponse) { ReadDiscreteInputsResponse resp = (ReadDiscreteInputsResponse) respFunc; byte[] resutArray = resp.getInputStatus().toByteArray(); byte[] valuesArray = ModbusFunctionUtil.getFunctionValues(respFunc); if (reqFunc instanceof ReadDiscreteInputsRequest) { ReadDiscreteInputsRequest req = (ReadDiscreteInputsRequest) reqFunc; // process business logic success=true; } } logger.debug(String.format("success:%s", success)); return success; }; } ================================================ FILE: easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example/processor/ExampleModbusSlaveRequestProcessor.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.example.processor; import java.util.BitSet; import java.util.Random; import com.github.zengfr.easymodbus4j.common.util.BitSetUtil; import com.github.zengfr.easymodbus4j.common.util.RegistersUtil; import com.github.zengfr.easymodbus4j.func.request.ReadCoilsRequest; import com.github.zengfr.easymodbus4j.func.request.ReadDiscreteInputsRequest; import com.github.zengfr.easymodbus4j.func.request.ReadHoldingRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.ReadInputRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.WriteMultipleCoilsRequest; import com.github.zengfr.easymodbus4j.func.request.WriteMultipleRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.WriteSingleCoilRequest; import com.github.zengfr.easymodbus4j.func.request.WriteSingleRegisterRequest; import com.github.zengfr.easymodbus4j.func.response.ReadCoilsResponse; import com.github.zengfr.easymodbus4j.func.response.ReadDiscreteInputsResponse; import com.github.zengfr.easymodbus4j.func.response.ReadHoldingRegistersResponse; import com.github.zengfr.easymodbus4j.func.response.ReadInputRegistersResponse; import com.github.zengfr.easymodbus4j.func.response.WriteMultipleCoilsResponse; import com.github.zengfr.easymodbus4j.func.response.WriteMultipleRegistersResponse; import com.github.zengfr.easymodbus4j.func.response.WriteSingleCoilResponse; import com.github.zengfr.easymodbus4j.func.response.WriteSingleRegisterResponse; import com.github.zengfr.easymodbus4j.processor.AbstractModbusProcessor; import com.github.zengfr.easymodbus4j.processor.ModbusSlaveRequestProcessor; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class ExampleModbusSlaveRequestProcessor extends AbstractModbusProcessor implements ModbusSlaveRequestProcessor { private static final InternalLogger logger = InternalLoggerFactory.getInstance(ExampleModbusSlaveRequestProcessor.class); protected static Random random = new Random(); public ExampleModbusSlaveRequestProcessor(short transactionIdentifierOffset) { super(transactionIdentifierOffset, true); } @Override public WriteSingleCoilResponse writeSingleCoil(short unitIdentifier, WriteSingleCoilRequest request) { return new WriteSingleCoilResponse(request.getOutputAddress(), request.isState()); } @Override public WriteSingleRegisterResponse writeSingleRegister(short unitIdentifier, WriteSingleRegisterRequest request) { return new WriteSingleRegisterResponse(request.getRegisterAddress(), request.getRegisterValue()); } @Override public ReadCoilsResponse readCoils(short unitIdentifier, ReadCoilsRequest request) { BitSet coils = new BitSet(request.getQuantityOfCoils()); coils = BitSetUtil.getRandomBits(request.getQuantityOfCoils(), random); if (coils.size() > 0 && random.nextInt(99) < 66) coils.set(0, false); return new ReadCoilsResponse(coils); } @Override public ReadDiscreteInputsResponse readDiscreteInputs(short unitIdentifier, ReadDiscreteInputsRequest request) { BitSet coils = new BitSet(request.getQuantityOfCoils()); coils = BitSetUtil.getRandomBits(request.getQuantityOfCoils(), random); //coils.set(0,79,false); //coils.set(0,true); return new ReadDiscreteInputsResponse(coils); } @Override public ReadInputRegistersResponse readInputRegisters(short unitIdentifier, ReadInputRegistersRequest request) { int[] registers = new int[request.getQuantityOfInputRegisters()]; registers = RegistersUtil.getRandomRegisters(registers.length, 1, 1024, random); return new ReadInputRegistersResponse(registers); } @Override public ReadHoldingRegistersResponse readHoldingRegisters(short unitIdentifier, ReadHoldingRegistersRequest request) { int[] registers = new int[request.getQuantityOfInputRegisters()]; registers = RegistersUtil.getRandomRegisters(registers.length, 1, 1024, random); // RegistersFactory.getInstance().getOrInit(unitIdentifier).getHoldingRegister(request.getStartingAddress()); return new ReadHoldingRegistersResponse(registers); } @Override public WriteMultipleCoilsResponse writeMultipleCoils(short unitIdentifier, WriteMultipleCoilsRequest request) { return new WriteMultipleCoilsResponse(request.getStartingAddress(), request.getQuantityOfOutputs()); } @Override public WriteMultipleRegistersResponse writeMultipleRegisters(short unitIdentifier, WriteMultipleRegistersRequest request) { // RegistersFactory.getInstance().getOrInit(unitIdentifier).setHoldingRegister(request.getStartingAddress(), // request.getRegisters()); return new WriteMultipleRegistersResponse(request.getStartingAddress(), request.getQuantityOfRegisters()); } } ================================================ FILE: easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example/schedule/ModbusMasterSchedule4ConfigFile.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.example.schedule; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.zengfr.easymodbus4j.common.util.FileUtil; import com.github.zengfr.easymodbus4j.common.util.InputStreamUtil; import com.github.zengfr.easymodbus4j.schedule.ModbusMasterSchedule; import com.github.zengfr.easymodbus4j.sender.util.ModbusRequestSendUtil.PriorityStrategy; import com.google.common.collect.Lists; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class ModbusMasterSchedule4ConfigFile extends ModbusMasterSchedule { private static Logger logger = LoggerFactory .getLogger(ModbusMasterSchedule4ConfigFile.class.getSimpleName()); protected static String configFileName = "autoSend.txt"; @Override protected int getFixedDelay() { return 0; } @Override protected PriorityStrategy getPriorityStrategy() { return PriorityStrategy.Channel; } @Override protected Logger getLogger() { return logger; } @Override protected List buildReqsList() { return parseReqs(); } protected static List parseReqs() { List configStrings = readConfig("/" + configFileName); List reqStrings = parseReqs(configStrings); return reqStrings; } protected static List parseReqs(List configStrings) { List reqStrings = Lists.newArrayList(configStrings); if (!configStrings.isEmpty()) { reqStrings.remove(0); } return reqStrings; } protected static List readConfig(String fileName) { logger.info("readConfig:" + fileName); List strList = Lists.newArrayList(); try { InputStream input = InputStreamUtil.getStream(fileName); if (input != null) strList = FileUtil.readLines(input, StandardCharsets.UTF_8); } catch (IOException ex) { logger.error("readConfig:" + fileName + " ex:", ex); } return strList; } } ================================================ FILE: easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example3/Example3.java ================================================ package com.github.zengfr.easymodbus4j.example3; import com.github.zengfr.easymodbus4j.ModbusConfs; import com.github.zengfr.easymodbus4j.client.ModbusClient4TcpMaster; import com.github.zengfr.easymodbus4j.client.ModbusClientTcpFactory; import com.github.zengfr.easymodbus4j.common.util.ConsoleUtil; import com.github.zengfr.easymodbus4j.common.util.ScheduledUtil; import com.github.zengfr.easymodbus4j.example.processor.ExampleModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.handle.impl.ModbusMasterResponseHandler; import com.github.zengfr.easymodbus4j.handler.ModbusResponseHandler; import com.github.zengfr.easymodbus4j.processor.ModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.sender.ChannelSender; import com.github.zengfr.easymodbus4j.sender.ChannelSenderFactory; import io.netty.channel.Channel; public class Example3 { private static ModbusClient4TcpMaster modbusClient; public static void main(String[] args) throws Exception { initClient(); scheduleToSendData(); //1\ ChannelSender to send data to machine //2\ ExampleModbusMasterResponseProcessor to receive resp data. } private static void initClient() throws Exception { String host="123.145.167.189"; int port=502; long sleep=3000; short transactionIdentifierOffset=0; ModbusConfs.MASTER_SHOW_DEBUG_LOG = true; ModbusMasterResponseProcessor masterProcessor=new ExampleModbusMasterResponseProcessor(transactionIdentifierOffset); ModbusResponseHandler responseHandler = new ModbusMasterResponseHandler(masterProcessor);; modbusClient = ModbusClientTcpFactory.getInstance().createClient4Master(host, port, responseHandler); Thread.sleep(sleep); } private static void scheduleToSendData() { Runnable runnable = () ->{ ConsoleUtil.clearConsole(true); Channel channel = modbusClient.getChannel(); if(channel==null||(!channel.isActive())||!channel.isOpen()||!channel.isWritable()) return; ChannelSender sender = ChannelSenderFactory.getInstance().get(channel); //short unitIdentifier=1; //ChannelSender sender2 =new ChannelSender(channel, unitIdentifier); int startAddress=0; int quantityOfCoils=4; try { sender.readCoilsAsync(startAddress, quantityOfCoils); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }; int sleep=1000; ScheduledUtil.getInstance().scheduleAtFixedRate(runnable, sleep * 5); } } ================================================ FILE: easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example3/Example4.java ================================================ package com.github.zengfr.easymodbus4j.example3; import java.util.Collection; import com.github.zengfr.easymodbus4j.ModbusConfs; import com.github.zengfr.easymodbus4j.common.util.ConsoleUtil; import com.github.zengfr.easymodbus4j.common.util.ScheduledUtil; import com.github.zengfr.easymodbus4j.example.processor.ExampleModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.handle.impl.ModbusMasterResponseHandler; import com.github.zengfr.easymodbus4j.handler.ModbusResponseHandler; import com.github.zengfr.easymodbus4j.processor.ModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.sender.ChannelSender; import com.github.zengfr.easymodbus4j.sender.ChannelSenderFactory; import com.github.zengfr.easymodbus4j.server.ModbusServer4TcpMaster; import com.github.zengfr.easymodbus4j.server.ModbusServerTcpFactory; import io.netty.channel.Channel; public class Example4 { private static ModbusServer4TcpMaster modbusServer; public static void main(String[] args) throws Exception { initServer(); scheduleToSendData(); // 1\ ChannelSender to send data to machine // 2\ ExampleModbusMasterResponseProcessor to receive resp data. } private static void initServer() throws Exception { int port = 502; long sleep = 3000; short transactionIdentifierOffset = 0; ModbusConfs.MASTER_SHOW_DEBUG_LOG = true; ModbusMasterResponseProcessor masterProcessor = new ExampleModbusMasterResponseProcessor( transactionIdentifierOffset); ModbusResponseHandler responseHandler = new ModbusMasterResponseHandler(masterProcessor); ; modbusServer = ModbusServerTcpFactory.getInstance().createServer4Master(port, responseHandler); Thread.sleep(sleep); } private static void scheduleToSendData() { Runnable runnable = () -> { ConsoleUtil.clearConsole(true); Collection channels = modbusServer.getChannels(); for (Channel channel : channels) { if (channel == null || (!channel.isActive()) || !channel.isOpen() || !channel.isWritable()) return; ChannelSender sender = ChannelSenderFactory.getInstance().get(channel); // short unitIdentifier=1; // ChannelSender sender2 =new ChannelSender(channel, unitIdentifier); int startAddress = 0; int quantityOfCoils = 4; try { sender.readCoilsAsync(startAddress, quantityOfCoils); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; int sleep = 1000; ScheduledUtil.getInstance().scheduleAtFixedRate(runnable, sleep * 5); } } ================================================ FILE: easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/main/Example.java ================================================ package com.github.zengfr.easymodbus4j.main; import com.github.zengfr.easymodbus4j.example.ModbusConsoleApp; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class Example { public static void main(String[] args) throws Exception { if (args == null || args.length <= 0) args = new String[] { "" }; String[] argsArray = args[0].split("[,;|]"); ModbusConsoleApp.initAndStart(argsArray); } } ================================================ FILE: easymodbus4j-example/src/main/resources/autoSend.txt ================================================ #function|address|values|#function autoSend every time for sleep time end when autoSend=T readCoilsAsync|81|1 readHoldingRegistersAsync|33|17 readInputRegisters|49|18 readDiscreteInputs|65|16 writeSingleCoil|17|F writeSingleRegister|18|22 writeMultipleCoils|25|T,F,T,F,T,T writeMultipleRegisters|24|1,3,5,7,14 #writeSingleCoil|19|T #writeSingleRegister|97|33 ================================================ FILE: easymodbus4j-example/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS}|%-5level|%thread|%logger{64}-%msg%n 127.0.0.1 4561 true 127.0.0.1 7071 channel default DEBUG log/debug-%d{yyyy-MM-dd}-%i-${channel}.log 20MB 31 2GB true %d{HH:mm:ss.SSS}|%-5level|%thread|%logger{64}-%msg%n channel default INFO ACCEPT DENY log/info-%d{yyyy-MM-dd}-%i-${channel}.log 20MB 31 2GB true %d{HH:mm:ss.SSS}|%-5level|%thread|%logger{64}-%msg%n channel default WARN log/warn-%d{yyyy-MM-dd}-%i-${channel}.log 20MB 31 %d{HH:mm:ss.SSS}|%-5level|%thread|%logger{64}-%msg%n 0 512 true 0 512 true 0 512 true ================================================ FILE: easymodbus4j-example/src/main/resources/readme.txt ================================================ ![easymodbus4j运行效果图截屏](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture.PNG?raw=true) # easymodbus4j easymodbus4j是一个高性能和易用的 Modbus 协议的 Java 实现,基于 Netty 开发,可用于 Modbus协议的Java客户端和服务器开发. easymodbus4j A high-performance and ease-of-use implementation of the Modbus protocol written in Java netty support for modbus 8 mode client/server and master/slave.
easymodbus4j 特点:
1、Netty NIO high performance高性能.
2、Modbus Function sync/aync 同步/异步非阻塞。
3、Modbus IoT Data Connector Supports工业物联网平台IoT支持。
4、支持Modbus TCP\Modbus RTU protocol两种通信协议.
5、灵活架构,支持8种生产部署模式,自由组合,满足不同生产要求.
6、通用组件包,支持高度自定义接口.
7、完全支持Modbus TCP 4种部署模式: TCP服务器master,TCP客户端slave,TCP服务器slave,TCP客户端master。
8、完全支持Modbus RTU 4种部署模式: RTU服务器master,RTU客户端slave,RTU服务器slave,RTU客户端master。
9、友好的调试以及日志支持bit\bitset\byte\short\int\float\double。
10、Supports Function Codes:
Read Coils (FC1)
Read Discrete Inputs (FC2)
Read Holding Registers (FC3)
Read Input Registers (FC4)
Write Single Coil (FC5)
Write Single Register (FC6)
Write Multiple Coils (FC15)
Write Multiple Registers (FC16)
Read/Write Multiple Registers (FC23)
#Example Project Code in https://github.com/zengfr/easymodbus4j [Repositories Central Sonatype Mvnrepository easymodbus4j](https://mvnrepository.com/artifact/com.github.zengfr/easymodbus4j) ``` artifactId/jar: easymodbus4j-core.jar Modbus protocol协议 easymodbus4j-codec.jar Modbus 通用编码器解码器 easymodbus4j.jar Modbus General/Common公共通用包 easymodbus4j-client.jar Modbus client客户端 easymodbus4j-server.jar Modbus server服务器端 easymodbus4j-extension.jar Modbus extension扩展包 ModbusMasterResponseProcessor/ModbusSlaveRequestProcessor interface ``` ``` 快速开发Quick Start: 第一步step1 ,import jar: maven: com.github.zengfr easymodbus4j-client 0.0.5 com.github.zengfr easymodbus4j-server 0.0.5 com.github.zengfr easymodbus4j-extension 0.0.5 第二步step2, implement handler: 2.1 if master 实现implement ResponseHandler接口 see easymodbus4j-example:ModbusMasterResponseHandler.java or 实现implement ModbusMasterResponseProcessor 接口 use new ModbusMasterResponseHandler(responseProcessor); 2.2 if slave 实现implement RequestHandler接口 see easymodbus4j-example:ModbusSlaveRequestHandler.java or 实现implement ModbusSlaveRequestProcessor 接口 use new ModbusSlaveRequestHandler(reqProcessor); 第三步step3, select one master/slave client/server mode: modbusServer = ModbusServerTcpFactory.getInstance().createServer4Master(port, responseHandler); modbusClient = ModbusClientTcpFactory.getInstance().createClient4Slave(host,port, requestHandler); modbusClient = ModbusClientTcpFactory.getInstance().createClient4Master(host, port, responseHandler); modbusServer = ModbusServerTcpFactory.getInstance().createServer4Slave(port, requestHandler); modbusServer = ModbusServerRtuFactory.getInstance().createServer4Master(port, responseHandler); modbusClient = ModbusClientRtuFactory.getInstance().createClient4Slave(host,port, requestHandler); modbusClient = ModbusClientRtuFactory.getInstance().createClient4Master(host, port, responseHandler); modbusServer = ModbusServerRtuFactory.getInstance().createServer4Slave(port, requestHandler); 第四步step4: 4.1 how to send a request ? Channel channel = client.getChannel()); Channel channel = server.getChannelsBy(...)); ChannelSender sender = ChannelSenderFactory.getInstance().get(channel); sender.readCoils(...) sender.readDiscreteInputs(...) sender.writeSingleRegister(...) 4.2 how to process request/response? see code in processResponseFrame mothod in ModbusMasterResponseHandler.java or ModbusMasterResponseProcessor.java public void processResponseFrame(Channel channel, int unitId, AbstractFunction reqFunc, ModbusFunction respFunc) { if (respFunc instanceof ReadCoilsResponse) { ReadCoilsResponse resp = (ReadCoilsResponse) respFunc; ReadCoilsRequest req = (ReadCoilsRequest) reqFunc; //process business logic for req/resp } }; 4.3 how to get response to byteArray for custom decode by yourself? see code in processResponseFrame mothod in ModbusMasterResponseHandler.java or ModbusMasterResponseProcessor.java public void processResponseFrame(Channel channel, int unitId, AbstractFunction reqFunc, ModbusFunction respFunc) { if (respFunc instanceof ReadDiscreteInputsResponse) { ReadDiscreteInputsResponse resp = (ReadDiscreteInputsResponse) respFunc; byte[] resutArray = resp.getInputStatus().toByteArray(); } }; 4.4 how to show log? see ModbusMasterResponseHandler.java in example project. ModbusFrameUtil.showFrameLog(logger, channel, frame); 4.5 how to custom a client/server advance by yourself? ModbusChannelInitializer modbusChannelInitializer=...; ModbusServerTcpFactory.getInstance().createServer4Master(port,modbusChannelInitializer); ``` #Example Project Code [master/easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example](https://github.com/zengfr/easymodbus4j/tree/master/easymodbus4j-example/src/main/java/com/github/zengfr/easymodbus4j/example)
Example run startup:
1、unzip file easymodbus4j-example-0.0.5-release.zip.
2、for modbus master mode:open autosend.txt file in dir or autosend.txt rsourcefile in easymodbus4j-example-0.0.5.jar 
3、for modbus master mode:edit autosend.txt file
4、start startup.bat.
5、you also can edit *.bat for modbus master/salve mode: .
说明:
1、解压缩zip文件到文件夹
2、java程序 运行不了 则安装jdk8.
3、解压后8个bat文件  对应TCP/RTU 服务器master,客户端slave,服务器slave,客户端master 8种模式.
4、Master模式 可以设置autosend.txt文件,定时发送读写请求。
5、记事本打开bat文件可以编辑相关参数,如定时延时发送时间以及详细日志开关。
capture运行效果图截屏: ![easymodbus4j运行效果图截屏1](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture.PNG?raw=true) ![easymodbus4j运行效果图截屏2](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture2.PNG?raw=true) ![easymodbus4j运行效果图截屏3](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture3.PNG?raw=true) ![easymodbus4j运行效果图截屏4](https://github.com/zengfr/easymodbus4j/blob/master/easymodbus4j-example/src/main/resources/capture4.PNG?raw=true) ================================================ FILE: easymodbus4j-example/src/main/resources/start0-Server4TcpMaster-Client4TcpSlave.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 0,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/start1-Server4TcpMaster.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 1,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/start2-Client4TcpSlave.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 2,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/start3-Client4TcpMaster.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 3,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/start4-Server4TcpSlave.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 4,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/start5-Server4RtuMaster-Client4RtuSlave.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 5,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/start6-Server4RtuMaster.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 6,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/start7-Client4RtuSlave.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 7,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/start8-Client4RtuMaster.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 8,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/start9-Server4RtuSlave.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example-0.0.1.jar 8,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example/src/main/resources/zip.xml ================================================ release zip ${project.basedir}\src\main\resources *.java zip.xml \ ${project.basedir}\target *.jar *-sources.jar \ false libs runtime ================================================ FILE: easymodbus4j-example/src/test/java/com/github/zengfr/easymodbus4j/AppTest.java ================================================ package com.github.zengfr.easymodbus4j; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import com.github.zengfr.easymodbus4j.logging.ChannelLogger; import com.github.zengfr.easymodbus4j.main.Example; public class AppTest { final static ChannelLogger logger=ChannelLogger.getLogger(AppTest.class); final static Logger logger2=LoggerFactory.getLogger(AppTest.class); @Test public void testLogger() throws Exception { logger.debug(null, "test", "test"); MDC.put("channel","test2"); logger2.debug("1234567"); } @Test public void test4TcpMaster() throws Exception { Example.main(new String[] { "1,127.0.0.1,502,1,0,T,0,T,12000,54321" }); System.in.read(); } @Test public void test4TcpClient() throws Exception { //Example.main(new String[] { "2,127.0.0.1,502,1,0,T,0,T,12000,54321" }); //System.in.read(); } } ================================================ FILE: easymodbus4j-example2/pom.xml ================================================ 4.0.0 com.github.zengfr easymodbus4j-example2 0.0.5 easymodbus4j-example2 false com.github.zengfr.project parent 0.0.2 ../parent/pom.xml easymodbus4j-commandclient com.github.zengfr 0.0.5 easymodbus4j-example com.github.zengfr 0.0.5 org.apache.httpcomponents httpclient commons-logging commons-logging org.slf4j jcl-over-slf4j org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 UTF-8 false org.apache.maven.plugins maven-jar-plugin 1.8 1.8 com.github.zengfr.easymodbus4j.main.Example2 true libs/ ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/ModbusServer4MasterApp.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app; import java.util.Collection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.zengfr.easymodbus4j.ModbusConsts; import com.github.zengfr.easymodbus4j.app.plugin.DeviceCommandPluginRegister; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPluginRegister; import com.github.zengfr.easymodbus4j.app.plugin.impl.DeviceCommandV1PluginImpl; import com.github.zengfr.easymodbus4j.app.plugin.impl.DeviceRepositoryV1PluginImpl; import com.github.zengfr.easymodbus4j.app.processor.CustomModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.app.schedule.ModbusMasterSchedule4All; import com.github.zengfr.easymodbus4j.app.schedule.ModbusMasterSchedule4DeviceId; import com.github.zengfr.easymodbus4j.app.server.udp.UdpServer; import com.github.zengfr.easymodbus4j.app.server.udp.UdpServerHandler4SendToServer; import com.github.zengfr.easymodbus4j.cache.ModebusFrameCache; import com.github.zengfr.easymodbus4j.common.util.ConsoleUtil; import com.github.zengfr.easymodbus4j.common.util.ScheduledUtil; import com.github.zengfr.easymodbus4j.ModbusConfs; import com.github.zengfr.easymodbus4j.example.ModbusConfig; import com.github.zengfr.easymodbus4j.example.ModbusSetup; import com.github.zengfr.easymodbus4j.processor.ModbusMasterResponseProcessor; import io.netty.channel.Channel; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.socket.DatagramPacket; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class ModbusServer4MasterApp { private static final InternalLogger logger = InternalLoggerFactory.getInstance(ModbusServer4MasterApp.class.getSimpleName()); public static void initAndStart(String[] argsArray) throws Exception { ModbusConfig config = ModbusConfig.parse(argsArray); start(config); } public static void start(ModbusConfig cfg) throws Exception { ModbusConsts.DEFAULT_UNIT_IDENTIFIER = cfg.unit_IDENTIFIER; ModbusConsts.HEARTBEAT=cfg.heartbeat; ModbusConfs.MASTER_SHOW_DEBUG_LOG = cfg.showDebugLog; ModbusConfs.IDLE_TIMEOUT_SECOND = cfg.idleTimeOut; ModbusConfs.RESPONS_EFRAME_IGNORE_LENGTH_THRESHOLD= cfg.ignoreLengthThreshold; DeviceCommandPluginRegister.getInstance().reg(DeviceCommandV1PluginImpl.class.newInstance()); DeviceRepositoryPluginRegister.getInstance().reg(DeviceRepositoryV1PluginImpl.class.newInstance()); ModbusMasterResponseProcessor masterProcessor = new CustomModbusMasterResponseProcessor(cfg.transactionIdentifierOffset); ModbusSetup setup = new ModbusSetup(); setup.initProperties(); setup.initHandler(masterProcessor, null); switch (cfg.type) { case 6: setup.setupServer4RtuMaster(cfg.port); break; default: setup.setupServer4TcpMaster(cfg.port); break; } Collection channels = setup.getModbusServer().getChannels(); UdpServer udpServer = new UdpServer(); SimpleChannelInboundHandler handler = new UdpServerHandler4SendToServer(channels); udpServer.setup(cfg.udpPort, handler); int sleep = cfg.sleep; logger.info(String.format("autoSend:%s sleep:%s ms", cfg.autoSend,sleep)); if (cfg.autoSend) { Thread.sleep(sleep); ModbusMasterSchedule4DeviceId modbusMasterSchedule4DeviceId = new ModbusMasterSchedule4DeviceId(); modbusMasterSchedule4DeviceId.schedule(channels, sleep *4); modbusMasterSchedule4DeviceId.run(channels); ModbusMasterSchedule4All modbusMasterSchedule4All = new ModbusMasterSchedule4All(); modbusMasterSchedule4All.schedule(channels, sleep); } Runnable runnable = () -> ConsoleUtil.clearConsole(true); new ScheduledUtil("clearConsole",1).scheduleAtFixedRate(runnable, sleep * 6); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/cache/AbstrctModbusKVCache.java ================================================ package com.github.zengfr.easymodbus4j.app.cache; import java.util.Set; import com.google.common.collect.BiMap; public abstract class AbstrctModbusKVCache { protected abstract BiMap getCacheMap(); public boolean containsValue(String v) { return getCacheMap().containsValue(v); } public boolean containsKey(String k) { return getCacheMap().containsKey(k); } public void put(String k, String v, boolean forcePut) { if (forcePut) getCacheMap().forcePut(k, v); else getCacheMap().put(k, v); } protected String getKey(String deviceId) { return getCacheMap().inverse().get(deviceId); } protected String getValue(String k) { return getCacheMap().get(k); } protected Set getValues() { return getCacheMap().values(); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/cache/ModbusDeviceIdVersionIdCache.java ================================================ package com.github.zengfr.easymodbus4j.app.cache; import java.util.HashMap; public class ModbusDeviceIdVersionIdCache extends HashMap { /** * */ private static final long serialVersionUID = 6593701804114127821L; private static class ModbusDeviceIdVersionIdCacheHolder { private static final ModbusDeviceIdVersionIdCache INSTANCE = new ModbusDeviceIdVersionIdCache(); } public static ModbusDeviceIdVersionIdCache getInstance() { return ModbusDeviceIdVersionIdCacheHolder.INSTANCE; } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/cache/ModbusIpPortDeviceIdCache.java ================================================ package com.github.zengfr.easymodbus4j.app.cache; import java.util.Set; import com.google.common.collect.BiMap; public class ModbusIpPortDeviceIdCache extends AbstrctModbusKVCache { private static class ModbusDeviceIdCacheHolder { private static final ModbusIpPortDeviceIdCache INSTANCE = new ModbusIpPortDeviceIdCache(); } public static ModbusIpPortDeviceIdCache getInstance() { return ModbusDeviceIdCacheHolder.INSTANCE; } @Override protected BiMap getCacheMap() { return ModbusKVCacheFactory.getInstance().getBiMap(this.getClass().getSimpleName()); } public String getDeviceId(String ipAndPort) { return getValue(ipAndPort); } public Set getDeviceIds() { return getValues(); } public String getIpAndPort(String deviceId) { return getKey(deviceId); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/cache/ModbusKVCacheFactory.java ================================================ package com.github.zengfr.easymodbus4j.app.cache; import java.util.Map; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.Maps; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; public class ModbusKVCacheFactory { private static class ModbusKVCacheFactoryHolder { private static final ModbusKVCacheFactory INSTANCE = new ModbusKVCacheFactory(); } protected static final InternalLogger logger = InternalLoggerFactory.getInstance(ModbusKVCacheFactory.class); public static ModbusKVCacheFactory getInstance() { return ModbusKVCacheFactoryHolder.INSTANCE; } private Map> cacheBiMap = Maps.newHashMap(); public BiMap getBiMap(String type) { if (!cacheBiMap.containsKey(type)) { cacheBiMap.put(type, HashBiMap.create()); } return cacheBiMap.get(type); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/cache/ModbusVersionIdCache.java ================================================ package com.github.zengfr.easymodbus4j.app.cache; import java.util.HashSet; public class ModbusVersionIdCache extends HashSet { /** * */ private static final long serialVersionUID = 8199263028001745303L; private static class ModbusVersionIdCacheHolder { private static final ModbusVersionIdCache INSTANCE = new ModbusVersionIdCache(); } public static ModbusVersionIdCache getInstance() { return ModbusVersionIdCacheHolder.INSTANCE; } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/plugin/DeviceCommandPlugin.java ================================================ package com.github.zengfr.easymodbus4j.app.plugin; import com.github.zengfr.easymodbus4j.app.common.DeviceCommand; import io.netty.buffer.ByteBuf; public interface DeviceCommandPlugin extends DevicePlugin { public boolean isEnabled(DeviceCommand cmd); public ByteBuf buildRequestFrame(DeviceCommand cmd); //public void parseResponseFrame(ByteBuf buffer); } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/plugin/DeviceCommandPluginRegister.java ================================================ package com.github.zengfr.easymodbus4j.app.plugin; import java.util.Map; import com.google.common.collect.Maps; public class DeviceCommandPluginRegister { private static DeviceCommandPluginRegister instance = new DeviceCommandPluginRegister(); private static Map plugins = Maps.newHashMap(); public static DeviceCommandPluginRegister getInstance() { return instance; } public void reg(Class pluginClass) throws InstantiationException, IllegalAccessException { if (pluginClass != null) reg(pluginClass.newInstance()); } public void reg(DeviceCommandPlugin plugin) { if (plugin != null) { plugins.put("", plugin); } } public DeviceCommandPlugin get() { return plugins.get(""); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/plugin/DevicePlugin.java ================================================ package com.github.zengfr.easymodbus4j.app.plugin; public interface DevicePlugin { } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/plugin/DeviceRepositoryPlugin.java ================================================ package com.github.zengfr.easymodbus4j.app.plugin; import java.util.Set; import com.github.zengfr.easymodbus4j.app.common.DeviceArg; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public interface DeviceRepositoryPlugin { public Set getVersionIds(); public String getVersionId(String deviceId); public DeviceArg getDeviceArg(String deviceId); public String getDeviceIdByIpAndPort(String ipAndPort); public void updateDeviceIpAndPort(String deviceId, String ipAndPort); public void updateFuctionValue(String ipAndPort,String deviceId, short func, int address, String value); boolean isGetDeviceIdReq(short funCode, int address, int quantityOfInputRegisters); } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/plugin/DeviceRepositoryPluginRegister.java ================================================ package com.github.zengfr.easymodbus4j.app.plugin; import java.util.Map; import com.google.common.collect.Maps; public class DeviceRepositoryPluginRegister { private static DeviceRepositoryPluginRegister instance = new DeviceRepositoryPluginRegister(); private static Map plugins = Maps.newHashMap(); public static DeviceRepositoryPluginRegister getInstance() { return instance; } public void reg(Class pluginClass) throws InstantiationException, IllegalAccessException { if (pluginClass != null) reg(pluginClass.newInstance()); } public void reg(DeviceRepositoryPlugin plugin) { if (plugin != null) plugins.put("", plugin); } public DeviceRepositoryPlugin get() { return plugins.get(""); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/plugin/impl/DeviceCommandAbstractPlugin.java ================================================ package com.github.zengfr.easymodbus4j.app.plugin.impl; import com.github.zengfr.easymodbus4j.app.plugin.DeviceCommandPlugin; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPlugin; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPluginRegister; import com.github.zengfr.easymodbus4j.codec.tcp.ModbusTcpDecoder; import com.github.zengfr.easymodbus4j.protocol.tcp.ModbusFrame; import com.github.zengfr.easymodbus4j.util.ModbusTransactionIdUtil; import io.netty.buffer.ByteBuf; public abstract class DeviceCommandAbstractPlugin implements DeviceCommandPlugin { protected int calculateTransactionIdentifier() { return ModbusTransactionIdUtil.calculateTransactionId(); } protected DeviceRepositoryPlugin getRepositoryPlugin() { return DeviceRepositoryPluginRegister.getInstance().get(); } protected ModbusFrame byteBuf2Frame(ByteBuf buffer, boolean decodeRequest) { return ModbusTcpDecoder.decodeFrame(buffer, decodeRequest); } protected ByteBuf frame2ByteBuf(ModbusFrame frame) { return frame.encode(); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/plugin/impl/DeviceCommandV1PluginImpl.java ================================================ package com.github.zengfr.easymodbus4j.app.plugin.impl; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import com.google.common.collect.Lists; import com.google.common.primitives.Booleans; import org.apache.commons.lang3.StringUtils; import io.netty.buffer.ByteBuf; import com.github.zengfr.easymodbus4j.ModbusConsts; import com.github.zengfr.easymodbus4j.app.common.DeviceCommand; import com.github.zengfr.easymodbus4j.app.common.FunctionCode; import com.github.zengfr.easymodbus4j.app.plugin.DeviceCommandPlugin; import com.github.zengfr.easymodbus4j.common.RegisterOrder; import com.github.zengfr.easymodbus4j.common.util.IntArrayUtil; import com.github.zengfr.easymodbus4j.common.util.RegistersUtil; import com.github.zengfr.easymodbus4j.func.request.ReadCoilsRequest; import com.github.zengfr.easymodbus4j.func.request.ReadDiscreteInputsRequest; import com.github.zengfr.easymodbus4j.func.request.ReadHoldingRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.ReadInputRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.WriteMultipleCoilsRequest; import com.github.zengfr.easymodbus4j.func.request.WriteMultipleRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.WriteSingleCoilRequest; import com.github.zengfr.easymodbus4j.func.request.WriteSingleRegisterRequest; import com.github.zengfr.easymodbus4j.protocol.ModbusFunction; import com.github.zengfr.easymodbus4j.protocol.tcp.ModbusFrame; import com.github.zengfr.easymodbus4j.protocol.tcp.ModbusHeader; public class DeviceCommandV1PluginImpl extends DeviceCommandAbstractPlugin implements DeviceCommandPlugin { public DeviceCommandV1PluginImpl() { } @Override public ByteBuf buildRequestFrame(DeviceCommand cmd) { ModbusFunction function = null; int fun = cmd.getFunctionCode(); int address = cmd.getAddress(); String v1 = "" + cmd.getValue(); String v2 = StringUtils.join(cmd.getValues(), ","); String v3 = StringUtils.strip(v1 + "," + v2, ","); List vList = Lists.newArrayList(v3.split(",")); if (!vList.isEmpty()) { String v = vList.get(0); switch (fun) { case FunctionCode.WRITE_SINGLE_COIL: boolean state = Boolean.valueOf(v); function = new WriteSingleCoilRequest(address, state); break; case FunctionCode.WRITE_SINGLE_REGISTER: int value = Integer.valueOf(v); function = new WriteSingleRegisterRequest(address, value); break; case FunctionCode.READ_COILS: int quantityOfCoils = Integer.valueOf(v); function = new ReadCoilsRequest(address, quantityOfCoils); break; case FunctionCode.READ_DISCRETE_INPUTS: int quantityOfCoils2 = Integer.valueOf(v); function = new ReadDiscreteInputsRequest(address, quantityOfCoils2); break; case FunctionCode.READ_INPUT_REGISTERS: int quantityOfInputRegisters = Integer.valueOf(v); function = new ReadInputRegistersRequest(address, quantityOfInputRegisters); break; case FunctionCode.READ_HOLDING_REGISTERS: int quantityOfInputRegisters2 = Integer.valueOf(v); function = new ReadHoldingRegistersRequest(address, quantityOfInputRegisters2); break; case FunctionCode.WRITE_MULTIPLE_REGISTERS: int[] registers = covertToIntegerArray("" + cmd.getValueType(), vList); int quantityOfRegisters = registers.length; function = new WriteMultipleRegistersRequest(address, quantityOfRegisters, registers); break; case FunctionCode.WRITE_MULTIPLE_COILS: String[] registersArray2 = StringUtils.split(v3, ","); List outputsValueList = Arrays.stream(registersArray2) .map(DeviceCommandV1PluginImpl::parseToBool).collect(Collectors.toList()); boolean[] outputsValue = Booleans.toArray(outputsValueList); int quantityOfOutputs = outputsValue.length; function = new WriteMultipleCoilsRequest(address, quantityOfOutputs, outputsValue); break; default: break; } } int transactionId = calculateTransactionIdentifier(); int pduLength = function.calculateLength(); int protocolIdentifier = ModbusConsts.DEFAULT_PROTOCOL_IDENTIFIER; short unitIdentifier = ModbusConsts.DEFAULT_UNIT_IDENTIFIER; ModbusHeader header = new ModbusHeader(transactionId, protocolIdentifier, pduLength, unitIdentifier); ModbusFrame frame = new ModbusFrame(header, function); ByteBuf buffer = frame2ByteBuf(frame); return buffer; } public static int[] covertToIntegerArray(String valueType, Iterable vArray) { ArrayList list = Lists.newArrayList(); for (String vItem : vArray) { if (vItem != null && !vItem.isEmpty() && !vItem.equals("null")) { int[] vv = covertToIntegerArray(valueType, vItem); for (Integer v : vv) { list.add(v); } } } return IntArrayUtil.toIntArray(list); } private static int[] covertToIntegerArray(String valueType, String v) { switch (valueType.toLowerCase()) { case "integer": Integer i = Integer.valueOf(v); return RegistersUtil.convertIntToRegisters(i, RegisterOrder.HighLow); case "float": Float f = Float.valueOf(v); return RegistersUtil.convertFloatToRegisters(f, RegisterOrder.HighLow); case "double": Double d = Double.valueOf(v); return RegistersUtil.convertDoubleToRegisters(d, RegisterOrder.HighLow); case "long": Long l = Long.valueOf(v); return RegistersUtil.convertLongToRegisters(l, RegisterOrder.HighLow); case "string": return RegistersUtil.convertStringToRegisters(v); } return new int[] { Integer.valueOf(v) }; } private static boolean parseToBool(String v) { return v != null && (v.equalsIgnoreCase("1") || v.equalsIgnoreCase("T")); } //@Override //public void parseResponseFrame(ByteBuf buffer) { // ModbusFrame frame = byteBuf2Frame(buffer, false); // DeviceRepositoryPlugin deviceRepositoryPlugin = getRepositoryPlugin(); // deviceRepositoryPlugin.getFunctionValues(version, cmd, values); // deviceRepositoryPlugin.updateCommandValue(cmd, value); //} @Override public boolean isEnabled(DeviceCommand cmd) { return true; } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/plugin/impl/DeviceRepositoryV1PluginImpl.java ================================================ package com.github.zengfr.easymodbus4j.app.plugin.impl; import java.util.Set; import com.alibaba.fastjson.JSON; import com.github.zengfr.easymodbus4j.app.cache.ModbusIpPortDeviceIdCache; import com.github.zengfr.easymodbus4j.app.cache.ModbusVersionIdCache; import com.github.zengfr.easymodbus4j.app.cache.ModbusDeviceIdVersionIdCache; import com.github.zengfr.easymodbus4j.app.common.DeviceArg; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPlugin; import com.github.zengfr.easymodbus4j.app.repository.DataRestRepository; import com.github.zengfr.easymodbus4j.app.repository.update_modbus_valuesReq; import com.github.zengfr.easymodbus4j.app.repository.update_modbus_valuesReqItem; import com.github.zengfr.easymodbus4j.app.repository.update_slaveipportReq; import com.github.zengfr.easymodbus4j.app.util.NetworkUtil; import com.google.common.collect.Lists; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; public class DeviceRepositoryV1PluginImpl implements DeviceRepositoryPlugin { private static final InternalLogger logger = InternalLoggerFactory.getInstance(DeviceRepositoryV1PluginImpl.class.getSimpleName()); @Override public void updateDeviceIpAndPort(String deviceId, String ipAndPort) { String[] ipAndPorts = ipAndPort.replace("/", "").split(":"); if (ipAndPorts.length >= 2) { ModbusIpPortDeviceIdCache.getInstance().put(ipAndPort, deviceId, true); logger.debug(String.format("updateIpAndPort:%s;%s;", deviceId, ipAndPort)); update_slaveipportReq req = new update_slaveipportReq(); req.remotIp = "" + NetworkUtil.getLocalHostLANAddressString().replace("/", ""); req.mainboard_no = deviceId; req.ip = ipAndPorts[0]; req.port = Integer.valueOf(ipAndPorts[1]); try { //DataRestRepository.update_ipport(req); } catch (Exception e) { logger.error(e); } } } @Override public void updateFuctionValue(String ipAndPort, String deviceId, short func, int address, String value) { logger.debug(String.format("updateFuncValue:%s;%s;%s;%s;%s", ipAndPort,deviceId, func, address, value)); update_modbus_valuesReqItem item = new update_modbus_valuesReqItem(); item.function = "" + func; item.address = "" + address; item.value = "" + value; update_modbus_valuesReq req = new update_modbus_valuesReq(); req.remotIp = "" + NetworkUtil.getLocalHostLANAddressString().replace("/", ""); req.time_stamp = System.currentTimeMillis(); req.mainboard_no = deviceId; req.items = Lists.newArrayList(); req.items.add(item); try { String[] ipAndPortArray = ipAndPort.replace("/", "").split(":"); req.ip = ipAndPortArray[0]; req.port = Integer.valueOf(ipAndPortArray[1]); DataRestRepository.update_values(req); } catch (Exception e) { logger.error(e); } } @Override public DeviceArg getDeviceArg(String deviceId) { DeviceArg arg = new DeviceArg(); arg.port = -1; arg.version = getVersionId(deviceId); String key = ModbusIpPortDeviceIdCache.getInstance().getIpAndPort(deviceId); if (key != null) { String[] keys = key.split(":"); if (keys.length > 1) { arg.ip = keys[0]; arg.port = Integer.parseInt(keys[1]); } } logger.debug(String.format("getDeviceArg:%s;%s", deviceId, JSON.toJSONString(arg))); return arg; } @Override public Set getVersionIds() { return ModbusVersionIdCache.getInstance(); } @Override public String getVersionId(String deviceId) { return ModbusDeviceIdVersionIdCache.getInstance().get(deviceId); } @Override public String getDeviceIdByIpAndPort(String ipAndPort) { return ModbusIpPortDeviceIdCache.getInstance().getDeviceId(ipAndPort); } @Override public boolean isGetDeviceIdReq(short funCode, int address, int quantityOfInputRegisters) { return funCode == 3 && (address == 69 || address == 48) && quantityOfInputRegisters == 2; } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/processor/CustomModbusMasterResponseProcessor.java ================================================ package com.github.zengfr.easymodbus4j.app.processor; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPlugin; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPluginRegister; import com.github.zengfr.easymodbus4j.common.util.ByteUtil; import com.github.zengfr.easymodbus4j.common.util.HexUtil; import com.github.zengfr.easymodbus4j.func.AbstractRequest; import com.github.zengfr.easymodbus4j.processor.AbstractModbusProcessor; import com.github.zengfr.easymodbus4j.processor.ModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.protocol.ModbusFunction; import com.github.zengfr.easymodbus4j.util.ModbusFunctionUtil; import io.netty.channel.Channel; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; public class CustomModbusMasterResponseProcessor extends AbstractModbusProcessor implements ModbusMasterResponseProcessor { private static final InternalLogger logger = InternalLoggerFactory.getInstance(CustomModbusMasterResponseProcessor.class.getSimpleName()); public CustomModbusMasterResponseProcessor(short transactionIdentifierOffset) { super(transactionIdentifierOffset, true); } @Override public boolean processResponseFrame(Channel channel, int unitId, AbstractRequest reqFunc, ModbusFunction respFunc) { boolean success = false; boolean isMatch = this.isRequestResponseMatch(reqFunc, respFunc); if (isMatch) { try { byte[] respFuncValuesArray = ModbusFunctionUtil.getFunctionValues(respFunc); success = isRequestResponseValueMatch(reqFunc, respFuncValuesArray); logger.info(String.format("processResponseFrame:%s;%s;%s;%s;%s;%s", success, channel.remoteAddress(), unitId, HexUtil.bytesToHexString(respFuncValuesArray), reqFunc, respFunc)); short funCode = reqFunc.getFunctionCode(); int address = reqFunc.getAddress(); int quantityOfInputRegisters = reqFunc.getValue(); processResponse(channel, funCode, address, quantityOfInputRegisters, respFuncValuesArray); } catch (IllegalArgumentException | SecurityException e) { logger.error(e); } } if (!success) { logger.warn(String.format("isMatch:%s;success:%s;%s;%s;%s;%s", isMatch, success, channel.remoteAddress(), unitId, reqFunc, respFunc)); } return success; } protected void processResponse(Channel channel, short funCode, int address, int quantityOfInputRegisters, byte[] valuesArray) { logger.debug(String.format("processResponse:%s;%s;%s;%s;%s", channel.remoteAddress(), funCode, address, quantityOfInputRegisters, HexUtil.bytesToHexString(valuesArray, " "))); String ipAndPort = String.format("%s", channel.remoteAddress().toString().replaceAll("/", "")); int[] value = ByteUtil.toIntArray(valuesArray); String valueHexStr = HexUtil.bytesToHexString(valuesArray, " "); DeviceRepositoryPlugin repositoryPlugin = getDeviceRepositoryPlugin(); if (repositoryPlugin.isGetDeviceIdReq(funCode, address, quantityOfInputRegisters)) { if (value.length > 0 && value[0] > 0) { String deviceId = "" + value[0]; repositoryPlugin.updateDeviceIpAndPort(deviceId, ipAndPort); } } else { String deviceId = repositoryPlugin.getDeviceIdByIpAndPort(ipAndPort); repositoryPlugin.updateFuctionValue(ipAndPort, deviceId, funCode, address, valueHexStr); } } protected DeviceRepositoryPlugin getDeviceRepositoryPlugin() { return DeviceRepositoryPluginRegister.getInstance().get(); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/repository/DataRestRepository.java ================================================ package com.github.zengfr.easymodbus4j.app.repository; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import org.apache.http.HttpEntity; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.PoolingClientConnectionManager; import org.apache.http.util.EntityUtils; import com.alibaba.fastjson.JSON; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; public class DataRestRepository { private static final InternalLogger logger = InternalLoggerFactory.getInstance(DataRestRepository.class.getSimpleName()); private static String serviceUrl = "http://120.27.26.44:9074"; private static Cache tokenCache = CacheBuilder.newBuilder() .expireAfterWrite(1000 * 60 * 10, TimeUnit.MILLISECONDS).build(); private static String getTokenByCache() throws Exception { Callable loader = () -> { return getToken(); }; String token = tokenCache.get("token", loader); if (token == null || token.isEmpty()) { tokenCache.invalidateAll(); // token = // "bearereyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJ3ZWJjbGllbnQiLCIgbW9iaWxlY2xpZW50Il0sInNob3BJZCI6ImNkODI2IiwiZXhwIjoxNTU4ODc4Nzc1LCJhdXRob3JpdGllcyI6WyJtb2RidXMiXSwianRpIjoiYzI3Y2MxMWMtOWQ5My00YTY1LWFiZmItNmEwNzA2OWJkZTAyIiwiY2xpZW50X2lkIjoiYXBpX2NsaWVudF90ZXN0In0.kwSanVJ6b4GKyQwjRFKVnIpLDeBYeSEi4dW22Q_vnxo"; } return token; } private static String getToken() throws Exception { String url = "/oauth/token"; access_tokenReq req = new access_tokenReq(); req.client_id = "api_client_test"; req.client_secret = "000000"; req.grant_type = "client_credentials"; access_tokenResp resp = post(String.format("%s%s?%s", serviceUrl, url, ""), req, false, access_tokenResp.class); if (resp != null && resp.access_token != null && !resp.access_token.isEmpty()) { return resp.token_type + resp.access_token; } return ""; } public static mainboard_adressResp get_mainboard_addresslist() throws Exception { String url = "/api/modbus/param/mainboardadresslist?"; req req = new req(); req.access_token = getTokenByCache(); mainboard_adressResp resp=get(String.format("%s%s?%s", serviceUrl, url, ""), true, mainboard_adressResp.class); if(resp!=null) { logger.debug(JSON.toJSONString(resp)); } return resp; } public static autosend_listResp get_autosendlist(String versionId) throws Exception { String url = "/api/modbus/autosendlist"; return get(String.format("%s%s?%s", serviceUrl, url, "model_no=" + versionId), true, autosend_listResp.class); } public static void update_values(update_modbus_valuesReq req) throws Exception { String url = "/api/modbus/values"; req.access_token = getTokenByCache(); post(String.format("%s%s?%s", serviceUrl, url, ""), req, true, req.class); } public static void update_ipport(update_slaveipportReq req) throws Exception { String url = "/api/modbus/slaveipport"; req.access_token = getTokenByCache(); post(String.format("%s%s?%s", serviceUrl, url, ""), req, true, req.class); } final static String CONTENT_TYPE_TEXT_JSON = "text/json"; protected static R post(String url, T body, boolean useToken, Class clazz) throws Exception { HttpPost post = new HttpPost(url); post.setHeader("Content-Type", "application/json;charset=UTF-8"); if (useToken) post.addHeader("Authorization", getTokenByCache()); post.setConfig(getRequestConfig()); String bodyString = JSON.toJSONString(body); StringEntity se = new StringEntity(bodyString); se.setContentType(CONTENT_TYPE_TEXT_JSON); post.setEntity(se); DefaultHttpClient client = new DefaultHttpClient(new PoolingClientConnectionManager()); CloseableHttpResponse response2 = null; response2 = client.execute(post); HttpEntity entity2 = response2.getEntity(); String s2 = EntityUtils.toString(entity2, "UTF-8"); logger.debug(String.format("post->url:%s;resp:%s", url, bodyString, s2)); return JSON.parseObject(s2, clazz); } protected static R get(String url, boolean useToken, Class clazz) throws Exception { HttpGet get = new HttpGet(url); if (useToken) get.addHeader("Authorization", getTokenByCache()); get.setConfig(getRequestConfig()); DefaultHttpClient client = new DefaultHttpClient(new PoolingClientConnectionManager()); CloseableHttpResponse response2 = null; response2 = client.execute(get); HttpEntity entity2 = response2.getEntity(); String s2 = EntityUtils.toString(entity2, "UTF-8"); logger.debug(String.format("get->url:%s;resp:%s", url, s2)); return JSON.parseObject(s2, clazz); } protected static RequestConfig getRequestConfig() { RequestConfig requestConfig = null; if (requestConfig == null) { requestConfig = RequestConfig.custom().setConnectionRequestTimeout(20000).setConnectTimeout(20000) .setSocketTimeout(20000).build(); } return requestConfig; } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/schedule/ModbusMasterSchedule4All.java ================================================ package com.github.zengfr.easymodbus4j.app.schedule; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.zengfr.easymodbus4j.app.ModbusServer4MasterApp; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPlugin; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPluginRegister; import com.github.zengfr.easymodbus4j.app.repository.DataRestRepository; import com.github.zengfr.easymodbus4j.app.repository.autosend_listResp; import com.github.zengfr.easymodbus4j.app.repository.autosend_listRespItem; import com.github.zengfr.easymodbus4j.schedule.ModbusMasterSchedule; import com.github.zengfr.easymodbus4j.sender.util.ModbusRequestSendUtil.PriorityStrategy; import com.google.common.collect.Lists; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; public class ModbusMasterSchedule4All extends ModbusMasterSchedule { private static Logger logger=LoggerFactory.getLogger(ModbusMasterSchedule4All.class.getSimpleName()); @Override protected int getFixedDelay() { return 300; } @Override protected PriorityStrategy getPriorityStrategy() { return PriorityStrategy.Req; } @Override protected Logger getLogger() { return logger; } @Override protected List buildReqsList() { return parseReqs(); } private static List parseReqs() { List reqStrings = Lists.newArrayList(); try { autosend_listResp resp = null; Set versionIds = getDeviceRepositoryPlugin().getVersionIds(); for (String versionId : versionIds) { resp = DataRestRepository.get_autosendlist(versionId); if (resp != null && resp.results != null) { for (autosend_listRespItem item : resp.results) { reqStrings.add(String.format("%s|%s|%s", item.function, item.address, item.quantity)); } } } } catch (Exception e) { logger.error("parseReqs",e); } return reqStrings; } protected static DeviceRepositoryPlugin getDeviceRepositoryPlugin() { return DeviceRepositoryPluginRegister.getInstance().get(); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/schedule/ModbusMasterSchedule4DeviceId.java ================================================ package com.github.zengfr.easymodbus4j.app.schedule; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.zengfr.easymodbus4j.app.cache.ModbusVersionIdCache; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPlugin; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPluginRegister; import com.github.zengfr.easymodbus4j.app.repository.DataRestRepository; import com.github.zengfr.easymodbus4j.app.repository.mainboard_adressResp; import com.github.zengfr.easymodbus4j.app.repository.mainboard_adressRespItem; import com.github.zengfr.easymodbus4j.schedule.ModbusMasterSchedule; import com.github.zengfr.easymodbus4j.sender.util.ModbusRequestSendUtil.PriorityStrategy; import com.google.common.collect.Lists; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; public class ModbusMasterSchedule4DeviceId extends ModbusMasterSchedule { private static Logger logger=LoggerFactory.getLogger(ModbusMasterSchedule4DeviceId.class.getSimpleName()); @Override protected int getFixedDelay() { return 300; } @Override protected PriorityStrategy getPriorityStrategy() { return PriorityStrategy.Req; } @Override protected Logger getLogger() { return logger; } @Override protected List buildReqsList() { return parseReqs(); } private static List parseReqs() { List reqStrings = Lists.newArrayList(); try { mainboard_adressResp resp = null; resp = DataRestRepository.get_mainboard_addresslist(); if (resp != null && resp.results != null && !resp.results.isEmpty()) { for (mainboard_adressRespItem item : resp.results) { reqStrings.add(String.format("%s|%s|%s", item.function, item.address, item.quantity)); ModbusVersionIdCache.getInstance().add(item.model_no); } }else { logger.error("get_mainboard_addresslist isEmpty"); } } catch (Exception e) { logger.error("parseReqs",e); } return reqStrings; } protected static DeviceRepositoryPlugin getDeviceRepositoryPlugin() { return DeviceRepositoryPluginRegister.getInstance().get(); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/server/udp/UdpServer.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.server.udp; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class UdpServer { private static final InternalLogger logger = InternalLoggerFactory.getInstance(UdpServer.class); public void setup(int port, SimpleChannelInboundHandler handler) throws InterruptedException { Bootstrap b = new Bootstrap(); EventLoopGroup group = new NioEventLoopGroup(); b.group(group).channel(NioDatagramChannel.class).option(ChannelOption.SO_BROADCAST, true).handler(handler); b.bind(port).sync();// .channel().closeFuture().await(); logger.info(String.format("UdpServer bind:%s", port)); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/server/udp/UdpServerHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.server.udp; import java.net.InetSocketAddress; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.socket.DatagramPacket; import io.netty.util.CharsetUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class UdpServerHandler extends SimpleChannelInboundHandler { private static final InternalLogger logger = InternalLoggerFactory.getInstance(UdpServerHandler.class.getSimpleName()); @Override protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception { messageReceived(ctx, packet.sender(),packet.content().toString(CharsetUtil.UTF_8)); } protected void messageReceived(ChannelHandlerContext ctx, InetSocketAddress sender, String msg) throws Exception { logger.debug(String.format("%s->%s", sender, msg)); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/server/udp/UdpServerHandler4SendToServer.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.app.server.udp; import java.net.InetSocketAddress; import java.util.Collection; import java.util.List; import org.apache.commons.lang3.StringUtils; import com.github.zengfr.easymodbus4j.app.common.DeviceArg; import com.github.zengfr.easymodbus4j.app.common.DeviceCommand; import com.github.zengfr.easymodbus4j.app.plugin.DeviceCommandPlugin; import com.github.zengfr.easymodbus4j.app.plugin.DeviceCommandPluginRegister; import com.github.zengfr.easymodbus4j.app.plugin.DeviceRepositoryPluginRegister; import com.github.zengfr.easymodbus4j.app.sender.UdpSender; import com.github.zengfr.easymodbus4j.app.sender.UdpSenderFactory; import com.github.zengfr.easymodbus4j.codec.tcp.ModbusTcpDecoder; import com.github.zengfr.easymodbus4j.protocol.tcp.ModbusFrame; import com.github.zengfr.easymodbus4j.sender.ChannelSender; import com.github.zengfr.easymodbus4j.sender.ChannelSenderFactory; import com.google.common.collect.Lists; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class UdpServerHandler4SendToServer extends UdpServerHandler { private static final InternalLogger logger = InternalLoggerFactory.getInstance(UdpServerHandler4SendToServer.class.getSimpleName()); protected Collection serverClientchannels = Lists.newArrayList(); public UdpServerHandler4SendToServer(Collection serverClientchannels) { this.serverClientchannels = serverClientchannels; } @Override protected void messageReceived(ChannelHandlerContext ctx, InetSocketAddress sender, String msg) throws Exception { super.messageReceived(ctx, sender, msg); int success = processMessage(ctx, msg); UdpSender udpSender = UdpSenderFactory.getInstance().get(ctx.channel()); udpSender.send(sender, String.format("%s;%s", success, msg)); } protected int processMessage(ChannelHandlerContext ctx, String msg) { int success = -1; if (StringUtils.isNotEmpty(msg)) { DeviceCommand cmd = parseCommand(msg); if (isEnabled(cmd)) { String ip = cmd.getIp(); int port = cmd.getPort(); String versionId = cmd.getVersion(); int funcCode = cmd.getFunctionCode(); DeviceArg deviceArg = getDeviceArg(cmd.getDeviceId()); if (deviceArg != null && deviceArg.port >= 0) { ip = deviceArg.ip; port = deviceArg.port; versionId = deviceArg.version != null ? deviceArg.version : versionId; } if (funcCode < 0) { Collection channels = getChannels(ip, port); success = 0; for (Channel channel : channels) { channel.close(); success++; } } if (funcCode > 0) { ModbusFrame reqFrame = buildRequestFrame(versionId, cmd); logger.info(String.format("v1219;%s;%s;%s;%s;%s;", ip, port, versionId, cmd.getValueType(), reqFrame)); if (reqFrame != null) { Collection channels = getChannels(ip, port); success = 0; for (Channel channel : channels) { ChannelSender sender = ChannelSenderFactory.getInstance().get(channel); sender.sendModbusFrame(reqFrame); success++; } } else { success--; } } } else { success--; } } else { success--; } return success; } protected DeviceCommand parseCommand(String msg) { DeviceCommand cmd = new DeviceCommand(); cmd.setFunctionCode(-1); if (StringUtils.isNotEmpty(msg)) { String[] args = msg.split(";"); if (args.length >= 4) { cmd.setDeviceId(args[1]); cmd.setIp(args[2]); cmd.setPort(Integer.valueOf(args[3])); } if (args.length >= 10) {// uuid-deviceId-ip-prot-vserion-func-address-value cmd.setDeviceId(args[1]); cmd.setIp(args[2]); cmd.setPort(Integer.valueOf(args[3])); cmd.setVersion(args[4]); cmd.setFunctionCode(Integer.valueOf(args[5])); cmd.setAddress(Integer.valueOf(args[6])); cmd.setValue(args[8]); cmd.setValues(args[9].split(",")); cmd.setValueType(args[7]); } } return cmd; } protected Collection getChannels(String host, int port) { List channels = Lists.newArrayList(); String key; if (port > 0) { key = String.format("/%s:%s", host, port); for (Channel channel : this.serverClientchannels) { if (channel.remoteAddress().toString().equalsIgnoreCase(key)) { channels.add(channel); break; } } } else { key = String.format("/%s:", host); for (Channel channel : this.serverClientchannels) { if (channel.remoteAddress().toString().contains(key)) { channels.add(channel); } } } return channels; } protected ModbusFrame buildRequestFrame(String version, DeviceCommand cmd) { DeviceCommandPlugin deviceCommandPlugin = getDeviceCommandPlugin(); if (deviceCommandPlugin != null) { ByteBuf buffer = deviceCommandPlugin.buildRequestFrame(cmd); boolean isSlave = true; ModbusFrame frame = ModbusTcpDecoder.decodeFrame(buffer, isSlave); return frame; } return null; } protected boolean isEnabled(DeviceCommand cmd) { if (cmd != null) { DeviceCommandPlugin deviceCommandPlugin = getDeviceCommandPlugin(); if (deviceCommandPlugin != null) { return deviceCommandPlugin.isEnabled(cmd); } } return false; } protected DeviceCommandPlugin getDeviceCommandPlugin() { return DeviceCommandPluginRegister.getInstance().get(); } protected DeviceArg getDeviceArg(String deviceId) { return DeviceRepositoryPluginRegister.getInstance().get().getDeviceArg(deviceId); } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/app/util/NetworkUtil.java ================================================ package com.github.zengfr.easymodbus4j.app.util; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.UnknownHostException; import java.util.Enumeration; public class NetworkUtil { public static String getLocalHostLANAddressString() { InetAddress ip=null; try { ip = getLocalHostLANAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } return ip==null?"":ip.toString(); } public static InetAddress getLocalHostLANAddress() throws UnknownHostException { try { InetAddress candidateAddress = null; // 遍历所有的网络接口 for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) { NetworkInterface iface = (NetworkInterface) ifaces.nextElement(); // 在所有的接口下再遍历IP for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) { InetAddress inetAddr = (InetAddress) inetAddrs.nextElement(); if (!inetAddr.isLoopbackAddress()) {// 排除loopback类型地址 if (inetAddr.isSiteLocalAddress()) { // 如果是site-local地址,就是它了 return inetAddr; } else if (candidateAddress == null) { // site-local类型的地址未被发现,先记录候选地址 candidateAddress = inetAddr; } } } } if (candidateAddress != null) { return candidateAddress; } // 如果没有发现 non-loopback地址.只能用最次选的方案 InetAddress jdkSuppliedAddress = InetAddress.getLocalHost(); if (jdkSuppliedAddress == null) { throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null."); } return jdkSuppliedAddress; } catch (Exception e) { UnknownHostException unknownHostException = new UnknownHostException( "Failed to determine LAN address: " + e); unknownHostException.initCause(e); throw unknownHostException; } } } ================================================ FILE: easymodbus4j-example2/src/main/java/com/github/zengfr/easymodbus4j/main/Example2.java ================================================ package com.github.zengfr.easymodbus4j.main; import com.github.zengfr.easymodbus4j.app.ModbusServer4MasterApp; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public class Example2 { public static void main(String[] args) throws Exception { if (args == null || args.length <= 0) args = new String[] { "" }; String[] argsArray = args[0].split("[,;|]"); switch (argsArray.length) { default: ModbusServer4MasterApp.initAndStart(argsArray); break; } System.in.read(); } } ================================================ FILE: easymodbus4j-example2/src/main/resources/log4j.properties ================================================ ### httpClient, wire->header log4j.logger.org.apache.http=error log4j.logger.httpclient.wire=error ================================================ FILE: easymodbus4j-example2/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS}|%-5level|%thread|%logger{64}-%msg%n true 127.0.0.1 7071 channel default DEBUG log/debug-%d{yyyy-MM-dd}-%i-${channel}.log 20MB 31 2GB true %d{HH:mm:ss.SSS}|%-5level|%thread|%logger{64}-%msg%n channel default INFO ACCEPT DENY log/info-%d{yyyy-MM-dd}-%i-${channel}.log 20MB 31 2GB true %d{HH:mm:ss.SSS}|%-5level|%thread|%logger{64}-%msg%n channel default WARN log/warn-%d{yyyy-MM-dd}-%i-${channel}.log 20MB 31 %d{HH:mm:ss.SSS}|%-5level|%thread|%logger{64}-%msg%n 0 512 true 0 512 true 0 512 true ================================================ FILE: easymodbus4j-example2/src/main/resources/readme.txt ================================================ ================================================ FILE: easymodbus4j-example2/src/main/resources/start0-Server4TcpMaster-UdpServer.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example2-0.0.1.jar 0,127.0.0.1,502,1,0,T,0,T,12000,heartbeat,0,54321 pause @echo on ================================================ FILE: easymodbus4j-example2/src/main/resources/start6-Server4RtuMaster-UdpServer.bat ================================================ @echo off rem type,host,port,unit_IDENTIFIER,transactionIdentifierOffset,showDebugLog,idleTimeout,autoSend,sleep,heartbeat,ignoreLengthThreshold,udpPort java -jar easymodbus4j-example2-0.0.1.jar 6,127.0.0.1,502,1,0,T,0,T,12000,www.mokuai.cn,36,54321 pause @echo on ================================================ FILE: easymodbus4j-example2/src/main/resources/zip.xml ================================================ release zip ${project.basedir}\src\main\resources *.java zip.xml \ ${project.basedir}\target *.jar *-sources.jar \ false libs runtime ================================================ FILE: easymodbus4j-example2/src/test/java/com/github/zengfr/easymodbus4j/RegistersUtilTest.java ================================================ package com.github.zengfr.easymodbus4j; import java.util.List; import org.junit.Test; import com.github.zengfr.easymodbus4j.app.plugin.impl.DeviceCommandV1PluginImpl; import com.github.zengfr.easymodbus4j.common.RegisterOrder; import com.github.zengfr.easymodbus4j.common.util.ByteUtil; import com.github.zengfr.easymodbus4j.common.util.HexUtil; import com.github.zengfr.easymodbus4j.common.util.RegistersUtil; import com.google.common.collect.Lists; public class RegistersUtilTest { @Test public void testServer4MasterAndUdpServer() throws Exception { int[] vv = RegistersUtil.convertFloatToRegisters(6.5f, RegisterOrder.HighLow); System.out.print(vv); float ff = RegistersUtil.convertRegistersToFloat(vv, RegisterOrder.HighLow); System.out.print(ff); byte[] bytes1 = RegistersUtil.toByteArrayFloat(ff); byte[] bytes2 = ByteUtil.floatToByte(new float[] { ff }); float[] ff2 = ByteUtil.toFloatArray(bytes2); System.out.print(ff2); int[] int2 = ByteUtil.toIntArray(bytes2); String ss = HexUtil.bytesToHexString(bytes2); System.out.print(ss); List vArray = Lists.newArrayList(); vArray.add("6.5"); vArray.add("null"); int[] s = DeviceCommandV1PluginImpl.covertToIntegerArray("float", vArray); System.out.print(s); } @Test public void testHexUtil() throws Exception { String hex = "DE0D";// 56845 byte[] bytes = HexUtil.hexStringToByte(hex); short[] ss1 = ByteUtil.toShortArray(bytes, false); short[] ss2 = ByteUtil.toShortArray(bytes, true); System.out.println(ss1[0]); System.out.println(ss2[0]); System.out.println("" + ((short) ss1[0] & 0xffff)); System.out.println("" + ((short) ss2[0] & 0xffff)); System.out.println((0x10000 + ss2[0])); int[] r = ByteUtil.toUShortArray(bytes); System.out.println(r[0]); } } ================================================ FILE: easymodbus4j-example2/src/test/java/com/github/zengfr/easymodbus4j/app/A.java ================================================ package com.github.zengfr.easymodbus4j.app; public class A { public A() { i = (j++ != 0) ? ++j : --j; } public int i; public static int j = 0; } ================================================ FILE: easymodbus4j-example2/src/test/java/com/github/zengfr/easymodbus4j/app/AppTest.java ================================================ package com.github.zengfr.easymodbus4j.app; import org.junit.Test; import com.github.zengfr.easymodbus4j.main.Example2; public class AppTest { @Test public void testServer4MasterAndUdpServer() throws Exception { Example2.main(new String[] { "0,127.0.0.1,502,1,1,T,T,25000,54321" }); } } ================================================ FILE: easymodbus4j-example2/src/test/java/com/github/zengfr/easymodbus4j/app/CaseTest.java ================================================ package com.github.zengfr.easymodbus4j.app; public class CaseTest { public static void main(String[] args) { A a1 = new A(); System.out.println(a1.i); System.out.println(a2.i); } public static A a2 = new A(); } ================================================ FILE: easymodbus4j-example2/src/test/java/com/github/zengfr/easymodbus4j/app/PrimeTest.java ================================================ package com.github.zengfr.easymodbus4j.app; public class PrimeTest { public static int FindNextPrime(int i) { int j =i<0?1:i+1; int m=j%2==0?j +1:j ; for (;m < i * i; m +=2) { if (isPrime(m)) { return m; } } return m; } public static boolean isPrime(int n) { if (n>2&&n % 2 == 0) return false; for (int i = 3; i * i <= n; i += 2) if (n % i == 0) return false; return true; } public static void main(String[] args) { System.out.println(FindNextPrime(0)); System.out.println(FindNextPrime(23)); System.out.println(FindNextPrime(2)); } } ================================================ FILE: easymodbus4j-extension/pom.xml ================================================ 4.0.0 com.github.zengfr easymodbus4j-extension 0.0.5 true com.github.zengfr.project parent 0.0.2 ../parent/pom.xml easymodbus4j com.github.zengfr 0.0.5 ================================================ FILE: easymodbus4j-extension/src/main/java/com/github/zengfr/easymodbus4j/handle/impl/ModbusMasterResponseHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.handle.impl; import com.github.zengfr.easymodbus4j.func.AbstractRequest; import com.github.zengfr.easymodbus4j.handler.ModbusResponseHandler; import com.github.zengfr.easymodbus4j.logging.ChannelLogger; import com.github.zengfr.easymodbus4j.processor.ModbusMasterResponseProcessor; import com.github.zengfr.easymodbus4j.protocol.ModbusFunction; import com.github.zengfr.easymodbus4j.protocol.tcp.ModbusFrame; import com.github.zengfr.easymodbus4j.util.ModbusFrameUtil; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ @ChannelHandler.Sharable public class ModbusMasterResponseHandler extends ModbusResponseHandler { private static final ChannelLogger logger = ChannelLogger.getLogger(ModbusMasterResponseHandler.class); private ModbusMasterResponseProcessor processor; public short getTransactionIdentifierOffset() { return this.processor.getTransactionIdentifierOffset(); } public ModbusMasterResponseHandler(ModbusMasterResponseProcessor processor) { super(true); this.processor = processor; } @Override protected boolean processResponseFrame(Channel channel, ModbusFrame frame) { if (this.processor.isShowFrameDetail()) { ModbusFrameUtil.showFrameLog(logger, channel, frame, true); } return super.processResponseFrame(channel, frame); } @Override protected int getReqTransactionIdByRespTransactionId(int respTransactionIdentifierOffset) { return respTransactionIdentifierOffset - this.getTransactionIdentifierOffset(); } protected int getRespTransactionIdByReqTransactionId(int reqTransactionIdentifier) { return reqTransactionIdentifier + this.getTransactionIdentifierOffset(); } @Override public ModbusFrame getResponseCache(int reqTransactionIdentifier,short funcCode) throws Exception { int respTransactionIdentifier = getRespTransactionIdByReqTransactionId(reqTransactionIdentifier); return super.getResponseCache(respTransactionIdentifier, funcCode); } @Override protected boolean processResponseFrame(Channel channel, int unitId, AbstractRequest reqFunc, ModbusFunction respFunc) { return this.processor.processResponseFrame(channel, unitId, reqFunc, respFunc); } } ================================================ FILE: easymodbus4j-extension/src/main/java/com/github/zengfr/easymodbus4j/handle/impl/ModbusSlaveRequestHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.handle.impl; import com.github.zengfr.easymodbus4j.func.request.ReadCoilsRequest; import com.github.zengfr.easymodbus4j.func.request.ReadDiscreteInputsRequest; import com.github.zengfr.easymodbus4j.func.request.ReadHoldingRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.ReadInputRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.WriteMultipleCoilsRequest; import com.github.zengfr.easymodbus4j.func.request.WriteMultipleRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.WriteSingleCoilRequest; import com.github.zengfr.easymodbus4j.func.request.WriteSingleRegisterRequest; import com.github.zengfr.easymodbus4j.func.response.ReadCoilsResponse; import com.github.zengfr.easymodbus4j.func.response.ReadDiscreteInputsResponse; import com.github.zengfr.easymodbus4j.func.response.ReadHoldingRegistersResponse; import com.github.zengfr.easymodbus4j.func.response.ReadInputRegistersResponse; import com.github.zengfr.easymodbus4j.func.response.WriteMultipleCoilsResponse; import com.github.zengfr.easymodbus4j.func.response.WriteMultipleRegistersResponse; import com.github.zengfr.easymodbus4j.func.response.WriteSingleCoilResponse; import com.github.zengfr.easymodbus4j.func.response.WriteSingleRegisterResponse; import com.github.zengfr.easymodbus4j.handler.ModbusRequestHandler; import com.github.zengfr.easymodbus4j.logging.ChannelLogger; import com.github.zengfr.easymodbus4j.processor.ModbusSlaveRequestProcessor; import com.github.zengfr.easymodbus4j.protocol.ModbusFunction; import com.github.zengfr.easymodbus4j.protocol.tcp.ModbusFrame; import com.github.zengfr.easymodbus4j.util.ModbusFrameUtil; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ @ChannelHandler.Sharable public class ModbusSlaveRequestHandler extends ModbusRequestHandler { private static final ChannelLogger logger = ChannelLogger.getLogger(ModbusSlaveRequestHandler.class); private ModbusSlaveRequestProcessor processor; public short getTransactionIdentifierOffset() { return this.processor.getTransactionIdentifierOffset(); } public ModbusSlaveRequestHandler(ModbusSlaveRequestProcessor processor) { this.processor = processor; } @Override protected int getRespTransactionIdByReqTransactionId(int reqTransactionIdentifier) { return reqTransactionIdentifier + this.getTransactionIdentifierOffset(); } @Override protected ModbusFunction processRequestFrame(Channel channel, ModbusFrame frame) { if (this.processor.isShowFrameDetail()) { ModbusFrameUtil.showFrameLog(logger, channel, frame, true); } return super.processRequestFrame(channel, frame); } @Override protected WriteSingleCoilResponse writeSingleCoil(short unitIdentifier, WriteSingleCoilRequest request) { return this.processor.writeSingleCoil(unitIdentifier, request); } @Override protected WriteSingleRegisterResponse writeSingleRegister(short unitIdentifier, WriteSingleRegisterRequest request) { return this.processor.writeSingleRegister(unitIdentifier, request); } @Override protected ReadCoilsResponse readCoils(short unitIdentifier, ReadCoilsRequest request) { return this.processor.readCoils(unitIdentifier, request); } @Override protected ReadDiscreteInputsResponse readDiscreteInputs(short unitIdentifier, ReadDiscreteInputsRequest request) { return this.processor.readDiscreteInputs(unitIdentifier, request); } @Override protected ReadInputRegistersResponse readInputRegisters(short unitIdentifier, ReadInputRegistersRequest request) { return this.processor.readInputRegisters(unitIdentifier, request); } @Override protected ReadHoldingRegistersResponse readHoldingRegisters(short unitIdentifier, ReadHoldingRegistersRequest request) { return this.processor.readHoldingRegisters(unitIdentifier, request); } @Override protected WriteMultipleCoilsResponse writeMultipleCoils(short unitIdentifier, WriteMultipleCoilsRequest request) { return this.processor.writeMultipleCoils(unitIdentifier, request); } @Override protected WriteMultipleRegistersResponse writeMultipleRegisters(short unitIdentifier, WriteMultipleRegistersRequest request) { return this.processor.writeMultipleRegisters(unitIdentifier, request); } } ================================================ FILE: easymodbus4j-extension/src/main/java/com/github/zengfr/easymodbus4j/processor/AbstractModbusProcessor.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.processor; import com.github.zengfr.easymodbus4j.func.AbstractRequest; import com.github.zengfr.easymodbus4j.protocol.ModbusFunction; import com.github.zengfr.easymodbus4j.util.ModbusFunctionUtil; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public abstract class AbstractModbusProcessor implements ModbusProcessor { private short transactionIdentifierOffset; private boolean isShowFrameDetail; public AbstractModbusProcessor() { this((short) 0, true); } public AbstractModbusProcessor(short transactionIdentifierOffset, boolean isShowFrameDetail) { this.transactionIdentifierOffset = transactionIdentifierOffset; this.isShowFrameDetail = isShowFrameDetail; } protected boolean isRequestResponseMatch(AbstractRequest reqFunc, ModbusFunction respFunc) { return reqFunc != null && respFunc != null && reqFunc.getFunctionCode() == respFunc.getFunctionCode(); } protected boolean isRequestResponseValueMatch(AbstractRequest reqFunc, ModbusFunction respFunc) { byte[] respFuncValuesArray = ModbusFunctionUtil.getFunctionValues(respFunc); return isRequestResponseValueMatch(reqFunc, respFuncValuesArray); } protected boolean isRequestResponseValueMatch(AbstractRequest reqFunc, byte[] respFuncValuesArray) { if (reqFunc == null) return false; int quantityOfInputRegisters = reqFunc.getValue(); return (quantityOfInputRegisters * 2 == respFuncValuesArray.length) || (respFuncValuesArray.length == 1 && quantityOfInputRegisters == respFuncValuesArray.length); } public short getTransactionIdentifierOffset() { return this.transactionIdentifierOffset; } public boolean isShowFrameDetail() { return isShowFrameDetail; }; } ================================================ FILE: easymodbus4j-extension/src/main/java/com/github/zengfr/easymodbus4j/processor/ModbusMasterResponseProcessor.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.processor; import com.github.zengfr.easymodbus4j.func.AbstractRequest; import com.github.zengfr.easymodbus4j.protocol.ModbusFunction; import io.netty.channel.Channel; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public interface ModbusMasterResponseProcessor extends ModbusProcessor { boolean processResponseFrame(Channel channel,int unitId, AbstractRequest reqFunc, ModbusFunction respFunc); } ================================================ FILE: easymodbus4j-extension/src/main/java/com/github/zengfr/easymodbus4j/processor/ModbusProcessor.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.processor; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public interface ModbusProcessor { short getTransactionIdentifierOffset(); boolean isShowFrameDetail(); } ================================================ FILE: easymodbus4j-extension/src/main/java/com/github/zengfr/easymodbus4j/processor/ModbusSlaveRequestProcessor.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.zengfr.easymodbus4j.processor; import com.github.zengfr.easymodbus4j.func.request.ReadCoilsRequest; import com.github.zengfr.easymodbus4j.func.request.ReadDiscreteInputsRequest; import com.github.zengfr.easymodbus4j.func.request.ReadHoldingRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.ReadInputRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.WriteMultipleCoilsRequest; import com.github.zengfr.easymodbus4j.func.request.WriteMultipleRegistersRequest; import com.github.zengfr.easymodbus4j.func.request.WriteSingleCoilRequest; import com.github.zengfr.easymodbus4j.func.request.WriteSingleRegisterRequest; import com.github.zengfr.easymodbus4j.func.response.ReadCoilsResponse; import com.github.zengfr.easymodbus4j.func.response.ReadDiscreteInputsResponse; import com.github.zengfr.easymodbus4j.func.response.ReadHoldingRegistersResponse; import com.github.zengfr.easymodbus4j.func.response.ReadInputRegistersResponse; import com.github.zengfr.easymodbus4j.func.response.WriteMultipleCoilsResponse; import com.github.zengfr.easymodbus4j.func.response.WriteMultipleRegistersResponse; import com.github.zengfr.easymodbus4j.func.response.WriteSingleCoilResponse; import com.github.zengfr.easymodbus4j.func.response.WriteSingleRegisterResponse; /** * @author zengfr QQ:362505707/1163551688 Email:zengfr3000@qq.com * https://github.com/zengfr/easymodbus4j */ public interface ModbusSlaveRequestProcessor extends ModbusProcessor { ReadCoilsResponse readCoils(short unitId, ReadCoilsRequest request); ReadDiscreteInputsResponse readDiscreteInputs(short unitId, ReadDiscreteInputsRequest request); ReadInputRegistersResponse readInputRegisters(short unitId, ReadInputRegistersRequest request); ReadHoldingRegistersResponse readHoldingRegisters(short unitId, ReadHoldingRegistersRequest request); WriteSingleCoilResponse writeSingleCoil(short unitId, WriteSingleCoilRequest request); WriteSingleRegisterResponse writeSingleRegister(short unitId, WriteSingleRegisterRequest request); WriteMultipleCoilsResponse writeMultipleCoils(short unitId, WriteMultipleCoilsRequest request); WriteMultipleRegistersResponse writeMultipleRegisters(short unitId, WriteMultipleRegistersRequest request); }