All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intelligt.modbus.jlibmodbus.msg.request.DiagnosticsRequest Maven / Gradle / Ivy

package com.intelligt.modbus.jlibmodbus.msg.request;

import com.intelligt.modbus.jlibmodbus.data.CommStatus;
import com.intelligt.modbus.jlibmodbus.data.DataHolder;
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusRequest;
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusResponse;
import com.intelligt.modbus.jlibmodbus.msg.response.DiagnosticsResponse;
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusInputStream;
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusOutputStream;
import com.intelligt.modbus.jlibmodbus.utils.DiagnosticsSubFunctionCode;
import com.intelligt.modbus.jlibmodbus.utils.ModbusFunctionCode;

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: [email protected]
 */

/**
 * MODBUS function code 08 provides a series of tests for checking the communication system
 * between a client ( Master) device and a server ( Slave), or for checking various internal error
 * conditions within a server.
 * The function uses a two–byte 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.
 * In general, issuing a diagnostic function to a remote device does not affect the running of the
 * user program in the remote device. User logic, like discrete and registers, is not accessed by
 * the diagnostics. Certain functions can optionally reset error counters in the remote device.
 * A server device can, however, be forced into ‘Listen Only Mode’ in which it will monitor the
 * messages on the communications system but not respond to them. This can affect the
 * outcome of your application program if it depends upon any further exchange of data with the
 * remote device. Generally, the mode is forced to remove a malfunctioning remote device from
 * the communications system.
 * The following diagnostic functions are dedicated to serial line devices.
 * The normal response to the Return Query Data request is to loopback the same data. The
 * function code and sub-function codes are also echoed.
 */
public class DiagnosticsRequest extends ModbusRequest {
    /**
     * Diagnostic uses a two–byte sub-function code field in the query to define the type of test to
     * be performed.
     */
    final static public int CLEAR_LOG = 0xff00;
    private DiagnosticsSubFunctionCode subFunctionCode = DiagnosticsSubFunctionCode.RESERVED;
    private int subFunctionData = 0;

    public DiagnosticsRequest() {
        super();
    }

    @Override
    protected Class getResponseClass() {
        return DiagnosticsResponse.class;
    }

    @Override
    public void writeRequest(ModbusOutputStream fifo) throws IOException {
        fifo.writeShortBE(getSubFunctionCode().toInt());
        fifo.writeShortBE(getSubFunctionData());
    }

    @Override
    public int requestSize() {
        return 4;
    }

    @Override
    public ModbusResponse process(DataHolder dataHolder) throws ModbusNumberException {
        DiagnosticsResponse response = new DiagnosticsResponse();
        response.setServerAddress(getServerAddress());
        response.setSubFunctionCode(getSubFunctionCode());
        CommStatus commStatus = dataHolder.getCommStatus();
        switch (getSubFunctionCode()) {
            case RETURN_QUERY_DATA:
                response.setSubFunctionData(getSubFunctionData());
                break;
            case RESTART_COMMUNICATIONS_OPTION:
                if (getSubFunctionData() == 0xff00) {
                    commStatus.setClearLog(true);
                }
                commStatus.setRestartCommunicationsOption(true);
                response.setSubFunctionData(getSubFunctionData());
                break;
            case RETURN_DIAGNOSTIC_REGISTER:
                response.setSubFunctionData(commStatus.getDiagnosticRegister());
                break;
            case CHANGE_ASCII_INPUT_DELIMITER:
                commStatus.setAsciiInputDelimiter((getSubFunctionData() >> 8) & 0xff);
                response.setSubFunctionData(getSubFunctionData());
                break;
            case FORCE_LISTEN_ONLY_MODE:
                commStatus.setListenOnlyMode(true);
                break;
            case CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER:
                commStatus.clearCountersAndDiagnosticRegister();
                response.setSubFunctionData(getSubFunctionData());
                break;
            case RETURN_BUS_MESSAGE_COUNT:
                response.setSubFunctionData(commStatus.getMessageCount());
                break;
            case RETURN_BUS_COMMUNICATION_ERROR_COUNT:
                response.setSubFunctionData(commStatus.getCommunicationErrorCount());
                break;
            case RETURN_BUS_EXCEPTION_ERROR_COUNT:
                response.setSubFunctionData(commStatus.getExceptionErrorCount());
                break;
            case RETURN_SLAVE_MESSAGE_COUNT:
                response.setSubFunctionData(commStatus.getSlaveMessageCount());
                break;
            case RETURN_SLAVE_NO_RESPONSE_COUNT:
                response.setSubFunctionData(commStatus.getSlaveNoResponseCount());
                break;
            case RETURN_SLAVE_NAK_COUNT:
                response.setSubFunctionData(commStatus.getSlaveNAKCount());
                break;
            case RETURN_SLAVE_BUSY_COUNT:
                response.setSubFunctionData(commStatus.getSlaveBusyCount());
                break;
            case RETURN_BUS_CHARACTER_OVERRUN_COUNT:
                response.setSubFunctionData(commStatus.getCharacterOverrunCount());
                break;
            case CLEAR_OVERRUN_COUNTER_AND_FLAG:
                commStatus.setCharacterOverrunCount(0);
                response.setSubFunctionData(getSubFunctionData());
                break;
            case RESERVED:
                break;
        }
        return response;
    }

    @Override
    protected boolean validateResponseImpl(ModbusResponse response) {
        DiagnosticsResponse r = (DiagnosticsResponse) response;

        if (getSubFunctionCode() != r.getSubFunctionCode())
            return false;

        switch (subFunctionCode) {
            case RETURN_QUERY_DATA:
            case RESTART_COMMUNICATIONS_OPTION:
            case CHANGE_ASCII_INPUT_DELIMITER:
            case CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER:
            case CLEAR_OVERRUN_COUNTER_AND_FLAG:
                return getSubFunctionData() == r.getSubFunctionData();
            case FORCE_LISTEN_ONLY_MODE:
                break;
            case RETURN_DIAGNOSTIC_REGISTER:
                break;
            case RETURN_BUS_MESSAGE_COUNT:
                break;
            case RETURN_BUS_COMMUNICATION_ERROR_COUNT:
                break;
            case RETURN_BUS_EXCEPTION_ERROR_COUNT:
                break;
            case RETURN_SLAVE_MESSAGE_COUNT:
                break;
            case RETURN_SLAVE_NO_RESPONSE_COUNT:
                break;
            case RETURN_SLAVE_NAK_COUNT:
                break;
            case RETURN_SLAVE_BUSY_COUNT:
                break;
            case RETURN_BUS_CHARACTER_OVERRUN_COUNT:
                break;
            case RESERVED:
                break;
        }
        return true;
    }

    @Override
    public void readPDU(ModbusInputStream fifo) throws ModbusNumberException, IOException {
        setSubFunctionCode(DiagnosticsSubFunctionCode.get(fifo.readShortBE()));
        setSubFunctionData(fifo.readShortBE());
    }

    public int getSubFunctionData() {
        return subFunctionData;
    }

    public void setSubFunctionData(int subFunctionData) {
        this.subFunctionData = subFunctionData;
    }

    public DiagnosticsSubFunctionCode getSubFunctionCode() {
        return subFunctionCode;
    }

    public void setSubFunctionCode(DiagnosticsSubFunctionCode subFunctionCode) {
        this.subFunctionCode = subFunctionCode;
    }

    @Override
    public int getFunction() {
        return ModbusFunctionCode.DIAGNOSTICS.toInt();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy