19
19
import io .netty .channel .SimpleChannelInboundHandler ;
20
20
import io .netty .channel .socket .SocketChannel ;
21
21
import io .netty .channel .socket .nio .NioSocketChannel ;
22
+ import java .util .List ;
22
23
import java .util .concurrent .CompletableFuture ;
23
24
import java .util .concurrent .CompletionStage ;
25
+ import java .util .concurrent .CopyOnWriteArrayList ;
24
26
import java .util .concurrent .atomic .AtomicReference ;
25
27
import java .util .function .Consumer ;
26
28
import org .slf4j .Logger ;
@@ -36,6 +38,8 @@ public class NettyTcpClientTransport implements ModbusTcpClientTransport {
36
38
37
39
private final AtomicReference <Consumer <ModbusTcpFrame >> frameReceiver = new AtomicReference <>();
38
40
41
+ private final List <ConnectionListener > connectionListeners = new CopyOnWriteArrayList <>();
42
+
39
43
private final ChannelFsm channelFsm ;
40
44
private final ExecutionQueue executionQueue ;
41
45
@@ -54,12 +58,23 @@ public NettyTcpClientTransport(NettyClientTransportConfig config) {
54
58
.build ()
55
59
);
56
60
61
+ executionQueue = new ExecutionQueue (config .executor ());
62
+
57
63
channelFsm .addTransitionListener (
58
- (from , to , via ) ->
59
- logger .debug ("onStateTransition: {} -> {} via {}" , from , to , via )
64
+ (from , to , via ) -> {
65
+ logger .debug ("onStateTransition: {} -> {} via {}" , from , to , via );
66
+
67
+ executionQueue .submit (() -> handleStateTransition (from , to , via ));
68
+ }
60
69
);
70
+ }
61
71
62
- executionQueue = new ExecutionQueue (config .executor ());
72
+ private void handleStateTransition (State from , State to , Event via ) {
73
+ if (from != State .Connected && to == State .Connected ) {
74
+ connectionListeners .forEach (ConnectionListener ::onConnection );
75
+ } else if (from == State .Connected && to != State .Connected ) {
76
+ connectionListeners .forEach (ConnectionListener ::onConnectionLost );
77
+ }
63
78
}
64
79
65
80
@ Override
@@ -99,6 +114,24 @@ public boolean isConnected() {
99
114
return channelFsm .getState () == State .Connected ;
100
115
}
101
116
117
+ /**
118
+ * Add a {@link ConnectionListener} to this transport.
119
+ *
120
+ * @param listener the listener to add.
121
+ */
122
+ public void addConnectionListener (ConnectionListener listener ) {
123
+ connectionListeners .add (listener );
124
+ }
125
+
126
+ /**
127
+ * Remove a {@link ConnectionListener} from this transport.
128
+ *
129
+ * @param listener the listener to remove.
130
+ */
131
+ public void removeConnectionListener (ConnectionListener listener ) {
132
+ connectionListeners .remove (listener );
133
+ }
134
+
102
135
private class ModbusTcpFrameHandler extends SimpleChannelInboundHandler <ModbusTcpFrame > {
103
136
104
137
@ Override
@@ -179,4 +212,18 @@ public static NettyTcpClientTransport create(
179
212
return new NettyTcpClientTransport (config );
180
213
}
181
214
215
+ public interface ConnectionListener {
216
+
217
+ /**
218
+ * Callback invoked when the transport has connected.
219
+ */
220
+ void onConnection ();
221
+
222
+ /**
223
+ * Callback invoked when the transport has disconnected.
224
+ */
225
+ void onConnectionLost ();
226
+
227
+ }
228
+
182
229
}
0 commit comments