1 package fr.ifremer.tutti.ichtyometer.interactive;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import com.google.common.base.Preconditions;
26 import com.google.common.io.Closeables;
27 import fr.ifremer.tutti.ichtyometer.IchtyometerClient;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import javax.microedition.io.StreamConnection;
32 import java.io.DataInputStream;
33 import java.io.DataOutputStream;
34 import java.io.IOException;
35 import java.util.concurrent.Callable;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.ExecutorService;
38 import java.util.concurrent.Executors;
39 import java.util.concurrent.Future;
40 import java.util.concurrent.TimeUnit;
41 import java.util.concurrent.TimeoutException;
42
43
44
45
46
47
48
49
50
51 public class CommandEngine {
52
53
54 private static final Log log = LogFactory.getLog(CommandEngine.class);
55
56 protected IchtyometerClient client;
57
58 protected StreamConnection connection;
59
60 protected DataOutputStream dataOutputStream;
61
62 protected DataInputStream dataInputStream;
63
64 protected ExecutorService service;
65
66 public void start(IchtyometerClient client) throws IOException {
67
68 Preconditions.checkNotNull(client, "client can not be null");
69 Preconditions.checkState(client.isOpen(), "client must be opened");
70 this.client = client;
71
72
73 this.service = Executors.newSingleThreadScheduledExecutor();
74
75
76 this.connection = client.openConnection();
77
78
79 this.dataInputStream = connection.openDataInputStream();
80
81
82 this.dataOutputStream = connection.openDataOutputStream();
83
84
85 if (log.isDebugEnabled()) {
86 log.debug("Ready to read remote device...");
87 }
88 }
89
90 public void stop() throws IOException {
91
92 Closeables.close(dataInputStream, true);
93 Closeables.close(dataOutputStream, true);
94 Closeables.close(client, true);
95 }
96
97 public Command sendCommand(String question) throws IOException {
98
99 Preconditions.checkNotNull(question, "command can not be null");
100
101 Callable<Command> call = new CommandCallable(question, dataInputStream, dataOutputStream);
102
103 Future<Command> submit = service.submit(call);
104
105 try {
106 return submit.get(1, TimeUnit.MINUTES);
107 } catch (InterruptedException | TimeoutException e) {
108 throw new IchtyometerCommandException("Time out on command " + question, e);
109 } catch (ExecutionException e) {
110 throw new IchtyometerCommandException(e.getCause());
111 }
112 }
113
114 protected static class CommandCallable implements Callable<Command> {
115
116 protected String question;
117
118 protected DataInputStream dataInputStream;
119
120 protected DataOutputStream dataOutputStream;
121
122 protected CommandCallable(String question,
123 DataInputStream dataInputStream,
124 DataOutputStream dataOutputStream) {
125
126 this.question = question;
127 this.dataInputStream = dataInputStream;
128 this.dataOutputStream = dataOutputStream;
129 }
130
131 @Override
132 public Command call() throws Exception {
133
134
135 dataOutputStream.writeChars(question);
136
137 StringBuilder responseBuilder = new StringBuilder();
138
139 boolean responseComplete = false;
140
141 while (!responseComplete) {
142
143 while (dataInputStream.available() > 0) {
144
145 int c = dataInputStream.read();
146
147 switch (c) {
148 case '\r':
149
150
151 responseBuilder.append('\n');
152 break;
153 case '#':
154
155
156 responseComplete = true;
157
158
159 responseBuilder.append((char) c);
160 break;
161 default:
162
163 responseBuilder.append((char) c);
164 }
165 }
166 }
167
168 String response = responseBuilder.toString();
169
170 return new Command(question, response, null);
171 }
172 }
173
174 }