import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.applet.Applet;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.URL;
public class tbClient extends Applet implements WindowListener,
ActionListener, MouseListener, MouseMotionListener {
static boolean PrintLog=false;
public static void log(String line) {
if (PrintLog) System.out.println(line);
}
public static void main(String[] args) {
Frame F=new Frame("WebCam Monitor");
tbClient C=new tbClient();
F.setSize(750, 500);
F.addWindowListener(C);
F.add(C);
C.init();
C.PrintLog=true;
C.start();
F.setVisible(true);
}
// Client-server parameters
static final String imgLocDefault = "http://webbot.bradley.edu/cgi-bin/bot1cam.cgi";
// static final String imgLocDeafault = "http://localhost/cgi-bin/bot1cam.cgi";
String imgLoc = null;
static final int timSlMsDefault = 1000;
int timSlMs = 1000;
static final String srvLocDefault = "webbot.bradley.edu";
// static final String srvLocDefault = "localhost"; // enable only for testing
String srvLoc = null;
static final int srvPortDefault = 6811;
int srvPort = 6811;
// Robot control parameters
static final int timToutDefault = 10;
int timTout = 10;
static final int senMoveDefault = 25;
int senMove = 25;
// GUI
tbImage WC;
tbTextArea LOG;
Button bF0, bF1, bF2, bF3, bF4, bB1, bB2, bB3, bB4;
Button bR15, bR30, bR45, bL15, bL30, bL45;
Button stat;
Label lSens;
Scrollbar sSens;
// Connection
Socket SOCK=null;
PrintWriter SEND=null;
BufferedReader RECV=null;
boolean conn=false;
private void Connect() {
tbClient.log("START: connecting to WebBot server...");
try {
SOCK=new Socket(srvLoc, srvPort);
SEND=new PrintWriter(SOCK.getOutputStream());
RECV=new BufferedReader(new InputStreamReader(SOCK.getInputStream()));
conn=true;
tbClient.log("START: connected to WebBot server");
LOG.start();
} catch (Exception e) {
SOCK=null;
SEND=null;
RECV=null;
conn=false;
tbClient.log("ERROR: connecting to WebBot server failed - "+e.getMessage());
}
}
public void ReportConnectionLost() {
tbClient.log("LOG: connection loss reproted");
SOCK=null;
SEND=null;
RECV=null;
conn=false;
setEnabledControlPanel(false);
}
public void setEnabledControlPanel(boolean status) {
bF0.setEnabled(status);
bF4.setEnabled(status);
bF3.setEnabled(status);
bF2.setEnabled(status);
bF1.setEnabled(status);
bB4.setEnabled(status);
bB3.setEnabled(status);
bB2.setEnabled(status);
bB1.setEnabled(status);
bL15.setEnabled(status);
bL30.setEnabled(status);
bL45.setEnabled(status);
bR15.setEnabled(status);
bR30.setEnabled(status);
bR45.setEnabled(status);
if (status) {
tbClient.log("LOG: control panel activated");
stat.setLabel("status report");
} else {
tbClient.log("LOG: control panel deactivated");
stat.setLabel("regain control");
}
}
private Panel CreateControlPanel() {
Panel CP=new Panel();
CP.setLayout(new GridLayout(3,1, 10, 10));
// assuming that LOG is already created by start();
CP.add(LOG);
// create the direction buttons
// and direction button subpanel
bF0 =new Button("STOP");
bF4 =new Button("Forward 4");
bF3 =new Button("Forward 3");
bF2 =new Button("Forward 2");
bF1 =new Button("Forward 1");
bB4 =new Button("Back 4");
bB3 =new Button("Back 3");
bB2 =new Button("Back 2");
bB1 =new Button("Back 1");
bL45 =new Button("L 45");
bL30 =new Button("L 30");
bL15 =new Button("L 15");
bR45 =new Button("R 45");
bR30 =new Button("R 30");
bR15 =new Button("R 15");
bF0.addActionListener(this);
bF4.addActionListener(this);
bF3.addActionListener(this);
bF2.addActionListener(this);
bF1.addActionListener(this);
bB4.addActionListener(this);
bB3.addActionListener(this);
bB2.addActionListener(this);
bB1.addActionListener(this);
bL45.addActionListener(this);
bL30.addActionListener(this);
bL15.addActionListener(this);
bR45.addActionListener(this);
bR30.addActionListener(this);
bR15.addActionListener(this);
{
Panel PSEN=new Panel();
{
PSEN.setLayout(new GridLayout(2,1, 0,0));
}
Panel PBUT=new Panel();
PBUT.setLayout(new GridLayout(4,1, 5,5));
Panel PBR1=new Panel();
PBR1.setLayout(new GridLayout(1,3, 5,5));
Panel PBR2=new Panel();
PBR2.setLayout(new GridLayout(1,3, 5,5));
Panel PBR3=new Panel();
PBR3.setLayout(new GridLayout(1,3, 5,5));
//Row One
PBR1.add(bF1);
PBR1.add(bF2);
PBR1.add(bF3);
PBR1.add(bF4);
//Row Two
PBR2.add(bL45);
PBR2.add(bL30);
PBR2.add(bL15);
PBR2.add(bR15);
PBR2.add(bR30);
PBR2.add(bR45);
//Row Three
PBR3.add(bB1);
PBR3.add(bB2);
PBR3.add(bB3);
PBR3.add(bB4);
// ???
PBUT.add(PBR1);
PBUT.add(PBR2);
PBUT.add(PBR3);
PBUT.add(PSEN);
CP.add(PBUT);
}
{
Panel SWPAN=new Panel();
SWPAN.setLayout(new GridLayout(5,1, 5,5));
stat=new Button("report status");
stat.addActionListener(this);
SWPAN.add(stat);
SWPAN.add(new Label("WebBot v2.5 - BU ECE Department", Label.CENTER));
CP.add(SWPAN);
}
return(CP);
}
private String getParamOrDefault(String name, String def) {
String p=def;
try {
p=getParameter(name);
} catch (Exception e) {
p=def;
}
tbClient.log("PARAM: "+name+"="+p);
return(p);
}
private int getParamOrDefault(String name, int def) {
int p=def;
try {
p=Integer.parseInt(getParameter(name), 10);
} catch (Exception e) {
p=def;
}
tbClient.log("PARAM: "+name+"="+p);
return(p);
}
public void init() {
tbClient.log("INIT: getting applet parameters...");
PrintLog=(getParamOrDefault("client-debug","false").equals("true"));
imgLoc =getParamOrDefault("image-location", imgLocDefault);
timSlMs=getParamOrDefault("image-refresh", timSlMsDefault);
srvLoc =getParamOrDefault("server-location", srvLocDefault);
srvPort=getParamOrDefault("server-port", srvPortDefault);
timTout=getParamOrDefault("control-tout", timToutDefault);
senMove=getParamOrDefault("control-sens", senMoveDefault);
tbClient.log("INIT: starting all services...");
// Client command log text area
LOG=new tbTextArea(this);
// Transmitted image canvas
WC=new tbImage(imgLoc, timSlMs);
WC.addMouseListener(this);
// WC.addMouseMotionListener(this); not used for now
setLayout(new BorderLayout(20,20));
Label title=new Label("Telerobotics Project", Label.CENTER);
title.setFont(new Font("Helvetica", Font.BOLD, 24));
title.setForeground(new Color(0,0,128));
add("North", title);
add("East", new Label(""));
Panel CP=new Panel();
CP.setLayout(new BorderLayout(20,20));
CP.add("Center", WC);
CP.add("East", CreateControlPanel());
add("Center", CP);
add("South", new Label(""));
add("West", new Label(""));
setVisible(true);
tbClient.log("START: new GUI created");
}
public void start() {
tbClient.log("START: starting all services...");
setEnabledControlPanel(true);
WC.start();
Connect(); // also starts LOG
// enable controls only if connected!
setEnabledControlPanel(conn);
tbClient.log("START: all services started...");
LOG.append("# services started");
}
public void stop() {
tbClient.log("STOP: stopping all services...");
setEnabledControlPanel(false);
tbClient.log("STOP: stopping image acquisition...");
WC.stop();
tbClient.log("STOP: stopping command log...");
LOG.stop();
tbClient.log("STOP: disconnecting from WebBot server...");
conn=false;
try { SEND.close(); } catch (Exception e) { } SEND=null;
try { SOCK.close(); } catch (Exception e) { } SOCK=null;
try { RECV.close(); } catch (Exception e) { } RECV=null;
LOG.append("# services commenced");
try {
Thread.currentThread().sleep(100);
} catch (Exception e) { }
tbClient.log("STOP: applet should have been stopped by now");
}
private void SendCommand(String command) {
if (SOCK==null||SEND==null) return;
try {
SEND.println(command);
SEND.flush();
LOG.append("->"+command);
tbClient.log("COMMAND: "+command+" sent");
} catch (Exception e) {
tbClient.log("ERROR: "+command+" "+e.getMessage());
LOG.append("# connection to server lost");
ReportConnectionLost();
}
}
// INTERFACE ActionListener -------
public void actionPerformed(ActionEvent e) {
if (e.getSource()==bF0) {
SendCommand("botmove f 0");
}
else if (e.getSource()==bF4) {
SendCommand("botmove f 4");
}
else if (e.getSource()==bF3) {
SendCommand("botmove f 3");
}
else if (e.getSource()==bF2) {
SendCommand("botmove f 2");
}
else if (e.getSource()==bF1) {
SendCommand("botmove f 1");
}
else if (e.getSource()==bB4) {
SendCommand("botmove b 4");
}
else if (e.getSource()==bB3) {
SendCommand("botmove b 3");
}
else if (e.getSource()==bB2) {
SendCommand("botmove b 2");
}
else if (e.getSource()==bB1) {
SendCommand("botmove b 1");
}
else if (e.getSource()==bR45) {
SendCommand("botmove r 3");
}
else if (e.getSource()==bR30) {
SendCommand("botmove r 2");
}
else if (e.getSource()==bR15) {
SendCommand("botmove r 1");
}
else if (e.getSource()==bL45) {
SendCommand("botmove l 3");
}
else if (e.getSource()==bL30) {
SendCommand("botmove l 2");
}
else if (e.getSource()==bL15) {
SendCommand("botmove l 1");
}
else if (e.getSource()==stat) {
if (!conn) {
Connect();
// enable controls only if connected!
if (conn) setEnabledControlPanel(true);
}
SendCommand("botstat 0");
}
else {
tbClient.log("COMMAND: unknown!");
LOG.append("# unrecognized event");
}
}
// INTERFACE MouseListener --------
public void mouseClicked(MouseEvent e) {
final Rectangle r=WC.getBounds();
final int cx=e.getX();
final int cy=e.getY();
// senMove is within 0..100 range
final int sensitivity=20*senMove;
final int px= sensitivity*(cx-r.width/2 )/r.width;
final int py=-sensitivity*(cy-r.height/2)/r.height;
SendCommand("botmove "+py+" "+px);
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
// INTERFACE MouseMotionListener --
public void mouseMoved(MouseEvent e) {}
public void mouseDragged(MouseEvent e) {}
// INTERFACE AdjustmentListener -------
public void adjustmentValueChanged(AdjustmentEvent e) {
if (e.getSource()!=sSens) return;
senMove=e.getValue();
lSens.setText(senMove+"%");
}
// INTERFACE WindowListener -------
public void windowClosing(WindowEvent e) { stop(); System.exit(0); }
public void windowClosed(WindowEvent e) { }
public void windowOpened(WindowEvent e) { }
public void windowIconified(WindowEvent e) { WC.pause(); }
public void windowDeiconified(WindowEvent e) { WC.resume(); }
public void windowActivated(WindowEvent e) { }
public void windowDeactivated(WindowEvent e) { }
}
class tbImage extends Canvas implements Runnable {
// parameters
private String imgLoc;
private int tmSlMs;
// variables
private MediaTracker MT = null;
private Image webcam = null;
private Thread process = null;
private boolean pause = false;
tbImage(String loc, int wait) {
super();
imgLoc=loc;
tmSlMs=wait;
MT=new MediaTracker(this);
}
public void start() {
if (process!=null) return;
process=new Thread(this,"Image Update");
process.start();
tbClient.log("IMAGE: started...");
}
public void pause() {
tbClient.log("IMAGE: update paused...");
pause=true;
}
public void resume() {
tbClient.log("IMAGE: update resumed...");
pause=false;
}
public void stop() {
tbClient.log("IMAGE: thread stop requested");
if (process==null) return;
Thread tokill=process;
process=null;
tokill.interrupt();
try {
tokill.join(100);
} catch (Exception e) {
tbClient.log("IMAGE: thread cannot stop in 100ms");
}
}
public void run() {
while(Thread.currentThread()==process) {
if (pause) {
try {
Thread.currentThread().sleep(100);
} catch (Exception e) { }
} else {
try {
tbClient.log("IMAGE: downloading...");
// remove the previous image from cache
if (webcam!=null) webcam.flush();
// get a new image by location
webcam = getToolkit().getImage(new URL(imgLoc));
// wait for downloading the image
// -- extra time added to thread.sleep()
MT.addImage(webcam,0);
MT.waitForAll();
MT.removeImage(webcam,0);
tbClient.log("IMAGE: refreshing...");
} catch(Exception e) {
webcam=null;
tbClient.log("IMAGE: "+e.getMessage()+"!");
}
repaint();
try {
tbClient.log("IMAGE: sleeping...");
Thread.currentThread().sleep(tmSlMs);
} catch (Exception e) { }
}
}
tbClient.log("IMAGE: thread commenced");
}
public void paint(Graphics g) {
final Rectangle r=getBounds();
g.drawRect(1,1,r.width-2,r.height-2);
if (webcam!=null) {
int wi=webcam.getWidth(this);
int hi=webcam.getHeight(this);
int w1=(r.width -wi)/2;
int h1=(r.height-hi)/2;
int w2=w1+wi;
int h2=h1+hi;
g.clearRect(2, 2, r.width-3,h1-3);
g.clearRect(2, h1,w1-3,hi);
g.clearRect(w2,h1,w1-3,hi);
g.clearRect(2,h2+1,r.width-3,h1-3);
g.drawImage(webcam, w1, h1, this);
}
}
public void update(Graphics g) {
paint(g);
}
}
class tbTextArea extends TextArea implements Runnable {
private tbClient PARENT = null;
private Thread process = null; // not running yet
tbTextArea(tbClient parent) {
super("", 4, 10, TextArea.SCROLLBARS_VERTICAL_ONLY);
setEditable(false);
setFont(new Font("Times", Font.BOLD, 10));
PARENT=parent;
}
public void append(String line) {
super.append(line+"\n");
}
public void start() {
if (process!=null) return; // do not start if already running
process=new Thread(this,"Command Log");
process.start();
tbClient.log("LOG: thread started");
}
public void stop() {
tbClient.log("LOG: thread stop requested");
process=null;
}
public void run() {
try {
while (Thread.currentThread()==process) {
String line=(PARENT.RECV).readLine();
append(line);
//tbClient.log("LOG: "+line);
}
} catch (Exception e) {
append("* connection lost");
tbClient.log("LOG: connection lost - disabling controls");
}
process=null;
PARENT.ReportConnectionLost();
tbClient.log("LOG: thread commenced");
}
}
syntax highlighted by Code2HTML, v. 0.8.11