Skip to content

Commit e26d55b

Browse files
author
Rob Bultman
committed
Adding utility that sets the UUID of ChillHub attachments.
1 parent 74b4de1 commit e26d55b

File tree

1 file changed

+324
-0
lines changed

1 file changed

+324
-0
lines changed

set-device-uuid.js

Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
var serial = require('serialport');
2+
var fs = require('fs');
3+
var stream = require('binary-stream');
4+
var sets = require('simplesets');
5+
var commons = require('./commons');
6+
var parsers = require('./parsing');
7+
var uuid = require('uuid-v4');
8+
9+
function ChillhubDevice(ttyPath) {
10+
var self = this;
11+
12+
var ESC = 0xfe;
13+
var STX = 0xff;
14+
self.deviceType = '';
15+
self.UUID = '';
16+
self.buf = [];
17+
self.msgBody = [];
18+
self.resources = {};
19+
self.registered = false;
20+
self.newUUID = '';
21+
22+
self.uid = ttyPath;
23+
self.tty = new serial.SerialPort('/dev/'+ttyPath, {
24+
baudrate: 115200,
25+
disconnectedCallback: function(err) {
26+
if (err) {
27+
console.log('error in disconnectedCallback');
28+
console.log(err);
29+
console.log('UUID is ' + self.UUID);
30+
}
31+
}
32+
});
33+
34+
self.tty.open(function(err) {
35+
if (err) {
36+
console.log('error opening serial port');
37+
console.log(err);
38+
return;
39+
}
40+
41+
self.tty.flush(function(err) {
42+
if (err) {
43+
console.log("Error flushing the serial port input buffer.");
44+
console.log(err);
45+
return;
46+
}
47+
48+
console.log("Serial port input buffer flushed.");
49+
50+
self.scanForStx = function() {
51+
while (self.buf.length > 0) {
52+
var c = self.buf.shift();
53+
if (c == STX) {
54+
self.commHandler = self.waitForLength;
55+
self.waitForLength();
56+
break;
57+
}
58+
}
59+
}
60+
61+
self.waitForLength = function() {
62+
if (self.buf.length > 1) {
63+
if (self.buf[0] == ESC) {
64+
self.buf.shift();
65+
}
66+
self.msgLen = self.buf.shift();
67+
self.bufIndex = 0;
68+
self.msgBody.length = 0;
69+
self.commHandler = self.waitForMessage;
70+
self.waitForMessage();
71+
}
72+
}
73+
74+
self.waitForMessage = function() {
75+
while (self.buf.length > self.bufIndex) {
76+
if (self.buf[self.bufIndex] == ESC) {
77+
if ((self.buf.length - self.bufIndex) > 1) {
78+
self.bufIndex++;
79+
} else {
80+
return;
81+
}
82+
}
83+
self.msgBody.push(self.buf[self.bufIndex++]);
84+
// wait for message plus sent checksum
85+
if (self.msgBody.length >= self.msgLen+2) {
86+
self.checkMessage();
87+
}
88+
}
89+
}
90+
91+
self.checkMessage= function() {
92+
var csSent = self.msgBody.pop() + self.msgBody.pop()*256;
93+
var cs = 42;
94+
for (var i = 0; i<self.msgBody.length; i++) {
95+
cs += self.msgBody[i];
96+
}
97+
if (cs == csSent) {
98+
// remove message from input buffer
99+
self.buf.splice(0, self.bufIndex);
100+
self.msgBody.shift();
101+
routeIncomingMessage(self.msgBody);
102+
} else {
103+
console.log("Check sum error.");
104+
self.buf.shift();
105+
}
106+
self.commHandler = self.scanForStx;
107+
self.scanForStx();
108+
}
109+
110+
self.commHandler = self.scanForStx;
111+
112+
self.tty.on('data', function(data) {
113+
// network byte order is big endian... let's go with that
114+
self.buf = self.buf.concat((new stream.Reader(data, stream.BIG_ENDIAN)).readBytes(data.length));
115+
self.commHandler();
116+
return;
117+
118+
while(self.buf.length > self.buf[0]) {
119+
msg = self.buf.slice(1,self.buf[0]+1);
120+
self.buf = self.buf.slice(self.buf[0]+1,self.buf.length);
121+
if (msg.length > 0) {
122+
routeIncomingMessage(msg);
123+
}
124+
}
125+
});
126+
self.tty.on('error', function(err) {
127+
console.log('serial error:');
128+
console.log(err);
129+
});
130+
self.tty.on('disconnect', function(err) {
131+
console.log('error disconnecting?');
132+
console.log(err);
133+
});
134+
135+
self.send = function(data) {
136+
// parse data into the format that usb devices expect and transmit it
137+
var dataBytes = parsers.parseJsonToStream(data);
138+
var writer = new stream.Writer(dataBytes.length+1, stream.BIG_ENDIAN);
139+
writer.writeUInt8(dataBytes.length);
140+
writer.writeBytes(dataBytes);
141+
var buf = writer.toArray();
142+
var outBuf = [];
143+
144+
if (buf.length > 255) {
145+
console.log("ERROR: Cannot send a message longer than 255 bytes!!!");
146+
return;
147+
}
148+
149+
var encodeByteToArray = function(b, a) {
150+
if (b == ESC || b == STX) {
151+
a.push(ESC);
152+
}
153+
a.push(b);
154+
}
155+
156+
// Take message body, wrap in STX and checksum, add escapes as needed.
157+
outBuf.push(STX);
158+
encodeByteToArray(buf.length, outBuf);
159+
var cs = 42;
160+
for (var i=0; i<buf.length; i++) {
161+
encodeByteToArray(buf[i], outBuf);
162+
cs += buf[i];
163+
}
164+
encodeByteToArray(commons.getNibble(cs, 2), outBuf);
165+
encodeByteToArray(commons.getNibble(cs, 1), outBuf);
166+
self.tty.write(outBuf, function(err) {
167+
if (err) {
168+
console.log('error writing to serial');
169+
console.log(err);
170+
}
171+
});
172+
return;
173+
174+
writer.writeUInt8(dataBytes.length);
175+
writer.writeBytes(dataBytes);
176+
console.log("WRITER in send",writer.toArray());
177+
self.tty.write(writer.toArray(), function(err) {
178+
if (err) {
179+
console.log('error writing to serial');
180+
console.log(err);
181+
}
182+
});
183+
};
184+
185+
if (self.onOpenCallback) {
186+
self.onOpenCallback();
187+
}
188+
});
189+
});
190+
191+
function setDeviceUUID() {
192+
self.send({
193+
type: 0x0c,
194+
content: self.newUUID
195+
});
196+
// wait a little, then request UUID again.
197+
setTimeout(function() {
198+
self.send({
199+
type: 0x08,
200+
content: {
201+
numericType: 'U8',
202+
numericValue: 1
203+
}
204+
});
205+
}, 2000);
206+
}
207+
208+
function startSetUUIDProcess() {
209+
self.newUUID = uuid();
210+
console.log("Attempting to set UUID to: " + self.newUUID);
211+
setDeviceUUID();
212+
}
213+
214+
function routeIncomingMessage(data) {
215+
// parse into whatever form and then send it along
216+
var jsonData = parsers.parseStreamToJson(data);
217+
218+
switch (jsonData.type) {
219+
case 0x00:
220+
if (self.registered == false) {
221+
if (jsonData.content === undefined) {
222+
console.log("Content is missing from message type 0x00 received from attachment.");
223+
return;
224+
}
225+
self.deviceType = jsonData.content[0];
226+
self.UUID = jsonData.content[1];
227+
console.log('Found device "'+self.deviceType+'" with UUID '+ self.UUID + '!');
228+
229+
self.registered = true;
230+
startSetUUIDProcess();
231+
} else {
232+
// we were registered, see if the set UUID process worked.
233+
if (jsonData.content === undefined) {
234+
console.log("Content is missing from message type 0x00 received from attachment.");
235+
return;
236+
}
237+
self.deviceType = jsonData.content[0];
238+
self.UUID = jsonData.content[1];
239+
if (self.UUID === self.newUUID) {
240+
console.log("New UUID successfully set.");
241+
process.exit(0);
242+
} else {
243+
console.log("ERROR: Unable to set the UUID on the device.");
244+
console.log("The device sent a UUID of " + self.UUID);
245+
process.exit(1);
246+
}
247+
}
248+
break;
249+
}
250+
}
251+
252+
self.cleanup = function() {
253+
};
254+
255+
self.registerOpenCallback = function(func) {
256+
self.onOpenCallback = func;
257+
}
258+
259+
self.sendRegistrationRequest = function sendRegistrationRequest () {
260+
self.send({
261+
type: 0x08,
262+
content: {
263+
numericType: 'U8',
264+
numericValue: 1
265+
}
266+
});
267+
}
268+
269+
self.checkForDeviceRegistration = function checkForDeviceRegistration() {
270+
if (!self.registered) {
271+
console.log("Device was not properly registered, requesting registration info again.");
272+
self.sendRegistrationRequest();
273+
setTimeout(self.checkForDeviceRegistration, 5000);
274+
}
275+
}
276+
277+
setTimeout(self.checkForDeviceRegistration, 5000);
278+
}
279+
280+
var devices = {};
281+
282+
if (process.platform === 'darwin') {
283+
console.log("We are running on a Mac, look for tty.usbmodem devices.");
284+
var filePattern = /^tty.usbmodem[0-9]+$/;
285+
} else {
286+
var filePattern = /^ttyACM[0-9]{1,2}$/;
287+
}
288+
289+
fs.readdir('/dev/', function(err, files) {
290+
files = files.filter(function(file) {
291+
return filePattern.test(file);
292+
});
293+
294+
files.forEach(function(filename) {
295+
console.log('registering new USB device ' + filename);
296+
devices[filename] = new ChillhubDevice(filename);
297+
(function() {
298+
var what = filename;
299+
devices[filename].registerOpenCallback (function() {
300+
devices[what].sendRegistrationRequest();
301+
});
302+
})();
303+
});
304+
});
305+
306+
// watch for new devices
307+
fs.watch('/dev/', function(event, filename) {
308+
console.log("Saw a change in dev.");
309+
if (!filePattern.test(filename))
310+
return;
311+
312+
fs.exists('/dev/'+filename, function (exists) {
313+
if (devices[filename] && !exists) {
314+
console.log('unregistering USB device ' + filename);
315+
devices[filename].cleanup();
316+
delete devices[filename];
317+
}
318+
else if (!devices[filename] && exists) {
319+
console.log('registering new USB device ' + filename);
320+
devices[filename] = new ChillhubDevice(filename);
321+
}
322+
});
323+
});
324+

0 commit comments

Comments
 (0)