incyclist-devices 1.5.20 → 1.5.22

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.
@@ -109,6 +109,7 @@ class AntAdapter extends device_1.default {
109
109
  return;
110
110
  clearInterval(this.ivDataTimeout);
111
111
  this.ivDataTimeout = undefined;
112
+ this.lastDataTS = undefined;
112
113
  }
113
114
  start(props) {
114
115
  return __awaiter(this, void 0, void 0, function* () {
package/lib/antv2/fe.d.ts CHANGED
@@ -8,7 +8,9 @@ export default class AntFEAdapter extends AntAdapter {
8
8
  protected logger: EventLogger;
9
9
  protected cyclingMode: CyclingMode;
10
10
  protected distanceInternal?: number;
11
+ protected startProps: any;
11
12
  protected msgCount: number;
13
+ protected isReconnecting: boolean;
12
14
  constructor(sensor: ISensor, protocol: AntProtocol);
13
15
  isBike(): boolean;
14
16
  isHrm(): boolean;
@@ -25,6 +27,7 @@ export default class AntFEAdapter extends AntAdapter {
25
27
  mapData(deviceData: any): IncyclistBikeData;
26
28
  transformData(bikeData: any): any;
27
29
  start(props?: any): Promise<any>;
28
- initTimeoutHandler(): void;
30
+ setFEDefaultTimeout(): void;
29
31
  stop(): Promise<boolean>;
32
+ reconnect(): Promise<boolean>;
30
33
  }
package/lib/antv2/fe.js CHANGED
@@ -18,9 +18,11 @@ const gd_eventlog_1 = require("gd-eventlog");
18
18
  const ant_fe_st_mode_1 = __importDefault(require("../ant/antfe/ant-fe-st-mode"));
19
19
  const ant_fe_erg_mode_1 = __importDefault(require("../ant/antfe/ant-fe-erg-mode"));
20
20
  const ant_fe_adv_st_mode_1 = __importDefault(require("../ant/antfe/ant-fe-adv-st-mode"));
21
+ const utils_2 = require("../utils");
21
22
  const DEFAULT_USER_WEIGHT = 75;
22
23
  const DEFAULT_BIKE_WEIGHT = 10;
23
24
  const DEFAULT_BIKE_WEIGHT_MOUNTAIN = 14.5;
25
+ const MAX_RETRIES = 3;
24
26
  class AntFEAdapter extends ant_device_1.default {
25
27
  constructor(sensor, protocol) {
26
28
  super(sensor, protocol);
@@ -30,6 +32,7 @@ class AntFEAdapter extends ant_device_1.default {
30
32
  };
31
33
  this.msgCount = 0;
32
34
  this.logger = new gd_eventlog_1.EventLogger('Ant+FE');
35
+ this.isReconnecting = false;
33
36
  }
34
37
  isBike() { return true; }
35
38
  isHrm() { return false; }
@@ -79,7 +82,7 @@ class AntFEAdapter extends ant_device_1.default {
79
82
  }
80
83
  sendUpdate(request) {
81
84
  return __awaiter(this, void 0, void 0, function* () {
82
- if (this.paused)
85
+ if (this.paused || this.isReconnecting)
83
86
  return;
84
87
  const update = this.getCyclingMode().sendBikeUpdate(request);
85
88
  this.logger.logEvent({ message: 'send bike update requested', update, request });
@@ -106,6 +109,9 @@ class AntFEAdapter extends ant_device_1.default {
106
109
  catch (err) {
107
110
  if (err.message && err.message.toLowerCase() === 'timeout') {
108
111
  this.emit('timeout');
112
+ if (this.startProps.automaticReconnect) {
113
+ yield this.reconnect();
114
+ }
109
115
  }
110
116
  this.logger.logEvent({ message: 'sendBikeUpdate() error', error: err.message });
111
117
  }
@@ -114,6 +120,7 @@ class AntFEAdapter extends ant_device_1.default {
114
120
  onDeviceData(deviceData) {
115
121
  if (!this.started || this.isStopped())
116
122
  return;
123
+ this.msgCount++;
117
124
  this.deviceData = deviceData;
118
125
  this.lastDataTS = Date.now();
119
126
  if (!this.ivDataTimeout)
@@ -189,73 +196,76 @@ class AntFEAdapter extends ant_device_1.default {
189
196
  });
190
197
  return __awaiter(this, void 0, void 0, function* () {
191
198
  _super.start.call(this, props);
199
+ this.startProps = props;
192
200
  this.logger.logEvent({ message: 'start', props });
193
201
  this.msgCount = 0;
194
202
  const opts = props || {};
195
203
  const { args = {}, user = {} } = opts;
196
204
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
197
205
  const { timeout = 20000 } = props || {};
198
- let start = Date.now();
199
- let startTimeout = start + timeout;
200
- const status = { userSent: false, slopeSent: false };
201
- let iv;
202
- const stopInterval = () => {
203
- if (iv)
204
- clearInterval(iv);
205
- iv = undefined;
206
+ let to;
207
+ const stopTimeoutCheck = () => {
208
+ if (to) {
209
+ clearTimeout(to);
210
+ to = null;
211
+ }
206
212
  };
207
- if (timeout) {
208
- iv = setInterval(() => __awaiter(this, void 0, void 0, function* () {
209
- if (Date.now() > startTimeout) {
210
- stopInterval();
211
- yield this.stop();
212
- reject(new Error(`could not start device, reason:timeout`));
213
- }
214
- if (this.started && this.msgCount > 1 && status.userSent) {
215
- this.logger.logEvent({ message: 'start success' });
216
- stopInterval();
213
+ to = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
214
+ yield this.stop();
215
+ reject(new Error(`could not start device, reason:timeout`));
216
+ to = null;
217
+ }), timeout);
218
+ this.setFEDefaultTimeout();
219
+ let success = false;
220
+ let status = { userSent: false, slopeSent: false };
221
+ let retry = 0;
222
+ while (!success && retry < MAX_RETRIES) {
223
+ retry++;
224
+ if (!this.started) {
225
+ this.started = yield this.ant.startSensor(this.sensor, this.onDeviceData.bind(this));
226
+ status = { userSent: false, slopeSent: false };
227
+ }
228
+ if (!this.started) {
229
+ yield (0, utils_2.sleep)(2000);
230
+ continue;
231
+ }
232
+ try {
233
+ const fe = this.sensor;
234
+ const mode = this.getCyclingMode();
235
+ const bikeType = mode ? mode.getSetting('bikeType').toLowerCase() : 'race';
236
+ const defaultBikeWeight = bikeType === 'mountain' ? DEFAULT_BIKE_WEIGHT_MOUNTAIN : DEFAULT_BIKE_WEIGHT;
237
+ const userWeight = args.userWeight || user.weight || DEFAULT_USER_WEIGHT;
238
+ const bikeWeight = args.bikeWeight || defaultBikeWeight;
239
+ status.userSent = status.userSent || (yield fe.sendUserConfiguration(userWeight, bikeWeight, args.wheelDiameter, args.gearRatio));
240
+ status.slopeSent = status.slopeSent || (yield fe.sendTrackResistance(0.0));
241
+ }
242
+ catch (err) {
243
+ this.logger.logEvent({ message: 'sending FE message error', error: err.message });
244
+ try {
245
+ yield yield this.ant.stopSensor(this.sensor);
217
246
  }
218
- }), 100);
247
+ catch (_a) { }
248
+ this.started = false;
249
+ }
250
+ success = status.userSent && status.slopeSent;
219
251
  }
220
- this.started = yield this.ant.startSensor(this.sensor, this.onDeviceData.bind(this));
221
- if (!this.started) {
222
- stopInterval();
223
- this.stop();
224
- return reject(new Error(`could not start device`));
252
+ while (success && this.msgCount === 0) {
253
+ yield (0, utils_2.sleep)(500);
225
254
  }
226
- this.initTimeoutHandler();
227
- try {
228
- const fe = this.sensor;
229
- const mode = this.getCyclingMode();
230
- const bikeType = mode ? mode.getSetting('bikeType').toLowerCase() : 'race';
231
- const defaultBikeWeight = bikeType === 'mountain' ? DEFAULT_BIKE_WEIGHT_MOUNTAIN : DEFAULT_BIKE_WEIGHT;
232
- const userWeight = args.userWeight || user.weight || DEFAULT_USER_WEIGHT;
233
- const bikeWeight = args.bikeWeight || defaultBikeWeight;
234
- let i = 0;
235
- while (i < 3 && (!status.userSent || !status.slopeSent)) {
236
- if (!timeout || iv)
237
- status.userSent = status.userSent || (yield fe.sendUserConfiguration(userWeight, bikeWeight, args.wheelDiameter, args.gearRatio));
238
- if (!timeout || iv)
239
- status.slopeSent = status.slopeSent || (yield fe.sendTrackResistance(0.0));
240
- i++;
241
- }
242
- stopInterval();
243
- if (status.userSent) {
244
- this.logger.logEvent({ message: 'start success' });
245
- return resolve(true);
246
- }
247
- this.logger.logEvent({ message: 'start failure' });
248
- this.stop();
249
- return reject(new Error(`could not start device, reason: could not send commands`));
255
+ if (success) {
256
+ this.logger.logEvent({ message: 'start success' });
257
+ stopTimeoutCheck();
258
+ resolve(true);
250
259
  }
251
- catch (error) {
252
- reject(new Error(`could not start device, reason:${error.message}`));
253
- return;
260
+ else {
261
+ this.logger.logEvent({ message: 'start failed' });
262
+ stopTimeoutCheck();
263
+ reject(new Error('could not start device, reason: could not send FE commands'));
254
264
  }
255
265
  }));
256
266
  });
257
267
  }
258
- initTimeoutHandler() {
268
+ setFEDefaultTimeout() {
259
269
  const fe = this.sensor;
260
270
  fe.setSendTimeout(5000);
261
271
  }
@@ -269,5 +279,24 @@ class AntFEAdapter extends ant_device_1.default {
269
279
  return stopped;
270
280
  });
271
281
  }
282
+ reconnect() {
283
+ return __awaiter(this, void 0, void 0, function* () {
284
+ this.logger.logEvent({ message: 'reconnect to device' });
285
+ this.isReconnecting = true;
286
+ try {
287
+ yield this.stop();
288
+ yield this.start(this.startProps);
289
+ this.started = true;
290
+ this.isReconnecting = false;
291
+ this.logger.logEvent({ message: 'reconnect success' });
292
+ return true;
293
+ }
294
+ catch (err) {
295
+ this.logger.logEvent({ message: 'reconnect failed' });
296
+ this.isReconnecting = false;
297
+ return false;
298
+ }
299
+ });
300
+ }
272
301
  }
273
302
  exports.default = AntFEAdapter;
@@ -672,7 +672,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
672
672
  if (!this.getBinding())
673
673
  throw new Error('no binding defined');
674
674
  this.getBinding().removeAllListeners('discover');
675
- const ongoing = this.peripheralCache.filter(i => i.state.isLoading);
675
+ const ongoing = this.peripheralCache.filter(i => i.state && i.state.isLoading);
676
676
  if (ongoing)
677
677
  ongoing.forEach(i => { i.isInterrupted = true; });
678
678
  yield this.getBinding().stopScanning();
@@ -4,6 +4,7 @@ export default class DaumClassicAdapter extends DaumAdapter {
4
4
  static NAME: string;
5
5
  name: string;
6
6
  id: string;
7
+ udid: number;
7
8
  constructor(protocol: any, bike: any);
8
9
  setID(id: any): void;
9
10
  getID(): string;
@@ -28,6 +28,8 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
28
28
  this.paused = undefined;
29
29
  this.iv = undefined;
30
30
  this.distanceInternal = undefined;
31
+ this.udid = Date.now();
32
+ this.logger.logEvent({ message: 'Device created', udid: this.udid, port: this.getPort() });
31
33
  this.initData();
32
34
  }
33
35
  setID(id) {
@@ -101,13 +103,13 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
101
103
  }
102
104
  startRide(props) {
103
105
  return __awaiter(this, void 0, void 0, function* () {
104
- this.logger.logEvent({ message: 'relaunch of device' });
106
+ this.logger.logEvent({ message: 'relaunch of device', udid: this.udid });
105
107
  return yield this.launch(props, true);
106
108
  });
107
109
  }
108
110
  start(props) {
109
111
  return __awaiter(this, void 0, void 0, function* () {
110
- this.logger.logEvent({ message: 'initial start of device' });
112
+ this.logger.logEvent({ message: 'initial start of device', udid: this.udid });
111
113
  return yield this.launch(props, false);
112
114
  });
113
115
  }
@@ -122,7 +124,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
122
124
  try {
123
125
  const version = yield this.bike.getVersion();
124
126
  const { serialNo, cockpit } = version || {};
125
- this.logEvent({ message: 'device info', deviceInfo: { serialNo, cockpit } });
127
+ this.logEvent({ message: 'device info', deviceInfo: { serialNo, cockpit }, udid: this.udid });
126
128
  }
127
129
  catch (_a) { }
128
130
  }
@@ -132,7 +134,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
132
134
  return true;
133
135
  }
134
136
  catch (err) {
135
- this.logger.logEvent({ message: 'start result: error', error: err.message });
137
+ this.logger.logEvent({ message: 'start result: error', error: err.message, udid: this.udid });
136
138
  throw new Error(`could not start device, reason:${err.message}`);
137
139
  }
138
140
  });
@@ -44,7 +44,7 @@ declare class Daum8i {
44
44
  getUserWeight(): any;
45
45
  getBikeWeight(): number;
46
46
  unblock(): void;
47
- connect(): void;
47
+ connect(): Promise<void>;
48
48
  reconnect(): Promise<void>;
49
49
  saveConnect(): Promise<unknown>;
50
50
  onPortOpen(): void;
@@ -118,87 +118,98 @@ class Daum8i {
118
118
  this.blocked = false;
119
119
  }
120
120
  connect() {
121
- this.logEvent({ message: "connect()", sp: (this.sp !== undefined), connected: this.connected, blocked: this.blocked, port: this.portName, settings: this.settings });
122
- if (this.connected || this.blocked) {
123
- return;
124
- }
125
- this.state.busy = true;
126
- this.state.commandsInQueue = {};
127
- try {
128
- if (this.sp !== undefined) {
129
- try {
130
- this.sp.removeAllListeners();
131
- this.sp.close();
132
- }
133
- catch (err) {
134
- }
135
- this.sp = undefined;
121
+ return __awaiter(this, void 0, void 0, function* () {
122
+ this.logEvent({ message: "connect()", sp: (this.sp !== undefined), connected: this.connected, blocked: this.blocked, port: this.portName, settings: this.settings });
123
+ if (this.connected || this.blocked) {
124
+ return;
136
125
  }
137
- if (this.sp === undefined) {
138
- if (this.tcpip) {
139
- const { host, port } = this.tcpipConnection;
140
- const { logger } = this.props;
141
- this.logEvent({ message: "creating TCPSocketPort", host, port });
142
- this.sp = new tcpserial_1.default({ host, port, net, timeout: OPEN_TIMEOUT, logger });
126
+ this.state.busy = true;
127
+ this.state.commandsInQueue = {};
128
+ try {
129
+ if (this.sp !== undefined) {
130
+ try {
131
+ this.sp.removeAllListeners();
132
+ yield this.sp.close();
133
+ }
134
+ catch (err) {
135
+ }
136
+ this.sp = undefined;
143
137
  }
144
- else {
145
- const settings = this.settings.port || {};
146
- settings.autoOpen = false;
147
- this.logEvent({ message: "creating SerialPort", port: this.port, settings });
148
- this.sp = new __SerialPort(this.port, settings);
138
+ if (this.sp === undefined) {
139
+ if (this.tcpip) {
140
+ const { host, port } = this.tcpipConnection;
141
+ const { logger } = this.props;
142
+ this.logEvent({ message: "creating TCPSocketPort", host, port });
143
+ this.sp = new tcpserial_1.default({ host, port, net, timeout: OPEN_TIMEOUT, logger });
144
+ }
145
+ else {
146
+ const settings = this.settings.port || {};
147
+ settings.autoOpen = false;
148
+ this.logEvent({ message: "creating SerialPort", port: this.port, settings });
149
+ this.sp = new __SerialPort(this.port, settings);
150
+ }
151
+ this.sp.on('open', this.onPortOpen.bind(this));
152
+ this.sp.on('close', this.onPortClose.bind(this));
153
+ this.sp.on('error', (error) => { this.onPortError(error); });
154
+ this.sp.on('data', (data) => { this.onData(data); });
149
155
  }
150
- this.sp.on('open', this.onPortOpen.bind(this));
151
- this.sp.on('close', this.onPortClose.bind(this));
152
- this.sp.on('error', (error) => { this.onPortError(error); });
153
- this.sp.on('data', (data) => { this.onData(data); });
156
+ const start = Date.now();
157
+ this.state.connecting = true;
158
+ this.state.opening = { start, timeout: start + this.getTimeoutValue() };
159
+ this.logEvent({ message: "opening port ..." });
160
+ yield this.sp.open();
154
161
  }
155
- const start = Date.now();
156
- this.state.connecting = true;
157
- this.state.opening = { start, timeout: start + this.getTimeoutValue() };
158
- this.logEvent({ message: "opening port ..." });
159
- this.sp.open();
160
- }
161
- catch (err) {
162
- this.logEvent({ message: "scan:error:", error: err.message, stack: err.stack });
163
- this.state.busy = false;
164
- }
162
+ catch (err) {
163
+ this.logEvent({ message: "connect:error:", error: err.message, stack: err.stack });
164
+ this.state.busy = false;
165
+ }
166
+ });
165
167
  }
166
168
  reconnect() {
167
169
  return __awaiter(this, void 0, void 0, function* () {
168
- yield this.saveClose();
169
- yield this.saveConnect();
170
+ try {
171
+ yield this.saveClose();
172
+ yield this.saveConnect();
173
+ }
174
+ catch (_a) { }
170
175
  });
171
176
  }
172
177
  saveConnect() {
173
- return new Promise((resolve, reject) => {
178
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
174
179
  if (this.isConnected()) {
175
180
  this.state.connecting = false;
176
181
  return resolve(true);
177
182
  }
178
- this.connect();
183
+ try {
184
+ yield this.connect();
185
+ }
186
+ catch (_a) { }
179
187
  const tTimeout = Date.now() + TIMEOUT_START;
180
188
  const iv = setInterval(() => {
181
- if (this.state.error !== undefined) {
182
- clearInterval(iv);
183
- this.forceClose();
184
- reject(this.state.error);
185
- this.state = { opened: false, closed: true, busy: false };
186
- }
187
- else if (this.isConnected()) {
188
- this.state.connecting = false;
189
- resolve(true);
190
- clearInterval(iv);
191
- }
192
- else {
193
- if (Date.now() > tTimeout) {
194
- this.state.connecting = false;
189
+ try {
190
+ if (this.state.error !== undefined) {
191
+ clearInterval(iv);
195
192
  this.forceClose();
193
+ reject(this.state.error);
194
+ this.state = { opened: false, closed: true, busy: false };
195
+ }
196
+ else if (this.isConnected()) {
197
+ this.state.connecting = false;
198
+ resolve(true);
196
199
  clearInterval(iv);
197
- reject(new Error('timeout'));
200
+ }
201
+ else {
202
+ if (Date.now() > tTimeout) {
203
+ this.state.connecting = false;
204
+ this.forceClose();
205
+ clearInterval(iv);
206
+ reject(new Error('timeout'));
207
+ }
198
208
  }
199
209
  }
210
+ catch (_a) { }
200
211
  }, 100);
201
- });
212
+ }));
202
213
  }
203
214
  onPortOpen() {
204
215
  this.error = undefined;
@@ -239,11 +250,14 @@ class Daum8i {
239
250
  this.error = error;
240
251
  if (this.blocked) {
241
252
  if (!this.state.closed) {
242
- if (this.sp) {
243
- this.sp.removeAllListeners();
244
- this.sp.close();
245
- this.sp = undefined;
253
+ try {
254
+ if (this.sp) {
255
+ this.sp.removeAllListeners();
256
+ this.sp.close();
257
+ this.sp = undefined;
258
+ }
246
259
  }
260
+ catch (_a) { }
247
261
  this.state = { opened: false, closed: true, busy: false };
248
262
  }
249
263
  return;
@@ -300,7 +314,10 @@ class Daum8i {
300
314
  sp.flush();
301
315
  }
302
316
  catch (_a) { }
303
- sp.close();
317
+ try {
318
+ sp.close();
319
+ }
320
+ catch (_b) { }
304
321
  this.connected = false;
305
322
  if (updateState)
306
323
  this.state = { opened: false, closed: true, busy: false };
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.5.20",
3
+ "version": "1.5.22",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",
7
7
  "@types/serialport": "^8.0.1",
8
8
  "gd-ant-plus": "^0.0.33",
9
- "incyclist-ant-plus": "^0.1.12",
9
+ "incyclist-ant-plus": "file:../ant-plus",
10
+ "incyclist-devices": "^1.5.21",
10
11
  "win32filetime": "^1.0.2"
11
12
  },
12
13
  "peerDependencies": {