项目初始化
29
.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
# idea
|
||||
/.idea/
|
||||
**/target/
|
||||
|
||||
/log/
|
||||
BIN
images/0.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
images/1.gif
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
images/11.gif
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
images/12.gif
Normal file
|
After Width: | Height: | Size: 361 B |
BIN
images/a.gif
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/calendar.jpg
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
images/excel.gif
Normal file
|
After Width: | Height: | Size: 142 B |
BIN
images/his.gif
Normal file
|
After Width: | Height: | Size: 370 B |
BIN
images/login.gif
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
images/mar.gif
Normal file
|
After Width: | Height: | Size: 180 B |
BIN
images/now.gif
Normal file
|
After Width: | Height: | Size: 202 B |
BIN
images/tr.gif
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
images/任务查询.gif
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/作业查询.gif
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/堆垛机.gif
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/小车.gif
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
images/红.gif
Normal file
|
After Width: | Height: | Size: 499 B |
BIN
images/红22.gif
Normal file
|
After Width: | Height: | Size: 390 B |
BIN
images/红22.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
images/红23.gif
Normal file
|
After Width: | Height: | Size: 403 B |
BIN
images/红25.gif
Normal file
|
After Width: | Height: | Size: 431 B |
BIN
images/绿.gif
Normal file
|
After Width: | Height: | Size: 515 B |
BIN
images/绿23.gif
Normal file
|
After Width: | Height: | Size: 404 B |
BIN
images/绿23.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
images/绿24.gif
Normal file
|
After Width: | Height: | Size: 417 B |
BIN
images/绿25.gif
Normal file
|
After Width: | Height: | Size: 434 B |
BIN
images/设备监控.gif
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/调度操作.gif
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/调度日志.gif
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/黄.gif
Normal file
|
After Width: | Height: | Size: 529 B |
BIN
images/黄25.gif
Normal file
|
After Width: | Height: | Size: 445 B |
BIN
images/黄25.jpg
Normal file
|
After Width: | Height: | Size: 25 KiB |
3
out/production/ft503-wcs/META-INF/MANIFEST.MF
Normal file
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: com.wms.dss.ats.customs.abb.form.ABBMainFrame
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping>
|
||||
<class name="com.wms.dss.ats.customs.abb.model.BasZxlx"
|
||||
table="bas_zxlx">
|
||||
<id name="zxlx" type="string">
|
||||
<column name="zxlx"/>
|
||||
</id>
|
||||
<property name="length" type="string">
|
||||
<column name="length" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="width" type="string">
|
||||
<column name="width" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="spare1" type="string">
|
||||
<column name="spare1" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="spare2" type="string">
|
||||
<column name="spare2" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="spare3" type="string">
|
||||
<column name="spare3" length="255" />
|
||||
</property>
|
||||
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping>
|
||||
<class name="com.wms.dss.ats.customs.abb.model.CarDeviceExecutionQueue"
|
||||
table="car_device_execution_queue">
|
||||
<id name="id" type="java.lang.Long">
|
||||
<column name="id"/>
|
||||
</id>
|
||||
<property name="taskCode" type="string">
|
||||
<column name="task_code" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="fromStation" type="string">
|
||||
<column name="from_station" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="toStation" type="string">
|
||||
<column name="to_station" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="containerCode" type="string">
|
||||
<column name="container_code" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="status" type="string">
|
||||
<column name="status" length="30" />
|
||||
</property>
|
||||
|
||||
<property name="createTime" type="timestamp">
|
||||
<column name="create_time" />
|
||||
</property>
|
||||
|
||||
<property name="startTime" type="timestamp">
|
||||
<column name="start_time" />
|
||||
</property>
|
||||
|
||||
<property name="finishTime" type="timestamp">
|
||||
<column name="finish_time" />
|
||||
</property>
|
||||
<property name="rwh" type="string">
|
||||
<column name="rwh" length="255" />
|
||||
</property>
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
<hibernate-mapping>
|
||||
<class name="com.wms.dss.ats.customs.abb.model.KzxcSsjMsg"
|
||||
table="kzxc_ssj_msg">
|
||||
<id name="ssjNo" type="java.lang.String">
|
||||
<column name="ssj_no"/>
|
||||
</id>
|
||||
<property name="rkdw" column="rkdw"/>
|
||||
<property name="zxlx" column="zxlx"/>
|
||||
<property name="rwh" column="rwh"/>
|
||||
<property name="status" column="status"/>
|
||||
<property name="qx" column="qx"/>
|
||||
<property name="fhwc" column="fhwc"/>
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping>
|
||||
<class name="com.wms.dss.ats.customs.abb.model.LineStatus"
|
||||
table="line_status">
|
||||
<id name="ssjNo" type="java.lang.String">
|
||||
<column name="ssj_no"/>
|
||||
</id>
|
||||
<property name="status" type="java.lang.String">
|
||||
<column name="status"/>
|
||||
</property>
|
||||
<property name="mode" type="java.lang.String">
|
||||
<column name="mode"/>
|
||||
</property>
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping>
|
||||
<class name="com.wms.dss.ats.customs.abb.model.RgvDeviceExecutionQueue"
|
||||
table="rgv_device_execution_queue">
|
||||
<id name="rwh" type="java.lang.Integer">
|
||||
<column name="rwh"/>
|
||||
</id>
|
||||
<property name="devName" type="java.lang.String">
|
||||
<column name="dev_name" />
|
||||
</property>
|
||||
<!-- 普通字段映射 -->
|
||||
<property name="devId" type="int">
|
||||
<column name="dev_id" />
|
||||
</property>
|
||||
|
||||
<property name="rwzt" type="int">
|
||||
<column name="rwzt" />
|
||||
</property>
|
||||
|
||||
<property name="ydz" type="int">
|
||||
<column name="ydz" />
|
||||
</property>
|
||||
|
||||
<property name="yzd" type="int">
|
||||
<column name="yzd" />
|
||||
</property>
|
||||
|
||||
<property name="mbdz" type="int">
|
||||
<column name="mbdz" />
|
||||
</property>
|
||||
|
||||
<property name="mbzd" type="int">
|
||||
<column name="mbzd" />
|
||||
</property>
|
||||
|
||||
<property name="xf" type="string">
|
||||
<column name="xf" length="80" />
|
||||
</property>
|
||||
|
||||
<property name="rwlx" type="int">
|
||||
<column name="rwlx" />
|
||||
</property>
|
||||
|
||||
<property name="scsj" type="string">
|
||||
<column name="scsj" length="20" />
|
||||
</property>
|
||||
|
||||
<property name="xfsj" type="string">
|
||||
<column name="xfsj" length="20" />
|
||||
</property>
|
||||
|
||||
<property name="jssj" type="string">
|
||||
<column name="jssj" length="20" />
|
||||
</property>
|
||||
|
||||
<property name="mlfs" type="int">
|
||||
<column name="mlfs" />
|
||||
</property>
|
||||
|
||||
<property name="trayCode" type="string">
|
||||
<column name="tray_code" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="hd" type="int">
|
||||
<column name="hd" />
|
||||
</property>
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping>
|
||||
<class name="com.wms.dss.ats.customs.abb.model.RgvDeviceExecutionQueueFinish"
|
||||
table="rgv_device_execution_queue_finish">
|
||||
<id name="rwh" type="java.lang.Integer">
|
||||
<column name="rwh"/>
|
||||
</id>
|
||||
<property name="devName" type="java.lang.String">
|
||||
<column name="dev_name" />
|
||||
</property>
|
||||
<!-- 普通字段映射 -->
|
||||
<property name="devId" type="int">
|
||||
<column name="dev_id" />
|
||||
</property>
|
||||
|
||||
<property name="rwzt" type="int">
|
||||
<column name="rwzt" />
|
||||
</property>
|
||||
|
||||
<property name="ydz" type="int">
|
||||
<column name="ydz" />
|
||||
</property>
|
||||
|
||||
<property name="yzd" type="int">
|
||||
<column name="yzd" />
|
||||
</property>
|
||||
|
||||
<property name="mbdz" type="int">
|
||||
<column name="mbdz" />
|
||||
</property>
|
||||
|
||||
<property name="mbzd" type="int">
|
||||
<column name="mbzd" />
|
||||
</property>
|
||||
|
||||
<property name="xf" type="string">
|
||||
<column name="xf" length="80" />
|
||||
</property>
|
||||
|
||||
<property name="rwlx" type="int">
|
||||
<column name="rwlx" />
|
||||
</property>
|
||||
|
||||
<property name="scsj" type="string">
|
||||
<column name="scsj" length="20" />
|
||||
</property>
|
||||
|
||||
<property name="xfsj" type="string">
|
||||
<column name="xfsj" length="20" />
|
||||
</property>
|
||||
|
||||
<property name="jssj" type="string">
|
||||
<column name="jssj" length="20" />
|
||||
</property>
|
||||
|
||||
<property name="mlfs" type="int">
|
||||
<column name="mlfs" />
|
||||
</property>
|
||||
|
||||
<property name="trayCode" type="string">
|
||||
<column name="tray_code" length="255" />
|
||||
</property>
|
||||
|
||||
<property name="hd" type="int">
|
||||
<column name="hd" />
|
||||
</property>
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
<hibernate-mapping>
|
||||
<class name="com.wms.dss.ats.customs.abb.model.RgvMsg" table="rgv_msg">
|
||||
<id name="id" column="id">
|
||||
<generator class="assigned"/>
|
||||
</id>
|
||||
<property name="devName" column="dev_name"/>
|
||||
<property name="rwh" column="rwh"/>
|
||||
<property name="czfs" column="czfs"/>
|
||||
<property name="yxzt" column="yxzt"/>
|
||||
<property name="ydz" column="ydz"/>
|
||||
<property name="mbdz" column="mbdz"/>
|
||||
<property name="yczt" column="yczt"/>
|
||||
<property name="yxxf" column="yxxf"/>
|
||||
<property name="jdbz" column="jdbz"/>
|
||||
<property name="trayCode" column="tray_code"/>
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
<hibernate-mapping>
|
||||
<class name="com.wms.dss.ats.customs.abb.model.SsjMsg" table="ssj_msg">
|
||||
<id name="ssjNo" column="ssj_no">
|
||||
<generator class="assigned"/>
|
||||
</id>
|
||||
<property name="rkdw" column="rkdw"/>
|
||||
<property name="ckkx" column="ckkx"/>
|
||||
<property name="rwh" column="rwh"/>
|
||||
<property name="status" column="status"/>
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping>
|
||||
<class name="com.wms.dss.ats.customs.abb.model.End"
|
||||
table="end">
|
||||
<id name="id" type="java.lang.Integer">
|
||||
<column name="id"/>
|
||||
</id>
|
||||
<property name="finishTime" type="java.util.Date">
|
||||
<column name="finish_time"/>
|
||||
</property>
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>PLCͨ<EFBFBD><EFBFBD>,<2C><>ȡPLC<4C><43><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD>
|
||||
41
out/production/ft503-wcs/log4j.properties
Normal file
@@ -0,0 +1,41 @@
|
||||
# Configure logging for testing
|
||||
# ???????INFO?debug<info<warn<error<fatal
|
||||
#
|
||||
log4j.rootLogger=info,stdout,SFILE
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{MM-dd HH:mm:ss.SSS} %-5p [%t] %37c %3x - %m%n
|
||||
log4j.appender.SFILE=org.apache.log4j.RollingFileAppender
|
||||
#log4j.appender.SFILE.DatePattern='.'yyyy-ww
|
||||
log4j.appender.SFILE.Append = true
|
||||
log4j.appender.SFILE.MaxFileSize=10MB
|
||||
log4j.appender.SFILE.MaxBackupIndex=50
|
||||
log4j.appender.SFILE.File=log/wmsServer.log
|
||||
log4j.appender.SFILE.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.SFILE.layout.ConversionPattern=%d{MM-dd HH:mm:ss.SSS} %-5p [%t] %37c %3x - %m%n
|
||||
log4j.logger.org.directwebremoting = ERROR
|
||||
|
||||
#?????????????????*******************************
|
||||
log4j.logger.robot=info,robot
|
||||
log4j.appender.robot=org.apache.log4j.RollingFileAppender
|
||||
#??????????
|
||||
log4j.additivity.robot = false
|
||||
log4j.appender.robot.Append = true
|
||||
log4j.appender.robot.MaxFileSize=10MB
|
||||
log4j.appender.robot.MaxBackupIndex=50
|
||||
log4j.appender.robot.File=log/wmsServer_plc.log
|
||||
log4j.appender.robot.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.robot.layout.ConversionPattern=%d{MM-dd HH:mm:ss.SSS} %-5p [%t] %37c %3x - %m%n
|
||||
|
||||
#???????????????*******************************
|
||||
log4j.logger.catchclap=info,catchclap
|
||||
log4j.appender.catchclap=org.apache.log4j.RollingFileAppender
|
||||
#??????????
|
||||
log4j.additivity.catchclap = false
|
||||
log4j.appender.catchclap.Append = true
|
||||
log4j.appender.catchclap.MaxFileSize=10MB
|
||||
log4j.appender.catchclap.MaxBackupIndex=50
|
||||
log4j.appender.catchclap.File=log/wmsServer_catchclap.log
|
||||
log4j.appender.catchclap.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.catchclap.layout.ConversionPattern=%d{MM-dd HH:mm:ss.SSS} %-5p [%t] %37c %3x - %m%n
|
||||
3
src/META-INF/MANIFEST.MF
Normal file
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: com.wms.dss.ats.customs.abb.form.ABBMainFrame
|
||||
|
||||
338
src/com/intelligt/modbus/jlibmodbus/Modbus.java
Normal file
@@ -0,0 +1,338 @@
|
||||
package com.intelligt.modbus.jlibmodbus;
|
||||
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
final public class Modbus {
|
||||
final static public int MAX_CONNECTION_TIMEOUT = 3000;
|
||||
final static public int MAX_RESPONSE_TIMEOUT = 1000;
|
||||
final static public int MAX_PDU_LENGTH = 254;
|
||||
/*
|
||||
slave id + function code.
|
||||
Note that actually the modbus pdu doesn't include the "slave id" field.
|
||||
*/
|
||||
final static public int MIN_PDU_LENGTH = 2;
|
||||
final static public int MAX_TCP_ADU_LENGTH = 260;
|
||||
final static public int MAX_RTU_ADU_LENGTH = 256;
|
||||
final static public int MAX_REGISTER_VALUE = 0xFFFF;
|
||||
final static public int MIN_START_ADDRESS = 0x0000;
|
||||
final static public int MAX_START_ADDRESS = 0xFFFF;
|
||||
final static public int MAX_READ_COIL_COUNT = 0x7D0;
|
||||
final static public int MAX_WRITE_COIL_COUNT = 0x7B0;
|
||||
final static public int MAX_READ_REGISTER_COUNT = 0x7D;
|
||||
final static public int MAX_WRITE_REGISTER_COUNT = 0x7B;
|
||||
final static public int MAX_FIFO_COUNT = 31;
|
||||
final static public int MIN_SERVER_ADDRESS = 1;
|
||||
final static public int MAX_SERVER_ADDRESS = 247;
|
||||
final static public int TCP_PORT = 502;
|
||||
final static public int PROTOCOL_ID = 0;
|
||||
final static public int TCP_DEFAULT_ID = 0xFF;
|
||||
final static public int BROADCAST_ID = 0x00;
|
||||
final static public int ASCII_CODE_CR = 0xd;
|
||||
final static public int ASCII_CODE_LF = 0xa;
|
||||
final static public int ASCII_CODE_COLON = 0x3a;
|
||||
final static public int COIL_VALUE_ON = 0xff00;
|
||||
final static public int COIL_VALUE_OFF = 0x0000;
|
||||
final static public int TRANSACTION_ID_MAX_VALUE = 0xFFFF;
|
||||
final static public int DEFAULT_READ_TIMEOUT = 1000;
|
||||
|
||||
final static private Logger log = Logger.getLogger(Modbus.class.getName());
|
||||
static private LogLevel logLevel = LogLevel.LEVEL_RELEASE;
|
||||
static private boolean autoIncrementTransactionId = false;
|
||||
|
||||
/**
|
||||
* the end of message delimiter, (LF character by default)
|
||||
*/
|
||||
static private int asciiMsgDelimiter = Modbus.ASCII_CODE_LF;
|
||||
|
||||
static {
|
||||
setLogLevel(logLevel);
|
||||
log().setUseParentHandlers(false);
|
||||
log().addHandler(new Handler() {
|
||||
@Override
|
||||
public void publish(LogRecord record) {
|
||||
System.out.println(record.getLevel().getName() + ": " + record.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
//do nothing
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Modbus() {
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for the version of the library.
|
||||
*
|
||||
* @return a string representing the version
|
||||
*/
|
||||
static public String getVersion() {
|
||||
return Version.getVersion();
|
||||
}
|
||||
|
||||
static public void setAsciiInputDelimiter(int asciiMsgDelimiter) {
|
||||
Modbus.asciiMsgDelimiter = asciiMsgDelimiter;
|
||||
}
|
||||
|
||||
static public int getAsciiMsgDelimiter() {
|
||||
return asciiMsgDelimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for log level
|
||||
*
|
||||
* @return current log level
|
||||
*/
|
||||
static public LogLevel getLogLevel() {
|
||||
return logLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* changes the log level for all loggers used
|
||||
*
|
||||
* @param level - LogLevel instance
|
||||
* @see LogLevel
|
||||
*/
|
||||
static public void setLogLevel(LogLevel level) {
|
||||
logLevel = level;
|
||||
log.setLevel(level.value());
|
||||
for (Handler handler : log.getHandlers()) {
|
||||
handler.setLevel(level.value());
|
||||
}
|
||||
}
|
||||
|
||||
static public boolean isLoggingEnabled() {
|
||||
return getLogLevel() != LogLevel.LEVEL_RELEASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for default logger
|
||||
*
|
||||
* @return default logger
|
||||
*/
|
||||
static public Logger log() {
|
||||
return log;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts ON/OFF value to boolean
|
||||
*
|
||||
* @param s 0xFF00 of 0x0000
|
||||
* @return true if s equals 0xFF00, else false
|
||||
*/
|
||||
static public boolean toCoil(int s) {
|
||||
return (((short) s) & 0xffff) == Modbus.COIL_VALUE_ON;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts boolean to ON/OFF value
|
||||
*
|
||||
* @param c a coil value
|
||||
* @return 0xFF00 if coil value is true, else 0x0000
|
||||
*/
|
||||
static public int fromCoil(boolean c) {
|
||||
return c ? Modbus.COIL_VALUE_ON : Modbus.COIL_VALUE_OFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* validates address of server
|
||||
*
|
||||
* @param serverAddress - The modbus server address
|
||||
* @return "true" if serverAddress is correct, else "false".
|
||||
*/
|
||||
static public boolean checkServerAddress(int serverAddress) {
|
||||
/*
|
||||
* hook for server address is equals zero:
|
||||
* some of modbus tcp slaves sets the UnitId value to zero, not ignoring value in this field.
|
||||
*/
|
||||
switch (serverAddress) {
|
||||
case 0x00:
|
||||
//Modbus.log().info("Broadcast message");
|
||||
return true;
|
||||
case 0xFF:
|
||||
//Modbus.log().info("Using 0xFF ModbusTCP default slave id");
|
||||
return true;
|
||||
default:
|
||||
return !(serverAddress < Modbus.MIN_SERVER_ADDRESS || serverAddress > Modbus.MAX_SERVER_ADDRESS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* validates is the value in the range from min to max.
|
||||
*
|
||||
* @param value - the value for checkFrame
|
||||
* @param min - minimum
|
||||
* @param max - maximum
|
||||
* @return "true" if value in the range from min to max, else "false".
|
||||
*/
|
||||
static private boolean checkRange(int value, int min, int max) {
|
||||
return !(value < min || value > max);
|
||||
}
|
||||
|
||||
/**
|
||||
* validates the value in the range from 1 to max.
|
||||
*
|
||||
* @param value - the value for checkFrame
|
||||
* @param max - maximum
|
||||
* @return "true" if value in the range from 1 to max, else "false".
|
||||
*/
|
||||
static private boolean checkQuantity(int value, int max) {
|
||||
return checkRange(value, 1, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* validates data offset in the range from Modbus.MIN_START_ADDRESS to max.
|
||||
*
|
||||
* @param value - the offset for checkFrame
|
||||
* @param max - maximum
|
||||
* @return "true" if offset in the range from Modbus.MIN_START_ADDRESS to max, else "false".
|
||||
*/
|
||||
static private boolean checkStartAddress(int value, int max) {
|
||||
return checkRange(value, MIN_START_ADDRESS, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* validates number of registers for read
|
||||
*
|
||||
* @param value - register count
|
||||
* @return "true" if quantity is correct, else "false".
|
||||
*/
|
||||
static public boolean checkReadRegisterCount(int value) {
|
||||
return checkQuantity(value, Modbus.MAX_READ_REGISTER_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* validates number of registers for write
|
||||
*
|
||||
* @param value - register count
|
||||
* @return "true" if quantity is correct, else "false".
|
||||
*/
|
||||
static public boolean checkWriteRegisterCount(int value) {
|
||||
return checkQuantity(value, Modbus.MAX_WRITE_REGISTER_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* validates number of coils for read
|
||||
*
|
||||
* @param value - coil count
|
||||
* @return "true" if quantity is correct, else "false".
|
||||
*/
|
||||
static public boolean checkReadCoilCount(int value) {
|
||||
return checkQuantity(value, Modbus.MAX_READ_COIL_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* validates number of coils for write
|
||||
*
|
||||
* @param value - coil count
|
||||
* @return "true" if quantity is correct, else "false".
|
||||
*/
|
||||
static public boolean checkWriteCoilCount(int value) {
|
||||
return checkQuantity(value, Modbus.MAX_WRITE_COIL_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* validates start address for read/write
|
||||
*
|
||||
* @param value - start address
|
||||
* @return "true" if start address is correct, else "false".
|
||||
*/
|
||||
static public boolean checkStartAddress(int value) {
|
||||
return checkStartAddress(value, Modbus.MAX_START_ADDRESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* validates end address for read/write
|
||||
* end address = start address + quantity
|
||||
*
|
||||
* @param value - end address
|
||||
* @return "true" if end address is correct, else "false".
|
||||
*/
|
||||
static public boolean checkEndAddress(int value) {
|
||||
return checkStartAddress(value, Modbus.MAX_START_ADDRESS + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* validates register value
|
||||
*
|
||||
* @param value - value of register
|
||||
* @return "true" if register value is correct, else "false".
|
||||
*/
|
||||
static public boolean checkRegisterValue(int value) {
|
||||
return checkRange((short)value, 0, Modbus.MAX_REGISTER_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns autoIncrementTransactionId variable
|
||||
*
|
||||
* @return "true" if autoincrement of TransactionId field is enabled, else "false".
|
||||
*/
|
||||
public static boolean isAutoIncrementTransactionId() {
|
||||
return Modbus.autoIncrementTransactionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* activates auto increment of TransactionId field. if you do not use ModbusTCP, invocation has no effect.
|
||||
*
|
||||
* @param autoIncrementTransactionId - new value of the autoIncrementTransactionId variable
|
||||
*/
|
||||
public static void setAutoIncrementTransactionId(boolean autoIncrementTransactionId) {
|
||||
Modbus.autoIncrementTransactionId = autoIncrementTransactionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* logging.Level wrapper.
|
||||
*/
|
||||
public enum LogLevel {
|
||||
LEVEL_RELEASE(Level.SEVERE),
|
||||
LEVEL_WARNINGS(Level.WARNING),
|
||||
LEVEL_VERBOSE(Level.INFO),
|
||||
LEVEL_DEBUG(Level.ALL);
|
||||
|
||||
final private Level value;
|
||||
|
||||
LogLevel(Level value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
*
|
||||
* @return logging.Level instance
|
||||
*/
|
||||
private Level value() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/com/intelligt/modbus/jlibmodbus/Version.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.intelligt.modbus.jlibmodbus;
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
/**
|
||||
* A class to keep the current version in.
|
||||
* It's an auto generated class, which used by
|
||||
* Modbus.getVersion().
|
||||
*
|
||||
* @since 1.2.3
|
||||
*/
|
||||
class Version {
|
||||
|
||||
private static final String version = "1.2.9.7";
|
||||
/**
|
||||
* returns the current version of the JLibModbus library
|
||||
*
|
||||
* @return a string representing the version
|
||||
*/
|
||||
public static String getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
304
src/com/intelligt/modbus/jlibmodbus/data/CommStatus.java
Normal file
@@ -0,0 +1,304 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.data.comm.ModbusCommEvent;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class CommStatus {
|
||||
/**
|
||||
* PDU length(254) - server_address - function_code - 3 x 2 Bytes
|
||||
*/
|
||||
public static final int EVENT_QUEUE_CAPACITY = Modbus.MAX_PDU_LENGTH - 8;
|
||||
/**
|
||||
* When the remote device enters its Listen Only Mode, all active communication controls are
|
||||
* turned off. The Ready watchdog timer is allowed to expire, locking the controls off. While the
|
||||
* device is in this mode, any MODBUS messages addressed to it or broadcast are monitored,
|
||||
* but no actions will be taken and no responses will be sent.
|
||||
*/
|
||||
private boolean listenOnlyMode = false;
|
||||
|
||||
volatile private boolean restartCommunicationsOption = false;
|
||||
|
||||
volatile private boolean clearLog = false;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private int diagnosticRegister = 0;
|
||||
/**
|
||||
* the status word will be all ones (FF FF hex) if a previously–issued program command is still being
|
||||
* processed by the remote device (a busy condition exists). Otherwise, the status word will be all zeros.
|
||||
*/
|
||||
private int commStatus = 0;
|
||||
/**
|
||||
* event counter is incremented once for each successful message completion. It
|
||||
* is not incremented for exception responses, poll commands, or fetch event counter
|
||||
* commands.
|
||||
*/
|
||||
private int eventCount = 0;
|
||||
/**
|
||||
* the quantity of messages that the remote device has detected
|
||||
* on the communications system since its last restart
|
||||
*/
|
||||
private int busMessageCount = 0;
|
||||
/**
|
||||
* the quantity of messages addressed to the remote device, or
|
||||
* broadcast, that the remote device has processed since its last restart
|
||||
*/
|
||||
private int slaveMessageCount = 0;
|
||||
/**
|
||||
* the quantity of CRC errors encountered by the remote device since its last restart
|
||||
*/
|
||||
private int communicationErrorCount = 0;
|
||||
/**
|
||||
* the quantity of MODBUS exception responses returned by the remote device since its last restart
|
||||
*/
|
||||
private int exceptionErrorCount = 0;
|
||||
/**
|
||||
* the quantity of messages addressed to the remote device for
|
||||
* which it has returned no response (neither a normal response nor an exception response),
|
||||
* since its last restart
|
||||
*/
|
||||
private int slaveNoResponseCount = 0;
|
||||
/**
|
||||
* the quantity of messages addressed to the remote device for
|
||||
* which it returned a Negative Acknowledge (NAK) exception response, since its last restart
|
||||
*/
|
||||
private int slaveNAKCount = 0;
|
||||
/**
|
||||
* the quantity of messages addressed to the remote device for
|
||||
* which it returned a Slave Device Busy exception response, since its last restart
|
||||
*/
|
||||
private int slaveBusyCount = 0;
|
||||
/**
|
||||
* the quantity of messages addressed to the remote device that
|
||||
* it could not handle due to a character overrun condition, since its last restart
|
||||
*/
|
||||
private int characterOverrunCount = 0;
|
||||
/**
|
||||
* Comm event queue. Capacity = PDU length(254) - server_address - function_code - 3 x 2 Bytes,
|
||||
* (Length of Status, Event Count and Message Count).
|
||||
*/
|
||||
final private LinkedList<ModbusCommEvent> eventQueue = new LinkedList<ModbusCommEvent>();
|
||||
|
||||
public CommStatus() {
|
||||
}
|
||||
|
||||
public void enter() {
|
||||
commStatus = 0xffff;
|
||||
}
|
||||
|
||||
public void leave() {
|
||||
commStatus = 0;
|
||||
}
|
||||
|
||||
public void incEventCounter() {
|
||||
eventCount++;
|
||||
}
|
||||
|
||||
public void incBusMessageCounter() {
|
||||
busMessageCount++;
|
||||
}
|
||||
|
||||
public void incSlaveMessageCounter() {
|
||||
slaveMessageCount++;
|
||||
}
|
||||
|
||||
public void incCommErrorCounter() {
|
||||
communicationErrorCount++;
|
||||
}
|
||||
|
||||
public void incExErrorCounter() {
|
||||
exceptionErrorCount++;
|
||||
}
|
||||
|
||||
public void incNoResponseCounter() {
|
||||
exceptionErrorCount++;
|
||||
}
|
||||
|
||||
public void incSlaveNAKCounter() {
|
||||
exceptionErrorCount++;
|
||||
}
|
||||
|
||||
public void incSlaveBusyCounter() {
|
||||
exceptionErrorCount++;
|
||||
}
|
||||
|
||||
public void incCharacterOverrunCounter() {
|
||||
exceptionErrorCount++;
|
||||
}
|
||||
|
||||
public int getCommStatus() {
|
||||
return commStatus;
|
||||
}
|
||||
|
||||
public void setCommStatus(int commStatus) {
|
||||
this.commStatus = commStatus;
|
||||
}
|
||||
|
||||
public int getEventCount() {
|
||||
return eventCount;
|
||||
}
|
||||
|
||||
public void setEventCount(int eventCount) {
|
||||
this.eventCount = eventCount;
|
||||
}
|
||||
|
||||
public int getMessageCount() {
|
||||
return busMessageCount;
|
||||
}
|
||||
|
||||
public void setBusMessageCount(int busMessageCount) {
|
||||
this.busMessageCount = busMessageCount;
|
||||
}
|
||||
|
||||
public int getSlaveMessageCount() {
|
||||
return slaveMessageCount;
|
||||
}
|
||||
|
||||
public void setSlaveMessageCount(int slaveMessageCount) {
|
||||
this.slaveMessageCount = slaveMessageCount;
|
||||
}
|
||||
|
||||
public int getCommunicationErrorCount() {
|
||||
return communicationErrorCount;
|
||||
}
|
||||
|
||||
public void setCommunicationErrorCount(int communicationErrorCount) {
|
||||
this.communicationErrorCount = communicationErrorCount;
|
||||
}
|
||||
|
||||
public int getExceptionErrorCount() {
|
||||
return exceptionErrorCount;
|
||||
}
|
||||
|
||||
public void setExceptionErrorCount(int exceptionErrorCount) {
|
||||
this.exceptionErrorCount = exceptionErrorCount;
|
||||
}
|
||||
|
||||
public int getSlaveNoResponseCount() {
|
||||
return slaveNoResponseCount;
|
||||
}
|
||||
|
||||
public void setSlaveNoResponseCount(int slaveNoResponseCount) {
|
||||
this.slaveNoResponseCount = slaveNoResponseCount;
|
||||
}
|
||||
|
||||
public int getSlaveNAKCount() {
|
||||
return slaveNAKCount;
|
||||
}
|
||||
|
||||
public void setSlaveNAKCount(int slaveNAKCount) {
|
||||
this.slaveNAKCount = slaveNAKCount;
|
||||
}
|
||||
|
||||
public int getSlaveBusyCount() {
|
||||
return slaveBusyCount;
|
||||
}
|
||||
|
||||
public void setSlaveBusyCount(int slaveBusyCount) {
|
||||
this.slaveBusyCount = slaveBusyCount;
|
||||
}
|
||||
|
||||
public int getCharacterOverrunCount() {
|
||||
return characterOverrunCount;
|
||||
}
|
||||
|
||||
public void setCharacterOverrunCount(int characterOverrunCount) {
|
||||
this.characterOverrunCount = characterOverrunCount;
|
||||
}
|
||||
|
||||
public int getDiagnosticRegister() {
|
||||
return diagnosticRegister;
|
||||
}
|
||||
|
||||
public void setDiagnosticRegister(int diagnosticRegister) {
|
||||
this.diagnosticRegister = diagnosticRegister;
|
||||
}
|
||||
|
||||
public void setAsciiInputDelimiter(int asciiInputDelimiter) {
|
||||
Modbus.setAsciiInputDelimiter(asciiInputDelimiter);
|
||||
}
|
||||
|
||||
public boolean isListenOnlyMode() {
|
||||
return listenOnlyMode;
|
||||
}
|
||||
|
||||
public void setListenOnlyMode(boolean listenOnlyMode) {
|
||||
this.listenOnlyMode = listenOnlyMode;
|
||||
}
|
||||
|
||||
public boolean isRestartCommunicationsOption() {
|
||||
return restartCommunicationsOption;
|
||||
}
|
||||
|
||||
public void setRestartCommunicationsOption(boolean restartCommunications) {
|
||||
this.restartCommunicationsOption = restartCommunications;
|
||||
}
|
||||
|
||||
public boolean isClearLog() {
|
||||
return clearLog;
|
||||
}
|
||||
|
||||
public void setClearLog(boolean clearLog) {
|
||||
this.clearLog = clearLog;
|
||||
}
|
||||
|
||||
public void clearCountersAndDiagnosticRegister() {
|
||||
setBusMessageCount(0);
|
||||
setEventCount(0);
|
||||
setCharacterOverrunCount(0);
|
||||
setCommunicationErrorCount(0);
|
||||
setExceptionErrorCount(0);
|
||||
setSlaveNoResponseCount(0);
|
||||
setSlaveBusyCount(0);
|
||||
setSlaveMessageCount(0);
|
||||
setSlaveNAKCount(0);
|
||||
}
|
||||
|
||||
public void restartCommunicationsOption() {
|
||||
clearCountersAndDiagnosticRegister();
|
||||
setListenOnlyMode(false);
|
||||
if (isClearLog()) {
|
||||
getEventLog().clear();
|
||||
setClearLog(false);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ModbusCommEvent> getEventLog() {
|
||||
return eventQueue;
|
||||
}
|
||||
|
||||
public void setEventQueue(List<ModbusCommEvent> eventQueue) {
|
||||
this.eventQueue.clear();
|
||||
this.eventQueue.addAll(eventQueue);
|
||||
}
|
||||
|
||||
public void addEvent(ModbusCommEvent event) {
|
||||
if (eventQueue.size() >= EVENT_QUEUE_CAPACITY)
|
||||
eventQueue.poll();
|
||||
eventQueue.add(event);
|
||||
}
|
||||
}
|
||||
215
src/com/intelligt/modbus/jlibmodbus/data/DataHolder.java
Normal file
@@ -0,0 +1,215 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.data.mei.ReadDeviceIdentificationInterface;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalFunctionException;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusFileRecord;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusFunctionCode;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/*
|
||||
facade
|
||||
*/
|
||||
public class DataHolder {
|
||||
final private CommStatus commStatus = new CommStatus();
|
||||
final private Map<Integer, FifoQueue> fifoMap = new TreeMap<Integer, FifoQueue>();
|
||||
final private Map<Integer, ModbusFile> fileMap = new TreeMap<Integer, ModbusFile>();
|
||||
private ModbusCoils coils = null;
|
||||
private ModbusCoils discreteInputs = null;
|
||||
private ModbusHoldingRegisters holdingRegisters = null;
|
||||
private ModbusHoldingRegisters inputRegisters = null;
|
||||
private SlaveId slaveId = null;
|
||||
private ExceptionStatus exceptionStatus = null;
|
||||
private ReadDeviceIdentificationInterface readDeviceIdentificationInterface = null;
|
||||
|
||||
private void checkPointer(Object o, int offset) throws IllegalDataAddressException {
|
||||
if (o == null)
|
||||
throw new IllegalDataAddressException(offset);
|
||||
}
|
||||
|
||||
public int readHoldingRegister(int offset) throws IllegalDataAddressException {
|
||||
checkPointer(holdingRegisters, offset);
|
||||
return holdingRegisters.get(offset);
|
||||
}
|
||||
|
||||
public int[] readHoldingRegisterRange(int offset, int quantity) throws IllegalDataAddressException {
|
||||
checkPointer(holdingRegisters, offset);
|
||||
return holdingRegisters.getRange(offset, quantity);
|
||||
}
|
||||
|
||||
public void writeHoldingRegister(int offset, int value) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkPointer(holdingRegisters, offset);
|
||||
holdingRegisters.set(offset, value);
|
||||
}
|
||||
|
||||
public void writeHoldingRegisterRange(int offset, int[] range) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkPointer(holdingRegisters, offset);
|
||||
holdingRegisters.setRange(offset, range);
|
||||
}
|
||||
|
||||
public int[] readInputRegisterRange(int offset, int quantity) throws IllegalDataAddressException {
|
||||
checkPointer(inputRegisters, offset);
|
||||
return inputRegisters.getRange(offset, quantity);
|
||||
}
|
||||
|
||||
public int[] readFifoQueue(int fifoPointerAddress) throws IllegalDataValueException, IllegalDataAddressException {
|
||||
FifoQueue fifoQueue = fifoMap.get(fifoPointerAddress);
|
||||
checkPointer(fifoQueue, fifoPointerAddress);
|
||||
return fifoQueue.get();
|
||||
}
|
||||
|
||||
public boolean[] readCoilRange(int offset, int quantity) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkPointer(coils, offset);
|
||||
return coils.getRange(offset, quantity);
|
||||
}
|
||||
|
||||
public void writeCoil(int offset, boolean value) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkPointer(coils, offset);
|
||||
coils.set(offset, value);
|
||||
}
|
||||
|
||||
public void writeCoilRange(int offset, boolean[] range) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkPointer(coils, offset);
|
||||
coils.setRange(offset, range);
|
||||
}
|
||||
|
||||
public byte[] readSlaveId() throws IllegalFunctionException {
|
||||
if (slaveId == null)
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.REPORT_SLAVE_ID.toInt());
|
||||
return slaveId.get();
|
||||
}
|
||||
|
||||
public int readExceptionStatus() throws IllegalFunctionException {
|
||||
if (exceptionStatus == null)
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.READ_EXCEPTION_STATUS.toInt());
|
||||
return exceptionStatus.get();
|
||||
}
|
||||
|
||||
public boolean[] readDiscreteInputRange(int offset, int quantity) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkPointer(discreteInputs, offset);
|
||||
return discreteInputs.getRange(offset, quantity);
|
||||
}
|
||||
|
||||
public void readFileRecord(ModbusFileRecord fileRecord) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
ModbusFile file = getFile(fileRecord.getFileNumber());
|
||||
checkPointer(file, fileRecord.getFileNumber());
|
||||
fileRecord.writeRegisters(file.read(fileRecord.getRecordNumber(), fileRecord.getRecordLength()));
|
||||
}
|
||||
|
||||
public void writeFileRecord(ModbusFileRecord fileRecord) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
ModbusFile file = getFile(fileRecord.getFileNumber());
|
||||
checkPointer(file, fileRecord.getFileNumber());
|
||||
file.write(fileRecord.getRecordNumber(), fileRecord.getRegisters());
|
||||
}
|
||||
|
||||
public ModbusCoils getCoils() {
|
||||
return coils;
|
||||
}
|
||||
|
||||
public void setCoils(ModbusCoils coils) {
|
||||
this.coils = coils;
|
||||
}
|
||||
|
||||
public ModbusCoils getDiscreteInputs() {
|
||||
return discreteInputs;
|
||||
}
|
||||
|
||||
public void setDiscreteInputs(ModbusCoils discreteInputs) {
|
||||
this.discreteInputs = discreteInputs;
|
||||
}
|
||||
|
||||
public ModbusHoldingRegisters getHoldingRegisters() {
|
||||
return holdingRegisters;
|
||||
}
|
||||
|
||||
public void setHoldingRegisters(ModbusHoldingRegisters holdingRegisters) {
|
||||
this.holdingRegisters = holdingRegisters;
|
||||
}
|
||||
|
||||
public ModbusHoldingRegisters getInputRegisters() {
|
||||
return inputRegisters;
|
||||
}
|
||||
|
||||
public void setInputRegisters(ModbusHoldingRegisters inputRegisters) {
|
||||
this.inputRegisters = inputRegisters;
|
||||
}
|
||||
|
||||
public CommStatus getCommStatus() {
|
||||
return commStatus;
|
||||
}
|
||||
|
||||
public SlaveId getSlaveId() {
|
||||
return slaveId;
|
||||
}
|
||||
|
||||
public void setSlaveId(SlaveId slaveId) {
|
||||
this.slaveId = slaveId;
|
||||
}
|
||||
|
||||
public ExceptionStatus getExceptionStatus() {
|
||||
return exceptionStatus;
|
||||
}
|
||||
|
||||
public void setExceptionStatus(ExceptionStatus exceptionStatus) {
|
||||
this.exceptionStatus = exceptionStatus;
|
||||
}
|
||||
|
||||
public FifoQueue getFifoQueue(int fifoPointerAddress) throws IllegalDataAddressException {
|
||||
FifoQueue file = fifoMap.get(fifoPointerAddress);
|
||||
if (file == null)
|
||||
throw new IllegalDataAddressException(fifoPointerAddress);
|
||||
return file;
|
||||
}
|
||||
|
||||
public void addFifoQueue(FifoQueue fifoQueue, int fifoPointerAddress) throws IllegalDataAddressException {
|
||||
if (fifoMap.containsKey(fifoPointerAddress))
|
||||
throw new IllegalDataAddressException(fifoPointerAddress);
|
||||
fifoMap.put(fifoPointerAddress, fifoQueue);
|
||||
}
|
||||
|
||||
public void addFile(ModbusFile file) throws IllegalDataAddressException {
|
||||
if (fileMap.containsKey(file.getNumber()))
|
||||
throw new IllegalDataAddressException(file.getNumber());
|
||||
fileMap.put(file.getNumber(), file);
|
||||
}
|
||||
|
||||
public ModbusFile getFile(int number) throws IllegalDataAddressException {
|
||||
ModbusFile file = fileMap.get(number);
|
||||
if (file == null)
|
||||
throw new IllegalDataAddressException(number);
|
||||
return file;
|
||||
}
|
||||
|
||||
public ReadDeviceIdentificationInterface getReadDeviceIdentificationInterface() {
|
||||
return readDeviceIdentificationInterface;
|
||||
}
|
||||
|
||||
public void setReadDeviceIdentificationInterface(ReadDeviceIdentificationInterface readDeviceIdentificationInterface) {
|
||||
this.readDeviceIdentificationInterface = readDeviceIdentificationInterface;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
abstract public class DataHolderBuilder {
|
||||
protected DataHolder dataHolder;
|
||||
|
||||
protected DataHolderBuilder() {
|
||||
createNewDataHolder();
|
||||
}
|
||||
|
||||
public DataHolder getDataHolder() {
|
||||
return dataHolder;
|
||||
}
|
||||
|
||||
final public void createNewDataHolder() {
|
||||
dataHolder = new DataHolder();
|
||||
}
|
||||
|
||||
public abstract void buildCoils();
|
||||
|
||||
public abstract void buildDiscreteInputs();
|
||||
|
||||
public abstract void buildHoldingRegisters();
|
||||
|
||||
public abstract void buildInputRegisters();
|
||||
|
||||
public abstract void buildSlaveId();
|
||||
|
||||
public abstract void buildExceptionStatus();
|
||||
|
||||
public abstract void buildFifoQueue();
|
||||
|
||||
public abstract void readDeviceIdentificationInterface();
|
||||
|
||||
final public DataHolder build() {
|
||||
createNewDataHolder();
|
||||
buildCoils();
|
||||
buildDiscreteInputs();
|
||||
buildHoldingRegisters();
|
||||
buildInputRegisters();
|
||||
buildSlaveId();
|
||||
buildExceptionStatus();
|
||||
buildFifoQueue();
|
||||
readDeviceIdentificationInterface();
|
||||
return getDataHolder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public interface ExceptionStatus {
|
||||
int get();
|
||||
|
||||
void set(int exceptionStatus);
|
||||
}
|
||||
58
src/com/intelligt/modbus/jlibmodbus/data/FifoQueue.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
abstract public class FifoQueue {
|
||||
|
||||
final private int capacity;
|
||||
|
||||
public FifoQueue(int capacity) {
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
public abstract int size();
|
||||
|
||||
abstract protected int[] peekImpl();
|
||||
|
||||
abstract protected void addImpl(int register);
|
||||
|
||||
abstract protected void pollImpl();
|
||||
|
||||
synchronized final public void poll() {
|
||||
if (size() != 0)
|
||||
pollImpl();
|
||||
}
|
||||
|
||||
synchronized final public void add(int register) {
|
||||
if (size() < capacity)
|
||||
addImpl(register);
|
||||
}
|
||||
|
||||
synchronized final public int[] get() throws IllegalDataValueException {
|
||||
if (size() > 31 || size() == 0) {
|
||||
throw new IllegalDataValueException();
|
||||
}
|
||||
return peekImpl();
|
||||
}
|
||||
}
|
||||
124
src/com/intelligt/modbus/jlibmodbus/data/ModbusCoils.java
Normal file
@@ -0,0 +1,124 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.DataUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* since 1.2.8.4 it extends Observable to notify observers if register values was changed.
|
||||
*
|
||||
* @see java.util.Observable
|
||||
* @see java.util.Observer
|
||||
*/
|
||||
public class ModbusCoils extends ModbusValues<Boolean> {
|
||||
private boolean[] coils = new boolean[0];
|
||||
|
||||
public ModbusCoils(int size) {
|
||||
this.coils = new boolean[Modbus.checkEndAddress(size) ? size : Modbus.MAX_START_ADDRESS];
|
||||
}
|
||||
|
||||
public ModbusCoils(byte[] bytes) {
|
||||
coils = DataUtils.toBitsArray(bytes, bytes.length*8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
return DataUtils.toByteArray(coils);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBytesBe(byte[] bytes) {
|
||||
coils = DataUtils.toBitsArray(bytes, bytes.length*8);
|
||||
}
|
||||
|
||||
public void setBytes(byte[] bytes, int quantity) {
|
||||
coils = DataUtils.toBitsArray(bytes, quantity);
|
||||
}
|
||||
|
||||
void setSize(int size) {
|
||||
if (coils.length != size) {
|
||||
coils = Arrays.copyOf(coils, size);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImpl(int offset, Boolean coil) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkAddress(offset);
|
||||
synchronized (this) {
|
||||
coils[offset] = coil;
|
||||
}
|
||||
}
|
||||
|
||||
public void setRange(int offset, boolean[] range) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkRange(offset, range.length);
|
||||
if (!Modbus.checkWriteCoilCount(range.length))
|
||||
throw new IllegalDataValueException();
|
||||
synchronized (this) {
|
||||
for (int i = 0; i < range.length; i++) {
|
||||
set(offset + i, range[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean[] getRange(int offset, int quantity) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkRange(offset, quantity);
|
||||
if (!Modbus.checkReadCoilCount(quantity))
|
||||
throw new IllegalDataValueException();
|
||||
synchronized (this) {
|
||||
return Arrays.copyOfRange(coils, offset, offset + quantity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public int getQuantity() {
|
||||
return coils.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public int getByteCount() {
|
||||
return (int)Math.ceil((double)coils.length/8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean get(int offset) throws IllegalDataAddressException {
|
||||
checkAddress(offset);
|
||||
synchronized (this) {
|
||||
return coils[offset];
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRange(int offset, int quantity) throws IllegalDataAddressException {
|
||||
if (offset + quantity > getQuantity())
|
||||
throw new IllegalDataAddressException(offset);
|
||||
}
|
||||
|
||||
private void checkAddress(int offset) throws IllegalDataAddressException {
|
||||
if (!Modbus.checkStartAddress(offset))
|
||||
throw new IllegalDataAddressException(offset);
|
||||
}
|
||||
}
|
||||
65
src/com/intelligt/modbus/jlibmodbus/data/ModbusFile.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
|
||||
|
||||
import java.util.Observable;
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "A file is an organization of records. Each file contains 10000 records, addressed 0000 to
|
||||
* 9999 decimal or 0X0000 to 0X270F. For example, record 12 is addressed as 12.
|
||||
* ...
|
||||
* The quantity of registers to be read, combined with all other fields in the expected response,
|
||||
* must not exceed the allowable length of the MODBUS PDU : 253 bytes."
|
||||
* <p>
|
||||
* so the length of file record must not exceed 250 bytes(253 - function_code - resp_data_len - sub_req_resp_len).
|
||||
*/
|
||||
abstract public class ModbusFile extends Observable {
|
||||
private final int number;
|
||||
|
||||
public ModbusFile(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
/**
|
||||
* read modbus file record
|
||||
*
|
||||
* @param recordNumber number of a record
|
||||
* @param recordLength read register count
|
||||
* @return record data
|
||||
* @throws IllegalDataAddressException record with number recordNumber not exist or recordLength bytes not allowable.
|
||||
*/
|
||||
abstract public int[] read(int recordNumber, int recordLength) throws IllegalDataAddressException;
|
||||
|
||||
public void write(int recordNumber, int[] buffer) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
notifyObservers(new int[]{recordNumber, buffer.length});
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.DataUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* since 1.2.8.4 it extends Observable to notify observers if register values was changed.
|
||||
*
|
||||
* @see java.util.Observable
|
||||
* @see java.util.Observer
|
||||
*/
|
||||
public class ModbusHoldingRegisters extends ModbusValues<Integer> {
|
||||
|
||||
private int[] registers = new int[0];
|
||||
|
||||
public ModbusHoldingRegisters(int size) {
|
||||
registers = new int[(Modbus.checkEndAddress(size) ? size : Modbus.MAX_START_ADDRESS)];
|
||||
}
|
||||
|
||||
public ModbusHoldingRegisters() {
|
||||
|
||||
}
|
||||
|
||||
void setSize(int size) {
|
||||
synchronized (this) {
|
||||
if (registers.length != size) {
|
||||
registers = Arrays.copyOf(registers, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkOffsetAndValue(int offset, int value) throws IllegalDataValueException, IllegalDataAddressException {
|
||||
checkAddress(offset);
|
||||
checkValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImpl(int offset, Integer value) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkAddress(offset);
|
||||
checkValue(value);
|
||||
synchronized (this) {
|
||||
registers[offset] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void setRange(int offset, int[] range) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkRange(offset, range.length);
|
||||
if (!Modbus.checkWriteRegisterCount(range.length))
|
||||
throw new IllegalDataAddressException(offset);
|
||||
synchronized (this) {
|
||||
for (int i = 0; i < range.length; i++) {
|
||||
set(offset + i, range[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setInt8At(int offset, int i8) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkOffsetAndValue(offset, i8);
|
||||
set(offset, (int) DataUtils.byteLow(i8));
|
||||
}
|
||||
|
||||
public void setInt16At(int offset, int i16) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
checkOffsetAndValue(offset, i16);
|
||||
set(offset, i16);
|
||||
}
|
||||
|
||||
public void setInt32At(int offset, int i32) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
setInt16At(offset, DataUtils.wordLow(i32));
|
||||
setInt16At(offset + 1, DataUtils.wordHigh(i32));
|
||||
}
|
||||
|
||||
public void setInt64At(int offset, long i64) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
setInt32At(offset, (int) (i64 & 0xffffffff));
|
||||
setInt32At(offset + 2, (int) ((i64 >> 32) & 0xffffffff));
|
||||
}
|
||||
|
||||
public void setFloat32At(int offset, float f32) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
setInt32At(offset, Float.floatToRawIntBits(f32));
|
||||
}
|
||||
|
||||
public void setFloat64At(int offset, double f64) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
setInt64At(offset, Double.doubleToRawLongBits(f64));
|
||||
}
|
||||
|
||||
public int getInt8At(int offset) throws IllegalDataAddressException {
|
||||
checkAddress(offset);
|
||||
return DataUtils.byteLow(get(offset));
|
||||
}
|
||||
|
||||
public int getInt16At(int offset) throws IllegalDataAddressException {
|
||||
return get(offset);
|
||||
}
|
||||
|
||||
public int getInt32At(int offset) throws IllegalDataAddressException {
|
||||
return (getInt16At(offset)&0xffff) | ((getInt16At(offset + 1)&0xffff) << 16);
|
||||
}
|
||||
|
||||
public long getInt64At(int offset) throws IllegalDataAddressException {
|
||||
return (getInt32At(offset)&0xffffffffL) | ((getInt32At(offset + 2)&0xffffffffL) << 32);
|
||||
}
|
||||
|
||||
public float getFloat32At(int offset) throws IllegalDataAddressException {
|
||||
return Float.intBitsToFloat(getInt32At(offset));
|
||||
}
|
||||
|
||||
public double getFloat64At(int offset) throws IllegalDataAddressException {
|
||||
return Double.longBitsToDouble(getInt64At(offset));
|
||||
}
|
||||
|
||||
public int[] getRegisters() {
|
||||
return Arrays.copyOf(registers, getQuantity());
|
||||
}
|
||||
|
||||
public void setRegisters(int[] registers) {
|
||||
this.registers = Arrays.copyOf(registers, registers.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public int getByteCount() {
|
||||
return getQuantity() * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
return DataUtils.toByteArray(registers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBytesBe(byte[] bytes) {
|
||||
registers = DataUtils.BeToIntArray(bytes);
|
||||
}
|
||||
|
||||
public void setBytesLe(byte[] bytes) {
|
||||
this.registers = DataUtils.LeToIntArray(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public int getQuantity() {
|
||||
return registers.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer get(int offset) throws IllegalDataAddressException {
|
||||
checkAddress(offset);
|
||||
synchronized (this) {
|
||||
return registers[offset];
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getRange(int offset, int quantity) throws IllegalDataAddressException {
|
||||
checkRange(offset, quantity);
|
||||
if (!Modbus.checkReadRegisterCount(quantity))
|
||||
throw new IllegalDataAddressException(offset);
|
||||
synchronized (this) {
|
||||
return Arrays.copyOfRange(registers, offset, offset + quantity);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRange(int offset, int quantity) throws IllegalDataAddressException {
|
||||
if (offset + quantity > getQuantity())
|
||||
throw new IllegalDataAddressException(offset);
|
||||
}
|
||||
|
||||
private void checkAddress(int offset) throws IllegalDataAddressException {
|
||||
if (DataUtils.wordLow(offset) > (getQuantity() - 1))
|
||||
throw new IllegalDataAddressException(offset);
|
||||
}
|
||||
|
||||
private void checkValue(int value) throws IllegalDataValueException {
|
||||
if (!Modbus.checkRegisterValue(value))
|
||||
throw new IllegalDataValueException();
|
||||
}
|
||||
}
|
||||
62
src/com/intelligt/modbus/jlibmodbus/data/ModbusValues.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Observable;
|
||||
|
||||
abstract public class ModbusValues<T> extends Observable implements Iterable<T> {
|
||||
|
||||
abstract public int getQuantity();
|
||||
|
||||
abstract public T get(int offset) throws IllegalDataAddressException;
|
||||
|
||||
abstract public void setImpl(int offset, T value) throws IllegalDataAddressException, IllegalDataValueException;
|
||||
|
||||
abstract public int getByteCount();
|
||||
|
||||
abstract public byte[] getBytes();
|
||||
|
||||
abstract public void setBytesBe(byte[] bytes);
|
||||
|
||||
final public void set(int offset, T value) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
setImpl(offset, value);
|
||||
setChanged();
|
||||
notifyObservers(new int[]{offset, 1});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
|
||||
int index = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < getQuantity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
if (hasNext()) {
|
||||
try {
|
||||
return get(index++);
|
||||
} catch (IllegalDataAddressException e) {
|
||||
Modbus.log().severe(this.getClass().getSimpleName() + " " + e.getLocalizedMessage() + ": quantity = " + getQuantity() + ", index = " + index);
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.data.mei.ReadDeviceIdentificationInterface;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class SimpleDataHolderBuilder extends DataHolderBuilder {
|
||||
final private int coilCount;
|
||||
final private int discreteInputCount;
|
||||
final private int holdingRegisterCount;
|
||||
final private int inputRegisterCount;
|
||||
final private int slaveIdSize;
|
||||
|
||||
public SimpleDataHolderBuilder(int size) {
|
||||
coilCount = discreteInputCount = holdingRegisterCount = inputRegisterCount = slaveIdSize = size;
|
||||
}
|
||||
|
||||
public SimpleDataHolderBuilder(int slaveIdSize, int inputRegisterCount, int holdingRegisterCount, int discreteInputCount, int coilCount) {
|
||||
this.slaveIdSize = slaveIdSize;
|
||||
this.inputRegisterCount = inputRegisterCount;
|
||||
this.holdingRegisterCount = holdingRegisterCount;
|
||||
this.discreteInputCount = discreteInputCount;
|
||||
this.coilCount = coilCount;
|
||||
}
|
||||
|
||||
public DataHolder getDataHolder() {
|
||||
return dataHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildCoils() {
|
||||
dataHolder.setCoils(new ModbusCoils(coilCount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildDiscreteInputs() {
|
||||
dataHolder.setDiscreteInputs(new ModbusCoils(discreteInputCount));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildHoldingRegisters() {
|
||||
dataHolder.setHoldingRegisters(new ModbusHoldingRegisters(holdingRegisterCount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildInputRegisters() {
|
||||
dataHolder.setInputRegisters(new ModbusHoldingRegisters(inputRegisterCount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildSlaveId() {
|
||||
dataHolder.setSlaveId(new SimpleSlaveId(slaveIdSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildExceptionStatus() {
|
||||
dataHolder.setExceptionStatus(new SimpleExceptionStatus(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildFifoQueue() {
|
||||
try {
|
||||
dataHolder.addFifoQueue(new SimpleFifoQueue(), 0);
|
||||
} catch (IllegalDataAddressException e) {
|
||||
//it newer be thrown
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readDeviceIdentificationInterface() {
|
||||
dataHolder.setReadDeviceIdentificationInterface(new ReadDeviceIdentificationInterface());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class SimpleExceptionStatus implements ExceptionStatus {
|
||||
|
||||
int value;
|
||||
|
||||
public SimpleExceptionStatus() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public SimpleExceptionStatus(int value) {
|
||||
set(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public int get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void set(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class SimpleFifoQueue extends FifoQueue {
|
||||
|
||||
final private Queue<Integer> queue = new LinkedList<Integer>();
|
||||
|
||||
public SimpleFifoQueue() {
|
||||
super(Modbus.MAX_FIFO_COUNT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] peekImpl() {
|
||||
if (queue.size() > 0) {
|
||||
int[] r = new int[queue.size()];
|
||||
Iterator<Integer> iterator = queue.iterator();
|
||||
for (int i = 0; i < r.length && iterator.hasNext(); i++) {
|
||||
r[i] = iterator.next();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addImpl(int register) {
|
||||
queue.add(register);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void pollImpl() {
|
||||
queue.poll();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusFileRecord;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class SimpleModbusFile extends ModbusFile {
|
||||
|
||||
final private Map<Integer, ModbusFileRecord> records = new TreeMap<Integer, ModbusFileRecord>();
|
||||
|
||||
public SimpleModbusFile(int number) {
|
||||
super(number);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public int[] read(int recordNumber, int recordLength) throws IllegalDataAddressException {
|
||||
if (!records.containsKey(recordNumber))
|
||||
throw new IllegalDataAddressException(recordNumber);
|
||||
int[] buffer = records.get(recordNumber).getRegisters();
|
||||
if (buffer.length < recordLength)
|
||||
throw new IllegalDataAddressException(recordLength);
|
||||
return Arrays.copyOf(buffer, recordLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void write(int recordNumber, int[] buffer) throws IllegalDataAddressException, IllegalDataValueException {
|
||||
if (records.containsKey(recordNumber)) {
|
||||
records.get(recordNumber).writeRegisters(buffer);
|
||||
} else {
|
||||
records.put(recordNumber, new ModbusFileRecord(getNumber(), recordNumber, buffer));
|
||||
}
|
||||
super.write(recordNumber, buffer);
|
||||
}
|
||||
}
|
||||
43
src/com/intelligt/modbus/jlibmodbus/data/SimpleSlaveId.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class SimpleSlaveId implements SlaveId {
|
||||
|
||||
private byte[] bytes = null;
|
||||
|
||||
public SimpleSlaveId(int size) {
|
||||
bytes = new byte[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public byte[] get() {
|
||||
return Arrays.copyOf(bytes, bytes.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void set(byte[] data) {
|
||||
bytes = Arrays.copyOf(data, data.length);
|
||||
}
|
||||
}
|
||||
28
src/com/intelligt/modbus/jlibmodbus/data/SlaveId.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public interface SlaveId {
|
||||
byte[] get();
|
||||
|
||||
void set(byte[] data);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data.comm;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
abstract public class ModbusCommEvent {
|
||||
|
||||
final private Type type;
|
||||
private int event = 0;
|
||||
|
||||
public ModbusCommEvent(Type type, int event) {
|
||||
this.type = type;
|
||||
this.event = type.getCode() | event;
|
||||
}
|
||||
|
||||
static public ModbusCommEvent getEvent(int event) {
|
||||
for (Type t : Type.values()) {
|
||||
if ((t.getCode() & event) == t.getCode()) {
|
||||
switch (t) {
|
||||
case SEND:
|
||||
return new ModbusCommEventSend(event);
|
||||
case RECEIVE:
|
||||
return new ModbusCommEventReceive(event);
|
||||
case INITIATED_COMMUNICATION_RESTART:
|
||||
return new ModbusCommEventInitiatedCommunicationRestart(event);
|
||||
case ENTER_LISTEN_ONLY_MODE:
|
||||
return new ModbusCommEventEnterListenOnlyMode(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
protected boolean isBitsSet(int bits) {
|
||||
return (event & bits) == bits;
|
||||
}
|
||||
|
||||
public int getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
SEND(0x80),
|
||||
RECEIVE(0x40),
|
||||
INITIATED_COMMUNICATION_RESTART(0x0),
|
||||
ENTER_LISTEN_ONLY_MODE(0x10);
|
||||
|
||||
final private int code;
|
||||
|
||||
Type(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data.comm;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusCommEventEnterListenOnlyMode extends ModbusCommEvent {
|
||||
public ModbusCommEventEnterListenOnlyMode() {
|
||||
super(Type.ENTER_LISTEN_ONLY_MODE, 0);
|
||||
}
|
||||
|
||||
public ModbusCommEventEnterListenOnlyMode(int event) {
|
||||
super(Type.ENTER_LISTEN_ONLY_MODE, event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data.comm;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusCommEventInitiatedCommunicationRestart extends ModbusCommEvent {
|
||||
|
||||
public ModbusCommEventInitiatedCommunicationRestart() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
protected ModbusCommEventInitiatedCommunicationRestart(int event) {
|
||||
super(Type.INITIATED_COMMUNICATION_RESTART, event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data.comm;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusCommEventReceive extends ModbusCommEvent {
|
||||
final static private int BIT_COMMUNICATION_ERROR = 0x1;
|
||||
final static private int BIT_CHARACTER_OVERRUN = 0x10;
|
||||
final static private int BIT_CURRENTLY_IN_LISTEN_ONLY_MODE = 0x20;
|
||||
final static private int BIT_BROADCAST_RECEIVED = 0x40;
|
||||
|
||||
protected ModbusCommEventReceive(int event) {
|
||||
super(Type.RECEIVE, event);
|
||||
}
|
||||
|
||||
static public ModbusCommEventReceive createCommunicationError() {
|
||||
return new ModbusCommEventReceive(BIT_COMMUNICATION_ERROR);
|
||||
}
|
||||
|
||||
static public ModbusCommEventReceive createCharacterOverrun() {
|
||||
return new ModbusCommEventReceive(BIT_CHARACTER_OVERRUN);
|
||||
}
|
||||
|
||||
static public ModbusCommEventReceive createCurrentlyInListenOnlyMode() {
|
||||
return new ModbusCommEventReceive(BIT_CURRENTLY_IN_LISTEN_ONLY_MODE);
|
||||
}
|
||||
|
||||
static public ModbusCommEventReceive createBroadcastReceived() {
|
||||
return new ModbusCommEventReceive(BIT_BROADCAST_RECEIVED);
|
||||
}
|
||||
|
||||
public boolean isCurrentlyInListenOnlyMode() {
|
||||
return isBitsSet(BIT_CURRENTLY_IN_LISTEN_ONLY_MODE);
|
||||
}
|
||||
|
||||
public boolean isCharacterOverrun() {
|
||||
return isBitsSet(BIT_CHARACTER_OVERRUN);
|
||||
}
|
||||
|
||||
public boolean isCommunicationError() {
|
||||
return isBitsSet(BIT_COMMUNICATION_ERROR);
|
||||
}
|
||||
|
||||
public boolean isBroadcastReceived() {
|
||||
return isBitsSet(BIT_BROADCAST_RECEIVED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data.comm;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusCommEventSend extends ModbusCommEvent {
|
||||
final static private int BIT_READ_EXCEPTION_SENT = 0x1;
|
||||
final static private int BIT_SLAVE_ABORT_EXCEPTION_SENT = 0x2;
|
||||
final static private int BIT_SLAVE_BUSY_EXCEPTION_SENT = 0x4;
|
||||
final static private int BIT_SLAVE_PROGRAM_NAK_EXCEPTION_SENT = 0x8;
|
||||
final static private int BIT_WRITE_TIMEOUT_ERROR_OCCURRED = 0x10;
|
||||
final static private int BIT_CURRENTLY_IN_LISTEN_ONLY_MODE = 0x20;
|
||||
|
||||
protected ModbusCommEventSend(int event) {
|
||||
super(Type.SEND, event);
|
||||
}
|
||||
|
||||
static public ModbusCommEventSend createExceptionSentRead() {
|
||||
return new ModbusCommEventSend(BIT_READ_EXCEPTION_SENT);
|
||||
}
|
||||
|
||||
static public ModbusCommEventSend createExceptionSlaveSentAbort() {
|
||||
return new ModbusCommEventSend(BIT_SLAVE_ABORT_EXCEPTION_SENT);
|
||||
}
|
||||
|
||||
static public ModbusCommEventSend createExceptionSlaveSentBusy() {
|
||||
return new ModbusCommEventSend(BIT_SLAVE_BUSY_EXCEPTION_SENT);
|
||||
}
|
||||
|
||||
static public ModbusCommEventSend createExceptionSentSlaveProgramNAK() {
|
||||
return new ModbusCommEventSend(BIT_SLAVE_PROGRAM_NAK_EXCEPTION_SENT);
|
||||
}
|
||||
|
||||
static public ModbusCommEventSend createWriteTimeoutErrorOccurred() {
|
||||
return new ModbusCommEventSend(BIT_WRITE_TIMEOUT_ERROR_OCCURRED);
|
||||
}
|
||||
|
||||
static public ModbusCommEventSend createCurrentlyInListenOnlyMode() {
|
||||
return new ModbusCommEventSend(BIT_CURRENTLY_IN_LISTEN_ONLY_MODE);
|
||||
}
|
||||
|
||||
public boolean isCurrentlyInListenOnlyMode() {
|
||||
return isBitsSet(BIT_CURRENTLY_IN_LISTEN_ONLY_MODE);
|
||||
}
|
||||
|
||||
public boolean isExceptionSentRead() {
|
||||
return isBitsSet(BIT_READ_EXCEPTION_SENT);
|
||||
}
|
||||
|
||||
public boolean isExceptionSlaveSentAbort() {
|
||||
return isBitsSet(BIT_SLAVE_ABORT_EXCEPTION_SENT);
|
||||
}
|
||||
|
||||
public boolean isExceptionSlaveSentBusy() {
|
||||
return isBitsSet(BIT_SLAVE_BUSY_EXCEPTION_SENT);
|
||||
}
|
||||
|
||||
public boolean isExceptionSentSlaveProgramNAK() {
|
||||
return isBitsSet(BIT_SLAVE_PROGRAM_NAK_EXCEPTION_SENT);
|
||||
}
|
||||
|
||||
public boolean isWriteTimeoutErrorOccurred() {
|
||||
return isBitsSet(BIT_WRITE_TIMEOUT_ERROR_OCCURRED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
package com.intelligt.modbus.jlibmodbus.data.mei;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ReadDeviceIdentificationInterface {
|
||||
|
||||
final static public int BASIC_OBJECT_COUNT = 3;
|
||||
final static public int REGULAR_OBJECT_COUNT = 0x7D;
|
||||
final static public int EXTENDED_OBJECT_COUNT = 0x7F;
|
||||
final static public int OBJECT_ID_VENDOR_NAME = 0;
|
||||
final static public int OBJECT_ID_PRODUCT_CODE = 1;
|
||||
final static public int OBJECT_ID_MAJOR_MINOR_REVISION = 2;
|
||||
final static public int OBJECT_ID_VENDOR_URL = 3;
|
||||
final static public int OBJECT_ID_PRODUCT_NAME = 4;
|
||||
final static public int OBJECT_ID_MODEL_NAME = 5;
|
||||
final static public int OBJECT_ID_USER_APPLICATION_NAME = 6;
|
||||
final private DataObjectsHolder dataObjectsBasic = new DataObjectsHolder(BASIC_OBJECT_COUNT);
|
||||
final private DataObjectsHolder dataObjectsRegular = new DataObjectsHolder(REGULAR_OBJECT_COUNT);
|
||||
final private DataObjectsHolder dataObjectsExtended = new DataObjectsHolder(EXTENDED_OBJECT_COUNT);
|
||||
|
||||
public ReadDeviceIdentificationInterface() {
|
||||
for (int i = 0; i < BASIC_OBJECT_COUNT; i++)
|
||||
dataObjectsBasic.add(new DataObject(i, new byte[0]));
|
||||
}
|
||||
|
||||
DataObjectsHolder getDataObjectsHolder(int id) {
|
||||
if (id < 0)
|
||||
throw new IllegalArgumentException();
|
||||
if (id >= REGULAR_OBJECT_COUNT)
|
||||
return dataObjectsExtended;
|
||||
if (id >= BASIC_OBJECT_COUNT)
|
||||
return dataObjectsRegular;
|
||||
return dataObjectsBasic;
|
||||
}
|
||||
|
||||
public void setValue(int id, String value) {
|
||||
setValue(new DataObject(id, value.getBytes(Charset.forName("UTF-8"))));
|
||||
}
|
||||
|
||||
public void setValue(DataObject dataObject) {
|
||||
getDataObjectsHolder(dataObject.getId()).add(dataObject);
|
||||
}
|
||||
|
||||
public DataObject getValue(int id) {
|
||||
return getDataObjectsHolder(id).get(id);
|
||||
}
|
||||
|
||||
public DataObject getVendorName() {
|
||||
return getValue(OBJECT_ID_VENDOR_NAME);
|
||||
}
|
||||
|
||||
public void setVendorName(String value) {
|
||||
setValue(OBJECT_ID_VENDOR_NAME, value);
|
||||
}
|
||||
|
||||
public DataObject getProductCode() {
|
||||
return getValue(OBJECT_ID_PRODUCT_CODE);
|
||||
}
|
||||
|
||||
public void setProductCode(String value) {
|
||||
setValue(OBJECT_ID_PRODUCT_CODE, value);
|
||||
}
|
||||
|
||||
public DataObject getMajorMinorRevision() {
|
||||
return getValue(OBJECT_ID_MAJOR_MINOR_REVISION);
|
||||
}
|
||||
|
||||
public void setMajorMinorRevision(String value) {
|
||||
setValue(OBJECT_ID_MAJOR_MINOR_REVISION, value);
|
||||
}
|
||||
|
||||
public DataObject getVendorUrl() {
|
||||
return getValue(OBJECT_ID_VENDOR_URL);
|
||||
}
|
||||
|
||||
public void setVendorUrl(String value) {
|
||||
setValue(OBJECT_ID_VENDOR_URL, value);
|
||||
}
|
||||
|
||||
public DataObject getProductName() {
|
||||
return getValue(OBJECT_ID_PRODUCT_NAME);
|
||||
}
|
||||
|
||||
public void setProductName(String value) {
|
||||
setValue(OBJECT_ID_PRODUCT_NAME, value);
|
||||
}
|
||||
|
||||
public DataObject getModelName() {
|
||||
return getValue(OBJECT_ID_MODEL_NAME);
|
||||
}
|
||||
|
||||
public void setModelName(String value) {
|
||||
setValue(OBJECT_ID_MODEL_NAME, value);
|
||||
}
|
||||
|
||||
public DataObject getUserApplicationName() {
|
||||
return getValue(OBJECT_ID_USER_APPLICATION_NAME);
|
||||
}
|
||||
|
||||
public void setUserApplicationName(String value) {
|
||||
setValue(OBJECT_ID_USER_APPLICATION_NAME, value);
|
||||
}
|
||||
|
||||
public DataObject[] getBasic() {
|
||||
return dataObjectsBasic.toArray();
|
||||
}
|
||||
|
||||
public DataObject[] getRegular() {
|
||||
return dataObjectsRegular.toArray();
|
||||
}
|
||||
|
||||
public DataObject[] getExtended() {
|
||||
return dataObjectsExtended.toArray();
|
||||
}
|
||||
|
||||
static public class DataObject {
|
||||
final private int id;
|
||||
private byte[] value;
|
||||
|
||||
public DataObject(int id, byte[] value) {
|
||||
this.id = id;
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return Arrays.copyOf(value, value.length);
|
||||
}
|
||||
|
||||
public void setValue(byte[] value) {
|
||||
this.value = Arrays.copyOf(value, value.length);
|
||||
}
|
||||
}
|
||||
|
||||
static private class DataObjectsHolder {
|
||||
final private int capacity;
|
||||
final TreeMap<Integer, DataObject> map;
|
||||
|
||||
public DataObjectsHolder(int capacity) {
|
||||
this.capacity = capacity;
|
||||
map = new TreeMap<Integer, DataObject>();
|
||||
}
|
||||
|
||||
public void add(DataObject dataObject) {
|
||||
if (map.containsKey(dataObject.getId())) {
|
||||
map.get(dataObject.getId()).setValue(dataObject.getValue());
|
||||
} else if (map.size() < capacity) {
|
||||
map.put(dataObject.getId(), dataObject);
|
||||
}
|
||||
}
|
||||
|
||||
public DataObject get(int id) {
|
||||
return map.get(id);
|
||||
}
|
||||
|
||||
public DataObject[] toArray() {
|
||||
return map.values().toArray(new DataObject[map.size()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "Specialized use in conjunction with programming
|
||||
* commands.
|
||||
* The server (or slave) has accepted the request
|
||||
* and is processing it, but a long duration of time
|
||||
* will be required to do so. This response is
|
||||
* returned to prevent a timeout error from occurring
|
||||
* in the client (or master). The client (or master)
|
||||
* can next issue a Poll Program Complete message
|
||||
* to determine if processing is completed."
|
||||
*/
|
||||
public class AcknowledgeException extends ModbusProtocolException {
|
||||
public AcknowledgeException() {
|
||||
super(ModbusExceptionCode.ACKNOWLEDGE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "Specialized use in conjunction with gateways,
|
||||
* indicates that the gateway was unable to allocate
|
||||
* an internal communication path from the input
|
||||
* port to the output port for processing the request.
|
||||
* Usually means that the gateway is misconfigured
|
||||
* or overloaded."
|
||||
*/
|
||||
public class GatewayPathUnavailableException extends ModbusProtocolException {
|
||||
public GatewayPathUnavailableException() {
|
||||
super(ModbusExceptionCode.GATEWAY_PATH_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "Specialized use in conjunction with gateways,
|
||||
* indicates that no response was obtained from the
|
||||
* target device. Usually means that the device is
|
||||
* not present on the network."
|
||||
*/
|
||||
public class GatewayTargetDeviceFailedToRespondException extends ModbusProtocolException {
|
||||
public GatewayTargetDeviceFailedToRespondException() {
|
||||
super(ModbusExceptionCode.GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "The data address received in the query is not an
|
||||
* allowable address for the server (or slave). More
|
||||
* specifically, the combination of reference number
|
||||
* and transfer length is invalid. For a controller with
|
||||
* 100 registers, the PDU addresses the first
|
||||
* register as 0, and the last one as 99. If a request
|
||||
* is submitted with a starting register address of 96
|
||||
* and a quantity of registers of 4, then this request
|
||||
* will successfully operate (address-wise at least)
|
||||
* on registers 96, 97, 98, 99. If a request is
|
||||
* submitted with a starting register address of 96
|
||||
* and a quantity of registers of 5, then this request
|
||||
* will fail with Exception Code 0x02 “Illegal Data
|
||||
* Address” since it attempts to operate on registers
|
||||
* 96, 97, 98, 99 and 100, and there is no register
|
||||
* with address 100."
|
||||
*/
|
||||
public class IllegalDataAddressException extends ModbusProtocolException {
|
||||
final private int dataAddress;
|
||||
|
||||
public IllegalDataAddressException(int dataAddress) {
|
||||
super(ModbusExceptionCode.ILLEGAL_DATA_ADDRESS);
|
||||
this.dataAddress = dataAddress;
|
||||
}
|
||||
|
||||
public int getDataAddress() {
|
||||
return dataAddress;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "A value contained in the query data field is not an
|
||||
* allowable value for server (or slave). This
|
||||
* indicates a fault in the structure of the remainder
|
||||
* of a complex request, such as that the implied
|
||||
* length is incorrect. It specifically does NOT mean
|
||||
* that a data item submitted for storage in a register
|
||||
* has a value outside the expectation of the
|
||||
* application program, since the MODBUS protocol
|
||||
* is unaware of the significance of any particular
|
||||
* value of any particular register."
|
||||
*/
|
||||
public class IllegalDataValueException extends ModbusProtocolException {
|
||||
|
||||
public IllegalDataValueException() {
|
||||
super(ModbusExceptionCode.ILLEGAL_DATA_VALUE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "The function code received in the query is not an
|
||||
* allowable action for the server (or slave). This
|
||||
* may be because the function code is only
|
||||
* applicable to newer devices, and was not
|
||||
* implemented in the unit selected. It could also
|
||||
* indicate that the server (or slave) is in the wrong
|
||||
* state to process a request of this type, for
|
||||
* example because it is unconfigured and is being
|
||||
* asked to return register values."
|
||||
*/
|
||||
public class IllegalFunctionException extends ModbusProtocolException {
|
||||
|
||||
final private int functionCode;
|
||||
|
||||
public IllegalFunctionException(int functionCode) {
|
||||
super(ModbusExceptionCode.ILLEGAL_FUNCTION);
|
||||
this.functionCode = functionCode;
|
||||
}
|
||||
|
||||
public int getFunctionCode() {
|
||||
return functionCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "Specialized use in conjunction with function codes
|
||||
* 20 and 21 and reference type 6, to indicate that
|
||||
* the extended file area failed to pass a consistency
|
||||
* checkFrame.
|
||||
* The server (or slave) attempted to read record
|
||||
* file, but detected a parity error in the memory.
|
||||
* The client (or master) can retry the request, but
|
||||
* service may be required on the server (or slave)
|
||||
* device."
|
||||
*/
|
||||
public class MemoryParityErrorException extends ModbusProtocolException {
|
||||
public MemoryParityErrorException() {
|
||||
super(ModbusExceptionCode.MEMORY_PARITY_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusChecksumException extends ModbusIOException {
|
||||
|
||||
public static final String CHECKSUM_ERROR_STRING = "checksum error: received %d, calculated %d";
|
||||
|
||||
public ModbusChecksumException(int recv, int calc) {
|
||||
super(String.format(CHECKSUM_ERROR_STRING, recv, calc));
|
||||
}
|
||||
|
||||
public ModbusChecksumException(int recv, int calc, Throwable cause) {
|
||||
super(String.format(CHECKSUM_ERROR_STRING, recv, calc), cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusIOException extends Exception {
|
||||
|
||||
public ModbusIOException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ModbusIOException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ModbusIOException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusMasterException extends Exception {
|
||||
|
||||
public ModbusMasterException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ModbusMasterException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusNumberException extends Exception {
|
||||
public ModbusNumberException(String message, int number) {
|
||||
super(message + " : " + number);
|
||||
}
|
||||
|
||||
public ModbusNumberException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
public class ModbusProtocolException extends Exception {
|
||||
|
||||
private final ModbusExceptionCode exception;
|
||||
|
||||
public ModbusProtocolException(ModbusExceptionCode exception) {
|
||||
super(exception.toString());
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
public ModbusExceptionCode getException() {
|
||||
return exception;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusSlaveException extends Exception {
|
||||
|
||||
public ModbusSlaveException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ModbusSlaveException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "Specialized use in conjunction with programming
|
||||
* commands.
|
||||
* The server (or slave) is engaged in processing a
|
||||
* long–duration program command. The client (or
|
||||
* master) should retransmit the message later when
|
||||
* the server (or slave) is free."
|
||||
*/
|
||||
public class SlaveDeviceBusyException extends ModbusProtocolException {
|
||||
public SlaveDeviceBusyException() {
|
||||
super(ModbusExceptionCode.SLAVE_DEVICE_BUSY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.intelligt.modbus.jlibmodbus.exception;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* quote from MODBUS Application Protocol Specification V1.1b
|
||||
* <p>
|
||||
* "An unrecoverable error occurred while the server
|
||||
* (or slave) was attempting to perform the
|
||||
* requested action."
|
||||
*/
|
||||
public class SlaveDeviceFailureException extends ModbusProtocolException {
|
||||
public SlaveDeviceFailureException() {
|
||||
super(ModbusExceptionCode.SLAVE_DEVICE_FAILURE);
|
||||
}
|
||||
}
|
||||
777
src/com/intelligt/modbus/jlibmodbus/master/ModbusMaster.java
Normal file
@@ -0,0 +1,777 @@
|
||||
package com.intelligt.modbus.jlibmodbus.master;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.data.CommStatus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusProtocolException;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.ModbusRequestBuilder;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.ModbusRequestFactory;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusFileRecord;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusMessage;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusRequest;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusResponse;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.mei.MEIReadDeviceIdentification;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.mei.ReadDeviceIdentificationCode;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.response.*;
|
||||
import com.intelligt.modbus.jlibmodbus.net.ModbusConnection;
|
||||
import com.intelligt.modbus.jlibmodbus.net.transport.ModbusTransport;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.FrameEvent;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.FrameEventListener;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.FrameEventListenerList;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusExceptionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
abstract public class ModbusMaster implements FrameEventListenerList {
|
||||
|
||||
final private ModbusConnection conn;
|
||||
final private BroadcastResponse broadcastResponse = new BroadcastResponse();
|
||||
private int transactionId = 0;
|
||||
private long requestTime = 0;
|
||||
|
||||
public ModbusMaster(ModbusConnection conn) {
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
public int getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public void setTransactionId(int transactionId) {
|
||||
this.transactionId = Math.min(Math.abs(transactionId), Modbus.TRANSACTION_ID_MAX_VALUE);
|
||||
}
|
||||
|
||||
protected ModbusConnection getConnection() {
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* this method allows you to implement your own behavior of connect method.
|
||||
*
|
||||
* @throws ModbusIOException
|
||||
*/
|
||||
protected void connectImpl() throws ModbusIOException {
|
||||
getConnection().open();
|
||||
}
|
||||
|
||||
/**
|
||||
* this method allows you to implement your own behavior of disconnect method.
|
||||
*
|
||||
* @throws ModbusIOException
|
||||
*/
|
||||
protected void disconnectImpl() throws ModbusIOException {
|
||||
getConnection().close();
|
||||
}
|
||||
|
||||
final public void connect() throws ModbusIOException {
|
||||
if (!isConnected()) {
|
||||
connectImpl();
|
||||
}
|
||||
}
|
||||
|
||||
final public void disconnect() throws ModbusIOException {
|
||||
if (isConnected()) {
|
||||
disconnectImpl();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return getConnection().isOpened();
|
||||
}
|
||||
|
||||
public void sendRequest(ModbusMessage msg) throws ModbusIOException {
|
||||
ModbusTransport transport = getConnection().getTransport();
|
||||
if (transport == null)
|
||||
throw new ModbusIOException("transport is null");
|
||||
transport.send(msg);
|
||||
requestTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
protected ModbusMessage readResponse(ModbusRequest request) throws ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
return getConnection().getTransport().readResponse(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* this function allows you to process your own ModbusRequest.
|
||||
* Each request class has a compliant response class for instance ReadHoldingRegistersRequest and ReadHoldingRegistersResponse.
|
||||
* If you process an instance of ReadHoldingRegistersRequest this function exactly either returns a ReadHoldingRegistersResponse instance or throws an exception.
|
||||
*
|
||||
* @param request an instance of ModbusRequest.
|
||||
* @return an instance of ModbusResponse.
|
||||
* @throws ModbusProtocolException
|
||||
* @throws ModbusIOException
|
||||
* @see ModbusRequestFactory
|
||||
* @see ModbusRequest
|
||||
* @see ModbusResponse
|
||||
* @see com.intelligt.modbus.jlibmodbus.msg.request
|
||||
* @see com.intelligt.modbus.jlibmodbus.msg.request
|
||||
*/
|
||||
synchronized public ModbusResponse processRequest(ModbusRequest request) throws ModbusProtocolException, ModbusIOException {
|
||||
try {
|
||||
sendRequest(request);
|
||||
if (request.getServerAddress() != Modbus.BROADCAST_ID) {
|
||||
do {
|
||||
try {
|
||||
ModbusResponse msg = (ModbusResponse) readResponse(request);
|
||||
request.validateResponse(msg);
|
||||
/*
|
||||
* if you have received an ACKNOWLEDGE,
|
||||
* it means that operation is in processing and you should be waiting for the answer
|
||||
*/
|
||||
if (msg.getModbusExceptionCode() != ModbusExceptionCode.ACKNOWLEDGE) {
|
||||
if (msg.isException())
|
||||
throw new ModbusProtocolException(msg.getModbusExceptionCode());
|
||||
return msg;
|
||||
}
|
||||
} catch (ModbusNumberException mne) {
|
||||
Modbus.log().warning(mne.getLocalizedMessage());
|
||||
}
|
||||
} while (System.currentTimeMillis() - requestTime < getConnection().getReadTimeout());
|
||||
/*
|
||||
* throw an exception if there is a response timeout
|
||||
*/
|
||||
throw new ModbusIOException("Response timeout.");
|
||||
} else {
|
||||
/*
|
||||
return because slaves do not respond broadcast requests
|
||||
*/
|
||||
broadcastResponse.setFunction(request.getFunction());
|
||||
return broadcastResponse;
|
||||
}
|
||||
} catch (ModbusIOException mioe) {
|
||||
disconnect();
|
||||
throw mioe;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ModbusMaster will block for only this amount of time.
|
||||
* If the timeout expires, a ModbusTransportException is raised, though the ModbusMaster is still valid.
|
||||
*
|
||||
* @param timeout the specified timeout, in milliseconds.
|
||||
*/
|
||||
public void setResponseTimeout(int timeout) {
|
||||
try {
|
||||
getConnection().setReadTimeout(timeout);
|
||||
} catch (Exception e) {
|
||||
Modbus.log().warning(e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to read the contents of a contiguous block of holding registers in a
|
||||
* remote device. The Request PDU specifies the starting register address and the number of
|
||||
* registers. In the PDU Registers are addressed starting at zero. Therefore registers numbered
|
||||
* 1-16 are addressed as 0-15.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param startAddress starting register address
|
||||
* @param quantity the number of registers
|
||||
* @return the register data
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public int[] readHoldingRegisters(int serverAddress, int startAddress, int quantity) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReadHoldingRegisters(serverAddress, startAddress, quantity);
|
||||
ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) processRequest(request);
|
||||
return response.getRegisters();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to read from 1 to 125 contiguous input registers in a remote
|
||||
* device. The Request PDU specifies the starting register address and the number of registers.
|
||||
* In the PDU Registers are addressed starting at zero. Therefore input registers numbered 1-16
|
||||
* are addressed as 0-15.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param startAddress starting register address
|
||||
* @param quantity the number of registers
|
||||
* @return the register data
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public int[] readInputRegisters(int serverAddress, int startAddress, int quantity) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReadInputRegisters(serverAddress, startAddress, quantity);
|
||||
ReadHoldingRegistersResponse response = (ReadInputRegistersResponse) processRequest(request);
|
||||
return response.getRegisters();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to read from 1 to 2000 contiguous status of coils in a remote
|
||||
* device. The Request PDU specifies the starting address, i.e. the address of the first coil
|
||||
* specified, and the number of coils. In the PDU Coils are addressed starting at zero. Therefore
|
||||
* coils numbered 1-16 are addressed as 0-15.
|
||||
* If the returned output quantity is not a multiple of eight, the remaining coils in the final boolean array
|
||||
* will be padded with FALSE.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param startAddress the address of the first coil
|
||||
* @param quantity the number of coils
|
||||
* @return the coils
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final synchronized public boolean[] readCoils(int serverAddress, int startAddress, int quantity) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReadCoils(serverAddress, startAddress, quantity);
|
||||
ReadCoilsResponse response = (ReadCoilsResponse) processRequest(request);
|
||||
return response.getCoils();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to read from 1 to 2000 contiguous status of discrete inputs in a
|
||||
* remote device. The Request PDU specifies the starting address, i.e. the address of the first
|
||||
* input specified, and the number of inputs. In the PDU Discrete Inputs are addressed starting
|
||||
* at zero. Therefore Discrete inputs numbered 1-16 are addressed as 0-15.
|
||||
* If the returned input quantity is not a multiple of eight, the remaining inputs in the final boolean array
|
||||
* will be padded with FALSE.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param startAddress the address of the first input
|
||||
* @param quantity the number of inputs
|
||||
* @return the discrete inputs
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public boolean[] readDiscreteInputs(int serverAddress, int startAddress, int quantity) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReadDiscreteInputs(serverAddress, startAddress, quantity);
|
||||
ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) processRequest(request);
|
||||
return response.getCoils();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to write a single output to either ON or OFF in a remote device.
|
||||
* The requested ON/OFF state is specified by a constant in the request data field. A value of
|
||||
* TRUE requests the output to be ON. A value of FALSE requests it to be OFF.
|
||||
* The Request PDU specifies the address of the coil to be forced. Coils are addressed starting
|
||||
* at zero. Therefore coil numbered 1 is addressed as 0.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param startAddress the address of the coil to be forced
|
||||
* @param flag the request data field
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public void writeSingleCoil(int serverAddress, int startAddress, boolean flag) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildWriteSingleCoil(serverAddress, startAddress, flag));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to write a single holding register in a remote device.
|
||||
* The Request PDU specifies the address of the register to be written. Registers are addressed
|
||||
* starting at zero. Therefore register numbered 1 is addressed as 0.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param startAddress the address of the register to be written
|
||||
* @param register value
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public void writeSingleRegister(int serverAddress, int startAddress, int register) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildWriteSingleRegister(serverAddress, startAddress, register));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to force each coil in a sequence of coils to either ON or OFF in a
|
||||
* remote device. The Request PDU specifies the coil references to be forced. Coils are
|
||||
* addressed starting at zero. Therefore coil numbered 1 is addressed as 0.
|
||||
* The requested ON/OFF states are specified by contents of the request array of boolean. A logical 'true'
|
||||
* in position of the array requests the corresponding output to be ON. A logical 'false' requests
|
||||
* it to be OFF.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param startAddress the address of the coils to be written
|
||||
* @param coils the coils
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public void writeMultipleCoils(int serverAddress, int startAddress, boolean[] coils) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildWriteMultipleCoils(serverAddress, startAddress, coils));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to write a block of contiguous registers (1 to 123 registers) in a
|
||||
* remote device.
|
||||
* The requested written values are specified in the request data field. Data is packed as two
|
||||
* bytes per register.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param startAddress the address of the registers to be written
|
||||
* @param registers the register data
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public void writeMultipleRegisters(int serverAddress, int startAddress, int[] registers) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildWriteMultipleRegisters(serverAddress, startAddress, registers));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code performs a combination of one read operation and one write operation in a
|
||||
* single MODBUS transaction. The write operation is performed before the read.
|
||||
* Holding registers are addressed starting at zero. Therefore holding registers 1-16 are
|
||||
* addressed in the PDU as 0-15.
|
||||
* The request specifies the starting address and number of holding registers to be read as well
|
||||
* as the starting address, number of holding registers, and the data to be written.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param readAddress the address of the registers to be read
|
||||
* @param readQuantity the number of registers to be read
|
||||
* @param writeAddress the address of the registers to be written
|
||||
* @param registers the number of registers to be written
|
||||
* @return the register value
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public int[] readWriteMultipleRegisters(int serverAddress, int readAddress, int readQuantity, int writeAddress, int[] registers) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReadWriteMultipleRegisters(serverAddress, readAddress, readQuantity, writeAddress, registers);
|
||||
ReadWriteMultipleRegistersResponse response = (ReadWriteMultipleRegistersResponse) processRequest(request);
|
||||
return response.getRegisters();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code allows to read the contents of a First-In-First-Out (FIFO) queue of register
|
||||
* in a remote device. The function returns the queued data.
|
||||
* Up to 31 queue data registers can be read.
|
||||
* The function reads the queue contents, but does not clear them.
|
||||
* If the queue count exceeds 31, an exception response is returned with an error code of 03
|
||||
* (Illegal Data Value).
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param fifoPointerAddress address of a fifo pointer register
|
||||
* @return the data register value
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public int[] readFifoQueue(int serverAddress, int fifoPointerAddress) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReadFifoQueue(serverAddress, fifoPointerAddress);
|
||||
ReadFifoQueueResponse response = (ReadFifoQueueResponse) processRequest(request);
|
||||
return response.getFifoValueRegister();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to perform a file record read.
|
||||
* A file is an organization of records. Each file contains 10000 records, addressed 0000 to
|
||||
* 9999 decimal or 0X0000 to 0X270F. For example, record 12 is addressed as 12.
|
||||
* The function can read multiple groups of references.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param records array of ModbusFileRecord
|
||||
* @return array of ModbusFileRecord has been read
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public ModbusFileRecord[] readFileRecord(int serverAddress, ModbusFileRecord[] records) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReadFileRecord(serverAddress, records);
|
||||
ReadFileRecordResponse response = (ReadFileRecordResponse) processRequest(request);
|
||||
return response.getFileRecords();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to perform a file record write. All Request Data Lengths are
|
||||
* provided in terms of number of bytes and all Record Lengths are provided in terms of the
|
||||
* number of 16-bit words.
|
||||
* A file is an organization of records. Each file contains 10000 records, addressed 0000 to
|
||||
* 9999 decimal or 0X0000 to 0X270F. For example, record 12 is addressed as 12.
|
||||
* The function can write multiple groups of references.
|
||||
*
|
||||
* @param serverAddress a server address
|
||||
* @param record the ModbusFileRecord to be written
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public void writeFileRecord(int serverAddress, ModbusFileRecord record) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildWriteFileRecord(serverAddress, record));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to modify the contents of a specified holding register using a
|
||||
* combination of an AND mask, an OR mask, and the register's current contents. The function
|
||||
* can be used to set or clear individual bits in the register.
|
||||
* The request specifies the holding register to be written, the data to be used as the AND
|
||||
* mask, and the data to be used as the OR mask. Registers are addressed starting at zero.
|
||||
* Therefore registers 1-16 are addressed as 0-15.
|
||||
* The function’s algorithm is:
|
||||
* Result = (Current Contents AND And_Mask) OR (Or_Mask AND (NOT And_Mask))
|
||||
* For example:
|
||||
* Hex Binary
|
||||
* Current Contents= 12 0001 0010
|
||||
* And_Mask = F2 1111 0010
|
||||
* Or_Mask = 25 0010 0101
|
||||
* <p>
|
||||
* (NOT And_Mask)= 0D 0000 1101
|
||||
* <p>
|
||||
* Result = 17 0001 0111
|
||||
* <p>
|
||||
* Note:
|
||||
* y If the Or_Mask value is zero, the result is simply the logical ANDing of the current contents and
|
||||
* And_Mask. If the And_Mask value is zero, the result is equal to the Or_Mask value.
|
||||
* y The contents of the register can be read with the Read Holding Registers function (function code 03).
|
||||
* They could, however, be changed subsequently as the controller scans its user logic program.
|
||||
*
|
||||
* @param serverAddress slave id
|
||||
* @param startAddress reference address
|
||||
* @param and the AND mask
|
||||
* @param or the OR mask
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
final public void maskWriteRegister(int serverAddress, int startAddress, int and, int or) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildMaskWriteRegister(serverAddress, startAddress, and, or));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function code is used to read the contents of eight Exception Status outputs in a remote
|
||||
* device.
|
||||
* The function provides a simple method for accessing this information, because the Exception
|
||||
* Output references are known (no output reference is needed in the function).
|
||||
* The normal response contains the status of the eight Exception Status outputs. The outputs
|
||||
* are packed into one data byte, with one bit per output. The status of the lowest output
|
||||
* reference is contained in the least significant bit of the byte.
|
||||
* The contents of the eight Exception Status outputs are device specific.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return the eight Exception Status outputs
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
abstract public int readExceptionStatus(int serverAddress) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* This function code is used to read the description of the type, the current status, and other
|
||||
* information specific to a remote device.
|
||||
* The data contents are specific to each type of device.
|
||||
*
|
||||
* @param serverAddress slave address
|
||||
* @return a byte array of the device's specific data
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
*/
|
||||
abstract public byte[] reportSlaveId(int serverAddress) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* This function code is used to get a status word and an event count from the remote device's
|
||||
* communication event counter.
|
||||
* By fetching the current count before and after a series of messages, a client can determine
|
||||
* whether the messages were handled normally by the remote device.
|
||||
* The device’s event counter is incremented once for each successful message completion. It
|
||||
* is not incremented for exception responses, poll commands, or fetch event counter
|
||||
* commands.
|
||||
* The event counter can be reset by means of the Diagnostics function (code 08), with a subfunction of Restart Communications Option (code 00 01) or Clear Counters and Diagnostic
|
||||
* Register (code 00 0A).
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return the CommStatus instance
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
* @see CommStatus
|
||||
*/
|
||||
abstract public CommStatus getCommEventCounter(int serverAddress) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* This function code is used to get a status word, event count, message count, and a field of
|
||||
* event bytes from the remote device.
|
||||
* The status word and event counts are identical to that returned by the Get Communications
|
||||
* Event Counter function (11, 0B hex).
|
||||
* The message counter contains the quantity of messages processed by the remote device
|
||||
* since its last restart, clear counters operation, or power–up. This count is identical to that
|
||||
* returned by the Diagnostic function (code 08), sub-function Return Bus Message Count (code
|
||||
* 11, 0B hex).
|
||||
* The event bytes field contains 0-64 bytes, with each byte corresponding to the status of one
|
||||
* MODBUS send or receive operation for the remote device. The remote device enters the
|
||||
* events into the field in chronological order. Byte 0 is the most recent event. Each new byte
|
||||
* flushes the oldest byte from the field.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return the CommStatus instance
|
||||
* @throws ModbusProtocolException if modbus-exception is received
|
||||
* @throws ModbusNumberException if response is invalid
|
||||
* @throws ModbusIOException if remote slave is unavailable
|
||||
* @see CommStatus
|
||||
*/
|
||||
abstract public CommStatus getCommEventLog(int serverAddress) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The data passed in the request data field is to be returned (looped back) in the response. The
|
||||
* entire response message should be identical to the request.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param queryData request data field
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public void diagnosticsReturnQueryData(int serverAddress, int queryData) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The remote device serial line port must be initialized and restarted, and all of its
|
||||
* communications event counters are cleared. If the port is currently in Listen Only Mode, no
|
||||
* response is returned. This function is the only one that brings the port out of Listen Only
|
||||
* Mode. If the port is not currently in Listen Only Mode, a normal response is returned. This
|
||||
* occurs before the restart is executed.
|
||||
* When the remote device receives the request, it attempts a restart and executes its power–up
|
||||
* confidence tests. Successful completion of the tests will bring the port online.
|
||||
* A request data field contents of FF 00 hex causes the port’s Communications Event Log to be
|
||||
* cleared also. Contents of 00 00 leave the log as it was prior to the restart.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param clearLog causes the port’s Communications Event Log to be cleared
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public void diagnosticsRestartCommunicationsOption(int serverAddress, boolean clearLog) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* Returns the contents of the remote device’s 16–bit diagnostic register are returned in the response.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return 16–bit diagnostic register
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public int diagnosticsReturnDiagnosticRegister(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The character passed in the request data field becomes the end of message delimiter
|
||||
* for future messages (replacing the default LF character). This function is useful in cases of a
|
||||
* Line Feed is not required at the end of ASCII messages.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param delimiter request data field
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public void diagnosticsChangeAsciiInputDelimiter(int serverAddress, int delimiter) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* Forces the addressed remote device to its Listen Only Mode for MODBUS communications.
|
||||
* This isolates it from the other devices on the network, allowing them to continue
|
||||
* communicating without interruption from the addressed remote device. No response is
|
||||
* returned.
|
||||
* When the remote device enters its Listen Only Mode, all active communication controls are
|
||||
* turned off. The Ready watchdog timer is allowed to expire, locking the controls off. While the
|
||||
* device is in this mode, any MODBUS messages addressed to it or broadcast are monitored,
|
||||
* but no actions will be taken and no responses will be sent.
|
||||
* The only function that will be processed after the mode is entered will be the Restart
|
||||
* Communications Option function (function code 8, sub-function 1).
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public void diagnosticsForceListenOnlyMode(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The goal is to clear all counters and the diagnostic register. Counters are also cleared upon power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public void diagnosticsClearCountersAndDiagnosticRegister(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages that the remote device has detected
|
||||
* on the communications system since its last restart, clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return bus message count
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public int diagnosticsReturnBusMessageCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of CRC errors encountered by the remote device
|
||||
* since its last restart, clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return CRC error count
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public int diagnosticsReturnBusCommunicationErrorCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of MODBUS exception responses returned by the
|
||||
* remote device since its last restart, clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return MODBUS exception response count
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public int diagnosticsReturnBusExceptionErrorCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device, or
|
||||
* broadcast, that the remote device has processed since its last restart, clear counters
|
||||
* operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return count of messages has been processed
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public int diagnosticsReturnSlaveMessageCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device for
|
||||
* which it has returned no response (neither a normal response nor an exception response),
|
||||
* since its last restart, clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return no-response count
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public int diagnosticsReturnSlaveNoResponseCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device for
|
||||
* which it returned a Negative Acknowledge (NAK) exception response, since its last restart,
|
||||
* clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return NAK count
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public int diagnosticsReturnSlaveNAKCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device for
|
||||
* which it returned a Slave Device Busy exception response, since its last restart, clear
|
||||
* counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return Slave Device Busy exception response count
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public int diagnosticsReturnSlaveBusyCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device that
|
||||
* it could not handle due to a character overrun condition, since its last restart, clear counters
|
||||
* operation, or power–up. A character overrun is caused by data characters arriving at the port
|
||||
* faster than they can be stored, or by the loss of a character due to a hardware malfunction.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return character overrun count
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public int diagnosticsReturnBusCharacterOverrunCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* Clears the overrun error counter and reset the error flag.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
abstract public void diagnosticsClearOverrunCounterAndFlag(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException;
|
||||
|
||||
/**
|
||||
* This function code allows reading the identification and additional information relative to the
|
||||
* physical and functional description of a remote device, only.
|
||||
* The Read Device Identification interface is modeled as an address space composed of a set
|
||||
* of addressable data elements. The data elements are called objects and an object Id
|
||||
* identifies them.
|
||||
* The interface consists of 3 categories of objects :
|
||||
* Basic Device Identification. All objects of this category are mandatory : VendorName,
|
||||
* Product code, and revision number.
|
||||
* Regular Device Identification. In addition to Basic data objects, the device provides
|
||||
* additional and optional identification and description data objects. All of the objects of
|
||||
* this category are defined in the standard but their implementation is optional .
|
||||
* Extended Device Identification. In addition to regular data objects, the device provides
|
||||
* additional and optional identification and description private data about the physical
|
||||
* device itself. All of these data are device dependent.
|
||||
* ObjectId ObjectName/Description Type M/O category
|
||||
* 0x00 VendorName ASCII String Mandatory Basic
|
||||
* 0x01 ProductCode ASCII String Mandatory Basic
|
||||
* 0x02 MajorMinorRevision ASCII String Mandatory Basic
|
||||
* 0x03 VendorUrl ASCII String Optional Regular
|
||||
* 0x04 ProductName ASCII String Optional Regular
|
||||
* 0x05 ModelName ASCII String Optional Regular
|
||||
* 0x06 UserApplicationName ASCII String Optional Regular
|
||||
* 0x07 Reserved Optional Optional Regular
|
||||
* …
|
||||
* 0x7F
|
||||
* 0x80 Private objects may be optionally device Optional Extended
|
||||
* … defined. The range [0x80 – 0xFF] dependant
|
||||
* 0xFF is Product dependant.
|
||||
*/
|
||||
final public MEIReadDeviceIdentification readDeviceIdentification(int serverAddress, int objectId, ReadDeviceIdentificationCode readDeviceId) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
EncapsulatedInterfaceTransportResponse response = (EncapsulatedInterfaceTransportResponse) processRequest(ModbusRequestBuilder.getInstance().buildReadDeviceIdentification(serverAddress, objectId, readDeviceId));
|
||||
return (MEIReadDeviceIdentification) response.getMei();
|
||||
}
|
||||
|
||||
/* facade */
|
||||
@Override
|
||||
public void addListener(FrameEventListener listener) {
|
||||
getConnection().addListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(FrameEventListener listener) {
|
||||
getConnection().removeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListeners() {
|
||||
getConnection().removeListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireFrameReceivedEvent(FrameEvent event) {
|
||||
getConnection().fireFrameReceivedEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireFrameSentEvent(FrameEvent event) {
|
||||
getConnection().fireFrameSentEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countListeners() {
|
||||
return getConnection().countListeners();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.intelligt.modbus.jlibmodbus.master;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.net.ModbusConnectionFactory;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialParameters;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialPort;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialPortException;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialUtils;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
final public class ModbusMasterASCII extends ModbusMasterSerial {
|
||||
|
||||
public ModbusMasterASCII(SerialParameters parameters) throws SerialPortException {
|
||||
super(ModbusConnectionFactory.getASCII(SerialUtils.createSerial(parameters)));
|
||||
}
|
||||
|
||||
public ModbusMasterASCII(String device, SerialPort.BaudRate baudRate, SerialPort.Parity parity) throws SerialPortException {
|
||||
this(new SerialParameters(device, baudRate, 7, parity == SerialPort.Parity.NONE ? 2 : 1, parity));
|
||||
}
|
||||
|
||||
public ModbusMasterASCII(String device, SerialPort.BaudRate baudRate) throws SerialPortException {
|
||||
this(device, baudRate, SerialPort.Parity.EVEN);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.intelligt.modbus.jlibmodbus.master;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialParameters;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialPort;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialPortException;
|
||||
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
final public class ModbusMasterFactory {
|
||||
|
||||
private ModbusMasterFactory() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ModbusMasterRTU instance.
|
||||
*
|
||||
* @param sp parameters of the serial port you would like to use.
|
||||
* @return the newly created rtu-master
|
||||
* @see SerialPort.Parity
|
||||
* @see SerialPort.BaudRate
|
||||
* @see ModbusMaster
|
||||
* @see ModbusMasterRTU
|
||||
* @see SerialParameters
|
||||
*/
|
||||
static public ModbusMaster createModbusMasterRTU(SerialParameters sp) throws SerialPortException {
|
||||
return new ModbusMasterRTU(sp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ModbusMasterASCII instance.
|
||||
*
|
||||
* @param sp parameters of the serial port you would like to use.
|
||||
* @return the newly created ascii-master
|
||||
* @see SerialPort.Parity
|
||||
* @see SerialPort.BaudRate
|
||||
* @see ModbusMaster
|
||||
* @see ModbusMasterASCII
|
||||
*/
|
||||
static public ModbusMaster createModbusMasterASCII(SerialParameters sp) throws SerialPortException {
|
||||
return new ModbusMasterASCII(sp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates ModbusMasterTCP instance.
|
||||
*
|
||||
* @param tcpParameters - a TcpParameters instance
|
||||
* @return the newly created tcp-master
|
||||
* @see ModbusMaster
|
||||
* @see ModbusMasterTCP
|
||||
* @see TcpParameters
|
||||
*/
|
||||
static public ModbusMaster createModbusMasterTCP(TcpParameters tcpParameters) {
|
||||
return new ModbusMasterTCP(tcpParameters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.intelligt.modbus.jlibmodbus.master;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.net.ModbusConnectionFactory;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialParameters;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialPort;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialPortException;
|
||||
import com.intelligt.modbus.jlibmodbus.serial.SerialUtils;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
final public class ModbusMasterRTU extends ModbusMasterSerial {
|
||||
|
||||
public ModbusMasterRTU(SerialParameters parameters) throws SerialPortException {
|
||||
super(ModbusConnectionFactory.getRTU(SerialUtils.createSerial(parameters)));
|
||||
}
|
||||
|
||||
public ModbusMasterRTU(String device, SerialPort.BaudRate baudRate, int dataBits, int stopBits, SerialPort.Parity parity) throws SerialPortException {
|
||||
this(new SerialParameters(device, baudRate, dataBits, stopBits, parity));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.intelligt.modbus.jlibmodbus.master;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.data.CommStatus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusProtocolException;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.ModbusRequestBuilder;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusRequest;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.response.*;
|
||||
import com.intelligt.modbus.jlibmodbus.net.ModbusConnection;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
abstract public class ModbusMasterSerial extends ModbusMaster {
|
||||
|
||||
final private CommStatus commStatus = new CommStatus();
|
||||
|
||||
public ModbusMasterSerial(ModbusConnection conn) {
|
||||
super(conn);
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int readExceptionStatus(int serverAddress) throws
|
||||
ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReadExceptionStatus(serverAddress);
|
||||
ReadExceptionStatusResponse response = (ReadExceptionStatusResponse) processRequest(request);
|
||||
return response.getExceptionStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public byte[] reportSlaveId(int serverAddress) throws ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReportSlaveId(serverAddress);
|
||||
ReportSlaveIdResponse response = (ReportSlaveIdResponse) processRequest(request);
|
||||
return response.getSlaveId();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public CommStatus getCommEventCounter(int serverAddress) throws ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildGetCommEventCounter(serverAddress);
|
||||
GetCommEventCounterResponse response = (GetCommEventCounterResponse) processRequest(request);
|
||||
synchronized (commStatus) {
|
||||
commStatus.setCommStatus(response.getStatus());
|
||||
commStatus.setEventCount(response.getEventCount());
|
||||
}
|
||||
return commStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
final public CommStatus getCommEventLog(int serverAddress) throws ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildGetCommEventLog(serverAddress);
|
||||
GetCommEventLogResponse response = (GetCommEventLogResponse) processRequest(request);
|
||||
synchronized (commStatus) {
|
||||
commStatus.setCommStatus(response.getStatus());
|
||||
commStatus.setEventCount(response.getEventCount());
|
||||
commStatus.setBusMessageCount(response.getMessageCount());
|
||||
commStatus.setEventQueue(response.getEventQueue());
|
||||
}
|
||||
return commStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void diagnosticsReturnQueryData(int serverAddress, int queryData) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildReturnQueryData(serverAddress, queryData));
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void diagnosticsRestartCommunicationsOption(int serverAddress, boolean clearLog) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildRestartCommunicationsOption(serverAddress, clearLog));
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int diagnosticsReturnDiagnosticRegister(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReturnDiagnosticRegister(serverAddress);
|
||||
DiagnosticsResponse response = (DiagnosticsResponse) processRequest(request);
|
||||
return response.getSubFunctionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void diagnosticsChangeAsciiInputDelimiter(int serverAddress, int delimiter) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildChangeAsciiInputDelimiter(serverAddress, delimiter));
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void diagnosticsForceListenOnlyMode(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildForceListenOnlyMode(serverAddress));
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void diagnosticsClearCountersAndDiagnosticRegister(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildClearCountersAndDiagnosticRegister(serverAddress));
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int diagnosticsReturnBusMessageCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReturnBusMessageCount(serverAddress);
|
||||
DiagnosticsResponse response = (DiagnosticsResponse) processRequest(request);
|
||||
return response.getSubFunctionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int diagnosticsReturnBusCommunicationErrorCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReturnBusCommunicationErrorCount(serverAddress);
|
||||
DiagnosticsResponse response = (DiagnosticsResponse) processRequest(request);
|
||||
return response.getSubFunctionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int diagnosticsReturnBusExceptionErrorCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReturnBusExceptionErrorCount(serverAddress);
|
||||
DiagnosticsResponse response = (DiagnosticsResponse) processRequest(request);
|
||||
return response.getSubFunctionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int diagnosticsReturnSlaveMessageCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReturnSlaveMessageCount(serverAddress);
|
||||
DiagnosticsResponse response = (DiagnosticsResponse) processRequest(request);
|
||||
return response.getSubFunctionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int diagnosticsReturnSlaveNoResponseCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReturnSlaveNoResponseCount(serverAddress);
|
||||
DiagnosticsResponse response = (DiagnosticsResponse) processRequest(request);
|
||||
return response.getSubFunctionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int diagnosticsReturnSlaveNAKCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReturnSlaveNAKCount(serverAddress);
|
||||
DiagnosticsResponse response = (DiagnosticsResponse) processRequest(request);
|
||||
return response.getSubFunctionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int diagnosticsReturnSlaveBusyCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReturnSlaveBusyCount(serverAddress);
|
||||
DiagnosticsResponse response = (DiagnosticsResponse) processRequest(request);
|
||||
return response.getSubFunctionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int diagnosticsReturnBusCharacterOverrunCount(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
ModbusRequest request = ModbusRequestBuilder.getInstance().buildReturnBusCharacterOverrunCount(serverAddress);
|
||||
DiagnosticsResponse response = (DiagnosticsResponse) processRequest(request);
|
||||
return response.getSubFunctionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void diagnosticsClearOverrunCounterAndFlag(int serverAddress) throws ModbusNumberException, ModbusProtocolException, ModbusIOException {
|
||||
processRequest(ModbusRequestBuilder.getInstance().buildClearOverrunCounterAndFlag(serverAddress));
|
||||
}
|
||||
}
|
||||
185
src/com/intelligt/modbus/jlibmodbus/master/ModbusMasterTCP.java
Normal file
@@ -0,0 +1,185 @@
|
||||
package com.intelligt.modbus.jlibmodbus.master;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.data.CommStatus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalFunctionException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusProtocolException;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusMessage;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusRequest;
|
||||
import com.intelligt.modbus.jlibmodbus.net.ModbusConnectionFactory;
|
||||
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusFunctionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
final public class ModbusMasterTCP extends ModbusMaster {
|
||||
final private boolean keepAlive;
|
||||
|
||||
public ModbusMasterTCP(TcpParameters parameters) {
|
||||
super(ModbusConnectionFactory.getTcpMaster(parameters));
|
||||
keepAlive = parameters.isKeepAlive();
|
||||
try {
|
||||
if (isKeepAlive()) {
|
||||
connect();
|
||||
}
|
||||
} catch (ModbusIOException e) {
|
||||
Modbus.log().warning("keepAlive is set, connection failed at creation time.");
|
||||
}
|
||||
}
|
||||
|
||||
private int nextTransactionId() {
|
||||
int nextId = getTransactionId() + 1;
|
||||
return nextId > Modbus.TRANSACTION_ID_MAX_VALUE ? 0 : nextId;
|
||||
}
|
||||
|
||||
public boolean isKeepAlive() {
|
||||
return keepAlive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRequest(ModbusMessage msg) throws ModbusIOException {
|
||||
if (!isKeepAlive())
|
||||
connect();
|
||||
try {
|
||||
if (Modbus.isAutoIncrementTransactionId()) {
|
||||
setTransactionId(nextTransactionId());
|
||||
}
|
||||
msg.setTransactionId(getTransactionId());
|
||||
super.sendRequest(msg);
|
||||
} catch (ModbusIOException e) {
|
||||
if (isKeepAlive()) {
|
||||
disconnect();
|
||||
connect();
|
||||
super.sendRequest(msg);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModbusMessage readResponse(ModbusRequest request) throws ModbusNumberException, ModbusIOException, ModbusProtocolException {
|
||||
ModbusMessage msg = super.readResponse(request);
|
||||
if (!isKeepAlive()) {
|
||||
disconnect();
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readExceptionStatus(int serverAddress) throws ModbusNumberException, ModbusIOException, ModbusProtocolException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.READ_EXCEPTION_STATUS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] reportSlaveId(int serverAddress) throws ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.REPORT_SLAVE_ID.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommStatus getCommEventCounter(int serverAddress) throws ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.GET_COMM_EVENT_COUNTER.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommStatus getCommEventLog(int serverAddress) throws ModbusProtocolException, ModbusNumberException, ModbusIOException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.GET_COMM_EVENT_LOG.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diagnosticsReturnQueryData(int serverAddress, int queryData) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diagnosticsRestartCommunicationsOption(int serverAddress, boolean clearLog) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int diagnosticsReturnDiagnosticRegister(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diagnosticsChangeAsciiInputDelimiter(int serverAddress, int delimiter) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diagnosticsForceListenOnlyMode(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diagnosticsClearCountersAndDiagnosticRegister(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int diagnosticsReturnBusMessageCount(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int diagnosticsReturnBusCommunicationErrorCount(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int diagnosticsReturnBusExceptionErrorCount(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int diagnosticsReturnSlaveMessageCount(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int diagnosticsReturnSlaveNoResponseCount(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int diagnosticsReturnSlaveNAKCount(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int diagnosticsReturnSlaveBusyCount(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int diagnosticsReturnBusCharacterOverrunCount(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diagnosticsClearOverrunCounterAndFlag(int serverAddress) throws ModbusNumberException, IllegalFunctionException {
|
||||
throw new IllegalFunctionException(ModbusFunctionCode.DIAGNOSTICS.toInt());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusMessage;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusRequest;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusResponse;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public interface ModbusMessageFactory {
|
||||
/**
|
||||
* This method creates a #ModbusMessage instance from #functionCode.
|
||||
* The returned value can be either an instance of ModbusRequest or ModbusResponse.
|
||||
*
|
||||
* @param functionCode a number representing a modbus function
|
||||
* @return an instance of a specific ModbusMessage
|
||||
* @see ModbusRequest
|
||||
* @see ModbusResponse
|
||||
* @see ModbusMessageFactory
|
||||
* @see ModbusResponseFactory
|
||||
*/
|
||||
ModbusMessage createMessage(int functionCode);
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.AbstractDataRequest;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.AbstractMultipleRequest;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusFileRecord;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusRequest;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.mei.ReadDeviceIdentificationCode;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.request.*;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.DiagnosticsSubFunctionCode;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Vladislav Y. Kochedykov
|
||||
* [https://github.com/kochedykov/jlibmodbus]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusRequestBuilder {
|
||||
|
||||
static public ModbusRequestBuilder getInstance() {
|
||||
return SingletonHolder.instance;
|
||||
}
|
||||
|
||||
private ModbusRequest setBaseParameter(ModbusRequest request, int serverAddress) throws ModbusNumberException {
|
||||
request.setServerAddress(serverAddress);
|
||||
return request;
|
||||
}
|
||||
|
||||
private void setSimpleDataRequestParameters(AbstractDataRequest request, int serverAddress, int startAddress) throws ModbusNumberException {
|
||||
request.setServerAddress(serverAddress);
|
||||
request.setStartAddress(startAddress);
|
||||
}
|
||||
|
||||
private void setMultipleDataRequestParameters(AbstractMultipleRequest request, int serverAddress, int startAddress, int quantity) throws ModbusNumberException {
|
||||
setSimpleDataRequestParameters(request, serverAddress, startAddress);
|
||||
request.setQuantity(quantity);
|
||||
}
|
||||
|
||||
public ModbusRequest buildReadCoils(int serverAddress, int startAddress, int quantity) throws ModbusNumberException {
|
||||
ReadCoilsRequest request = new ReadCoilsRequest();
|
||||
setMultipleDataRequestParameters(request, serverAddress, startAddress, quantity);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildReadDiscreteInputs(int serverAddress, int startAddress, int quantity) throws ModbusNumberException {
|
||||
ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest();
|
||||
setMultipleDataRequestParameters(request, serverAddress, startAddress, quantity);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildReadInputRegisters(int serverAddress, int startAddress, int quantity) throws ModbusNumberException {
|
||||
ReadInputRegistersRequest request = new ReadInputRegistersRequest();
|
||||
setMultipleDataRequestParameters(request, serverAddress, startAddress, quantity);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildReadHoldingRegisters(int serverAddress, int startAddress, int quantity) throws ModbusNumberException {
|
||||
ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest();
|
||||
setMultipleDataRequestParameters(request, serverAddress, startAddress, quantity);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildReadWriteMultipleRegisters(int serverAddress, int readAddress, int readQuantity, int writeAddress, int[] registers) throws ModbusNumberException {
|
||||
ReadWriteMultipleRegistersRequest request = new ReadWriteMultipleRegistersRequest();
|
||||
request.setServerAddress(serverAddress);
|
||||
request.setReadAddress(readAddress);
|
||||
request.setReadQuantity(readQuantity);
|
||||
request.setWriteAddress(writeAddress);
|
||||
request.setWriteRegisters(registers);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildWriteSingleCoil(int serverAddress, int startAddress, boolean coil) throws ModbusNumberException {
|
||||
WriteSingleCoilRequest request = new WriteSingleCoilRequest();
|
||||
setSimpleDataRequestParameters(request, serverAddress, startAddress);
|
||||
request.setCoil(coil);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildWriteMultipleCoils(int serverAddress, int startAddress, boolean[] coils) throws ModbusNumberException {
|
||||
WriteMultipleCoilsRequest request = new WriteMultipleCoilsRequest();
|
||||
setSimpleDataRequestParameters(request, serverAddress, startAddress);
|
||||
request.setCoils(coils);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildWriteMultipleRegisters(int serverAddress, int startAddress, int[] registers) throws ModbusNumberException {
|
||||
WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest();
|
||||
setSimpleDataRequestParameters(request, serverAddress, startAddress);
|
||||
request.setRegisters(registers);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildWriteMultipleRegisters(int serverAddress, int startAddress, byte[] bytes) throws ModbusNumberException {
|
||||
WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest();
|
||||
setSimpleDataRequestParameters(request, serverAddress, startAddress);
|
||||
request.setBytes(bytes);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildWriteSingleRegister(int serverAddress, int startAddress, int register) throws ModbusNumberException {
|
||||
WriteSingleRegisterRequest request = new WriteSingleRegisterRequest();
|
||||
setSimpleDataRequestParameters(request, serverAddress, startAddress);
|
||||
request.setValue(register);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildMaskWriteRegister(int serverAddress, int startAddress, int and, int or) throws ModbusNumberException {
|
||||
MaskWriteRegisterRequest request = new MaskWriteRegisterRequest();
|
||||
setSimpleDataRequestParameters(request, serverAddress, startAddress);
|
||||
request.setMaskAnd(and);
|
||||
request.setMaskOr(or);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildReadExceptionStatus(int serverAddress) throws ModbusNumberException {
|
||||
return setBaseParameter(new ReadExceptionStatusRequest(), serverAddress);
|
||||
}
|
||||
|
||||
public ModbusRequest buildReportSlaveId(int serverAddress) throws ModbusNumberException {
|
||||
return setBaseParameter(new ReportSlaveIdRequest(), serverAddress);
|
||||
}
|
||||
|
||||
public ModbusRequest buildGetCommEventCounter(int serverAddress) throws ModbusNumberException {
|
||||
return setBaseParameter(new GetCommEventCounterRequest(), serverAddress);
|
||||
}
|
||||
|
||||
public ModbusRequest buildGetCommEventLog(int serverAddress) throws ModbusNumberException {
|
||||
return setBaseParameter(new GetCommEventLogRequest(), serverAddress);
|
||||
}
|
||||
|
||||
public ModbusRequest buildReadFifoQueue(int serverAddress, int fifoPointerAddress) throws ModbusNumberException {
|
||||
ReadFifoQueueRequest request = new ReadFifoQueueRequest();
|
||||
request.setServerAddress(serverAddress);
|
||||
request.setStartAddress(fifoPointerAddress);
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildReadFileRecord(int serverAddress, ModbusFileRecord[] records) throws ModbusNumberException {
|
||||
ReadFileRecordRequest request = new ReadFileRecordRequest();
|
||||
request.setServerAddress(serverAddress);
|
||||
request.addFileRecords(Arrays.asList(records));
|
||||
return request;
|
||||
}
|
||||
|
||||
public ModbusRequest buildWriteFileRecord(int serverAddress, ModbusFileRecord record) throws ModbusNumberException {
|
||||
WriteFileRecordRequest request = new WriteFileRecordRequest();
|
||||
request.setServerAddress(serverAddress);
|
||||
request.setFileRecord(record);
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function uses a sub-function code field in the query to define the type of test to
|
||||
* be performed. The server echoes both the function code and sub-function code in a normal
|
||||
* response. Some of the diagnostics cause data to be returned from the remote device in the
|
||||
* data field of a normal response.
|
||||
*
|
||||
* @param subFunctionCode a sub-function code
|
||||
* @param serverAddress a slave address
|
||||
* @param data request data field
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
* @see DiagnosticsRequest
|
||||
* @see DiagnosticsSubFunctionCode
|
||||
*/
|
||||
public ModbusRequest buildDiagnostics(DiagnosticsSubFunctionCode subFunctionCode, int serverAddress, int data) throws ModbusNumberException {
|
||||
DiagnosticsRequest request = new DiagnosticsRequest();
|
||||
request.setServerAddress(serverAddress);
|
||||
request.setSubFunctionCode(subFunctionCode);
|
||||
request.setSubFunctionData(data);
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* The data passed in the request data field is to be returned (looped back) in the response. The
|
||||
* entire response message should be identical to the request.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param queryData request data field
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnQueryData(int serverAddress, int queryData) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_QUERY_DATA, serverAddress, queryData);
|
||||
}
|
||||
|
||||
/**
|
||||
* The remote device serial line port must be initialized and restarted, and all of its
|
||||
* communications event counters are cleared. If the port is currently in Listen Only Mode, no
|
||||
* response is returned. This function is the only one that brings the port out of Listen Only
|
||||
* Mode. If the port is not currently in Listen Only Mode, a normal response is returned. This
|
||||
* occurs before the restart is executed.
|
||||
* When the remote device receives the request, it attempts a restart and executes its power–up
|
||||
* confidence tests. Successful completion of the tests will bring the port online.
|
||||
* A request data field contents of FF 00 hex causes the port’s Communications Event Log to be
|
||||
* cleared also. Contents of 00 00 leave the log as it was prior to the restart.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param clearLog causes the port’s Communications Event Log to be cleared
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildRestartCommunicationsOption(int serverAddress, boolean clearLog) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RESTART_COMMUNICATIONS_OPTION, serverAddress, clearLog ? DiagnosticsRequest.CLEAR_LOG : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of the remote device’s 16–bit diagnostic register are returned in the response.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnDiagnosticRegister(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_DIAGNOSTIC_REGISTER, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The character passed in the request data field becomes the end of message delimiter
|
||||
* for future messages (replacing the default LF character). This function is useful in cases of a
|
||||
* Line Feed is not required at the end of ASCII messages.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @param delimiter request data field
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildChangeAsciiInputDelimiter(int serverAddress, int delimiter) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.CHANGE_ASCII_INPUT_DELIMITER, serverAddress, delimiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the addressed remote device to its Listen Only Mode for MODBUS communications.
|
||||
* This isolates it from the other devices on the network, allowing them to continue
|
||||
* communicating without interruption from the addressed remote device. No response is
|
||||
* returned.
|
||||
* When the remote device enters its Listen Only Mode, all active communication controls are
|
||||
* turned off. The Ready watchdog timer is allowed to expire, locking the controls off. While the
|
||||
* device is in this mode, any MODBUS messages addressed to it or broadcast are monitored,
|
||||
* but no actions will be taken and no responses will be sent.
|
||||
* The only function that will be processed after the mode is entered will be the Restart
|
||||
* Communications Option function (function code 8, sub-function 1).
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildForceListenOnlyMode(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.FORCE_LISTEN_ONLY_MODE, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The goal is to clear all counters and the diagnostic register. Counters are also cleared upon power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildClearCountersAndDiagnosticRegister(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages that the remote device has detected
|
||||
* on the communications system since its last restart, clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnBusMessageCount(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_BUS_MESSAGE_COUNT, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of CRC errors encountered by the remote device
|
||||
* since its last restart, clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnBusCommunicationErrorCount(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_BUS_COMMUNICATION_ERROR_COUNT, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of MODBUS exception responses returned by the
|
||||
* remote device since its last restart, clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnBusExceptionErrorCount(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_BUS_EXCEPTION_ERROR_COUNT, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device, or
|
||||
* broadcast, that the remote device has processed since its last restart, clear counters
|
||||
* operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnSlaveMessageCount(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_SLAVE_MESSAGE_COUNT, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device for
|
||||
* which it has returned no response (neither a normal response nor an exception response),
|
||||
* since its last restart, clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnSlaveNoResponseCount(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_SLAVE_NO_RESPONSE_COUNT, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device for
|
||||
* which it returned a Negative Acknowledge (NAK) exception response, since its last restart,
|
||||
* clear counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnSlaveNAKCount(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_SLAVE_NAK_COUNT, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device for
|
||||
* which it returned a Slave Device Busy exception response, since its last restart, clear
|
||||
* counters operation, or power–up.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnSlaveBusyCount(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_SLAVE_BUSY_COUNT, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The response data field returns the quantity of messages addressed to the remote device that
|
||||
* it could not handle due to a character overrun condition, since its last restart, clear counters
|
||||
* operation, or power–up. A character overrun is caused by data characters arriving at the port
|
||||
* faster than they can be stored, or by the loss of a character due to a hardware malfunction.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildReturnBusCharacterOverrunCount(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.RETURN_BUS_CHARACTER_OVERRUN_COUNT, serverAddress, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the overrun error counter and reset the error flag.
|
||||
*
|
||||
* @param serverAddress a slave address
|
||||
* @return DiagnosticsRequest instance
|
||||
* @throws ModbusNumberException if server address is in-valid
|
||||
*/
|
||||
public ModbusRequest buildClearOverrunCounterAndFlag(int serverAddress) throws ModbusNumberException {
|
||||
return buildDiagnostics(DiagnosticsSubFunctionCode.CLEAR_OVERRUN_COUNTER_AND_FLAG, serverAddress, 0);
|
||||
}
|
||||
|
||||
public ModbusRequest buildReadDeviceIdentification(int serverAddress, int objectId, ReadDeviceIdentificationCode readDeviceId) throws ModbusNumberException {
|
||||
ReadDeviceIdentificationRequest request = new ReadDeviceIdentificationRequest();
|
||||
request.setServerAddress(serverAddress);
|
||||
request.setObjectId(objectId);
|
||||
request.setReadDeviceId(readDeviceId);
|
||||
return request;
|
||||
}
|
||||
|
||||
static private class SingletonHolder {
|
||||
final static private ModbusRequestBuilder instance = new ModbusRequestBuilder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusMessage;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusRequest;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.request.*;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusFunctionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
final public class ModbusRequestFactory implements ModbusMessageFactory {
|
||||
|
||||
private ModbusRequestFactory() {
|
||||
|
||||
}
|
||||
|
||||
static public ModbusRequestFactory getInstance() {
|
||||
return SingletonHolder.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a #ModbusRequest instance from #functionCode
|
||||
*
|
||||
* @param functionCode a number representing a modbus function
|
||||
* @return an instance of a specific ModbusRequest
|
||||
* @see ModbusRequest
|
||||
* @see ModbusMessageFactory
|
||||
* @see ModbusResponseFactory
|
||||
*/
|
||||
@Override
|
||||
public ModbusMessage createMessage(int functionCode) {
|
||||
ModbusMessage msg;
|
||||
|
||||
switch (ModbusFunctionCode.get(functionCode)) {
|
||||
case READ_COILS:
|
||||
msg = new ReadCoilsRequest();
|
||||
break;
|
||||
case READ_DISCRETE_INPUTS:
|
||||
msg = new ReadDiscreteInputsRequest();
|
||||
break;
|
||||
case READ_HOLDING_REGISTERS:
|
||||
msg = new ReadHoldingRegistersRequest();
|
||||
break;
|
||||
case READ_INPUT_REGISTERS:
|
||||
msg = new ReadInputRegistersRequest();
|
||||
break;
|
||||
case WRITE_SINGLE_COIL:
|
||||
msg = new WriteSingleCoilRequest();
|
||||
break;
|
||||
case WRITE_SINGLE_REGISTER:
|
||||
msg = new WriteSingleRegisterRequest();
|
||||
break;
|
||||
case WRITE_MULTIPLE_COILS:
|
||||
msg = new WriteMultipleCoilsRequest();
|
||||
break;
|
||||
case WRITE_MULTIPLE_REGISTERS:
|
||||
msg = new WriteMultipleRegistersRequest();
|
||||
break;
|
||||
case MASK_WRITE_REGISTER:
|
||||
msg = new MaskWriteRegisterRequest();
|
||||
break;
|
||||
case READ_WRITE_MULTIPLE_REGISTERS:
|
||||
msg = new ReadWriteMultipleRegistersRequest();
|
||||
break;
|
||||
case READ_FIFO_QUEUE:
|
||||
msg = new ReadFifoQueueRequest();
|
||||
break;
|
||||
case READ_FILE_RECORD:
|
||||
msg = new ReadFileRecordRequest();
|
||||
break;
|
||||
case WRITE_FILE_RECORD:
|
||||
msg = new WriteFileRecordRequest();
|
||||
break;
|
||||
case READ_EXCEPTION_STATUS:
|
||||
msg = new ReadExceptionStatusRequest();
|
||||
break;
|
||||
case REPORT_SLAVE_ID:
|
||||
msg = new ReportSlaveIdRequest();
|
||||
break;
|
||||
case GET_COMM_EVENT_COUNTER:
|
||||
msg = new GetCommEventCounterRequest();
|
||||
break;
|
||||
case GET_COMM_EVENT_LOG:
|
||||
msg = new GetCommEventLogRequest();
|
||||
break;
|
||||
case DIAGNOSTICS:
|
||||
msg = new DiagnosticsRequest();
|
||||
break;
|
||||
case ENCAPSULATED_INTERFACE_TRANSPORT:
|
||||
msg = new EncapsulatedInterfaceTransportRequest();
|
||||
break;
|
||||
default:
|
||||
msg = new IllegalFunctionRequest(functionCode);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
static private class SingletonHolder {
|
||||
final static private ModbusRequestFactory instance = new ModbusRequestFactory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusMessage;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusRequest;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusResponse;
|
||||
import com.intelligt.modbus.jlibmodbus.msg.response.*;
|
||||
import com.intelligt.modbus.jlibmodbus.utils.ModbusFunctionCode;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
final public class ModbusResponseFactory implements ModbusMessageFactory {
|
||||
|
||||
private ModbusResponseFactory() {
|
||||
|
||||
}
|
||||
|
||||
static public ModbusResponseFactory getInstance() {
|
||||
return SingletonHolder.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a #ModbusResponse instance from #functionCode
|
||||
*
|
||||
* @param functionCode a number representing a modbus function
|
||||
* @return an instance of a specific ModbusRequest
|
||||
* @see ModbusRequest
|
||||
* @see ModbusMessageFactory
|
||||
* @see ModbusResponseFactory
|
||||
*/
|
||||
@Override
|
||||
public ModbusMessage createMessage(int functionCode) {
|
||||
ModbusResponse msg;
|
||||
|
||||
switch (ModbusFunctionCode.get(functionCode)) {
|
||||
case READ_COILS:
|
||||
msg = new ReadCoilsResponse();
|
||||
break;
|
||||
case READ_DISCRETE_INPUTS:
|
||||
msg = new ReadDiscreteInputsResponse();
|
||||
break;
|
||||
case READ_HOLDING_REGISTERS:
|
||||
msg = new ReadHoldingRegistersResponse();
|
||||
break;
|
||||
case READ_INPUT_REGISTERS:
|
||||
msg = new ReadInputRegistersResponse();
|
||||
break;
|
||||
case WRITE_SINGLE_COIL:
|
||||
msg = new WriteSingleCoilResponse();
|
||||
break;
|
||||
case WRITE_SINGLE_REGISTER:
|
||||
msg = new WriteSingleRegisterResponse();
|
||||
break;
|
||||
case WRITE_MULTIPLE_COILS:
|
||||
msg = new WriteMultipleCoilsResponse();
|
||||
break;
|
||||
case WRITE_MULTIPLE_REGISTERS:
|
||||
msg = new WriteMultipleRegistersResponse();
|
||||
break;
|
||||
case MASK_WRITE_REGISTER:
|
||||
msg = new MaskWriteRegisterResponse();
|
||||
break;
|
||||
case READ_WRITE_MULTIPLE_REGISTERS:
|
||||
msg = new ReadWriteMultipleRegistersResponse();
|
||||
break;
|
||||
case READ_FIFO_QUEUE:
|
||||
msg = new ReadFifoQueueResponse();
|
||||
break;
|
||||
case READ_FILE_RECORD:
|
||||
msg = new ReadFileRecordResponse();
|
||||
break;
|
||||
case WRITE_FILE_RECORD:
|
||||
msg = new WriteFileRecordResponse();
|
||||
break;
|
||||
case READ_EXCEPTION_STATUS:
|
||||
msg = new ReadExceptionStatusResponse();
|
||||
break;
|
||||
case REPORT_SLAVE_ID:
|
||||
msg = new ReportSlaveIdResponse();
|
||||
break;
|
||||
case GET_COMM_EVENT_COUNTER:
|
||||
msg = new GetCommEventCounterResponse();
|
||||
break;
|
||||
case GET_COMM_EVENT_LOG:
|
||||
msg = new GetCommEventLogResponse();
|
||||
break;
|
||||
case DIAGNOSTICS:
|
||||
msg = new DiagnosticsResponse();
|
||||
break;
|
||||
case ENCAPSULATED_INTERFACE_TRANSPORT:
|
||||
msg = new EncapsulatedInterfaceTransportResponse();
|
||||
break;
|
||||
default:
|
||||
msg = new IllegalFunctionResponse(functionCode);
|
||||
}
|
||||
if (ModbusFunctionCode.isException(functionCode)) {
|
||||
msg.setException();
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
static private class SingletonHolder {
|
||||
final static private ModbusResponseFactory instance = new ModbusResponseFactory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg.base;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusInputStream;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
abstract public class AbstractDataRequest extends ModbusRequest {
|
||||
|
||||
private int startAddress;
|
||||
|
||||
protected AbstractDataRequest() {
|
||||
super();
|
||||
}
|
||||
|
||||
abstract protected void writeData(ModbusOutputStream fifo) throws IOException;
|
||||
|
||||
abstract protected void readData(ModbusInputStream fifo) throws IOException, ModbusNumberException;
|
||||
|
||||
@Override
|
||||
final public void readPDU(ModbusInputStream fifo) throws ModbusNumberException, IOException {
|
||||
setStartAddress(fifo.readShortBE());
|
||||
readData(fifo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeRequest(ModbusOutputStream fifo) throws IOException {
|
||||
fifo.writeShortBE(getStartAddress());
|
||||
writeData(fifo);
|
||||
}
|
||||
|
||||
public int getStartAddress() {
|
||||
return startAddress;
|
||||
}
|
||||
|
||||
public void setStartAddress(int startAddress) throws ModbusNumberException {
|
||||
if (!Modbus.checkStartAddress(startAddress)) {
|
||||
throw new ModbusNumberException("Error in start address", startAddress);
|
||||
}
|
||||
this.startAddress = startAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
final public int requestSize() {
|
||||
return 2 + dataSize();
|
||||
}
|
||||
|
||||
abstract protected int dataSize();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg.base;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusInputStream;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
abstract public class AbstractMultipleRequest extends AbstractDataRequest {
|
||||
private int quantity;
|
||||
|
||||
protected AbstractMultipleRequest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readData(ModbusInputStream fifo) throws IOException, ModbusNumberException {
|
||||
setQuantity(fifo.readShortBE());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeData(ModbusOutputStream fifo) throws IOException {
|
||||
fifo.writeShortBE(quantity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int dataSize() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(int quantity) throws ModbusNumberException {
|
||||
if (!checkAddressRange(getStartAddress(), quantity))
|
||||
throw new ModbusNumberException("End address out of bounds", getStartAddress() + quantity);
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
protected abstract boolean checkAddressRange(int startAddress, int quantity);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg.base;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusInputStream;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
abstract public class AbstractReadResponse extends ModbusResponse {
|
||||
|
||||
private int byteCount = 0;
|
||||
|
||||
protected AbstractReadResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return byteCount;
|
||||
}
|
||||
|
||||
protected void setByteCount(int byteCount) throws ModbusNumberException {
|
||||
if (byteCount > (Modbus.MAX_PDU_LENGTH - 2))
|
||||
throw new ModbusNumberException("Byte count greater than max allowable");
|
||||
this.byteCount = byteCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void readResponse(ModbusInputStream fifo) throws IOException, ModbusNumberException {
|
||||
setByteCount(fifo.read());
|
||||
readData(fifo);
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void writeResponse(ModbusOutputStream fifo) throws IOException {
|
||||
fifo.write(getByteCount());
|
||||
writeData(fifo);
|
||||
}
|
||||
|
||||
abstract protected void readData(ModbusInputStream fifo) throws IOException, ModbusNumberException;
|
||||
|
||||
abstract protected void writeData(ModbusOutputStream fifo) throws IOException;
|
||||
|
||||
@Override
|
||||
final protected int responseSize() {
|
||||
return 1 + getByteCount();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg.base;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusInputStream;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
abstract public class AbstractWriteMultipleRequest extends AbstractMultipleRequest {
|
||||
|
||||
private byte[] values;
|
||||
private int byteCount;
|
||||
|
||||
protected AbstractWriteMultipleRequest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeData(ModbusOutputStream fifo) throws IOException {
|
||||
super.writeData(fifo);
|
||||
fifo.write(getByteCount());
|
||||
fifo.write(getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readData(ModbusInputStream fifo) throws IOException, ModbusNumberException {
|
||||
super.readData(fifo);
|
||||
setByteCount(fifo.read());
|
||||
values = new byte[byteCount];
|
||||
int size;
|
||||
if ((size = fifo.read(values, 0, getByteCount())) < getByteCount())
|
||||
Modbus.log().warning(getByteCount() + " bytes expected, but " + size + " received.");
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return byteCount;
|
||||
}
|
||||
|
||||
public void setByteCount(int byteCount) throws ModbusNumberException {
|
||||
if (byteCount > Modbus.MAX_WRITE_REGISTER_COUNT * 2) {
|
||||
//TODO add a description
|
||||
throw new ModbusNumberException("" + byteCount);
|
||||
}
|
||||
this.byteCount = byteCount;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setBytes(byte[] values) throws ModbusNumberException {
|
||||
this.values = values;
|
||||
setByteCount(values.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int dataSize() {
|
||||
return super.dataSize() + 1 + getByteCount();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg.base;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.Modbus;
|
||||
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusInputStream;
|
||||
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
|
||||
public abstract class AbstractWriteResponse extends ModbusResponse {
|
||||
private int startAddress = 0;
|
||||
|
||||
protected AbstractWriteResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
final protected void readResponse(ModbusInputStream fifo) throws IOException {
|
||||
try {
|
||||
setStartAddress(fifo.readShortBE());
|
||||
} catch (ModbusNumberException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
readValue(fifo);
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void writeResponse(ModbusOutputStream fifo) throws IOException {
|
||||
fifo.writeShortBE(getStartAddress());
|
||||
writeValue(fifo);
|
||||
}
|
||||
|
||||
abstract protected void readValue(ModbusInputStream fifo) throws IOException;
|
||||
|
||||
abstract protected void writeValue(ModbusOutputStream fifo) throws IOException;
|
||||
|
||||
final public int getStartAddress() {
|
||||
return startAddress;
|
||||
}
|
||||
|
||||
public void setStartAddress(int startAddress) throws ModbusNumberException {
|
||||
if (!(Modbus.checkStartAddress(startAddress)))
|
||||
throw new ModbusNumberException("Error in start address", startAddress);
|
||||
this.startAddress = startAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
final protected int responseSize() {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.intelligt.modbus.jlibmodbus.msg.base;
|
||||
|
||||
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 "Invertor" Factory", JSC
|
||||
* [http://www.sbp-invertor.ru]
|
||||
*
|
||||
* This file is part of JLibModbus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Authors: Vladislav Y. Kochedykov, software engineer.
|
||||
* email: vladislav.kochedykov@gmail.com
|
||||
*/
|
||||
public class ModbusFileRecord {
|
||||
final static public int REF_TYPE = 0x06;
|
||||
final private int number;
|
||||
final private int file;
|
||||
private int length = 0;
|
||||
private int[] registers;
|
||||
|
||||
public ModbusFileRecord(int fileNumber, int recordNumber, int registerCount) {
|
||||
this.file = fileNumber;
|
||||
this.number = recordNumber;
|
||||
this.length = registerCount;
|
||||
}
|
||||
|
||||
public ModbusFileRecord(int file, int number, int[] buffer) {
|
||||
this.file = file;
|
||||
this.number = number;
|
||||
setRegisters(buffer);
|
||||
}
|
||||
|
||||
public int[] getRegisters() {
|
||||
return Arrays.copyOf(registers, registers.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* setter
|
||||
*
|
||||
* @param registers modbus register values
|
||||
*/
|
||||
protected void setRegisters(int[] registers) {
|
||||
this.registers = Arrays.copyOf(registers, registers.length);
|
||||
this.length = registers.length;
|
||||
}
|
||||
|
||||
public void writeRegisters(int[] registers) throws IllegalDataValueException {
|
||||
if (registers.length > getRegisters().length)
|
||||
throw new IllegalDataValueException();
|
||||
this.length = registers.length;
|
||||
}
|
||||
|
||||
public int getFileNumber() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public int getRecordNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public int getRecordLength() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||