-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathobidrfid.py
339 lines (296 loc) · 10.3 KB
/
obidrfid.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#!/usr/bin/python
# -*- coding: utf-8 -*-
import ctypes
import time
import subprocess
import platform
libfetcp = ctypes.CDLL('libfetcp.so')
libfeisc = ctypes.CDLL('libfeisc.so')
# default port
DEFAULT_PORT = 10001
def ping(ip, timeout=2):
'''
Test if the antenna is reachable, to abort before the default 30s timeout
default to 2s
'''
try:
subprocess.check_output("ping -{} 1 {} -W {}".format('n' if platform.system().lower()=="windows" else 'c', ip, timeout), shell=True)
except subprocess.CalledProcessError:
return False
return True
def rfid_connect(ip, port=DEFAULT_PORT):
'''
Connect to the RFID antenna
'''
if ping(ip):
port_handle = libfetcp.FETCP_Connect(ip.encode(), port)
if (port_handle > 0):
print('Port connected...')
reader_handle = libfeisc.FEISC_NewReader(port_handle)
if (reader_handle > 0):
back = libfeisc.FEISC_SetReaderPara(
reader_handle,
ctypes.c_char_p(b'FrameSupport'),
ctypes.c_char_p(b'Advanced')
)
print('Reader initialized, set param {}'.format(back))
return reader_handle
else:
print('--- ! Reader can not be initializer, error {}'.format(reader_handle))
else:
print('--- ! Connection failed, error {}'.format(port_handle))
return None
def rfid_read(reader):
'''
Read tags
First send a RF Reset and wait 5ms
'''
sReqData = (ctypes.c_ubyte * 64)()
sReqData[0] = 0x01
sReqData[1] = 0x00
iReqLen = ctypes.c_int(2)
sRespData = (ctypes.c_ubyte * 1024)()
iRespLen = ctypes.c_int()
reader_read = libfeisc.FEISC_0xB0_ISOCmd
reader_read.argtypes = [
ctypes.c_int,
ctypes.c_ubyte,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_int,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.POINTER(ctypes.c_int),
ctypes.c_int,
]
# first a software reset
rfid_reader_software_reset(reader)
time.sleep(.005)
back = libfeisc.FEISC_0xB0_ISOCmd(
reader, # reader ID
ctypes.c_ubyte(255), # bus addr, I don't think that's relevant for TCP/IP..
sReqData, # request data, unsigned char *
iReqLen,
sRespData,
ctypes.byref(iRespLen),
2
)
# return values
transponders = []
if back == 0:
if iRespLen.value > 0:
result = sRespData[2:iRespLen.value]
# split in sizes of 20 elements
size = 20
transponders_bytes = [result[i:i + size] for i in range(len(result))[::size]]
for t in transponders_bytes:
# first 2 is TR-TYPE
tr_type = bytearray(t[:2]).decode('utf8')
dsfid = bytearray(t[2:4]).decode('utf8')
iid = bytearray(t[4:]).decode('utf8')
transponders.append({
'tr_type': tr_type,
'dsfid': dsfid,
'iid': iid,
})
elif back > 1:
print('Status: {}'.format(rfid_status_text(back)))
elif back < 0:
print('Error: {}'.format(rfid_error_text(back)))
return transponders
def rfid_reader_info(reader):
'''
Print reader info
'''
ucInfo = (ctypes.c_ubyte * 300)()
reader_info = libfeisc.FEISC_0x66_ReaderInfo
reader_info.argtypes = [
ctypes.c_int,
ctypes.c_ubyte,
ctypes.c_ubyte,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_int
]
back = reader_info(reader, ctypes.c_ubyte(255), 0x00, ucInfo, 0)
if (back == 0):
print('Reader: {}'.format(ucInfo[4]))
elif (back > 0):
print('--- ! Reader info status {}'.format(rfid_status_text(back)))
else:
print('--- ! Reader info error {}'.format(back))
print(rfid_error_text(ctypes.c_int(back)))
def rfid_reader_lan_configuration_read(reader):
'''
Print reader lan configuration,
If successfull, returns the 14 byts configuration
to use with the write function below
'''
ucConfBlock = (ctypes.c_ubyte * 14)()
reader_conf = libfeisc.FEISC_0x80_ReadConfBlock
reader_conf.argtypes = [
ctypes.c_int,
ctypes.c_ubyte,
ctypes.c_ubyte,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_int
]
# read from configuration block 168. This is actually the block 40
# prepended with the bytes 1 and 0 to read from the EEPROM
back = reader_conf(reader, ctypes.c_ubyte(255), 168, ucConfBlock, 0)
if (back == 0):
return ucConfBlock
elif (back > 0):
print('--- ! Reader conf status {}'.format(rfid_status_text(back)))
else:
print('--- ! Reader conf error {}'.format(back))
print(rfid_error_text(ctypes.c_int(back)))
def rfid_reader_lan_configuration_write(reader, conf, ip):
'''
Write LAN reader configuration,
input is the reader handler, the 14 bytes configuration block
as obtained from the 'read' function above
and an array with the new ip, e.g. [192, 168, 142, 12]
This will be written to the EPPROM and requires a SystemReset
to be saved in the configuration.
'''
if len(ip) != 4:
print('Invalid ip, expected array of 4 numbers.')
return False
reader_conf = libfeisc.FEISC_0x81_WriteConfBlock
reader_conf.argtypes = [
ctypes.c_int,
ctypes.c_ubyte,
ctypes.c_ubyte,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_int
]
conf[0] = ip[0]
conf[1] = ip[1]
conf[2] = ip[2]
conf[3] = ip[3]
back = reader_conf(reader, ctypes.c_ubyte(255), 168, conf, 0)
if (back == 0):
return True
elif (back > 0):
print('--- ! Reader conf status {}'.format(rfid_status_text(back)))
return False
else:
print('--- ! Reader conf error {}'.format(back))
print(rfid_error_text(ctypes.c_int(back)))
return False
def rfid_reader_system_reset(reader):
'''
Perform a system reset (0x64) and save the configuration
set in the EPPROM
'''
back = libfeisc.FEISC_0x64_SystemReset(reader, ctypes.c_ubyte(255))
if (back == 0):
return True
elif (back > 0):
print('--- ! Reader reset status {}'.format(rfid_status_text(back)))
return False
else:
print('--- ! Reader reset error {}'.format(back))
print(rfid_error_text(ctypes.c_int(back)))
return False
def rfid_reader_software_reset(reader):
'''
Perform a software reset (0x69)
'''
back = libfeisc.FEISC_0x69_RFReset(reader, ctypes.c_ubyte(255))
if (back == 0):
return True
elif (back > 0):
print('--- ! Reader reset status {}'.format(rfid_status_text(back)))
return False
else:
print('--- ! Reader reset error {}'.format(back))
print(rfid_error_text(ctypes.c_int(back)))
return False
def rfid_error_text(error_code):
'''
Print text for error code
'''
ucInfo = ctypes.create_string_buffer(300)
libfeisc.FEISC_GetErrorText(error_code, ucInfo)
return ucInfo.value
def rfid_status_text(status_code):
'''
Print text for status code
'''
ucInfo = ctypes.create_string_buffer(300)
print('## checking status {}'.format(status_code))
ucStatus = ctypes.c_ubyte(status_code)
back = libfeisc.FEISC_GetStatusText(ucStatus, ucInfo)
if (back == 0):
return ucInfo.value
else:
print('Status check error, return value: {}'.format(back))
print('{}'.format(rfid_error_text(back)))
return None
def validate_ip(s):
a = s.split('.')
if len(a) != 4:
return False
for x in a:
if not x.isdigit():
return False
i = int(x)
if i < 0 or i > 255:
return False
return True
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("command", help="Command, 'config' to configure the reader ip address or 'read' to start reading RFID tags.", choices=['config', 'read'])
parser.add_argument("--ip", help="the IP address of the reader.")
parser.add_argument("--set-ip", help="the IP address to configure.")
args = parser.parse_args()
if args.command == 'config':
print('Configuration')
ip = args.ip
set_ip = args.set_ip
if ip is None or set_ip is None:
print('Invalid usage, use --ip and --set-ip to change the IP configuration of the reader.')
quit()
# validate ip... basic
if not validate_ip(ip):
print('Invalid reader IP address {}'.format(ip))
quit()
if not validate_ip(set_ip):
print('Invalid IP address {}'.format(set_ip))
quit()
# all good, connect to the reader
print('Connecting to IP address {}'.format(ip))
reader = rfid_connect(ip)
conf = rfid_reader_lan_configuration_read(reader)
print('Reader {} ready.'.format(reader))
print('Reading reader info...')
rfid_reader_info(reader)
print('Changing IP address to {}'.format(set_ip))
rfid_reader_lan_configuration_write(reader, conf, [int(x) for x in set_ip.split('.')])
rfid_reader_system_reset(reader)
print('All set, the IP address of the reader is now {}'.format(set_ip))
quit()
if args.command == 'read':
ip = args.ip
if ip is None or not validate_ip(ip):
print('Invalid reader IP address.')
quit()
reader = rfid_connect(ip)
print('Reader {} ready.'.format(reader))
print('Reading reader info...')
rfid_reader_info(reader)
print('Press Ctrl-C to exit.')
print('======== READING TAGS ============')
try:
while(True):
found = rfid_read(reader)
if (len(found)):
print('----------------------')
print('Found {} transponders:'.format(len(found)))
for f in found:
print('TR_TYPE = {} | DSFID = {} | IID = {}'.format(f.get('tr_type'), f.get('dsfid'), f.get('iid')))
else:
print('No transponders in range.')
time.sleep(.25)
except KeyboardInterrupt:
print('goodbye')