From d77ca3cd7d9141573e34ac57bcbc5b3a4ff1c956 Mon Sep 17 00:00:00 2001 From: Alexander Featherston Date: Fri, 11 Aug 2023 01:16:25 -0400 Subject: [PATCH 1/2] Attempted fix of Offset issues and utilizing enums in place of hardcoded numbers. Changes to be committed: modified: software/script/chameleon_cli_unit.py modified: software/script/chameleon_cmd.py --- software/script/chameleon_cli_unit.py | 16 ++++-- software/script/chameleon_cmd.py | 75 ++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 4cb0ded..cbd7fff 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -788,9 +788,11 @@ class SlotIndexRequireUint(DeviceRequiredUnit): @staticmethod def add_slot_args(parser: ArgumentParserNoExit): - slot_choices = [1, 2, 3, 4, 5, 6, 7, 8] + slot_choices = chameleon_cmd.SlotNumber.list() + help_str = f"Slot Indexes: {slot_choices}" + parser.add_argument('-s', "--slot", type=int, required=True, - help="Slot index", metavar="number", choices=slot_choices) + help=help_str, metavar="number", choices=slot_choices) return parser class SenseTypeRequireUint(DeviceRequiredUnit): @@ -803,9 +805,12 @@ class SenseTypeRequireUint(DeviceRequiredUnit): @staticmethod def add_sense_type_args(parser: ArgumentParserNoExit): - slot_choices = [1, 2] + slot_list = chameleon_cmd.TagSenseType.list() + slot_choices = chameleon_cmd.TagSenseType.choices() + help_str = f"Sense Types: {slot_list}" + parser.add_argument('-st', "--sense_type", type=int, required=True, - help="Sense type", metavar="number", choices=slot_choices) + help=help_str, metavar="number", choices=slot_choices) return parser @@ -910,7 +915,7 @@ class HWSlotNickSet(SlotIndexRequireUint, SenseTypeRequireUint): parser = ArgumentParserNoExit() self.add_slot_args(parser) self.add_sense_type_args(parser) - parser.add_argument('-n', '--name', type=str, required=True, help="Yout tag nick name for slot") + parser.add_argument('-n', '--name', type=str, required=True, help="Your tag nick name for slot") return parser # hw slot nick set -s 1 -st 1 -n 测试名称保存 @@ -921,6 +926,7 @@ class HWSlotNickSet(SlotIndexRequireUint, SenseTypeRequireUint): if len(name.encode(encoding="gbk")) > 32: raise ValueError("Your tag nick name too long.") self.cmd_positive.set_slot_tag_nick_name(slot_num, sense_type, name) + #print(f'{slot_num} selected for nickname {name}.') print(f' - Set tag nick name for slot {slot_num} success.') diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 0f793d5..d0b8ccd 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -42,6 +42,37 @@ DATA_CMD_SET_MF1_DETECTION_ENABLE = 5003 DATA_CMD_GET_MF1_DETECTION_COUNT = 5004 DATA_CMD_GET_MF1_DETECTION_RESULT = 5005 +@enum.unique +class SlotNumber(enum.IntEnum): + SLOT_1 = 0, + SLOT_2 = 1, + SLOT_3 = 2, + SLOT_4 = 3, + SLOT_5 = 4, + SLOT_6 = 5, + SLOT_7 = 6, + SLOT_8 = 7, + SLOT_NO = 8, + + @staticmethod + def list(exclude_unknown=True): + enum_list = [] + for name, value in SlotNumber.__members__.items(): + if value == SlotNumber.SLOT_NO: + continue + enum_list.append(int(name.replace('SLOT_',''))) + + return enum_list + + @staticmethod + def fix(index: int): + for name, value in SlotNumber.__members__.items(): + if value == SlotNumber.SLOT_NO: + continue + if index == int(name.replace('SLOT_','')): + return value + + @enum.unique class TagSenseType(enum.IntEnum): @@ -52,6 +83,26 @@ class TagSenseType(enum.IntEnum): # 高频13.56mhz场感应 TAG_SENSE_HF = 2, + @staticmethod + def list(exclude_unknown=True): + enum_list = [] + for name, value in TagSenseType.__members__.items(): + if value == TagSenseType.TAG_SENSE_NO: + continue + enum_list.append(f"{name.replace('TAG_SENSE_','')} = {value}") + + return enum_list + + @staticmethod + def choices(exclude_unknown=True): + choice_list = [] + for name, value in TagSenseType.__members__.items(): + if value == TagSenseType.TAG_SENSE_NO: + continue + choice_list.append(value) + + return choice_list + @enum.unique class TagSpecificType(enum.IntEnum): @@ -267,7 +318,7 @@ class BaseChameleonCMD: data.extend(key) return self.device.send_cmd_sync(DATA_CMD_WRITE_EM410X_TO_T5577, 0x00, data) - def set_slot_activated(self, slot_index): + def set_slot_activated(self, slot_index: SlotNumber): """ 设置当前激活使用的卡槽 :param slot_index: 卡槽索引,从 1 - 8(不是从0下标开始) @@ -276,10 +327,10 @@ class BaseChameleonCMD: if slot_index < 1 or slot_index > 8: raise ValueError("The slot index range error(1-8)") data = bytearray() - data.append(slot_index - 1) + data.append(SlotNumber.fix(slot_index)) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ACTIVATED, 0x00, data) - def set_slot_tag_type(self, slot_index: int, tag_type: TagSpecificType): + def set_slot_tag_type(self, slot_index: SlotNumber, tag_type: TagSpecificType): """ 设置当前卡槽的模拟卡的标签类型 注意:此操作并不会更改flash中的数据,flash中的数据的变动仅在下次保存时更新 @@ -290,11 +341,11 @@ class BaseChameleonCMD: if slot_index < 1 or slot_index > 8: raise ValueError("The slot index range error(1-8)") data = bytearray() - data.append(slot_index - 1) + data.append(SlotNumber.fix(slot_index)) data.append(tag_type) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_TYPE, 0x00, data) - def set_slot_data_default(self, slot_index: int, tag_type: TagSpecificType): + def set_slot_data_default(self, slot_index: SlotNumber, tag_type: TagSpecificType): """ 设置指定卡槽的模拟卡的数据为缺省数据 注意:此API会将flash中的数据一并进行设置 @@ -305,11 +356,11 @@ class BaseChameleonCMD: if slot_index < 1 or slot_index > 8: raise ValueError("The slot index range error(1-8)") data = bytearray() - data.append(slot_index - 1) + data.append(SlotNumber.fix(slot_index)) data.append(tag_type) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_DATA_DEFAULT, 0x00, data) - def set_slot_enable(self, slot_index: int, enable: bool): + def set_slot_enable(self, slot_index: SlotNumber, enable: bool): """ 设置指定的卡槽是否使能 :param slot_index: 卡槽号码 @@ -319,7 +370,7 @@ class BaseChameleonCMD: if slot_index < 1 or slot_index > 8: raise ValueError("The slot index range error(1-8)") data = bytearray() - data.append(slot_index - 1) + data.append(SlotNumber.fix(slot_index)) data.append(0x01 if enable else 0x00) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ENABLE, 0X00, data) @@ -386,7 +437,7 @@ class BaseChameleonCMD: data.extend(uid) return self.device.send_cmd_sync(DATA_CMD_SET_MF1_ANTI_COLLISION_RES, 0X00, data) - def set_slot_tag_nick_name(self, slot: int, sense_type: int, name: str): + def set_slot_tag_nick_name(self, slot: SlotNumber, sense_type: TagSenseType, name: str): """ 设置MF1的模拟卡的防冲撞资源信息 :param slot: 卡槽号码 @@ -395,11 +446,11 @@ class BaseChameleonCMD: :return: """ data = bytearray() - data.extend([slot, sense_type]) + data.extend([SlotNumber.fix(slot), sense_type]) data.extend(name.encode(encoding="gbk")) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_NICK, 0x00, data) - def get_slot_tag_nick_name(self, slot: int, sense_type: int): + def get_slot_tag_nick_name(self, slot: SlotNumber, sense_type: TagSenseType): """ 设置MF1的模拟卡的防冲撞资源信息 :param slot: 卡槽号码 @@ -408,7 +459,7 @@ class BaseChameleonCMD: :return: """ data = bytearray() - data.extend([slot, sense_type]) + data.extend([SlotNumber.fix(slot), sense_type]) return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_TAG_NICK, 0x00, data) def update_slot_data_config(self): From 828d88c273da5e5d194f5823646e0ea685fe49e0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 18 Aug 2023 17:47:44 +0200 Subject: [PATCH 2/2] Several changes on TagSenseType, TagSpecificType and SlotNumber: * SlotNumber values range from 1 to 8 rather than from 0 to 7 this allows more straightforward usage as ppl can use equivalently SLOT_1 or 1. * SlotNumber.fix -> .to_fw, and add .from_fw * removed unnecessary SLOT_NO * More straightforward use of enums, no need for .value, .__members__, name.replace() etc * Unify usage between TagSenseType and TagSpecificType * Add str representations for TagSenseType * Fixed TagSpecificType related help (e.g. in hw slot type -h) * Removed some redundant error raise * Note: iterations can be done with `for slot in chameleon_cmd.SlotNumber:` --- software/script/chameleon_cli_unit.py | 41 +++++----- software/script/chameleon_cmd.py | 106 +++++++++++--------------- 2 files changed, 67 insertions(+), 80 deletions(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 7783c33..cb135d6 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -798,7 +798,7 @@ class SlotIndexRequireUint(DeviceRequiredUnit): @staticmethod def add_slot_args(parser: ArgumentParserNoExit): - slot_choices = chameleon_cmd.SlotNumber.list() + slot_choices = [x.value for x in chameleon_cmd.SlotNumber] help_str = f"Slot Indexes: {slot_choices}" parser.add_argument('-s', "--slot", type=int, required=True, @@ -815,14 +815,19 @@ class SenseTypeRequireUint(DeviceRequiredUnit): @staticmethod def add_sense_type_args(parser: ArgumentParserNoExit): - slot_list = chameleon_cmd.TagSenseType.list() - slot_choices = chameleon_cmd.TagSenseType.choices() - help_str = f"Sense Types: {slot_list}" - + sense_choices = chameleon_cmd.TagSenseType.list() + + help_str = "" + for s in chameleon_cmd.TagSenseType: + if s == chameleon_cmd.TagSenseType.TAG_SENSE_NO: + continue + help_str += f"{s.value} = {s}, " + parser.add_argument('-st', "--sense_type", type=int, required=True, - help=help_str, metavar="number", choices=slot_choices) + help=help_str, metavar="number", choices=sense_choices) return parser + class HWSlotInfo(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit or None: return @@ -830,11 +835,11 @@ class HWSlotInfo(DeviceRequiredUnit): # hw slot info def on_exec(self, args: argparse.Namespace): data = self.cmd_positive.get_slot_info().data - selected = self.cmd_positive.get_active_slot().data[0] - for slot in range(8): - print(f' - Slot {slot + 1} data{" (active)" if slot == selected else ""}:') - print(f' HF: {chameleon_cmd.TagSpecificType(data[slot * 2])}') - print(f' LF: {chameleon_cmd.TagSpecificType(data[slot * 2 + 1])}') + selected = chameleon_cmd.SlotNumber.from_fw(self.cmd_positive.get_active_slot().data[0]) + for slot in chameleon_cmd.SlotNumber: + print(f' - Slot {slot} data{" (active)" if slot == selected else ""}:') + print(f' HF: {chameleon_cmd.TagSpecificType(data[chameleon_cmd.SlotNumber.to_fw(slot) * 2])}') + print(f' LF: {chameleon_cmd.TagSpecificType(data[chameleon_cmd.SlotNumber.to_fw(slot) * 2 + 1])}') class HWSlotSet(SlotIndexRequireUint): @@ -855,10 +860,10 @@ class TagTypeRequiredUint(DeviceRequiredUnit): def add_type_args(parser: ArgumentParserNoExit): type_choices = chameleon_cmd.TagSpecificType.list() help_str = "" - for name, value in chameleon_cmd.TagSpecificType.__members__.items(): - if value == chameleon_cmd.TagSpecificType.TAG_TYPE_UNKNOWN: + for t in chameleon_cmd.TagSpecificType: + if t == chameleon_cmd.TagSpecificType.TAG_TYPE_UNKNOWN: continue - help_str += f"{value} = {name.replace('TAG_TYPE_', '')}, " + help_str += f"{t.value} = {t}, " parser.add_argument('-t', "--type", type=int, required=True, help=help_str, metavar="number", choices=type_choices) return parser @@ -990,8 +995,8 @@ class HWSlotOpenAll(DeviceRequiredUnit): lf_type = chameleon_cmd.TagSpecificType.TAG_TYPE_EM410X # set all slot - for slot in range(1,9): - print(f' Slot{slot} setting...') + for slot in chameleon_cmd.SlotNumber: + print(f' Slot {slot} setting...') # first to set tag type self.cmd_positive.set_slot_tag_type(slot, hf_type) self.cmd_positive.set_slot_tag_type(slot, lf_type) @@ -1000,11 +1005,11 @@ class HWSlotOpenAll(DeviceRequiredUnit): self.cmd_positive.set_slot_data_default(slot, lf_type) # finally, we can enable this slot. self.cmd_positive.set_slot_enable(slot, True) - print(f' Open slot{slot} finish') + print(f' Slot {slot} setting done.') # update config and save to flash self.cmd_positive.update_slot_data_config() - print(f' - Open all slot and set data to default success.') + print(f' - Succeeded opening all slots and setting data to default.') class HWDFU(DeviceRequiredUnit): diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 38d7feb..1e964b0 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -54,34 +54,24 @@ DATA_CMD_GET_MF1_DETECTION_RESULT = 5005 @enum.unique class SlotNumber(enum.IntEnum): - SLOT_1 = 0, - SLOT_2 = 1, - SLOT_3 = 2, - SLOT_4 = 3, - SLOT_5 = 4, - SLOT_6 = 5, - SLOT_7 = 6, - SLOT_8 = 7, - SLOT_NO = 8, + SLOT_1 = 1, + SLOT_2 = 2, + SLOT_3 = 3, + SLOT_4 = 4, + SLOT_5 = 5, + SLOT_6 = 6, + SLOT_7 = 7, + SLOT_8 = 8, @staticmethod - def list(exclude_unknown=True): - enum_list = [] - for name, value in SlotNumber.__members__.items(): - if value == SlotNumber.SLOT_NO: - continue - enum_list.append(int(name.replace('SLOT_',''))) - - return enum_list + def to_fw(index: int): # can be int or SlotNumber + # SlotNumber() will raise error for us if index not in slot range + return SlotNumber(index).value - 1 @staticmethod - def fix(index: int): - for name, value in SlotNumber.__members__.items(): - if value == SlotNumber.SLOT_NO: - continue - if index == int(name.replace('SLOT_','')): - return value - + def from_fw(index: int): + # SlotNumber() will raise error for us if index not in fw range + return SlotNumber(index + 1) @enum.unique @@ -93,26 +83,20 @@ class TagSenseType(enum.IntEnum): # 高频13.56mhz场感应 TAG_SENSE_HF = 2, + @staticmethod def list(exclude_unknown=True): - enum_list = [] - for name, value in TagSenseType.__members__.items(): - if value == TagSenseType.TAG_SENSE_NO: - continue - enum_list.append(f"{name.replace('TAG_SENSE_','')} = {value}") - + enum_list = list(map(int, TagSenseType)) + if exclude_unknown: + enum_list.remove(TagSenseType.TAG_SENSE_NO) return enum_list - - @staticmethod - def choices(exclude_unknown=True): - choice_list = [] - for name, value in TagSenseType.__members__.items(): - if value == TagSenseType.TAG_SENSE_NO: - continue - choice_list.append(value) - - return choice_list + def __str__(self): + if self == TagSenseType.TAG_SENSE_LF: + return "LF" + elif self == TagSenseType.TAG_SENSE_HF: + return "HF" + return "None" @enum.unique class TagSpecificType(enum.IntEnum): @@ -138,21 +122,21 @@ class TagSpecificType(enum.IntEnum): return enum_list def __str__(self): - if self.value == TagSpecificType.TAG_TYPE_EM410X: + if self == TagSpecificType.TAG_TYPE_EM410X: return "EM410X" - elif self.value == TagSpecificType.TAG_TYPE_MIFARE_Mini: + elif self == TagSpecificType.TAG_TYPE_MIFARE_Mini: return "Mifare Mini" - elif self.value == TagSpecificType.TAG_TYPE_MIFARE_1024: + elif self == TagSpecificType.TAG_TYPE_MIFARE_1024: return "Mifare Classic 1k" - elif self.value == TagSpecificType.TAG_TYPE_MIFARE_2048: + elif self == TagSpecificType.TAG_TYPE_MIFARE_2048: return "Mifare Classic 2k" - elif self.value == TagSpecificType.TAG_TYPE_MIFARE_4096: + elif self == TagSpecificType.TAG_TYPE_MIFARE_4096: return "Mifare Classic 4k" - elif self.value == TagSpecificType.TAG_TYPE_NTAG_213: + elif self == TagSpecificType.TAG_TYPE_NTAG_213: return "NTAG 213" - elif self.value == TagSpecificType.TAG_TYPE_NTAG_215: + elif self == TagSpecificType.TAG_TYPE_NTAG_215: return "NTAG 215" - elif self.value == TagSpecificType.TAG_TYPE_NTAG_216: + elif self == TagSpecificType.TAG_TYPE_NTAG_216: return "NTAG 216" return "Unknown" @@ -371,10 +355,9 @@ class BaseChameleonCMD: :param slot_index: 卡槽索引,从 1 - 8(不是从0下标开始) :return: """ - if slot_index < 1 or slot_index > 8: - raise ValueError("The slot index range error(1-8)") + # SlotNumber() will raise error for us if slot_index not in slot range data = bytearray() - data.append(SlotNumber.fix(slot_index)) + data.append(SlotNumber.to_fw(slot_index)) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ACTIVATED, 0x00, data) def set_slot_tag_type(self, slot_index: SlotNumber, tag_type: TagSpecificType): @@ -385,10 +368,9 @@ class BaseChameleonCMD: :param tag_type: 标签类型 :return: """ - if slot_index < 1 or slot_index > 8: - raise ValueError("The slot index range error(1-8)") + # SlotNumber() will raise error for us if slot_index not in slot range data = bytearray() - data.append(SlotNumber.fix(slot_index)) + data.append(SlotNumber.to_fw(slot_index)) data.append(tag_type) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_TYPE, 0x00, data) @@ -400,10 +382,9 @@ class BaseChameleonCMD: :param tag_type: 要设置的缺省标签类型 :return: """ - if slot_index < 1 or slot_index > 8: - raise ValueError("The slot index range error(1-8)") + # SlotNumber() will raise error for us if slot_index not in slot range data = bytearray() - data.append(SlotNumber.fix(slot_index)) + data.append(SlotNumber.to_fw(slot_index)) data.append(tag_type) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_DATA_DEFAULT, 0x00, data) @@ -414,10 +395,9 @@ class BaseChameleonCMD: :param enable: 是否使能 :return: """ - if slot_index < 1 or slot_index > 8: - raise ValueError("The slot index range error(1-8)") + # SlotNumber() will raise error for us if slot_index not in slot range data = bytearray() - data.append(SlotNumber.fix(slot_index)) + data.append(SlotNumber.to_fw(slot_index)) data.append(0x01 if enable else 0x00) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ENABLE, 0X00, data) @@ -492,8 +472,9 @@ class BaseChameleonCMD: :param name: 卡槽昵称 :return: """ + # SlotNumber() will raise error for us if slot not in slot range data = bytearray() - data.extend([SlotNumber.fix(slot), sense_type]) + data.extend([SlotNumber.to_fw(slot), sense_type]) data.extend(name.encode(encoding="gbk")) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_NICK, 0x00, data) @@ -505,8 +486,9 @@ class BaseChameleonCMD: :param name: 卡槽昵称 :return: """ + # SlotNumber() will raise error for us if slot not in slot range data = bytearray() - data.extend([SlotNumber.fix(slot), sense_type]) + data.extend([SlotNumber.to_fw(slot), sense_type]) return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_TAG_NICK, 0x00, data) def update_slot_data_config(self):