mirror of
https://github.com/RfidResearchGroup/ChameleonUltra.git
synced 2026-03-31 21:15:47 +00:00
572 lines
20 KiB
Python
572 lines
20 KiB
Python
import enum
|
||
|
||
import chameleon_com
|
||
import chameleon_status
|
||
|
||
DATA_CMD_GET_APP_VERSION = 1000
|
||
DATA_CMD_CHANGE_MODE = 1001
|
||
DATA_CMD_GET_DEVICE_MODE = 1002
|
||
DATA_CMD_SET_SLOT_ACTIVATED = 1003
|
||
DATA_CMD_SET_SLOT_TAG_TYPE = 1004
|
||
DATA_CMD_SET_SLOT_DATA_DEFAULT = 1005
|
||
DATA_CMD_SET_SLOT_ENABLE = 1006
|
||
|
||
DATA_CMD_SET_SLOT_TAG_NICK = 1007
|
||
DATA_CMD_GET_SLOT_TAG_NICK = 1008
|
||
|
||
DATA_CMD_SLOT_DATA_CONFIG_SAVE = 1009
|
||
|
||
DATA_CMD_ENTER_BOOTLOADER = 1010
|
||
DATA_CMD_GET_DEVICE_CHIP_ID = 1011
|
||
|
||
DATA_CMD_SCAN_14A_TAG = 2000
|
||
DATA_CMD_MF1_SUPPORT_DETECT = 2001
|
||
DATA_CMD_MF1_NT_LEVEL_DETECT = 2002
|
||
DATA_CMD_MF1_DARKSIDE_DETECT = 2003
|
||
DATA_CMD_MF1_DARKSIDE_ACQUIRE = 2004
|
||
DATA_CMD_MF1_NT_DIST_DETECT = 2005
|
||
DATA_CMD_MF1_NESTED_ACQUIRE = 2006
|
||
DATA_CMD_MF1_CHECK_ONE_KEY_BLOCK = 2007
|
||
DATA_CMD_MF1_READ_ONE_BLOCK = 2008
|
||
DATA_CMD_MF1_WRITE_ONE_BLOCK = 2009
|
||
|
||
DATA_CMD_SCAN_EM410X_TAG = 3000
|
||
DATA_CMD_WRITE_EM410X_TO_T5577 = 3001
|
||
|
||
DATA_CMD_LOAD_MF1_BLOCK_DATA = 4000
|
||
DATA_CMD_SET_MF1_ANTI_COLLISION_RES = 4001
|
||
|
||
DATA_CMD_SET_EM410X_EMU_ID = 5000
|
||
DATA_CMD_SET_MF1_DETECTION_ENABLE = 5003
|
||
DATA_CMD_GET_MF1_DETECTION_COUNT = 5004
|
||
DATA_CMD_GET_MF1_DETECTION_RESULT = 5005
|
||
|
||
|
||
@enum.unique
|
||
class TagSenseType(enum.IntEnum):
|
||
# 无场感应
|
||
TAG_SENSE_NO = 0,
|
||
# 低频125khz场感应
|
||
TAG_SENSE_LF = 1,
|
||
# 高频13.56mhz场感应
|
||
TAG_SENSE_HF = 2,
|
||
|
||
|
||
@enum.unique
|
||
class TagSpecificType(enum.IntEnum):
|
||
# 特定的且必须存在的标志不存在的类型
|
||
TAG_TYPE_UNKNOWN = 0
|
||
# 125khz(ID卡)系列
|
||
TAG_TYPE_EM410X = 1
|
||
# Mifare系列
|
||
TAG_TYPE_MIFARE_Mini = 2
|
||
TAG_TYPE_MIFARE_1024 = 3
|
||
TAG_TYPE_MIFARE_2048 = 4
|
||
TAG_TYPE_MIFARE_4096 = 5
|
||
# NTAG系列
|
||
TAG_TYPE_NTAG_213 = 6
|
||
TAG_TYPE_NTAG_215 = 7
|
||
TAG_TYPE_NTAG_216 = 8
|
||
|
||
@staticmethod
|
||
def list(exclude_unknown=True):
|
||
enum_list = list(map(int, TagSpecificType))
|
||
if exclude_unknown:
|
||
enum_list.remove(TagSpecificType.TAG_TYPE_UNKNOWN)
|
||
return enum_list
|
||
|
||
|
||
class BaseChameleonCMD:
|
||
"""
|
||
Chameleon cmd function
|
||
"""
|
||
|
||
def __init__(self, chameleon: chameleon_com.ChameleonCom):
|
||
"""
|
||
:param chameleon: chameleon instance, @see chameleon_device.Chameleon
|
||
"""
|
||
self.device = chameleon
|
||
|
||
def get_firmware_version(self) -> int:
|
||
"""
|
||
Get firmware version number(application)
|
||
"""
|
||
resp = self.device.send_cmd_sync(DATA_CMD_GET_APP_VERSION, 0x00, None)
|
||
return int.from_bytes(resp.data, 'little')
|
||
|
||
def get_device_chip_id(self) -> str:
|
||
"""
|
||
Get device chip id
|
||
"""
|
||
resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_CHIP_ID, 0x00, None)
|
||
return resp.data.hex()
|
||
|
||
|
||
|
||
def is_reader_device_mode(self) -> bool:
|
||
"""
|
||
Get device mode, reader or tag
|
||
:return: True is reader mode, else tag mode
|
||
"""
|
||
resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_MODE, 0x00, None)
|
||
return True if resp.data[0] == 1 else False
|
||
|
||
def set_reader_device_mode(self, reader_mode: bool = True):
|
||
"""
|
||
Change device mode, reader or tag
|
||
:param reader_mode: True if reader mode, False if tag mode.
|
||
:return:
|
||
"""
|
||
return self.device.send_cmd_sync(DATA_CMD_CHANGE_MODE, 0x00, 0x0001 if reader_mode else 0x0000)
|
||
|
||
def scan_tag_14a(self):
|
||
"""
|
||
扫描场内的14a标签
|
||
:return:
|
||
"""
|
||
return self.device.send_cmd_sync(DATA_CMD_SCAN_14A_TAG, 0x00, None)
|
||
|
||
def detect_mf1_support(self):
|
||
"""
|
||
检测是否是mifare classic标签
|
||
:return:
|
||
"""
|
||
return self.device.send_cmd_sync(DATA_CMD_MF1_SUPPORT_DETECT, 0x00, None)
|
||
|
||
def detect_mf1_nt_level(self):
|
||
"""
|
||
检测mifare classic的nt漏洞的等级
|
||
:return:
|
||
"""
|
||
return self.device.send_cmd_sync(DATA_CMD_MF1_NT_LEVEL_DETECT, 0x00, None)
|
||
|
||
def detect_darkside_support(self):
|
||
"""
|
||
检测卡片是否易受mifare classic darkside攻击
|
||
:return:
|
||
"""
|
||
return self.device.send_cmd_sync(DATA_CMD_MF1_DARKSIDE_DETECT, 0x00, None, timeout=20)
|
||
|
||
def detect_nt_distance(self, block_known, type_known, key_known):
|
||
"""
|
||
检测卡片的随机数距离
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.append(type_known)
|
||
data.append(block_known)
|
||
data.extend(key_known)
|
||
return self.device.send_cmd_sync(DATA_CMD_MF1_NT_DIST_DETECT, 0x00, data)
|
||
|
||
def acquire_nested(self, block_known, type_known, key_known, block_target, type_target):
|
||
"""
|
||
采集Nested解密需要的关键NT参数
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.append(type_known)
|
||
data.append(block_known)
|
||
data.extend(key_known)
|
||
data.append(type_target)
|
||
data.append(block_target)
|
||
return self.device.send_cmd_sync(DATA_CMD_MF1_NESTED_ACQUIRE, 0x00, data)
|
||
|
||
def acquire_darkside(self, block_target, type_target, first_recover: int or bool, sync_max):
|
||
"""
|
||
采集Darkside解密需要的关键参数
|
||
:param block_target:
|
||
:param type_target:
|
||
:param first_recover:
|
||
:param sync_max:
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.append(type_target)
|
||
data.append(block_target)
|
||
if isinstance(first_recover, bool):
|
||
first_recover = 0x01 if first_recover else 0x00
|
||
data.append(first_recover)
|
||
data.append(sync_max)
|
||
return self.device.send_cmd_sync(DATA_CMD_MF1_DARKSIDE_ACQUIRE, 0x00, data, timeout=sync_max + 5)
|
||
|
||
def auth_mf1_key(self, block, type_value, key):
|
||
"""
|
||
验证mf1秘钥,只验证单个扇区的指定类型的秘钥
|
||
:param block:
|
||
:param type_value:
|
||
:param key:
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.append(type_value)
|
||
data.append(block)
|
||
data.extend(key)
|
||
return self.device.send_cmd_sync(DATA_CMD_MF1_CHECK_ONE_KEY_BLOCK, 0x00, data)
|
||
|
||
def read_mf1_block(self, block, type_value, key):
|
||
"""
|
||
读取mf1单块
|
||
:param block:
|
||
:param type_value:
|
||
:param key:
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.append(type_value)
|
||
data.append(block)
|
||
data.extend(key)
|
||
return self.device.send_cmd_sync(DATA_CMD_MF1_READ_ONE_BLOCK, 0x00, data)
|
||
|
||
def write_mf1_block(self, block, type_value, key, block_data):
|
||
"""
|
||
写入mf1单块
|
||
:param block:
|
||
:param type_value:
|
||
:param key:
|
||
:param block_data:
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.append(type_value)
|
||
data.append(block)
|
||
data.extend(key)
|
||
data.extend(block_data)
|
||
return self.device.send_cmd_sync(DATA_CMD_MF1_WRITE_ONE_BLOCK, 0x00, data)
|
||
|
||
def read_em_410x(self):
|
||
"""
|
||
读取EM410X的卡号
|
||
:return:
|
||
"""
|
||
return self.device.send_cmd_sync(DATA_CMD_SCAN_EM410X_TAG, 0x00, None)
|
||
|
||
def write_em_410x_to_t55xx(self, id_bytes: bytearray):
|
||
"""
|
||
写入EM410X卡号到T55XX中
|
||
:param id_bytes: ID卡号
|
||
:return:
|
||
"""
|
||
new_key = [0x20, 0x20, 0x66, 0x66]
|
||
old_keys = [
|
||
[0x51, 0x24, 0x36, 0x48],
|
||
[0x19, 0x92, 0x04, 0x27],
|
||
]
|
||
if len(id_bytes) != 5:
|
||
raise ValueError("The id bytes length must equal 5")
|
||
data = bytearray()
|
||
data.extend(id_bytes)
|
||
data.extend(new_key)
|
||
for key in old_keys:
|
||
data.extend(key)
|
||
return self.device.send_cmd_sync(DATA_CMD_WRITE_EM410X_TO_T5577, 0x00, data)
|
||
|
||
def set_slot_activated(self, slot_index):
|
||
"""
|
||
设置当前激活使用的卡槽
|
||
:param slot_index: 卡槽索引,从 1 - 8(不是从0下标开始)
|
||
:return:
|
||
"""
|
||
if slot_index < 1 or slot_index > 8:
|
||
raise ValueError("The slot index range error(1-8)")
|
||
data = bytearray()
|
||
data.append(slot_index - 1)
|
||
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):
|
||
"""
|
||
设置当前卡槽的模拟卡的标签类型
|
||
注意:此操作并不会更改flash中的数据,flash中的数据的变动仅在下次保存时更新
|
||
:param slot_index: 卡槽号码
|
||
:param tag_type: 标签类型
|
||
:return:
|
||
"""
|
||
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(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):
|
||
"""
|
||
设置指定卡槽的模拟卡的数据为缺省数据
|
||
注意:此API会将flash中的数据一并进行设置
|
||
:param slot_index: 卡槽号码
|
||
:param tag_type: 要设置的缺省标签类型
|
||
:return:
|
||
"""
|
||
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(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):
|
||
"""
|
||
设置指定的卡槽是否使能
|
||
:param slot_index: 卡槽号码
|
||
:param enable: 是否使能
|
||
:return:
|
||
"""
|
||
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(0x01 if enable else 0x00)
|
||
return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ENABLE, 0X00, data)
|
||
|
||
def set_em140x_sim_id(self, id_bytes: bytearray):
|
||
"""
|
||
设置EM410x模拟的卡号
|
||
:param id_bytes: 卡号的字节
|
||
:return:
|
||
"""
|
||
if len(id_bytes) != 5:
|
||
raise ValueError("The id bytes length must equal 5")
|
||
return self.device.send_cmd_sync(DATA_CMD_SET_EM410X_EMU_ID, 0x00, id_bytes)
|
||
|
||
def set_mf1_detection_enable(self, enable: bool):
|
||
"""
|
||
设置是否使能当前卡槽的侦测
|
||
:param enable: 是否使能
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.append(0x01 if enable else 0x00)
|
||
return self.device.send_cmd_sync(DATA_CMD_SET_MF1_DETECTION_ENABLE, 0x00, data)
|
||
|
||
def get_mf1_detection_count(self):
|
||
"""
|
||
获取当前侦测记录的统计个数
|
||
:return:
|
||
"""
|
||
return self.device.send_cmd_sync(DATA_CMD_GET_MF1_DETECTION_COUNT, 0x00, None)
|
||
|
||
def get_mf1_detection_log(self, index: int):
|
||
"""
|
||
从指定的index位置开始获取侦测日志
|
||
:param index: 开始索引
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.extend(index.to_bytes(4, "big", signed=False))
|
||
return self.device.send_cmd_sync(DATA_CMD_GET_MF1_DETECTION_RESULT, 0x00, data)
|
||
|
||
def set_mf1_block_data(self, block_start: int, block_data: bytearray):
|
||
"""
|
||
设置MF1的模拟卡的块数据
|
||
:param block_start: 开始设置块数据的位置,包含此位置
|
||
:param block_data: 要设置的块数据的字节缓冲区,可包含多个块数据,自动从 block_start 递增
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.append(block_start & 0xFF)
|
||
data.extend(block_data)
|
||
return self.device.send_cmd_sync(DATA_CMD_LOAD_MF1_BLOCK_DATA, 0x00, data)
|
||
|
||
def set_mf1_anti_collision_res(self, sak: bytearray, atqa: bytearray, uid: bytearray):
|
||
"""
|
||
设置MF1的模拟卡的防冲撞资源信息
|
||
:param sak: sak字节
|
||
:param atqa: atqa数组
|
||
:param uid: 卡号数组
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.extend(sak)
|
||
data.extend(atqa)
|
||
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):
|
||
"""
|
||
设置MF1的模拟卡的防冲撞资源信息
|
||
:param slot: 卡槽号码
|
||
:param sense_type: 场类型
|
||
:param name: 卡槽昵称
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.extend([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):
|
||
"""
|
||
设置MF1的模拟卡的防冲撞资源信息
|
||
:param slot: 卡槽号码
|
||
:param sense_type: 场类型
|
||
:param name: 卡槽昵称
|
||
:return:
|
||
"""
|
||
data = bytearray()
|
||
data.extend([slot, sense_type])
|
||
return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_TAG_NICK, 0x00, data)
|
||
|
||
def update_slot_data_config(self):
|
||
"""
|
||
更新卡槽的配置和数据到flash中。
|
||
:return:
|
||
"""
|
||
return self.device.send_cmd_sync(DATA_CMD_SLOT_DATA_CONFIG_SAVE, 0x00, None)
|
||
|
||
def enter_dfu_mode(self):
|
||
"""
|
||
重启进入DFU模式(bootloader)
|
||
:return:
|
||
"""
|
||
return self.device.send_cmd_auto(DATA_CMD_ENTER_BOOTLOADER, 0x00, None)
|
||
|
||
|
||
class NegativeResponseError(Exception):
|
||
"""
|
||
Not positive response
|
||
"""
|
||
|
||
|
||
class PositiveChameleonCMD(BaseChameleonCMD):
|
||
"""
|
||
子类重写基础指令交互实现类,针对每个指令进行单独封装结果处理
|
||
如果结果是成功状态,那么就返回对应的数据,否则直接抛出异常
|
||
"""
|
||
|
||
@staticmethod
|
||
def check_status(status_ret, status_except):
|
||
"""
|
||
检查状态码,如果在接受为成功的
|
||
:param status_ret: 执行指令之后返回的状态码
|
||
:param status_except: 可以认为是执行成功的状态码
|
||
:return:
|
||
"""
|
||
if isinstance(status_except, int):
|
||
status_except = [status_except]
|
||
if status_ret not in status_except:
|
||
if status_ret in chameleon_status.Device and status_ret in chameleon_status.message:
|
||
raise NegativeResponseError(chameleon_status.message[status_ret])
|
||
else:
|
||
raise NegativeResponseError(f"Not positive response and unknown status {status_ret}")
|
||
return
|
||
|
||
def scan_tag_14a(self):
|
||
ret = super(PositiveChameleonCMD, self).scan_tag_14a()
|
||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||
return ret
|
||
|
||
def detect_nt_distance(self, block_known, type_known, key_known):
|
||
ret = super(PositiveChameleonCMD, self).detect_nt_distance(block_known, type_known, key_known)
|
||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||
return ret
|
||
|
||
def acquire_nested(self, block_known, type_known, key_known, block_target, type_target):
|
||
ret = super(PositiveChameleonCMD, self).acquire_nested(
|
||
block_known, type_known, key_known, block_target, type_target)
|
||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||
return ret
|
||
|
||
def acquire_darkside(self, block_target, type_target, first_recover: int or bool, sync_max):
|
||
ret = super(PositiveChameleonCMD, self).acquire_darkside(block_target, type_target, first_recover, sync_max)
|
||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||
return ret
|
||
|
||
def auth_mf1_key(self, block, type_value, key):
|
||
ret = super(PositiveChameleonCMD, self).auth_mf1_key(block, type_value, key)
|
||
self.check_status(ret.status, [
|
||
chameleon_status.Device.HF_TAG_OK,
|
||
chameleon_status.Device.MF_ERRAUTH,
|
||
])
|
||
return ret
|
||
|
||
def read_mf1_block(self, block, type_value, key):
|
||
ret = super(PositiveChameleonCMD, self).read_mf1_block(block, type_value, key)
|
||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||
return ret
|
||
|
||
def write_mf1_block(self, block, type_value, key, block_data):
|
||
ret = super(PositiveChameleonCMD, self).write_mf1_block(block, type_value, key, block_data)
|
||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||
return ret
|
||
|
||
def read_em_410x(self):
|
||
ret = super(PositiveChameleonCMD, self).read_em_410x()
|
||
self.check_status(ret.status, chameleon_status.Device.LF_TAG_OK)
|
||
return ret
|
||
|
||
def write_em_410x_to_t55xx(self, id_bytes: bytearray):
|
||
ret = super(PositiveChameleonCMD, self).write_em_410x_to_t55xx(id_bytes)
|
||
self.check_status(ret.status, chameleon_status.Device.LF_TAG_OK)
|
||
return ret
|
||
|
||
def set_slot_activated(self, slot_index):
|
||
ret = super(PositiveChameleonCMD, self).set_slot_activated(slot_index)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def set_slot_tag_type(self, slot_index: int, tag_type: TagSpecificType):
|
||
ret = super(PositiveChameleonCMD, self).set_slot_tag_type(slot_index, tag_type)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def set_slot_data_default(self, slot_index: int, tag_type: TagSpecificType):
|
||
ret = super(PositiveChameleonCMD, self).set_slot_data_default(slot_index, tag_type)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def set_slot_enable(self, slot_index: int, enable: bool):
|
||
ret = super(PositiveChameleonCMD, self).set_slot_enable(slot_index, enable)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def set_em140x_sim_id(self, id_bytes: bytearray):
|
||
ret = super(PositiveChameleonCMD, self).set_em140x_sim_id(id_bytes)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def set_mf1_detection_enable(self, enable: bool):
|
||
ret = super(PositiveChameleonCMD, self).set_mf1_detection_enable(enable)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def get_mf1_detection_log(self, index: int):
|
||
ret = super(PositiveChameleonCMD, self).get_mf1_detection_log(index)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def set_mf1_block_data(self, block_start: int, data: bytearray):
|
||
ret = super(PositiveChameleonCMD, self).set_mf1_block_data(block_start, data)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def set_mf1_anti_collision_res(self, sak: int, atqa: bytearray, uid: bytearray):
|
||
ret = super(PositiveChameleonCMD, self).set_mf1_anti_collision_res(sak, atqa, uid)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def set_slot_tag_nick_name(self, slot: int, sense_type: int, name: str):
|
||
ret = super(PositiveChameleonCMD, self).set_slot_tag_nick_name(slot, sense_type, name)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
def get_slot_tag_nick_name(self, slot: int, sense_type: int):
|
||
ret = super(PositiveChameleonCMD, self).get_slot_tag_nick_name(slot, sense_type)
|
||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||
return ret
|
||
|
||
|
||
if __name__ == '__main__':
|
||
# connect to chameleon
|
||
dev = chameleon_com.ChameleonCom()
|
||
dev.open("com19")
|
||
cml = BaseChameleonCMD(dev)
|
||
ver = cml.get_firmware_version()
|
||
print(f"Firmware number of application: {ver}")
|
||
id = cml.get_device_chip_id()
|
||
print(f"Device chip id: {id}")
|
||
|
||
|
||
# disconnect
|
||
dev.close()
|
||
|
||
# nerver exit
|
||
while True: pass
|