Remove NFC Tag in Python - python

I got my hands on a Lego Dimensions pad which is in fact a triple NFC reader. Found some code on github to start playing with it with a raspberry pi. I've got it so far that it sends a webhook to my Home Assistant to turn on a light when placing a minifigure on the pad. Where I got stuck and my python programming skills fall short is to also send a webhook when the tag is removed. Can anyone point me in the right direction?
Thx!
#!/usr/bin/python
import usb.core
import usb.util
from time import sleep
import requests
TOYPAD_INIT = [0x55, 0x0f, 0xb0, 0x01, 0x28, 0x63, 0x29, 0x20, 0x4c, 0x45, 0x47, 0x4f, 0x20, 0x32, 0x30, 0x31, 0x34, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
# Colors
OFF = [0,0,0]
RED = [255,0,0]
GREEN = [0,255,0]
BLUE = [0,0,255]
YELLOW = [255,255,0]
PURPLE = [128,0,128]
# Pad number
ALL_PADS = 0
CENTER_PAD = 1
LEFT_PAD = 2
RIGHT_PAD = 3
# Actions
TAG_INSERTED = 0
TAG_REMOVED = 1
# UIDs can be retrieved with Android App (most probably in hexadecimal)
uidBatman = [4, 117, 251, 42, 41, 73, 128] # Batman Lego
uidLucy = [4, 66, 84, 114, 82, 66, 129] # Lucy Lego
uidGandalf = [4, 133, 184, 90, 181, 73, 128] # Gandalf
# Webhook var
auth_token='[Token]'
hed = {'Authorization': 'Bearer ' + auth_token}
dataon = {"state": "on"}
dataoff = {"state": "off"}
def init_usb():
global dev
dev = usb.core.find(idVendor=0x0e6f, idProduct=0x0241)
if dev is None:
print("Device not found")
else:
if dev.is_kernel_driver_active(0):
dev.detach_kernel_driver(0)
print usb.util.get_string(dev, dev.iProduct)
dev.set_configuration()
dev.write(1,TOYPAD_INIT)
return dev
def send_command(dev,command):
# calculate checksum
checksum = 0
for word in command:
checksum = checksum + word
if checksum >= 256:
checksum -= 256
message = command+[checksum]
# pad message
while(len(message) < 32):
message.append(0x00)
# send message
dev.write(1, message)
return
def switch_pad(pad, colour):
send_command(dev,[0x55, 0x06, 0xc0, 0x02, pad, colour[0], colour[1], colour[2],])
return
def main():
init_usb()
if dev != None :
while True:
try:
in_packet = dev.read(0x81, 32, timeout = 10)
bytelist = list(in_packet)
if not bytelist:
pass
elif bytelist[0] != 0x56: # NFC packets start with 0x56
pass
else:
pad_num = bytelist[2]
uid_bytes = bytelist[6:13]
action = bytelist[5]
if action == TAG_INSERTED :
print uid_bytes
if (uid_bytes == uidBatman) :
switch_pad(pad_num, RED)
url = '[URL]'
response = requests.post(url, json=dataon, headers=hed)
print(response)
print(response.json())
elif (uid_bytes == uidLucy) :
switch_pad(pad_num, PURPLE)
url = '[URL]'
response = requests.post(url, json=data, headers=hed)
print(response)
print(response.json())
elif (uid_bytes == uidGandalf) :
switch_pad(pad_num, YELLOW)
url = '[URL]'
response = requests.post(url, json=data, headers=hed)
print(response)
print(response.json())
else:
# some other tag
switch_pad(pad_num, GREEN)
else:
# some tag removed
switch_pad(pad_num, OFF)
except usb.USBError, err:
pass
switch_pad(ALL_PADS,OFF)
return
if __name__ == '__main__':
main()

Related

Overflow while using ReadWriteMemory

I'm trying to fetch information from a hex editor. But ReadWriteMemory gives me an error about "<class 'OverflowError'>: int too long to convert"
Here is my code:
from ReadWriteMemory import ReadWriteMemory
base_address = 0x7FF6D60A0000
static_address_offset = 0x0074DE40
pointer_static_address = base_address + static_address_offset
offsets = [0x08, 0x08, 0xB0, 0x08, 0x278, 0x10, 0xD0]
rmw = ReadWriteMemory()
process = rmw.get_process_by_name('010Editor.exe')
process.open()
pointer = process.get_pointer(pointer_static_address, offsets=offsets)
pointer_value = process.read(pointer)
print(pointer_value)
How can I solve this?
I fixed it using 'pymem', So it appears that ReadWriteMemory can't handle 64bit applications.
from pymem import *
from pymem.process import *
pm = Pymem('010Editor.exe')
def GetByteNumber():
def GetPtrAddr(base, offsets):
addr = pm.read_longlong(base)
for i in offsets:
if i != offsets[-1]:
addr = pm.read_longlong(addr + i)
return addr + offsets[-1]
return pm.read_int(GetPtrAddr(pm.base_address + 0x0074DE40, offsets=[0x8, 0x8, 0x60, 0x8, 0x10, 0xB0, 0xD0]))

write 8 bites to RS-485 using modbus_tk

Ethernet to RS-485 сonverter is connected to the computer and then I have 3 RS-485 controllers connected. I am writing registers to controllers using pymodbus. How can I do the same with modbus_tk?
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.utilities import computeCRC
Defaults.Timeout = 0.02
client = ModbusClient('192.168.0.191', port=9761)
client.connect()
builder = BinaryPayloadBuilder()
data = [0x00, 0x06, 0x00, 0x01, 0x00, 0xFF]
builder.add_8bit_uint(data[0])
builder.add_8bit_uint(data[1])
builder.add_8bit_uint(data[2])
builder.add_8bit_uint(data[3])
builder.add_8bit_uint(data[4])
builder.add_8bit_uint(data[5])
crc = computeCRC(data)
builder.add_8bit_uint(crc >> 8)
builder.add_8bit_uint(crc & 0x00FF)
payload = builder.build()
address = 0
client.write_registers(address, payload, skip_encode=True, unit=1)

I wrote this python program and it keeps giving me errors

I wrote this and it keeps giving me errors:
import usb.util
from time import sleep
TOYPAD_INIT = [0x55, 0x0f, 0xb0, 0x01, 0x28, 0x63, 0x29, 0x20, 0x4c, 0x45, 0x47, 0x4f, 0x20, 0x32, 0x30, 0x31, 0x34, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
OFF = [0,0,0]
RED = [255,0,0]
GREEN = [0,255,0]
BLUE = [0,0,255]
ALL_PADS = 0
CENTER_PAD = 1
LEFT_PAD = 2
RIGHT_PAD = 3
# Actions
TAG_INSERTED = 0
TAG_REMOVED = 1
# UIDs can be retrieved with Android App (most probably in hexadecimal)
uidDarthVader = (4, 161, 158, 210, 227, 64 , 128) # Darth Vader from Disney Infinity 3.0
def init_usb():
global dev
dev = usb.core.find(idVendor=0x0e6f, idProduct=0x0241)
if dev is None:
print('Device not found')
else:
if dev.is_kernel_driver_active(0):
dev.detach_kernel_driver(0)
print(usb.util.get_string(dev, dev.iProduct))
dev.set_configuration()
dev.write(1,TOYPAD_INIT)
return dev
def send_command(dev,command):
# calculate checksum
checksum = 0
for word in command:
checksum = checksum + word
if checksum >= 256:
checksum -= 256
message = command+[checksum]
# pad message
while(len(message) < 32):
message.append(0x00)
# send message
dev.write(1, message)
return
def switch_pad(pad, colour):
send_command(dev,[0x55, 0x06, 0xc0, 0x02, pad, colour[0], colour[1], colour[2],])
return
def uid_compare(uid1, uid2):
match = True
for i in range(0,7):
if (uid1[i] != uid2[i]) :
match = False
return match
def main():
init_usb()
if dev != None :
while True:
try:
in_packet = dev.read(0x81, 32, timeout = 10)
bytelist = list(in_packet)
if not bytelist:
pass
elif bytelist[0] != 0x56: # NFC packets start with 0x56
pass
else:
pad_num = bytelist[2]
uid_bytes = bytelist[6:13]
match = uid_compare(uid_bytes, uidDarthVader)
action = bytelist[5]
if action == TAG_INSERTED :
if match:
# Darth Vader
switch_pad(pad_num, RED)
else:
# some other tag
switch_pad(pad_num, GREEN)
else:
# some tag removed
switch_pad(pad_num, OFF)
except(usb.USBError, err):
pass
switch_pad(ALL_PADS,OFF)
return
if __name__ == '__main__':
main()
and get one of two errors:
NameError: name 'err' is not defined
or
except usb.USBError, err:
^
SyntaxError: invalid syntax
why is that? My goal is to use this for a piece of tech i'm developing. i have tried looking on the web found nothing and tried reformatting the code still didn't work, finally i tried to use the code formatting assistant and it still didn't help.
Your error is a result of the variable err being undefined.
Here I can replicate the error:
In [7]: try:
...: raise SyntaxError
...: except(SyntaxError, err):
...: print("Error message")
...:
---------------------------------------------------------------------------
SyntaxError Traceback (most recent call last)
<ipython-input-7-7c18a68f8815> in <module>
1 try:
----> 2 raise SyntaxError
3 except(SyntaxError, err):
SyntaxError: None
During handling of the above exception, another exception occurred:
NameError Traceback (most recent call last)
<ipython-input-7-7c18a68f8815> in <module>
1 try:
2 raise SyntaxError
----> 3 except(SyntaxError, err):
4 print("Error message")
5
NameError: name 'err' is not defined
Instead, try removing the err, your except line should read
except(SyntaxError):
You should also know that the github repo where you got the code that you copy-pasted is in python 2, so that is likely why you are seeing this error.
Here is a link to the source, I've taken the liberty of fixing the syntax highlighting.

Send APDU Commands in python (RC522, RaspberryPi)

I build up some kind of RFID-Reader with an Raspberry Pi 3 and an RC522 using this code as a start: https://github.com/mxgxw/MFRC522-python.
Unfortunately I'm not able to get a APDU-Response from my card after sending any APDU-Command.
My current workflow is more or less the ISO 14443-4:
Search for cards
receive ATQA
Perform anticollision and select card
Determine whether card is supporting ISO-14443-4 protocol or not
Send RATS and receive ATS
Perform an PPS-Request [Until here everything is fine and I get responses.]
Send an APDU-Command [btw. command works fine with my smartphone and an APP]
#Scan for cards
(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
#If a card is found
if status == MIFAREReader.MI_OK:
print "Card detected"
TagType = (TagType >> 6) | 0 #(Länge der UID errechnen
print "Tagtype: %s" % (TagType)
# START ANTI-COLLISION AS OF ISO 14443
if TagType == 0:
print "UID length is single -- starting ANTI-COLLISION CL1"
(status,uid) = MIFAREReader.MFRC522_Anticoll()
if status == MIFAREReader.MI_OK:
print "Card read UID: %s,%s,%s,%s" % (uid[0], uid[1], uid[2], uid[3])
elif TagType == 1: # Ignore this part as there is no functionality by now
print "CARD IS NOT SUPPORTED YET"
(status,uid) = MIFAREReader.MFRC522_Anticoll()
elif TagType == 2:
print "CARD IS NOT SUPPORTED YET"
(status,uid) = MIFAREReader.MFRC522_Anticoll()
elif TagType == 3:
print "CARD IS NOT SUPPORTED YET"
(status,uid) = MIFAREReader.MFRC522_Anticoll()
else:
print "An unexpected error occured: UID length is not covered by ISO-14443."
(size, APDU) = MIFAREReader.MFRC522_SelectTag(uid)
print "Card selected"
print "ISO 14443-4 Compatibility: %s" % (APDU)
if APDU == 1: # Card supports ISO 14443-4 protocol [Problem could be here]
#SEND RATS
print "Sening RATS"
RATS_Sequenz = [0xE0, 0x50]
CRC_RATS = []
CRC_RATS = MIFAREReader.CalulateCRC(RATS_Sequenz)
RATS_Sequenz.append(CRC_RATS[0])
RATS_Sequenz.append(CRC_RATS[1])
(stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, RATS_Sequenz)
# Muss: Auswertung des ATS
# PPS
print "Initialisiere PPS-Kommando"
PPSS_Sequenz = [0xD0, 0x11, 0x00]
CRC_PPSS = []
CRC_PPSS = MIFAREReader.CalulateCRC(PPSS_Sequenz)
PPSS_Sequenz.append(CRC_PPSS[0])
PPSS_Sequenz.append(CRC_PPSS[1])
(stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, PPSS_Sequenz)
#PCB = [0x02]
#PCB.append(PCB[0])
#PCB.append(PCB[1])
#(stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, PCB)
command = [0xFF, 0x41, 0x00, 0x00, 0x00] # NOT THE COMMAND!
Header = [0x00, 0x22, 0xC1, 0xA4, 0x12, 0x80, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x02, 0x83, 0x01, 0x02, 0x84, 0x01, 0x0D] #Command to be sent
pOut = MIFAREReader.CalulateCRC(Header)
Header.append(pOut[0])
Header.append(pOut[1])
(stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, (Header))
time.sleep(1) # Leftover from here / another non working try
Body = [0x80, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x02, 0x83, 0x01, 0x02, 0x84, 0x01, 0x0D]
#pOut = MIFAREReader.CalulateCRC(Body)
#Body.append(pOut[0])
#Body.append(pOut[1])
#(stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, Body)
elif APDU == 0:
#HALT
command = [0x50]
pOut = MIFAREReader.CalulateCRC(command)
command.append(pOut[0])
command.append(pOut[1])
(stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, command)
#WOP
This is the send function as found in the 'library':
def MFRC522_ToCard(self,command,sendData):
backData = []
backLen = 0
status = self.MI_ERR
irqEn = 0x00
waitIRq = 0x00
lastBits = None
n = 0
i = 0
if command == self.PCD_AUTHENT:
irqEn = 0x12
waitIRq = 0x10
if command == self.PCD_TRANSCEIVE:
irqEn = 0x77
waitIRq = 0x30
self.Write_MFRC522(self.CommIEnReg, irqEn|0x80)
self.ClearBitMask(self.CommIrqReg, 0x80)
self.SetBitMask(self.FIFOLevelReg, 0x80)
self.Write_MFRC522(self.CommandReg, self.PCD_IDLE);
while(i<len(sendData)):
self.Write_MFRC522(self.FIFODataReg, sendData[i])
i = i+1
self.Write_MFRC522(self.CommandReg, command)
if command == self.PCD_TRANSCEIVE:
self.SetBitMask(self.BitFramingReg, 0x80)
i = 2000
while True:
n = self.Read_MFRC522(self.CommIrqReg)
i = i - 1
if ~((i!=0) and ~(n&0x01) and ~(n&waitIRq)):
break
self.ClearBitMask(self.BitFramingReg, 0x80)
if i != 0:
if (self.Read_MFRC522(self.ErrorReg) & 0x1B)==0x00:
status = self.MI_OK
if n & irqEn & 0x01:
status = self.MI_NOTAGERR
if command == self.PCD_TRANSCEIVE:
n = self.Read_MFRC522(self.FIFOLevelReg)
lastBits = self.Read_MFRC522(self.ControlReg) & 0x07
if lastBits != 0:
backLen = (n-1)*8 + lastBits
else:
backLen = n*8
if n == 0:
n = 1
if n > self.MAX_LEN:
n = self.MAX_LEN
i = 0
while i<n:
backData.append(self.Read_MFRC522(self.FIFODataReg))
i = i + 1;
else:
status = self.MI_ERR
print"Status: %s, Data: %s, Length: %s" % (status, backData, backLen)
return (status,backData,backLen)
The command is send using the 'toCard' function of the code mentioned above with following structure:
APDU-Command + CRC-Bytes.
e.g. 0x00 [CLA], 0x22 [INS], 0xC1 [P1], 0xA4 [P2], 0x12 [Length], 0x80 [DATA, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x02, 0x83, 0x01, 0x02, 0x84, 0x01, 0x0D, CRC1, CRC2
I also tried sending the Command with an additional PCB or in multiple parts (e.g. Header first then body).
I'm not sure if the structure of the APDU-Command is or if I forgot some part of the activation process as of ISO 14443. I'd be glad if anybody can help me.

Weird behavior in Python in array initialization

In the following you see a snippet of my Python program that I wrote to send APDU commands to smart cards. I used PySCard library in this program.
First Program :
for LOAD_KEY in validLoadCommands:
data,sw1,sw2 =connection.transmit(LOAD_KEY)
temp = LOAD_KEY
x= temp[3]
for j in range(0,len(LOAD_KEY)):
LOAD_KEY[j]=hex(LOAD_KEY[j])
print ' >>>',' Load Command :',
for j in range(0,len(LOAD_KEY)):
LOAD_KEY[j]=str(LOAD_KEY[j])
if len(LOAD_KEY[j])==3:
LOAD_KEY[j]=LOAD_KEY[j][0:2]+'0'+LOAD_KEY[j][2]
print LOAD_KEY[j],
print
for j in range(0,len(data)):
data[j]=hex(data[j])
print ' <<<',' Data :',
for j in range(0,len(data)):
data[j]=str(data[j])
if len(data[j])==3:
data[j]=data[j][0:2]+'0'+data[j][2]
print data[j],
print '--',hex(sw1),hex(sw2)
if (temp[2] == 0x00 or temp[2] == 0x20):
keyType = 0x60
else:
keyType = 0x61
AUTH = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, blockNum, keyType,temp[3]]
print 'AUTH Command: ', AUTH
data,sw1,sw2 =connection.transmit(AUTH)
print data, sw1, sw2
And its output :
Auth Command: [255, 134, 0, 0, 5, 1, 0, 4, 97, '0x0e']
Traceback (most recent call last):
File "C:\Users\Erb4h1m\Desktop\Faraadis Alborz Card Reader\CRT-603-CZ1_Read1Block.py", line 199, in <module>
data,sw1,sw2 =connection.transmit(AUTH)
File "D:\Software\Python27\lib\site-packages\smartcard\CardConnectionDecorator.py", line 82, in transmit
return self.component.transmit(bytes, protocol)
File "D:\Software\Python27\lib\site-packages\smartcard\CardConnection.py", line 140, in transmit
data, sw1, sw2 = self.doTransmit(bytes, protocol)
File "D:\Software\Python27\lib\site-packages\smartcard\pcsc\PCSCCardConnection.py", line 173, in doTransmit
hresult, response = SCardTransmit(self.hcard, pcscprotocolheader, bytes)
File "D:\Software\Python27\lib\site-packages\smartcard\scard\scard.py", line 1329, in SCardTransmit
return _scard.SCardTransmit(*args)
TypeError: Expected a list of bytes.
And when I replace temp[3] with x:
for LOAD_KEY in validLoadCommands:
data,sw1,sw2 =connection.transmit(LOAD_KEY)
temp = LOAD_KEY
x= temp[3]
for j in range(0,len(LOAD_KEY)):
LOAD_KEY[j]=hex(LOAD_KEY[j])
print ' >>>',' Load Command :',
for j in range(0,len(LOAD_KEY)):
LOAD_KEY[j]=str(LOAD_KEY[j])
if len(LOAD_KEY[j])==3:
LOAD_KEY[j]=LOAD_KEY[j][0:2]+'0'+LOAD_KEY[j][2]
print LOAD_KEY[j],
print
for j in range(0,len(data)):
data[j]=hex(data[j])
print ' <<<',' Data :',
for j in range(0,len(data)):
data[j]=str(data[j])
if len(data[j])==3:
data[j]=data[j][0:2]+'0'+data[j][2]
print data[j],
print '--',hex(sw1),hex(sw2)
if (temp[2] == 0x00 or temp[2] == 0x20):
keyType = 0x60
else:
keyType = 0x61
AUTH = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, blockNum, keyType, x]
print 'AUTH Command: ', AUTH
data,sw1,sw2 =connection.transmit(AUTH)
print data, sw1, sw2
Then the output is:
AUTH: [255, 134, 0, 0, 5, 1, 0, 4, 97, 14]
[] 144 0
As you see above, in the second case I DON'T receive any error, while there is no difference between first program and second program! I only replaced
AUTH = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, blockNum, keyType,temp[3]]
with:
AUTH = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, blockNum, keyType,x]
and x is initialized with temp[3] in the top of program. neither x nor temp[3] didn't changed between the line of initialization and the line of error.
What is going here?
Your temp variable reference LOAD_KEY (Line 3: temp = LOAD_KEY)
When x= temp[3] get called, it's the value of LOAD_KEY at index 3 right after your connection.transmit that is set.
When you are sending temp[3] for your AUTH, LOAD_KEY have changed and so does temp[3]. So it's not anymore the same value as x.
connection.transmit => LOAD_KEY is set => temp => [3] => x
*** LOAD_KEY changes ***
x => old value of temp[3] aka LOAD_KEY[3]
temp[3] => whatever your code have put in it
Edit: short example
>>> LOAD_KEY = ['one', 'two', 'three', 'four']
>>> temp = LOAD_KEY
>>> x = temp[3]
>>> LOAD_KEY[3] = 'new value'
>>>
>>> LOAD_KEY[3]
'new value'
>>> temp[3]
'new value'
>>> x
'four'
In you first example, temp[3] is a string ('0x0e').
In your second example, x is an integer (14).
This is because you're converting the integer values of the LOAD_KEY list to an hexadecimal string with the following line:
LOAD_KEY[j] = hex(LOAD_KEY[j])
In order to convert a string in hexadecimal representation to an integer, use the second argument of the built-in type int to set the base to 16:
>>> int('0x0e', 16)
14

Categories

Resources