@@ -74,11 +74,15 @@ UART.ports = ["Web Serial"]; // force only Web Serial to be used
74
74
UART.debug = 3; // show all debug messages
75
75
etc...
76
76
77
- As of Espruino 2v25 you can also send data packets :
77
+ As of Espruino 2v25 you can also send files :
78
78
79
79
UART.getConnection().espruinoSendFile("test.txt","This is a test of sending data to Espruino").then(_=>console.log("Done"))
80
80
UART.getConnection().espruinoSendFile("test.txt","This is a test of sending data to Espruino's SD card",{fs:true}).then(_=>console.log("Done"))
81
81
82
+ And receive them:
83
+
84
+ UART.getConnection().espruinoReceiveFile("test.txt", {}).then(contents=>console.log("Received", JSON.stringify(contents)));
85
+
82
86
Or evaluate JS on the device and return the response as a JS object:
83
87
84
88
UART.getConnection().espruinoEval("1+2").then(res => console.log("=",res));
@@ -380,6 +384,12 @@ To do:
380
384
on ( evt , cb ) { let e = "on" + evt ; if ( ! this [ e ] ) this [ e ] = [ ] ; this [ e ] . push ( cb ) ; } ; // on only works with a single handler
381
385
emit ( evt , data1 , data2 ) { let e = "on" + evt ; if ( this [ e ] ) this [ e ] . forEach ( fn => fn ( data1 , data2 ) ) ; } ;
382
386
removeListener ( evt , callback ) { let e = "on" + evt ; if ( this [ e ] ) this [ e ] = this [ e ] . filter ( fn => fn != callback ) ; } ;
387
+ // on("open", () => ... ) connection opened
388
+ // on("close", () => ... ) connection closed
389
+ // on("data", (data) => ... ) when data is received (as string)
390
+ // on("packet", (type,data) => ... ) when a packet is received (if .parsePackets=true)
391
+ // on("ack", () => ... ) when an ACK is received (if .parsePackets=true)
392
+ // on("nak", () => ... ) when an ACK is received (if .parsePackets=true)
383
393
isOpen = false ; // is the connection actually open?
384
394
isOpening = true ; // in the process of opening a connection?
385
395
txInProgress = false ; // is transmission in progress?
@@ -402,7 +412,7 @@ To do:
402
412
let flags = ( this . rxDataHandlerPacket . charCodeAt ( 0 ) << 8 ) | this . rxDataHandlerPacket . charCodeAt ( 1 ) ;
403
413
let len = flags & 0x1FFF ;
404
414
let rxLen = this . rxDataHandlerPacket . length ;
405
- if ( rxLen > 2 && rxLen >= ( len + 2 ) ) {
415
+ if ( rxLen >= 2 && rxLen >= ( len + 2 ) ) {
406
416
log ( 3 , "Got packet end" ) ;
407
417
if ( this . rxDataHandlerTimeout ) {
408
418
clearTimeout ( this . rxDataHandlerTimeout ) ;
@@ -433,7 +443,7 @@ To do:
433
443
ch = undefined ;
434
444
}
435
445
if ( ch === undefined ) { // if we're supposed to remove the char, do it
436
- data = data . substring ( 0 , i - 1 ) + data . substring ( i + 1 ) ;
446
+ data = data . substring ( 0 , i ) + data . substring ( i + 1 ) ;
437
447
i -- ;
438
448
} else
439
449
this . rxDataHandlerLastCh = ch ;
@@ -465,6 +475,7 @@ To do:
465
475
EVENT : 0x4000 , // parse as JSON and create `E.on('packet', ...)` event
466
476
FILE_SEND : 0x6000 , // called before DATA, with {fn:"filename",s:123}
467
477
DATA : 0x8000 , // Sent after FILE_SEND with blocks of data for the file
478
+ FILE_RECV : 0xA000 // receive a file - returns a series of PT_TYPE_DATA packets, with a final zero length packet to end
468
479
}
469
480
if ( ! pkType in PKTYPES ) throw new Error ( "'pkType' not one of " + Object . keys ( PKTYPES ) ) ;
470
481
let connection = this ;
@@ -504,6 +515,7 @@ To do:
504
515
noACK : bool // (don't wait to acknowledgements)
505
516
chunkSize : int // size of chunks to send (default 1024) for safety this depends on how big your device's input buffer is if there isn't flow control
506
517
progress : (chunkNo,chunkCount)=>{} // callback to report upload progress
518
+ timeout : int (optional, milliseconds, default=1000)
507
519
} */
508
520
espruinoSendFile ( filename , data , options ) {
509
521
if ( "string" != typeof data ) throw new Error ( "'data' must be a String" ) ;
@@ -539,9 +551,57 @@ To do:
539
551
return connection . espruinoSendPacket ( "DATA" , packet , packetOptions ) . then ( sendData ) ;
540
552
}
541
553
}
554
+ /* Receive a file from Espruino using 2v25 packets.
555
+ options = { // mainly passed to Espruino
556
+ fs : true // optional -> write using require("fs") (to SD card)
557
+ timeout : int // milliseconds timeout (default=1000)
558
+ }
559
+ } */
560
+ espruinoReceiveFile ( filename , options ) {
561
+ options = options || { } ;
562
+ options . fn = filename ;
563
+ let connection = this ;
564
+ return new Promise ( ( resolve , reject ) => {
565
+ let fileContents = "" , timeout ;
566
+ function scheduleTimeout ( ) {
567
+ if ( timeout ) clearTimeout ( timeout ) ;
568
+ timeout = setTimeout ( ( ) => {
569
+ timeout = undefined ;
570
+ cleanup ( ) ;
571
+ reject ( "espruinoReceiveFile Timeout" ) ;
572
+ } , options . timeout || 1000 ) ;
573
+ }
574
+ function cleanup ( ) {
575
+ connection . removeListener ( "packet" , onPacket ) ;
576
+ if ( timeout ) {
577
+ clearTimeout ( timeout ) ;
578
+ timeout = undefined ;
579
+ }
580
+ }
581
+ function onPacket ( type , data ) {
582
+ if ( type != 0x8000 ) return ; // ignore things that are not DATA packet
583
+ if ( data . length == 0 ) { // 0 length packet = EOF
584
+ cleanup ( ) ;
585
+ resolve ( fileContents ) ;
586
+ } else {
587
+ fileContents += data ;
588
+ scheduleTimeout ( ) ;
589
+ }
590
+ }
591
+ connection . parsePackets = true ;
592
+ connection . on ( "packet" , onPacket ) ;
593
+ scheduleTimeout ( ) ;
594
+ connection . espruinoSendPacket ( "FILE_RECV" , JSON . stringify ( options ) ) . then ( ( ) => {
595
+ // now wait...
596
+ } , err => {
597
+ cleanup ( ) ;
598
+ reject ( err ) ;
599
+ } ) ;
600
+ } ) ;
601
+ }
542
602
/* Send a JS expression to be evaluated on Espruino using using 2v25 packets.
543
603
options = {
544
- timeout : int // milliseconds timeout
604
+ timeout : int // milliseconds timeout (default=1000)
545
605
stmFix : bool // if set, this works around an issue in Espruino STM32 2v24 and earlier where USB could get in a state where it only sent small chunks of data at a time
546
606
}*/
547
607
espruinoEval ( expr , options ) {
0 commit comments