From 3b0e00d24e2161b94df8982e25c2e8df13ae161d Mon Sep 17 00:00:00 2001 From: Xander Date: Thu, 23 Mar 2017 12:38:58 -0400 Subject: [PATCH 1/3] Added New Options Added GetUID, DumpMFU, Identify, LButton_Long and RButton_Long. --- Software/Chameleon/Device.py | 76 ++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/Software/Chameleon/Device.py b/Software/Chameleon/Device.py index 57169c78..556e985b 100644 --- a/Software/Chameleon/Device.py +++ b/Software/Chameleon/Device.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 import serial import serial.tools.list_ports @@ -13,15 +13,20 @@ class Device: COMMAND_DOWNLOAD = "DOWNLOAD" COMMAND_SETTING = "SETTING" COMMAND_UID = "UID" + COMMAND_GETUID = "GETUID" + COMMAND_IDENTIFY = "IDENTIFY" + COMMAND_DUMPMFU = "DUMP_MFU" COMMAND_CONFIG = "CONFIG" COMMAND_LOG_DOWNLOAD = "LOGDOWNLOAD" COMMAND_LOG_CLEAR = "LOGCLEAR" COMMAND_LOGMODE = "LOGMODE" COMMAND_LBUTTON = "LBUTTON" + COMMAND_LBUTTONLONG = "LBUTTON_LONG" COMMAND_RBUTTON = "RBUTTON" + COMMAND_RBUTTONLONG = "RBUTTON_LONG" COMMAND_GREEN_LED = "LEDGREEN" COMMAND_RED_LED = "LEDRED" - + STATUS_CODE_OK = 100 STATUS_CODE_OK_WITH_TEXT = 101 STATUS_CODE_WAITING_FOR_XMODEM = 110 @@ -49,33 +54,32 @@ class Device: SUGGEST_CHAR = "?" SET_CHAR = "=" GET_CHAR = "?" - + def __init__(self, verboseFunc = None): self.verboseFunc = verboseFunc self.serial = serial.Serial(None, 9600, timeout=5.0) self.versionString = "" self.supportedConfs = [] - + def verboseLog(self, text): if (self.verboseFunc): self.verboseFunc(text) - + def listDevices(): devices = [] for port in serial.tools.list_ports.grep("({0:04x}:{1:04x})|({0:04X}:{1:04X})".format(Chameleon.USB_VID, Chameleon.USB_PID)): devices.append(port[0]) - return devices - - def connect(self, comport): + return devices + def connect(self, comport): self.serial.port = comport try: self.serial.open() except: pass - + if (self.serial.isOpen()): # Send escape key to force clearing the Chameleon's input buffer self.serial.write(b"\x1B") @@ -94,20 +98,20 @@ def connect(self, comport): return False result = self.getCmdSuggestions(self.COMMAND_CONFIG) - + if (result['statusCode'] == self.STATUS_CODE_OK_WITH_TEXT): self.supportedConfs = result['response'].split(",") else: return False else: return False - + return True - + def disconnect(self): self.verboseLog("Closing serial port") self.serial.close() - + def isConnected(self): return self.serial.isOpen() @@ -116,7 +120,7 @@ def read(self, size=1024, timeout=0.01): data = self.serial.read(size) self.serial.timeout = 5.0 return data - + def writeCmd(self, cmd): # Execute command cmdLine = cmd + self.LINE_ENDING @@ -130,19 +134,19 @@ def writeCmd(self, cmd): return None else: self.verboseLog("Executing <{}>: {}".format(cmd, status)) - + statusCode, statusText = status.split(":") statusCode = int(statusCode) - + result = {'statusCode': statusCode, 'statusText': statusText, 'response': None} - + if (statusCode == self.STATUS_CODE_OK_WITH_TEXT): result['response'] = self.readResponse() elif (statusCode == self.STATUS_CODE_TRUE): result['response'] = True elif (statusCode == self.STATUS_CODE_FALSE): result['response'] = False - + return result def readResponse(self): @@ -150,27 +154,30 @@ def readResponse(self): response = self.serial.readline().decode('ascii').rstrip() self.verboseLog("Response: {}".format(response)) return response - + def execCmd(self, cmd, args=None): if (args is None): return self.writeCmd("{}".format(cmd)) else: return self.writeCmd("{} {}".format(cmd, args)) - + def getSetCmd(self, cmd, arg=None): # Determine if set or get mode if (arg is None): return self.writeCmd("{}{}".format(cmd, self.GET_CHAR)) else: return self.writeCmd("{}{}{}".format(cmd, self.SET_CHAR, arg)) - + + def returnCmd(self, cmd, arg=None): + return self.writeCmd("{}".format(cmd)) + def getCmdSuggestions(self, cmd): result = self.getSetCmd(cmd, self.SUGGEST_CHAR) if (result['response'] is not None): result['suggestions'] = result['response'].split(",") return result - + def cmdUploadDump(self, dataStream): if (self.execCmd(self.COMMAND_UPLOAD)['statusCode'] == self.STATUS_CODE_WAITING_FOR_XMODEM): # XMODEM started @@ -201,7 +208,7 @@ def cmdClearLog(self): def cmdLogMode(self, newLogMode): return self.getSetCmd(self.COMMAND_LOGMODE, newLogMode) - + def cmdVersion(self): return self.getSetCmd(self.COMMAND_VERSION) @@ -211,6 +218,15 @@ def cmdSetting(self, newSetting = None): def cmdUID(self, newUID = None): return self.getSetCmd(self.COMMAND_UID, newUID) + def cmdGetUID(self): + return self.returnCmd(self.COMMAND_GETUID) + + def cmdIdentify(self): + return self.returnCmd(self.COMMAND_IDENTIFY) + + def cmdDumpMFU(self): + return self.returnCmd(self.COMMAND_DUMPMFU) + def cmdConfig(self, newConfig = None): if (newConfig == self.SUGGEST_CHAR): return self.getCmdSuggestions(self.COMMAND_CONFIG) @@ -223,18 +239,30 @@ def cmdLButton(self, newAction = None): else: return self.getSetCmd(self.COMMAND_LBUTTON, newAction) + def cmdLButtonLong(self, newAction = None): + if (newAction == self.SUGGEST_CHAR): + return self.getCmdSuggestions(self.COMMAND_LBUTTONLONG) + else: + return self.getSetCmd(self.COMMAND_LBUTTONLONG, newAction) + def cmdRButton(self, newAction = None): if (newAction == self.SUGGEST_CHAR): return self.getCmdSuggestions(self.COMMAND_RBUTTON) else: return self.getSetCmd(self.COMMAND_RBUTTON, newAction) + def cmdRButtonLong(self, newAction = None): + if (newAction == self.SUGGEST_CHAR): + return self.getCmdSuggestions(self.COMMAND_RBUTTONLONG) + else: + return self.getSetCmd(self.COMMAND_RBUTTONLONG, newAction) + def cmdGreenLED(self, newFunction = None): if (newFunction == self.SUGGEST_CHAR): return self.getCmdSuggestions(self.COMMAND_GREEN_LED) else: return self.getSetCmd(self.COMMAND_GREEN_LED, newFunction) - + def cmdRedLED(self, newFunction = None): if (newFunction == self.SUGGEST_CHAR): return self.getCmdSuggestions(self.COMMAND_RED_LED) From ce87f0a4ff3379d7bacf51cfcef18f28f54e74bb Mon Sep 17 00:00:00 2001 From: Xander Date: Thu, 23 Mar 2017 12:42:15 -0400 Subject: [PATCH 2/3] Added Options Added GetUID, DumpMFU, Identify, LButton_Long and RButton_Long. --- Software/chamtool.py | 83 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/Software/chamtool.py b/Software/chamtool.py index 6f97a966..afab4028 100755 --- a/Software/chamtool.py +++ b/Software/chamtool.py @@ -11,8 +11,8 @@ def verboseLog(text): formatString = "[{}] {}" timeString = datetime.datetime.utcnow() - print(formatString.format(timeString, text), file=sys.stderr) - + print(formatString.format(timeString, text), sys.stderr) + # Command funcs def cmdInfo(chameleon, arg): return "{}".format(chameleon.cmdVersion()['response']) @@ -27,11 +27,11 @@ def cmdSetting(chameleon, arg): return "Setting has been changed to {}".format(chameleon.cmdSetting()['response']) else: return "Change setting to {} failed: {}".format(arg, result['statusText']) - return - + return + def cmdUID(chameleon, arg): result = chameleon.cmdUID(arg) - + if (arg is None): return "{}".format(result['response']) else: @@ -40,8 +40,17 @@ def cmdUID(chameleon, arg): else: return "Setting UID to {} failed: {}".format(arg, result['statusText']) +def cmdGetUID(chameleon, arg): + return "{}".format(chameleon.cmdGetUID()['response']) + +def cmdIdentify(chameleon, arg): + return "{}".format(chameleon.cmdIdentify()['response']) + +def cmdDumpMFU(chameleon, arg): + return "{}".format(chameleon.cmdDumpMFU()['response']) + def cmdConfig(chameleon, arg): - result = chameleon.cmdConfig(arg) + result = chameleon.cmdConfig(chameleon, arg) if (arg is None): return "Current configuration: {}".format(result['response']) @@ -62,7 +71,7 @@ def cmdDownload(chameleon, arg): with open(arg, 'wb') as fileHandle: bytesReceived = chameleon.cmdDownloadDump(fileHandle) return "{} Bytes successfully written to {}".format(bytesReceived, arg) - + def cmdLog(chameleon, arg): with open(arg, 'wb') as fileHandle: bytesReceived = chameleon.cmdDownloadLog(fileHandle) @@ -70,7 +79,7 @@ def cmdLog(chameleon, arg): def cmdLButton(chameleon, arg): result = chameleon.cmdLButton(arg) - + if (arg is None): return "Current left button action: {}".format(result['response']) else: @@ -81,9 +90,22 @@ def cmdLButton(chameleon, arg): else: return "Setting left button action to {} failed: {}".format(arg, result['statusText']) +def cmdLButtonLong(chameleon, arg): + result = chameleon.cmdLButtonLong(arg) + + if (arg is None): + return "Current long press left button action: {}".format(result['response']) + else: + if (arg == chameleon.SUGGEST_CHAR): + return "Possible long press left button actions: {}".format(", ".join(result['suggestions'])) + elif (result['statusCode'] in chameleon.STATUS_CODES_SUCCESS): + return "Long press left button action has been set to {}".format(chameleon.cmdLButtonLong()['response']) + else: + return "Setting long press left button action to {} failed: {}".format(arg, result['statusText']) + def cmdRButton(chameleon, arg): result = chameleon.cmdRButton(arg) - + if (arg is None): return "Current right button action: {}".format(result['response']) else: @@ -94,9 +116,22 @@ def cmdRButton(chameleon, arg): else: return "Setting right button action to {} failed: {}".format(arg, result['statusText']) +def cmdRButtonLong(chameleon, arg): + result = chameleon.cmdRButtonLong(arg) + + if (arg is None): + return "Current long press right button action: {}".format(result['response']) + else: + if (arg == chameleon.SUGGEST_CHAR): + return "Possible long press right button actions: {}".format(", ".join(result['suggestions'])) + elif (result['statusCode'] in chameleon.STATUS_CODES_SUCCESS): + return "Long press right button action has been set to {}".format(chameleon.cmdRButtonLong()['response']) + else: + return "Setting long press right button action to {} failed: {}".format(arg, result['statusText']) + def cmdGreenLED(chameleon, arg): result = chameleon.cmdGreenLED(arg) - + if (arg is None): return "Current green LED function: {}".format(result['response']) else: @@ -109,7 +144,7 @@ def cmdGreenLED(chameleon, arg): def cmdRedLED(chameleon, arg): result = chameleon.cmdRedLED(arg) - + if (arg is None): return "Current red LED function: {}".format(result['response']) else: @@ -119,7 +154,7 @@ def cmdRedLED(chameleon, arg): return "Red LED function has been set to {}".format(chameleon.cmdRedLED()['response']) else: return "Setting red LED function to {} failed: {}".format(arg, result['statusText']) - + # Custom class for argparse class CmdListAction(argparse.Action): def __init__(self, option_strings, dest, default=False, required=False, @@ -127,19 +162,19 @@ def __init__(self, option_strings, dest, default=False, required=False, super(CmdListAction, self).__init__( option_strings=option_strings, dest=dest, nargs=nargs, const=const, default=default, required=required, help=help, metavar=metavar, type=type, choices=choices) - + def __call__(self, parser, namespace, values, option_string=None): # Create new attribute cmdList if not exist and append command to list if not hasattr(namespace, "cmdList"): setattr(namespace, "cmdList", []) - + namespace.cmdList.append([self.dest, values]) def main(): argParser = argparse.ArgumentParser(description="Controls the Chameleon through the command line") argParser.add_argument("-v", "--verbose", dest="verbose", action="store_true", default=0, help="output verbose") argParser.add_argument("-p", "--port", dest="port", metavar="COMPORT", help="specify device's comport") - + # Add the commands using custom action that populates a list in the order the arguments are given cmdArgGroup = argParser.add_argument_group(title="Chameleon commands", description="These arguments can appear multiple times and are executed in the order they are given on the command line. " "Some of these arguments can be used with '" + Chameleon.Device.SUGGEST_CHAR + "' as parameter to get a list of suggestions.") @@ -149,13 +184,18 @@ def main(): cmdArgGroup.add_argument("-i", "--info", dest="info", action=CmdListAction, nargs=0, help="retrieve the version information") cmdArgGroup.add_argument("-s", "--setting", dest="setting", action=CmdListAction, nargs='?', type=int, choices=Chameleon.VALID_SETTINGS, help="retrieve or set the current setting") cmdArgGroup.add_argument("-U", "--uid", dest="uid", action=CmdListAction, nargs='?', help="retrieve or set the current UID") + cmdArgGroup.add_argument("-gu", "--getuid", dest="getuid", action=CmdListAction, nargs='?', help="retrieve UID of device in range") + cmdArgGroup.add_argument("-I", "--identify", dest="identify", action=CmdListAction, nargs='?', help="identify device in range") + cmdArgGroup.add_argument("-D", "--dumpmfu", dest="dumpmfu", action=CmdListAction, nargs='?', help="dump information about card in range") cmdArgGroup.add_argument("-c", "--config", dest="config", action=CmdListAction, metavar="CFGNAME", nargs='?', help="retrieve or set the current configuration") cmdArgGroup.add_argument("-lb", "--lbutton", dest="lbutton", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current left button action") + cmdArgGroup.add_argument("-lbl", "--lbuttonlong", dest="lbutton_long", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current left button long press action") cmdArgGroup.add_argument("-rb", "--rbutton", dest="rbutton", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current right button action") + cmdArgGroup.add_argument("-rbl", "--rbuttonlong", dest="rbutton_long", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current right button long press action") cmdArgGroup.add_argument("-gl", "--gled", dest="gled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current green led function") cmdArgGroup.add_argument("-rl", "--rled", dest="rled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current red led function") args = argParser.parse_args() - + if (args.verbose): verboseFunc = verboseLog else: @@ -163,7 +203,7 @@ def main(): # Instantiate device object and connect chameleon = Chameleon.Device(verboseFunc) - + if (args.port): if (chameleon.connect(args.port)): # Generate a jumptable and execute all commands in the order they are given on the command line @@ -171,11 +211,16 @@ def main(): "setting" : cmdSetting, "info" : cmdInfo, "uid" : cmdUID, + "getuid" : cmdGetUID, + "identify" : cmdIdentify, + "dumpmfu" : cmdDumpMFU, "config" : cmdConfig, "upload" : cmdUpload, "download" : cmdDownload, "log" : cmdLog, "lbutton" : cmdLButton, + "lbutton_long" : cmdLButtonLong, + "rbutton_long" : cmdRButtonLong, "rbutton" : cmdRButton, "gled" : cmdGreenLED, "rled" : cmdRedLED, @@ -197,9 +242,9 @@ def main(): print("List of potential Chameleons connected to the system:") for port in Chameleon.Device.listDevices(): print(port) - + sys.exit(0) - + if __name__ == "__main__": main() From 42ea0bf3c7529a3b97e05280dcbe3696e0773b32 Mon Sep 17 00:00:00 2001 From: Xander Date: Thu, 23 Mar 2017 16:32:58 -0400 Subject: [PATCH 3/3] Update chamtool.py --- Software/chamtool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/chamtool.py b/Software/chamtool.py index afab4028..7bb9da39 100755 --- a/Software/chamtool.py +++ b/Software/chamtool.py @@ -50,7 +50,7 @@ def cmdDumpMFU(chameleon, arg): return "{}".format(chameleon.cmdDumpMFU()['response']) def cmdConfig(chameleon, arg): - result = chameleon.cmdConfig(chameleon, arg) + result = chameleon.cmdConfig(arg) if (arg is None): return "Current configuration: {}".format(result['response'])