mirror of
https://github.com/RfidResearchGroup/ChameleonMini.git
synced 2026-05-12 11:20:37 -07:00
Merge pull request #102 from j-xander/patch-1
Added New Options to chamtool
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/python3
|
||||
|
||||
import serial
|
||||
import serial.tools.list_ports
|
||||
@@ -13,18 +13,22 @@ 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"
|
||||
COMMAND_THRESHOLD = "THRESHOLD"
|
||||
COMMAND_UPGRADE = "upgrade"
|
||||
|
||||
|
||||
STATUS_CODE_OK = 100
|
||||
STATUS_CODE_OK_WITH_TEXT = 101
|
||||
STATUS_CODE_WAITING_FOR_XMODEM = 110
|
||||
@@ -52,33 +56,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")
|
||||
@@ -97,20 +100,20 @@ class Device:
|
||||
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()
|
||||
|
||||
@@ -119,7 +122,7 @@ class Device:
|
||||
data = self.serial.read(size)
|
||||
self.serial.timeout = 5.0
|
||||
return data
|
||||
|
||||
|
||||
def writeCmd(self, cmd):
|
||||
# Execute command
|
||||
cmdLine = cmd + self.LINE_ENDING
|
||||
@@ -133,19 +136,19 @@ class Device:
|
||||
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):
|
||||
@@ -153,27 +156,30 @@ class Device:
|
||||
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
|
||||
@@ -204,7 +210,7 @@ class Device:
|
||||
|
||||
def cmdLogMode(self, newLogMode):
|
||||
return self.getSetCmd(self.COMMAND_LOGMODE, newLogMode)
|
||||
|
||||
|
||||
def cmdVersion(self):
|
||||
return self.getSetCmd(self.COMMAND_VERSION)
|
||||
|
||||
@@ -214,6 +220,15 @@ class Device:
|
||||
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)
|
||||
@@ -226,18 +241,30 @@ class Device:
|
||||
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)
|
||||
|
||||
+62
-17
@@ -11,8 +11,8 @@ import datetime
|
||||
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,6 +40,15 @@ 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)
|
||||
|
||||
@@ -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)
|
||||
@@ -81,7 +90,7 @@ def cmdLogMode(chameleon, arg):
|
||||
|
||||
def cmdLButton(chameleon, arg):
|
||||
result = chameleon.cmdLButton(arg)
|
||||
|
||||
|
||||
if (arg is None):
|
||||
return "Current left button action: {}".format(result['response'])
|
||||
else:
|
||||
@@ -92,9 +101,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:
|
||||
@@ -105,9 +127,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:
|
||||
@@ -120,7 +155,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:
|
||||
@@ -154,19 +189,19 @@ class CmdListAction(argparse.Action):
|
||||
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.")
|
||||
@@ -176,17 +211,22 @@ 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("-lm", "--logmode", dest="logmode", action=CmdListAction, metavar="LOGMODE", nargs='?', help="retrieve or set the current log mode")
|
||||
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")
|
||||
cmdArgGroup.add_argument("-th", "--threshold", dest="threshold", action=CmdListAction, nargs='?', help="retrieve or set the threshold")
|
||||
cmdArgGroup.add_argument("-ug", "--upgrade", dest="upgrade", action=CmdListAction, nargs=0, help="set the micro Controller to upgrade mode")
|
||||
|
||||
args = argParser.parse_args()
|
||||
|
||||
|
||||
if (args.verbose):
|
||||
verboseFunc = verboseLog
|
||||
else:
|
||||
@@ -194,7 +234,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
|
||||
@@ -202,12 +242,17 @@ def main():
|
||||
"setting" : cmdSetting,
|
||||
"info" : cmdInfo,
|
||||
"uid" : cmdUID,
|
||||
"getuid" : cmdGetUID,
|
||||
"identify" : cmdIdentify,
|
||||
"dumpmfu" : cmdDumpMFU,
|
||||
"config" : cmdConfig,
|
||||
"upload" : cmdUpload,
|
||||
"download" : cmdDownload,
|
||||
"log" : cmdLog,
|
||||
"logmode" : cmdLogMode,
|
||||
"lbutton" : cmdLButton,
|
||||
"lbutton_long" : cmdLButtonLong,
|
||||
"rbutton_long" : cmdRButtonLong,
|
||||
"rbutton" : cmdRButton,
|
||||
"gled" : cmdGreenLED,
|
||||
"rled" : cmdRedLED,
|
||||
@@ -231,9 +276,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()
|
||||
|
||||
Reference in New Issue
Block a user