UNPKG

50.2 kBJavaScriptView Raw
1/*
2Configuration:
3Connect a BLE port to port A on the Tessel.
4Place any BLE peripheral within a few feet of the Tessel.
5
6Missing Tests:
7The ability to test whether _allowDuplicates works on scanning. Would need more BLE peripherals
8in setup
9*/
10// Test frameworks
11var tessel = require('tessel');
12var blePort = tessel.port('a');
13var bleDriver = require('../');
14var async = require('async');
15
16// Used for bluetooth tests
17var bluetooth;
18var peripheral;
19
20var slaveBPort = tessel.port('b');
21var slaveDPort = tessel.port('c');
22
23var slaveB;
24var slaveD;
25
26// Indication LEDs
27var passedLED = tessel.led(1);
28var failedLED = tessel.led(2);
29var failed = false;
30var failTimeout;
31
32console.log("Setting up tests...");
33
34bluetooth = bleDriver.use(blePort, function(err) {
35 if (err) {
36 return failModule(err);
37 }
38 else {
39 slaveB = bleDriver.use(slaveBPort, function(err) {
40 if (err) {
41 return failModule(err)
42 }
43 else {
44 beginTesting();
45 }
46 })
47 }
48});
49
50function beginTesting() {
51 console.log("Commencing tests.");
52 async.waterfall([
53 // portTest,
54 // , scanTest
55 // , filterTest
56 // , connectTest
57 // , serviceDiscoveryTest
58 // , characteristicDiscoveryTest
59 // , characteristicServiceDiscoveryTest
60 // , discoverAllTest
61 // , readCharacteristicTest
62 // , writeCharacteristicTest
63 writeLongCharacteristicTest
64 ],
65
66 function(err) {
67 if (err) {
68 return failModule(err);
69 }
70 else {
71 return passModule();
72 }
73 });
74 // portTest(function() {
75 // scanTest(function() {
76 // filterTest(function() {
77 // connectTest(function() {
78 // serviceDiscoveryTest(function() {
79 // characteristicDiscoveryTest(function() {
80 // characteristicServiceDiscoveryTest(function() {
81 // discoverAllTest(passModule);
82 // readCharacteristicTest(passModule);
83 // writeCharacteristicTest(passModule);
84 // writeLongCharacteristicTest(passModule);
85 // discoverAllDescriptorsTest(passModule);
86 // discoverCharacteristicDescriptorTest(passModule);
87 // discoverAllAttributesTest(passModule);
88 // readDescriptorTest(passModule);
89 // writeDescriptorTest(passModule);
90 // notificationTest(passModule);
91 // indicationTest(passModule);
92 // signalStrengthTest(passModule);
93 // systemCommandsTest(passModule);
94 // advertisingTest(passModule);
95 // advertisementDataTest(passModule);
96 // readFirmwareTest(passModule);
97 // maxNumberValueTest(passModule)
98 // readWriteValueTest(passModule);
99 // readWriteLongValueTest(passModule);
100 // remoteWriteTest(passModule);
101 // remoteStatusUpdateTest(passModule);
102 // ADCTest(passModule);
103 // i2cTest(passModule);
104 // gpioReadTest(passModule);
105 // gpioWriteTest(function() {
106 // gpioReadTest(passModule);
107 // })
108 // gpioWatchTest(passModule);
109 // gpioWatchChangeTest(passModule);
110 // bondingTest(passModule);
111 // });
112 // });
113 // });
114 // });
115 // });
116 // });
117}
118
119// function bondingTest(callback) {
120// bluetooth.setBondable(true, function(err) {
121// if (err) {
122// return failModule("Setting to bondable", err);
123// }
124// else {
125// console.log("Set to bondable successful...");
126// connectToMoosh(function(moosh) {
127// bluetooth.on('disconnect', function(peripheral, reason) {
128// console.log(peripheral.toString() + "disconnected because" + reason);
129// });
130// bluetooth.startEncryption(moosh, function(err) {
131// if (err) {
132// return failModule("Starting encryption", err);
133// }
134// else {
135// console.log("Successfully encrypted connection!");
136// bluetooth.getBonds(function(err, bonds) {
137// if (err) {
138// return failModule("Retrieving bonds", err);
139// }
140// else {
141// console.log("Got these bonds: ", bonds);
142// }
143// });
144// }
145// });
146// });
147// }
148// })
149// }
150//
151// function gpioWatchChangeTest(callback) {
152// var gpio = bluetooth.gpio("p0_2");
153// var trig = tessel.port('b').gpio(2).output();
154// trig.high();
155// gpio.watch('change', function(err, timestamp, type) {
156// console.log("Got this int", err, timestamp, type);
157// if (err) {
158// return failModule("Error setting watch on gpio", err);
159// }
160// else {
161// gpio.unwatch('change', function(err) {
162// if (err) {
163// return failModule("Error removing watch", err);
164// }
165// var timeout = setTimeout(function() {
166// gpio.removeAllListeners();
167// console.log("GPIO Watch Test Passed!");
168// callback && callback();
169// }, 2000);
170// gpio.on('change', function(err, timestamp, type) {
171// console.log("Somehow it was hit!", err, timestamp, type);
172// clearTimeout(timeout);
173//
174// return failModule("Pin Watch interrupt fired after unwatch.");
175// });
176// trig.high();
177// });
178// }
179// });
180// setTimeout(function() {
181// trig.low();
182// }, 1000);
183// }
184//
185// function gpioWatchTest(callback) {
186// var gpio = bluetooth.gpio("p0_2");
187// var trig = tessel.port('b').gpio(2).output();
188// gpio.watch('rise', function(err, timestamp, type) {
189// console.log("Got this", err, timestamp, type);
190// if (err) {
191// return failModule("Error setting watch on gpio", err);
192// }
193// else {
194// gpio.unwatch('rise', function(err) {
195// if (err) {
196// return failModule("Error removing watch", err);
197// }
198// var timeout = setTimeout(function() {
199// gpio.removeAllListeners();
200// console.log("GPIO Watch Test Passed!");
201// callback && callback();
202// }, 2000);
203// gpio.on('rise', function() {
204// clearTimeout(timeout);
205//
206// return failModule("Pin Watch interrupt fired after unwatch.");
207// });
208// });
209// }
210// });
211// setTimeout(function() {
212// trig.high();
213// }, 1000);
214// }
215//
216// function gpioWriteTest(callback) {
217// var gpio = bluetooth.gpio("p0_2");
218// var reader = tessel.port('b').gpio(2).input();
219// gpio.setOutput(true, function(err) {
220// if (err) {
221// return failModule ("Setting GPIO as output");
222// }
223// else {
224// var value = reader.readSync();
225// if (value != 1) {
226// return failModule("Writing correct GPIO value");
227// }
228// else {
229// gpio.write(0, function(err) {
230// if (err) {
231// return failModule("Writing to gpio", err);
232// }
233// value = reader.readSync();
234// if (value != 0) {
235// return failModule("Writing correct GPIO value again...");
236// }
237// else {
238// console.log("GPIO Writing Test Passed.");
239// callback && callback();
240// }
241// })
242// }
243//
244// }
245// });
246// }
247// // This requires "p0_2" to be connected to port b, gpio 2
248// function gpioReadTest(callback) {
249// var gpio = bluetooth.gpio("p0_2");
250// var writer = tessel.port('b').gpio(2).output();
251// writer.high();
252// gpio.read(function(err, value) {
253// if (err) {
254// return failModule("Reading gpio", err);
255// }
256// else if (value != 1) {
257// return failModule("Reading correct gpio value");
258// }
259// else {
260// writer.low();
261// gpio.read(function(err, value) {
262// if (err) {
263// return failModule("Reading GPIO again", err);
264// }
265// else if (value != 0 ) {
266// return failModule("Reading correct gpio value the second time");
267// }
268// else {
269// console.log("GPIO Read Test Passed");
270// callback && callback();
271// }
272// });
273// }
274// });
275// }
276//
277// // This currently requires a Seeeduino programmed
278// // to send an 11 char string back (listening on address 0x40)
279// function i2cTest(callback) {
280// var testString = "Hell yeah!";
281// var master = bluetooth.I2C(0x40);
282// master.transfer(testString, testString.length, function(err, rx) {
283// if (err) {
284// failModule("Transferring i2c data", err);
285// }
286// else if (testString.length != rx.length) {
287// failModule("Receiving correct number of bytes");
288// }
289// else {
290// console.log("I2C test passed.");
291// callback && callback();
292// }
293// });
294// }
295//
296// function ADCTest(callback) {
297// var adcread = tessel.port('b').gpio(3).output();
298// adcread.high();
299// bluetooth.readADC(function(err, value) {
300// adcread.low();
301// bluetooth.readADC(function(err, value) {
302// callback && callback();
303// });
304// });
305// }
306//
307// function remoteStatusUpdateTest(callback) {
308// bluetooth.startAdvertising(function(err) {
309// if (err) {
310// return failModule("Beginning Advertisement", err);
311// }
312// bluetooth.once('connect', function(connection) {
313// console.log("Connected!", connection);
314// bluetooth.on('remoteNotification', function(connection, index) {
315// console.log("Master watching notifications!", connection, index);
316// bluetooth.once('disconnect', function(connection, reason) {
317// console.log("Disconnected!", connection, reason);
318// })
319// });
320// })
321// })
322// }
323// function remoteWriteTest(callback) {
324// bluetooth.startAdvertising(function(err) {
325// if (err) {
326// return failModule("Beginning Advertisement", err);
327// }
328// bluetooth.once('connect', function(connection) {
329// console.log("Connected!", connection);
330// bluetooth.on('remoteWrite', function(connection, handle, value) {
331// console.log("Value was written!", connection, handle, value.toString());
332// bluetooth.once('disconnect', function(connection, reason) {
333// console.log("Disconnected!", connection, reason);
334// })
335// });
336// })
337// })
338// }
339//
340// function readWriteLongValueTest(callback) {
341// var testPhrase = "Alpha Bar Cappa Foo Something Super Long"
342// bluetooth.writeLocalValue(0, testPhrase, function(err) {
343// if (err) {
344// return failModule("Writing local value", err);
345// }
346// else {
347// bluetooth.readLocalValue(0, 0, function(err, value) {
348// var repeat = value;
349// if (err) {
350// return failModule("Reading local value", err);
351// }
352// else if (value.toString() == testPhrase) {
353// return failModule("Comparing written with long read local");
354// }
355// else {
356// bluetooth.readLocalValue(0, 32, function(err, value) {
357// repeat = Buffer.concat([repeat, value]);
358// if (err) {
359// return failModule("Reading local value", err);
360// }
361// else if (repeat.toString() != testPhrase) {
362// return failModule("Comparing written with long read local");
363// }
364// else {
365// console.log("Read Write Test Complete");
366// callback && callback()
367// }
368// });
369// }
370// });
371// }
372// })
373// }
374//
375// function readWriteValueTest(callback) {
376// var testPhrase = "Alpha Bar Cappa Foo"
377// bluetooth.writeLocalValue(0, testPhrase, function(err) {
378// if (err) {
379// return failModule("Writing local value", err);
380// }
381// else {
382// bluetooth.readLocalValue(0, 0, function(err, value) {
383// if (err) {
384// return failModule("Reading local value", err);
385// }
386// else if (value.toString() != testPhrase) {
387// return failModule("Comparing written with read local");
388// }
389// else {
390// console.log("Read Write Test Complete");
391// callback && callback()
392// }
393// });
394// }
395// })
396// }
397//
398// function readFirmwareTest(callback) {
399// bluetooth.getFirmwareVersion(function(err, version) {
400// if (err) {
401// return failModule("Reading firmware", err);
402// }
403// console.log("Got this version", version);
404//
405// });
406// }
407//
408// function maxNumberValueTest(callback) {
409// bluetooth.maxNumValues(function(err, max) {
410// if (err) {
411// failModule("Getting max values", err);
412// }
413// if (max <= 0) {
414// failModule("Getting actual max value");
415// }
416// else {
417// console.log("Max Num Values Test Passed.");
418// callback && callback();
419// }
420// });
421// }
422//
423// // Can't make this test until we use multiple modules
424// function advertisementDataTest(callback) {
425// }
426//
427//
428// function advertisingTest(callback) {
429// bluetooth.once('startAdvertising', function() {
430// console.log("Started advertising");
431// bluetooth.once('connect', function() {
432// bluetooth.once('disconnect', function(reason) {
433// console.log("Disconnected from master...");
434// bluetooth.once('stopAdvertising', function(err) {
435// if (err) {
436// return failModule("Stopping advertisement event", err);
437// }
438// console.log("Advertising Test Passed.");
439// bluetooth.reset(callback);
440// });
441// bluetooth.stopAdvertising(function(err) {
442// if (err) {
443// return failModule("Stopping advertisement", err);
444// }
445// });
446// });
447// });
448// });
449// bluetooth.startAdvertising(function(err) {
450// if (err) {
451// return failModule("Starting to advertise", err);
452// }
453// });
454// }
455// function systemCommandsTest(callback) {
456// bluetooth.getBluetoothAddress(function(err, address) {
457// if (err) {
458// return failModule("Retrieving address", err);
459// }
460// bluetooth.getMaxConnections(function(err, max) {
461// if (err) {
462// return failModule("Retrieving max connections", err);
463// }
464// console.log("System Commands Test Passed.");
465// });
466// })
467// }
468//
469// function signalStrengthTest(callback) {
470// connectToMoosh(function(moosh) {
471// moosh.updateRssi(function(err, rssi) {
472// if (err) {
473// return failModule("Getting signal strength", err);
474// }
475// if (rssi > 0) {
476// return failModule("Invalid Rssi value" + rssi.toString());
477// }
478// moosh.disconnect(callback);
479// });
480// });
481// }
482//
483// function indicationTest(callback) {
484// connectToMoosh(function(moosh) {
485// console.log("Connected to moosh. Searching for chars...");
486// moosh.discoverCharacteristics(['ffa2', 'ffa6'], function(err, characteristics) {
487// if (err) {
488// return failModule("Discovering meter settings and sample chars", err);
489// }
490// else {
491// console.log("Got these: ", characteristics.toString());
492// if (characteristics.length == 2) {
493// var meterSettings = characteristics[1];
494// var meterSample = characteristics[0];
495// meterSample.once('indication', function(value) {
496// console.log("Got indications of this value!", value);
497// meterSample.stopNotifications(function(err) {
498// if (err) {
499// return failModule("Stopping indications", err);
500// console.log("Stopped indications...");
501// }
502//
503// });
504// });
505// console.log("Starting indications...");
506// meterSample.confirmIndication(function(err) {
507// if (err) {
508// return failModule("Confirming indication...", err);
509// }
510// console.log("Confirmation sent");
511// });
512// // meterSample.startIndications(function(err) {
513// // if (err) {
514// // failModule("Starting indications", err);
515// // }
516// // console.log("Starting meter sampling...")
517// // meterSettings.write(new Buffer([3, 2, 0, 0, 0, 0, 0, 0, 23]), function(err, written) {
518// // if (err) {
519// // return failModule("Writing to characteristic in indication test", err);
520// // }
521// // else {
522// // console.log("Meter is sampling...");
523// // }
524// // });
525// // });
526// }
527// }
528// });
529// });
530// }
531//
532// function notificationTest(callback) {
533// connectToMoosh(function(moosh) {
534// console.log("Connected to moosh. Searching for chars...");
535// moosh.discoverCharacteristics(['ffa2', 'ffa6'], function(err, characteristics) {
536// if (err) {
537// return failModule("Discovering meter settings and sample chars", err);
538// }
539// else {
540// if (characteristics.length == 2) {
541// var meterSettings = characteristics[1];
542// var meterSample = characteristics[0];
543// meterSample.once('notification', function(value) {
544// console.log("Got notified of this value!", value);
545// meterSample.stopNotifications(function(err) {
546// if (err) {
547// return failModule("Stopping notifications", err);
548// }
549// console.log("Stopped notifications...");
550// });
551// });
552// console.log("Starting notifications...");
553// meterSample.startNotifications(function(err) {
554// if (err) {
555// failModule("Starting notifications", err);
556// }
557// console.log("Starting meter sampling...")
558// meterSettings.write(new Buffer([3, 2, 0, 0, 0, 0, 0, 0, 23]), function(err, written) {
559// if (err) {
560// return failModule("Writing to characteristic in notification test", err);
561// }
562// else {
563// console.log("Meter is sampling...");
564// }
565// });
566// });
567// }
568// }
569// });
570// });
571// }
572// function writeDescriptorTest(callback) {
573// connectToMoosh(function(moosh) {
574// moosh.discoverCharacteristics(['ffa2'], function(err, characteristics) {
575// if (err) {
576// return failModule("Discovering characteristic in write descriptor test", err);
577// }
578// else {
579// if (characteristics.length == 1) {
580// characteristics[0].discoverAllDescriptors(function(err, descriptors) {
581// if (err) {
582// return failModule("Writing characteristic descriptor", err);
583// }
584// var gate = 0;
585// if (descriptors.length) {
586// bluetooth.once('descriptorWrite', function(descriptor, value) {
587// gate++;
588// });
589// moosh.once('descriptorWrite', function(descriptor, value) {
590// gate++;
591// });
592// descriptors[0].once('descriptorWrite', function(value) {
593//
594// if (gate === 3) {
595// console.log("Descriptor Write Test Passed.")
596// // bluetooth.reset(callback);
597// }
598// });
599// descriptors[0].write(new Buffer([0x1, 0x0]), function(err, value) {
600// if (err) {
601// return failModule("writing descriptor", err);
602// }
603// else {
604// gate++;
605// }
606// });
607// }
608// else {
609// return failModule("Reading correct number of descriptors");
610// }
611// });
612// }
613// else {
614// return failModule("Reading correct number of characteristics");
615// }
616// }
617// });
618// });
619// }
620// function readDescriptorTest(callback) {
621// connectToMoosh(function(moosh) {
622//
623// moosh.discoverCharacteristics(['ffa2'], function(err, characteristics) {
624// if (err) {
625// return failModule("Discovering characteristic in read descriptor test", err);
626// }
627// else {
628// if (characteristics.length == 1) {
629// characteristics[0].discoverAllDescriptors(function(err, descriptors) {
630// if (err) {
631// return failModule("Reading characteristic descriptor", err);
632// }
633// var gate = 0;
634// if (descriptors.length) {
635// bluetooth.once('descriptorRead', function(descriptor, value) {
636// gate++;
637// });
638// moosh.once('descriptorRead', function(descriptor, value) {
639// gate++;
640// });
641// descriptors[0].once('descriptorRead', function(value) {
642//
643// if (gate === 3) {
644// console.log("Descriptor Read Test Passed.")
645// bluetooth.reset(callback);
646// }
647// });
648// descriptors[0].read(function(err, value) {
649// if (err) {
650// return failModule("Reading descriptor", err);
651// }
652// else {
653// gate++;
654// }
655// });
656// }
657// else {
658// return failModule("Reading correct number of descriptors");
659// }
660// });
661// }
662// else {
663// return failModule("Reading correct number of characteristics");
664// }
665// }
666// });
667// })
668// }
669//
670//
671// function discoverAllAttributesTest(callback) {
672// connectToMoosh(function(moosh) {
673// moosh.discoverAllAttributes(function(err, results) {
674// if (err) {
675// return failModule("Discovering all attributes", results);
676// }
677// else {
678// if (results.services.length === 0) {
679// return failModule("Discovering correct number of services");
680// }
681// if (results.characteristics.length === 0) {
682// return failModule("Discovering correct number of characteristics");
683// }
684// if (results.descriptors.length === 0) {
685// return failModule("Discovering correct number of descriptors");
686// }
687// moosh.disconnect(function() {
688// bluetooth.reset(callback);
689// });
690// }
691// });
692// });
693// }
694//
695// function discoverCharacteristicDescriptorTest(callback) {
696// connectToMoosh(function(moosh) {
697// moosh.discoverAllCharacteristics(function(err, characteristics) {
698// if (err) {
699// return failModule("Discovering single characteristic in descriptor discovery", err);
700// }
701// else {
702// var char;
703// for (var i = 0; i < characteristics.length; i++) {
704// if (characteristics[i].uuid.toString() === "ffa6") {
705// char = characteristics[i];
706// }
707// }
708//
709// if (char) {
710// char.discoverAllDescriptors(function(err, descriptors) {
711// if (err) {
712// return failModule("Discovering descriptors of characteristic", err);
713// }
714// else {
715// console.log("Found these descriptors lying around", descriptors.toString());
716// }
717// });
718// }
719// else {
720// console.log("No char match found");
721// }
722// }
723// });
724// });
725// }
726//
727// function discoverAllDescriptorsTest(callback) {
728// connectToMoosh(function(moosh) {
729// moosh.discoverAllDescriptors(function(err, descriptors) {
730// if (err) {
731// return failModule("Discovering all descriptors", err);
732// }
733// else {
734// console.log("Here are the descriptors", descriptors.toString());
735// moosh.disconnect(function(err) {
736// if (err) {
737// return failModule("Disconnecting from moosh", err);
738// }
739// else {
740// bluetooth.reset(callback);
741// }
742// });
743// }
744// });
745// });
746// }
747//
748// function discoverSpecificService(callback) {
749// connectToMoosh(function(moosh) {
750// var meterSettings = "ffa2";
751// bluetooth.discoverSpecificServices(moosh, [meterSettings], function(err, services) {
752// if (err) {
753// return failModule("Discovering specific service quickly", err);
754// }
755// else {
756// console.log("Found these services", services);
757// }
758// })
759// })
760// }
761//
762function writeLongCharacteristicTest(callback) {
763 connectToSlaveB(function(err, slave) {
764 if (err) {
765 return callback && callback(err);
766 }
767 else {
768 var characteristicUUID = "883f1e6b76f64da187eb6bdbdb617888";
769 slave.discoverCharacteristics([characteristicUUID], function(err, characteristics) {
770 if (err) {
771 return callback && callback(err);
772 }
773 else if (characteristics.length != 1) {
774 return callback && callback(new Error("Retrieved invalid number of characteristics from discovery."));
775 }
776 else{
777 var testChar = characteristics[0];
778 console.log(testChar.toString());
779 var testValue = new Buffer(100);
780 testChar.write(testValue, function(err, written) {
781 console.log("Result: ", err, written);
782 if (err) {
783 return callback && callback(err);
784 }
785 else {
786 console.log("We supposedly wrote this:", written);
787 testChar.read(function(err, value) {
788 console.log("read back", value);
789 if (err) {
790 return callback && callback(err);
791 }
792 else {
793 console.log("v", value.length);
794 console.log("t", testValue.length);
795 slave.disconnect(function(err) {
796 if (err) {
797 return failModule("Disconnecting after char write");
798 }
799 bluetooth.reset(callback);
800 })
801 }
802 });
803 }
804 });
805 }
806 });
807 }
808 });
809}
810
811
812function writeCharacteristicTest(callback) {
813 console.log("Commencing single write test.");
814 connectToSlaveB(function(err, slave) {
815 if (err) {
816 return callback && callback(err);
817 }
818 else {
819 var characteristicUUID = "883f1e6b76f64da187eb6bdbdb617888";
820 slave.discoverCharacteristics([characteristicUUID], function(err, characteristics) {
821 if (err) {
822 return callback && callback(err);
823 }
824 else if (characteristics.length != 1) {
825 return callback && callback(new Error("Retrieved invalid number of characteristics from discovery."));
826 }
827 else{
828 var testChar = characteristics[0];
829 var testValue = "Testing 123"
830 testChar.write(testValue, function(err, written) {
831 if (err) {
832 return callback && callback(err);
833 }
834 else {
835 testChar.read(function(err, value) {
836 if (err) {
837 return callback && callback(err);
838 }
839 else if (value.toString() != testValue){
840 return callback && callback(new Error("Incorrect value read back from write test."));
841 }
842 else {
843 slave.disconnect(function(err) {
844 if (err) {
845 return failModule("Disconnecting after char write");
846 }
847 console.log("Successfully wrote single buffer.");
848 bluetooth.reset(callback);
849 })
850 }
851 });
852 }
853 });
854 }
855 });
856 }
857 });
858}
859
860function readCharacteristicTest(callback) {
861 var testString = "KickingAss";
862 var characteristicUUID = "883f1e6b76f64da187eb6bdbdb617888";
863 slaveB.writeLocalHandle(22, testString, function(err) {
864 if (err) {
865 return callback && callback(err);
866 }
867 else {
868 connectToSlaveB(function(err, slave) {
869 slave.discoverCharacteristics([characteristicUUID], function(err, characteristics) {
870 if (characteristics.length != 1) {
871 return callback && callback(new Error("Invalid number of characteristics recovered."));
872 }
873 else{
874 var gate = 0;
875 var testChar = characteristics[0];
876 bluetooth.on('characteristicRead', function(characteristic, value){
877 if (characteristic && (value.toString() === testString)) {
878 gate++;
879 }
880 });
881 slave.on('characteristicRead', function(characteristic, value) {
882 if (characteristic && (value.toString() === testString)) {
883 gate++;
884 }
885 })
886 testChar.on('characteristicRead', function(value) {
887 if ((value.toString() === testString) && gate == 3) {
888 slave.disconnect(function(err) {
889 if (err) {
890 return callback && callback(err);
891 }
892 else {
893 console.log("Characteristic reading test passed!");
894 bluetooth.reset(callback);
895 }
896 })
897 }
898 else {
899 return callback && callback(new Error("Invalid gate read or value..."));
900 }
901 });
902 testChar.read(function(err, value) {
903 if (err) {
904 return callback && callback(err);
905 }
906 if (value.toString() != testString) {
907 return callback && callback(new Error("String returned is not as written"))
908 }
909 gate++;
910 })
911 }
912 });
913 });
914 }
915 });
916}
917//
918// function discoverAllTest(callback) {
919// connectToMoosh(function(moosh) {
920// var gate = 0;
921// moosh.on('servicesDiscover', function(services) {
922// gate++;
923// });
924// bluetooth.on('servicesDiscover', function(services) {
925// gate++;
926// });
927// moosh.on('characteristicsDiscover', function(characteristics) {
928// if (gate != 4) {
929// return failModule("Didn't hit all the gates" + gate.toString());
930// }
931// else {
932// moosh.disconnect(function(err) {
933// bluetooth.reset(callback);
934// });
935// }
936// });
937// bluetooth.on('characteristicsDiscover', function(characteristics) {
938// gate++
939// });
940// moosh.discoverAllServicesAndCharacteristics(function(err, result) {
941// if (err) {
942// return failModule("Discovering all services and chars", err);
943// }
944// else if (result.services.length != 0 && result.characteristics.length != 0) {
945// console.log("Heck yes!", result);
946// }
947//
948// gate++;
949// });
950// });
951// }
952//
953
954// function characteristicServiceDiscoveryTest(callback) {
955// // connectToMoosh(function(moosh) {
956// // completeServiceCharacteristicDiscoveryTest(moosh, function() {
957// // moosh.disconnect(function(err) {
958// // if (err) {
959// // return failModule("Disconnect from moosh in char service disco test", err);
960// // }
961// connectToMoosh(function(moosh) {
962// console.log("Connected!");
963// subsetServiceCharacteristicDiscoveryTest(moosh, function() {
964// moosh.disconnect(function(err) {
965// if (err) {
966// return failModule("Disconnect from moosh in char service disco test", err);
967// }
968// // serviceSyncingDiscoveryTest(function() {
969// bluetooth.reset(callback);
970// // });
971// });
972// });
973// });
974// // });
975// // });
976// }
977//
978// function serviceSyncingDiscoveryTest(callback) {
979// connectToMoosh(function(moosh) {
980// bluetooth.discoverAllCharacteristics(moosh, function() {
981// bluetooth.discoverAllServices(moosh, function() {
982// if (moosh._unassignedCharacteristics.length == 0) {
983// moosh.disconnect(function(err) {
984// if (err) {
985// return failModule("Disconnect from moosh in char service disco test", err);
986// }
987// console.log("Completed service syncing test.");
988// bluetooth.reset(callback);
989// });
990// }
991// else {
992// console.log("Shit length: ", moosh._unassignedCharacteristics.length);
993// return failModule("Still have unassigned characteristics after discovery");
994// }
995// });
996// });
997// });
998// }
999//
1000// function completeServiceCharacteristicDiscoveryTest(peripheral, callback) {
1001// console.log("Discovering all services");
1002// peripheral.discoverAllServices(function(err, services) {
1003// if (err) {
1004// return failModule("Discovering all services", err);
1005// }
1006// console.log("Done discovering all services", services);
1007// console.log("From the horse's mouth: ", peripheral.services);
1008// peripheral.discoverAllCharacteristics(function(err, characteristics) {
1009// if (err) {
1010// return failModule("Discovering all chars", err);
1011// }
1012// callback && callback();
1013// });
1014// });
1015// }
1016//
1017// function subsetServiceCharacteristicDiscoveryTest(peripheral, callback) {
1018// peripheral.discoverAllServices(function(err, services) {
1019// if (err) {
1020// return failModule("Discovering all services", err);
1021// }
1022// services.forEach(function(service) {
1023// if (service.uuid.toString() === "ffa0") {
1024// var reqChar = ["ffa6"];
1025// service.discoverAllCharacteristics(function(err, allChars) {
1026// console.log("Discovered all: ", allChars.toString());
1027// if (allChars.length >= reqChar.length) {
1028// console.log("Disocvering specific");
1029// service.discoverCharacteristics(reqChar, function(err, subsetChars) {
1030// console.log("Then found these: ", subsetChars.toString());
1031// if (subsetChars.length == reqChar.length) {
1032// callback();
1033// }
1034// else {
1035// return failModule("Characteristic Length validation");
1036// }
1037// });
1038// }
1039// });
1040// }
1041// })
1042// });
1043// }
1044
1045/*
1046Tests surrounding discovering characteristics
1047 discovering specific characteristics (from controller and peripheral)
1048 discovering all characteristics
1049 discovering all characteristics of a service
1050 characteristic sync when they're discovered before their service
1051*/
1052function characteristicDiscoveryTest(callback) {
1053 // console.log("Beginning characteristic discovery test");
1054 connectToSlaveB(function(err, slave) {
1055 if (err) {
1056 return callback && callback(err);
1057 }
1058 else {
1059 // allCharacteristicDiscoveryTest(slave, function(err) {
1060 // if (err) {
1061 // return callback && callback(err);
1062 // }
1063 // else {
1064 specificCharacteristicDiscoveryTest(slave, function(err) {
1065 if (err) {
1066 return callback && callback(err);
1067 }
1068 slave.disconnect(function(err) {
1069 if (err) {
1070 return callback && callback(err);
1071 }
1072 bluetooth.reset(callback);
1073 });
1074 });
1075 // }
1076 // });
1077 }
1078 });
1079}
1080
1081function specificCharacteristicDiscoveryTest(peripheral, callback) {
1082 var reqChar = ["ffa6", "883f1e6b76f64da187eb6bdbdb617888", "50888c106cc511e3981f0800200c9a66"];
1083 console.log("Specific characteristic discovery test");
1084 peripheral.discoverCharacteristics(reqChar, function(err, pc) {
1085 if (err) {
1086 return callback && callback(err);
1087 }
1088 else {
1089 bluetooth.discoverCharacteristics(peripheral, reqChar, function(err, mc) {
1090 if (err) {
1091 return callback && callback(err);
1092 }
1093 else {
1094 if ((pc.length != (reqChar.length-1)) || ((reqChar.length-1) != mc.length)) {
1095 return callback && callback(new Error("Invalid number of characteristics returned from subset"));
1096 }
1097 else {
1098 console.log("Specific characteristic discovery test passed.");
1099 callback && callback();
1100 }
1101 }
1102 });
1103 }
1104 });
1105}
1106
1107
1108function allCharacteristicDiscoveryTest(peripheral, callback) {
1109 console.log("Discovering all characteristics...");
1110 peripheral.discoverAllCharacteristics(function(err, pc) {
1111 console.log("Hit the callback");
1112 if (err) {
1113 return callback && callback(err);
1114 }
1115 bluetooth.discoverAllCharacteristics(peripheral, function(err, mc) {
1116 if (err) {
1117 return callback && callback(err);
1118 }
1119 console.log("PC Length: ", pc.length);
1120 console.log("MC Length: ", mc.length);
1121 if (pc.length != mc.length || pc.length === 0) {
1122 return callback && callback(new Error("Peripheral char length does not equal controller char length"));
1123 }
1124 else {
1125 callback && callback();
1126 }
1127 });
1128 });
1129}
1130
1131/*
1132Tests surrounding discovering services
1133 discovering specific services
1134 discovering all services
1135 (still needs) discovering included services
1136*/
1137function serviceDiscoveryTest(callback) {
1138
1139 // Set the timeout for failure
1140 //failTimeout;// = setTimeout(failModule.bind(null, "Service Discovery Test"), 30000);
1141
1142 connectToSlaveB(function(err, slave) {
1143 if (err) {
1144 callback && callback(err);
1145 }
1146 else {
1147 discoverSpecificServicesTest(slave, function(err) {
1148 if (err) {
1149 callback && callback(err);
1150 }
1151 else {
1152 discoverAllServicesTest(slave, function(err) {
1153 if (err) {
1154 callback && callback(err);
1155 }
1156 else {
1157 slave.disconnect(function(err) {
1158 if (err) {
1159 return callback && callback(err);
1160 }
1161 else {
1162 clearTimeout(failTimeout);
1163 bluetooth.reset(callback);
1164 }
1165 })
1166 }
1167 });
1168 }
1169 });
1170 }
1171 });
1172}
1173
1174function discoverAllServicesTest(peripheral, callback) {
1175 var gate = 0;
1176 bluetooth.once('servicesDiscover', function(services) {
1177 return gate++;
1178 });
1179 peripheral.once('servicesDiscover', function(services) {
1180
1181 if (gate === 2 && services.length > 2) {
1182 console.log("Complete service discovery test passed.");
1183 return callback && callback();
1184 }
1185 else {
1186 callback && callback(new Error("Incorrect number of gates hit on all service discovery."));
1187 }
1188 });
1189 console.log("Attempting complete discovery test...");
1190 bluetooth.discoverAllServices(peripheral, function(err, services) {
1191 if (err) {
1192 return callback && callback(err);
1193 }
1194 gate++;
1195 });
1196}
1197
1198function discoverSpecificServicesTest(peripheral, callback) {
1199 var reqServices = ["1800", "d752c5fb13804cd5b0efcac7d72cff20"];
1200 var gate = 0;
1201 bluetooth.once('servicesDiscover', function(services) {
1202 if (services.length === reqServices.length) {
1203 return gate++;
1204 }
1205 else {
1206 return callback && callback(new Error("Invalid number of services returned on specific service discovery test."));
1207 }
1208 });
1209 peripheral.once('servicesDiscover', function(services) {
1210 if (gate === 2 && services.length === 2) {
1211 console.log("Subset service discovery test passed.");
1212 bluetooth.removeAllListeners();
1213 peripheral.removeAllListeners();
1214 callback && callback();
1215 }
1216 else {
1217 return callback && callback(new Error("Gate = " + gate.toString() + " not 2"));
1218 }
1219 });
1220 console.log("Attempting subset discovery test");
1221 peripheral.discoverServices(reqServices, function(err, services) {
1222 if (err) {
1223 return callback && callback(err);
1224 }
1225 gate++;
1226 });
1227}
1228
1229
1230function connectToSlaveB(callback) {
1231 slaveB.startAdvertising(function(err) {
1232 if (err) {
1233 return failModule(err);
1234 }
1235 else {
1236 bluetooth.once('discover', function(slave) {
1237 bluetooth.stopScanning(function(err) {
1238 if (err) {
1239 return callback && callback(err);
1240 }
1241
1242 slave.connect(function(err) {
1243 if (err) {
1244 return callback && callback(err);
1245 }
1246 else {
1247 return callback && callback(null, slave);
1248 }
1249 });
1250 });
1251 });
1252
1253 bluetooth.startScanning({serviceUUIDs:["08c8c7a06cc511e3981f0800200c9a66"]}, function(err) {
1254 if (err) {
1255 return callback && callback(err);
1256 }
1257 });
1258 }
1259 });
1260}
1261/*
1262Tests surrounding connecting to peripherals
1263connect
1264disconnect
1265*/
1266function connectTest(callback) {
1267
1268 // Set the timeout for failure
1269 console.log("Beginning connect test!");
1270 //failTimeout;// = setTimeout(failModule.bind(null, "Connect Test"), 45000);
1271 // Gate flag
1272 var gate = 0;
1273
1274 slaveB.startAdvertising(function(err) {
1275 if (err) {
1276 return failModule(err);
1277 }
1278 else {
1279
1280 // Start scanning
1281 bluetooth.startScanning({serviceUUIDs:['08c8c7a06cc511e3981f0800200c9a66']}, function(err) {
1282 // If there was an error, fail
1283 if (err) {
1284 return callback && callback(err);
1285 }
1286 // Once we discover a peripheral
1287 bluetooth.once('discover', function(peripheral) {
1288 // Stop scanning
1289 bluetooth.stopScanning(function(err) {
1290 if (err) {
1291 return callback && callback(err);
1292 }
1293 peripheral.connect(function(err) {
1294 if (err) {
1295 return callback && callback(err);
1296 }
1297 gate++;
1298 });
1299 });
1300 // Once we are connected to it
1301 bluetooth.once('connect', function(connectedPeripheral) {
1302 // Increase gate
1303 gate++;
1304 // Make sure it's the correct peripheral
1305 if (connectedPeripheral != peripheral) {
1306 return callback && callback(new Error("Connect controller event equalty test"));
1307 }
1308 });
1309 // Once the peripheral gets the connect event
1310 peripheral.once('connect', function() {
1311 // Check the gate status
1312 if (gate == 2) {
1313 // When we get the disconnect event
1314 bluetooth.on('disconnect', function(peripheral, reason) {
1315 if (err) {
1316 return callback && callback(err);
1317 }
1318 // Increase the gate
1319 gate++;
1320 });
1321 // When the peripheral gets the disconnect event
1322 peripheral.once('disconnect', function(reason) {
1323 // Check the gate status
1324 if (gate != 4) {
1325 return callback && callback(new Error("Reqested connect peripheral not same as event returned."))
1326 }
1327 bluetooth.removeAllListeners();
1328 // Stop the timeout
1329 clearTimeout(failTimeout);
1330 // Declare success
1331 console.log("Connect Test Passed");
1332 // Next test
1333 bluetooth.reset(callback);
1334 });
1335
1336 // Tell the peripheral to disconnect
1337 peripheral.disconnect(function(err) {
1338 // Increase gate
1339 gate++;
1340 });
1341 }
1342 else {
1343 return callback && callback(new Error("Not all gates hit in connect"));
1344 }
1345 });
1346 });
1347
1348 })
1349 }
1350 });
1351}
1352/*
1353Test surrounding filtering peripherals
1354scan with impassable filter
1355scan with passable filter
1356*/
1357function filterTest(callback) {
1358 var gate = 0;
1359 console.log("Starting filter test...");
1360 slaveB.startAdvertising(function(err) {
1361 if (err) {
1362 return failModule(err);
1363 }
1364 else {
1365 impassableFilterTest(5000, function(err) {
1366 if (err) {
1367 return callback && callback(err);
1368 }
1369 else {
1370 passableFilterTest(15000, function(err) {
1371 if (err) {
1372 return failModule(err);
1373 }
1374 else {
1375 clearTimeout(failTimeout);
1376 bluetooth.reset(callback);
1377 }
1378 });
1379 }
1380 });
1381 }
1382 });
1383}
1384
1385function passableFilterTest(timeout, callback) {
1386 //var passTimeout;// = setTimeout(failModule.bind(null, "Passable filter test"), timeout);
1387
1388 var gate = 0;
1389
1390 bluetooth.once('discover', function(peripheral) {
1391 bluetooth.stopScanning(function(err) {
1392 if (err) {
1393 return callback && callback(err);
1394 }
1395 else {
1396 clearTimeout(passTimeout);
1397 bluetooth.removeAllListeners();
1398 console.log("Passable Filter Test Passed.");
1399 bluetooth.reset(callback);
1400 }
1401 });
1402 });
1403
1404 console.log("Passable filter test started.");
1405 bluetooth.startScanning({serviceUUIDs:["08c8c7a06cc511e3981f0800200c9a66"]}, function(err) {
1406 if (err) {
1407 return callback && callback(err);
1408 }
1409 });
1410
1411}
1412
1413function impassableFilterTest(timeout, callback) {
1414 successTimeout = setTimeout(function() {
1415 if (!failed) {
1416 bluetooth.stopScanning(function(err) {
1417 if (err) {
1418 return callback && callback(err);
1419 }
1420 bluetooth.removeAllListeners();
1421 console.log("Impassable Filter Test Passed.");
1422 callback && callback();
1423 });
1424 }
1425 }, timeout);
1426
1427 bluetooth.startScanning({serviceUUIDs:["fffffff"]}, function(err) {
1428 if (err) {
1429 return callback && callback(err);
1430 }
1431
1432 bluetooth.once('discover', function(peripheral) {
1433
1434 return callback && callback(new Error("Discovered peripheral in impassable filter test"));
1435 });
1436 });
1437}
1438
1439/*
1440Test surrounding scanning for peripheral
1441*/
1442function scanTest(callback) {
1443
1444 console.log("Starting scan test.");
1445
1446 slaveB.startAdvertising(function(err) {
1447 if (err) {
1448 return failModule(err);
1449 }
1450 else {
1451 // Set timeout for failure
1452 //failTimeout;// = setTimeout(failModule.bind(null, "Scan Test"), 40000);
1453
1454 // Flag to keep track of functions that must be hit
1455 var gate = 0;
1456
1457 // When the scan starts, trip the gate
1458 bluetooth.once('scanStart', function() {
1459 console.log("Scan start ")
1460 gate++;
1461 });
1462
1463 // When the scan stops
1464 bluetooth.once('scanStop', function() {
1465 // We should have had three gates tripped
1466 if (gate == 3) {
1467 // clear failure timeout
1468 clearTimeout(failTimeout);
1469
1470 console.log("Scan tests passed.");
1471 // remove any existing listeners
1472 bluetooth.removeAllListeners();
1473
1474 // Continue with tests after resetting
1475 bluetooth.reset(callback);
1476 }
1477 else {
1478 callback && callback(new Error("Not all gates passed for scanning..."));
1479 }
1480 });
1481
1482 // Start scanning
1483 bluetooth.startScanning(function(err) {
1484 console.log("Started scanning!")
1485 if (err) {
1486 // If there was an error, fail
1487 return callback && callback(err);
1488 }
1489 gate++;
1490
1491 // When we discover a peripheral, stop the scan
1492 bluetooth.once('discover', function(peripheral) {
1493 bluetooth.stopScanning(function(err) {
1494 console.log("Stopped scanning!")
1495 gate++;
1496 if (err) {
1497 callback && callback(err);
1498 }
1499 });
1500 });
1501 });
1502 }
1503 });
1504}
1505
1506/*
1507Test surrounding instantiation of module
1508*/
1509function portTest(callback) {
1510
1511 // Set timeout for this test
1512 //failTimeout;// = setTimeout(failModule.bind(null, "Port Test"), 30000);
1513
1514 wrongPortTest(function() {
1515 rightPortTest(function() {
1516 clearTimeout(failTimeout);
1517 callback && callback();
1518 })
1519 })
1520}
1521
1522function wrongPortTest(callback) {
1523 console.log("Testing Wrong Port Detection...");
1524 // No BLEs connected to this port
1525 var wrongPort = tessel.port('b');
1526 // Try to use the wrong port, testing callback
1527 bleDriver.use(wrongPort, function(err) {
1528 // If there wasn't an error, fail the test
1529 if (!err) {
1530 return callback && callback(new Error("No error thrown for invalid module port."));
1531 }
1532 // Connect to the wrong port again, this time testing events
1533 var wrongBLE = bleDriver.use(wrongPort);
1534
1535 // If there was an error, continue with test
1536 wrongBLE.once('error', function(err) {
1537 console.log("Successfully detected wrong module port.");
1538 wrongBLE.messenger.removeAllListeners();
1539 wrongBLE.removeAllListeners();
1540
1541 callback();
1542 });
1543
1544 // If the module connected somehow, fail the test
1545 wrongBLE.once('ready', callback.bind(null, "Checking that incorrect port is not connected"));
1546 });
1547}
1548
1549function rightPortTest(callback) {
1550
1551 console.log("Testing Right Port Detection...");
1552
1553 var rightBLE = bleDriver.use(blePort, function(err) {
1554 if (err) {
1555 return callback && callback(err);
1556 }
1557
1558 // If there was an error connecting to the real port, fail the test
1559 rightBLE.once('error', callback.bind(this));
1560
1561 // If the module connected
1562 rightBLE.once('ready', function() {
1563 // Cancel the timeout
1564 clearTimeout(failTimeout);
1565
1566 console.log("Successfully connected to correct module port.");
1567 rightBLE.messenger.removeAllListeners();
1568 // Continue with the next test
1569 rightBLE.removeAllListeners();
1570
1571 callback();
1572 });
1573 });
1574}
1575
1576function failModule(err)
1577{
1578 failed = true;
1579 clearTimeout(failTimeout);
1580 passedLED.low();
1581 console.log("Test failed.");
1582 if (err) {
1583 console.log(err);
1584 }
1585 bluetooth.reset(function() {
1586 failedLED.high();
1587 })
1588
1589}
1590
1591function passModule()
1592{
1593 if (!failed) {
1594 console.log("Tests passed.");
1595 passedLED.high();
1596 }
1597}
1598
1599setInterval(function() {}, 10000);