Skip to content

Commit

Permalink
Reading incoming serial data, routing messages to drivers
Browse files Browse the repository at this point in the history
-removed bin/

Coordinator.java:
-added byteBuffer to hold incomming serial data
-added processMessage() to process incoming messages from remote modules and route commands to drivers
-added boolean connectionReady to indicate whether the local arduino link is ready to accept input
-disabled check for IO in main loop for testing

Driver.java:
-added getState() to get the state of the thread.

SerialConnection:
-changed visibility of more methods to package
-disabled printing of read char in serialEvent()
-disabling more debug messages since the code seems solid enough
  • Loading branch information
ciasaboark committed Jan 29, 2014
1 parent 357845b commit fd575fa
Show file tree
Hide file tree
Showing 14 changed files with 120 additions and 45 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Expand Up @@ -132,7 +132,7 @@ public void run() {
Log.d(moduleName, "flashing LED on pin " + i);
Coordinator.sendCommand(moduleName, String.valueOf(i));
try {
Thread.sleep(5000);
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Expand Down
@@ -1,4 +1,5 @@
package org.apparatus_templi;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
Expand All @@ -22,8 +23,8 @@
*/
public class Coordinator {


// private static incommingBuffer;
//TODO check that 1000 bytes enough
private static ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
private static ArrayList<String> remoteModules = new ArrayList<String>();
private static HashMap<String, Driver> loadedDrivers = new HashMap<String, Driver>();
private static int portNum;
Expand Down Expand Up @@ -52,6 +53,7 @@ public class Coordinator {
private static byte termByte = (byte)0x0A;

private static SerialConnection serialConnection;
private static boolean connectionReady = false;



Expand Down Expand Up @@ -105,15 +107,15 @@ private boolean serialDataAvailable() {
* @param command
*/
private static synchronized void sendCommandV0(String moduleName, String command) {
Log.d(TAG, "sending message as protocol 0");
// Log.d(TAG, "sending message as protocol 0");
boolean sendMessage = true;
byte[] bytes = {0b0};

String message = moduleName + ":" + command + "\n";
try {
bytes = message.getBytes("US-ASCII");
Log.d(TAG, "message in hex: '" + DatatypeConverter.printHexBinary(bytes) + "'");
Log.d(TAG, "message in ascii (trimmed): '" + new String(bytes).trim() + "'");
// Log.d(TAG, "message in hex: '" + DatatypeConverter.printHexBinary(bytes) + "'");
// Log.d(TAG, "message in ascii (trimmed): '" + new String(bytes).trim() + "'");
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "sendCommandV0() error converting message to ASCII, discarding");
sendMessage = false;
Expand Down Expand Up @@ -193,21 +195,76 @@ private static synchronized void sendCommandV1(String moduleName, String command
}
}

private static synchronized void processMessage(byte[] byteArray) {
//TODO check the protocol version based off the first byte
//Since we only support protocol version 0 right now we only need to
//+ convert this to a string using ASCII encoding
String inMessage = "";
try {
inMessage = new String(byteArray, "US-ASCII");
// Log.d(TAG, "processing incomming message: '" + inMessage + "'");
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "unable to format incomming message as ASCII text, discarding");
}


String destination;
String command;

//the local arduino will send "READY\n" after it is finished with
//+ its setup. Since this can sometimes become garbled (i.e. "REAREADY\N")
//+ we have to be a bit loose in how the message is matched.
if (inMessage.indexOf(";") == -1 && inMessage.trim().endsWith("READY")) {
//TODO
Log.d(TAG, "local arduino link is ready");
connectionReady = true;
} else if (inMessage.indexOf(":") != -1) {
destination = inMessage.substring(0, inMessage.indexOf(":"));
command = inMessage.substring(inMessage.indexOf(":") + 1, inMessage.length());
Log.d(TAG, "read incomming message to: '" + destination + "' contents: '" + command + "'");

if (destination.equals("DEBUG")) {
Log.d(TAG, "requested debug from remote module '" + command + "'");
} else {
//route the message to the appropriate driver
if (loadedDrivers.containsKey(destination)) {
Driver destDriver = loadedDrivers.get(destination);
if (destDriver.getState() != Thread.State.TERMINATED) {
Log.d(TAG, "passing message to driver");
destDriver.receiveCommand(command);
} else {
//TODO re-launch the driver passing in the command
Log.w(TAG, "could not route incomming message to driver because it is terminated");
}
} else {
Log.d(TAG, "incomming message could not be routed to a running driver");
}
}
} else {
//the incomming message does not match any known format
Log.w(TAG, "incomming message does not match any known formats");
}
}

/**
* Sends the given command to a specific remote module
* @param moduleName the unique name of the remote module
* @param command the command to send to the remote module
*/
static synchronized void sendCommand(String moduleName, String command) {
switch (protocolVersion) {
case 0:
sendCommandV0(moduleName, command);
break;
case 1:
sendCommandV1(moduleName, command);
break;
default:
Log.e(TAG, "unknown protocol version: " + (int)protocolVersion + ", discarding message");
if (connectionReady) {
switch (protocolVersion) {
case 0:
sendCommandV0(moduleName, command);
break;
case 1:
sendCommandV1(moduleName, command);
break;
default:
Log.e(TAG, "unknown protocol version: " + (int)protocolVersion + ", discarding message");
}
} else {
Log.w(TAG, "local arduino connection not yet ready, discarding message");
}
}

Expand Down Expand Up @@ -396,7 +453,7 @@ static synchronized void setIoReady(boolean state) {
ioReady = state;
}

public static void main(String argv[]) {
public static void main(String argv[]) throws InterruptedException {
//Using apache commons cli to parse the command line options
Options options = new Options();
options.addOption("help", false, "Display this help message.");
Expand Down Expand Up @@ -503,25 +560,39 @@ public static void main(String argv[]) {
//enter main loop
while (true) {
//wait for input or output to be ready
while (!ioReady) {
// while (!ioReady) {
// }

}

try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//check for incomming serial data
if (serialConnection.isDataAvailable()) {
//read a byte
int readInt = -1;
try {
readInt = serialConnection.readInputByte();
// Log.d(TAG, "read incomming byte: " + readInt);
} catch (IOException e) {
Log.e(TAG, "error reading from serial connection");
}

//if the buffer is not empty
if (readInt != -1) {
byte b = (byte)readInt;
// Log.d(TAG, "read byte: " + new String(new byte[]{b}));
//if this is a termination byte then we need to process the incomming message
if (b == 0x0A) {
processMessage(byteBuffer.toByteArray());
byteBuffer = new ByteArrayOutputStream();
} else {
byteBuffer.write(b);
}
} else {
Log.d(TAG, "no data to read");
}
}

ioReady = false;
Thread.yield();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread.sleep(100);
}


Expand Down
Expand Up @@ -25,5 +25,9 @@ String getModuleName() {
return this.name;
}

Thread.State getState() {
return Thread.currentThread().getState();
}


}
Expand Up @@ -9,11 +9,10 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Enumeration;
import java.util.LinkedHashSet;

import javax.xml.bind.DatatypeConverter;


public class SerialConnection implements SerialPortEventListener {
private static final String TAG = "SerialTest";
Expand Down Expand Up @@ -107,15 +106,15 @@ private void initialize(String preferredConnection) {
}
}

public boolean isConnected() {
boolean isConnected() {
return connected;
}

/**
* This should be called when you stop using the port.
* This will prevent port locking on platforms like Linux.
*/
public synchronized void close() {
synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
Expand All @@ -128,19 +127,20 @@ public synchronized void close() {
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
// String inputLine = bReader.readLine();
byte[] inputByte = new byte[1];
input.read(inputByte);
Log.d(TAG, "read hex value: " + DatatypeConverter.printHexBinary(inputByte));
Log.d(TAG, "Read char value: " + new String(inputByte));
// byte[] inputByte = new byte[1];
// input.read(inputByte);
// Log.d(TAG, "read hex value: " + DatatypeConverter.printHexBinary(inputByte));
// Log.d(TAG, "Read char value: " + new String(inputByte));

//notify the coordinator that incoming data is available
Coordinator.setIoReady(true);
} catch (Exception e) {
System.err.println(e.toString());
}
}
// Ignore all the other eventTypes, but you should consider the other ones.
}

public synchronized boolean isDataAvailable() {
synchronized boolean isDataAvailable() {
boolean available = false;
try {
if (input.available() > 0) {
Expand All @@ -152,15 +152,15 @@ public synchronized boolean isDataAvailable() {
return available;
}

public synchronized int readInputByte() throws IOException {
synchronized int readInputByte() throws IOException {
return input.read();
}



public synchronized void writeData(byte[] data) {
synchronized void writeData(byte[] data) {
try {
Log.d(TAG, "writing byte[] data to output");
// Log.d(TAG, "writing byte[] data to output");
output.write(data);
output.flush();
} catch (IOException e) {
Expand Down

0 comments on commit fd575fa

Please sign in to comment.