Class AbstractNettyIOClient<T,U extends SocketAddress>

java.lang.Object
org.openremote.agent.protocol.io.AbstractNettyIOClient<T,U>
All Implemented Interfaces:
IOClient<T>, NettyIOClient<T>
Direct Known Subclasses:
SerialIOClient, TCPIOClient, UDPIOClient, WebsocketIOClient

public abstract class AbstractNettyIOClient<T,U extends SocketAddress> extends Object implements NettyIOClient<T>
This is a IOClient implementation for netty.

It uses the netty component for managing the connection.

Concrete implementations are responsible for providing the ChannelOutboundHandlers and ChannelInboundHandlers required to encode/decode the specific type of messages sent/received to/from this client. For IOClients that require some specific encoders/decoders irrespective of the message type (e.g. UDPIOClient and WebsocketIOClient) the addEncodersDecoders(io.netty.channel.Channel) method can be overridden so the IOClient can exactly control the order and types of encoders/decoders in the pipeline.

Users of the IOClient can add encoders/decoders for their specific message type using the setEncoderDecoderProvider(java.util.function.Supplier<io.netty.channel.ChannelHandler[]>), each IOClient should make it clear to users what the required output type(s) are for the last encoder and decoder that a user may wish to add, if adding encoders/decoders is not supported then IOClients should override this setter and throw an UnsupportedOperationException.

Typically for outgoing messages a single ChannelOutboundHandler is sufficient and the AbstractNettyIOClient.MessageToByteEncoder can be used as a base.

For inbound messages; the decoders required are very much dependent on the message type and IOClient type, any number of standard netty ChannelInboundHandlers can be used but the last handler should build messages of type <T> and pass them to the onMessageReceived(T) method of the client; the AbstractNettyIOClient.ByteToMessageDecoder or AbstractNettyIOClient.MessageToByteEncoder can be used for this purpose, which one to use will depend on the previous ChannelInboundHandlers in the pipeline.

NOTE: Care must be taken when working with Netty ByteBuf as Netty uses reference counting to manage their lifecycle. Refer to the Netty documentation for more information.

  • Field Details

    • RECONNECT_DELAY_INITIAL_MILLIS

      public static long RECONNECT_DELAY_INITIAL_MILLIS
    • RECONNECT_DELAY_MAX_MILLIS

      public static long RECONNECT_DELAY_MAX_MILLIS
    • messageConsumers

      protected final List<Consumer<T>> messageConsumers
    • connectionStatusConsumers

      protected final List<Consumer<org.openremote.model.asset.agent.ConnectionStatus>> connectionStatusConsumers
    • connectionStatus

      protected org.openremote.model.asset.agent.ConnectionStatus connectionStatus
    • channel

      protected io.netty.channel.Channel channel
    • bootstrap

      protected io.netty.bootstrap.Bootstrap bootstrap
    • workerGroup

      protected io.netty.channel.EventLoopGroup workerGroup
    • executorService

      protected ExecutorService executorService
    • scheduledExecutorService

      protected ScheduledExecutorService scheduledExecutorService
    • connectRetry

      protected CompletableFuture<Void> connectRetry
    • connectTimeout

      protected int connectTimeout
    • encoderDecoderProvider

      protected Supplier<io.netty.channel.ChannelHandler[]> encoderDecoderProvider
  • Constructor Details

    • AbstractNettyIOClient

      protected AbstractNettyIOClient()
  • Method Details

    • setEncoderDecoderProvider

      public void setEncoderDecoderProvider(Supplier<io.netty.channel.ChannelHandler[]> encoderDecoderProvider) throws UnsupportedOperationException
      Description copied from interface: NettyIOClient
      Allows appropriate encoders and decoders to be added to the message pipeline; if an IOClient doesn't support this then an UnsupportedOperationException will be thrown, consult the IOClient's documentation.
      Specified by:
      setEncoderDecoderProvider in interface NettyIOClient<T>
      Throws:
      UnsupportedOperationException
    • getConnectTimeoutMillis

      public int getConnectTimeoutMillis()
    • setConnectTimeoutMillis

      public void setConnectTimeoutMillis(int connectTimeout)
    • getChannelClass

      protected abstract Class<? extends io.netty.channel.Channel> getChannelClass()
    • getWorkerGroup

      protected abstract io.netty.channel.EventLoopGroup getWorkerGroup()
    • startChannel

      protected abstract Future<Void> startChannel()
      Start the actual connection and return a future indicating completion state. Implementors can also add any custom connection logic they require.
    • configureChannel

      protected void configureChannel()
    • connect

      public void connect()
      Description copied from interface: IOClient
      Connect to the device
      Specified by:
      connect in interface IOClient<T>
    • scheduleDoConnect

      protected void scheduleDoConnect(long initialDelay)
    • waitForConnectFuture

      protected Void waitForConnectFuture(Future<Void> connectFuture) throws Exception
      Throws:
      Exception
    • doConnect

      protected Future<Void> doConnect()
    • disconnect

      public void disconnect()
      Description copied from interface: IOClient
      Disconnect from the device
      Specified by:
      disconnect in interface IOClient<T>
    • doReconnect

      protected void doReconnect()
    • doDisconnect

      protected void doDisconnect()
    • sendMessage

      public void sendMessage(T message)
      Description copied from interface: IOClient
      Send a message over the wire
      Specified by:
      sendMessage in interface IOClient<T>
    • getConnectionStatus

      public org.openremote.model.asset.agent.ConnectionStatus getConnectionStatus()
      Description copied from interface: IOClient
      Get current connection status
      Specified by:
      getConnectionStatus in interface IOClient<T>
    • addConnectionStatusConsumer

      public void addConnectionStatusConsumer(Consumer<org.openremote.model.asset.agent.ConnectionStatus> connectionStatusConsumer)
      Description copied from interface: IOClient
      Add a consumer of connection status
      Specified by:
      addConnectionStatusConsumer in interface IOClient<T>
    • removeConnectionStatusConsumer

      public void removeConnectionStatusConsumer(Consumer<org.openremote.model.asset.agent.ConnectionStatus> connectionStatusConsumer)
      Description copied from interface: IOClient
      Remove a consumer of connection status
      Specified by:
      removeConnectionStatusConsumer in interface IOClient<T>
    • removeAllConnectionStatusConsumers

      public void removeAllConnectionStatusConsumers()
      Description copied from interface: IOClient
      Remove every consumer of connection status
      Specified by:
      removeAllConnectionStatusConsumers in interface IOClient<T>
    • addMessageConsumer

      public void addMessageConsumer(Consumer<T> messageConsumer)
      Description copied from interface: IOClient
      Add a consumer of received messages
      Specified by:
      addMessageConsumer in interface IOClient<T>
    • removeMessageConsumer

      public void removeMessageConsumer(Consumer<T> messageConsumer)
      Description copied from interface: IOClient
      Remove a consumer of received messages
      Specified by:
      removeMessageConsumer in interface IOClient<T>
    • removeAllMessageConsumers

      public void removeAllMessageConsumers()
      Description copied from interface: IOClient
      Remove every consumer of received messages
      Specified by:
      removeAllMessageConsumers in interface IOClient<T>
    • initChannel

      protected void initChannel(io.netty.channel.Channel channel) throws Exception
      Inserts the decoders and encoders into the channel pipeline and configures standard exception handling and logging
      Throws:
      Exception
    • addEncodersDecoders

      protected void addEncodersDecoders(io.netty.channel.Channel channel) throws Exception
      Throws:
      Exception
    • onMessageReceived

      protected void onMessageReceived(T message)
    • onDecodeException

      protected void onDecodeException(io.netty.channel.ChannelHandlerContext ctx, io.netty.handler.codec.DecoderException decoderException)
    • onEncodeException

      protected void onEncodeException(io.netty.channel.ChannelHandlerContext ctx, io.netty.handler.codec.EncoderException encoderException)
    • onConnectionStatusChanged

      protected void onConnectionStatusChanged(org.openremote.model.asset.agent.ConnectionStatus connectionStatus)
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • toCompletableFuture

      public static CompletableFuture<Void> toCompletableFuture(Future<Void> future) throws UnsupportedOperationException
      Throws:
      UnsupportedOperationException