Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 104 additions & 22 deletions src/com/dynamicperception/nmxcommandline/main/NMXCommandLine.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.dynamicperception.nmxcommandline.main;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
Expand All @@ -15,15 +17,16 @@
import com.dynamicperception.nmxcommandline.helpers.Consts;
import com.dynamicperception.nmxcommandline.models.Command;
import com.dynamicperception.nmxcommandline.models.NMXComs;
import com.dynamicperception.nmxcommandline.models.Command.Names.General;

public class NMXCommandLine {

private static boolean execute;
private static Serial serial;
final static String DELIMITER = " ";
//private static long lastTime;
private static String version = "0.2-beta";
private static String version = "0.3-beta";

public static void main(String[] args) {
// Create serial object
serial = new Serial();
Expand All @@ -38,7 +41,7 @@ public static void main(String[] args) {
}

try{
serial.openPort(args[0]);
serial.openPort(Integer.parseInt(args[0]));
}catch(RuntimeException e){
Console.pln("Invalid port! Either you picked the wrong number or you have the wrong syntax.\n"
+ "A full one-time execution should look something like this: "
Expand All @@ -60,6 +63,27 @@ public static void main(String[] args) {
// Print help
printHelp();

/*
* Send an arbitrary command to clear initial connection hiccup. Also
* reroute system out to temporary file to avoid printing the error
* this will likely generate.
*/
try {
PrintStream oldOut = System.out;
File tempFile = new File("temp.txt");
tempFile.createNewFile();
PrintStream tempOut = new PrintStream(tempFile);
System.setOut(tempOut);
Command.execute(General.GET_FIRMWARE);
System.setOut(oldOut);
tempOut.close();
tempFile.delete();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


// Enter program loop
execute = true;
while(execute){
Expand All @@ -74,7 +98,7 @@ private static void printTerminalHelp(){
Console.pln("\nIn order to enter the interactive command line tool, run this JAR file without arguments.\n"
+ "Alternatively, you may run it with the following arguments to execute a single NMX command and then\n"
+ "immediately disconnect from the controller and close this application:\n\n"
+ "\"NMXCommander.jar <PORT NAME> <COMMAND TYPE>.<COMMAND NAME> <DATA or MOTOR # (if needed)> <MOTOR DATA (if needed)>\"\n\n"
+ "\"NMXCommander.jar [PORT NAME] [COMMAND TYPE].[COMMAND NAME] [DATA or MOTOR # (if required)] [MOTOR DATA (if required)]\"\n\n"
+ "If you're not familiar with the command types, names, data, etc., open the application in interactive\n"
+ "mode first and read the extended help there.");
}
Expand All @@ -86,16 +110,32 @@ private static void printHelp(){
Console.pln("\n\n******** NMX Commander " + version + " Overview ********\n\n"
+ "This command line tool allows you to manually send single instuctions to the NMX controller.\n"
+ "This is done by giving input with the following syntax:\n\n"
+ "Non-motor commands -- \"<COMMAND TYPE>.<COMMAND NAME> <DATA (if required)>\"\n"
+ "Motor commands -- \"m.<COMMAND NAME> <MOTOR #> <DATA (if required)>\"\n\n"
+ "Non-motor commands -- \"[COMMAND TYPE].[COMMAND NAME] [DATA (if required)]\"\n"
+ "Motor commands -- \"m.[COMMAND NAME] [MOTOR #] [DATA (if required)]\"\n\n"
+ "Non-motor command types include \"g\" (general), \"c\" (camera), and \"k\" (key frame)\n"
+ "When specifying the motor number for motor commands, counting starts at 0 (i.e. valid motor #s are 0, 1, 2)\n\n\n"
+ "******** NMX Commander Configuration Commands ********\n\n"
+ "* \"outputAddress [ADDR # optional argument]\" -- without optional parameter, reports the current command address. With the\n"
+ "optional parameter, sets the address to which the command will be sent. This is 3 by default and should not be changed unless\n"
+ "you have manually reassigned the address of one or more of your controllers. !!!Sending commands to an incorrect address will\n"
+ "cause you lots of headaches!!!\n\n"
+ "* \"commandDetail [0/1 optional argument]\" -- without optional parameter, reports whether commandDetail is enabled. With the\n"
+ "optional parameter, sets commandDetail enabled. If true, NMX Commander will print the command name and any additional data\n"
+ "output to the NMX\n\n"
+ "* \"serialDetail [0/1 optional argument]\" -- without optional parameter, reports whether serialDetail is enabled. With the\n"
+ "optional parameter, sets serialDetail enabled. If true, NMX Commander will print the raw packet received from the NMX for\n"
+ "each command\n\n\n"
+ "* \"responseTimout [TIMEOUT optional argument]\" -- without optional parameter, reports current response timeout in milliseconds\n"
+ "With optional parameter, sets timeout length. If you find that you encounter a situation where you are getting many timeouts that\n"
+ "are not causing problems (e.g. you don't care about the response contents, but the command seems to be executing properly), you\n"
+ "may want to shorten the timout in order to increase command throughput.\n\n\n"
+ "******** Other Useful Commands ********\n\n"
+ "* \"help\" -- prints this information again\n\n"
+ "* \"<COMMAND TYPE>.<COMMAND NAME> -h\" -- prints command-specific help\n\n"
+ "* \"list <COMMAND TYPE>\" -- lists all commands of that type\n\n"
+ "* \"find <COMMAND TYPE>.<SEARCH TERM>\" -- returns all commands of that type containing the search term\n\n"
+ "* \"runMacro <PATH>\" -- runs a command macro list from a text file. Type \"runMacro\" without arguments\n"
+ "* \"[COMMAND TYPE].[COMMAND NAME] -h\" -- prints command-specific help\n\n"
+ "* \"list [COMMAND TYPE]\" -- lists all commands of that type\n\n"
+ "* \"find [COMMAND TYPE].[SEARCH TERM]\" -- returns all commands of that type containing the search term\n\n"
+ "* \"repeat [N] [COMMAND TYPE].[COMMAND NAME]\" -- repeats the given command N times\n\n"
+ "* \"runMacro [PATH]\" -- runs a command macro list from a text file. Type \"runMacro\" without arguments\n"
+ "for macro file syntax\n\n"
+ "* \"exit\" -- closes the serial port and exits the application\n\n\n"
+ "******** Some Important Tips ********\n\n"
Expand All @@ -110,7 +150,7 @@ private static void printHelp(){
+ "BE CAREFUL ABOUT THIS! If you accidentally send your rig two or four times as far as you intended, you can break\n"
+ "your valueable equipment!\n\n"
+ "* If you try to send a motor to a position and it either does not move or does not go all the way to where you sent it,\n"
+ "try running the command \"m.resetLimits <MOTOR #>\" to clear any end limits that may be restricting movement.");
+ "try running the command \"m.resetLimits [MOTOR #]\" to clear any end limits that may be restricting movement.");
}

/**
Expand Down Expand Up @@ -175,14 +215,52 @@ else if(args.get(0).indexOf("//") != -1){
else if(args.get(0).equals("help")){
printHelp();
}
else if(args.get(0).equals("commandDetail")){
try{
boolean enabled = args.get(1).equals("0") ? false : true;
Command.setCommandDetail(enabled);
}catch(IndexOutOfBoundsException e){
System.out.println("Command detail enabled? : " + Command.getCommandDetail());
}
}
else if(args.get(0).equals("serialDetail")){
try{
boolean enabled = args.get(1).equals("0") ? false : true;
NMXComs.setSerialDetail(enabled);
}catch(IndexOutOfBoundsException e){
System.out.println("Serial detail enabled? : " + NMXComs.getSerialDetail());
}
}
else if(args.get(0).equals("outputAddress")){
try{
int addr = Integer.parseInt(args.get(1));
Command.setAddr(addr);
}catch(IndexOutOfBoundsException e){
System.out.println("Current command address: " + Command.getAddr());
}catch(NumberFormatException e){
System.out.println("Invalid address. Must be an integer.");
}

}
else if(args.get(0).equals("responseTimeout")){
try{
int timeout = Integer.parseInt(args.get(1));
NMXComs.setResponseTimeout(timeout);
}catch(IndexOutOfBoundsException e){
System.out.println("Current timout in milliseconds: " + NMXComs.getResponseTimeout());
}catch(NumberFormatException e){
System.out.println("Invalid address. Must be an integer.");
}

}
// Run command list from file
else if(args.get(0).equals("runMacro")){
try {
if(args.size() == 1){
Console.pln("\nrunMacro syntax -- \"runMacro <PATH>\"");
Console.pln("\nrunMacro syntax -- \"runMacro [PATH]\"");
Console.pln("Example -> \"runMacro c:\\NMXmacro.txt\"\n");
Console.pln("The text file should have one command on each line with the following syntax:\n\n"
+ "\"<DELAY TIME> <COMMAND TYPE>.<COMMAND NAME> <DATA or MOTOR # (if needed)> <MOTOR DATA (if needed)>\"\n\n"
+ "\"[DELAY TIME] [COMMAND TYPE].[COMMAND NAME] [DATA or MOTOR # (if required)] [MOTOR DATA (if required)]\"\n\n"
+ "The following example enables the camera, sets the focus time to 600ms, trigger time to 100ms, sets home\n"
+ "for each of the motors (e.g. sets current position to 0), immediately takes an exposure, commands the motors to\n"
+ "a new position, waits 5000ms, takes another exposure, waits 1000ms, commands the motors back to their original\n"
Expand Down Expand Up @@ -231,28 +309,32 @@ else if(args.get(0).equals("replayLog")){
// Help request
else if(args.get(0).toLowerCase().equals("list")){
if(args.size() < 2){
Console.pln("List syntax -- \"list <COMMAND TYPE>\"");
Console.pln("List syntax -- \"list [COMMAND TYPE]\"");
Console.pln("Example -> \"list c\" prints the list of valid camera commands");
return;
}
Command.printList(Command.getType(args.get(1)));
return;
}
// Repeat the following command n times. (e.g. "repeat 2 m.getMS 0")
else if(args.get(0).equals("repeat")){
int count = Integer.parseInt(args.get(1));
for(int i = 0; i < 2; i++){
args.remove(0);
else if(args.get(0).equals("repeat")){
try{
int count = Integer.parseInt(args.get(1));
for(int i = 0; i < 2; i++){
args.remove(0);
}
for(int i = 0; i < count; i++){
parseCommand(args);
}
}catch(IndexOutOfBoundsException | NumberFormatException e){
Console.pln("Invalid syntax. Try \"repeat [#] [command]\"");
}
for(int i = 0; i < count; i++){
parseCommand(args);
}
return;
}
// Find command name
else if(args.get(0).equals("find")){
if(args.size() < 2){
Console.pln("Find syntax -- \"find <COMMAND TYPE>.<SEARCH TERM>\"");
Console.pln("Find syntax -- \"find [COMMAND TYPE].[SEARCH TERM]\"");
Console.pln("Example -> \"find m.speed\" prints the following:");
List <String> exampleArgs = Arrays.asList("find", "m.speed");
findCommand(exampleArgs);
Expand Down
34 changes: 20 additions & 14 deletions src/com/dynamicperception/nmxcommandline/models/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class Command {
private final static int MOTOR_COUNT = 3;
private static int addr = 3;
private static int currentControllerNum = 0;
private static boolean debug = true;
private static boolean commandDetail = false;
private static List<Command> generalList = new ArrayList<Command>();
private static List<Command> motorList = new ArrayList<Command>();
private static List<Command> cameraList = new ArrayList<Command>();
Expand Down Expand Up @@ -157,10 +157,6 @@ else if(returnType == Boolean.class){
ret = (T) Void.class.cast(null);
}

// Print debug if necessary
if(debug){
System.out.println("Command: " + thisCommand.name);
}
if(ret != null)
System.out.println(ret);
else
Expand Down Expand Up @@ -966,14 +962,22 @@ public static Command get(Type type, int command){
throw new UnsupportedOperationException();
}

public static void setDebug(boolean debug){
Command.debug = debug;
public static void setCommandDetail(boolean enabled){
Command.commandDetail = enabled;
}

public static boolean getCommandDetail(){
return Command.commandDetail;
}

public static void setAddr(int addr){
Command.addr = addr;
}

public static int getAddr(){
return Command.addr;
}

public static int getControllerNum(){
return currentControllerNum;
}
Expand Down Expand Up @@ -1117,18 +1121,20 @@ private <T>T executeThis(int subAddr, String dataStr, boolean hasData){
data = (int) Math.round(Float.parseFloat(dataStr));
}
}

// Print debug if necessary
if(debug){
System.out.println("Command: " + this.name + " Input data: " + dataStr);
}

String commandPacket = "";

// Send the command to the NMX
if(hasData){
NMXComs.cmd(addr, subAddr, this.command, this.dataLength, data);
commandPacket = NMXComs.cmd(addr, subAddr, this.command, this.dataLength, data);
}
else{
NMXComs.cmd(addr, subAddr, this.command);
commandPacket = NMXComs.cmd(addr, subAddr, this.command);
}

// Print debug if necessary
if(commandDetail){
System.out.println("Command: " + commandPacket + " Output data: " + dataStr);
}

// Wait for the NMX to clear
Expand Down
Loading