@SuppressWarnings("unchecked")
    public static <Request extends ModbusRequest, Response extends ModbusResponse>
        ModbusTcpServiceRequest<Request, Response> of(ModbusTcpPayload payload, Channel channel) {

      return new ModbusTcpServiceRequest<>(
          payload.getTransactionId(),
          payload.getUnitId(),
          (Request) payload.getModbusPdu(),
          channel);
    }
  private void onChannelRead(ChannelHandlerContext ctx, ModbusTcpPayload payload) {
    ServiceRequestHandler handler = requestHandler.get();
    if (handler == null) return;

    switch (payload.getModbusPdu().getFunctionCode()) {
      case ReadCoils:
        handler.onReadCoils(ModbusTcpServiceRequest.of(payload, ctx.channel()));
        break;

      case ReadDiscreteInputs:
        handler.onReadDiscreteInputs(ModbusTcpServiceRequest.of(payload, ctx.channel()));
        break;

      case ReadHoldingRegisters:
        handler.onReadHoldingRegisters(ModbusTcpServiceRequest.of(payload, ctx.channel()));
        break;

      case ReadInputRegisters:
        handler.onReadInputRegisters(ModbusTcpServiceRequest.of(payload, ctx.channel()));
        break;

      case WriteSingleCoil:
        handler.onWriteSingleCoil(ModbusTcpServiceRequest.of(payload, ctx.channel()));
        break;

      case WriteSingleRegister:
        handler.onWriteSingleRegister(ModbusTcpServiceRequest.of(payload, ctx.channel()));
        break;

      case WriteMultipleCoils:
        handler.onWriteMultipleCoils(ModbusTcpServiceRequest.of(payload, ctx.channel()));
        break;

      case WriteMultipleRegisters:
        handler.onWriteMultipleRegisters(ModbusTcpServiceRequest.of(payload, ctx.channel()));
        break;

      case MaskWriteRegister:
        handler.onMaskWriteRegister(ModbusTcpServiceRequest.of(payload, ctx.channel()));
        break;

      default:
        /* Function code not currently supported */
        ExceptionResponse response =
            new ExceptionResponse(
                payload.getModbusPdu().getFunctionCode(), ExceptionCode.IllegalFunction);

        ctx.writeAndFlush(
            new ModbusTcpPayload(payload.getTransactionId(), payload.getUnitId(), response));
        break;
    }
  }