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