1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.chabala.brick.controllab;
20
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.io.Closeable;
25 import java.io.IOException;
26 import java.time.Duration;
27 import java.util.concurrent.*;
28
29
30
31
32 class KeepAliveMonitor implements Closeable {
33 private final Logger log = LoggerFactory.getLogger(getClass());
34 private final SerialPortWriter serialPortWriter;
35 private final ScheduledExecutorService executor;
36 private final long keepAlivePeriodMs;
37 private static final byte KEEP_ALIVE_COMMAND = 0x02;
38
39 private static final int KEEP_ALIVE_PERIOD_MS = 1800;
40 private ScheduledFuture<?> task;
41
42
43
44
45
46
47
48
49 KeepAliveMonitor(SerialPortWriter serialPortWriter) {
50 this(serialPortWriter, Duration.ofMillis(KEEP_ALIVE_PERIOD_MS));
51 }
52
53 KeepAliveMonitor(SerialPortWriter serialPortWriter, Duration keepAlivePeriod) {
54 this.serialPortWriter = serialPortWriter;
55 this.keepAlivePeriodMs = keepAlivePeriod.toMillis();
56 executor = Executors.newSingleThreadScheduledExecutor(
57 new NamedDaemonThreadFactory(
58 "KeepAlive " + serialPortWriter.getPortName()));
59 scheduleTask();
60 }
61
62
63
64
65
66
67 void reset() {
68 task.cancel(false);
69 scheduleTask();
70 }
71
72 private void scheduleTask() {
73 task = executor.scheduleAtFixedRate(() -> sendCommand(KEEP_ALIVE_COMMAND),
74 keepAlivePeriodMs, keepAlivePeriodMs, TimeUnit.MILLISECONDS);
75 }
76
77 private void sendCommand(byte b) {
78 try {
79 serialPortWriter.sendCommand(b, log);
80 } catch (IOException e) {
81 log.error(e.getMessage(), e);
82 }
83 }
84
85
86
87
88 @Override
89 public void close() {
90 if (executor != null) {
91 executor.shutdownNow();
92 }
93 }
94
95
96
97
98 private static class NamedDaemonThreadFactory implements ThreadFactory {
99 private ThreadFactory defaultThreadFactory = Executors.defaultThreadFactory();
100 private final String threadName;
101
102 NamedDaemonThreadFactory(String threadName) {
103 this.threadName = threadName;
104 }
105
106 @Override
107 public Thread newThread(Runnable r) {
108 Thread thread = defaultThreadFactory.newThread(r);
109 thread.setName(threadName);
110 thread.setDaemon(true);
111 return thread;
112 }
113 }
114 }