· 4 years ago · Apr 09, 2021, 06:26 AM
1import { InterfaceBoard, TTOFValue, TPowerPulse, TGPIOQueryResult, TStatusCommandActuator } from "./InterfaceBoard";
2import SerialPort from "serialport";
3import WaitQueue from 'wait-queue';
4import { uuid } from 'uuidv4';
5import { emitLog } from "./EmitLog";
6import { LevelMessageLogEntry } from "appcore-ts/log/processor_log";
7import { appendFileSync } from "fs";
8
9const InterByteTimeout = require('@serialport/parser-inter-byte-timeout')
10
11enum TPacket
12{
13 PACKET_TYPE_NONE = 0,
14 PACKET_TYPE_PING = 1,
15 PACKET_TYPE_PONG = 2,
16 PACKET_TYPE_SET_STEPPER_POS = 3,
17 PACKET_TYPE_GET_STEPPER_POS = 4,
18 PACKET_TYPE_STEPPER_POS = 5,
19 PACKET_TYPE_POWER_PULSE = 6,
20 PACKET_TYPE_GPIO_GET = 7,
21 PACKET_TYPE_GPIO_GET_ALL = 8,
22 PACKET_TYPE_GPIO_SET = 9,
23 PACKET_TYPE_GPIO_SINGLE = 10,
24 PACKET_TYPE_GPIO_ALL = 11,
25 PACKET_TYPE_GET_BELT_ENCODER_POS = 12,
26 PACKET_TYPE_BELT_ENCODER_POS = 13,
27 PACKET_TYPE_TOF_GET_PULSE_LENGTH = 14,
28 PACKET_TYPE_TOF_PULSE_LENGTH = 15,
29 PACKET_TYPE_TOF_SET_PULSE_LENGTH = 16,
30 PACKET_TYPE_TOF_GET_DELAY = 17,
31 PACKET_TYPE_TOF_DELAY = 18,
32 PACKET_TYPE_TOF_SET_DELAY = 19,
33 PACKET_TYPE_INTERRUPT_POWER = 20,
34 PACKET_TYPE_GET_ACTUATOR_ENCODER_POS = 21,
35 PACKET_TYPE_ACTUATOR_ENCODER_POS = 22,
36 PACKET_TYPE_GET_UNIQUE_ID = 23,
37 PACKET_TYPE_UNIQUE_ID = 24,
38 PACKET_TYPE_TOF_GET_COUNTER = 25,
39 PACKET_TYPE_TOF_COUNTER = 26,
40 PACKET_TYPE_GET_SUPPLY_VOLTAGE = 27,
41 PACKET_TYPE_SUPPLY_VOLTAGE = 28,
42 PACKET_TYPE_LOG_BUFFER = 29,
43 PACKET_TYPE_ENABLE_JTAG = 30,
44 PACKET_TYPE_ACT_MOVE_PLUS = 31,
45 PACKET_TYPE_ACT_MOVE_MINUS = 32,
46 PACKET_TYPE_ACT_MOVE_PLUS_MINUS_DONE = 33,
47 PACKET_TYPE_STEPPER_POS_SET_WITHOUT_MOVE = 34,
48 PACKET_TYPE_ACT_POS_SET = 35,
49 PACKET_TYPE_ACT_MOVE_STOP = 36
50};
51
52
53enum TLogType
54{
55 LOGTYPE_EXEC = 0,
56 LOGTYPE_COMM = 1,
57 LOGTYPE_ENC = 2,
58 LOGTYPE_ACT = 3,
59 LOGTYPE_TOF = 4,
60 LOGTYPE_GPIO = 5
61};
62
63enum TLogEnc
64{
65 LOG_ENC_STEP = 0
66};
67
68enum TLogAct
69{
70 LOG_ACT_DELTA = 0,
71 LOG_ACT_CMD_START = 1,
72 LOG_ACT_CMD_FINISH = 2
73};
74
75enum TLogTOF
76{
77 LOG_TOF_INITIALIZED = 0,
78 LOG_TOF_TOFIN_TRANSITION_LOW_TO_HIGH = 1,
79 LOG_TOF_TOFIN_TRANSITION_HIGH_TO_LOW = 2,
80 LOG_TOF_TOFOUT_TRANSITION_LOW_TO_HIGH = 3,
81 LOG_TOF_TOFOUT_TRANSITION_HIGH_TO_LOW = 4
82}
83
84enum TGPIONum
85{
86 GPIO_TOF = 100
87}
88
89enum TLogGPIO
90{
91 LOG_GPIO_GPO20_SPIKE = 0
92};
93
94enum TLogExecution
95{
96 LOG_EXEC_MAIN_ENTRY_POINT = 0,
97};
98
99enum TGPIOValue
100{
101 LOW = 0,
102 HIGH = 1
103}
104
105
106
107class Request
108{
109 id: string | undefined;
110 command: Buffer | undefined;
111 answer_expected: boolean = true;
112
113 public constructor(init?: Partial<Request>)
114 {
115 Object.assign(this, init);
116 }
117}
118
119
120type TReturnPWB = Buffer | undefined;
121
122export class BoardPrintware implements InterfaceBoard
123{
124
125 private listeners_: Map<string, Function> = new Map();
126 private requests_: WaitQueue<Request> = new WaitQueue();
127 private requests_prio_: WaitQueue<Request> = new WaitQueue();
128 private responses_: WaitQueue<number> = new WaitQueue();
129 private actual_request_: string | undefined = undefined;
130 private port_: SerialPort;
131 private timeout_: NodeJS.Timeout | undefined = undefined;
132
133 private belt_speed_callback_: ((ips: number) => void) | undefined = undefined;
134 private page_ready_callback_: (() => void) | undefined = undefined;
135
136 private actuator_command_status_callback_: ((status_prm: TStatusCommandActuator) => void) | undefined = undefined;
137 private actuator_encoder_delta_callback_: ((delta_prm: number) => void) | undefined = undefined;
138
139
140
141 private snyc_byte_ = 0xA2;
142 private pwb_timeout_ms_ = 300;
143 private SERUTIL_ENCRYPTED_SYNC_FLAG = 129;
144 private SERUTIL_CLEAR_SYNC_FLAG = 1;
145 private SERUTIL_ENCRYPTED_ASYNC_FLAG = 130;
146 private SERUTIL_CLEAR_ASYNC_FLAG = 2;
147 private LOG_SIZE_BUF_DATA = 4;
148 private SERUTIL_REDUNDANCY = 2;
149
150 private incoming_buffer_: Uint8Array = new Uint8Array();
151
152 //private secret_key = process.env.RIPE_PWB_KEY || "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
153 private secret_key = process.env.RIPE_PWB_KEY || "862315379ce1590a42d214ac372bcb16f8e61660160eeb5d1e73d74fa8a700a0bf3931b84a068d1167960f986e73b9fab9a632383ca74071ce4d9fa71b65b9de965e4790c56f47076464ba742bb96ade936055828974aded3a6e2c1bba1d34219b278365e5516d4cf1f8bc10495d2a583dfb608c0ac9300b5bc5159be8cdef4ccf34c4789e7605c4dcc74bfd6b70a3f29e135a55de03f9494392c8731a04008f767c8005a283d889a2bb7fbd57cffd2bad161391c5e40d0de72c0e379b09e994abf91792dab6bd370f468c6d35dafd06e698e53bca7e784e70169c655591773f84c526df6cc296aa96765cdd571988f0266c14ae301879e1db96966b82223aae";
154 private secret_array: Uint8Array;
155
156 private last_encoder_data_: { step: number, log_id: number } | undefined = undefined;
157 private last_print_ready_spike_log_id_: number | undefined = undefined;
158 private last_actuator_command_log_id_: number | undefined = undefined;
159 private last_tofin_log_id_: number | undefined = undefined;
160 private last_tofout_log_id_: number | undefined = undefined;
161 private last_actuator_encoder_delta_log_id_: number | undefined = undefined;
162
163 private sentinel_bytes_ = Uint8Array.from([0x56, 0xF2, 0x8F, 0x03, 0x87, 0xC9, 0xF4, 0x98, 0x23]);
164 private checksum_bytes_ = Uint8Array.from([0xFF, 0x00, 0xAA]);
165
166 RegisterListenerPositionEncoderDeltaActuator(callback: (delta_prm: number) => void)
167 {
168 this.actuator_encoder_delta_callback_ = callback;
169 }
170
171 UnregisterListenerPositionEncoderDeltaActuator()
172 {
173 this.actuator_encoder_delta_callback_ = undefined;
174 }
175
176 RegisterListenerCommandStatusActuator(callback: (status_prm: TStatusCommandActuator) => void)
177 {
178 this.actuator_command_status_callback_ = callback;
179 }
180
181 UnregisterListenerCommandStatusActuator()
182 {
183 this.actuator_command_status_callback_ = undefined;
184 }
185
186
187 private getUint32From4Bytes(from: Buffer): number
188 {
189 return from[3] * 16777216 + from[2] * 65536 + from[1] * 256 + from[0];
190 }
191
192
193
194 constructor(port_prm: string)
195 {
196 this.port_ = new SerialPort(port_prm, {
197 baudRate: 38400
198 });
199 this.runRequestWorker();
200 this.secret_array = Uint8Array.from(Buffer.from(this.secret_key, 'hex'));
201 }
202
203
204 private decryptMessage(message: Uint8Array): Uint8Array
205 {
206 /* check if data is encrypted */
207 //console.log("decrypting: ",message);
208 if (message[this.SERUTIL_REDUNDANCY] == this.SERUTIL_ENCRYPTED_SYNC_FLAG || message[this.SERUTIL_REDUNDANCY] == this.SERUTIL_ENCRYPTED_ASYNC_FLAG)
209 {
210 /* decrypt data */
211 let seed: number = message[2 * this.SERUTIL_REDUNDANCY];
212 for (let i = 3 * this.SERUTIL_REDUNDANCY; i < message.length; i++)
213 {
214 /* never decode length byte */
215 if (i < 4 * this.SERUTIL_REDUNDANCY || i >= 4 * this.SERUTIL_REDUNDANCY + this.SERUTIL_REDUNDANCY)
216 {
217 message[i] ^= this.secret_array[seed];
218 seed++;
219 if (seed == 256) seed = 0;
220 }
221 }
222 }
223
224 message = Buffer.concat([this.incoming_buffer_.slice(0, this.SERUTIL_REDUNDANCY), message.slice(3 * this.SERUTIL_REDUNDANCY)]); /* remove sync byte and encryption */
225
226 return message;
227 }
228
229 private processLogEntry(entry: Uint8Array): void
230 {
231 //console.log("Processing entry... ", entry);
232 let log_id = 0;
233 log_id |= Number(entry[0]);
234 log_id |= Number(entry[1]) << 8;
235 log_id |= Number(entry[2]) << 16;
236 log_id |= Number(entry[3]) << 24;
237
238
239
240 //console.log("Log entry: ", log_id);
241
242 if (entry[4] == TLogType.LOGTYPE_EXEC)
243 {
244 if (entry[5] == TLogExecution.LOG_EXEC_MAIN_ENTRY_POINT)
245 {
246 /* board restart */
247 this.last_encoder_data_ = undefined;
248 this.last_print_ready_spike_log_id_ = undefined;
249 emitLog(LevelMessageLogEntry.WARN, "Board restarted...");
250 }
251 }
252 else if (entry[4] == TLogType.LOGTYPE_ENC)
253 {
254 let encoder_step = 0;
255 encoder_step |= Number(entry[6]);
256 encoder_step |= Number(entry[7]) << 8;
257 encoder_step |= Number(entry[8]) << 16;
258 encoder_step |= Number(entry[9]) << 24;
259
260 if (this.last_encoder_data_ !== undefined)
261 {
262 if (this.last_encoder_data_.log_id < log_id)
263 {
264 /* compute belt speed, new log generates in every second */
265 if (this.belt_speed_callback_ !== undefined) this.belt_speed_callback_((encoder_step - this.last_encoder_data_.step) / 2400.0);
266 this.last_encoder_data_ = { log_id: log_id, step: encoder_step };
267 }
268 }
269 else
270 {
271
272 this.last_encoder_data_ = { log_id: log_id, step: encoder_step };
273 }
274 }
275 else if (entry[4] == TLogType.LOGTYPE_GPIO && entry[5] == TLogGPIO.LOG_GPIO_GPO20_SPIKE)
276 {
277 //console.log("PROCESSING SPIKE ENTRY")
278 if (this.last_print_ready_spike_log_id_ !== undefined)
279 {
280 //console.log("LAST entry: ", this.last_print_ready_spike_log_id_);
281 //console.log("New log id: ", log_id);
282 if (this.last_print_ready_spike_log_id_ < log_id)
283 {
284 this.last_print_ready_spike_log_id_ = log_id;
285 emitLog(LevelMessageLogEntry.INFO, "Print ready spike registered");
286 if (this.page_ready_callback_ !== undefined) this.page_ready_callback_();
287 }
288 }
289 else
290 {
291 this.last_print_ready_spike_log_id_ = log_id;
292 emitLog(LevelMessageLogEntry.INFO, "Print ready spike registered");
293 if (this.page_ready_callback_ !== undefined) this.page_ready_callback_();
294 }
295 }
296 else if (entry[4] == TLogType.LOGTYPE_ACT)
297 {
298 if (entry[5] == TLogAct.LOG_ACT_CMD_START || entry[5] == TLogAct.LOG_ACT_CMD_FINISH)
299 {
300 if (this.last_actuator_command_log_id_ !== undefined)
301 {
302 if (this.last_actuator_command_log_id_ < log_id)
303 {
304 /* new log entry */
305 this.last_actuator_command_log_id_ = log_id;
306
307 if (this.actuator_command_status_callback_ !== undefined)
308 {
309 this.actuator_command_status_callback_(entry[5] == TLogAct.LOG_ACT_CMD_START ? TStatusCommandActuator.START : TStatusCommandActuator.FINISH);
310 }
311 }
312 }
313 else
314 {
315 /* new log entry */
316 this.last_actuator_command_log_id_ = log_id;
317
318 if (this.actuator_command_status_callback_ !== undefined)
319 {
320 this.actuator_command_status_callback_(entry[5] == TLogAct.LOG_ACT_CMD_START ? TStatusCommandActuator.START : TStatusCommandActuator.FINISH);
321 }
322 }
323 }
324 else if (entry[5] == TLogAct.LOG_ACT_DELTA)
325 {
326 let position = 0;
327 position |= Number(entry[6]);
328 position |= Number(entry[7]) << 8;
329 position |= Number(entry[8]) << 16;
330 position |= Number(entry[9]) << 24;
331 if (position >> 31 == 1)
332 {
333 position = ~position;
334 position += 1;
335 position &= 0xFFFFFFFF;
336 position *= -1;
337 }
338
339 if (this.last_actuator_encoder_delta_log_id_ !== undefined)
340 {
341 if (this.last_actuator_encoder_delta_log_id_ < log_id)
342 {
343 /* new log entry */
344 this.last_actuator_encoder_delta_log_id_ = log_id;
345
346 if (this.actuator_encoder_delta_callback_ !== undefined)
347 {
348 this.actuator_encoder_delta_callback_(position);
349 }
350 }
351 }
352 else
353 {
354 /* new log entry */
355 this.last_actuator_encoder_delta_log_id_ = log_id;
356 if (this.actuator_encoder_delta_callback_ !== undefined)
357 {
358 this.actuator_encoder_delta_callback_(position);
359 }
360 }
361 }
362 else emitLog(LevelMessageLogEntry.WARN, "Unprocessed actuator log entry: " + JSON.stringify(entry));
363 }
364 else if (entry[4] == TLogType.LOGTYPE_TOF)
365 {
366 //console.log(entry)
367 if (entry[5] == TLogTOF.LOG_TOF_TOFIN_TRANSITION_HIGH_TO_LOW || entry[5] == TLogTOF.LOG_TOF_TOFIN_TRANSITION_LOW_TO_HIGH)
368 {
369 if (this.last_tofin_log_id_ !== undefined)
370 {
371 if (this.last_tofin_log_id_ < log_id)
372 {
373 /* new log entry */
374 this.last_tofin_log_id_ = log_id;
375
376 emitLog(LevelMessageLogEntry.INFO, "TOF input change registered.");
377 }
378 }
379 else
380 {
381 /* new log entry */
382 this.last_tofin_log_id_ = log_id;
383
384 emitLog(LevelMessageLogEntry.INFO, "TOF input change registered.");
385 }
386 }
387 else if (entry[5] == TLogTOF.LOG_TOF_TOFOUT_TRANSITION_LOW_TO_HIGH || entry[5] == TLogTOF.LOG_TOF_TOFOUT_TRANSITION_HIGH_TO_LOW)
388 {
389 if (this.last_tofout_log_id_ !== undefined)
390 {
391 if (this.last_tofout_log_id_ < log_id)
392 {
393 /* new log entry */
394 this.last_tofout_log_id_ = log_id;
395
396 emitLog(LevelMessageLogEntry.INFO, "TOF output change registered.");
397 }
398 }
399 else
400 {
401 /* new log entry */
402 this.last_tofout_log_id_ = log_id;
403
404 emitLog(LevelMessageLogEntry.INFO, "TOF output change registered.");
405 }
406 }
407 else emitLog(LevelMessageLogEntry.WARN, "Unprocessed TOF log entry: " + JSON.stringify(entry));
408 }
409 else emitLog(LevelMessageLogEntry.WARN, "Unprocessed log entry: " + JSON.stringify(entry));
410
411 }
412
413 private processLogMessage(message: Uint8Array): void
414 {
415
416 /* determine number of entries received */
417 let nr_of_entries = message[2] / (this.LOG_SIZE_BUF_DATA + 6 /* 4 byte id, 1 byte logtype, 1 byte logmessage */);
418 for (let i = 0; i < nr_of_entries; i++)
419 {
420 let entry = message.slice(
421 3 + i * (this.LOG_SIZE_BUF_DATA + 6),
422 3 + i * (this.LOG_SIZE_BUF_DATA + 6) + (this.LOG_SIZE_BUF_DATA + 6));
423
424 this.processLogEntry(entry);
425 }
426
427 }
428
429 private checkMessageRedundancy(message: Uint8Array): boolean
430 {
431 if (message.length % this.SERUTIL_REDUNDANCY !== 0)
432 {
433 return false;
434 }
435 else
436 {
437 let redundancy_ok = true;
438 for (let i = 0; i < message.length && redundancy_ok; i += this.SERUTIL_REDUNDANCY)
439 {
440 for (let j = 1; j < this.SERUTIL_REDUNDANCY; j++)
441 {
442 if (message[i] !== message[i + j]) redundancy_ok = false;
443 }
444 }
445
446 return redundancy_ok;
447 }
448 }
449
450 private removeMessageRedundancy(message: Uint8Array): Uint8Array
451 {
452 let ret_array = new Uint8Array(message.length / this.SERUTIL_REDUNDANCY);
453 let j = 0;
454 for (let i = 0; i < message.length; i += this.SERUTIL_REDUNDANCY)
455 {
456 ret_array[j++] = message[i];
457 }
458 return ret_array;
459 }
460
461 private processMessage(message: Uint8Array): void
462 {
463 /* Check sentinel bytes first */
464 if (message.length - this.sentinel_bytes_.length - this.checksum_bytes_.length >= 5 * this.SERUTIL_REDUNDANCY)
465 {
466 let sentinel_ok = true;
467 let k = 0;
468 for (let i = message.length - this.sentinel_bytes_.length * this.SERUTIL_REDUNDANCY - this.checksum_bytes_.length * this.SERUTIL_REDUNDANCY; i < message.length - this.checksum_bytes_.length * this.SERUTIL_REDUNDANCY && sentinel_ok; i += this.SERUTIL_REDUNDANCY)
469 {
470 for (let j = 0; j < this.SERUTIL_REDUNDANCY; j++)
471 {
472 if (this.sentinel_bytes_[k] !== message[i + j]) sentinel_ok = false;
473 }
474 k++;
475 }
476
477
478
479 let checksum_byte = new Uint8Array(this.checksum_bytes_.length);
480 for (let i = 0; i < this.checksum_bytes_.length; i++)
481 {
482 checksum_byte[i] = this.checksum_bytes_[i];
483 }
484
485 for (let i = this.SERUTIL_REDUNDANCY; i < message.length - this.checksum_bytes_.length * this.SERUTIL_REDUNDANCY; i++)
486 {
487 for (let j = 0; j < this.checksum_bytes_.length; j++)
488 {
489 checksum_byte[j] ^= message[i];
490 }
491 }
492
493 let checksum_ok = true;
494 for (let j = 0; j < this.checksum_bytes_.length; j++)
495 {
496 if (checksum_byte[j] !== message[message.length - (this.checksum_bytes_.length * this.SERUTIL_REDUNDANCY) + (j * this.SERUTIL_REDUNDANCY)])
497 {
498 emitLog(LevelMessageLogEntry.ERROR, "Checksum shall be: " + checksum_byte[j] + " instead of " + message[message.length - (this.checksum_bytes_.length * this.SERUTIL_REDUNDANCY) + j]);
499 checksum_ok = false;
500 }
501 }
502
503
504
505
506
507 if (sentinel_ok && checksum_ok)
508 {
509 /* remove sentinel bytes and checksum bytes */
510 message = message.slice(0, message.length - this.sentinel_bytes_.length * this.SERUTIL_REDUNDANCY - this.checksum_bytes_.length * this.SERUTIL_REDUNDANCY);
511
512 for (let i = 0; i < this.SERUTIL_REDUNDANCY; i++)
513 {
514 message[4 * this.SERUTIL_REDUNDANCY + i] -= this.sentinel_bytes_.length;
515 message[4 * this.SERUTIL_REDUNDANCY + i] -= this.checksum_bytes_.length;
516 }
517
518
519 //console.log("Message length: ",message.length)
520
521 /* Check if data is async or sync */
522
523 if (message[this.SERUTIL_REDUNDANCY] == this.SERUTIL_CLEAR_SYNC_FLAG || message[this.SERUTIL_REDUNDANCY] == this.SERUTIL_ENCRYPTED_SYNC_FLAG)
524 {
525 //console.log("SYNC message received: ", message);
526 // sync
527 if (this.actual_request_ !== undefined)
528 {
529 //console.log("Actual request not undefined")
530 if (this.timeout_ !== undefined) { clearTimeout(this.timeout_); }
531 let func = this.actual_request_ ? this.listeners_.get(this.actual_request_) : undefined;
532 if (func)
533 {
534 //console.log("func not undefined")
535 message = this.decryptMessage(message);
536
537
538 /* check redundancy */
539
540 if (this.checkMessageRedundancy(message) === true)
541 {
542 message = this.removeMessageRedundancy(message);
543 func.call(this, message);
544 if (this.actual_request_) this.listeners_.delete(this.actual_request_);
545 this.actual_request_ = undefined;
546 this.responses_.push(1);
547 //console.log("RESPONSE pushed");
548 }
549 else
550 {
551 emitLog(LevelMessageLogEntry.ERROR, "Sync message redundancy error: " + JSON.stringify(message));
552 }
553 }
554
555 }
556 }
557 else if (message[this.SERUTIL_REDUNDANCY] == this.SERUTIL_ENCRYPTED_ASYNC_FLAG || message[this.SERUTIL_REDUNDANCY] == this.SERUTIL_CLEAR_ASYNC_FLAG)
558 {
559 //console.log("ASYNC");
560 message = this.decryptMessage(message);
561
562 /* check redundancy */
563
564 if (this.checkMessageRedundancy(message) === true)
565 {
566 message = this.removeMessageRedundancy(message);
567 //console.log("ASYNC message received: ", message);
568 if (message[1] == TPacket.PACKET_TYPE_LOG_BUFFER)
569 {
570 this.processLogMessage(message);
571 }
572 }
573 else
574 {
575 emitLog(LevelMessageLogEntry.ERROR, "Async message redundancy error: " + JSON.stringify(message));
576 }
577 }
578 else
579 {
580 emitLog(LevelMessageLogEntry.ERROR, "Message was not async or sync: " + JSON.stringify(message));
581 }
582 }
583 else
584 {
585 emitLog(LevelMessageLogEntry.ERROR, "Sentinel bytes or checksum are not correct: " + Buffer.from(message).toString('hex'));
586 }
587
588 }
589 else
590 {
591 emitLog(LevelMessageLogEntry.ERROR, "Message length is not correct, could not find sentinel bytes and checksum bytes: " + JSON.stringify(message));
592 }
593 }
594
595 private tryProcessBuffer(): void
596 {
597 //console.log("trying to process")
598
599
600 if (this.incoming_buffer_.length >= (5 + this.sentinel_bytes_.length + this.checksum_bytes_.length) * this.SERUTIL_REDUNDANCY)
601 {
602 //console.log("length fine")
603 /* there is a chance we have at least one complete message */
604 let sync_index = -1;
605 do
606 {
607 /* find first sync byte */
608 sync_index = this.incoming_buffer_.findIndex((element, index, array) => { return element == this.snyc_byte_ });
609 //console.log("SYNC index found: ", sync_index);
610 if (sync_index !== -1)
611 {
612
613 /* sync index found */
614 if (sync_index !== 0)
615 {
616 /* junk found in the buffer */
617 emitLog(LevelMessageLogEntry.WARN, "Junk found in buffer");
618
619 /*this.incoming_buffer_ = Buffer.concat([this.incoming_buffer_.slice(sync_index)]);
620 if (this.incoming_buffer_.length < 5 + this.sentinel_bytes_.length + this.checksum_bytes_.length)
621 {
622 this.incoming_buffer_ = new Uint8Array();
623 }*/
624
625 this.incoming_buffer_ = new Uint8Array();
626 }
627
628 //console.log("MESSAGE LENGTH: ",this.incoming_buffer_.length)
629
630
631 /* check length */
632 if (this.incoming_buffer_[4 * this.SERUTIL_REDUNDANCY] * this.SERUTIL_REDUNDANCY /* length byte */ + 5 * this.SERUTIL_REDUNDANCY /* headers */ <= this.incoming_buffer_.length)
633 {
634 /* complete message found */
635 //console.log("PROCESSING MESSAGE")
636 this.processMessage(Uint8Array.from(Buffer.from(Buffer.from(this.incoming_buffer_.slice(0, this.incoming_buffer_[4 * this.SERUTIL_REDUNDANCY] * this.SERUTIL_REDUNDANCY + 5 * this.SERUTIL_REDUNDANCY)).toString('hex'), 'hex')));
637
638 /* remove processed message from the buffer */
639 //console.log("LENGTH: ", this.incoming_buffer_.length, " Expected length: ", this.incoming_buffer_[4] /* length byte */ + 5 /* headers */)
640 if (this.incoming_buffer_.length === this.incoming_buffer_[4 * this.SERUTIL_REDUNDANCY] * this.SERUTIL_REDUNDANCY /* length byte */ + 5 * this.SERUTIL_REDUNDANCY /* headers */)
641 {
642 //console.log("clearing array")
643 this.incoming_buffer_ = new Uint8Array();
644 }
645 else
646 {
647 this.incoming_buffer_ = Buffer.concat([this.incoming_buffer_.slice(this.incoming_buffer_[4 * this.SERUTIL_REDUNDANCY] * this.SERUTIL_REDUNDANCY + 5 * this.SERUTIL_REDUNDANCY)]);
648 }
649 /*console.log("Remaining: ", this.incoming_buffer_.length);
650 if (this.incoming_buffer_.length > 0 && this.incoming_buffer_.length < 50)
651 {
652 console.log("alma");
653 }*/
654 }
655 else
656 {
657 /* ignore buffer */
658 emitLog(LevelMessageLogEntry.INFO, "Ignoring buffer, message did not arrive completely.");
659 sync_index = -1;
660 }
661 }
662 } while (sync_index !== -1);
663 }
664
665 //this.incoming_buffer_ = new Uint8Array();
666 }
667
668 private async runRequestWorker()
669 {
670
671 let parser = this.port_.pipe(new InterByteTimeout({ interval: 50 }));
672
673 this.port_.on("error", () =>
674 {
675 emitLog(LevelMessageLogEntry.ERROR, "Error on COM port");
676
677 this.port_.close();
678 setTimeout(() =>
679 {
680 this.port_.open();
681 }, 1000);
682 });
683
684 this.port_.on("open", () =>
685 {
686 parser.on("data", (data: any) =>
687 {
688 appendFileSync("incoming.dat", data);
689 //console.log("Data amount arrived: ", data.length)
690 //console.log("data arrived", data)
691 let new_buff = new Uint8Array(this.incoming_buffer_.length + data.length);
692 new_buff.set(this.incoming_buffer_);
693 new_buff.set(Uint8Array.from(data), this.incoming_buffer_.length);
694 this.incoming_buffer_ = new_buff;
695 this.tryProcessBuffer();
696 });
697
698 });
699
700
701 while (true)
702 {
703 let request = await this.requests_.shift();
704
705 if (this.requests_prio_.length !== 0)
706 {
707 /* put normal prio request back to queue, we have high prio task to do */
708 this.requests_.unshift(request);
709 request = await this.requests_prio_.shift();
710 }
711
712 if (request.command !== undefined && request.id !== undefined)
713 {
714
715 /* Check if message needs to be encoded */
716 //console.log(new Date().getTime(), "Actual: ", request.command)
717 if (request.command[1] == this.SERUTIL_ENCRYPTED_SYNC_FLAG)
718 {
719 let seed = Math.floor(Math.random() * 256);
720 request.command[2] = seed;
721 let actual_seed_byte_idx: number = seed;
722 for (let i = 3; i < request.command.length; i++)
723 {
724 /* never encode length byte */
725 if (i != 4)
726 {
727 request.command[i] ^= this.secret_array[actual_seed_byte_idx];
728 actual_seed_byte_idx++;
729 if (actual_seed_byte_idx == 256) actual_seed_byte_idx = 0;
730 }
731 }
732 }
733
734
735 /* add sentinel bytes */
736 request.command = Buffer.concat([request.command, Buffer.from(this.sentinel_bytes_)]);
737 request.command[4] += this.sentinel_bytes_.length;
738
739 /* add checksum bytes without sync byte */
740
741 let checksum_byte = new Uint8Array(this.checksum_bytes_.length);
742 for (let i = 0; i < this.checksum_bytes_.length; i++)
743 {
744 checksum_byte[i] = this.checksum_bytes_[i];
745 }
746
747 request.command[4] += checksum_byte.length;
748 for (let i = 1; i < request.command.length; i++)
749 {
750 for (let j = 0; j < checksum_byte.length; j++)
751 {
752 checksum_byte[j] ^= request.command[i];
753 }
754 }
755
756
757 request.command = Buffer.concat([request.command, Buffer.from(checksum_byte)]);
758
759
760
761
762 this.actual_request_ = request.id;
763 this.port_.write(request.command);
764
765
766 if (request.answer_expected)
767 {
768 this.timeout_ = setTimeout(() =>
769 {
770 this.actual_request_ = undefined;
771 this.responses_.push(0);
772 emitLog(LevelMessageLogEntry.WARN, "Timeout happened for request (" + request.id + "): " + JSON.stringify(request.command));
773 }, this.pwb_timeout_ms_);
774
775 await this.responses_.shift();
776 }
777 };
778
779 }
780 }
781
782
783 SetBeltSpeedCallback(callback: (ips: number) => void): void
784 {
785 this.belt_speed_callback_ = callback;
786 }
787
788 SetPageReadyCallback(callback: () => void): void
789 {
790 this.page_ready_callback_ = callback;
791 }
792
793 private getPingCommand(): Buffer
794 {
795 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_PING, 0]));
796 }
797
798 private getGetGPIOCommand(pin_prm: number): Buffer
799 {
800 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_GPIO_GET, 1, pin_prm]));
801 }
802
803 private getGetStepperPositonCommand(): Buffer
804 {
805 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_GET_STEPPER_POS, 0]));
806 }
807
808 private getGetTOFDelayCommand(): Buffer
809 {
810 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_TOF_GET_DELAY, 0]));
811 }
812
813 private getGetTOFCounterCommand(): Buffer
814 {
815 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_TOF_GET_COUNTER, 0]));
816 }
817
818 private getGetTOFPulseLengthCommand(): Buffer
819 {
820 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_TOF_GET_PULSE_LENGTH, 0]));
821 }
822
823 private getGetBeltEncoderPositonCommand(): Buffer
824 {
825 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_GET_BELT_ENCODER_POS, 0]));
826 }
827
828 private getGetActuatorEncoderPositonCommand(): Buffer
829 {
830 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_GET_ACTUATOR_ENCODER_POS, 0]));
831 }
832
833 private getShortPowerPulseCommand(): Buffer
834 {
835 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_POWER_PULSE, 1, 1]));
836 }
837
838 private getUniqueIdCommand(): Buffer
839 {
840 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_CLEAR_SYNC_FLAG, 0, TPacket.PACKET_TYPE_GET_UNIQUE_ID, 1, 1]));
841 }
842
843 private getLongPowerPulseCommand(): Buffer
844 {
845 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_POWER_PULSE, 1, 2]));
846 }
847
848 private getPowerInterruptCommand(): Buffer
849 {
850 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_INTERRUPT_POWER, 1, 0]));
851 }
852
853 private getGetAllGPIOValuesCommand(): Buffer
854 {
855 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_GPIO_GET_ALL, 0]));
856 }
857
858 private getMoveStepperStopCommand(): Buffer
859 {
860 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_ACT_MOVE_STOP, 0]));
861 }
862
863 private getGetPowerSupplyVoltageCommand(): Buffer
864 {
865 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_GET_SUPPLY_VOLTAGE, 0]));
866 }
867
868 private getSetActuatorEncoderPositionCommand(pos_prm: number): Buffer
869 {
870 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_ACT_POS_SET, 4,
871 Number((pos_prm & 0xFF)),
872 Number((pos_prm & 0xFF00) >> 8),
873 Number((pos_prm & 0xFF0000) >> 16),
874 Number((pos_prm & 0xFF000000) >> 24),
875 ]));
876 }
877
878
879 private getSetStepperPositonCommandWithoutMove(pos_prm: number): Buffer
880 {
881 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_STEPPER_POS_SET_WITHOUT_MOVE, 4,
882 Number((pos_prm & 0xFF)),
883 Number((pos_prm & 0xFF00) >> 8),
884 Number((pos_prm & 0xFF0000) >> 16),
885 Number((pos_prm & 0xFF000000) >> 24),
886 ]));
887 }
888
889
890 private getSetStepperPositonCommand(pos_prm: number): Buffer
891 {
892 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_SET_STEPPER_POS, 4,
893 Number((pos_prm & 0xFF)),
894 Number((pos_prm & 0xFF00) >> 8),
895 Number((pos_prm & 0xFF0000) >> 16),
896 Number((pos_prm & 0xFF000000) >> 24),
897 ]));
898 }
899
900 private getMoveStepperPlusCommand(pos_prm: number): Buffer
901 {
902 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_ACT_MOVE_PLUS, 4,
903 Number((pos_prm & 0xFF)),
904 Number((pos_prm & 0xFF00) >> 8),
905 Number((pos_prm & 0xFF0000) >> 16),
906 Number((pos_prm & 0xFF000000) >> 24),
907 ]));
908 }
909
910 private getMoveStepperMinusCommand(pos_prm: number): Buffer
911 {
912 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_ACT_MOVE_MINUS, 4,
913 Number((pos_prm & 0xFF)),
914 Number((pos_prm & 0xFF00) >> 8),
915 Number((pos_prm & 0xFF0000) >> 16),
916 Number((pos_prm & 0xFF000000) >> 24),
917 ]));
918 }
919
920 private getSetTOFDelayCommand(delay_prm: number): Buffer
921 {
922 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_TOF_SET_DELAY, 4,
923 Number((delay_prm & 0xFF)),
924 Number((delay_prm & 0xFF00) >> 8),
925 Number((delay_prm & 0xFF0000) >> 16),
926 Number((delay_prm & 0xFF000000) >> 24),
927 ]));
928 }
929
930 private getSetTOFPulseLengthCommand(pulse_length: number): Buffer
931 {
932 return Buffer.from(new Uint8Array([this.snyc_byte_, this.SERUTIL_ENCRYPTED_SYNC_FLAG, 0, TPacket.PACKET_TYPE_TOF_SET_PULSE_LENGTH, 4,
933 Number((pulse_length & 0xFF)),
934 Number((pulse_length & 0xFF00) >> 8),
935 Number((pulse_length & 0xFF0000) >> 16),
936 Number((pulse_length & 0xFF000000) >> 24),
937 ]));
938 }
939
940 async GetAllGPIOValues()
941 {
942 return new Promise<TGPIOQueryResult>(resolve =>
943 {
944 let request_id = uuid();
945 this.listeners_.set(request_id, (data: TReturnPWB) =>
946 {
947 if (data && data[1] == TPacket.PACKET_TYPE_GPIO_ALL)
948 {
949 //console.log(data);
950
951 /* Data length shall equal to the length defined in the message + sync byte + data length byte + packet type byte */
952 if (data.length == (data[2] + 3))
953 {
954 let ret: TGPIOQueryResult = new Map<number, TGPIOValue>();
955 for (var i = 0; i < (data[2] % 2 == 0 ? (data[2]) / 2 : ((data[2]) / 2) + 1); i++)
956 {
957 switch (data[3 + (i * 2) + 1])
958 {
959 case 0:
960 ret.set(data[3 + (i * 2)], TGPIOValue.LOW);
961 break;
962 case 1:
963 ret.set(data[3 + (i * 2)], TGPIOValue.HIGH);
964 break;
965 }
966 }
967 resolve(ret);
968 }
969 }
970 });
971 this.requests_.push(new Request({ id: request_id, command: this.getGetAllGPIOValuesCommand() }));
972 });
973 }
974
975 pad(n: any, width: any, z: any)
976 {
977 z = z || '0';
978 n = n + '';
979 return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
980 }
981
982 async GetUniqueId()
983 {
984 return new Promise<string>(resolve =>
985 {
986 let request_id = uuid();
987 this.listeners_.set(request_id, (data: TReturnPWB) =>
988 {
989 if (data && data.length === 11 && data[1] == TPacket.PACKET_TYPE_UNIQUE_ID)
990 {
991
992 let res: string = "";
993 for (var i = 0; i < 8; i++)
994 {
995 res = res.concat(this.pad(data[i + 3].toString(16), 2, '0'));
996 }
997
998 resolve(res);
999 }
1000 else
1001 {
1002 resolve("");
1003 }
1004 });
1005 this.requests_.push(new Request({ id: request_id, command: this.getUniqueIdCommand() }));
1006 });
1007 }
1008
1009 async PingEngine()
1010 {
1011 return new Promise<boolean>(resolve =>
1012 {
1013 let request_id = uuid();
1014 this.listeners_.set(request_id, (data: TReturnPWB) =>
1015 {
1016 if (data && data[1] == TPacket.PACKET_TYPE_PONG) resolve(true); else resolve(false);
1017 });
1018 this.requests_.push(new Request({ id: request_id, command: this.getPingCommand() }));
1019 });
1020 }
1021
1022 async TriggerPowerPulse(pulse_prm: TPowerPulse)
1023 {
1024 return new Promise<void>(resolve =>
1025 {
1026 let request_id = uuid();
1027 this.listeners_.set(request_id, (data: TReturnPWB) =>
1028 {
1029 resolve();
1030 });
1031 let command;
1032
1033 switch (pulse_prm)
1034 {
1035 case TPowerPulse.INTERRUPT_POWER:
1036 command = this.getPowerInterruptCommand();
1037 break;
1038
1039 case TPowerPulse.LONG:
1040 command = this.getLongPowerPulseCommand();
1041 break;
1042
1043 case TPowerPulse.SHORT:
1044 command = this.getShortPowerPulseCommand();
1045 break;
1046 }
1047
1048 this.requests_.push(new Request({ id: request_id, command: command }));
1049 });
1050 }
1051
1052 async SetActuatorEncoderPosition(pos_prm: number)
1053 {
1054 return new Promise<void>(resolve =>
1055 {
1056 let request_id = uuid();
1057 this.listeners_.set(request_id, (data: TReturnPWB) =>
1058 {
1059 resolve();
1060 });
1061 this.requests_.push(new Request({ id: request_id, command: this.getSetActuatorEncoderPositionCommand(pos_prm) }));
1062 });
1063 }
1064
1065 async SetStepperPositionWithoutMove(pos_prm: number)
1066 {
1067 return new Promise<void>(resolve =>
1068 {
1069 let request_id = uuid();
1070 this.listeners_.set(request_id, (data: TReturnPWB) =>
1071 {
1072 resolve();
1073 });
1074 this.requests_.push(new Request({ id: request_id, command: this.getSetStepperPositonCommandWithoutMove(pos_prm) }));
1075 });
1076 }
1077
1078 async SetStepperPosition(pos_prm: number)
1079 {
1080 return new Promise<void>(resolve =>
1081 {
1082 let request_id = uuid();
1083 this.listeners_.set(request_id, (data: TReturnPWB) =>
1084 {
1085 resolve();
1086 });
1087 this.requests_.push(new Request({ id: request_id, command: this.getSetStepperPositonCommand(pos_prm) }));
1088 });
1089 }
1090
1091 async ActuatorMoveStop()
1092 {
1093 return new Promise<void>(resolve =>
1094 {
1095 let request_id = uuid();
1096 /*this.listeners_.set(request_id, (data: TReturnPWB) =>
1097 {
1098 resolve();
1099 });*/
1100 this.requests_prio_.push(new Request({ id: request_id, command: this.getMoveStepperStopCommand(), answer_expected: false }));
1101 /* dummy request to trigger processing */
1102 this.requests_.push(new Request());
1103 });
1104 }
1105
1106 async ActuatorMoveDown(pos_prm: number)
1107 {
1108 return new Promise<void>(resolve =>
1109 {
1110 let request_id = uuid();
1111 /*this.listeners_.set(request_id, (data: TReturnPWB) =>
1112 {
1113 resolve();
1114 });*/
1115 this.requests_prio_.push(new Request({ id: request_id, command: this.getMoveStepperMinusCommand(pos_prm), answer_expected: false }));
1116 /* dummy request to trigger processing */
1117 this.requests_.push(new Request());
1118 });
1119 }
1120
1121 async ActuatorMoveUp(pos_prm: number)
1122 {
1123 return new Promise<void>(resolve =>
1124 {
1125 let request_id = uuid();
1126 /*this.listeners_.set(request_id, (data: TReturnPWB) =>
1127 {
1128 resolve();
1129 });*/
1130 this.requests_prio_.push(new Request({ id: request_id, command: this.getMoveStepperPlusCommand(pos_prm), answer_expected: false }));
1131 /* dummy request to trigger processing */
1132 this.requests_.push(new Request());
1133 });
1134 }
1135
1136 async SetTOFDelay(delay_prm: number)
1137 {
1138 return new Promise<void>(resolve =>
1139 {
1140 let request_id = uuid();
1141 this.listeners_.set(request_id, (data: TReturnPWB) =>
1142 {
1143 resolve();
1144 });
1145 this.requests_.push(new Request({ id: request_id, command: this.getSetTOFDelayCommand(delay_prm) }));
1146 });
1147 }
1148
1149 async SetTOFPulseLength(pulse_length_prm: number)
1150 {
1151 return new Promise<void>(resolve =>
1152 {
1153 let request_id = uuid();
1154 this.listeners_.set(request_id, (data: TReturnPWB) =>
1155 {
1156 resolve();
1157 });
1158 this.requests_.push(new Request({ id: request_id, command: this.getSetTOFPulseLengthCommand(pulse_length_prm) }));
1159 });
1160 }
1161
1162 async GetBeltEncoderPosition()
1163 {
1164 return new Promise<number>(resolve =>
1165 {
1166 let request_id = uuid();
1167 this.listeners_.set(request_id, (data: TReturnPWB) =>
1168 {
1169 if (data && data.length == 7 && data[1] == TPacket.PACKET_TYPE_BELT_ENCODER_POS)
1170 {
1171 let position = 0;
1172 position |= Number(data[3]);
1173 position |= Number(data[4]) << 8;
1174 position |= Number(data[5]) << 16;
1175 position |= Number(data[6]) << 24;
1176 if (position >> 31 == 1)
1177 {
1178 position = ~position;
1179 position += 1;
1180 position &= 0xFFFFFFFF;
1181 position *= -1;
1182 }
1183
1184 resolve(position);
1185 }
1186 else
1187 {
1188 resolve(-999999);
1189 }
1190 });
1191 this.requests_.push(new Request({ id: request_id, command: this.getGetBeltEncoderPositonCommand() }));
1192 });
1193 }
1194
1195 async GetActuatorEncoderPosition()
1196 {
1197 return new Promise<number>(resolve =>
1198 {
1199 let request_id = uuid();
1200 this.listeners_.set(request_id, (data: TReturnPWB) =>
1201 {
1202 if (data && data.length == 7 && data[1] == TPacket.PACKET_TYPE_ACTUATOR_ENCODER_POS)
1203 {
1204 let position = 0;
1205 position |= Number(data[3]);
1206 position |= Number(data[4]) << 8;
1207 position |= Number(data[5]) << 16;
1208 position |= Number(data[6]) << 24;
1209 if (position >> 31 == 1)
1210 {
1211 position = ~position;
1212 position += 1;
1213 position &= 0xFFFFFFFF;
1214 position *= -1;
1215 }
1216 resolve(position);
1217 }
1218 else
1219 {
1220 resolve(2147483647); /* invalid value: 0x7FFFFFFF */
1221 }
1222 });
1223 this.requests_.push(new Request({ id: request_id, command: this.getGetActuatorEncoderPositonCommand() }));
1224 });
1225 }
1226
1227
1228 async GetPowerSupplyVoltage()
1229 {
1230 return new Promise<number>(resolve =>
1231 {
1232 let request_id = uuid();
1233 this.listeners_.set(request_id, (data: TReturnPWB) =>
1234 {
1235 if (data && data.length == 7 && data[1] == TPacket.PACKET_TYPE_SUPPLY_VOLTAGE)
1236 {
1237 let voltage = 0;
1238 voltage |= Number(data[3]);
1239 voltage |= Number(data[4]) << 8;
1240 voltage |= Number(data[5]) << 16;
1241 voltage |= Number(data[6]) << 24;
1242 if (voltage >> 31 == 1)
1243 {
1244 voltage = ~voltage;
1245 voltage += 1;
1246 voltage &= 0xFFFFFFFF;
1247 voltage *= -1;
1248 }
1249 resolve(voltage / 1000.0);
1250 }
1251 else
1252 {
1253 resolve(-999999);
1254 }
1255 });
1256 this.requests_.push(new Request({ id: request_id, command: this.getGetPowerSupplyVoltageCommand() }));
1257 });
1258 }
1259
1260
1261
1262 async GetStepperPosition()
1263 {
1264 return new Promise<number>(resolve =>
1265 {
1266 let request_id = uuid();
1267 this.listeners_.set(request_id, (data: TReturnPWB) =>
1268 {
1269 if (data && data.length == 7 && data[1] == TPacket.PACKET_TYPE_STEPPER_POS)
1270 {
1271 let position = 0;
1272 position |= Number(data[3]);
1273 position |= Number(data[4]) << 8;
1274 position |= Number(data[5]) << 16;
1275 position |= Number(data[6]) << 24;
1276 if (position >> 31 == 1)
1277 {
1278 position = ~position;
1279 position += 1;
1280 position &= 0xFFFFFFFF;
1281 position *= -1;
1282 }
1283
1284 resolve(position);
1285 }
1286 else
1287 {
1288 resolve(2147483647); /* invalid value: 0x7FFFFFFF */
1289 }
1290 });
1291 this.requests_.push(new Request({ id: request_id, command: this.getGetStepperPositonCommand() }));
1292 });
1293 }
1294
1295 async GetTOFSensor()
1296 {
1297 return new Promise<TTOFValue>(resolve =>
1298 {
1299 let request_id = uuid();
1300 this.listeners_.set(request_id, (data: TReturnPWB) =>
1301 {
1302 if (data && data.length == 5 && data[1] == TPacket.PACKET_TYPE_GPIO_SINGLE)
1303 {
1304 switch (data[4])
1305 {
1306 case TGPIOValue.LOW:
1307 resolve(TTOFValue.NOT_PRESENT);
1308 break;
1309
1310 case TGPIOValue.HIGH:
1311 resolve(TTOFValue.PRESENT);
1312 break;
1313
1314 default:
1315 resolve(TTOFValue.UNKNOWN);
1316 }
1317 }
1318 else
1319 {
1320 //console.log(data);
1321 resolve(TTOFValue.UNKNOWN);
1322 }
1323 });
1324 this.requests_.push(new Request({ id: request_id, command: this.getGetGPIOCommand(TGPIONum.GPIO_TOF) }));
1325 });
1326 }
1327
1328 async GetTOFDelay()
1329 {
1330 return new Promise<number>(resolve =>
1331 {
1332 let request_id = uuid();
1333 this.listeners_.set(request_id, (data: TReturnPWB) =>
1334 {
1335 if (data && data.length == 7 && data[1] == TPacket.PACKET_TYPE_TOF_DELAY)
1336 {
1337 let res = this.getUint32From4Bytes(data.slice(3));
1338 resolve(res);
1339 }
1340 else
1341 {
1342 resolve(4294967294); /* invalid tof delay: 0xFFFFFFFE */
1343 }
1344 });
1345 this.requests_.push(new Request({ id: request_id, command: this.getGetTOFDelayCommand() }));
1346 });
1347 }
1348
1349 async GetTOFCounter()
1350 {
1351 return new Promise<number>(resolve =>
1352 {
1353 let request_id = uuid();
1354 this.listeners_.set(request_id, (data: TReturnPWB) =>
1355 {
1356 if (data && data.length == 7 && data[1] == TPacket.PACKET_TYPE_TOF_COUNTER)
1357 {
1358 //console.log(data);
1359 let res = this.getUint32From4Bytes(data.slice(3));
1360 resolve(res);
1361 }
1362 else
1363 {
1364 resolve(999999);
1365 }
1366 });
1367 this.requests_.push(new Request({ id: request_id, command: this.getGetTOFCounterCommand() }));
1368 });
1369 }
1370
1371 async GetTOFPulseLength()
1372 {
1373 return new Promise<number>(resolve =>
1374 {
1375 let request_id = uuid();
1376 this.listeners_.set(request_id, (data: TReturnPWB) =>
1377 {
1378 if (data && data.length == 7 && data[1] == TPacket.PACKET_TYPE_TOF_PULSE_LENGTH)
1379 {
1380 let res = this.getUint32From4Bytes(data.slice(3));
1381 resolve(res);
1382 }
1383 else
1384 {
1385 resolve(999999);
1386 }
1387 });
1388 this.requests_.push(new Request({ id: request_id, command: this.getGetTOFPulseLengthCommand() }));
1389 });
1390 }
1391
1392
1393}
1394