From 53b947df484159f5934898ba6c0aa69a9c869007 Mon Sep 17 00:00:00 2001 From: Ido Hadanny Date: Thu, 22 Sep 2011 21:30:13 +0300 Subject: added stuff --- .../hackingroomba/roombacomm/RobotConnection.java | 364 +++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 roombacomm-client/src/com/hackingroomba/roombacomm/RobotConnection.java (limited to 'roombacomm-client/src/com/hackingroomba/roombacomm/RobotConnection.java') diff --git a/roombacomm-client/src/com/hackingroomba/roombacomm/RobotConnection.java b/roombacomm-client/src/com/hackingroomba/roombacomm/RobotConnection.java new file mode 100644 index 0000000..504d19a --- /dev/null +++ b/roombacomm-client/src/com/hackingroomba/roombacomm/RobotConnection.java @@ -0,0 +1,364 @@ +/* + * roombacomm.ArduinoClient -- test out the Arduino subsystem without robot motion + * + * Copyright (c) 2009 Paul Bouchier, bouchier@at@classicnet.net + * + * 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.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +public class RobotConnection implements Runnable { + private int waittime; + private String robotServer; + private int robotPortNum = 0; + private Socket socket; + public InputStream in; + public OutputStream out; + public enum ConnectionType {SERIAL, NET}; + private ConnectionType connectionType; + private int maxStringSize = 200; + byte[] readBytes = new byte[maxStringSize]; + byte[] readBytesBuf = new byte[maxStringSize]; + + // variables for the read thread + Thread thread; + private int readRequestLength = 0; + private int numBytesRead; + private boolean readComplete; + public enum ReadTerminator {LF, COUNT, NULL}; + private ReadTerminator readTerminator; + private int readTimeout = 1000; // 1000ms read timeout + + public RobotConnection(String robotServer, int preferredPortNum) { + connectionType = ConnectionType.NET; + robotPortNum = preferredPortNum; + this.robotServer = robotServer; + } + /** + * Initialize the connection with a server name and optional ':' delimited port number + * @param robotServer port name (if serial) or server IP. Server IP may have a trailing ":port" + */ + public RobotConnection(String robotServer) { + this.robotServer = robotServer; + } + + private void parseServerString(String robotServer) + { + // open a connection to robot (net or serial) + char portNameChar1 = robotServer.charAt(0); + if (portNameChar1 >= '0' && portNameChar1 <='9') { // portname begins with number, assume it's an IP + connectionType = ConnectionType.NET; + String s[] = robotServer.split(":"); + if (s.length == 2){ // if length = 1, leave robotServer alone - portNum was specified another way + this.robotServer = s[0]; + try { + robotPortNum = Integer.parseInt(s[1]); + } catch( Exception e ) { + robotPortNum = 0; + } + System.err.println("Using network server '" + this.robotServer + ":" + robotPortNum + "'" ); + } + + } else { + connectionType = ConnectionType.SERIAL; + this.robotServer = robotServer; // serial port name + System.out.println("Using serial port " + robotServer); + System.err.println("Error: Serial port not supported"); + } + } + + /** + * Create a network or serial connection and associated input & output streams. After creating + * the connection, the caller should get the input & output streams to use for reading & writing + * the connection. Alternatively, the caller can use the in and out objects. + */ + public boolean connect() + { + parseServerString(robotServer); // the server string can override the preferred port number & connectionType + if (connectionType == ConnectionType.NET) { + try { + if ((robotServer == null) || (robotPortNum == 0)) { + System.out.println("Error: server or port not set"); + return false; + } + // open a socket to the robot + socket = new Socket(robotServer, robotPortNum); + socket.setKeepAlive(true); + socket.setTcpNoDelay(true); + socket.setSoTimeout(0); + //socket.setSoTimeout(30000);// timeout in milliseconds - 30 sec + in = socket.getInputStream(); + out = socket.getOutputStream(); + + // hang a read thread on the socket + readComplete = true; // initialize the "go" variables + readRequestLength = 0; + thread = new Thread(this); + thread.setPriority(Thread.MAX_PRIORITY); + thread.start(); + } catch( Exception e ) { + System.out.println("connect: "+e); //e.printStackTrace(); + return false; + } + } else if (connectionType == ConnectionType.SERIAL) { + System.out.println("ERROR: SERIAL NOT IMPLEMENTED YET"); + return false; + } + return true; + } + + public void disconnect() { + try { + // do io streams need to be closed first? + if (in != null) in.close(); + if (out != null) out.close(); + } catch (Exception e) { + System.out.print("exception in disconnect"); + e.printStackTrace(); + } + in = null; + out = null; + + try { + if (socket != null) socket.close(); + } catch (Exception e) { + e.printStackTrace(); + } + socket = null; + } + public boolean send(int b) { // will also cover char + try { + //System.out.println("Send_( "+b+" & 0xff)"); + out.write(b & 0xff); // for good measure do the & + out.flush(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + public boolean send(byte[] bytes) { + try { + //logmsg("Send_byte( "+bytes+")"); + out.write(bytes); + out.flush(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + public boolean sendToArduino(int b) { // will also cover char + byte [] arduinoHeader = {'m', ' '}; // roomba commands to arduino are prefixed with m & end with LF + byte arduinoTrailer = '\r'; + + try { + //System.out.println("Send_( "+b+" & 0xff)"); + out.write(arduinoHeader); + out.write(b & 0xff); // for good measure do the & + out.write(arduinoTrailer); + out.flush(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + public boolean sendToArduino(byte[] bytes) { + byte [] arduinoHeader = {'m', ' '}; // roomba commands to arduino are prefixed with m & end with LF + byte arduinoTrailer = '\r'; + + try { + //logmsg("Send_byte( "+bytes+")"); + out.write(arduinoHeader); + out.write(bytes); + out.write(arduinoTrailer); + out.flush(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + public byte [] readBot(int count) throws Exception + { + byte [] returnData = new byte[count]; + readComplete = false; + readTerminator = ReadTerminator.COUNT; + readRequestLength = count; + + // wait max 1000ms for read to complete - most anything should be done by then + //System.out.println("Trying to read " + readRequestLength + " bytes"); + for (int i=0; i<200; i++) { + Thread.sleep(5); // wait 5ms for answer to come back + if (readComplete == true) + break; + } + if (readComplete) { + System.arraycopy(readBytes, 0, returnData, 0, numBytesRead); + return (returnData); + } else { + return (null); + } + } + + public void flushInput() + { + while(true) { + String junk; + System.out.print("Flushing... "); + try { + junk = readBotToTerminator(ReadTerminator.LF); + if (junk != null) + System.out.println("Flushed: " + junk); + else + return; + } catch (Exception e) { + System.err.println("Exception while flushing" + e.getMessage()); + return; + } + } + } + + /** + * Read bytes from ArduinoBot up to \n, \r, or other terminator + * @return String read from robot + */ + public String readBotToTerminator(ReadTerminator terminator) throws Exception + { + readComplete = false; + readTerminator = terminator; + readRequestLength = maxStringSize; + numBytesRead = 0; + + // wait readTimout ms for read to complete - most anything should be done by then + Thread.sleep(10); + for (int i=0; i 0) { + readLength = in.read(buffer); // read & discard data following the terminator (handles extra \n) + //System.out.println("readByBlock discarded " + readLength + " bytes"); + } + Thread.sleep(5); + continue; + } + bytesLeftToRead = readRequestLength; + readBytes[0] = 0; // initialize data to empty string + //System.out.println("readByBlock starting to read"); + // ACHTUNG - buffer gets overwritten at the beginning by multiple read buffers + for (int i=0; i<5; i++) { + readLength = in.read(buffer, 0, (readRequestLength - bufferIndex)); // read as much as there is, even if its more than was requested + if ((readLength == -1) || (in == null)) { + System.out.println("Error in run: in.read() returned -1 or null; application exiting in 30s: " + readLength); + Thread.sleep(30000); + System.exit(-1);; + } + bytesLeftToRead -= readLength; + for (int j=0; j 0) && (((readTerminator == ReadTerminator.COUNT) && (bufferIndex >= readRequestLength)) || + ((readTerminator == ReadTerminator.LF) && (readBytes[bufferIndex-1] == '\n') && (bufferIndex > 1)) || // guard against a single \n from previous read causing premature termination + ((readTerminator == ReadTerminator.NULL) && (readBytes[bufferIndex-1] == '\0')) || + (bufferIndex == maxStringSize))) + { + numBytesRead = bufferIndex; + readRequestLength = 0; // flag this request as complete (so ditch all following data until next request + readComplete = true; + bufferIndex = 0; + //System.out.println("readByBlock completed read with bufferIndex: " + numBytesRead + " readLength: " + readLength); + break; + } else { + Thread.sleep(10); + if (bufferIndex > 0) { + //System.out.println("readByBlock has " + bufferIndex + ", trying again"); + } else { + System.out.print("."); + } + } + } + } catch (Exception e) { + System.out.println("Exception: readByBlock thread exiting" + e.getMessage()); + //e.printStackTrace(); + return; // causes thread to exit + } + //System.out.println("readByBlock read " + readLength + " bytes"); + } + } + + public InputStream getIn() { + return in; + } + public OutputStream getOut() { + return out; + } + public void setReadTimeout(int readTimeout) { + this.readTimeout = readTimeout; + } + +} \ No newline at end of file -- cgit v1.3.1