incyclist-devices 2.0.31 → 2.0.33

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.
@@ -14,6 +14,7 @@ export declare class SerialIncyclistDevice extends ControllableDevice {
14
14
  isEqual(settings: SerialDeviceSettings): boolean;
15
15
  getPort(): string;
16
16
  getUniqueName(): string;
17
+ getSerialInterface(): SerialInterface;
17
18
  getInterface(): string;
18
19
  setMaxUpdateFrequency(ms: number): void;
19
20
  setPullFrequency(ms: number): void;
@@ -40,6 +40,9 @@ class SerialIncyclistDevice extends adpater_1.ControllableDevice {
40
40
  getUniqueName() {
41
41
  return `${this.getName()} (${this.getPort()})`;
42
42
  }
43
+ getSerialInterface() {
44
+ throw new Error('not implemented');
45
+ }
43
46
  getInterface() {
44
47
  return 'serial';
45
48
  }
@@ -7,14 +7,14 @@ export interface TCPOpenOptions extends OpenOptions {
7
7
  timeout?: number;
8
8
  }
9
9
  export declare interface TCPBindingInterface<T extends BindingPortInterface = BindingPortInterface, R extends OpenOptions = OpenOptions, P extends PortInfo = PortInfo> extends BindingInterface<TCPPortBinding, TCPOpenOptions> {
10
- list(port?: number): Promise<P[]>;
10
+ list(port?: number, excludeList?: string[]): Promise<P[]>;
11
11
  }
12
12
  export declare class CanceledError extends Error {
13
13
  canceled: true;
14
14
  constructor(message: string);
15
15
  }
16
16
  export declare function scanPort(host: string, port: number): Promise<boolean>;
17
- export declare function scanSubNet(sn: string, port: number): Promise<string[]>;
17
+ export declare function scanSubNet(sn: string, port: number, excludeHosts?: string[]): Promise<string[]>;
18
18
  export declare function getSubnets(): string[];
19
19
  export declare const TCPBinding: TCPBindingInterface;
20
20
  export declare class TCPPortBinding implements BindingPortInterface {
@@ -50,10 +50,11 @@ function scanPort(host, port) {
50
50
  });
51
51
  }
52
52
  exports.scanPort = scanPort;
53
- function scanSubNet(sn, port) {
53
+ function scanSubNet(sn, port, excludeHosts) {
54
54
  const range = [];
55
55
  for (let i = 1; i < 255; i++)
56
- range.push(i);
56
+ if (!excludeHosts || !excludeHosts.includes(`${sn}.${i}`))
57
+ range.push(i);
57
58
  return Promise.all(range.map(j => scanPort(`${sn}.${j}`, port).then(success => success ? `${sn}.${j}` : null).catch()))
58
59
  .then(hosts => hosts.filter(h => h !== null))
59
60
  .catch();
@@ -86,13 +87,14 @@ function getSubnets() {
86
87
  }
87
88
  exports.getSubnets = getSubnets;
88
89
  exports.TCPBinding = {
89
- list(port) {
90
+ list(port, excludeList) {
90
91
  return __awaiter(this, void 0, void 0, function* () {
91
92
  if (!port)
92
93
  return [];
93
94
  const subnets = getSubnets();
94
- const hosts = [];
95
- yield Promise.all(subnets.map(sn => scanSubNet(sn, port).then(found => { hosts.push(...found); })));
95
+ let hosts = [];
96
+ const excludeHosts = excludeList.map(e => e && e.includes(':') ? e.split(':')[0] : e);
97
+ yield Promise.all(subnets.map(sn => scanSubNet(sn, port, excludeHosts).then(found => { hosts.push(...found); })));
96
98
  return hosts.map(host => ({
97
99
  path: `${host}:${port}`,
98
100
  manufacturer: undefined,
@@ -199,8 +199,10 @@ class DaumAdapterBase extends adapter_1.SerialIncyclistDevice {
199
199
  if (this.stopped)
200
200
  return Promise.resolve(true);
201
201
  this.logEvent({ message: 'stop request' });
202
+ if (this.paused)
203
+ this.resume();
202
204
  this.stopped = true;
203
- return new Promise((resolve, reject) => {
205
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
204
206
  try {
205
207
  if (this.iv) {
206
208
  if (this.iv.sync)
@@ -211,15 +213,15 @@ class DaumAdapterBase extends adapter_1.SerialIncyclistDevice {
211
213
  }
212
214
  if (this.bike.stopWorker && typeof this.bike.stopWorker === 'function')
213
215
  this.bike.stopWorker();
216
+ yield this.bike.close();
214
217
  this.logEvent({ message: 'stop request completed' });
215
- this.paused = undefined;
216
218
  resolve(true);
217
219
  }
218
220
  catch (err) {
219
221
  this.logEvent({ message: 'stop error', error: err.message });
220
222
  reject(err);
221
223
  }
222
- });
224
+ }));
223
225
  }
224
226
  canSendUpdate() {
225
227
  if (this.paused || this.stopped)
@@ -2,6 +2,7 @@ import CyclingMode from '../../../modes/cycling-mode';
2
2
  import DaumAdapter from '../DaumAdapter';
3
3
  import { DeviceProperties } from '../../../types/device';
4
4
  import { SerialDeviceSettings } from '../../adapter';
5
+ import SerialInterface from '../../serial-interface';
5
6
  export interface DaumClassicDeviceProperties extends DeviceProperties {
6
7
  gear?: number;
7
8
  }
@@ -21,6 +22,7 @@ export default class DaumClassicAdapter extends DaumAdapter {
21
22
  getProtocolName(): string;
22
23
  getSupportedCyclingModes(): Array<any>;
23
24
  getDefaultCyclingMode(): CyclingMode;
25
+ getSerialInterface(): SerialInterface;
24
26
  check(): Promise<boolean>;
25
27
  performCheck(): Promise<boolean>;
26
28
  pause(): Promise<boolean>;
@@ -80,6 +80,10 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
80
80
  getDefaultCyclingMode() {
81
81
  return new daum_classic_1.default(this);
82
82
  }
83
+ getSerialInterface() {
84
+ var _a;
85
+ return (_a = this.bike) === null || _a === void 0 ? void 0 : _a.serial;
86
+ }
83
87
  check() {
84
88
  return __awaiter(this, void 0, void 0, function* () {
85
89
  if (this.isStopped())
@@ -1,4 +1,5 @@
1
1
  import { DeviceProperties } from '../../../types/device';
2
+ import { SerialInterface } from '../..';
2
3
  import { SerialDeviceSettings } from '../../adapter';
3
4
  import { SerialCommProps } from '../../comm';
4
5
  import DaumAdapter from '../DaumAdapter';
@@ -14,6 +15,7 @@ export default class DaumPremiumAdapter extends DaumAdapter {
14
15
  getPort(): any;
15
16
  getInterface(): string;
16
17
  getProtocolName(): string;
18
+ getSerialInterface(): SerialInterface;
17
19
  isEqual(settings: SerialDeviceSettings): boolean;
18
20
  getSupportedCyclingModes(): Array<any>;
19
21
  check(): Promise<boolean>;
@@ -90,6 +90,10 @@ class DaumPremiumAdapter extends DaumAdapter_1.default {
90
90
  getProtocolName() {
91
91
  return PROTOCOL_NAME;
92
92
  }
93
+ getSerialInterface() {
94
+ var _a;
95
+ return (_a = this.bike) === null || _a === void 0 ? void 0 : _a.serial;
96
+ }
93
97
  isEqual(settings) {
94
98
  if (this.getInterface() === device_1.INTERFACE.TCPIP) {
95
99
  const as = this.settings;
@@ -186,9 +190,7 @@ class DaumPremiumAdapter extends DaumAdapter_1.default {
186
190
  const { route, onStatusUpdate, gear } = props;
187
191
  var info = {};
188
192
  this.initData();
189
- if (isRelaunch) {
190
- yield this.stop();
191
- }
193
+ yield this.stop();
192
194
  return (0, utils_1.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () {
193
195
  try {
194
196
  yield this.connect();
@@ -240,7 +242,7 @@ class DaumPremiumAdapter extends DaumAdapter_1.default {
240
242
  if (!this.bike.isConnected()) {
241
243
  const connected = yield this.bike.connect();
242
244
  if (!connected)
243
- return;
245
+ throw new Error('not connected');
244
246
  }
245
247
  return this.getBike().getTrainingData();
246
248
  });
@@ -1,13 +1,39 @@
1
1
  /// <reference types="node" />
2
2
  import { ReservedCommands } from './utils';
3
3
  import { SerialInterface, SerialPortProvider } from '../..';
4
- import { Queue } from '../../../utils/utils';
5
4
  import { EventLogger } from 'gd-eventlog';
6
5
  import { User } from "../../../types/user";
7
6
  import { Route } from "../../../types/route";
8
7
  import { SerialCommProps } from "../../comm";
9
8
  import { SerialPortStream } from "@serialport/stream";
10
9
  import { OnDeviceStartCallback } from "./types";
10
+ import { Queue } from "../../../utils/utils";
11
+ export type ResponseObject = {
12
+ type: ResponseType;
13
+ data?: string;
14
+ error?: Error;
15
+ };
16
+ export type ResponseType = 'ACK' | 'NAK' | 'Response' | 'Error';
17
+ export type Daum8iCommsState = {
18
+ waitingForStart?: boolean;
19
+ waitingForACK?: boolean;
20
+ waitingForEnd?: boolean;
21
+ partialCmd?: any;
22
+ data: Queue<ResponseObject>;
23
+ };
24
+ export type ConnectionState = 'Connecting' | 'Connected' | 'Disconnected' | 'Disconnecting';
25
+ export declare class CheckSumError extends Error {
26
+ constructor();
27
+ }
28
+ export declare class ACKTimeout extends Error {
29
+ constructor();
30
+ }
31
+ export declare class BusyTimeout extends Error {
32
+ constructor();
33
+ }
34
+ export declare class ResponseTimeout extends Error {
35
+ constructor();
36
+ }
11
37
  export default class Daum8i {
12
38
  logger: EventLogger;
13
39
  serial: SerialInterface;
@@ -18,17 +44,16 @@ export default class Daum8i {
18
44
  };
19
45
  port: string;
20
46
  settings: any;
21
- sp: SerialPortStream;
22
47
  props: any;
23
- connected: boolean;
24
- blocked: boolean;
25
- state: any;
48
+ protected sp: SerialPortStream;
49
+ protected connectState: ConnectionState;
50
+ protected connectPromise: Promise<SerialPortStream>;
51
+ protected disconnectPromise: Promise<boolean>;
52
+ protected writePromise: Promise<void>;
53
+ protected sendCmdPromise: Promise<string>;
54
+ protected actualBikeType?: string;
55
+ protected recvState: Daum8iCommsState;
26
56
  bikeData: any;
27
- processor: any;
28
- error: Error;
29
- queue: Queue<any>;
30
- cmdCurrent: any;
31
- cmdStart: number;
32
57
  isLoggingPaused: boolean;
33
58
  spp: SerialPortProvider;
34
59
  serialportProps: any;
@@ -40,29 +65,25 @@ export default class Daum8i {
40
65
  resumeLogging(): void;
41
66
  logEvent(e: any): void;
42
67
  connect(): Promise<boolean>;
68
+ closePort(): Promise<boolean>;
69
+ cleanupPort(): void;
43
70
  close(): Promise<boolean>;
44
71
  flush(): Promise<void>;
45
- getLogState(): {
46
- sending: any;
47
- busy: any;
48
- writeBusy: any;
49
- opening: any;
50
- connecting: any;
51
- waitingForStart: any;
52
- waitingForEnd: any;
53
- waitingForAck: any;
54
- retry: any;
55
- };
56
72
  onPortClose(): Promise<void>;
57
- onPortError(error: any): Promise<void>;
58
- forceClose(updateState?: boolean): Promise<void>;
59
- sendTimeout(message: any): void;
60
- checkForResponse(): boolean;
73
+ onPortError(error: Error): Promise<void>;
74
+ isSending(): boolean;
75
+ rejectCurrent(error: Error): void;
61
76
  getTimeoutValue(cmd?: any): number;
62
77
  onData(data: any, depth?: number): any;
78
+ waitWithTimeout(promise: Promise<any>, timeout: number, onTimeout?: () => void): Promise<any>;
63
79
  sendDaum8iCommand(command: string, payload?: string | any[]): Promise<string>;
64
- writeDone(): void;
65
- write(buffer: Buffer): Promise<void>;
80
+ onIgnored(payload: string): void;
81
+ onACK(): void;
82
+ onNAK: () => void;
83
+ waitForACK(): Promise<boolean>;
84
+ waitForResponse(): Promise<string>;
85
+ portWrite(buffer: Buffer): Promise<void>;
86
+ write(buffer: Buffer, ackExpected?: boolean): Promise<void>;
66
87
  sendACK(): Promise<void>;
67
88
  sendNAK(): Promise<void>;
68
89
  sendReservedDaum8iCommand(command: ReservedCommands, data?: Buffer): Promise<any[]>;
@@ -9,9 +9,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ResponseTimeout = exports.BusyTimeout = exports.ACKTimeout = exports.CheckSumError = void 0;
12
13
  const constants_1 = require("../constants");
13
14
  const utils_1 = require("./utils");
14
15
  const gd_eventlog_1 = require("gd-eventlog");
16
+ const utils_2 = require("../../../utils/utils");
15
17
  const DEFAULT_TIMEOUT = 10000;
16
18
  const MAX_DATA_BLOCK_SIZE = 512;
17
19
  const DS_BITS_OFF = 0;
@@ -34,9 +36,38 @@ const validatePath = (path) => {
34
36
  const port = parts[1];
35
37
  return `${host}:${port}`;
36
38
  };
37
- const drain = (sp) => new Promise(resolve => { sp.drain(resolve); });
39
+ class CheckSumError extends Error {
40
+ constructor() {
41
+ super();
42
+ this.message = 'checksum incorrect';
43
+ }
44
+ }
45
+ exports.CheckSumError = CheckSumError;
46
+ class ACKTimeout extends Error {
47
+ constructor() {
48
+ super();
49
+ this.message = 'ACK timeout';
50
+ }
51
+ }
52
+ exports.ACKTimeout = ACKTimeout;
53
+ class BusyTimeout extends Error {
54
+ constructor() {
55
+ super();
56
+ this.message = 'BUSY timeout';
57
+ }
58
+ }
59
+ exports.BusyTimeout = BusyTimeout;
60
+ class ResponseTimeout extends Error {
61
+ constructor() {
62
+ super();
63
+ this.message = 'RESP timeout';
64
+ }
65
+ }
66
+ exports.ResponseTimeout = ResponseTimeout;
38
67
  class Daum8i {
39
68
  constructor(props) {
69
+ this.onNAK = () => {
70
+ };
40
71
  this.props = props || {};
41
72
  const { logger, serial, path } = props;
42
73
  this.serial = serial;
@@ -44,12 +75,9 @@ class Daum8i {
44
75
  const w = global.window;
45
76
  this.logger = logger || ((w === null || w === void 0 ? void 0 : w.DEVICE_DEBUG) || process.env.DEBUG ? DEBUG_LOGGER : new gd_eventlog_1.EventLogger('DaumPremium'));
46
77
  this.isLoggingPaused = false;
47
- this.connected = false;
48
- this.blocked = false;
49
- this.state = {
50
- ack: { wait: false, startWait: undefined },
51
- commandsInQueue: {},
52
- };
78
+ this.connectState = 'Disconnected';
79
+ this.connectPromise = null;
80
+ this.recvState = { data: new utils_2.Queue() };
53
81
  this.settings = {};
54
82
  this.bikeData = {
55
83
  userWeight: 75,
@@ -65,7 +93,7 @@ class Daum8i {
65
93
  return this.path;
66
94
  }
67
95
  isConnected() {
68
- return this.connected;
96
+ return this.connectState === 'Connected' || this.connectState === 'Disconnecting';
69
97
  }
70
98
  pauseLogging() {
71
99
  this.isLoggingPaused = true;
@@ -87,159 +115,124 @@ class Daum8i {
87
115
  if (this.isConnected() && this.sp) {
88
116
  return true;
89
117
  }
118
+ if (this.connectState === 'Connecting') {
119
+ if (this.connectPromise) {
120
+ try {
121
+ yield this.connectPromise;
122
+ }
123
+ catch (_a) {
124
+ }
125
+ }
126
+ return this.isConnected();
127
+ }
90
128
  try {
91
- const port = yield this.serial.openPort(this.path);
129
+ this.connectState = 'Connecting';
130
+ this.connectPromise = this.serial.openPort(this.path);
131
+ const port = yield this.connectPromise;
132
+ this.connectPromise = null;
92
133
  if (port !== null) {
93
- this.connected = true;
134
+ this.connectState = 'Connected';
94
135
  this.sp = port;
95
136
  this.sp.on('close', this.onPortClose.bind(this));
96
- this.sp.on('error', (error) => { this.onPortError(error); });
97
- this.sp.on('data', (data) => { this.onData(data); });
137
+ this.sp.on('error', this.onPortError.bind(this));
138
+ this.sp.on('data', this.onData.bind(this));
98
139
  return true;
99
140
  }
100
141
  else {
142
+ this.connectState = 'Disconnected';
101
143
  return false;
102
144
  }
103
145
  }
104
- catch (_a) {
146
+ catch (_b) {
147
+ this.connectState = 'Disconnected';
105
148
  return false;
106
149
  }
107
150
  });
108
151
  }
152
+ closePort() {
153
+ return __awaiter(this, void 0, void 0, function* () {
154
+ if (!this.sp)
155
+ return true;
156
+ try {
157
+ yield this.flush();
158
+ yield this.serial.closePort(this.path);
159
+ return true;
160
+ }
161
+ catch (err) {
162
+ this.logEvent({ message: 'could not close ', reason: err.message });
163
+ return false;
164
+ }
165
+ });
166
+ }
167
+ cleanupPort() {
168
+ if (this.sp) {
169
+ this.sp.removeAllListeners();
170
+ }
171
+ this.sp = null;
172
+ this.recvState.data.clear();
173
+ }
109
174
  close() {
110
175
  return __awaiter(this, void 0, void 0, function* () {
111
- if (this.isConnected() && this.serial && this.sp) {
176
+ let isDisconnected = false;
177
+ if (this.disconnectPromise) {
112
178
  try {
113
- yield this.flush();
114
- yield this.serial.closePort(this.path);
179
+ isDisconnected = yield this.disconnectPromise;
115
180
  }
116
- catch (err) {
117
- this.logEvent({ message: 'could not close ', reason: err.message });
118
- return false;
181
+ catch (_a) {
119
182
  }
183
+ return isDisconnected;
120
184
  }
121
- this.connected = false;
122
- if (this.sp) {
123
- this.sp.removeAllListeners();
124
- this.sp = null;
185
+ if (this.connectState === 'Disconnected') {
186
+ this.cleanupPort();
187
+ return true;
125
188
  }
126
- return true;
189
+ else if (this.connectState === 'Disconnecting' || this.connectState === 'Connected' || this.connectState === 'Connecting') {
190
+ this.connectState = 'Disconnecting';
191
+ this.disconnectPromise = this.closePort();
192
+ isDisconnected = yield this.disconnectPromise;
193
+ this.connectPromise = null;
194
+ this.disconnectPromise = null;
195
+ if (isDisconnected)
196
+ this.connectState = 'Disconnected';
197
+ this.cleanupPort();
198
+ }
199
+ return isDisconnected;
127
200
  });
128
201
  }
129
202
  flush() {
130
203
  return __awaiter(this, void 0, void 0, function* () {
131
- if (!this.state.writeBusy)
132
- return;
133
- return new Promise(done => {
134
- const iv = setInterval(() => {
135
- if (!this.state.writeBusy) {
136
- clearInterval(iv);
137
- this.writeDone();
138
- done();
139
- }
140
- }, 100);
141
- });
204
+ if (this.writePromise) {
205
+ yield this.waitWithTimeout(this.writePromise, 1000);
206
+ this.writePromise = null;
207
+ }
142
208
  });
143
209
  }
144
- getLogState() {
145
- let s = undefined;
146
- const { sending, busy, opening, connecting, writeBusy, waitingForStart, waitingForAck, waitingForEnd, retry } = this.state;
147
- if (sending) {
148
- s = {};
149
- s.command = sending.command;
150
- s.payload = sending.payload;
151
- }
152
- return { sending: s, busy, writeBusy, opening, connecting, waitingForStart, waitingForEnd, waitingForAck, retry };
153
- }
154
210
  onPortClose() {
155
211
  return __awaiter(this, void 0, void 0, function* () {
156
- this.connected = false;
157
- if (this.sp) {
158
- this.sp.removeAllListeners();
159
- this.sp = null;
160
- }
212
+ if (this.connectState !== 'Disconnected' && this.connectState !== 'Disconnecting')
213
+ this.logEvent({ message: "port closed:", port: this.path });
214
+ this.connectState = 'Disconnected';
215
+ this.cleanupPort();
161
216
  });
162
217
  }
163
218
  onPortError(error) {
164
219
  return __awaiter(this, void 0, void 0, function* () {
165
- this.logEvent({ message: "port error:", port: this.path, error: error.message, connected: this.connected, state: this.getLogState() });
166
- this.error = error;
167
- if (this.blocked) {
168
- if (!this.state.closed) {
169
- yield this.close();
170
- }
220
+ if (this.connectState === 'Disconnecting' || this.connectState === 'Disconnected') {
171
221
  return;
172
222
  }
173
- if (this.state.sending) {
174
- if (this.state.sending.reject)
175
- this.state.sending.reject(error);
176
- this.writeDone();
177
- yield this.close();
178
- return;
223
+ this.logEvent({ message: "port error:", port: this.path, error: error.message, connected: this.isConnected(), state: this.connectState });
224
+ if (this.isSending()) {
225
+ this.rejectCurrent(error);
179
226
  }
180
- this.state.busy = false;
227
+ if (this.connectState === 'Connected')
228
+ this.close();
181
229
  });
182
230
  }
183
- forceClose(updateState = false) {
184
- return __awaiter(this, void 0, void 0, function* () {
185
- if (!this.sp)
186
- return;
187
- try {
188
- yield this.close();
189
- this.writeDone();
190
- if (this.queue !== undefined)
191
- this.queue.clear();
192
- }
193
- catch (_a) { }
194
- this.connected = false;
195
- if (updateState)
196
- this.state = { opened: false, closed: true, busy: false };
197
- });
198
- }
199
- sendTimeout(message) {
200
- this.logEvent({ message: `sendCommand:${message || 'timeout'}`, port: this.path, cmd: this.cmdCurrent });
201
- delete this.state.commandsInQueue[this.cmdCurrent.command];
202
- if (this.cmdCurrent.callbackErr !== undefined) {
203
- let cb = this.cmdCurrent.callbackErr;
204
- this.state.busy = false;
205
- this.cmdCurrent = undefined;
206
- this.cmdStart = undefined;
207
- cb(408, { message: message || "timeout" });
208
- }
231
+ isSending() {
232
+ return (this.writePromise !== undefined && this.writePromise !== null) || (this.sendCmdPromise !== null && this.sendCmdPromise !== undefined);
209
233
  }
210
- checkForResponse() {
211
- const d = Date.now();
212
- const s = this.state.sending;
213
- if (s === undefined)
214
- return false;
215
- const rejectFn = s.reject;
216
- const reject = (err) => {
217
- if (rejectFn && typeof rejectFn === 'function') {
218
- rejectFn(err);
219
- }
220
- };
221
- const error = this.state.error;
222
- if (error !== undefined) {
223
- reject(error);
224
- return false;
225
- }
226
- try {
227
- if (this.state.waitingForACK) {
228
- const timeoutACK = this.state.ack ? this.state.ack.timeout : this.state.sending.timeout;
229
- if (d < timeoutACK)
230
- return true;
231
- reject(new Error('ACK timeout'));
232
- return false;
233
- }
234
- if (d < this.state.sending.timeout)
235
- return true;
236
- reject(new Error('RESP timeout'));
237
- return false;
238
- }
239
- catch (err) {
240
- this.logEvent({ message: 'checkForResponse: Exception', port: this.path, error: err.message, stack: err.stack });
241
- }
242
- return true;
234
+ rejectCurrent(error) {
235
+ this.recvState.data.enqueue({ type: 'Error', error });
243
236
  }
244
237
  getTimeoutValue(cmd) {
245
238
  let timeout = DEFAULT_TIMEOUT;
@@ -254,18 +247,13 @@ class Daum8i {
254
247
  return __awaiter(this, void 0, void 0, function* () {
255
248
  let cmd = '';
256
249
  const MAX_DEPTH = 5;
257
- if (this.state.waitingForEnd) {
258
- cmd = this.state.partialCmd;
250
+ if (this.recvState.waitingForEnd) {
251
+ cmd = this.recvState.partialCmd;
259
252
  }
260
253
  const bufferData = Buffer.isBuffer(data) ? data : Buffer.from(data, 'latin1');
261
- const s = this.state.sending;
262
- if (s === undefined) {
263
- this.logEvent({ message: 'onData:IGNORED', data: bufferData.toString('hex') });
264
- return;
265
- }
266
- const { portName, resolve } = this.state.sending;
267
254
  let incoming = bufferData;
268
- this.logEvent({ message: 'sendCommand:RECV', data: (0, utils_1.hexstr)(incoming) });
255
+ if (depth === 0)
256
+ this.logEvent({ message: 'sendCommand:RECV', data: (0, utils_1.hexstr)(incoming), state: this.recvState });
269
257
  for (let i = 0; i < incoming.length; i++) {
270
258
  const getRemaining = () => {
271
259
  let remaining = '';
@@ -278,179 +266,222 @@ class Daum8i {
278
266
  };
279
267
  const c = incoming.readUInt8(i);
280
268
  if (c === 0x06) {
281
- this.state.waitingForStart = true;
282
- this.state.waitingForACK = false;
269
+ this.recvState.waitingForStart = true;
270
+ this.recvState.waitingForACK = false;
283
271
  const remaining = getRemaining();
284
- this.logEvent({ message: "sendCommand:ACK received:", port: portName, remaining: (0, utils_1.hexstr)(remaining) });
272
+ this.recvState.data.enqueue({ type: 'ACK' });
285
273
  if (remaining && remaining !== '' && depth < MAX_DEPTH)
286
274
  return this.onData(remaining, depth + 1);
287
275
  }
288
276
  else if (c === 0x15) {
289
- this.state.waitingForStart = true;
290
- this.state.waitingForACK = false;
277
+ this.recvState.waitingForStart = true;
278
+ this.recvState.waitingForACK = false;
291
279
  const remaining = getRemaining();
292
- this.logEvent({ message: "sendCommand:NAK received:", port: portName, remaining: (0, utils_1.hexstr)(remaining) });
280
+ this.recvState.data.enqueue({ type: 'NAK' });
293
281
  if (remaining && remaining !== '' && depth < MAX_DEPTH)
294
282
  return this.onData(remaining, depth + 1);
295
283
  }
296
284
  else if (c === 0x01) {
297
- this.state.waitingForEnd = true;
285
+ this.recvState.waitingForStart = false;
286
+ this.recvState.waitingForEnd = true;
298
287
  }
299
288
  else if (c === 0x17) {
300
289
  const remaining = getRemaining();
301
- if (this.state.waitingForACK) {
302
- this.logEvent({ message: "sendCommand:ignored:", duration: Date.now() - this.state.sending.tsRequest, port: portName, cmd: `${cmd} [${(0, utils_1.hexstr)(cmd)}]`, remaining: (0, utils_1.hexstr)(remaining) });
303
- this.state.waitingForEnd = false;
290
+ this.recvState.waitingForEnd = false;
291
+ const cmdStr = cmd.substring(0, cmd.length - 2);
292
+ const checksumExtracted = cmd.slice(-2);
293
+ const checksumCalculated = (0, utils_1.checkSum)((0, utils_1.getAsciiArrayFromStr)(cmdStr), []);
294
+ if (checksumExtracted === checksumCalculated) {
295
+ const payload = cmd.substring(3, cmd.length - 2);
296
+ this.recvState.data.enqueue({ type: 'Response', data: payload });
304
297
  }
305
298
  else {
306
- this.logEvent({ message: "sendCommand:received:", duration: Date.now() - this.state.sending.tsRequest, port: portName, cmd: `${cmd} [${(0, utils_1.hexstr)(cmd)}]`, remaining: (0, utils_1.hexstr)(remaining) });
307
- this.state.waitingForEnd = false;
308
- const cmdStr = cmd.substring(0, cmd.length - 2);
309
- const checksumExtracted = cmd.slice(-2);
310
- const checksumCalculated = (0, utils_1.checkSum)((0, utils_1.getAsciiArrayFromStr)(cmdStr), []);
311
- if (checksumExtracted === checksumCalculated) {
312
- yield this.sendACK();
313
- if (this.state.sending && this.state.sending.responseCheckIv) {
314
- clearInterval(this.state.sending.responseCheckIv);
315
- }
316
- this.state = {
317
- sending: undefined,
318
- busy: false,
319
- writeBusy: false,
320
- waitingForStart: false,
321
- waitingForEnd: false,
322
- waitingForACK: false,
323
- };
324
- const payload = cmd.substring(3, cmd.length - 2);
325
- resolve(payload);
326
- }
327
- else {
328
- yield this.sendNAK();
329
- }
299
+ const error = new CheckSumError();
300
+ this.recvState.data.enqueue({ type: 'Error', error, data: cmd });
301
+ this.recvState.waitingForACK = false;
302
+ this.recvState.waitingForStart = true;
303
+ this.recvState.waitingForEnd = false;
330
304
  }
331
305
  cmd = '';
332
306
  if (remaining && depth < 5)
333
307
  return this.onData(remaining, depth + 1);
334
308
  }
335
309
  else {
336
- if (this.state.waitingForEnd)
310
+ if (this.recvState.waitingForEnd)
337
311
  cmd += String.fromCharCode(c);
338
312
  }
339
313
  }
340
- if (this.state.waitingForEnd) {
341
- this.state.partialCmd = cmd;
314
+ if (this.recvState.waitingForEnd) {
315
+ this.recvState.partialCmd = cmd;
342
316
  }
343
317
  });
344
318
  }
345
- sendDaum8iCommand(command, payload = '') {
346
- const tsRequest = Date.now();
347
- return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
348
- if (this.blocked)
349
- return reject(new Error('blocked'));
350
- if (!this.state.busy) {
351
- this.state.busy = true;
319
+ waitWithTimeout(promise, timeout, onTimeout) {
320
+ return __awaiter(this, void 0, void 0, function* () {
321
+ let to;
322
+ const toPromise = (ms) => {
323
+ return new Promise(resolve => { to = setTimeout(resolve, ms); });
324
+ };
325
+ let res;
326
+ try {
327
+ res = yield Promise.race([promise, toPromise(timeout).then(() => { if (onTimeout)
328
+ onTimeout(); })]);
352
329
  }
353
- else {
354
- const message = (0, utils_1.buildMessage)(command, payload);
330
+ catch (_a) {
331
+ }
332
+ clearTimeout(to);
333
+ return res;
334
+ });
335
+ }
336
+ sendDaum8iCommand(command, payload = '') {
337
+ return __awaiter(this, void 0, void 0, function* () {
338
+ const message = (0, utils_1.buildMessage)(command, payload);
339
+ const tsRequest = Date.now();
340
+ if (this.sendCmdPromise) {
355
341
  this.logEvent({ message: 'sendCommand:waiting', port: this.path, cmd: command, hex: (0, utils_1.hexstr)(message) });
356
- const busyWait = () => {
357
- return new Promise((done) => {
358
- let start = Date.now();
359
- let timeout = start + 5000;
360
- const iv = setInterval(() => {
361
- if (this.state.busy) {
362
- if (Date.now() > timeout) {
363
- clearInterval(iv);
364
- done(false);
365
- }
366
- }
367
- else {
368
- clearInterval(iv);
369
- done(true);
370
- }
371
- }, 10);
372
- });
373
- };
374
- const res = yield busyWait();
375
- if (!res) {
342
+ const onTimeout = () => {
376
343
  this.logEvent({ message: 'sendCommand:busy timeout', port: this.path, cmd: command, hex: (0, utils_1.hexstr)(message), duration: Date.now() - tsRequest });
377
- return reject(new Error('BUSY timeout'));
344
+ throw new Error('BUSY timeout');
345
+ };
346
+ this.waitWithTimeout(this.sendCmdPromise, 5000, onTimeout);
347
+ this.sendCmdPromise = null;
348
+ }
349
+ this.sendCmdPromise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
350
+ try {
351
+ this.logEvent({ message: "sendCommand:sending:", port: this.path, cmd: command, hex: (0, utils_1.hexstr)(message) });
352
+ if (!this.isConnected()) {
353
+ const connected = yield this.connect();
354
+ if (!connected) {
355
+ reject(new Error('not connected'));
356
+ return;
357
+ }
358
+ }
359
+ let retryCnt = 0;
360
+ let ok = false;
361
+ do {
362
+ yield this.write(Buffer.from(message));
363
+ ok = yield this.waitForACK();
364
+ if (!ok) {
365
+ yield (0, utils_2.sleep)(1000);
366
+ retryCnt++;
367
+ }
368
+ } while (!ok && retryCnt < 5);
369
+ const res = yield this.waitForResponse();
370
+ this.sendCmdPromise = null;
371
+ resolve(res);
372
+ }
373
+ catch (err) {
374
+ this.logEvent({ message: "sendCommand:error:", port: this.path, error: err.message, stack: err.stack });
375
+ this.sendCmdPromise = null;
376
+ reject(err);
377
+ }
378
+ }));
379
+ return this.sendCmdPromise;
380
+ });
381
+ }
382
+ onIgnored(payload) {
383
+ this.logEvent({ message: 'onData:IGNORED', port: this.path, data: payload });
384
+ }
385
+ onACK() {
386
+ }
387
+ waitForACK() {
388
+ return __awaiter(this, void 0, void 0, function* () {
389
+ this.recvState.waitingForACK = true;
390
+ const timeout = this.getTimeoutValue();
391
+ let waitingForACK = true;
392
+ let start = Date.now();
393
+ let tsTimeout = start + timeout;
394
+ while (waitingForACK && Date.now() < tsTimeout) {
395
+ const response = this.recvState.data.dequeue();
396
+ if (!response) {
397
+ yield (0, utils_2.sleep)(5);
398
+ }
399
+ else {
400
+ if (response.type === 'ACK' || response.type === 'NAK') {
401
+ this.logEvent({ message: `sendCommand:${response.type} received:`, port: this.path });
402
+ waitingForACK = false;
403
+ return (response.type === 'ACK');
404
+ }
378
405
  }
379
- this.state.busy = true;
380
406
  }
381
- const port = this.sp;
382
- const portName = this.path;
383
- this.state.received = [];
384
- try {
385
- const message = (0, utils_1.buildMessage)(command, payload);
386
- const start = Date.now();
387
- const timeout = start + this.getTimeoutValue();
388
- this.logEvent({ message: "sendCommand:sending:", port: this.path, cmd: command, hex: (0, utils_1.hexstr)(message) });
389
- this.state.writeBusy = true;
390
- if (!this.connected || port === undefined) {
391
- this.logEvent({ message: "sendCommand:error: not connected", port: this.path });
392
- this.writeDone();
393
- return reject(new Error('not connected'));
407
+ throw new ACKTimeout();
408
+ });
409
+ }
410
+ waitForResponse() {
411
+ return __awaiter(this, void 0, void 0, function* () {
412
+ const timeout = this.getTimeoutValue();
413
+ let waitingForResponse = true;
414
+ let start = Date.now();
415
+ let tsTimeout = start + timeout;
416
+ let retry = 0;
417
+ while (waitingForResponse && Date.now() < tsTimeout && retry < 5) {
418
+ const response = this.recvState.data.dequeue();
419
+ if (!response) {
420
+ yield (0, utils_2.sleep)(5);
394
421
  }
395
- yield this.write(Buffer.from(message));
396
- this.state.waitingForACK = true;
397
- this.state.writeBusy = false;
398
- this.state.retry = 0;
399
- this.state.ack = { start, timeout };
400
- this.state.sending = { command, payload, start, timeout, port, portName, tsRequest, resolve, reject };
401
- const iv = setInterval(() => {
402
- const stillWaiting = this.checkForResponse();
403
- if (!stillWaiting) {
404
- clearInterval(iv);
405
- this.writeDone();
422
+ else {
423
+ if (response.type === 'Response') {
424
+ this.logEvent({ message: `sendCommand:received:`, port: this.path, cmd: response.data });
425
+ yield this.sendACK();
426
+ waitingForResponse = false;
427
+ return response.data;
428
+ }
429
+ if (response.type === 'Error') {
430
+ this.logEvent({ message: `sendCommand:received:ERROR`, port: this.path, error: response.error.message });
431
+ if (response.error instanceof CheckSumError && retry < 5) {
432
+ yield this.sendNAK();
433
+ retry++;
434
+ }
435
+ else {
436
+ throw response.error;
437
+ }
406
438
  }
407
- }, 10);
408
- this.state.sending.responseCheckIv = iv;
439
+ }
440
+ }
441
+ throw new ResponseTimeout();
442
+ });
443
+ }
444
+ portWrite(buffer) {
445
+ return __awaiter(this, void 0, void 0, function* () {
446
+ if (!this.sp) {
447
+ this.logEvent({ message: 'write failed', error: 'port is not opened' });
448
+ return;
449
+ }
450
+ try {
451
+ yield this.sp.write(buffer);
409
452
  }
410
453
  catch (err) {
411
- this.logEvent({ message: "sendCommand:error:", port: portName, error: err.message, stack: err.stack });
412
- this.writeDone();
413
- reject(err);
454
+ this.logEvent({ message: 'write failed', error: err.message });
414
455
  }
415
- }));
416
- }
417
- writeDone() {
418
- this.state.writeBusy = false;
419
- this.state.busy = false;
420
- if (this.state.sending && this.state.sending.responseCheckIv) {
421
- clearInterval(this.state.sending.responseCheckIv);
422
- }
423
- this.state.sending = undefined;
424
- this.state.waitingForStart = false;
425
- this.state.waitingForEnd = false;
426
- this.state.waitingForACK = false;
456
+ });
427
457
  }
428
- write(buffer) {
458
+ write(buffer, ackExpected = true) {
429
459
  return __awaiter(this, void 0, void 0, function* () {
430
- return new Promise((done) => __awaiter(this, void 0, void 0, function* () {
431
- this.state.writeBusy = true;
460
+ if (this.writePromise) {
432
461
  try {
433
- yield this.sp.write(buffer);
434
- this.state.writeBusy = false;
435
- done();
462
+ yield this.writePromise;
436
463
  }
437
- catch (err) {
438
- this.state.writeBusy = false;
439
- done();
464
+ catch (_a) {
440
465
  }
441
- }));
466
+ this.writePromise = null;
467
+ }
468
+ this.writePromise = this.portWrite(buffer);
469
+ if (ackExpected)
470
+ this.recvState.waitingForACK = true;
471
+ yield this.writePromise;
472
+ this.writePromise = null;
442
473
  });
443
474
  }
444
475
  sendACK() {
445
476
  return __awaiter(this, void 0, void 0, function* () {
446
- this.logEvent({ message: "sendCommand:sending ACK", port: this.path, queue: this.state.commandsInQueue });
447
- yield this.write(Buffer.from([0x06]));
477
+ this.logEvent({ message: "sendCommand:sending ACK", port: this.path });
478
+ yield this.write(Buffer.from([0x06]), false);
448
479
  });
449
480
  }
450
481
  sendNAK() {
451
482
  return __awaiter(this, void 0, void 0, function* () {
452
- this.logEvent({ message: "sendCommand:sending NAK", port: this.path, queue: this.state.commandsInQueue });
453
- yield this.write(Buffer.from([0x15]));
483
+ this.logEvent({ message: "sendCommand:sending NAK", port: this.path });
484
+ yield this.write(Buffer.from([0x15]), false);
454
485
  });
455
486
  }
456
487
  sendReservedDaum8iCommand(command, data) {
@@ -512,7 +543,7 @@ class Daum8i {
512
543
  else {
513
544
  throw (new Error(`unknown actual device type ${typeof str === 'string' ? (0, utils_1.ascii)(str.charAt(0)) : str}`));
514
545
  }
515
- this.state.actualBikeType = deviceType;
546
+ this.actualBikeType = deviceType;
516
547
  return deviceType;
517
548
  });
518
549
  }
@@ -545,7 +576,7 @@ class Daum8i {
545
576
  deviceType = constants_1.ACTUAL_BIKE_TYPE.MOUNTAIN;
546
577
  else
547
578
  throw (new Error('unknown actual device type'));
548
- this.state.actualBikeType = deviceType;
579
+ this.actualBikeType = deviceType;
549
580
  return deviceType;
550
581
  });
551
582
  }
@@ -46,6 +46,7 @@ export default class KettlerSerialComms<T extends Command> extends EventEmitter
46
46
  _setSendState(state: SendState): void;
47
47
  _setCurrentCmd(cmd: T): void;
48
48
  stopCurrentTimeoutCheck(): void;
49
+ getSerialInterface(): SerialInterface;
49
50
  onPortOpen(): void;
50
51
  onPortClose(): Promise<void>;
51
52
  onPortError(err: any): void;
@@ -102,6 +102,9 @@ class KettlerSerialComms extends events_1.default {
102
102
  this.currentTimeout = undefined;
103
103
  }
104
104
  }
105
+ getSerialInterface() {
106
+ return this.serial;
107
+ }
105
108
  onPortOpen() {
106
109
  this.logger.logEvent({ message: 'port opened', port: this.getPort() });
107
110
  this.state = SerialCommsState.Connected;
@@ -5,6 +5,7 @@ import { Command } from "../../../types/command";
5
5
  import CyclingMode, { IncyclistBikeData } from "../../../modes/cycling-mode";
6
6
  import { SerialDeviceSettings, SerialIncyclistDevice } from "../../adapter";
7
7
  import { DeviceData } from "../../../types/data";
8
+ import SerialInterface from "../../serial-interface";
8
9
  export interface KettlerRacerCommand extends Command {
9
10
  }
10
11
  export interface KettlerExtendedBikeData {
@@ -44,6 +45,7 @@ export default class KettlerRacerAdapter extends SerialIncyclistDevice {
44
45
  getID(): string;
45
46
  getName(): string;
46
47
  getPort(): string;
48
+ getSerialInterface(): SerialInterface;
47
49
  _getComms(): SerialComms<KettlerRacerCommand>;
48
50
  _setComms(comms: SerialComms<KettlerRacerCommand>): void;
49
51
  getLogger(): EventLogger;
@@ -58,6 +58,10 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
58
58
  const settings = this.settings;
59
59
  return settings.port;
60
60
  }
61
+ getSerialInterface() {
62
+ if (this.comms)
63
+ return this.comms.getSerialInterface();
64
+ }
61
65
  _getComms() {
62
66
  return this.comms;
63
67
  }
@@ -30,6 +30,7 @@ export declare class SinglePathScanner {
30
30
  isScanning: boolean;
31
31
  props: SerialScannerProps;
32
32
  logger: EventLogger;
33
+ isFound: boolean;
33
34
  constructor(path: string, serial: SerialInterface, props: SerialScannerProps);
34
35
  logEvent(event: any): void;
35
36
  onStopRequest(resolve: any): Promise<void>;
@@ -45,6 +46,7 @@ export default class SerialInterface extends EventEmitter implements IncyclistIn
45
46
  logger: EventLogger;
46
47
  toScan: NodeJS.Timeout;
47
48
  connected: boolean;
49
+ inUse: string[];
48
50
  static _instances: SerialInterface[];
49
51
  static getInstance(props: SerialInterfaceProps): SerialInterface;
50
52
  static _add(instance: SerialInterface): void;
@@ -53,6 +55,8 @@ export default class SerialInterface extends EventEmitter implements IncyclistIn
53
55
  setBinding(binding: BindingInterface): void;
54
56
  getName(): string;
55
57
  isConnected(): boolean;
58
+ setInUse(path: string): void;
59
+ releaseInUse(path: string): void;
56
60
  connect(): Promise<boolean>;
57
61
  disconnect(): Promise<boolean>;
58
62
  openPort(path: string): Promise<SerialPortStream | null>;
@@ -18,6 +18,7 @@ const serialport_1 = __importDefault(require("./serialport"));
18
18
  const gd_eventlog_1 = require("gd-eventlog");
19
19
  const utils_1 = require("../utils/utils");
20
20
  const adapters_1 = __importDefault(require("../adapters"));
21
+ const adapter_factory_1 = __importDefault(require("./adapter-factory"));
21
22
  const DEFAULT_SCAN_TIMEOUT = 10000;
22
23
  exports.SerialInterfaceType = {
23
24
  SERIAL: 'serial',
@@ -29,6 +30,7 @@ class SinglePathScanner {
29
30
  this.serial = serial;
30
31
  this.result = undefined;
31
32
  this.isScanning = false;
33
+ this.isFound = false;
32
34
  this.props = props;
33
35
  this.logger = props.logger || new gd_eventlog_1.EventLogger('SerialScanner');
34
36
  }
@@ -44,7 +46,8 @@ class SinglePathScanner {
44
46
  onStopRequest(resolve) {
45
47
  return __awaiter(this, void 0, void 0, function* () {
46
48
  this.logEvent({ message: 'stopping scan', path: this.path });
47
- yield this.serial.closePort(this.path);
49
+ if (!this.isFound)
50
+ yield this.serial.closePort(this.path);
48
51
  this.isScanning = false;
49
52
  resolve(this.result);
50
53
  });
@@ -73,8 +76,8 @@ class SinglePathScanner {
73
76
  const adapter = adapters_1.default.create(adapterSettings);
74
77
  found = yield adapter.check();
75
78
  if (found) {
79
+ this.isFound = true;
76
80
  const name = adapter.getName();
77
- yield this.serial.closePort(this.path).catch();
78
81
  resolve(Object.assign(Object.assign({}, adapterSettings), { name }));
79
82
  }
80
83
  yield (0, utils_1.sleep)(100);
@@ -117,6 +120,7 @@ class SerialInterface extends events_1.default {
117
120
  this.ifaceName = ifaceName;
118
121
  this.binding = undefined;
119
122
  this.ports = [];
123
+ this.inUse = [];
120
124
  this.isScanning = false;
121
125
  this.isStopScanRequested = false;
122
126
  this.scanEvents = new events_1.default();
@@ -148,6 +152,18 @@ class SerialInterface extends events_1.default {
148
152
  isConnected() {
149
153
  return this.connected;
150
154
  }
155
+ setInUse(path) {
156
+ this.logEvent({ message: 'block port for further scans', port: path });
157
+ if (!this.inUse.includes(path))
158
+ this.inUse.push(path);
159
+ }
160
+ releaseInUse(path) {
161
+ if (this.inUse.includes(path)) {
162
+ this.logEvent({ message: 're-enable port for further scans', port: path });
163
+ const idx = this.inUse.findIndex(r => r === path);
164
+ this.inUse.splice(idx, 1);
165
+ }
166
+ }
151
167
  connect() {
152
168
  return __awaiter(this, void 0, void 0, function* () {
153
169
  const binding = serialport_1.default.getInstance().getBinding(this.ifaceName);
@@ -255,13 +271,18 @@ class SerialInterface extends events_1.default {
255
271
  this.scanEvents.emit('timeout');
256
272
  }, timeout);
257
273
  }
258
- this.logEvent({ message: 'checking for ports' });
259
274
  this.isScanning = true;
275
+ let attemptNo = 0;
260
276
  do {
277
+ if (attemptNo === 0)
278
+ this.logEvent({ message: 'checking for ports', port, excludes: this.inUse });
279
+ else
280
+ this.logEvent({ message: 'checking for ports retry', retry: attemptNo });
281
+ attemptNo++;
261
282
  try {
262
283
  if (this.getName() === 'tcpip') {
263
284
  const _binding = binding;
264
- paths = (yield _binding.list(port)) || [];
285
+ paths = (yield _binding.list(port, this.inUse)) || [];
265
286
  }
266
287
  else {
267
288
  paths = (yield binding.list()) || [];
@@ -277,6 +298,7 @@ class SerialInterface extends events_1.default {
277
298
  if (Date.now() > toExpiresAt)
278
299
  timeOutExpired = true;
279
300
  } while (this.isScanning && !timeOutExpired && paths.length === 0);
301
+ paths = paths.filter(p => !this.inUse.includes(p.path));
280
302
  if (paths.length === 0) {
281
303
  this.logEvent({ message: 'nothing to scan ' });
282
304
  if (this.toScan) {
@@ -291,6 +313,9 @@ class SerialInterface extends events_1.default {
291
313
  yield Promise.all(scanners.map(s => s.scan()
292
314
  .then(device => {
293
315
  if (device) {
316
+ const adapter = adapter_factory_1.default.getInstance().createInstance(device);
317
+ const path = adapter.getPort();
318
+ this.inUse.push(path);
294
319
  detected.push(device);
295
320
  this.emit('device', device);
296
321
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "2.0.31",
3
+ "version": "2.0.33",
4
4
  "dependencies": {
5
5
  "@serialport/bindings-interface": "^1.2.2",
6
6
  "@serialport/parser-byte-length": "^9.0.1",