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
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]))
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 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.
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.
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