bmweb-cli 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bmweb.js +59 -17
- package/package.json +1 -1
package/dist/bmweb.js
CHANGED
|
@@ -814,6 +814,7 @@ import { createInterface } from "node:readline";
|
|
|
814
814
|
|
|
815
815
|
// src/serial.ts
|
|
816
816
|
import { readdirSync as readdirSync2 } from "node:fs";
|
|
817
|
+
var RX_KICK_MS = 4;
|
|
817
818
|
var PORT_PATTERNS = [
|
|
818
819
|
/^cu\.usbserial/i,
|
|
819
820
|
/^cu\.SLAB/i,
|
|
@@ -827,8 +828,12 @@ var NodeSerialPort = class {
|
|
|
827
828
|
binding = null;
|
|
828
829
|
/** chunks heard and not yet read */
|
|
829
830
|
chunks = [];
|
|
830
|
-
/**
|
|
831
|
-
|
|
831
|
+
/** reads waiting for bytes, oldest first, when the queue is empty */
|
|
832
|
+
waiters = [];
|
|
833
|
+
/** the receive kick, running while a read waits (see startKick) */
|
|
834
|
+
kick = null;
|
|
835
|
+
/** a kick ioctl in flight, so they never pile up */
|
|
836
|
+
kicking = false;
|
|
832
837
|
/** the lines as last set, so a partial setSignals keeps the others */
|
|
833
838
|
lines = { dtr: false, rts: false, brk: false };
|
|
834
839
|
/** the wire trace sink, when the CLI wants one */
|
|
@@ -864,23 +869,25 @@ var NodeSerialPort = class {
|
|
|
864
869
|
async close() {
|
|
865
870
|
const b = this.binding;
|
|
866
871
|
this.binding = null;
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
this.waiter = null;
|
|
870
|
-
w({ value: void 0, done: true });
|
|
871
|
-
}
|
|
872
|
+
this.stopKick();
|
|
873
|
+
this.wakeAll();
|
|
872
874
|
this.chunks = [];
|
|
873
875
|
if (b) await b.close();
|
|
874
876
|
}
|
|
877
|
+
/** Tell every waiting read the port is done, and forget them. */
|
|
878
|
+
wakeAll() {
|
|
879
|
+
const ws = this.waiters;
|
|
880
|
+
this.waiters = [];
|
|
881
|
+
for (const w of ws) w({ value: void 0, done: true });
|
|
882
|
+
}
|
|
875
883
|
/**
|
|
876
884
|
* Bytes the binding heard: to the waiting read, else queued.
|
|
877
885
|
* @param chunk - the bytes
|
|
878
886
|
*/
|
|
879
887
|
push(chunk) {
|
|
880
888
|
if (!chunk.length) return;
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
this.waiter = null;
|
|
889
|
+
const w = this.waiters.shift();
|
|
890
|
+
if (w) {
|
|
884
891
|
w({ value: chunk, done: false });
|
|
885
892
|
return;
|
|
886
893
|
}
|
|
@@ -916,19 +923,54 @@ var NodeSerialPort = class {
|
|
|
916
923
|
if (next) return Promise.resolve({ value: next, done: false });
|
|
917
924
|
if (!this.binding) return Promise.resolve({ value: void 0, done: true });
|
|
918
925
|
return new Promise((resolve2) => {
|
|
919
|
-
this.
|
|
926
|
+
this.waiters.push(resolve2);
|
|
927
|
+
this.startKick();
|
|
920
928
|
});
|
|
921
929
|
}
|
|
930
|
+
/**
|
|
931
|
+
* Make the driver deliver what it has heard.
|
|
932
|
+
*
|
|
933
|
+
* THE BUG THIS FIXES. On macOS the built-in FTDI driver does not wake the
|
|
934
|
+
* reader when bytes arrive: with a read armed and the process simply
|
|
935
|
+
* waiting, an ECU's answer sat in the driver until some OTHER call touched
|
|
936
|
+
* the device (the next write, a modem-line change, close), and only then
|
|
937
|
+
* came out -- measured on a real car as 0 bytes for the first exchange
|
|
938
|
+
* after open and every later exchange delivering the PREVIOUS one's bytes
|
|
939
|
+
* at its start. Polling the modem lines (a TIOCMGET, no wire traffic)
|
|
940
|
+
* every few milliseconds while a read waits makes each answer arrive
|
|
941
|
+
* within the poll interval, first exchange included. The interval never
|
|
942
|
+
* holds the process open and stops itself once no read is waiting.
|
|
943
|
+
*/
|
|
944
|
+
startKick() {
|
|
945
|
+
if (this.kick) return;
|
|
946
|
+
const tick = () => {
|
|
947
|
+
const b = this.binding;
|
|
948
|
+
if (!b || !this.waiters.length) {
|
|
949
|
+
this.stopKick();
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
if (this.kicking) return;
|
|
953
|
+
this.kicking = true;
|
|
954
|
+
b.get().catch(() => null).then(() => {
|
|
955
|
+
this.kicking = false;
|
|
956
|
+
});
|
|
957
|
+
};
|
|
958
|
+
this.kick = setInterval(tick, RX_KICK_MS);
|
|
959
|
+
if (typeof this.kick === "object" && "unref" in this.kick)
|
|
960
|
+
this.kick.unref();
|
|
961
|
+
}
|
|
962
|
+
/** Stop the receive kick. */
|
|
963
|
+
stopKick() {
|
|
964
|
+
if (!this.kick) return;
|
|
965
|
+
clearInterval(this.kick);
|
|
966
|
+
this.kick = null;
|
|
967
|
+
}
|
|
922
968
|
/**
|
|
923
969
|
* Cancel the reader: a waiting read is told `done`, buffered bytes go.
|
|
924
970
|
*/
|
|
925
971
|
cancel() {
|
|
926
972
|
this.chunks = [];
|
|
927
|
-
|
|
928
|
-
const w = this.waiter;
|
|
929
|
-
this.waiter = null;
|
|
930
|
-
w({ value: void 0, done: true });
|
|
931
|
-
}
|
|
973
|
+
this.wakeAll();
|
|
932
974
|
}
|
|
933
975
|
/**
|
|
934
976
|
* Write bytes. Resolves when the OS has them, not when they have left the
|
|
@@ -2620,7 +2662,7 @@ async function tuiCommand(chassis, sgbd, opts = {}) {
|
|
|
2620
2662
|
}
|
|
2621
2663
|
|
|
2622
2664
|
// src/bmweb.ts
|
|
2623
|
-
var VERSION = true ? "0.1.
|
|
2665
|
+
var VERSION = true ? "0.1.4" : "0.0.0-dev";
|
|
2624
2666
|
var INCLUDE = {
|
|
2625
2667
|
include: {
|
|
2626
2668
|
kind: "list",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bmweb-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "BMWeb's tools as a command line: read INPA .IPO scripts, compile .IPS sources, search the corpus job index, decode and diff shared Garage reports, and, over a K+DCAN cable, run jobs, whole-car scans and INPA screens in the terminal.",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"type": "module",
|