Skip to content

Commit 20fc800

Browse files
committed
Updated Puck.js/UART.js
Puck.write/eval now wait until they have received data with a newline in (if requested) and return the LAST received line, rather than the first (as before) Added configurable timeouts for write/etc
1 parent d659cfa commit 20fc800

File tree

2 files changed

+61
-41
lines changed

2 files changed

+61
-41
lines changed

puck.js

+38-25
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ Or more advanced usage with control of the connection
5151
ChangeLog:
5252
5353
...
54-
1v00 : Added Promises to write/eval
55-
1v01 : Raise default Chunk Size to 20
56-
Auto-adjust chunk size up if we receive >20 bytes in a packet
54+
1.02: Puck.write/eval now wait until they have received data with a newline in (if requested)
55+
and return the LAST received line, rather than the first (as before)
56+
Added configurable timeouts for write/etc
57+
1.01: Raise default Chunk Size to 20
58+
Auto-adjust chunk size up if we receive >20 bytes in a packet
59+
1.00: Added Promises to write/eval
5760
5861
*/
5962
(function (root, factory) {
@@ -328,31 +331,37 @@ ChangeLog:
328331
function onWritten() {
329332
if (callbackNewline) {
330333
connection.cb = function(d) {
331-
var newLineIdx = connection.received.indexOf("\n");
332-
if (newLineIdx>=0) {
333-
var l = connection.received.substr(0,newLineIdx);
334-
connection.received = connection.received.substr(newLineIdx+1);
335-
connection.cb = undefined;
336-
if (cbTimeout) clearTimeout(cbTimeout);
337-
cbTimeout = undefined;
338-
if (callback)
339-
callback(l);
340-
isBusy = false;
341-
handleQueue();
342-
}
334+
// if we hadn't got a newline this time (even if we had one before)
335+
// then ignore it (https://github.com/espruino/BangleApps/issues/3771)
336+
if (!d.includes("\n")) return;
337+
// now return the LAST received non-empty line
338+
var lines = connection.received.split("\n");
339+
var idx = lines.length-1;
340+
while (lines[idx].trim().length==0 && idx>0) idx--; // skip over empty lines
341+
var line = lines.splice(idx,1)[0]; // get the non-empty line
342+
connection.received = lines.join("\n"); // put back other lines
343+
// remove handler and return
344+
connection.cb = undefined;
345+
if (cbTimeout) clearTimeout(cbTimeout);
346+
cbTimeout = undefined;
347+
if (callback)
348+
callback(line);
349+
isBusy = false;
350+
handleQueue();
343351
};
344352
}
345353
// wait for any received data if we have a callback...
346-
var maxTime = 300; // 30 sec - Max time we wait in total, even if getting data
347-
var dataWaitTime = callbackNewline ? 100/*10 sec if waiting for newline*/ : 3/*300ms*/;
354+
var maxTime = puck.timeoutMax; // Max time we wait in total, even if getting data
355+
var dataWaitTime = callbackNewline ? puck.timeoutNewline : puck.timeoutNormal;
348356
var maxDataTime = dataWaitTime; // max time we wait after having received data
357+
const POLLINTERVAL = 100;
349358
cbTimeout = setTimeout(function timeout() {
350359
cbTimeout = undefined;
351-
if (maxTime) maxTime--;
352-
if (maxDataTime) maxDataTime--;
360+
if (maxTime>0) maxTime-=POLLINTERVAL;
361+
if (maxDataTime>0) maxDataTime-=POLLINTERVAL;
353362
if (connection.hadData) maxDataTime=dataWaitTime;
354-
if (maxDataTime && maxTime) {
355-
cbTimeout = setTimeout(timeout, 100);
363+
if (maxDataTime>0 && maxTime>0) {
364+
cbTimeout = setTimeout(timeout, POLLINTERVAL);
356365
} else {
357366
connection.cb = undefined;
358367
if (callback)
@@ -362,7 +371,7 @@ ChangeLog:
362371
connection.received = "";
363372
}
364373
connection.hadData = false;
365-
}, 100);
374+
}, POLLINTERVAL);
366375
}
367376

368377
if (connection && (connection.isOpen || connection.isOpening)) {
@@ -397,6 +406,7 @@ ChangeLog:
397406
// ----------------------------------------------------------
398407

399408
var puck = {
409+
version : "1.02",
400410
/// Are we writing debug information? 0 is no, 1 is some, 2 is more, 3 is all.
401411
debug : 1,
402412
/** When we receive more than 20 bytes, should we increase the chunk size we use
@@ -405,6 +415,12 @@ ChangeLog:
405415
increaseMTU : true,
406416
/// Should we use flow control? Default is true
407417
flowControl : true,
418+
/// timeout (in ms) in .write when waiting for any data to return
419+
timeoutNormal : 300,
420+
/// timeout (in ms) in .write/.eval when waiting for a newline
421+
timeoutNewline : 10000,
422+
/// timeout (in ms) to wait at most
423+
timeoutMax : 30000,
408424
/// Used internally to write log information - you can replace this with your own function
409425
log : function(level, s) { if (level <= this.debug) console.log("<BLE> "+s)},
410426
/// Called with the current send progress or undefined when done - you can replace this with your own function
@@ -418,7 +434,6 @@ ChangeLog:
418434
write : write,
419435
/// Evaluate an expression and call cb with the result. Creates a connection if it doesn't exist
420436
eval : function(expr, cb) {
421-
422437
const response = write('\x10Bluetooth.println(JSON.stringify(' + expr + '))\n', true)
423438
.then(function (d) {
424439
try {
@@ -428,8 +443,6 @@ ChangeLog:
428443
return Promise.reject(d);
429444
}
430445
});
431-
432-
433446
if (cb) {
434447
return void response.then(cb, (err) => cb(null, err));
435448
} else {

uart.js

+23-16
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ UART.getConnection().espruinoEval("1+2").then(res => console.log("=",res));
9191
ChangeLog:
9292
9393
...
94+
1.09: UART.write/eval now wait until they have received data with a newline in (if requested)
95+
and return the LAST received line, rather than the first (as before)
9496
1.08: Add UART.getConnectionAsync()
9597
Add .espruinoEval(... {stmFix:true}) to work around occasional STM32 USB issue in 2v24 and earlier firmwares
9698
1s->2s packet timeout
@@ -570,7 +572,7 @@ To do:
570572
cleanup();
571573
reject("espruinoReceiveFile Timeout");
572574
}, options.timeout || 1000);
573-
}
575+
}
574576
function cleanup() {
575577
connection.removeListener("packet", onPacket);
576578
if (timeout) {
@@ -642,7 +644,7 @@ To do:
642644
.catch(err=>{
643645
console.error("Error sending STM fix:",err);
644646
cleanup();
645-
});
647+
});
646648
}, 50);
647649
}, err => {
648650
cleanup();
@@ -1072,19 +1074,24 @@ To do:
10721074
function onWritten() {
10731075
if (callbackNewline) {
10741076
connection.cb = function(d) {
1075-
var newLineIdx = connection.received.indexOf("\n");
1076-
if (newLineIdx>=0) {
1077-
var l = connection.received.substr(0,newLineIdx);
1078-
connection.received = connection.received.substr(newLineIdx+1);
1079-
connection.cb = undefined;
1080-
if (cbTimeout) clearTimeout(cbTimeout);
1081-
cbTimeout = undefined;
1082-
if (callback)
1083-
callback(l);
1084-
resolve(l);
1085-
isBusy = false;
1086-
handleQueue();
1087-
}
1077+
// if we hadn't got a newline this time (even if we had one before)
1078+
// then ignore it (https://github.com/espruino/BangleApps/issues/3771)
1079+
if (!d.includes("\n")) return;
1080+
// now return the LAST received non-empty line
1081+
var lines = connection.received.split("\n");
1082+
var idx = lines.length-1;
1083+
while (lines[idx].trim().length==0 && idx>0) idx--; // skip over empty lines
1084+
var line = lines.splice(idx,1)[0]; // get the non-empty line
1085+
connection.received = lines.join("\n"); // put back other lines
1086+
// remove handler and return
1087+
connection.cb = undefined;
1088+
if (cbTimeout) clearTimeout(cbTimeout);
1089+
cbTimeout = undefined;
1090+
if (callback)
1091+
callback(line);
1092+
resolve(l);
1093+
isBusy = false;
1094+
handleQueue();
10881095
};
10891096
}
10901097
// wait for any received data if we have a callback...
@@ -1147,7 +1154,7 @@ To do:
11471154
// ----------------------------------------------------------
11481155

11491156
var uart = {
1150-
version : "1.08",
1157+
version : "1.09",
11511158
/// Are we writing debug information? 0 is no, 1 is some, 2 is more, 3 is all.
11521159
debug : 1,
11531160
/// Should we use flow control? Default is true

0 commit comments

Comments
 (0)