407 lines
20 KiB
Java
407 lines
20 KiB
Java
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();
|
||
}
|
||
}
|