Skip to content

Instantly share code, notes, and snippets.

@quinkennedy
Created May 12, 2012 00:03
Show Gist options
  • Save quinkennedy/2663199 to your computer and use it in GitHub Desktop.
Save quinkennedy/2663199 to your computer and use it in GitHub Desktop.
Finds arduinos attached via USB and prints out their ID and serial port string
import java.lang.ProcessBuilder;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.io.BufferedReader;
import java.io.FileReader;
static class ArduinoConnector{
public static final String DEFAULT_ECS_MAP_FILENAME = "ECSMap.txt";
public static final String SERIAL_NUMBER = "Serial Number: ";
public static final String LOCATION = "Location ID: ";
public static String getSerialName(String a_sECSName, String a_sMapFilename) throws FileNotFoundException, IOException {
String sID = null;
BufferedReader reader = new BufferedReader(new FileReader(a_sMapFilename));
for(String line = reader.readLine(); line != null; line = reader.readLine()){
String[] pieces = split(line,';');
if (pieces.length == 2 && pieces[0].equals(a_sECSName)){
sID = pieces[1];
break;
}
}
//if it isn't in the map, return false (failed)
if (sID == null){
return null;
}
return GetSerialName(sID);
}
//thanks to https://github.com/davidvondle/Upload-And-Retrieve-Source/blob/master/GistUploader/src/template/tool/GistUploader.java
private static String GetSerialName(String a_sSerialNumber){
//assuming OSX
String getUsbArgs[] = new String[2];
getUsbArgs[0]="system_profiler";
getUsbArgs[1]="SPUSBDataType";
//this probably needs to be smarter and allow for zeros within the number, such as '303'
//also, it could be that we really only need to strip the first 4 or 5 digits from the number
//and then strip leading zeros off of that, instead of running this open-ended regex
String regex = "^0x0*([1-9a-f]*)0*";
Pattern p = Pattern.compile(regex);
Matcher m;
String serialIn;
try {
Process process = new ProcessBuilder(getUsbArgs).start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
String currSerial = null;
String currLocation = null;
boolean foundArduino=false;
int serialNumPosition, locationPosition;
while ( (line = br.readLine ()) != null) {
serialNumPosition = line.indexOf(SERIAL_NUMBER);
if (serialNumPosition >= 0) {
currSerial = line.substring(serialNumPosition + SERIAL_NUMBER.length());
if (!currSerial.equals(a_sSerialNumber)){
currSerial = null;
}
} else if (currSerial != null && (line.indexOf("Arduino") >= 0 || line.indexOf("FT232R") >= 0 || line.indexOf("Vendor ID: 0x20a0") >= 0)) { //Vendor ID: 0x20a0 is freetronics
foundArduino = true;
} else if (foundArduino && currSerial != null) {
locationPosition = line.indexOf(LOCATION);
if (locationPosition >= 0){
currLocation = line.substring(locationPosition + LOCATION.length());
m = p.matcher(currLocation);
if (m.groupCount() > 0 && m.find()){
return "/dev/tty.usbmodem"+m.group(1)+"1";
}
currSerial = null;
currLocation = null;
foundArduino = false;
}
}
}
}
catch(IOException e) {
System.out.println(e.getMessage());
}
return null;
}
}
import processing.serial.*;
import java.lang.ProcessBuilder;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
String SERIAL_NUMBER = "Serial Number: ";
String LOCATION = "Location ID: ";
Hashtable mapping = new Hashtable();
public void setup() {
size(200, 200);
noLoop();
importECSMap();
//Hashtable of Arduino IDs -> serial interface names
Hashtable serialNums = findSerialNumbers();
String currKey, currValue;
println("list of Arduino IDs that are not assigned ECS names:");
int i = 1;
for(Enumeration IDs = serialNums.keys(); IDs.hasMoreElements();){
currKey = (String)IDs.nextElement();
if (!mapping.containsKey(currKey)){
currValue = (String)serialNums.get(currKey);
println(i++ + ")\tID: " + currKey);
//println("\tserial port: " + currValue);
} else {
String ecsName = (String)mapping.get(currKey);
try {
println("\tserial port from ECS name: " + ArduinoConnector.getSerialName(ecsName,dataPath("ECSMap.txt")));
} catch (Exception e){
println(e.getMessage());
}
}
}
println();
//println((new Serial(this)).list());
println("done");
}
//Builds a Hashmap from a semi-colon separated file
//This is intended to build a Hashmap of ArduinoIDs -> ECS names
public void importECSMap(){
try{
BufferedReader reader = createReader("ECSMap.txt");
for(String line = reader.readLine(); line != null; line = reader.readLine()){
String[] pieces = split(line,';');
if (pieces.length == 2){
//map ids -> names
mapping.put(pieces[0],pieces[1]);
}
}
}catch(Exception e){
println(e.getMessage());
}
}
//thanks to https://github.com/davidvondle/Upload-And-Retrieve-Source/blob/master/GistUploader/src/template/tool/GistUploader.java
//Returns a Hashtable of Arduino IDs -> serial interface names
public Hashtable findSerialNumbers() {
//assuming OSX
String getUsbArgs[] = new String[2];
getUsbArgs[0]="system_profiler";
getUsbArgs[1]="SPUSBDataType";
Hashtable serialNums = new Hashtable();
//this probably needs to be smarter and allow for zeros within the number, such as '303'
//also, it could be that we really only need to strip the first 4 or 5 digits from the number
//and then strip leading zeros off of that, instead of running this open-ended regex
String regex = "^0x0*([1-9a-f]*)0*";
Pattern p = Pattern.compile(regex);
Matcher m;
String serialIn;
try {
Process process = new ProcessBuilder(getUsbArgs).start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
String currSerial = null;
String currLocation = null;
boolean foundArduino=false;
int serialNumPosition, locationPosition;
while ( (line = br.readLine ()) != null) {
println(line);
serialNumPosition = line.indexOf(SERIAL_NUMBER);
if (serialNumPosition >= 0) {
currSerial = line.substring(serialNumPosition + SERIAL_NUMBER.length());
} else if (line.indexOf("Arduino") >= 0 || line.indexOf("FT232R") >= 0 || line.indexOf("Vendor ID: 0x20a0") >= 0) { //Vendor ID: 0x20a0 is freetronics
foundArduino = true;
} else if (foundArduino && currSerial != null) {
locationPosition = line.indexOf(LOCATION);
if (locationPosition >= 0){
currLocation = line.substring(locationPosition + LOCATION.length());
m = p.matcher(currLocation);
if (m.groupCount() > 0 && m.find()){
serialIn = "/dev/tty.usbmodem"+m.group(1)+"1";
serialNums.put(currSerial, serialIn);
} else {
println("ERROR: ");
println(currSerial + " : " + currLocation);
}
currSerial = null;
currLocation = null;
foundArduino = false;
}
}
}
}
catch(IOException e) {
println(e.getMessage());
System.out.println(e.getMessage());
}
return serialNums;
}
74132343430351C0B1F1;ForestOutputKingKong
6413138323135170F0E1;HouseOutputLamp
import processing.serial.*;
Serial s;
void setup(){
String serialName = null;
try {
serialName = ArduinoConnector.getSerialName("MrMonkey",dataPath("ECSMap.txt"));
}catch(Exception e){}
if (serialName == null){
print("OH NO!");
} else {
s = new Serial(this, serialName, 9600);
}
}
@quinkennedy
Copy link
Author

You will want to make the following directory & file structure. ECSMap.txt is provided as an example of the format expected (semi-colon seperated, one entry per line)

ArduinoSniffer/

  • ArduinoSniffer.pde
  • data/
    • ECSMap.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment