public interface ModbusPdu {

    FunctionCode getFunctionCode();

} public class ExceptionResponse extends SimpleModbusResponse {

    private final ExceptionCode exceptionCode;

    public ExceptionResponse(FunctionCode functionCode, ExceptionCode exceptionCode) {
        super(functionCode);

        this.exceptionCode = exceptionCode;
    }

    public ExceptionCode getExceptionCode() {
        return exceptionCode;
    }

} public class MaskWriteRegisterResponse extends SimpleModbusResponse {

    private final int address;
    private final int andMask;
    private final int orMask;

    /**
     * @param address 0x0000 to 0xFFFF (0 to 65535)
     * @param andMask 0x0000 to 0xFFFF (0 to 65535)
     * @param orMask  0x0000 to 0xFFFF (0 to 65535)
     */
    public MaskWriteRegisterResponse(int address, int andMask, int orMask) {
        super(FunctionCode.MaskWriteRegister);

        this.address = address;
        this.andMask = andMask;
        this.orMask = orMask;
    }

    public int getAddress() {
        return address;
    }

    public int getAndMask() {
        return andMask;
    }

    public int getOrMask() {
        return orMask;
    }

} public class ReadCoilsResponse extends ByteBufModbusResponse {

    public ReadCoilsResponse(ByteBuf coilStatus) {
        super(coilStatus, FunctionCode.ReadCoils);
    }

    /**
     * The coils in the response message are packed as one coil per bit of the data field. Status is indicated as 1=ON
     * and 0=OFF. The LSB of the first data byte contains the output addressed in the query. The other coils follow
     * toward the high order end of this byte, and from low order to high order in subsequent bytes.
     * <p>
     * If the returned output quantity is not a multiple of eight, the remaining bits in the final data byte will be
     * padded with zeros (toward the high order end of the byte).
     *
     * @return the {@link ByteBuf} containing coil status, 8 coils per byte.
     */
    public ByteBuf getCoilStatus() {
        return super.content();
    }

} public class ReadDiscreteInputsResponse extends ByteBufModbusResponse {

    public ReadDiscreteInputsResponse(ByteBuf data) {
        super(data, FunctionCode.ReadDiscreteInputs);
    }

    /**
     * The discrete inputs in the response message are packed as one input per bit of the data field. Status is
     * indicated as 1=ON; 0=OFF. The LSB of the first data byte contains the input addressed in the query. The other
     * inputs follow toward the high order end of this byte, and from low order to high order in subsequent bytes.
     * <p>
     * If the returned input quantity is not a multiple of eight, the remaining bits in the final data byte will be
     * padded with zeros (toward the high order end of the byte).
     *
     * @return the {@link ByteBuf} containing input status, 8 inputs per byte.
     */
    public ByteBuf getInputStatus() {
        return super.content();
    }

} public class ReadHoldingRegistersResponse extends ByteBufModbusResponse {

    public ReadHoldingRegistersResponse(ByteBuf registers) {
        super(registers, FunctionCode.ReadHoldingRegisters);
    }

    /**
     * The register data in the response message are packed as two bytes per register, with the binary contents right
     * justified within each byte. For each register, the first byte contains the high order bits and the second
     * contains the low order bits.
     *
     * @return the {@link ByteBuf} containing register data, two bytes per register.
     */
    public ByteBuf getRegisters() {
        return super.content();
    }

} public class ReadInputRegistersResponse extends ByteBufModbusResponse {

    public ReadInputRegistersResponse(ByteBuf registers) {
        super(registers, FunctionCode.ReadInputRegisters);
    }

    /**
     * The register data in the response message are packed as two bytes per register, with the binary contents right
     * justified within each byte. For each register, the first byte contains the high order bits and the second
     * contains the low order bits.
     *
     * @return the {@link ByteBuf} containing register data, two bytes per register.
     */
    public ByteBuf getRegisters() {
        return super.content();
    }

} public class ReadWriteMultipleRegistersResponse extends ByteBufModbusResponse {

    public ReadWriteMultipleRegistersResponse(ByteBuf registers) {
        super(registers, FunctionCode.ReadWriteMultipleRegisters);
    }

    /**
     * The register data in the response message are packed as two bytes per register, with the binary contents right
     * justified within each byte. For each register, the first byte contains the high order bits and the second
     * contains the low order bits.
     *
     * @return the {@link ByteBuf} containing register data, two bytes per register.
     */
    public ByteBuf getRegisters() {
        return super.content();
    }

} public class WriteMultipleCoilsResponse extends SimpleModbusResponse {

    private final int address;
    private final int quantity;

    /**
     * @param address  0x0000 to 0xFFFF (0 to 65535)
     * @param quantity 0x0001 to 0x07B0 (1 to 2000)
     */
    public WriteMultipleCoilsResponse(int address, int quantity) {
        super(FunctionCode.WriteMultipleCoils);

        this.address = address;
        this.quantity = quantity;
    }

    public int getAddress() {
        return address;
    }

    public int getQuantity() {
        return quantity;
    }

} public class WriteMultipleRegistersResponse extends SimpleModbusResponse {

    private final int address;
    private final int quantity;

    /**
     * @param address  0x0000 to 0xFFFF (0 to 65535)
     * @param quantity 0x0001 to 0x007B (1 to 123)
     */
    public WriteMultipleRegistersResponse(int address, int quantity) {
        super(FunctionCode.WriteMultipleRegisters);

        this.address = address;
        this.quantity = quantity;
    }

    public int getAddress() {
        return address;
    }

    public int getQuantity() {
        return quantity;
    }

} public class WriteSingleCoilResponse extends SimpleModbusResponse {

    private final int address;
    private final int value;

    /**
     * @param address 0x0000 to 0xFFFF (0 to 65535)
     * @param value   true or false (0xFF00 or 0x0000)
     */
    public WriteSingleCoilResponse(int address, int value) {
        super(FunctionCode.WriteSingleCoil);

        this.address = address;
        this.value = value;
    }

    public int getAddress() {
        return address;
    }

    public int getValue() {
        return value;
    }

} public class WriteSingleRegisterResponse extends SimpleModbusResponse {

    private final int address;
    private final int value;

    /**
     * @param address 0x0000 to 0xFFFF (0 to 65535)
     * @param value   0x0000 to 0xFFFF (0 to 65535)
     */
    public WriteSingleRegisterResponse(int address, int value) {
        super(FunctionCode.WriteSingleRegister);

        this.address = address;
        this.value = value;
    }

    public int getAddress() {
        return address;
    }

    public int getValue() {
        return value;
    }

}
import io.netty.util.ReferenceCountUtil;
import com.digitalpetri.modbus.ModbusPdu;
import com.digitalpetri.modbus.responses.ExceptionResponse;
import com.digitalpetri.modbus.responses.MaskWriteRegisterResponse;
import com.digitalpetri.modbus.responses.ReadCoilsResponse;
import com.digitalpetri.modbus.responses.ReadDiscreteInputsResponse;
import com.digitalpetri.modbus.responses.ReadHoldingRegistersResponse;
import com.digitalpetri.modbus.responses.ReadInputRegistersResponse;
import com.digitalpetri.modbus.responses.ReadWriteMultipleRegistersResponse;
import com.digitalpetri.modbus.responses.WriteMultipleCoilsResponse;
import com.digitalpetri.modbus.responses.WriteMultipleRegistersResponse;
import com.digitalpetri.modbus.responses.WriteSingleCoilResponse;
import com.digitalpetri.modbus.responses.WriteSingleRegisterResponse;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.EncoderException;
/*
 * Copyright 2016 Kevin Herron
 *
 * 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.
 */

package com.digitalpetri.modbus.codec;


public class ModbusResponseEncoder implements ModbusPduEncoder {

    @Override
    public ByteBuf encode(ModbusPdu modbusPdu, ByteBuf buffer) throws EncoderException {
        try {
            if (modbusPdu instanceof ExceptionResponse) {
                return encodeExceptionResponse((ExceptionResponse) modbusPdu, buffer);
            } else {
                switch (modbusPdu.getFunctionCode()) {
                    case ReadCoils:
                        return encodeReadCoils((ReadCoilsResponse) modbusPdu, buffer);

                    case ReadDiscreteInputs:
                        return encodeReadDiscreteInputs((ReadDiscreteInputsResponse) modbusPdu, buffer);

                    case ReadHoldingRegisters:
                        return encodeReadHoldingRegisters((ReadHoldingRegistersResponse) modbusPdu, buffer);

                    case ReadInputRegisters:
                        return encodeReadInputRegisters((ReadInputRegistersResponse) modbusPdu, buffer);

                    case WriteSingleCoil:
                        return encodeWriteSingleCoil((WriteSingleCoilResponse) modbusPdu, buffer);

                    case WriteSingleRegister:
                        return encodeWriteSingleRegister((WriteSingleRegisterResponse) modbusPdu, buffer);

                    case WriteMultipleCoils:
                        return encodeWriteMultipleCoils((WriteMultipleCoilsResponse) modbusPdu, buffer);

                    case WriteMultipleRegisters:
                        return encodeWriteMultipleRegisters((WriteMultipleRegistersResponse) modbusPdu, buffer);

                    case MaskWriteRegister:
                        return encodeMaskWriteRegister((MaskWriteRegisterResponse) modbusPdu, buffer);

                    case ReadWriteMultipleRegisters:
                        return encodeReadWriteMultipleRegisters((ReadWriteMultipleRegistersResponse) modbusPdu, buffer);