incyclist-devices 1.4.2 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,7 +31,6 @@ export declare type IncyclistBikeData = {
31
31
  pedalRpm: number;
32
32
  speed: number;
33
33
  heartrate: number;
34
- distance: number;
35
34
  distanceInternal: number;
36
35
  time?: number;
37
36
  gear?: number;
package/lib/Device.d.ts CHANGED
@@ -1,6 +1,17 @@
1
1
  import { DeviceProtocol, Device } from './DeviceProtocol';
2
2
  import CyclingMode from './CyclingMode';
3
- export declare type OnDeviceDataCallback = (data: any) => void;
3
+ export declare type DeviceData = {
4
+ speed?: number;
5
+ slope?: number;
6
+ power?: number;
7
+ cadence?: number;
8
+ heartrate?: number;
9
+ distance?: number;
10
+ timestamp?: number;
11
+ deviceTime?: number;
12
+ deviceDistanceCounter?: number;
13
+ };
14
+ export declare type OnDeviceDataCallback = (data: DeviceData) => void;
4
15
  export interface Bike {
5
16
  setCyclingMode(mode: CyclingMode | string, settings?: any): void;
6
17
  getSupportedCyclingModes(): Array<any>;
@@ -1,6 +1,6 @@
1
1
  import { EventLogger } from 'gd-eventlog';
2
- import CyclingMode from '../CyclingMode';
3
- import DeviceAdapterBase, { Bike, DeviceAdapter } from '../Device';
2
+ import CyclingMode, { IncyclistBikeData } from '../CyclingMode';
3
+ import DeviceAdapterBase, { Bike, DeviceAdapter, DeviceData } from '../Device';
4
4
  import { User } from '../types/user';
5
5
  interface DaumAdapter {
6
6
  getCurrentBikeData(): Promise<any>;
@@ -13,7 +13,8 @@ export default class DaumAdapterBase extends DeviceAdapterBase implements Device
13
13
  distanceInternal: number;
14
14
  paused: boolean;
15
15
  stopped: boolean;
16
- data: any;
16
+ daumRunData: IncyclistBikeData;
17
+ deviceData: DeviceData;
17
18
  currentRequest: any;
18
19
  requests: Array<any>;
19
20
  iv: any;
@@ -56,7 +57,7 @@ export default class DaumAdapterBase extends DeviceAdapterBase implements Device
56
57
  sendRequests(): Promise<void>;
57
58
  bikeSync(): Promise<void>;
58
59
  updateData(prev: any, bikeData: any): void;
59
- transformData(): void;
60
+ transformData(): DeviceData;
60
61
  sendRequest(request: any): Promise<any>;
61
62
  refreshRequests(): void;
62
63
  processClientRequest(request: any): Promise<unknown>;
@@ -29,7 +29,16 @@ class DaumAdapterBase extends Device_1.default {
29
29
  this.bike = bike;
30
30
  this.stopped = false;
31
31
  this.paused = false;
32
- this.data = {};
32
+ this.daumRunData = {
33
+ isPedalling: false,
34
+ time: 0,
35
+ power: 0,
36
+ pedalRpm: 0,
37
+ speed: 0,
38
+ distanceInternal: 0,
39
+ heartrate: 0
40
+ };
41
+ this.deviceData = {};
33
42
  const options = props || {};
34
43
  this.cyclingMode = options.cyclingMode;
35
44
  this.setUserSettings(options.userSettings);
@@ -114,15 +123,16 @@ class DaumAdapterBase extends Device_1.default {
114
123
  this.distanceInternal = undefined;
115
124
  this.paused = false;
116
125
  this.stopped = false;
117
- this.data = {
118
- time: 0,
119
- slope: 0,
120
- distance: 0,
121
- speed: 0,
126
+ this.daumRunData = {
122
127
  isPedalling: false,
128
+ time: 0,
123
129
  power: 0,
124
- distanceInternal: 0
130
+ pedalRpm: 0,
131
+ speed: 0,
132
+ distanceInternal: 0,
133
+ heartrate: 0
125
134
  };
135
+ this.deviceData = {};
126
136
  this.currentRequest = {};
127
137
  this.requests = [];
128
138
  const name = this.getCyclingMode().getName();
@@ -200,14 +210,14 @@ class DaumAdapterBase extends Device_1.default {
200
210
  }
201
211
  sendData() {
202
212
  if (this.onDataFn)
203
- this.onDataFn(this.data);
213
+ this.onDataFn(this.deviceData);
204
214
  }
205
215
  update() {
206
216
  return __awaiter(this, void 0, void 0, function* () {
207
217
  this.updateBusy = true;
208
218
  this.getCurrentBikeData()
209
219
  .then(bikeData => {
210
- this.updateData(this.data, bikeData);
220
+ this.updateData(this.daumRunData, bikeData);
211
221
  this.transformData();
212
222
  this.updateBusy = false;
213
223
  })
@@ -262,35 +272,32 @@ class DaumAdapterBase extends Device_1.default {
262
272
  data.pedalRpm = bikeData.cadence;
263
273
  data.speed = bikeData.speed;
264
274
  data.heartrate = bikeData.heartrate;
265
- data.distance = bikeData.distance / 100;
266
- data.distanceInternal = bikeData.distance;
275
+ data.distanceInternal = bikeData.distanceInternal;
267
276
  data.gear = bikeData.gear;
268
- if (this.tsPrevData && data.isPedalling) {
269
- this.adapterTime = Date.now() - this.tsPrevData;
270
- }
271
- this.tsPrevData = Date.now();
272
- data.time = Math.round(this.adapterTime || 0);
277
+ data.time = bikeData.time;
273
278
  if (bikeData.slope)
274
279
  data.slope = bikeData.slope;
275
- this.data = this.getCyclingMode().updateData(data);
280
+ this.daumRunData = this.getCyclingMode().updateData(data);
276
281
  }
277
282
  transformData() {
278
- if (this.data === undefined)
283
+ if (this.daumRunData === undefined)
279
284
  return;
280
285
  let distance = 0;
281
- if (this.distanceInternal !== undefined && this.data.distanceInternal !== undefined) {
282
- distance = (0, utils_1.intVal)(this.data.distanceInternal - this.distanceInternal);
286
+ if (this.distanceInternal !== undefined && this.daumRunData.distanceInternal !== undefined) {
287
+ distance = (0, utils_1.intVal)(this.daumRunData.distanceInternal - this.distanceInternal);
283
288
  }
284
- if (this.data.distanceInternal !== undefined)
285
- this.distanceInternal = this.data.distanceInternal;
289
+ if (this.daumRunData.distanceInternal !== undefined)
290
+ this.distanceInternal = this.daumRunData.distanceInternal;
286
291
  let data = {
287
- speed: (0, utils_1.floatVal)(this.data.speed),
288
- slope: (0, utils_1.floatVal)(this.data.slope),
289
- power: (0, utils_1.intVal)(this.data.power),
290
- cadence: (0, utils_1.intVal)(this.data.pedalRpm),
291
- heartrate: (0, utils_1.intVal)(this.data.heartrate),
292
+ speed: (0, utils_1.floatVal)(this.daumRunData.speed),
293
+ slope: (0, utils_1.floatVal)(this.daumRunData.slope),
294
+ power: (0, utils_1.intVal)(this.daumRunData.power),
295
+ cadence: (0, utils_1.intVal)(this.daumRunData.pedalRpm),
296
+ heartrate: (0, utils_1.intVal)(this.daumRunData.heartrate),
292
297
  distance,
293
- timestamp: Date.now()
298
+ timestamp: Date.now(),
299
+ deviceTime: this.daumRunData.time,
300
+ deviceDistanceCounter: this.daumRunData.distanceInternal
294
301
  };
295
302
  if (this.ignoreHrm)
296
303
  delete data.heartrate;
@@ -301,7 +308,7 @@ class DaumAdapterBase extends Device_1.default {
301
308
  if (this.ignoreBike) {
302
309
  data = { heartrate: data.heartrate };
303
310
  }
304
- this.data = data;
311
+ this.deviceData = data;
305
312
  }
306
313
  sendRequest(request) {
307
314
  return __awaiter(this, void 0, void 0, function* () {
@@ -331,10 +338,10 @@ class DaumAdapterBase extends Device_1.default {
331
338
  });
332
339
  }
333
340
  refreshRequests() {
334
- if (!this.data.isPedalling || this.data.pedalRpm === 0)
341
+ if (!this.daumRunData.isPedalling || this.daumRunData.pedalRpm === 0)
335
342
  return;
336
- let bikeRequest = this.getCyclingMode().sendBikeUpdate({ refresh: true });
337
- const prev = this.requests[this.requests.length - 1];
343
+ let bikeRequest = this.getCyclingMode().sendBikeUpdate({ refresh: true }) || {};
344
+ const prev = this.requests[this.requests.length - 1] || {};
338
345
  if (bikeRequest.targetPower !== undefined && bikeRequest.targetPower !== prev.targetPower) {
339
346
  this.logEvent({ message: 'add request', request: bikeRequest });
340
347
  this.requests.push(bikeRequest);
@@ -342,7 +349,7 @@ class DaumAdapterBase extends Device_1.default {
342
349
  }
343
350
  processClientRequest(request) {
344
351
  if (request.slope !== undefined) {
345
- this.data.slope = request.slope;
352
+ this.daumRunData.slope = request.slope;
346
353
  }
347
354
  return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
348
355
  let bikeRequest = this.getCyclingMode().sendBikeUpdate(request);
@@ -146,7 +146,6 @@ class ERGCyclingMode extends CyclingMode_1.CyclingModeBase {
146
146
  let speed;
147
147
  let m = this.adapter.getWeight();
148
148
  let distanceInternal = prevData.distanceInternal || 0;
149
- let distance = Math.round(distanceInternal / 100);
150
149
  let ts = Date.now();
151
150
  let duration = this.prevUpdateTS === 0 ? 0 : ((ts - this.prevUpdateTS) / 1000);
152
151
  if (rpm === 0 || bikeData.isPedalling === false) {
@@ -157,12 +156,10 @@ class ERGCyclingMode extends CyclingMode_1.CyclingModeBase {
157
156
  speed = calculations_1.default.calculateSpeed(m, power, slope, { bikeType });
158
157
  let v = speed / 3.6;
159
158
  distanceInternal += Math.round(v * duration);
160
- distance = Math.round(distanceInternal / 100);
161
159
  }
162
160
  data.speed = parseFloat(speed.toFixed(1));
163
161
  data.power = Math.round(power);
164
162
  data.distanceInternal = Math.round(distanceInternal);
165
- data.distance = distance;
166
163
  data.slope = slope;
167
164
  data.pedalRpm = rpm;
168
165
  data.gear = gear;
@@ -64,7 +64,6 @@ class PowerMeterCyclingMode extends CyclingMode_1.CyclingModeBase {
64
64
  data.speed = parseFloat(speed.toFixed(1));
65
65
  data.power = Math.round(power);
66
66
  data.distanceInternal = Math.round(distanceInternal);
67
- data.distance = Math.round(distanceInternal / 100);
68
67
  data.slope = slope;
69
68
  this.logger.logEvent({ message: "updateData result", data, bikeData, prevRequest: {}, prevSpeed: prevData.speed });
70
69
  this.data = JSON.parse(JSON.stringify(data));
@@ -104,7 +104,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
104
104
  startState.startProg = true;
105
105
  }
106
106
  if (!startState.setGear) {
107
- yield this.bike.setGear(this.data.gear || (opts.gear || 10));
107
+ yield this.bike.setGear(this.daumRunData.gear || (opts.gear || 10));
108
108
  startState.setGear = true;
109
109
  }
110
110
  const startRequest = this.getCyclingMode().getBikeInitRequest();
@@ -84,7 +84,6 @@ class DaumClassicCyclingMode extends SmartTrainerCyclingMode_1.default {
84
84
  data.power = Math.round(power);
85
85
  data.slope = slope;
86
86
  data.distanceInternal = distanceInternal;
87
- data.distance = Math.round(distanceInternal / 100);
88
87
  this.logger.logEvent({ message: "updateData result", data, bikeData, prevRequest: this.prevRequest || {}, prevSpeed: prevData.speed, event: this.event });
89
88
  this.data = JSON.parse(JSON.stringify(data));
90
89
  this.prevUpdateTS = ts;
@@ -123,7 +123,7 @@ function hexstr(arr, start, len) {
123
123
  }
124
124
  exports.hexstr = hexstr;
125
125
  function Float32ToHex(float32) {
126
- function getHex(i) { return ('00' + i.toString(16)).slice(-2); }
126
+ function getHex(i) { return ('00' + i.toString(16)).slice(-2).toUpperCase(); }
127
127
  var view = new DataView(new ArrayBuffer(4));
128
128
  view.setFloat32(0, float32);
129
129
  return Array.apply(null, { length: 4 }).map((_, i) => getHex(view.getUint8(i))).join('');
@@ -55,19 +55,23 @@ class DaumClassicCyclingMode extends PowerMeterCyclingMode_1.default {
55
55
  let power = data.power || 0;
56
56
  let speed = data.speed || 0;
57
57
  let slope = (prevData.slope !== undefined ? prevData.slope : prevRequest.slope || 0);
58
- let distanceInternal = prevData.distanceInternal || 0;
58
+ let distanceBike = data.distanceInternal || 0;
59
+ let distancePrev = prevData.distanceInternal || 0;
60
+ let distanceInternal = distanceBike;
61
+ let ts = Date.now();
59
62
  if (!bikeData.pedalRpm || bikeData.isPedalling === false) {
60
63
  speed = 0;
61
64
  power = 0;
62
65
  }
63
- let ts = Date.now();
64
- let v = speed / 3.6;
65
- let duration = this.prevUpdateTS === 0 ? 0 : ((ts - this.prevUpdateTS) / 1000);
66
- distanceInternal += Math.round(v * duration);
66
+ if (distanceBike < distancePrev) {
67
+ this.logger.logEvent({ message: '~~~ distance overflow', distanceBike, distancePrev });
68
+ let v = speed / 3.6;
69
+ let duration = this.prevUpdateTS === 0 ? 0 : ((ts - this.prevUpdateTS) / 1000);
70
+ distanceInternal = distancePrev + Math.round(v * duration);
71
+ }
67
72
  data.speed = parseFloat(speed.toFixed(1));
68
73
  data.power = Math.round(power);
69
74
  data.distanceInternal = Math.round(distanceInternal);
70
- data.distance = Math.round(distanceInternal / 100);
71
75
  data.slope = slope;
72
76
  this.logger.logEvent({ message: "updateData result", data, bikeData, prevRequest: {}, prevSpeed: prevData.speed });
73
77
  this.data = JSON.parse(JSON.stringify(data));
@@ -111,8 +111,11 @@ class DaumPremiumDevice extends DaumAdapter_1.default {
111
111
  else {
112
112
  info.person = true;
113
113
  }
114
- const gear = yield this.bike.setGear(this.data.gear || (opts.gear || 10));
115
- return gear;
114
+ if (!this.getCyclingMode().getModeProperty('eppSupport')) {
115
+ const gear = yield this.bike.setGear(this.daumRunData.gear || (opts.gear || 10));
116
+ return gear;
117
+ }
118
+ return;
116
119
  }
117
120
  catch (err) {
118
121
  console.error(err);
@@ -78,7 +78,7 @@ declare class Daum8i {
78
78
  heartrate: number;
79
79
  speed: number;
80
80
  slope: number;
81
- distance: number;
81
+ distanceInternal: number;
82
82
  cadence: number;
83
83
  power: number;
84
84
  physEnergy: number;
@@ -592,7 +592,6 @@ class Daum8i {
592
592
  .then((res) => {
593
593
  const resData = Uint8Array.from(res, x => x.charCodeAt(0));
594
594
  const cmd = (0, utils_1.esc2bin)(resData);
595
- console.log('~~~ cmd', cmd);
596
595
  return cmd;
597
596
  });
598
597
  }
@@ -711,17 +710,27 @@ class Daum8i {
711
710
  });
712
711
  }
713
712
  setPerson(person) {
713
+ this.logger.logEvent({ message: 'setPerson() request' });
714
714
  return this.sendReservedDaum8iCommand(utils_1.ReservedCommands.PERSON_SET, 'BF', (0, utils_1.getPersonData)(person))
715
715
  .then((res) => {
716
716
  const buffer = Buffer.from(res);
717
- return buffer.readInt16LE(0) === utils_1.ReservedCommands.PERSON_SET;
717
+ const success = buffer.readInt16LE(0) === utils_1.ReservedCommands.PERSON_SET;
718
+ this.logger.logEvent({ message: 'setPerson() response', success, buffer });
719
+ if (!success)
720
+ throw new Error('Illegal Response');
721
+ return true;
718
722
  });
719
723
  }
720
724
  programUploadInit() {
725
+ this.logger.logEvent({ message: 'programUploadInit() request' });
721
726
  return this.sendReservedDaum8iCommand(utils_1.ReservedCommands.PROGRAM_LIST_BEGIN, 'BF')
722
727
  .then((res) => {
723
728
  const buffer = Buffer.from(res);
724
- return buffer.readInt16LE(0) === utils_1.ReservedCommands.PROGRAM_LIST_BEGIN;
729
+ const success = buffer.readInt16LE(0) === utils_1.ReservedCommands.PROGRAM_LIST_BEGIN;
730
+ this.logger.logEvent({ message: 'programUploadInit() response', success, buffer });
731
+ if (!success)
732
+ throw new Error('Illegal Response');
733
+ return true;
725
734
  });
726
735
  }
727
736
  programUploadStart(bikeType, route) {
@@ -741,12 +750,15 @@ class Daum8i {
741
750
  payload.writeInt16LE(0, 30);
742
751
  payload.writeInt32LE(7, 32);
743
752
  payload.writeInt32LE(epp.length, 36);
753
+ this.logger.logEvent({ message: 'programUploadStart() request' });
744
754
  return this.sendReservedDaum8iCommand(utils_1.ReservedCommands.PROGRAM_LIST_NEW_PROGRAM, 'BF', payload)
745
755
  .then((res) => {
746
756
  const buffer = Buffer.from(res);
747
757
  if (buffer.readInt16LE(0) === utils_1.ReservedCommands.PROGRAM_LIST_NEW_PROGRAM) {
758
+ this.logger.logEvent({ message: 'programUploadStart() response', success: true });
748
759
  return epp;
749
760
  }
761
+ this.logger.logEvent({ message: 'programUploadStart() response', success: false });
750
762
  throw new Error('Illegal Response');
751
763
  });
752
764
  }
@@ -760,23 +772,31 @@ class Daum8i {
760
772
  payload.writeInt32LE(offset, 4);
761
773
  const chunk = Buffer.from(epp.slice(offset, offset + size));
762
774
  chunk.copy(payload, 8);
775
+ this.logger.logEvent({ message: 'programUploadSendBlock() request', offset, size });
763
776
  return this.sendReservedDaum8iCommand(utils_1.ReservedCommands.PROGRAM_LIST_CONTINUE_PROGRAM, 'BF', payload)
764
777
  .then((res) => {
765
778
  const buffer = Buffer.from(res);
766
779
  let success = buffer.readInt16LE(0) === utils_1.ReservedCommands.PROGRAM_LIST_CONTINUE_PROGRAM;
767
- console.log('~~ Buffer', buffer, buffer.readInt16LE(2), buffer.readInt8(4));
768
780
  success = success && (buffer.readInt16LE(2) === 1);
769
781
  success = success && (buffer.readInt8(4) === 1);
782
+ this.logger.logEvent({ message: 'programUploadSendBlock() response' });
770
783
  if (!success)
771
784
  throw new Error('Illegal Response');
772
- return success;
785
+ return true;
786
+ ;
773
787
  });
774
788
  }
775
789
  programUploadDone() {
790
+ this.logger.logEvent({ message: 'programUploadDone() request' });
776
791
  return this.sendReservedDaum8iCommand(utils_1.ReservedCommands.PROGRAM_LIST_END, 'BF')
777
792
  .then((res) => {
778
793
  const buffer = Buffer.from(res);
779
- return buffer.readInt16LE(0) === utils_1.ReservedCommands.PROGRAM_LIST_END;
794
+ const success = buffer.readInt16LE(0) === utils_1.ReservedCommands.PROGRAM_LIST_END;
795
+ this.logger.logEvent({ message: 'programUploadDone() response', success });
796
+ if (!success)
797
+ throw new Error('Illegal Response');
798
+ return true;
799
+ ;
780
800
  });
781
801
  }
782
802
  programUpload(bikeType, route) {
@@ -800,10 +820,16 @@ class Daum8i {
800
820
  startProgram(programId = 1) {
801
821
  const payload = Buffer.alloc(2);
802
822
  payload.writeInt16LE(programId, 0);
823
+ this.logger.logEvent({ message: 'startProgram() request', programId });
803
824
  return this.sendReservedDaum8iCommand(utils_1.ReservedCommands.PROGRAM_LIST_START, 'BF', payload)
804
825
  .then((res) => {
805
826
  const buffer = Buffer.from(res);
806
- return buffer.readInt16LE(0) === utils_1.ReservedCommands.PROGRAM_LIST_START;
827
+ const success = buffer.readInt16LE(0) === utils_1.ReservedCommands.PROGRAM_LIST_START;
828
+ this.logger.logEvent({ message: 'startProgram() request', programId, success });
829
+ if (!success)
830
+ throw new Error('Illegal Response');
831
+ return true;
832
+ ;
807
833
  });
808
834
  }
809
835
  setGear(gear) {
@@ -49,7 +49,7 @@ export declare function parseTrainingData(payload: any): {
49
49
  heartrate: number;
50
50
  speed: number;
51
51
  slope: number;
52
- distance: number;
52
+ distanceInternal: number;
53
53
  cadence: number;
54
54
  power: number;
55
55
  physEnergy: number;
@@ -258,9 +258,9 @@ function routeToEpp(route, date) {
258
258
  let offset = 0;
259
259
  const name = route.name || '';
260
260
  const description = route.description || '';
261
- const minElevation = Math.min(...route.points.map(p => p.elevation));
262
- const maxElevation = Math.max(...route.points.map(p => p.elevation));
263
- const sampleRate = route.points.length !== 0 ? route.totalDistance / route.points.length : 0;
261
+ const minElevation = route.minElevation ? route.minElevation : 0;
262
+ const maxElevation = route.maxElevation ? route.minElevation : Math.max(...route.points.map(p => p.elevation));
263
+ const sampleRate = route.points.length !== 0 ? Math.round(route.totalDistance / route.points.length) : 0;
264
264
  buffer.writeUInt32LE(fileTime.low, offset);
265
265
  offset += 4;
266
266
  buffer.writeUInt32LE(fileTime.high, offset);
@@ -314,9 +314,9 @@ function parseTrainingData(payload) {
314
314
  const data = {
315
315
  time: parseInt(vals[0]),
316
316
  heartrate: parseInt(vals[1]),
317
- speed: parseFloat(vals[2]),
317
+ speed: parseFloat(vals[2]) * 3.6,
318
318
  slope: parseFloat(vals[3]),
319
- distance: parseInt(vals[4]),
319
+ distanceInternal: parseInt(vals[4]),
320
320
  cadence: parseFloat(vals[5]),
321
321
  power: parseInt(vals[6]),
322
322
  physEnergy: parseFloat(vals[7]),
@@ -18,4 +18,7 @@ export declare type Route = {
18
18
  description?: string;
19
19
  lapMode: boolean;
20
20
  totalDistance: number;
21
+ minElevation?: number;
22
+ maxElevation?: number;
23
+ sampleRate?: number;
21
24
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.2",
3
+ "version": "1.4.5",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",