
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 (preferably on the Connection instance) 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 tracer tracer to be used for tracing raw data.
    * @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, Tracer tracer, ModbusMessage message)
        throws IOException, InterruptedException;

    /**
    * Receives a Modbus message
    * @param connection connection to receive message from.
    * @param tracer tracer to be used for tracing errors and raw data.
    * @param isRequest {@code true} if a request is to be received,
    * {@code false} if a response is to be received.
    * @param reporter handler for reporting recoverable errors.
    * May be {@code null} if no reporting is required.
    * @return the received message.
    * @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,
            boolean isRequest, Reporter reporter)
        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_TARGET_FAILED_TO_RESPOND) 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_TARGET_FAILED_TO_RESPOND) 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 input delimiter character.
    * This is only relevant to the ASCII packet type.
    * @param delimiter the new delimiter character.
    * @return the previous delimiter character.
    */
    int setDelimiter (int delimiter);


    /** 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);
}

