
package uk.co.wingpath.modbus;

import java.io.*;
import uk.co.wingpath.io.*;
import uk.co.wingpath.util.*;

/**
* This interface is implemented by classes that send and receive Modbus
* messages.
* <p>Different implementations are used for the different methods of
* packaging Modbus messages (RTU, ASCII, TCP).
* <p>Implementations are not thread-safe and do not guarantee atomicity:
* callers must synchronize in order to ensure thread-safety and atomicity
* of reads/writes/transactions.
*/
public interface PacketType
{
    /**
    * Sends a Modbus message.
    * @param connection connection to send message to.
    * @param message the message to be sent.
    * @throws IOException if an I/O error occurs.
    * @throws InterruptedException if the thread is interrupted.
    */
    void send (Connection connection, ModbusMessage message)
        throws IOException, InterruptedException;

    /**
    * Receives a Modbus request.
    * @param connection connection to receive request from.
    * @param tracer tracer to be used for tracing errors and raw data.
    * May be {@code null} if no tracing is required.
    * @param counters diagnostic counters.
    * May be {@code null} if no diagnostic counting is required.
    * @return the received request.
    * @throws InterruptedIOException if a timeout occurs before a request is
    * received.
    * @throws IOException if some other I/O error occurs.
    * @throws InterruptedException if the thread is interrupted.
    */
    ModbusMessage receiveRequest (Connection connection, Tracer tracer,
            ModbusCounters counters)
        throws InterruptedIOException, IOException, InterruptedException;

    /**
    * Receives a Modbus response.
    * @param connection connection to receive response from.
    * @param tracer tracer to be used for tracing errors and raw data.
    * May be {@code null} if no tracing is required.
    * @param counters diagnostic counters.
    * May be {@code null} if no diagnostic counting is required.
    * @return the received response.
    * @throws InterruptedIOException if a timeout occurs before a response is
    * received.
    * @throws IOException if some other I/O error occurs.
    * @throws InterruptedException if the thread is interrupted.
    */
    ModbusMessage receiveResponse (Connection connection, Tracer tracer,
            ModbusCounters counters)
        throws InterruptedIOException, IOException, InterruptedException;

    /**
    * Receives a Modbus message (request or response).
    * <p>It's not always possible to tell if a Modbus message is a request or
    * response message simply by inspecting its contents (some response
    * messages are simply echoes of the requests). This method
    * assumes that a message is a request if it's not possible to distinguish.
    * @param connection connection to receive message from.
    * @param tracer tracer to be used for tracing errors and raw data.
    * May be {@code null} if no tracing is required.
    * @param counters diagnostic counters.
    * May be {@code null} if no diagnostic counting is required.
    * @return the received message. If expectRequest is false, this will be
    * a response message. If expectRequest is true, the returned message may
    * be a request or a response.
    * @throws InterruptedIOException if a timeout occurs before a message is
    * received.
    * @throws IOException if some other I/O error occurs.
    * @throws InterruptedException if the thread is interrupted.
    */
    ModbusMessage receive (Connection connection, Tracer tracer,
            ModbusCounters counters)
        throws InterruptedIOException, IOException, InterruptedException;

    /**
    * Does packet type support transaction identifiers?
    * @return {@code true} if transaction identifiers supported
    */
    boolean hasTransactionIds ();

    /** 
    * Sets the timeout for the start of a message.
    * <p>A ModbusException (ERROR_TIMED_OUT) will be thrown
    * by the {@link #receive receive} method if the first byte of a message
    * is not received within this period.
    * @param timeout timeout in milliseconds.
    */
    void setTimeout (int timeout);

    /** 
    * Sets the timeout for the end of a message.
    * <p>A ModbusException (ERROR_TIMED_OUT) will be thrown
    * by the {@link #receive receive} method if there is a gap longer than this
    * period within a message.
    * @param timeout timeout in milliseconds.
    */
    void setEomTimeout (int timeout);

    /** Sets the maximum PDU size.
    * @param maxPdu maximum PDU size in bytes.
    */
    public void setMaxPdu (int maxPdu);

    /**
    * Sets the "allow long messages" state.
    * Default value is {@code false}.
    * If set to {@code true}, messages with more than 255 bytes of data
    * will be allowed:
    * the byte count in received messages will be ignored, and the byte
    * count in sent messages will be set to 0 if more than 255 bytes of data
    * are being sent.
    * @param allowLongMessages value for "allow long messages" state.
    */
    void setAllowLongMessages (boolean allowLongMessages);
}

