fba-cli 1.0.4 → 1.0.5

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.
@@ -0,0 +1,430 @@
1
+ import { WebSocket } from 'ws';
2
+ import { spawn } from 'child_process';
3
+ import * as remote_types from './remote_types.js';
4
+ import { retryOperation } from './util.js';
5
+ const mapEAC = new Map();
6
+ const maprEAC = new Map();
7
+ let maxEAC = 0;
8
+ export function getIdxFromEAC(eac) {
9
+ let eMap = maprEAC.get(eac.e);
10
+ if (eMap === undefined) {
11
+ eMap = new Map();
12
+ maprEAC.set(eac.e, eMap);
13
+ }
14
+ let aMap = eMap.get(eac.a);
15
+ if (aMap === undefined) {
16
+ aMap = new Map();
17
+ eMap.set(eac.a, aMap);
18
+ }
19
+ let idx = aMap.get(eac.c);
20
+ if (idx !== undefined) {
21
+ return idx;
22
+ }
23
+ else {
24
+ idx = ++maxEAC;
25
+ aMap.set(eac.c, idx);
26
+ mapEAC.set(idx, eac);
27
+ return idx;
28
+ }
29
+ }
30
+ export function getEACFromIdx(idx) {
31
+ const eac = mapEAC.get(idx);
32
+ return eac;
33
+ }
34
+ export function char4U32LeToString(char4le) {
35
+ let codes = [char4le & 0xff, 0xff & (char4le >> 8), 0xff & (char4le >> 16), 0xff & (char4le >> 24)];
36
+ while (codes.length > 0 && codes[codes.length - 1] === 0) {
37
+ codes.splice(-1);
38
+ }
39
+ return String.fromCharCode(...codes);
40
+ }
41
+ export const MTIN_LOG_strs = ['', 'fatal', 'error', 'warn', 'info', 'debug', 'verbose', '', '', '', '', '', '', '', '', ''];
42
+ class AdltMsg {
43
+ _eac;
44
+ index;
45
+ htyp;
46
+ receptionTimeInMs;
47
+ timeStamp;
48
+ // lifecycle?: DltLifecycleInfoMinIF | undefined
49
+ lifecycle_id;
50
+ mcnt;
51
+ mstp;
52
+ mtin;
53
+ verbose;
54
+ payloadString;
55
+ constructor(binMsg /*, lifecycle?: DltLifecycleInfoMinIF*/) {
56
+ // cached ECU, APID, CTID:
57
+ this._eac = getEACFromIdx(getIdxFromEAC({ e: char4U32LeToString(binMsg.ecu), a: char4U32LeToString(binMsg.apid), c: char4U32LeToString(binMsg.ctid) }));
58
+ this.index = binMsg.index;
59
+ this.receptionTimeInMs = Number(binMsg.reception_time / 1000n);
60
+ this.timeStamp = binMsg.timestamp_dms;
61
+ //this.lifecycle = lifecycle
62
+ this.lifecycle_id = binMsg.lifecycle_id;
63
+ this.htyp = binMsg.htyp;
64
+ this.mcnt = binMsg.mcnt;
65
+ this.mstp = (binMsg.verb_mstp_mtin >> 1) & 0x7;
66
+ this.mtin = (binMsg.verb_mstp_mtin >> 4) & 0xf;
67
+ this.verbose = (binMsg.verb_mstp_mtin & 0x01) === 0x01;
68
+ this.payloadString = binMsg.payload_as_text;
69
+ }
70
+ get ecu() {
71
+ return this._eac.e;
72
+ }
73
+ get apid() {
74
+ return this._eac.a;
75
+ }
76
+ get ctid() {
77
+ return this._eac.c;
78
+ }
79
+ asRestObject(idHint) {
80
+ return {
81
+ id: this.index,
82
+ type: 'msg',
83
+ attributes: {
84
+ timeStamp: this.timeStamp,
85
+ ecu: this.ecu,
86
+ mcnt: this.mcnt,
87
+ apid: this.apid,
88
+ ctid: this.ctid,
89
+ mtin: MTIN_LOG_strs[this.mtin],
90
+ payloadString: this.payloadString,
91
+ lifecycle: this.lifecycle_id, // this.lifecycle ? this.lifecycle.persistentId : undefined,
92
+ },
93
+ };
94
+ }
95
+ }
96
+ export class AdltRemoteClient {
97
+ fileBasedMsgsHandler;
98
+ webSocket;
99
+ adltVersion;
100
+ webSocketIsConnected = false;
101
+ webSocketErrors = [];
102
+ _reqCallbacks = [];
103
+ streamMsgs = new Map();
104
+ constructor(fileBasedMsgsHandler) {
105
+ this.fileBasedMsgsHandler = fileBasedMsgsHandler;
106
+ }
107
+ close() {
108
+ if (this.webSocket) {
109
+ // todo if connected???
110
+ this.webSocket.close();
111
+ }
112
+ }
113
+ /**
114
+ * connect to (an existing) adlt process via websocket
115
+ *
116
+ * Does not start the adlt process!
117
+ *
118
+ * @param wssUrl url of the adlt remote websocket. e.g. ws://localhost:7777
119
+ * @returns the adlt version connected to
120
+ */
121
+ connectToWebSocket(wssUrl) {
122
+ const webSocket = new WebSocket(wssUrl, [], { perMessageDeflate: false, origin: 'adlt-logs', maxPayload: 1000000000 });
123
+ this.webSocket = webSocket;
124
+ webSocket.binaryType = 'arraybuffer'; // todo ArrayBuffer needed for sink?
125
+ return new Promise((resolve, reject) => {
126
+ let promiseWaits = true;
127
+ webSocket.on('message', (data, isBinary) => {
128
+ try {
129
+ if (isBinary) {
130
+ this.onBinaryMessage(data);
131
+ }
132
+ else {
133
+ const text = data.toString();
134
+ if (text.startsWith('info:')) {
135
+ // todo still used?
136
+ console.info(`AdltRemoteClient.on(message) info:`, text);
137
+ }
138
+ else if (this._reqCallbacks.length > 0) {
139
+ // response to a request:
140
+ // console.info(`AdltRemoteClient.on(message) response for request:`, text)
141
+ let cb = this._reqCallbacks.shift();
142
+ if (cb) {
143
+ cb(text);
144
+ }
145
+ }
146
+ else {
147
+ console.warn(`AdltRemoteClient.on(message) unexpected text=`, text);
148
+ }
149
+ }
150
+ }
151
+ catch (e) {
152
+ console.error(`ws on message got error:${e}\n`);
153
+ }
154
+ });
155
+ webSocket.on('upgrade', (response) => {
156
+ // console.log(`AdltRemoteClient.on(upgrade) got response:`) //, response)
157
+ let ah = response.headers['adlt-version'];
158
+ this.adltVersion = ah && !Array.isArray(ah) ? ah : ah && Array.isArray(ah) ? ah.join(',') : undefined;
159
+ if (this.adltVersion) {
160
+ /*
161
+ if (!semver.satisfies(this.adltVersion, MIN_ADLT_VERSION_SEMVER_RANGE)) {
162
+ vscode.window.showErrorMessage(
163
+ `Your adlt version is not matching the required version!\nPlease correct!\nDetected version is '${this.adltVersion}' vs required '${MIN_ADLT_VERSION_SEMVER_RANGE}.'`,
164
+ { modal: true },
165
+ )
166
+ } else {
167
+ console.log(`adlt.AdltDocumentProvider got matching adlt version ${this.adltVersion} vs ${MIN_ADLT_VERSION_SEMVER_RANGE}.`)
168
+ }*/
169
+ //console.log(`AdltRemoteClient.on(upgrade) got adlt version:${this.adltVersion}`)
170
+ }
171
+ });
172
+ webSocket.on('open', () => {
173
+ this.webSocketIsConnected = true;
174
+ this.webSocketErrors = [];
175
+ if (promiseWaits) {
176
+ promiseWaits = false;
177
+ resolve(this.adltVersion || 'no version');
178
+ }
179
+ });
180
+ webSocket.on('close', () => {
181
+ this.webSocketIsConnected = false;
182
+ this.webSocketErrors.push('wss closed');
183
+ // console.warn(`AdltRemoteClient.on(close) wss got close`)
184
+ // this.emitStatusChanges.fire(this.uri)
185
+ });
186
+ webSocket.on('error', (err) => {
187
+ console.warn(`AdltRemoteClient.on(error) wss got error:`, err);
188
+ this.webSocketErrors.push(`error: ${err}`);
189
+ if (promiseWaits) {
190
+ promiseWaits = false;
191
+ reject(err);
192
+ }
193
+ // this.emitStatusChanges.fire(this.uri)
194
+ });
195
+ });
196
+ }
197
+ sendAndRecvAdltMsg(req) {
198
+ return new Promise((resolve, reject) => {
199
+ if (this.webSocket) {
200
+ this._reqCallbacks.push((response) => {
201
+ // if we get an error/n ok we do reject as well:
202
+ if (response.startsWith('ok:')) {
203
+ resolve(response);
204
+ }
205
+ else {
206
+ console.warn(`AdltRemoteClient.sendAndRecvAdltMsg got nok ('${response}') for request '${req}'`);
207
+ reject(response);
208
+ }
209
+ });
210
+ this.webSocket.send(req, (err) => {
211
+ if (err) {
212
+ console.warn(`AdltRemoteClient.sendAndRecvAdltMsg wss got error:`, err);
213
+ this.webSocketErrors.push(`wss send failed with:${err}`);
214
+ // todo! this.emitStatusChanges.fire(this.uri);
215
+ }
216
+ });
217
+ }
218
+ else {
219
+ console.error(`AdltRemoteClient.sendAndRecvAdltMsg got no webSocket yet!`);
220
+ reject(`AdltRemoteClient.sendAndRecvAdltMsg got no webSocket yet!`);
221
+ }
222
+ });
223
+ }
224
+ onBinaryMessage(data) {
225
+ try {
226
+ const bin_type = remote_types.readBinType(data);
227
+ switch (bin_type.tag) {
228
+ case 'DltMsgs':
229
+ case 'StreamInfo':
230
+ {
231
+ let streamId = bin_type.tag === 'DltMsgs' ? bin_type.value[0] : bin_type.value.stream_id;
232
+ let streamData = this.streamMsgs.get(streamId);
233
+ if (streamData && !Array.isArray(streamData)) {
234
+ this.processBinStreamMsgs(bin_type, streamData);
235
+ }
236
+ else {
237
+ // we store the pure data for later processing:
238
+ if (!streamData) {
239
+ streamData = [bin_type];
240
+ this.streamMsgs.set(streamId, streamData);
241
+ }
242
+ else {
243
+ streamData.push(bin_type);
244
+ if (streamData.length > 3) {
245
+ console.warn(`adlt.on(binary): appended ${bin_type.tag} for yet unknown stream=${streamId}, streamData.length=${streamData.length}`);
246
+ }
247
+ }
248
+ }
249
+ }
250
+ break;
251
+ case 'FileInfo':
252
+ case 'Lifecycles':
253
+ case 'EacInfo':
254
+ case 'PluginState':
255
+ {
256
+ this.fileBasedMsgsHandler(bin_type);
257
+ }
258
+ break;
259
+ default:
260
+ console.warn(`ws on binary message ignored:${bin_type.tag}`);
261
+ break;
262
+ }
263
+ }
264
+ catch (e) {
265
+ console.error(`ws on binary message got error:${e}\n`);
266
+ }
267
+ }
268
+ processBinStreamMsgs(bin_type, streamData) {
269
+ try {
270
+ switch (bin_type.tag) {
271
+ case 'DltMsgs':
272
+ const [streamId, msgs] = bin_type.value;
273
+ if (msgs.length === 0) {
274
+ // indicates end of query:
275
+ if (streamData.sink.onDone) {
276
+ streamData.sink.onDone();
277
+ }
278
+ this.streamMsgs.delete(streamId);
279
+ //console.error(`adlt.processBinDltMsgs deleted stream #${streamId}\n\n`)
280
+ }
281
+ else {
282
+ for (let i = 0; i < msgs.length; ++i) {
283
+ let binMsg = msgs[i];
284
+ let msg = new AdltMsg(binMsg /*, this.lifecycleInfoForPersistentId(binMsg.lifecycle_id)*/);
285
+ streamData.msgs.push(msg);
286
+ }
287
+ if (streamData.sink.onNewMessages) {
288
+ streamData.sink.onNewMessages(msgs.length);
289
+ }
290
+ }
291
+ break;
292
+ case 'StreamInfo':
293
+ const si = bin_type.value;
294
+ // console.log(`adlt.processBinStreamMsgs: StreamInfo stream=${si.stream_id}, stream msgs=${si.nr_stream_msgs} processed=${si.nr_file_msgs_processed} total=${si.nr_file_msgs_total}`);
295
+ if (streamData.sink.onStreamInfo) {
296
+ streamData.sink.onStreamInfo(si.nr_stream_msgs, si.nr_file_msgs_processed, si.nr_file_msgs_total);
297
+ }
298
+ break;
299
+ }
300
+ }
301
+ catch (e) {
302
+ console.error(`adlt.processBinStreamMsgs got error:${e}\n`);
303
+ }
304
+ }
305
+ /**
306
+ * calculate and return the matching messages. Does not modify the current content/view.
307
+ * @param filters list of filters to use. Should only be pos and neg filters. Others will be ignored.
308
+ * @param maxMsgsToReturn maximum number of messages to return. As this is no async function the caller
309
+ * needs to be careful!
310
+ * @returns list of matching messages (as Promise)
311
+ */
312
+ getMatchingMessages(filters, maxMsgsToReturn) {
313
+ let p = new Promise((resolve, reject) => {
314
+ const matchingMsgs = [];
315
+ // sort the filters here into the enabled pos and neg:
316
+ try {
317
+ let filterStr = filters
318
+ .filter((f) => ('enabled' in f ? f.enabled : true))
319
+ .map((f) => JSON.stringify({ ...f, enabled: true }))
320
+ .join(',');
321
+ this.sendAndRecvAdltMsg(`query {"window":[0,${maxMsgsToReturn}], "filters":[${filterStr}]}`)
322
+ .then((response) => {
323
+ const streamObj = JSON.parse(response.substring(10));
324
+ let sink = {
325
+ onDone() {
326
+ // console.log(`adlt.getMatchingMessages done matchingMsgs.length=${matchingMsgs.length}`)
327
+ resolve(matchingMsgs);
328
+ },
329
+ };
330
+ // here some data might be already there for that stream.
331
+ // this can happen even though the wss data arrives sequentially but the processing
332
+ // here for wss data is a direct call vs. an asyn .then()...
333
+ let curStreamMsgData = this.streamMsgs.get(streamObj.id);
334
+ let streamData = { msgs: matchingMsgs, sink: sink };
335
+ this.streamMsgs.set(streamObj.id, streamData);
336
+ if (curStreamMsgData && Array.isArray(curStreamMsgData)) {
337
+ // process the data now:
338
+ curStreamMsgData.forEach((msgs) => this.processBinStreamMsgs(msgs, streamData));
339
+ }
340
+ })
341
+ .catch((reason) => {
342
+ reject(reason);
343
+ });
344
+ }
345
+ catch (e) {
346
+ throw new Error(`getMatchingMessages failed due to error '${e}'`);
347
+ reject(e);
348
+ }
349
+ });
350
+ return p;
351
+ }
352
+ }
353
+ /**
354
+ * get the host&port (e.g. 127.0.0.1:7777) & spawned process of adlt process.
355
+ * Starts adlt and tries to find an open port in range
356
+ * 6700-6789.
357
+ *
358
+ * Sets internal variables _adltProcess and _adltPort as well.
359
+ * @returns a promise for the host&port and the spawned process
360
+ */
361
+ export function getAdltProcessAndPort(adltCommand, outStream) {
362
+ return new Promise((resolve, reject) => {
363
+ // start it
364
+ // currently it retries 89 times even if spawnAdltProcess rejects with ENOENT! todo
365
+ retryOperation((retries_left) => spawnAdltProcess(adltCommand, 6789 - retries_left, outStream), 10, 89)
366
+ .then(([childProc, port]) => {
367
+ resolve({ hostAndPort: `127.0.0.1:${port}`, process: childProc });
368
+ })
369
+ .catch((reason) => {
370
+ reject(reason);
371
+ });
372
+ });
373
+ }
374
+ /**
375
+ * spawn an adlt process at specified port.
376
+ *
377
+ * Checks whether the process could be started sucessfully and
378
+ * whether its listening on the port.
379
+ *
380
+ * Uses adltCommand to start the process and the params 'remote -p<port>'.
381
+ *
382
+ * It listens on stdout and stderr (and on 'close' and 'error' events) and forwards output to the outStream.
383
+ * This could be improved/changed to listen only until a successful start is detected.
384
+ *
385
+ * Rejects with 'ENOENT' or 'AddrInUse' or 'did close unexpectedly' in case of errors.
386
+ *
387
+ * @param port number of port to use for remote websocket
388
+ * @returns pair of ChildProcess started and the port number
389
+ */
390
+ function spawnAdltProcess(adltCommand, port, outStream) {
391
+ return new Promise((resolve, reject) => {
392
+ let finishedListening = [false]; // todo could be a regular boolean
393
+ let childProc = spawn(adltCommand, ['remote', `-p=${port}`], { detached: false, windowsHide: true });
394
+ childProc.on('error', (err) => {
395
+ outStream.write(`spawnAdltProcess process got err='${err}'\n`);
396
+ if (!finishedListening[0] && err.message.includes('ENOENT')) {
397
+ finishedListening[0] = true;
398
+ reject(`ENOENT - ${adltCommand} not found in path?. Detail error: ${err.message}`);
399
+ }
400
+ });
401
+ childProc.on('close', (code, signal) => {
402
+ outStream.write(`spawnAdltProcess(port=${port}) process got close code='${code}' signal='${signal}'\n`);
403
+ if (!finishedListening[0]) {
404
+ finishedListening[0] = true;
405
+ reject('did close unexpectedly');
406
+ }
407
+ });
408
+ childProc?.stdout?.on('data', (data) => {
409
+ // todo or use 'spawn' event?
410
+ try {
411
+ if (!finishedListening[0] && `${data}`.includes('remote server listening on')) {
412
+ finishedListening[0] = true; // todo stop searching for ... (might as well stop listening completely for stdout)
413
+ resolve([childProc, port]);
414
+ }
415
+ outStream.write(data);
416
+ }
417
+ catch (err) {
418
+ outStream.write(`spawnAdltProcess(port=${port}) process stdout got err='${err}, typeof data=${typeof data}'\n`);
419
+ }
420
+ });
421
+ childProc?.stderr?.on('data', (data) => {
422
+ outStream.write(`spawnAdltProcess(port=${port}) process got stderr='${data}'\n`);
423
+ if (!finishedListening[0] && `${data}`.includes('AddrInUse')) {
424
+ finishedListening[0] = true;
425
+ reject('AddrInUse');
426
+ }
427
+ });
428
+ });
429
+ }
430
+ //# sourceMappingURL=adltRemoteClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adltRemoteClient.js","sourceRoot":"","sources":["../src/adltRemoteClient.ts"],"names":[],"mappings":"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"}