root / trunk / code / projects / colonet / ColonetGUI / SimpleColonet.java @ 13
History | View | Annotate | Download (16.6 KB)
1 |
|
---|---|
2 |
import java.awt.*; |
3 |
import java.awt.event.*; |
4 |
import java.applet.*; |
5 |
import javax.swing.*; |
6 |
import javax.swing.event.*; |
7 |
import java.net.*; |
8 |
import java.io.*; |
9 |
|
10 |
/**
|
11 |
* Colonet: The Colony Control Applet.
|
12 |
* This applet provides a graphical control mechanism for the robot colony designed
|
13 |
* for web deployment.
|
14 |
*
|
15 |
* @author Gregory Tress
|
16 |
* @version 0.1
|
17 |
*
|
18 |
*/
|
19 |
public class SimpleColonet extends JApplet implements ActionListener, KeyListener, ChangeListener |
20 |
{ |
21 |
|
22 |
/*
|
23 |
* Graphical Applet Elements
|
24 |
*/
|
25 |
|
26 |
ColonetServerInterface csi; |
27 |
DataListener datalistener; |
28 |
|
29 |
// panelTop contains stuff on top
|
30 |
JPanel panelTop;
|
31 |
JPanel panelConnect;
|
32 |
JTextField txtHost;
|
33 |
JTextField txtPort;
|
34 |
JButton btnConnect;
|
35 |
|
36 |
// panelMove contains directional buttons for controlling the robot
|
37 |
JPanel panelMove;
|
38 |
JButton btnF, btnB, btnL, btnR, btnActivate;
|
39 |
boolean isMoving;
|
40 |
|
41 |
// panelCommands contains
|
42 |
JPanel panelCommands;
|
43 |
JButton btnClearLog;
|
44 |
JButton btnBuzzerOn;
|
45 |
JButton btnBuzzerOff;
|
46 |
JButton btnRequestBattery;
|
47 |
JButton btnChangeOrbColor;
|
48 |
JButton btnGetSensorData;
|
49 |
JComboBox cmbRobotNumber;
|
50 |
String robotNumber;
|
51 |
|
52 |
JColorChooser chooser;
|
53 |
JPanel panelChooser;
|
54 |
|
55 |
JPanel panelBottom;
|
56 |
JTextArea log;
|
57 |
JScrollPane spLog;
|
58 |
|
59 |
JPanel panelWebcam;
|
60 |
WebcamLoader webcamLoader; |
61 |
boolean destroyed = false; |
62 |
|
63 |
/**
|
64 |
* Sets up user control elements.
|
65 |
* Specifies layout for all GUI elements,
|
66 |
* attaches all ActionListeners, KeyListeners, and ChangeListeners, and
|
67 |
* creates threads for loading webcam image and listening for incoming data.
|
68 |
*
|
69 |
*/
|
70 |
public void init () { |
71 |
Container content = getContentPane();
|
72 |
content.setLayout(new GridLayout(2,1)); |
73 |
|
74 |
txtHost = new JTextField(); |
75 |
txtPort = new JTextField(); |
76 |
btnConnect = new JButton("Connect"); |
77 |
panelConnect = new JPanel(); |
78 |
panelConnect.setLayout(new GridLayout(2,3)); |
79 |
panelConnect.add(new JLabel("Host")); |
80 |
panelConnect.add(new JLabel("Port")); |
81 |
panelConnect.add(new JLabel(" ")); |
82 |
panelConnect.add(txtHost); |
83 |
panelConnect.add(txtPort); |
84 |
panelConnect.add(btnConnect); |
85 |
panelConnect.setBorder(BorderFactory.createTitledBorder("Connection")); |
86 |
|
87 |
btnF = new JButton("Forward"); |
88 |
btnB = new JButton("Back"); |
89 |
btnL = new JButton("Left"); |
90 |
btnR = new JButton("Right"); |
91 |
btnActivate = new JButton("On/Stop"); |
92 |
panelMove = new JPanel(); |
93 |
panelMove.setLayout(new GridLayout(3,3)); |
94 |
panelMove.add(new JLabel("")); |
95 |
panelMove.add(btnF); |
96 |
panelMove.add(new JLabel("")); |
97 |
panelMove.add(btnL); |
98 |
panelMove.add(btnActivate); |
99 |
panelMove.add(btnR); |
100 |
panelMove.add(new JLabel("")); |
101 |
panelMove.add(btnB); |
102 |
panelMove.add(new JLabel("")); |
103 |
panelMove.setBorder(BorderFactory.createTitledBorder("Movement Control")); |
104 |
|
105 |
btnClearLog = new JButton("Clear Log"); |
106 |
btnBuzzerOn = new JButton("Buzzer On"); |
107 |
btnBuzzerOff = new JButton("Buzzer Off"); |
108 |
btnRequestBattery = new JButton("Request Battery"); |
109 |
btnChangeOrbColor = new JButton("Change Orb Color"); |
110 |
btnGetSensorData = new JButton("Get Sensor Data"); |
111 |
String [] robotList = {"All ", "0", "1", "2", "3", "4", "5"}; |
112 |
cmbRobotNumber = new JComboBox(robotList); |
113 |
panelCommands = new JPanel(); |
114 |
panelCommands.setLayout(new FlowLayout()); |
115 |
panelCommands.add(btnBuzzerOn); |
116 |
panelCommands.add(btnBuzzerOff); |
117 |
panelCommands.add(btnClearLog); |
118 |
panelCommands.add(btnRequestBattery); |
119 |
//panelCommands.add(btnChangeOrbColor);
|
120 |
panelCommands.add(btnGetSensorData); |
121 |
panelCommands.add(new JLabel("Robot # to control")); |
122 |
panelCommands.add(cmbRobotNumber); |
123 |
panelCommands.setBorder(BorderFactory.createTitledBorder("Commands")); |
124 |
|
125 |
chooser = new JColorChooser(); |
126 |
chooser.setPreviewPanel(new JPanel()); |
127 |
panelChooser = new JPanel(); |
128 |
panelChooser.setLayout(new BorderLayout()); |
129 |
panelChooser.add(chooser, BorderLayout.CENTER);
|
130 |
panelChooser.setBorder(BorderFactory.createTitledBorder("Orb")); |
131 |
|
132 |
panelTop = new JPanel(); |
133 |
panelTop.setLayout(new BorderLayout()); |
134 |
panelTop.add(panelConnect, BorderLayout.NORTH);
|
135 |
panelTop.add(panelMove, BorderLayout.WEST);
|
136 |
panelTop.add(panelCommands, BorderLayout.CENTER);
|
137 |
panelTop.add(panelChooser, BorderLayout.EAST);
|
138 |
|
139 |
log = new JTextArea(); |
140 |
spLog = new JScrollPane(log, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); |
141 |
spLog.setBorder(BorderFactory.createTitledBorder("Log")); |
142 |
log.setEditable(false);
|
143 |
|
144 |
panelWebcam = new JPanel(); |
145 |
panelWebcam.setBorder(BorderFactory.createTitledBorder("Webcam")); |
146 |
|
147 |
panelBottom = new JPanel(); |
148 |
panelBottom.setLayout(new GridLayout(1,2)); |
149 |
panelBottom.add(spLog); |
150 |
panelBottom.add(panelWebcam); |
151 |
|
152 |
content.add(panelTop); |
153 |
content.add(panelBottom); |
154 |
|
155 |
txtHost.setText("roboclub1.frc.ri.cmu.edu");
|
156 |
txtPort.setText("10123");
|
157 |
isMoving = false;
|
158 |
|
159 |
btnConnect.addActionListener(this);
|
160 |
btnClearLog.addActionListener(this);
|
161 |
btnBuzzerOn.addActionListener(this);
|
162 |
btnBuzzerOff.addActionListener(this);
|
163 |
btnRequestBattery.addActionListener(this);
|
164 |
btnChangeOrbColor.addActionListener(this);
|
165 |
btnGetSensorData.addActionListener(this);
|
166 |
|
167 |
btnActivate.addActionListener(this);
|
168 |
btnActivate.addKeyListener(this);
|
169 |
btnF.addActionListener(this);
|
170 |
btnF.addKeyListener(this);
|
171 |
btnB.addActionListener(this);
|
172 |
btnB.addKeyListener(this);
|
173 |
btnL.addActionListener(this);
|
174 |
btnL.addKeyListener(this);
|
175 |
btnR.addActionListener(this);
|
176 |
btnR.addKeyListener(this);
|
177 |
|
178 |
chooser.getSelectionModel().addChangeListener(this);
|
179 |
|
180 |
csi = new ColonetServerInterface(log);
|
181 |
webcamLoader = new WebcamLoader(this); |
182 |
datalistener = new DataListener(log);
|
183 |
} |
184 |
|
185 |
/**
|
186 |
* Attempt to shut down the applet cleanly.
|
187 |
* Clean up leftover tasks when destroyed,
|
188 |
* i.e., browser window is closed or appletviewer is stopped.
|
189 |
* This method attempts to pause the destruction of the applet for 1000ms.
|
190 |
* If successful, other threads will have the chance to receive the shutdown
|
191 |
* signal and stop. Otherwise catches an exception.
|
192 |
*/
|
193 |
public void destroy () |
194 |
{ |
195 |
try {
|
196 |
destroyed = true;
|
197 |
//Wait for a second to give other threads a chance to be interrupted and return.
|
198 |
//This may not be necessary but it seems to prevent some browser crashes.
|
199 |
Thread.sleep(1000); |
200 |
} catch (InterruptedException e) { |
201 |
err("Interrupted exception in destroy()");
|
202 |
} |
203 |
} |
204 |
|
205 |
public void actionPerformed (ActionEvent event) { |
206 |
Object source = event.getSource();
|
207 |
|
208 |
if (source == btnConnect)
|
209 |
{ |
210 |
csi.connect(txtHost.getText(), txtPort.getText()); |
211 |
webcamLoader.start(); |
212 |
datalistener.start(); |
213 |
} |
214 |
else if (source == btnClearLog) |
215 |
log.setText("");
|
216 |
else if (source == btnBuzzerOn) |
217 |
{ |
218 |
csi.sendData(ColonetServerInterface.BUZZER_SET_FREQ + " 254", ColonetServerInterface.GLOBAL_DEST);
|
219 |
} |
220 |
else if (source == btnBuzzerOff) |
221 |
{ |
222 |
csi.sendData(ColonetServerInterface.BUZZER_OFF, ColonetServerInterface.GLOBAL_DEST); |
223 |
} |
224 |
else if (source == btnRequestBattery) |
225 |
{ |
226 |
csi.sendRequest(ColonetServerInterface.BATTERY, ColonetServerInterface.GLOBAL_DEST); |
227 |
} |
228 |
else if (source == btnGetSensorData) |
229 |
{ |
230 |
SensorDataWindow sd = new SensorDataWindow(this); |
231 |
Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize(); |
232 |
sd.setBounds(screenDim.width/4, screenDim.height/4, screenDim.width/2, screenDim.height/2); |
233 |
sd.setVisible(true);
|
234 |
} |
235 |
else if (source == btnActivate) |
236 |
{ |
237 |
isMoving = false;
|
238 |
csi.sendData(ColonetServerInterface.MOTORS_INIT, ColonetServerInterface.GLOBAL_DEST); |
239 |
csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 0", ColonetServerInterface.GLOBAL_DEST);
|
240 |
csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 0", ColonetServerInterface.GLOBAL_DEST);
|
241 |
} |
242 |
else if (source == btnF) |
243 |
{ |
244 |
isMoving = true;
|
245 |
csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 200", ColonetServerInterface.GLOBAL_DEST);
|
246 |
csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 200", ColonetServerInterface.GLOBAL_DEST);
|
247 |
} |
248 |
else if (source == btnB) |
249 |
{ |
250 |
isMoving = true;
|
251 |
csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 200", ColonetServerInterface.GLOBAL_DEST);
|
252 |
csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 200", ColonetServerInterface.GLOBAL_DEST);
|
253 |
} |
254 |
else if (source == btnL) |
255 |
{ |
256 |
isMoving = true;
|
257 |
csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 200", ColonetServerInterface.GLOBAL_DEST);
|
258 |
csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 200", ColonetServerInterface.GLOBAL_DEST);
|
259 |
} |
260 |
else if (source == btnR) |
261 |
{ |
262 |
isMoving = true;
|
263 |
csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 200", ColonetServerInterface.GLOBAL_DEST);
|
264 |
csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 200", ColonetServerInterface.GLOBAL_DEST);
|
265 |
} |
266 |
|
267 |
} |
268 |
|
269 |
public void stateChanged (ChangeEvent e) |
270 |
{ |
271 |
//Update the orb color
|
272 |
int red = chooser.getColor().getRed();
|
273 |
int green = chooser.getColor().getGreen();
|
274 |
int blue = chooser.getColor().getBlue();
|
275 |
csi.sendData(ColonetServerInterface.ORB_SET + " " + red + " " + green + " " + blue, ColonetServerInterface.GLOBAL_DEST); |
276 |
} |
277 |
|
278 |
|
279 |
/**
|
280 |
* Display informational message box on the screen. Used for casual communicaton to the user.
|
281 |
* @param text Text to display
|
282 |
*/
|
283 |
private void msg (String text) { |
284 |
JOptionPane.showMessageDialog(null, text, "Colonet", JOptionPane.INFORMATION_MESSAGE); |
285 |
} |
286 |
|
287 |
/**
|
288 |
* Display warning message box on the screen. Used for minor alerts or exceptions.
|
289 |
* @param text Text to display
|
290 |
*/
|
291 |
private void warn (String text) { |
292 |
JOptionPane.showMessageDialog(null, text, "Colonet", JOptionPane.WARNING_MESSAGE); |
293 |
} |
294 |
|
295 |
/**
|
296 |
* Display error message box on the screen. Used for major errors or exceptions in the program.
|
297 |
* @param text Text to display
|
298 |
*/
|
299 |
private void err (String text) { |
300 |
JOptionPane.showMessageDialog(null, text, "Colonet", JOptionPane.ERROR_MESSAGE); |
301 |
} |
302 |
|
303 |
public void keyPressed (KeyEvent e) { |
304 |
if (isMoving) return; |
305 |
try {
|
306 |
if (e.getKeyCode() == KeyEvent.VK_UP) { |
307 |
log.append("Key: Up\n");
|
308 |
isMoving = true;
|
309 |
|
310 |
csi.sendData(ColonetServerInterface.MOVE_AVOID + " 200 0 0", ColonetServerInterface.GLOBAL_DEST);
|
311 |
|
312 |
//sendData(MOTOR1_SET + " 1 200");
|
313 |
//sendData(MOTOR2_SET + " 1 200");
|
314 |
} |
315 |
else if (e.getKeyCode() == KeyEvent.VK_DOWN) { |
316 |
log.append("Key: Down\n");
|
317 |
isMoving = true;
|
318 |
csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 200", ColonetServerInterface.GLOBAL_DEST);
|
319 |
csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 200", ColonetServerInterface.GLOBAL_DEST);
|
320 |
} |
321 |
else if (e.getKeyCode() == KeyEvent.VK_LEFT) { |
322 |
log.append("Key: Left\n");
|
323 |
isMoving = true;
|
324 |
csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 200", ColonetServerInterface.GLOBAL_DEST);
|
325 |
csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 200", ColonetServerInterface.GLOBAL_DEST);
|
326 |
} |
327 |
else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { |
328 |
log.append("Key: Right\n");
|
329 |
isMoving = true;
|
330 |
csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 200", ColonetServerInterface.GLOBAL_DEST);
|
331 |
csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 200", ColonetServerInterface.GLOBAL_DEST);
|
332 |
} |
333 |
|
334 |
} catch (Exception ex) { |
335 |
log.append("Error sending command.\n");
|
336 |
} |
337 |
} |
338 |
|
339 |
public void keyReleased (KeyEvent e) { |
340 |
if (!isMoving) return; |
341 |
// if we are no longer pressing a direction key, stop the robot
|
342 |
if (e.getKeyCode() == KeyEvent.VK_UP || |
343 |
e.getKeyCode() == KeyEvent.VK_DOWN ||
|
344 |
e.getKeyCode() == KeyEvent.VK_LEFT ||
|
345 |
e.getKeyCode() == KeyEvent.VK_RIGHT)
|
346 |
log.append("Stopping robot\n");
|
347 |
isMoving = false;
|
348 |
csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 0", ColonetServerInterface.GLOBAL_DEST);
|
349 |
csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 0", ColonetServerInterface.GLOBAL_DEST);
|
350 |
} |
351 |
public void keyTyped (KeyEvent e) { |
352 |
|
353 |
} |
354 |
|
355 |
/**
|
356 |
* Listens for incoming data from the colonet server.
|
357 |
* This includes responses to requests for robot data.
|
358 |
*/
|
359 |
class DataListener extends Thread |
360 |
{ |
361 |
|
362 |
JTextArea log;
|
363 |
BufferedReader reader;
|
364 |
|
365 |
/**
|
366 |
* Create a new DataListener that listens for incoming data on the specified socket.
|
367 |
* @param log TextArea to which incoming messages should be printed.
|
368 |
* @param socket Socket on which to listen for data.
|
369 |
*/
|
370 |
public DataListener (JTextArea log) |
371 |
{ |
372 |
super("Colonet DataListener"); |
373 |
this.log = log;
|
374 |
} |
375 |
|
376 |
public void run () |
377 |
{ |
378 |
String line;
|
379 |
log.append("Started listener for responses\n");
|
380 |
while (!destroyed)
|
381 |
{ |
382 |
try {
|
383 |
if (csi.isReady())
|
384 |
{ |
385 |
line = csi.getBufferedReader().readLine(); |
386 |
if (line != null) log.append("Message from server: " + line + "\n"); |
387 |
} |
388 |
Thread.sleep(500); |
389 |
} catch (Exception e) { |
390 |
warn("Error: " + e);
|
391 |
} |
392 |
} |
393 |
} |
394 |
|
395 |
} |
396 |
|
397 |
|
398 |
class WebcamLoader extends Thread |
399 |
{ |
400 |
|
401 |
URL path;
|
402 |
Image image;
|
403 |
MediaTracker mt;
|
404 |
int BUFFER = 16; // this is arbitrary. it makes the image look nice. |
405 |
|
406 |
public WebcamLoader (JApplet applet) |
407 |
{ |
408 |
super("Colonet WebcamLoader"); |
409 |
try {
|
410 |
path = new URL("http://roboclub1.frc.ri.cmu.edu/ColonetGUI/webcam/colonet.jpg"); |
411 |
} catch (MalformedURLException e) { |
412 |
err("MalformedURLException.\nCannot load webcam image.");
|
413 |
} |
414 |
mt = new MediaTracker(applet); |
415 |
} |
416 |
|
417 |
public void run () |
418 |
{ |
419 |
while (!destroyed) {
|
420 |
try {
|
421 |
Thread.sleep(1000); |
422 |
if (destroyed) return; |
423 |
if (image != null) image.flush(); |
424 |
image = getImage(path); |
425 |
mt.addImage(image, 1);
|
426 |
mt.waitForID(1);
|
427 |
panelWebcam.getGraphics().drawImage(image, |
428 |
BUFFER, //dx1 - the x coordinate of the first corner of the destination rectangle.
|
429 |
BUFFER, //dy1 - the y coordinate of the first corner of the destination rectangle.
|
430 |
panelWebcam.getWidth() - BUFFER, //dx2 - the x coordinate of the second corner of the destination rectangle.
|
431 |
panelWebcam.getHeight() - BUFFER, //dy2 - the y coordinate of the second corner of the destination rectangle.
|
432 |
0, //sx1 - the x coordinate of the first corner of the source rectangle. |
433 |
0, //sy1 - the y coordinate of the first corner of the source rectangle. |
434 |
image.getWidth(null), //sx2 - the x coordinate of the second corner of the source rectangle. |
435 |
image.getHeight(null), //sy2 - the y coordinate of the second corner of the source rectangle. |
436 |
null //observer - object to be notified as more of the image is scaled and converted. |
437 |
); |
438 |
|
439 |
} catch (InterruptedException e) { |
440 |
//Closing the browser window will probably couse an InterruptedException.
|
441 |
//I can't think of anything else to do than let it happen and then return.
|
442 |
return;
|
443 |
} catch (java.security.AccessControlException e) {
|
444 |
warn("java.security.AccessControlException in WebcamLoader.\n" +
|
445 |
"The image cannot be loaded from the specified location.\n" +
|
446 |
"Make sure you are accessing this applet from the correct server.");
|
447 |
destroyed = true;
|
448 |
} |
449 |
} |
450 |
} |
451 |
} |
452 |
|
453 |
class SensorDataWindow extends JFrame implements ActionListener |
454 |
{ |
455 |
|
456 |
JApplet applet;
|
457 |
JTextArea log;
|
458 |
JScrollPane spLog;
|
459 |
JButton btnClose;
|
460 |
JPanel panelButtons;
|
461 |
SensorDataLoader sdl; |
462 |
|
463 |
public SensorDataWindow (JApplet applet) |
464 |
{ |
465 |
super("Sensor Data"); |
466 |
this.applet = applet;
|
467 |
|
468 |
log = new JTextArea(); |
469 |
log.setEditable(false);
|
470 |
spLog = new JScrollPane(log, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); |
471 |
spLog.setBorder(BorderFactory.createTitledBorder("Log")); |
472 |
|
473 |
Container content = this.getContentPane(); |
474 |
content.setLayout(new BorderLayout()); |
475 |
content.add(spLog, BorderLayout.CENTER);
|
476 |
|
477 |
btnClose = new JButton("Close Window"); |
478 |
btnClose.addActionListener(this);
|
479 |
panelButtons = new JPanel(); |
480 |
panelButtons.setLayout(new FlowLayout()); |
481 |
panelButtons.add(btnClose); |
482 |
content.add(panelButtons, BorderLayout.SOUTH);
|
483 |
|
484 |
//start thread to continuously update data
|
485 |
sdl = new SensorDataLoader(this, this.applet); |
486 |
sdl.start(); |
487 |
|
488 |
//if the window is closed,
|
489 |
//make sure we stop the thread.
|
490 |
this.addWindowListener(new SensorDataWindowListener()); |
491 |
|
492 |
} |
493 |
|
494 |
public void actionPerformed (ActionEvent event) |
495 |
{ |
496 |
Object source = event.getSource();
|
497 |
if (source == btnClose)
|
498 |
{ |
499 |
this.setVisible(false); |
500 |
sdl.stopMe(); |
501 |
} |
502 |
} |
503 |
|
504 |
class SensorDataWindowListener extends WindowAdapter |
505 |
{ |
506 |
public SensorDataWindowListener ()
|
507 |
{ |
508 |
super();
|
509 |
} |
510 |
public void windowClosing (WindowEvent e) |
511 |
{ |
512 |
sdl.stopMe(); |
513 |
} |
514 |
} |
515 |
|
516 |
} |
517 |
|
518 |
class SensorDataLoader extends Thread |
519 |
{ |
520 |
|
521 |
SensorDataWindow window; |
522 |
JApplet applet;
|
523 |
boolean running;
|
524 |
|
525 |
public SensorDataLoader (SensorDataWindow window, JApplet applet) |
526 |
{ |
527 |
this.window = window;
|
528 |
this.applet = applet;
|
529 |
} |
530 |
|
531 |
public void run () |
532 |
{ |
533 |
running = true;
|
534 |
log.append("Sensor data loading started.\n");
|
535 |
while (running)
|
536 |
{ |
537 |
try {
|
538 |
Thread.sleep(2000); |
539 |
} catch (InterruptedException e) { |
540 |
err("InterruptedException in SensorDataLoader\n" + e);
|
541 |
} |
542 |
log.append("<update data here ...>\n");
|
543 |
} |
544 |
log.append("Sensor data loading stopped.\n");
|
545 |
} |
546 |
|
547 |
public void stopMe () |
548 |
{ |
549 |
running = false;
|
550 |
} |
551 |
|
552 |
} |
553 |
|
554 |
} |