Package modbuspal.link

Source Code of modbuspal.link.ModbusSlaveProcessor

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package modbuspal.link;

import java.util.logging.Level;
import java.util.logging.Logger;
import modbuspal.main.*;
import modbuspal.main.ModbusConst;
import static modbuspal.main.ModbusConst.XC_ILLEGAL_FUNCTION;
import modbuspal.master.ModbusMasterRequest;
import modbuspal.recorder.ModbusPalRecorder;
import modbuspal.slave.ModbusPduProcessor;
import modbuspal.slave.ModbusSlave;
import modbuspal.slave.ModbusSlaveAddress;


/**
* the abstract class for processing incoming PDU
* @author nnovic
*/
public abstract class ModbusSlaveProcessor
implements ModbusConst
{
    /**
     * reference on the project that hold all the information
     * for the modbus slaves to simulate
     */
    protected final ModbusPalProject modbusPalProject;

    /**
     * Constructor that stores the reference of the modbuspal project
     * @param mpp
     */
    protected ModbusSlaveProcessor(ModbusPalProject mpp)
    {
        modbusPalProject = mpp;
    }

    /**
     * The subclass will call this method in order to process the content of
     * the PDU that has been received from the master.
     * The reply is written in the same buffer where the request was transmitted.
     * @param slaveID the slave identifier of the target MODBUS device
     * @param buffer a byte buffer containing the MODBUS PDU
     * @param offset the offset in the buffer where the PDU actually starts
     * @param pduLength the length of the PDU.
     * @return the size of the reply. if less than 1, modbuspal considers that
     * there is no reply to the request.
     */
    protected int processPDU(ModbusSlaveAddress slaveID, byte[] buffer, int offset, int pduLength)
    {
        // record the request
        ModbusPalRecorder.recordIncoming(slaveID,buffer,offset,pduLength);

        // check if the slave is enabled
        if( modbusPalProject.isSlaveEnabled(slaveID) == false )
        {
            System.err.println("Slave "+slaveID+" is not enabled");
            modbusPalProject.notifyPDUnotServiced();
            return 0;
        }

        // get the slave:
        ModbusSlave slave = modbusPalProject.getModbusSlave(slaveID);

        // process the "no reply" error rate of the slave:
        if( Math.random() < slave.getNoReplyErrorRate() )
        {
            System.err.println("Slave "+slaveID+" will no reply (check value error rate)" );
            modbusPalProject.notifyPDUnotServiced();
            return 0;
        }

        byte functionCode = buffer[offset+0];
        ModbusPduProcessor mspp = slave.getPduProcessor(functionCode);
        if( mspp == null )
        {
            System.err.println("Unsupported function code "+functionCode);
            int length = makeExceptionResponse(functionCode,XC_ILLEGAL_FUNCTION, buffer, offset);
            ModbusPalRecorder.recordOutgoing(slaveID,buffer,offset,length);
            modbusPalProject.notifyExceptionResponse();
            return length;
        }

        int length = mspp.processPDU(functionCode, slaveID, buffer, offset, modbusPalProject.isLeanModeEnabled());
        if(length<0)
        {
            System.err.println("Illegal function code "+functionCode);
            length = makeExceptionResponse(functionCode,XC_ILLEGAL_FUNCTION, buffer, offset);
        }

        if( isExceptionResponse(buffer,offset)==true )
        {
            modbusPalProject.notifyExceptionResponse();
        }
        else
        {
            modbusPalProject.notifyPDUprocessed();
        }

        // delay the reply
        try {
            Thread.sleep(slave.getReplyDelay());
        } catch (InterruptedException ex) {
            Logger.getLogger(ModbusSlaveProcessor.class.getName()).log(Level.SEVERE, null, ex);
        }

        ModbusPalRecorder.recordOutgoing(slaveID,buffer,offset,length);
        return length;
    }

   
   
   
    protected int buildPDU(ModbusMasterRequest req, ModbusSlaveAddress slaveID, byte[] buffer, int offset/*, int pduLength*/)
    {
        // record the request
        // ModbusPalRecorder.recordIncoming(slaveID,buffer,offset,pduLength);

        // check if the slave is enabled
        if( modbusPalProject.isSlaveEnabled(slaveID) == false )
        {
            System.err.println("Slave "+slaveID+" is not enabled");
            req.notifyPDUnotServiced();
            modbusPalProject.notifyPDUnotServiced();
            return -1;
        }

       
        byte functionCode = req.getFunctionCode();
       
       
        // get the slave:
        ModbusSlave slave = modbusPalProject.getModbusSlave(slaveID);

        // retrive the pdu processor for the modbus function:
       
        ModbusPduProcessor mspp = slave.getPduProcessor(functionCode);
        if( mspp == null )
        {
            System.err.println("Unsupported function code "+functionCode);
            //int length = makeExceptionResponse(functionCode,XC_ILLEGAL_FUNCTION, buffer, offset);
            //ModbusPalRecorder.recordOutgoing(slaveID,buffer,offset,length);
            req.notifyExceptionResponse();
            modbusPalProject.notifyExceptionResponse();
            return -1;
        }

        int length = mspp.buildPDU(req, slaveID, buffer, offset, modbusPalProject.isLeanModeEnabled());
        if(length==-1)
        {
            System.err.println("Illegal function code "+functionCode);
            req.notifyPDUnotServiced();
            modbusPalProject.notifyPDUnotServiced();
            return -1;
        }

        //req.notifyPDUprocessed();
        //modbusPalProject.notifyPDUprocessed();      

        return length;
    }   
   
   
   
   
   
    /**
     * The subclass will call this method in order to process the content of
     * the PDU that has been received from the slave.
     * @param slaveID the slave identifier of the replying MODBUS device
     * @param buffer a byte buffer containing the MODBUS PDU
     * @param offset the offset in the buffer where the PDU actually starts
     * @param pduLength the length of the PDU.
     * @return
     */
    protected boolean processPDU(ModbusMasterRequest req, ModbusSlaveAddress slaveID, byte[] buffer, int offset, int pduLength)
    {
        // record the request
        // ModbusPalRecorder.recordIncoming(slaveID,buffer,offset,pduLength);

        // check if the slave is enabled
        if( modbusPalProject.isSlaveEnabled(slaveID) == false )
        {
            System.err.println("Slave "+slaveID+" is not enabled");
            req.notifyPDUnotServiced();
            modbusPalProject.notifyPDUnotServiced();
            return false;
        }

        // get the slave:
        ModbusSlave slave = modbusPalProject.getModbusSlave(slaveID);

        byte functionCode = buffer[offset+0];
       
        //
        if( isExceptionResponse(buffer,offset)==true )
        {
            req.notifyExceptionResponse();
            modbusPalProject.notifyExceptionResponse();
            return false;
        }

       
        // retrive the pdu processor for the modbus function:
       
        ModbusPduProcessor mspp = slave.getPduProcessor(functionCode);
        if( mspp == null )
        {
            System.err.println("Unsupported function code "+functionCode);
            //int length = makeExceptionResponse(functionCode,XC_ILLEGAL_FUNCTION, buffer, offset);
            //ModbusPalRecorder.recordOutgoing(slaveID,buffer,offset,length);
            req.notifyExceptionResponse();
            modbusPalProject.notifyExceptionResponse();
            return false;
        }

        boolean result = mspp.processPDU(req, slaveID, buffer, offset, modbusPalProject.isLeanModeEnabled());
        if(result==false)
        {
            System.err.println("Illegal function code "+functionCode);
            req.notifyPDUnotServiced();
            modbusPalProject.notifyPDUnotServiced();
            return false;
        }

        req.notifyPDUprocessed();
        modbusPalProject.notifyPDUprocessed();      

        return true;
    }

    /**
     * Builds a standard exception response given the specified arguments.
     * @param functionCode the function code that generates the exception
     * @param exceptionCode the code that explicits the cause of the exception
     * @param buffer the buffer where to write the exception
     * @param offset the offset in the buffer where to start writing
     * @return the length of the exception response
     */
    public static int makeExceptionResponse(byte functionCode, byte exceptionCode, byte[] buffer, int offset)
    {
        buffer[offset+0] = (byte) (((byte)0x80) | functionCode);
        buffer[offset+1] = exceptionCode;
        return 2;
    }

    /**
     * Builds a standard exception response given the specified arguments.
     * The function code is OR-ed with 0x80.
     * @param exceptionCode the code that explicits the cause of the exception
     * @param buffer the buffer where to write the exception
     * @param offset the offset in the buffer where to start writing
     * @return the length of the exception response
     */
    public static int makeExceptionResponse(byte exceptionCode, byte[] buffer, int offset)
    {
        buffer[offset+0] |= (byte)0x80;
        buffer[offset+1] = exceptionCode;
        return 2;
    }

    private boolean isExceptionResponse(byte[] buffer, int offset)
    {
        byte b = buffer[offset];
        return( (b&0x80) == 0x80 );
    }

}
TOP

Related Classes of modbuspal.link.ModbusSlaveProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.