diff options
| author | Ido Hadanny <ido.hadanny@gmail.com> | 2011-09-22 21:30:13 +0300 |
|---|---|---|
| committer | Ido Hadanny <ido.hadanny@gmail.com> | 2011-09-22 21:30:13 +0300 |
| commit | 53b947df484159f5934898ba6c0aa69a9c869007 (patch) | |
| tree | 189d5903a67765c390de8f1e3423e6b80cde57d1 /roombacomm-client/src/com/hackingroomba/roombacomm/RoombaCommTCPClient.java | |
| parent | 654ca6d59e99b5e72b05dfb917bc5888c4ba6b1b (diff) | |
added stuff
Diffstat (limited to 'roombacomm-client/src/com/hackingroomba/roombacomm/RoombaCommTCPClient.java')
| -rw-r--r-- | roombacomm-client/src/com/hackingroomba/roombacomm/RoombaCommTCPClient.java | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/roombacomm-client/src/com/hackingroomba/roombacomm/RoombaCommTCPClient.java b/roombacomm-client/src/com/hackingroomba/roombacomm/RoombaCommTCPClient.java new file mode 100644 index 0000000..34c16cf --- /dev/null +++ b/roombacomm-client/src/com/hackingroomba/roombacomm/RoombaCommTCPClient.java @@ -0,0 +1,451 @@ +/* + * RoombaComm TCP Interface + * + * + * Copyright (c) 2005 Tod E. Kurt, tod@todbot.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ + + +package com.hackingroomba.roombacomm; + + +import java.net.*; +import java.io.*; + +import com.hackingroomba.roombacomm.*; +/* + * SVN id value is $Id: RoombaCommTCPClient.java 182 2010-11-02 03:49:10Z bouchier $ + */ +public class RoombaCommTCPClient extends RoombaComm implements Runnable +{ + String host = null; + int port = -1; + + Socket socket; + InputStream input; + OutputStream output; + + Thread thread; + private byte buffer[] = new byte[32768]; + int bufferIndex; + int bufferLast; + + + // constructor + public RoombaCommTCPClient() { + super(); + } + + public RoombaCommTCPClient(RobotConnection rc) + { + super(rc); + } + + public boolean connect(String portid) { + String s[] = portid.split(":"); + if( s.length < 2 ) { + logmsg("bad portid "+portid); + return false; + }else{ + logmsg("portid is ("+portid+")"); + port=0; + host = s[0]; + if (host != null){ + logmsg("Host is ("+host+")"); + }else{ + logmsg("Host is (null)"); + return false; + } + try { + port = Integer.parseInt(s[1]); + } catch( Exception e ) { + logmsg("bad port "+e); + return false; + } + logmsg("connecting to '"+host+":"+port+"'"); + try { + socket = new Socket(host, port); + socket.setKeepAlive(true); + socket.setSoTimeout(30000);// timeout in milliseconds - 30 sec + input = socket.getInputStream(); + output = socket.getOutputStream(); + thread = new Thread(this); + thread.start(); + //this.setConnected(this.updateSensors()); // test if we are connected or not + this.setConnected(true); // TODO: fix this properly + } catch( Exception e ) { + logmsg("connect: "+e); //e.printStackTrace(); + return false; + } + } + return true; + } + + public void disconnect() { + try { + // do io streams need to be closed first? + if (input != null) input.close(); + if (output != null) output.close(); + this.setConnected(false); + } catch (Exception e) { + System.out.print("exception in disconnect"); + e.printStackTrace(); + } + thread = null; + input = null; + output = null; + + try { + if (socket != null) socket.close(); + } catch (Exception e) { + e.printStackTrace(); + } + socket = null; + } + + public boolean send(byte[] bytes) { + // use robotConnection if it exists, else do it the old way + if (robotConnection != null) { + return(robotConnection.send(bytes)); + } + + try { + //logmsg("Send_byte( "+bytes+")"); + output.write(bytes); + output.flush(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + public boolean send(int b) { // will also cover char + // use robotConnection if it exists, else do it the old way + if (robotConnection != null) { + return(robotConnection.send(b)); + } + + try { + //logmsg("Send_( "+b+" & 0xff)"); + output.write(b & 0xff); // for good measure do the & + output.flush(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return false; + } + + public void wakeup() { + logmsg("wakup unimplemented"); + } + + public boolean updateSensorsOLD() { + sensorsValid = false; + for(int i=0; i < 20; i++) { + sensors(); + if( sensorsValid ) { + if ((buffer[1] > 1) || (buffer[1] < 0)) { + sensorsValid = false; + logmsg("updateSensors: received invalid data while attempting to read Roomba sensors!"); + } else { + logmsg("updateSensors: sensorsValid!"); + } + break; + } + logmsg("updateSensors: pausing..."); + pause( 50 ); + } + return sensorsValid; + } + + // copied from RoombaCommSerial + public void computeSensors() { + sensorsValid = true; + sensorsLastUpdateTime = System.currentTimeMillis(); + computeSafetyFault(); + } + + public String[] listPorts() { + String s[] = new String[0]; + if( host !=null && port !=-1 ) { + String p[] = { host+":"+port }; + return p; + } + return s; + } + + + ////////////////////////////////////////////////////////////////// + + /** + * + */ + public void run() { + bufferLast = 0; + while (Thread.currentThread() == thread) { + try { + while (input != null) { + buffer[bufferLast++] = (byte) input.read(); // this will block - wait until there's something + //logmsg("TCP received sensor data: " + buffer[bufferLast-1]); + if( bufferLast == readRequestLength ) { + bufferLast = 0; + System.arraycopy(buffer, 0, sensor_bytes, 0, 26); + sensorsValid = true; + //computeSensors(); + } + +// synchronized (getBuffer()) { +// if (bufferLast == getBuffer().length) { +// byte temp[] = new byte[bufferLast << 1]; +// System.arraycopy(getBuffer(), 0, temp, 0, bufferLast); +// setBuffer(temp); +// } +// getBuffer()[bufferLast++] = (byte) input.read(); +// } + } + +// try { +// // uhh.. not sure what's best here.. since blocking, +// // do we need to worry about sleeping much? or is this +// // gonna try to slurp cpu away from the main applet? +// Thread.sleep(10); +// } catch (InterruptedException ex) { } + + } catch (IOException e) { + System.err.println("run:"+e); + } + } + } + + /** + * Returns the number of bytes that have been read from serial + * and are waiting to be dealt with by the user. + */ + public int available() { + return (bufferLast - bufferIndex); + } + + /** + * Ignore all the bytes read so far and empty the buffer. + */ + public void clear() { + bufferLast = 0; + bufferIndex = 0; + } + + /** + * Returns a number between 0 and 255 for the next byte that's + * waiting in the buffer. + * Returns -1 if there was no byte (although the user should + * first check available() to see if things are ready to avoid this) + */ + public int read() { + if (bufferIndex == bufferLast) return -1; + + synchronized (getBuffer()) { + int outgoing = getBuffer()[bufferIndex++] & 0xff; + if (bufferIndex == bufferLast) { // rewind + bufferIndex = 0; + bufferLast = 0; + } + return outgoing; + } + } + + + /** + * Returns the next byte in the buffer as a char. + * Returns -1, or 0xffff, if nothing is there. + */ + public char readChar() { + if (bufferIndex == bufferLast) return (char)(-1); + return (char) read(); + } + + + /** + * Return a byte array of anything that's in the serial buffer. + * Not particularly memory/speed efficient, because it creates + * a byte array on each read, but it's easier to use than + * readBytes(byte b[]) (see below). + */ + public byte[] readBytes() { + if (bufferIndex == bufferLast) return null; + + synchronized (getBuffer()) { + int length = bufferLast - bufferIndex; + byte outgoing[] = new byte[length]; + System.arraycopy(getBuffer(), bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + } + + /** + * Grab whatever is in the serial buffer, and stuff it into a + * byte buffer passed in by the user. This is more memory/time + * efficient than readBytes() returning a byte[] array. + * + * Returns an int for how many bytes were read. If more bytes + * are available than can fit into the byte array, only those + * that will fit are read. + */ + public int readBytes(byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + + synchronized (getBuffer()) { + int length = bufferLast - bufferIndex; + if (length > outgoing.length) length = outgoing.length; + System.arraycopy(getBuffer(), bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + } + + + /** + * Reads from the serial port into a buffer of bytes up to and + * including a particular character. If the character isn't in + * the serial buffer, then 'null' is returned. + */ + public byte[] readBytesUntil(int interesting) { + if (bufferIndex == bufferLast) return null; + byte what = (byte)interesting; + + synchronized (getBuffer()) { + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (getBuffer()[k] == what) { + found = k; + break; + } + } + if (found == -1) return null; + + int length = found - bufferIndex + 1; + byte outgoing[] = new byte[length]; + System.arraycopy(getBuffer(), bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + } + + + /** + * Reads from the serial port into a buffer of bytes until a + * particular character. If the character isn't in the serial + * buffer, then 'null' is returned. + * + * If outgoing[] is not big enough, then -1 is returned, + * and an error message is printed on the console. + * If nothing is in the buffer, zero is returned. + * If 'interesting' byte is not in the buffer, then 0 is returned. + */ + public int readBytesUntil(int interesting, byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + byte what = (byte)interesting; + + synchronized (getBuffer()) { + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (getBuffer()[k] == what) { + found = k; + break; + } + } + if (found == -1) return 0; + + int length = found - bufferIndex + 1; + if (length > outgoing.length) { + System.err.println("readBytesUntil() byte buffer is" + + " too small for the " + length + + " bytes up to and including char " + interesting); + return -1; + } + //byte outgoing[] = new byte[length]; + System.arraycopy(getBuffer(), bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + } + + + /** + * Return whatever has been read from the serial port so far + * as a String. It assumes that the incoming characters are ASCII. + * + * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public String readString() { + if (bufferIndex == bufferLast) return null; + return new String(readBytes()); + } + + + /** + * Combination of readBytesUntil and readString. See caveats in + * each function. Returns null if it still hasn't found what + * you're looking for. + * + * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public String readStringUntil(int interesting) { + byte b[] = readBytesUntil(interesting); + if (b == null) return null; + return new String(b); + } + + /** + * @param buffer the buffer to set + */ + public void setBuffer(byte buffer[]) { + this.buffer = buffer; + } + + /** + * @return the buffer + */ + public byte[] getBuffer() { + return buffer; + } + + +} + + |
