root / trunk / code / projects / colonet / client / ColonetServerInterface.java @ 1967
History | View | Annotate | Download (20.5 KB)
1 | 32 | gtress | /*
|
---|---|---|---|
2 | 539 | emarinel | * ColonetServerInterface.java
|
3 | * Gregory Tress
|
||
4 | 32 | gtress | */
|
5 | |||
6 | import java.net.*; |
||
7 | import java.io.*; |
||
8 | import javax.swing.JOptionPane; |
||
9 | import javax.swing.JTextArea; |
||
10 | |||
11 | 333 | gtress | /**
|
12 | * The Colonet server interface class. This class handles direct communication with the Colonet server. The general
|
||
13 | 527 | emarinel | * contract is that this class will encapsulate the process of sending commands and requests to the server and
|
14 | * receiving responses. This class should provide methods to send specific commands and requests so that the
|
||
15 | * Colonet can easily communicate with the server. When data is received from the server, the ColonetServerInterface
|
||
16 | * decides how to handle it and in many cases this means simply passing it to the Colonet.
|
||
17 | 333 | gtress | * <p>
|
18 | * The motivation is that any number of Colonet-type classes could be designed for different purposes if needed, with
|
||
19 | 527 | emarinel | * this class being used by each one for communication.
|
20 | 333 | gtress | * For instance, if an application is designed which only monitors sensor data, or that only has access to
|
21 | * the task queue, etc., the application could easily plug in to this interface.
|
||
22 | 527 | emarinel | * The Colonet should generally not contain communication-specific code or Strings of command and request data.
|
23 | 333 | gtress | * If additional commands and requests are needed for permanent implementation, it is suggested that convenience
|
24 | * classes be created in the ColonetServerInterface and called from the Colonet.
|
||
25 | *
|
||
26 | 527 | emarinel | * @author Gregory Tress
|
27 | 333 | gtress | */
|
28 | 527 | emarinel | public class ColonetServerInterface |
29 | 32 | gtress | { |
30 | 531 | emarinel | /* Old packet structure:
|
31 | 527 | emarinel | |
32 | 539 | emarinel | COMMAND PACKET STRUCTURE
|
33 | 1: SEND_TO_ROBOT
|
||
34 | 2: # of robot, or GLOBAL_DEST
|
||
35 | 3: COLONET_COMMMAND
|
||
36 | 4: message code (i.e. ORB_SET)
|
||
37 | 5: any data, as many that fit in the packet
|
||
38 | 527 | emarinel | |
39 | 32 | gtress | REQUEST PACKET STRUCTURE
|
40 | 539 | emarinel | 1: REQUEST_FROM_SERVER
|
41 | 2: # of robot
|
||
42 | 3: COLONET_REQUEST
|
||
43 | 4: ???
|
||
44 | 527 | emarinel | |
45 | 539 | emarinel | 9/12/07 New server interface structure
|
46 | Client will no longer send full robot packets to the server.
|
||
47 | Commands will be defined as necessary.
|
||
48 | 32 | gtress | */
|
49 | 527 | emarinel | |
50 | 76 | gtress | //General Colonet Interface
|
51 | 32 | gtress | public static final String SEND_TO_ROBOT = "0"; |
52 | 67 | gtress | public static final String REQUEST_FROM_SERVER = "1"; |
53 | 32 | gtress | public static final String RESPONSE_TO_CLIENT_REQUEST = "2"; |
54 | public static final String COLONET_COMMAND = "13"; //0x0D |
||
55 | public static final String COLONET_REQUEST = "14"; //0x0E |
||
56 | public static final String CORONET_RESPONSE = "15"; //0x0F |
||
57 | 76 | gtress | public static final String GLOBAL_DEST = "200"; |
58 | 698 | gtress | |
59 | //Common requests
|
||
60 | 459 | gtress | public static final String CLIENT_REQUEST_ROBOT_POSITIONS = "86"; |
61 | public static final String CLIENT_ASSIGN_ROBOT_ID = "87"; |
||
62 | 665 | gtress | public static final String CLIENT_SET_VIRTUAL_WALL = "89"; |
63 | 698 | gtress | public static final String SERVER_CLEAR_VIRTUAL_WALL = "92"; |
64 | 470 | gtress | public static final String MOVE_TO_ABSOLUTE_POSITION = "83"; //0x53 |
65 | 682 | gtress | public static final String ROBOT_REPORT_ARRIVED_AT_POSITION = "93"; //0x5D |
66 | 698 | gtress | public static final String REQUEST_BOM_MATRIX = "144"; |
67 | public static final String REQUEST_XBEE_IDS = "145"; |
||
68 | 739 | gtress | public static final String RECHARGE = "96"; //0x60 |
69 | 765 | gtress | public static final String RECHARGE_STOP = "97"; //0x61 |
70 | 527 | emarinel | |
71 | 107 | gtress | //Queue instructions
|
72 | public static final String COLONET_QUEUE = "100"; |
||
73 | 527 | emarinel | public static final String QUEUE_UPDATE = "101"; |
74 | 107 | gtress | public static final String QUEUE_ADD = "102"; |
75 | public static final String QUEUE_REMOVE = "103"; |
||
76 | public static final String QUEUE_REORDER = "104"; |
||
77 | 527 | emarinel | |
78 | 32 | gtress | //Use BATTERY to request battery level
|
79 | public static final String BATTERY = "56"; //0x38 |
||
80 | 527 | emarinel | |
81 | 32 | gtress | //MOTORS
|
82 | public static final String MOTORS_INIT = "23"; //0x17 |
||
83 | public static final String MOTOR1_SET = "24"; //0x18 |
||
84 | public static final String MOTOR2_SET = "25"; //0x19 |
||
85 | public static final String MOTORS_OFF = "26"; //0x1A |
||
86 | public static final String MOVE = "27"; //0x1B |
||
87 | 39 | gtress | public static final String MOVE_AVOID = "28"; //0x1C |
88 | 586 | gtress | public static final String MOVE_R = "29"; //0x1D |
89 | public static final String MOVE_L = "30"; //0x1E |
||
90 | public static final String MOVE_F = "31"; //0x1F |
||
91 | public static final String MOVE_B = "32"; //0x1G |
||
92 | 527 | emarinel | |
93 | 32 | gtress | //BUZZER
|
94 | public static final String BUZZER_INIT = "0"; //0x00 |
||
95 | public static final String BUZZER_SET_VAL = "1"; //0x01 |
||
96 | public static final String BUZZER_SET_FREQ = "2"; //0x02 |
||
97 | public static final String BUZZER_CHIRP = "3"; //0x03 |
||
98 | public static final String BUZZER_OFF = "4"; //0x04 |
||
99 | |||
100 | //ORB
|
||
101 | public static final String ORB_INIT = "12"; //0x0C |
||
102 | public static final String ORB_SET = "13"; //0x0D |
||
103 | public static final String ORB_SET_COLOR = "14"; //0x0E |
||
104 | public static final String ORB_DISABLE = "15"; //0x0F |
||
105 | public static final String ORB_ENABLE = "16"; //0x10 |
||
106 | public static final String ORB_SET_DIO = "17"; //0x11 |
||
107 | public static final String LED_INIT = "18"; //0x12 |
||
108 | public static final String LED_USER = "19"; //0x13 |
||
109 | public static final String ORB_SET_NUM_NS = "20"; //0x14 |
||
110 | public static final String ORB_SET_NUM = "21"; //0x15 |
||
111 | public static final String ORB_SEND = "22"; //0x16 |
||
112 | |||
113 | 539 | emarinel | Colonet colonet; //save reference to the entire applet locally
|
114 | 32 | gtress | Socket socket;
|
115 | OutputStreamWriter out;
|
||
116 | BufferedReader reader;
|
||
117 | 76 | gtress | DataListener dataListener; |
118 | 527 | emarinel | |
119 | 32 | gtress | /*
|
120 | 539 | emarinel | * FUNCTION IMPLEMENTATIONS
|
121 | 32 | gtress | */
|
122 | |||
123 | 333 | gtress | /**
|
124 | * Constructs a new ColonetServerInterface. When constructing a ColonetServerInterface, a valid Colonet object
|
||
125 | 527 | emarinel | * reference must be provided to ensure that data is routed correctly.
|
126 | 333 | gtress | *
|
127 | 527 | emarinel | * @param colonet The Colonet object to save locally. This reference cannot be changed once the
|
128 | 539 | emarinel | * ColonetSreverInterface has been contsructed.
|
129 | 333 | gtress | * @throws NullPointerException if colonet is null
|
130 | *
|
||
131 | */
|
||
132 | 136 | gtress | public ColonetServerInterface (Colonet colonet) {
|
133 | this.colonet = colonet;
|
||
134 | 76 | gtress | dataListener = new DataListener();
|
135 | 32 | gtress | } |
136 | |||
137 | public Socket getSocket () { |
||
138 | return socket;
|
||
139 | } |
||
140 | 527 | emarinel | |
141 | 32 | gtress | public OutputStreamWriter getOutputStreamWriter () { |
142 | return out;
|
||
143 | } |
||
144 | 527 | emarinel | |
145 | 32 | gtress | public BufferedReader getBufferedReader () { |
146 | return reader;
|
||
147 | } |
||
148 | 527 | emarinel | |
149 | 32 | gtress | public boolean isReady () { |
150 | 333 | gtress | if (socket == null || out == null || reader == null) |
151 | return false; |
||
152 | if (!socket.isConnected() || socket.isClosed() || socket.isInputShutdown() || socket.isOutputShutdown())
|
||
153 | return false; |
||
154 | 32 | gtress | return true; |
155 | } |
||
156 | 527 | emarinel | |
157 | 32 | gtress | public boolean isInputReady () { |
158 | try {
|
||
159 | if (reader.ready()) return true; |
||
160 | } catch (Exception e) { |
||
161 | return false; |
||
162 | } |
||
163 | return false; |
||
164 | } |
||
165 | 527 | emarinel | |
166 | 420 | gtress | public String getLine () throws IOException { |
167 | return reader.readLine();
|
||
168 | 39 | gtress | } |
169 | 527 | emarinel | |
170 | 32 | gtress | /**
|
171 | * Create socket connection to Colonet server.
|
||
172 | 333 | gtress | * If successful, start thread for listening for incoming data.
|
173 | 32 | gtress | */
|
174 | public void connect (String strHost, String strPort) { |
||
175 | //make sure hostname and port are valid
|
||
176 | if (strHost.equals("") || strPort.equals("")) { |
||
177 | err("Please enter a hostname and port.");
|
||
178 | return;
|
||
179 | } |
||
180 | int port = 0; |
||
181 | try {
|
||
182 | port = Integer.parseInt(strPort);
|
||
183 | } catch (Exception e) { |
||
184 | err("Invalid port");
|
||
185 | return;
|
||
186 | } |
||
187 | 527 | emarinel | |
188 | 181 | gtress | //make sure we aren't already connected.
|
189 | 32 | gtress | if (socket != null && socket.isConnected()) { |
190 | 181 | gtress | return;
|
191 | 32 | gtress | } |
192 | 527 | emarinel | |
193 | 32 | gtress | try {
|
194 | socket = new Socket(strHost, port); |
||
195 | 420 | gtress | socket.setKeepAlive(true);
|
196 | 32 | gtress | } catch (UnknownHostException e) { |
197 | err("Unknown Host Exception");
|
||
198 | return;
|
||
199 | } catch (IOException e) { |
||
200 | 542 | emarinel | err("Failed to connect to " + strHost + ".\n"); |
201 | 32 | gtress | return;
|
202 | } catch (java.security.AccessControlException e) {
|
||
203 | 585 | gtress | err("Permission denied.\n\n"
|
204 | 542 | emarinel | + "You may only connect to the server from which this applet was loaded.");
|
205 | 32 | gtress | return;
|
206 | } |
||
207 | 542 | emarinel | |
208 | 32 | gtress | if (socket == null || !socket.isConnected()) { |
209 | return;
|
||
210 | } |
||
211 | try {
|
||
212 | out = new OutputStreamWriter(socket.getOutputStream()); |
||
213 | reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); |
||
214 | } catch (IOException e) { |
||
215 | warn("Could not get transfer streams from socket connection.");
|
||
216 | } |
||
217 | 542 | emarinel | |
218 | 76 | gtress | dataListener.start(); |
219 | 32 | gtress | } |
220 | 527 | emarinel | |
221 | 420 | gtress | public void disconnect () { |
222 | 542 | emarinel | try {
|
223 | if (reader != null) { |
||
224 | reader.close(); |
||
225 | 539 | emarinel | } |
226 | 542 | emarinel | if (out != null) { |
227 | out.close(); |
||
228 | } |
||
229 | 549 | gtress | colonet.disconnect(); |
230 | 542 | emarinel | } catch (IOException e) { |
231 | } |
||
232 | 420 | gtress | } |
233 | 527 | emarinel | |
234 | 107 | gtress | /*
|
235 | 517 | gtress | * Send a general String to the OutputStream.
|
236 | 107 | gtress | */
|
237 | 333 | gtress | private void sendString (String s) { |
238 | 32 | gtress | //make sure we can send
|
239 | if (!this.isReady()) { |
||
240 | 585 | gtress | colonet.getInfoPanel().append("Could not send data.\n");
|
241 | 32 | gtress | return;
|
242 | } |
||
243 | //send packet
|
||
244 | try {
|
||
245 | 590 | gtress | Thread.sleep(100); //pause to be safe |
246 | 107 | gtress | out.write(s); |
247 | 32 | gtress | out.flush(); |
248 | } catch (IOException e) { |
||
249 | 585 | gtress | colonet.getInfoPanel().setText("Could not send data.\n");
|
250 | 107 | gtress | } catch (InterruptedException e) { |
251 | 67 | gtress | } |
252 | 32 | gtress | } |
253 | 527 | emarinel | |
254 | 333 | gtress | /**
|
255 | * General send-to-server method. This method is used by other command methods, which are usually convenience
|
||
256 | 527 | emarinel | * methods that simply specify arguments to this method. A command consists of a String which holds integers
|
257 | * separated by spaces. This method should not be used directly unless you know the format of the particular
|
||
258 | * command you are sending. If implementing a particular command for permanent use, it is recommended that
|
||
259 | 333 | gtress | * you create a new wrapper method specific to that command in the ColonetServerInterface file.
|
260 | *
|
||
261 | * Note that no checking is performed in this method to ensure the correct formatting of the String arguments.
|
||
262 | * If malformed commands or robot numbers are specified, the behavior of the request at the server will be
|
||
263 | 527 | emarinel | * undefined and could result in server failure.
|
264 | 333 | gtress | *
|
265 | * @param s The command String in its correct format. The format of a command String is ultimately specified
|
||
266 | 527 | emarinel | * by the Colonet server application and may change.
|
267 | * @param robotNumber The number of the robot that is the subject of the command, if any. The robot number
|
||
268 | * is specified as a single integer in a String. If the command does not have a single robot subject, this
|
||
269 | * argument can be null or an empty String, whichever is convenient.
|
||
270 | 333 | gtress | */
|
271 | 527 | emarinel | public void sendData (String s, String robotNumber) { |
272 | 107 | gtress | //create packet
|
273 | String packet = ""; |
||
274 | packet += ColonetServerInterface.SEND_TO_ROBOT; |
||
275 | 333 | gtress | if (robotNumber != null) |
276 | 517 | gtress | packet += " " + robotNumber;
|
277 | 107 | gtress | packet += " " + ColonetServerInterface.COLONET_COMMAND;
|
278 | 539 | emarinel | packet += " " + s; //add the command code here |
279 | 107 | gtress | packet += "\n";
|
280 | sendString(packet); |
||
281 | 585 | gtress | //colonet.getInfoPanel().append("S:" + packet);
|
282 | 107 | gtress | } |
283 | 527 | emarinel | |
284 | 333 | gtress | /**
|
285 | * General request-from-server method. This method is used by other request methods, which are usually convenience
|
||
286 | 527 | emarinel | * methods that simply specify arguments to this method. A request consists of a String which holds integers
|
287 | * separated by spaces. This method should not be used directly unless you know the format of the particular
|
||
288 | 333 | gtress | * request you are making. If implementing a particular request, it is recommended that you create a new method
|
289 | * specific to that request in the ColonetServerInterface file.
|
||
290 | *
|
||
291 | */
|
||
292 | private void sendRequest (String s, String robotNumber) { |
||
293 | 32 | gtress | //create packet
|
294 | 107 | gtress | String packet = ""; |
295 | packet += ColonetServerInterface.REQUEST_FROM_SERVER; |
||
296 | 270 | gtress | packet += " " + robotNumber;
|
297 | 539 | emarinel | packet += " " + s; //add the command code here |
298 | 32 | gtress | packet += "\n";
|
299 | 107 | gtress | sendString(packet); |
300 | 32 | gtress | } |
301 | 527 | emarinel | |
302 | /**
|
||
303 | * Sends a request to the server to report the entire BOM sensor matrix. The server will reply at its convenience.
|
||
304 | 333 | gtress | * No guarantee is made (end-to-end or otherwise) that the server will respond in a timely manner or at all
|
305 | * to any individual request.
|
||
306 | */
|
||
307 | 107 | gtress | public void sendSensorDataRequest () { |
308 | sendRequest(ColonetServerInterface.REQUEST_BOM_MATRIX, "");
|
||
309 | } |
||
310 | 527 | emarinel | |
311 | 333 | gtress | /**
|
312 | 527 | emarinel | * Sends a request to the server to report a list of XBee IDs. The server will reply at its convenience.
|
313 | 333 | gtress | * The purpose of having this list is to ensure that robots are properly identified for control purposes.
|
314 | 527 | emarinel | * This keeps robot identification consistent between sessions and prevents arbitrary assignment.
|
315 | 333 | gtress | * No guarantee is made (end-to-end or otherwise) that the server will respond in a timely manner or at all
|
316 | * to any individual request.
|
||
317 | *
|
||
318 | * @see Colonet#parseXBeeIDs(String)
|
||
319 | */
|
||
320 | 136 | gtress | public void sendXBeeIDRequest () { |
321 | sendRequest(ColonetServerInterface.REQUEST_XBEE_IDS, "");
|
||
322 | } |
||
323 | 527 | emarinel | |
324 | 333 | gtress | /**
|
325 | 527 | emarinel | * Sends a battery request for a specific robot to the server. The server will reply at its convenience.
|
326 | * Behavior is undefined if an invalid robot number is specified. The server will probably not respond in
|
||
327 | 333 | gtress | * this case.
|
328 | * No guarantee is made (end-to-end or otherwise) that the server will respond in a timely manner or at all
|
||
329 | * to any individual request.
|
||
330 | *
|
||
331 | * @param robotNum The number of the robot for which we are requesting the battery. Note that this value
|
||
332 | * is sent as-is to the server. No mapping to or from XBee IDs is performed. The contract for this is
|
||
333 | * currently undefined.
|
||
334 | * @see Colonet#parseBattery(String)
|
||
335 | */
|
||
336 | 270 | gtress | public void sendBatteryRequest (int robotNum) { |
337 | 425 | gtress | //create packet
|
338 | String packet = ""; |
||
339 | packet += ColonetServerInterface.SEND_TO_ROBOT; |
||
340 | packet += " " + robotNum;
|
||
341 | packet += " " + ColonetServerInterface.COLONET_REQUEST;
|
||
342 | 539 | emarinel | packet += " " + ColonetServerInterface.BATTERY; //add the command code here |
343 | 425 | gtress | packet += "\n";
|
344 | sendString(packet); |
||
345 | 567 | gtress | //System.out.println("Sent battery request: " + packet);
|
346 | 270 | gtress | } |
347 | 527 | emarinel | |
348 | 459 | gtress | /**
|
349 | * Requests a list of all robot positions and correspondind robot IDs.
|
||
350 | */
|
||
351 | public void sendPositionRequest () { |
||
352 | sendRequest(ColonetServerInterface.CLIENT_REQUEST_ROBOT_POSITIONS, "");
|
||
353 | } |
||
354 | 527 | emarinel | |
355 | 459 | gtress | /**
|
356 | * Send a robot ID assignment update to store on the server.
|
||
357 | */
|
||
358 | public void sendIDAssignment (int oldID, int newID) { |
||
359 | String packet = ""; |
||
360 | packet += ColonetServerInterface.REQUEST_FROM_SERVER; |
||
361 | 522 | gtress | packet += " " + CLIENT_ASSIGN_ROBOT_ID;
|
362 | 459 | gtress | packet += " " + oldID + " " + newID; |
363 | packet += "\n";
|
||
364 | sendString(packet); |
||
365 | } |
||
366 | 527 | emarinel | |
367 | /**
|
||
368 | 665 | gtress | * Order a robot to move to an absolute coordinate point.
|
369 | */
|
||
370 | 470 | gtress | public void sendAbsoluteMove (int id, int x, int y) { |
371 | 648 | emarinel | int x_high = (x>>8) & 0xff; |
372 | int x_low = x & 0xff; |
||
373 | int y_high = (y>>8) & 0xff; |
||
374 | int y_low = y & 0xff; |
||
375 | |||
376 | sendData(MOVE_TO_ABSOLUTE_POSITION + " " + x_high + " " + x_low + " " + y_high + " " + y_low, "" + id); |
||
377 | 470 | gtress | } |
378 | 739 | gtress | |
379 | /**
|
||
380 | * Tell a robot to recharge now
|
||
381 | */
|
||
382 | public void sendRecharge (int id) { |
||
383 | sendData(RECHARGE + "", id + ""); |
||
384 | 763 | gtress | System.out.println("Sent recharge command to ID " + id); |
385 | 739 | gtress | } |
386 | 681 | emarinel | |
387 | 765 | gtress | /**
|
388 | * Tell a robot to stop recharing now
|
||
389 | */
|
||
390 | public void sendRechargeStop (int id) { |
||
391 | sendData(RECHARGE_STOP + "", id + ""); |
||
392 | System.out.println("Sent recharge stop command to ID " + id); |
||
393 | } |
||
394 | |||
395 | 670 | gtress | /**
|
396 | * Establish a boundary for robot motion.
|
||
397 | */
|
||
398 | public void sendBoundary (int x1, int y1, int x2, int y2) { |
||
399 | String packet = ""; |
||
400 | 698 | gtress | packet += ColonetServerInterface.REQUEST_FROM_SERVER; |
401 | packet += " " + CLIENT_SET_VIRTUAL_WALL;
|
||
402 | 670 | gtress | packet += " " + x1 + " " + y1 + " " + x2 + " " + y2; |
403 | packet += "\n";
|
||
404 | sendString(packet); |
||
405 | } |
||
406 | 698 | gtress | |
407 | /**
|
||
408 | * Clear the boundary for robot motion.
|
||
409 | */
|
||
410 | public void sendBoundaryClear () { |
||
411 | String packet = ""; |
||
412 | packet += ColonetServerInterface.REQUEST_FROM_SERVER; |
||
413 | packet += " " + SERVER_CLEAR_VIRTUAL_WALL;
|
||
414 | packet += "\n";
|
||
415 | sendString(packet); |
||
416 | } |
||
417 | 527 | emarinel | |
418 | 107 | gtress | /*
|
419 | 539 | emarinel | * Queue management
|
420 | 107 | gtress | */
|
421 | 333 | gtress | private void sendQueueInstruction (String inst) { |
422 | 107 | gtress | String packet = ""; |
423 | packet += ColonetServerInterface.COLONET_QUEUE; |
||
424 | packet += " " + inst;
|
||
425 | packet += "\n";
|
||
426 | sendString(packet); |
||
427 | } |
||
428 | 527 | emarinel | |
429 | 333 | gtress | /**
|
430 | 527 | emarinel | * Notifies the Colonet server to add a task to the current task queue. The Colonet server holds the canonical
|
431 | 333 | gtress | * task queue. Any applet can send tasks to add to the queue. Local copies of the queue in the applet are for
|
432 | * display purposes only, and are not authoritative when adding tasks. All clients send additions asynchronously,
|
||
433 | 527 | emarinel | * and as a result no guarantee is made that a task will be added in the specificed location in the queue or at
|
434 | 333 | gtress | * all. If an invalid position is specified, the task will probably not be added to the queue and may cause
|
435 | * server failure. Due to the asynchronous nature of the queue, we cannot easily account for concurrent
|
||
436 | * modification failures on the client side.
|
||
437 | *
|
||
438 | 527 | emarinel | * @param pos The position in the queue at which we would like the task to be placed. Note that this is not
|
439 | 333 | gtress | * guaranteed. Invalid positions may cause the task to be discarded at the server.
|
440 | 527 | emarinel | * @param data The String containing the command code(s) for the task and any arguments necessary to fully
|
441 | 333 | gtress | * define the behavior of the task. This format is currently not specified. In the future, the canonical format
|
442 | * of the data String will ultimately be defined by the Colonet server.
|
||
443 | * @param description A String that contains a description of the task. This will be the message displayed to
|
||
444 | 527 | emarinel | * the user when information about the task is requested.
|
445 | 333 | gtress | */
|
446 | 107 | gtress | public void sendQueueAdd (int pos, String data, String description) { |
447 | String packet = ""; |
||
448 | packet += ColonetServerInterface.QUEUE_ADD; |
||
449 | packet += " " + pos;
|
||
450 | packet += " " + data;
|
||
451 | packet += " [" + description + "]"; |
||
452 | packet += "\n";
|
||
453 | sendQueueInstruction(packet); |
||
454 | } |
||
455 | 527 | emarinel | |
456 | 333 | gtress | /**
|
457 | 527 | emarinel | * Notifies the Colonet server to remove a task from the current task queue. The Colonet server holds the canonical
|
458 | 333 | gtress | * task queue. Any applet can remove a task from the queue. Local copies of the queue in the applet are for
|
459 | * display purposes only, and are not authoritative when removing tasks. All clients remove tasks asynchronously,
|
||
460 | 527 | emarinel | * and as a result no guarantee is made that the correct task will actually be removed.
|
461 | 333 | gtress | * If an invalid position is specified, the state of the queue is undefined and server failure may result.
|
462 | * Due to the asynchronous nature of the queue, we cannot easily account for concurrent
|
||
463 | * modification failures on the client side.
|
||
464 | *
|
||
465 | 527 | emarinel | * @param pos The position in the queue at which we would like the task to be removed. Note that this is not
|
466 | 333 | gtress | * guaranteed. Invalid positions may result in a corrupted queue.
|
467 | */
|
||
468 | 107 | gtress | public void sendQueueRemove (int pos) { |
469 | String packet = ""; |
||
470 | packet += ColonetServerInterface.QUEUE_REMOVE; |
||
471 | packet += " " + pos;
|
||
472 | packet += "\n";
|
||
473 | sendQueueInstruction(packet); |
||
474 | } |
||
475 | 32 | gtress | |
476 | 333 | gtress | /**
|
477 | 527 | emarinel | * Notifies the Colonet server to reorder tasks in the current task queue. The Colonet server holds the canonical
|
478 | 333 | gtress | * task queue. Any applet can reorder tasks in the queue. Local copies of the queue in the applet are for
|
479 | * display purposes only, and are not authoritative when reordering tasks. All clients reorder tasks asynchronously,
|
||
480 | 527 | emarinel | * and as a result no guarantee is made that the correct tasks will actually be reordered.
|
481 | 333 | gtress | * If an invalid position is specified, the state of the queue is undefined and server failure may result.
|
482 | * Due to the asynchronous nature of the queue, we cannot easily account for concurrent
|
||
483 | * modification failures on the client side.
|
||
484 | *
|
||
485 | * @param pos1 The queue position of a task which we would like to reorder.
|
||
486 | * @param pos2 The queue position of a task which we would like to reorder.
|
||
487 | */
|
||
488 | 107 | gtress | public void sendQueueReorder (int pos1, int pos2) { |
489 | String packet = ""; |
||
490 | packet += ColonetServerInterface.QUEUE_REORDER; |
||
491 | packet += " " + pos1;
|
||
492 | packet += " " + pos2;
|
||
493 | packet += "\n";
|
||
494 | sendQueueInstruction(packet); |
||
495 | } |
||
496 | 32 | gtress | |
497 | 136 | gtress | public void sendQueueUpdate () { |
498 | sendQueueInstruction(ColonetServerInterface.QUEUE_UPDATE); |
||
499 | } |
||
500 | 527 | emarinel | |
501 | 32 | gtress | /**
|
502 | * Display informational message box on the screen. Used for casual communicaton to the user.
|
||
503 | * @param text Text to display
|
||
504 | */
|
||
505 | 35 | gtress | public void msg (String text) { |
506 | 470 | gtress | JOptionPane.showMessageDialog(colonet, text, "Colonet", JOptionPane.INFORMATION_MESSAGE); |
507 | 32 | gtress | } |
508 | 527 | emarinel | |
509 | 32 | gtress | /**
|
510 | * Display warning message box on the screen. Used for minor alerts or exceptions.
|
||
511 | * @param text Text to display
|
||
512 | */
|
||
513 | 35 | gtress | public void warn (String text) { |
514 | 470 | gtress | JOptionPane.showMessageDialog(colonet, text, "Colonet", JOptionPane.WARNING_MESSAGE); |
515 | 32 | gtress | } |
516 | 527 | emarinel | |
517 | 32 | gtress | /**
|
518 | * Display error message box on the screen. Used for major errors or exceptions in the program.
|
||
519 | * @param text Text to display
|
||
520 | */
|
||
521 | 35 | gtress | public void err (String text) { |
522 | 470 | gtress | JOptionPane.showMessageDialog(colonet, text, "Colonet", JOptionPane.ERROR_MESSAGE); |
523 | 32 | gtress | } |
524 | 527 | emarinel | |
525 | |||
526 | 76 | gtress | /*
|
527 | 539 | emarinel | * DataListener thread.
|
528 | 76 | gtress | *
|
529 | */
|
||
530 | class DataListener extends Thread { |
||
531 | 545 | gtress | final int DATALISTENER_DELAY = 122; |
532 | 527 | emarinel | |
533 | 76 | gtress | public DataListener () {
|
534 | super("Colonet DataListener"); |
||
535 | } |
||
536 | 527 | emarinel | |
537 | 76 | gtress | public void run () { |
538 | String line;
|
||
539 | 527 | emarinel | while (true) { |
540 | 76 | gtress | try {
|
541 | 420 | gtress | line = reader.readLine(); |
542 | 539 | emarinel | if (line == null) { |
543 | throw new IOException(); |
||
544 | } |
||
545 | 420 | gtress | parseData(line); |
546 | 76 | gtress | Thread.sleep(DATALISTENER_DELAY);
|
547 | } catch (InterruptedException e) { |
||
548 | return;
|
||
549 | 420 | gtress | } catch (IOException e) { |
550 | 539 | emarinel | disconnect(); |
551 | return;
|
||
552 | 420 | gtress | } |
553 | 76 | gtress | } |
554 | } |
||
555 | 527 | emarinel | |
556 | 76 | gtress | public void parseData (String line) { |
557 | 333 | gtress | // Sensor Matrix
|
558 | 136 | gtress | if (line.startsWith(ColonetServerInterface.RESPONSE_TO_CLIENT_REQUEST + " " + |
559 | ColonetServerInterface.REQUEST_BOM_MATRIX)) |
||
560 | colonet.parseMatrix(line); |
||
561 | 270 | gtress | // Task Queue
|
562 | 155 | gtress | else if (line.startsWith(ColonetServerInterface.COLONET_QUEUE)) |
563 | 136 | gtress | colonet.parseQueue(line); |
564 | 270 | gtress | // XBee IDs
|
565 | 155 | gtress | else if (line.startsWith(ColonetServerInterface.RESPONSE_TO_CLIENT_REQUEST + " " + |
566 | 136 | gtress | ColonetServerInterface.REQUEST_XBEE_IDS)) |
567 | colonet.parseXBeeIDs(line); |
||
568 | 270 | gtress | // Battery
|
569 | else if (line.startsWith(ColonetServerInterface.RESPONSE_TO_CLIENT_REQUEST + " " + |
||
570 | ColonetServerInterface.BATTERY)) |
||
571 | colonet.parseBattery(line); |
||
572 | 459 | gtress | // Robot Positions
|
573 | else if (line.startsWith(ColonetServerInterface.RESPONSE_TO_CLIENT_REQUEST + " " + |
||
574 | ColonetServerInterface.CLIENT_REQUEST_ROBOT_POSITIONS)) |
||
575 | colonet.parsePositions(line); |
||
576 | 682 | gtress | else if (line.startsWith(ColonetServerInterface.ROBOT_REPORT_ARRIVED_AT_POSITION)) |
577 | colonet.parseMoveUpdate(line); |
||
578 | 333 | gtress | // Unknown type
|
579 | 510 | gtress | else {
|
580 | 567 | gtress | System.out.println("Got unknown data: " + line + "\n"); |
581 | 510 | gtress | } |
582 | 76 | gtress | } |
583 | } |
||
584 | 420 | gtress | } |