Amin Etesamian Amin Etesamian - 26 days ago 10
Python Question

Trying to figure out block data

I'm trying to write a python driver for RFID-230-2 card reader.
As the document says, in order to communicate with the device, one has to make a packet in the format below:

|STX|ADDR|LEN|CMD/STU|DATA|BCC|

STX: Communication start character, 1 byte, 0x02
ADDR: Device Addr, 1 byte, 0 can be used in any addr
LEN: Data length, 1 byte, data length of CMD/STU+DATA
CMD/STU: Command byte (Host->Reader) or Status byte (Reader->Host), 1byte
DATA: Data information, byte is not specified. Can be not existed
BCC: Section checking character, 1 byte, the XOR value of all the bytes except STX, BCC


In order to be able to read data from rfid reader, on has to set
CMD
to
0x38
and set the
DATA
as follows:
enter image description here

but I haven't been able to figure out how to create such data format.
any Help will be appreciated. This is what I have gone so far

STX = 0x02
REQUEST_FORMAT = 'bbbbbb'

def communicate(self, command, data):
address = 0x0
length = 1 + len(str(data)) + len(str(command))
bcc = address ^ length ^ command
i = struct.pack(REQUEST_FORMAT, STX, address, length, command, data, bcc)
ser = serial.Serial('/dev/ttyUSB0', 9600)
ser.write(i)
time.sleep(.1)
resp = ser.read()


The program stop at
resp = ser.read()
waiting for a resp.
This is the full doc if anyone is intrested.
http://www.tetagroup.net/products/pdf/rft230.pdf

################ EDIT 1

as the document says, in order to read a card you have to provide
Request Card Parameter
+
Card Series No.

you can get the card series no from Anti Collide command return data. but the question is, how can I put that card series no along side request card paramteres to select the card?
the card series no is 4byte data. I tried this but

communicate(0x33, [0x93, 1487824920])


File "main.py", line 21, in communicate
i = struct.pack('BBBB%sBB' % len(data), STX, address, length, command, *(data + [bcc]))
struct.error: ubyte format requires 0 <= number <= 255


1487824920 is the result of:

a = binascii.hexlify(data)
card_series = int(a, 16)

Answer

There are a couple of issues with your approach. Firstly the BCC computation should include the data bytes. Secondly, data bytes depend on which command is being used, so if there are not any present, for example with the get version command, the format needs to be modified. I suggest your first command should be to get the version number. This will help you to prove that it is working correctly:

import binascii        
import struct

STX = 0x02

def communicate(command, data=[]):
    address = 0x0
    length = 1 + len(data) 
    bcc = address ^ length ^ command

    for b in data:
        bcc ^= b

    if len(data):
        i = struct.pack('BBBB{}BB'.format(len(data)), STX, address, length, command, *(data + [bcc]))
    else:
        i = struct.pack('BBBBB'.format(len(data)), STX, address, length, command, bcc)

    # Display the command to be sent in hex 
    print binascii.b2a_hex(i)

    ser = serial.Serial('/dev/ttyUSB0', 9600)
    ser.write(i)
    time.sleep(.1)
    resp = ser.read()        
    print binascii.b2a_hex(resp)  # display response

communicate(0x21)           # Get version number
communicate(0x23, [0])      # Set baud rate of device to 9600

To pass more data bytes, add more numbers to the list.