@@ -14,19 +14,23 @@ const net = require('net');
14
14
const http = require ( 'http' ) ;
15
15
const bufferEqual = require ( 'buffer-equal' ) ;
16
16
const Buffer = require ( 'safe-buffer' ) . Buffer ;
17
+ const dgram = require ( 'dgram' ) ;
17
18
18
19
const wifiOutputModeJSON = 'json' ;
19
20
const wifiOutputModeRaw = 'raw' ;
20
-
21
+ const wifiOutputProtocolUDP = 'udp' ;
22
+ const wifiOutputProtocolTCP = 'tcp' ;
21
23
/**
22
24
* Options object
23
25
* @type {InitializationObject }
24
26
* @private
25
27
*/
26
28
const _options = {
27
29
attempts : 10 ,
30
+ burst : false ,
28
31
debug : false ,
29
32
latency : 10000 ,
33
+ protocol : [ wifiOutputProtocolTCP , wifiOutputProtocolUDP ] ,
30
34
sampleRate : 0 ,
31
35
sendCounts : false ,
32
36
simulate : false ,
@@ -43,11 +47,17 @@ const _options = {
43
47
* @typedef {Object } InitializationObject
44
48
* @property {Number } attempts - The number of times to try and perform an SSDP search before quitting. (Default 10)
45
49
*
50
+ * @property {Boolean } burst - Only applies for UDP, but the wifi shield will send 3 of the same packets on UDP to
51
+ * increase the chance packets arrive to this module (Default false)
52
+ *
46
53
* @property {Boolean } debug - Print out a raw dump of bytes sent and received. (Default `false`)
47
54
*
48
55
* @property {Number } latency - The latency, or amount of time between packet sends, of the WiFi shield. The time is in
49
56
* micro seconds!
50
57
*
58
+ * @property {String } protocol - Either send the data over TCP or UDP. UDP seems better for either a bad router or slow
59
+ * router. Default is TCP
60
+ *
51
61
* @property {Number } sampleRate - The sample rate to set the board to. (Default is zero)
52
62
*
53
63
* @property {Boolean } sendCounts - Send integer raw counts instead of scaled floats.
@@ -159,11 +169,14 @@ function Wifi (options) {
159
169
this . _shieldName = null ;
160
170
this . _streaming = false ;
161
171
this . _version = null ;
172
+ this . _lastPacketArrival = 0 ;
162
173
163
174
/** Public Properties (keep alphabetical) */
164
175
165
176
this . curOutputMode = wifiOutputModeRaw ;
177
+ this . internalRawDataPackets = [ ] ;
166
178
this . wifiShieldArray = [ ] ;
179
+ this . wifiServerUDPPort = 0 ;
167
180
168
181
/** Initializations */
169
182
@@ -173,6 +186,41 @@ function Wifi (options) {
173
186
// This allows us to use the emitter class freely outside of the module
174
187
util . inherits ( Wifi , EventEmitter ) ;
175
188
189
+ /**
190
+ * This function is for redundancy after a long packet send, the wifi firmware can resend the same
191
+ * packet again, using this till add redundancy on poor networks.
192
+ * @param rawDataPackets -
193
+ * @returns {Array }
194
+ */
195
+ Wifi . prototype . bufferRawDataPackets = function ( rawDataPackets ) {
196
+ if ( this . internalRawDataPackets . length === 0 ) {
197
+ this . internalRawDataPackets = rawDataPackets ;
198
+ return [ ] ;
199
+ } else {
200
+ let out = [ ] ;
201
+ let coldStorage = [ ] ;
202
+ _ . forEach ( rawDataPackets , ( newRDP ) => {
203
+ let found = false ;
204
+ _ . forEach ( this . internalRawDataPackets , ( oldRDP ) => {
205
+ if ( ! found && bufferEqual ( newRDP , oldRDP ) ) {
206
+ out . push ( oldRDP ) ;
207
+ found = true ;
208
+ }
209
+ } ) ;
210
+ if ( ! found ) {
211
+ coldStorage . push ( newRDP ) ;
212
+ }
213
+ } ) ;
214
+ if ( out . length === 0 ) {
215
+ out = this . internalRawDataPackets ;
216
+ this . internalRawDataPackets = rawDataPackets ;
217
+ } else {
218
+ this . internalRawDataPackets = coldStorage ;
219
+ }
220
+ return out ;
221
+ }
222
+ } ;
223
+
176
224
/**
177
225
* @description Send a command to the board to turn a specified channel off
178
226
* @param channelNumber
@@ -334,10 +382,6 @@ Wifi.prototype.disconnect = function () {
334
382
return Promise . resolve ( ) ;
335
383
} ;
336
384
337
- Wifi . prototype . eraseCredentials = function ( ) {
338
- this . delete
339
- } ;
340
-
341
385
/**
342
386
* @description Checks if the driver is connected to a board.
343
387
* @returns {boolean } - True if connected.
@@ -717,6 +761,7 @@ Wifi.prototype.streamStart = function () {
717
761
return new Promise ( ( resolve , reject ) => {
718
762
if ( this . isStreaming ( ) ) return reject ( 'Error [.streamStart()]: Already streaming' ) ;
719
763
this . _streaming = true ;
764
+ this . _lastPacketArrival = 0 ;
720
765
this . write ( k . OBCIStreamStart )
721
766
. then ( ( ) => {
722
767
if ( this . options . verbose ) console . log ( 'Sent stream start to board.' ) ;
@@ -859,6 +904,11 @@ Wifi.prototype._processBytes = function (data) {
859
904
860
905
this . buffer = output . buffer ;
861
906
907
+ // if (this.options.redundancy) {
908
+ // this._rawDataPacketToSample.rawDataPackets = this.bufferRawDataPackets(output.rawDataPackets);
909
+ // } else {
910
+ // this._rawDataPacketToSample.rawDataPackets = output.rawDataPackets;
911
+ // }
862
912
this . _rawDataPacketToSample . rawDataPackets = output . rawDataPackets ;
863
913
864
914
_ . forEach ( this . _rawDataPacketToSample . rawDataPackets , ( rawDataPacket ) => {
@@ -928,13 +978,24 @@ Wifi.prototype._finalizeNewSampleForDaisy = function (sampleObject) {
928
978
* @private
929
979
*/
930
980
Wifi . prototype . _connectSocket = function ( ) {
931
- return this . post ( '/tcp' , {
932
- ip : ip . address ( ) ,
933
- output : this . curOutputMode ,
934
- port : this . wifiGetLocalPort ( ) ,
935
- delimiter : false ,
936
- latency : this . _latency
937
- } ) ;
981
+ if ( this . options . protocol === 'udp' ) {
982
+ return this . post ( `/${ this . options . protocol } ` , {
983
+ ip : ip . address ( ) ,
984
+ output : this . curOutputMode ,
985
+ port : this . wifiGetLocalPort ( ) ,
986
+ delimiter : false ,
987
+ latency : this . _latency ,
988
+ redundancy : this . options . burst
989
+ } ) ;
990
+ } else {
991
+ return this . post ( `/${ this . options . protocol } ` , {
992
+ ip : ip . address ( ) ,
993
+ output : this . curOutputMode ,
994
+ port : this . wifiGetLocalPort ( ) ,
995
+ delimiter : false ,
996
+ latency : this . _latency
997
+ } ) ;
998
+ }
938
999
} ;
939
1000
940
1001
/**
@@ -945,28 +1006,59 @@ Wifi.prototype.destroy = function () {
945
1006
if ( this . wifiClient ) {
946
1007
this . wifiClient . stop ( ) ;
947
1008
}
1009
+ if ( this . wifiServerUDP ) {
1010
+ this . wifiServerUDP . removeAllListeners ( 'error' ) ;
1011
+ this . wifiServerUDP . removeAllListeners ( 'message' ) ;
1012
+ this . wifiServerUDP . removeAllListeners ( 'listening' ) ;
1013
+ this . wifiServerUDP . close ( ) ;
1014
+ }
948
1015
this . wifiClient = null ;
949
1016
} ;
950
1017
951
1018
Wifi . prototype . wifiGetLocalPort = function ( ) {
952
- return this . wifiServer . address ( ) . port ;
1019
+ if ( this . options . protocol === wifiOutputProtocolUDP ) {
1020
+ return this . wifiServerUDPPort ;
1021
+ } else {
1022
+ return this . wifiServer . address ( ) . port ;
1023
+ }
953
1024
} ;
954
1025
955
1026
Wifi . prototype . wifiInitServer = function ( ) {
956
- let persistentBuffer = null ;
957
- const delimBuf = new Buffer ( "\r\n" ) ;
958
1027
this . wifiServer = net . createServer ( ( socket ) => {
959
- // streamJSON.on("data", (sample) => {
960
- // console.log(sample);
961
- // });
962
1028
socket . on ( 'data' , ( data ) => {
963
1029
this . _processBytes ( data ) ;
964
1030
} ) ;
965
1031
socket . on ( 'error' , ( err ) => {
966
1032
if ( this . options . verbose ) console . log ( 'SSDP:' , err ) ;
967
1033
} ) ;
968
1034
} ) . listen ( ) ;
969
- if ( this . options . verbose ) console . log ( "Server on port: " , this . wifiGetLocalPort ( ) ) ;
1035
+ if ( this . options . verbose ) console . log ( "TCP: on port: " , this . wifiGetLocalPort ( ) ) ;
1036
+
1037
+ this . wifiServerUDP = dgram . createSocket ( 'udp4' ) ;
1038
+
1039
+ this . wifiServerUDP . on ( 'error' , ( err ) => {
1040
+ if ( this . options . verbose ) console . log ( `server error:\n${ err . stack } ` ) ;
1041
+ this . wifiServerUDP . close ( ) ;
1042
+ } ) ;
1043
+
1044
+ let lastMsg = null ;
1045
+
1046
+ this . wifiServerUDP . on ( 'message' , ( msg ) => {
1047
+ if ( ! bufferEqual ( lastMsg , msg ) ) {
1048
+ this . _processBytes ( msg ) ;
1049
+ }
1050
+ lastMsg = msg ;
1051
+ } ) ;
1052
+
1053
+ this . wifiServerUDP . on ( 'listening' , ( ) => {
1054
+ const address = this . wifiServerUDP . address ( ) ;
1055
+ this . wifiServerUDPPort = address . port ;
1056
+ if ( this . options . verbose ) console . log ( `server listening ${ address . address } :${ address . port } ` ) ;
1057
+ } ) ;
1058
+
1059
+ this . wifiServerUDP . bind ( {
1060
+ address : ip . address ( )
1061
+ } ) ;
970
1062
} ;
971
1063
972
1064
Wifi . prototype . processResponse = function ( res , cb ) {
0 commit comments