项目初始化

This commit is contained in:
liuhanqing
2025-12-10 10:01:24 +08:00
commit af63c05a97
346 changed files with 54556 additions and 0 deletions

29
.gitignore vendored Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
images/1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
images/11.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
images/12.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

BIN
images/a.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/calendar.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
images/excel.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

BIN
images/his.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

BIN
images/login.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
images/mar.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

BIN
images/now.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

BIN
images/tr.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
images/任务查询.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/作业查询.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/堆垛机.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/小车.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
images/红.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

BIN
images/红22.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

BIN
images/红22.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
images/红23.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

BIN
images/红25.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

BIN
images/绿.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

BIN
images/绿23.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

BIN
images/绿23.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
images/绿24.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

BIN
images/绿25.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

BIN
images/设备监控.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/调度操作.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/调度日志.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/黄.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

BIN
images/黄25.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

BIN
images/黄25.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: com.wms.dss.ats.customs.abb.form.ABBMainFrame

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View 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
View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: com.wms.dss.ats.customs.abb.form.ABBMainFrame

View 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;
}
}
}

View 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;
}
}

View 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);
}
}

View 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;
}
}

View File

@@ -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();
}
}

View 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 ExceptionStatus {
int get();
void set(int exceptionStatus);
}

View 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();
}
}

View 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);
}
}

View 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;
}
}

View File

@@ -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();
}
}

View 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() {
}
};
}
}

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View 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);
}
}

View 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);
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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()]);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View 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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View 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());
}
}

View File

@@ -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);
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

Some files were not shown because too many files have changed in this diff Show More