forked from bensinober/node_rfidgeek
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rfid.js
320 lines (278 loc) · 9.77 KB
/
rfid.js
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
var sys = require('sys'),
events = require('events'),
com = require("serialport");
/*
* Constructor
*/
function Rfidgeek(options) {
// default options
options = options || {};
this.websocket = options.websocket ;
this.portname = options.portname || '/dev/ttyUSB0' ;
this.tagtype = options.tagtype || 'ISO15693' ;
this.scaninterval = options.scaninterval || 1000 ;
this.readerconfig = options.readerconfig || './univelop_500b.json' ;
this.length_to_read = options.length_to_read || 8 ;
this.bytes_per_read = options.bytes_per_read || 1 ;
logger = require('./logger');
logger.debugLevel = options.debug || 'none' ;
if(false === (this instanceof Rfidgeek)) {
return new Rfidgeek(options);
}
events.EventEmitter.call(this);
}
// Make Rfidgeek inherit EventEmitter - ability to create custom events on the fly
sys.inherits(Rfidgeek, events.EventEmitter);
/*
* exported init function
*/
Rfidgeek.prototype.init = function() {
var self = this;
if(self.websocket) { // websocket boolean
var wss = require("./wsserver.js"); // websocket server - pushes to connected clients
var ws = require("./wsclient.js"); // websocket client - sends rfid result to server
ws.connect('ws://localhost:8080/ws');
// grab websocket handle when ready
ws.on('ready', function(connection) {
socket = connection;
});
}
// read reader config file
var readerConfig = require(self.readerconfig);
// data variables
var tagData = ''; // this stores the tag data
var readData = ''; // this stores the read buffer
var start_offset = 0;
var offset = start_offset;
// Create new serialport pointer
var reader = new com.SerialPort(self.portname , {
baudRate: 115200,
dataBits: 8,
parity: 'none',
stopBits: 1,
flowControl: false,
buffersize: 1024
}, true); // this is the openImmediately flag [default is true]
/* Workflow:
Reader gets 'open' event, runs:
* emit initialize event
* turns on the scan loop
* gets tag data, quits scan loop, activates read tag loop
* read tag loop completed, reactivated scan loop
*/
// EVENT LISTENERS
reader.on('open',function() {
logger.log('info', 'Port open');
reader.on('initialize', initialize);
reader.on('initcodes', initcodes);
reader.on('scanloop', self.scanTagLoop);
reader.on('readtag', readTag);
reader.on('rfiddata', rfidData);
reader.on('readtagdata', readTagData);
// unregister tag if removed
reader.on('tagremoved', function() {
logger.log('info', 'Tag removed');
if (self.websocket) {
socket.sendUTF("Tag removed");
}
tagData = '';
});
// register new tag and
// start readloop if ISO15693 tag, else ignore
reader.on('tagfound', function( tag ) {
if (tag != tagData) { // do nothing unless new tag is found
logger.log('info', "New tag found!");
if (self.websocket) {
socket.sendUTF(tag);
}
self.emit('tagfound', tag); // emit to calling external app!
tagData = tag; // register new tag
if (self.tagtype == 'ISO15693') { // if ISO15693 tag:
stopScan(); // stop scanning for tags
readTag(tag); // start read loop
}
} else {
logger.log('info', "same tag still...");
}
});
reader.on('rfidresult', function(data) {
logger.log('info', "Full tag received: "+data);
if (self.websocket) {
socket.sendUTF(data.substring(1)); // send to websockets, skip first byte
}
self.emit('rfiddata', data.substring(1)); // emit to external app
});
reader.on('data', gotData);
reader.emit('initialize', readerConfig.initialize['init']);
reader.emit('scanloop', readerConfig.protocols[self.tagtype]);
});
// error
reader.on('error', function( msg ) {
logger.log('error', msg );
});
// close
reader.on('close', function ( err ) {
logger.log('info', 'port closed');
});
// FUNCTIONS
// initialize reader and emit initcodes event
var initialize = function(cmd, callback) {
reader.write(cmd, function(err) {
if (err){ callback(err)}
else {
logger.log('info', 'initialized reader...')
// initialized? emit initcodes
reader.emit('initcodes', readerConfig.protocols[self.tagtype]['initcodes']);
}
});
}
// run initcodes (before each tag loop)
var initcodes = function(cmd, callback) {
reader.write(cmd['register_write_request'], function(err,cb) {
if (err){ callback(err)}
else {
reader.write(cmd['agc_enable'], function(err,cb) {
if (err){ callback(err)}
else {
reader.write(cmd['am_input'], function(err,cb) {
if (err){ callback(err,cb)}
else {
logger.log('info', "ran initcodes!");
}
});
}
});
}
});
}
// Hex string to ASCII
var hex2a = function(hex) {
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
var dec2hex = function(d) {
return ("0"+(Number(d).toString(16))).slice(-2).toUpperCase()
}
// TAG LOOP FUNCTIONS - do inventory check
//var scanLoop = setInterval(function() { scanTagLoop(readerConfig.protocols[self.tagtype]) }, 1000 );
this.scanTagLoop = function (){
// run inventory check in intervals
inventory(readerConfig.protocols[self.tagtype]['inventory'], function(err) {
if (err) { logger.log('error', err) }
});
}
var stopScan = function() {
clearInterval(scanLoop);
}
// inventory command
var inventory = function(cmd, callback) {
reader.write(cmd, function(err) {
if (err) {
logger.log('error', err);
callback(err)
}
else {
logger.log('info', 'ran inventory!')
}
});
}
// END TAG LOOP FUNCTIONS
// initialize read tag loop
var readTag = function( tag, callback ) {
reader.emit('initcodes', readerConfig.protocols[self.tagtype]['initcodes']);
logger.log('debug', "found tag id: " + tag );
readData = ''; // reset data
offset = start_offset;
logger.log('debug', "sending readtagdata event, offset: "+offset );
reader.emit('readtagdata', offset);
}
// read data loop
var readTagData = function( offset, callback ) {
if(offset != self.length_to_read) {
cmd = ['01','0C','00','03','04','18','00','23', dec2hex(offset), dec2hex(self.bytes_per_read), '00', '00'].join('');
logger.log('debug', "offset: "+offset+ " tagdata cmd: " + cmd );
reader.write(cmd, function(err) {
if(err) { throw new Error (err) }
offset += self.bytes_per_read +1; // need to shift offset by 1
// do we need to delay read to next event loop?
process.nextTick(function() {
readTagData(offset);
});
});
}
}
// function rfidData, on rfiddata event
var rfidData = function( data, callback) {
var str = hex2a(data);
logger.log('debug', "rfiddata received: " + str );
readData += str;
// rfid data consumed
if (readData.length >= self.length_to_read || /575F4F4B/.test(str)) {
reader.removeListener('readtag', readTag);
reader.emit('rfidresult', readData);
// reader.emit('scanloop', readerConfig.protocols[self.tagType]);
// start new scanloop
scanLoop = setInterval(function() { self.scanTagLoop(readerConfig.protocols[self.tagtype]) }, self.scaninterval );
} else {
// continue reading
offset += self.bytes_per_read + 1; // need to shift offset with 1
reader.emit('readtagdata', offset);
}
}
// data event
var gotData = function( data ) {
logger.log('debug', 'received: '+data);
data = String(data)
if(!!data) {
// ISO15693 needs special treatment
if(self.tagtype == 'ISO15693') {
// ISO15693 NO TAG
if (/,40]/.test(data)) {
logger.log('debug', 'no tag ...');
if (tagData) { // if tagData exist then tag is considered removed
reader.emit('tagremoved')
}
}
// ISO15693 TAG
else if (/,..]/.test(data)) { // we have an inventory response! (comma and position)
var tag=data.match(/\[([0-9A-F]+)\,..\]/); // check for actual tag - strip away empty tag location ids (eg. ',40)
if (tag && tag[1]) {
reader.emit('tagfound', tag[1]);
}
}
// ISO15693 RFID DATA
else if (/\[.+\]/.test(data)) { // we have response data! (within brackets, no comma)
var rfiddata = data.match(/\[00(.+)\]/); // strip initial 00 response
logger.log('debug', "response data! "+rfiddata);
if (rfiddata) {
reader.emit('rfiddata', rfiddata[1]);
}
}
// ANY OTHER PROXIMITY TAG
}
else if (/\[.+\]/.test(data)) {
var tag = data.match(/\[(.+)\]/); // tag is anything between brackets
logger.log('debug', "tag! "+tag);
if (tag && tag[1]) {
reader.emit('tagfound', tag[1]);
}
}
}
}
}
Rfidgeek.prototype.start = function() {
var self = this;
scanLoop = setInterval(function() { self.scanTagLoop() }, self.scaninterval );
}
Rfidgeek.prototype.stop = function() {
clearInterval(scanLoop);
}
module.exports = Rfidgeek
// for browser compatibility
//if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
// module.exports = rfidGeek;
//else
// window.rfidGeek = rfidGeek;
//})();