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