incyclist-devices 1.4.24 → 1.4.27

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.
Files changed (42) hide show
  1. package/lib/Device.d.ts +1 -1
  2. package/lib/Device.js +2 -2
  3. package/lib/DeviceProtocol.d.ts +3 -1
  4. package/lib/DeviceProtocol.js +2 -0
  5. package/lib/DeviceSupport.d.ts +6 -1
  6. package/lib/DeviceSupport.js +9 -0
  7. package/lib/ant/AntScanner.js +7 -5
  8. package/lib/ant/antfe/AntFEAdapter.js +0 -19
  9. package/lib/ant/anthrm/AntHrmAdapter.js +0 -11
  10. package/lib/ant/antpwr/pwr-adapter.js +0 -11
  11. package/lib/ble/ble-device.d.ts +36 -0
  12. package/lib/ble/ble-device.js +174 -0
  13. package/lib/ble/ble-interface.d.ts +51 -0
  14. package/lib/ble/ble-interface.js +330 -0
  15. package/lib/ble/ble.d.ts +81 -0
  16. package/lib/ble/ble.js +51 -0
  17. package/lib/ble/hrm.d.ts +48 -0
  18. package/lib/ble/hrm.js +128 -0
  19. package/lib/ble/incyclist-protocol.d.ts +31 -0
  20. package/lib/ble/incyclist-protocol.js +106 -0
  21. package/lib/ble/pwr.d.ts +32 -0
  22. package/lib/ble/pwr.js +96 -0
  23. package/lib/calculations.js +2 -3
  24. package/lib/daum/DaumAdapter.d.ts +4 -4
  25. package/lib/daum/DaumAdapter.js +24 -20
  26. package/lib/daum/DaumPowerMeterCyclingMode.d.ts +8 -0
  27. package/lib/daum/DaumPowerMeterCyclingMode.js +21 -0
  28. package/lib/daum/ERGCyclingMode.d.ts +3 -6
  29. package/lib/daum/ERGCyclingMode.js +15 -27
  30. package/lib/daum/classic/DaumClassicAdapter.js +1 -1
  31. package/lib/daum/premium/DaumClassicCyclingMode.d.ts +2 -2
  32. package/lib/daum/premium/DaumClassicCyclingMode.js +2 -2
  33. package/lib/daum/premium/DaumPremiumAdapter.js +1 -1
  34. package/lib/daum/premium/tcpserial.js +0 -1
  35. package/lib/modes/power-base.d.ts +20 -0
  36. package/lib/modes/power-base.js +70 -0
  37. package/lib/modes/power-meter.d.ts +12 -10
  38. package/lib/modes/power-meter.js +30 -46
  39. package/lib/modes/simulator.d.ts +27 -0
  40. package/lib/modes/simulator.js +118 -0
  41. package/lib/simulator/Simulator.js +3 -3
  42. package/package.json +2 -1
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importStar = (this && this.__importStar) || function (mod) {
12
+ if (mod && mod.__esModule) return mod;
13
+ var result = {};
14
+ if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
15
+ result["default"] = mod;
16
+ return result;
17
+ };
18
+ var __importDefault = (this && this.__importDefault) || function (mod) {
19
+ return (mod && mod.__esModule) ? mod : { "default": mod };
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ const gd_eventlog_1 = require("gd-eventlog");
23
+ const DeviceProtocol_1 = __importStar(require("../DeviceProtocol"));
24
+ const DeviceRegistry_1 = __importDefault(require("../DeviceRegistry"));
25
+ const ble_1 = require("./ble");
26
+ const ble_interface_1 = __importDefault(require("./ble-interface"));
27
+ const hrm_1 = __importStar(require("./hrm"));
28
+ const pwr_1 = __importDefault(require("./pwr"));
29
+ const supportedDeviceTypes = [hrm_1.default, pwr_1.default];
30
+ class BleProtocol extends DeviceProtocol_1.default {
31
+ constructor(binding) {
32
+ super();
33
+ const b = binding || BleProtocol._defaultBinding;
34
+ this.logger = new gd_eventlog_1.EventLogger('BLE');
35
+ this.ble = new ble_interface_1.default({ binding: b, logger: this.logger });
36
+ BleProtocol._instances.push(this);
37
+ }
38
+ static setDefaultBinding(binding) {
39
+ BleProtocol._defaultBinding = binding;
40
+ BleProtocol._instances.forEach((p) => {
41
+ if (p.ble && !p.ble.getBinding()) {
42
+ p.ble.setBinding(binding);
43
+ }
44
+ });
45
+ }
46
+ setBinding(binding) {
47
+ if (this.ble)
48
+ this.ble.setBinding(binding);
49
+ }
50
+ createDevice(bleDevice) {
51
+ const fromDevice = bleDevice instanceof ble_1.BleDeviceClass;
52
+ const profile = bleDevice instanceof ble_1.BleDeviceClass ? bleDevice.getProfile() : bleDevice.profile;
53
+ const props = () => {
54
+ const { id, name, address } = bleDevice;
55
+ return { id, name, address };
56
+ };
57
+ switch (profile.toLocaleLowerCase()) {
58
+ case 'hr':
59
+ case 'heartrate monitor':
60
+ return new hrm_1.HrmAdapter(fromDevice ? bleDevice : new hrm_1.default(props()), this);
61
+ }
62
+ }
63
+ getName() { return 'BLE'; }
64
+ getInterfaces() { return [DeviceProtocol_1.INTERFACE.BLE]; }
65
+ isBike() { return true; }
66
+ isHrm() { return true; }
67
+ isPower() { return true; }
68
+ add(settings) {
69
+ this.logger.logEvent({ message: 'adding device', settings });
70
+ const device = this.createDevice(settings);
71
+ return device;
72
+ }
73
+ scan(props) {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ try {
76
+ this.ble.on('device', (bleDevice) => {
77
+ if (props && props.onDeviceFound) {
78
+ const device = this.createDevice(bleDevice);
79
+ props.onDeviceFound(device, this);
80
+ }
81
+ });
82
+ this.logger.logEvent({ message: 'scan started' });
83
+ yield this.ble.scan({ deviceTypes: supportedDeviceTypes });
84
+ if (props && props.onScanFinished) {
85
+ props.onScanFinished(props.id);
86
+ }
87
+ }
88
+ catch (err) {
89
+ this.logger.logEvent({ message: 'error', error: err.message });
90
+ }
91
+ });
92
+ }
93
+ stopScan() {
94
+ return __awaiter(this, void 0, void 0, function* () {
95
+ yield this.ble.stopScan();
96
+ return;
97
+ });
98
+ }
99
+ isScanning() {
100
+ return this.ble.isScanning();
101
+ }
102
+ }
103
+ exports.default = BleProtocol;
104
+ BleProtocol._defaultBinding = undefined;
105
+ BleProtocol._instances = [];
106
+ DeviceRegistry_1.default.register(new BleProtocol());
@@ -0,0 +1,32 @@
1
+ /// <reference types="node" />
2
+ import { BleDevice } from './ble-device';
3
+ declare type PowerData = {
4
+ instantaneousPower?: number;
5
+ balance?: number;
6
+ accTorque?: number;
7
+ rpm: number;
8
+ raw?: Buffer;
9
+ };
10
+ declare type CrankData = {
11
+ revolutions?: number;
12
+ time?: number;
13
+ cntUpdateMissing?: number;
14
+ };
15
+ export default class BleCyclingPowerDevice extends BleDevice {
16
+ static services: string[];
17
+ static characteristics: string[];
18
+ instantaneousPower: number;
19
+ balance: number;
20
+ accTorque: number;
21
+ currentCrankData: CrankData;
22
+ prevCrankData: CrankData;
23
+ rpm: number;
24
+ getProfile(): string;
25
+ getServiceUUids(): string[];
26
+ getRpm(crankData: any): number;
27
+ parsePower(data: Buffer): PowerData;
28
+ onData(characteristic: string, data: Buffer): void;
29
+ write(characteristic: any, data: any): Promise<boolean>;
30
+ read(characteristic: any): Promise<Buffer>;
31
+ }
32
+ export {};
package/lib/ble/pwr.js ADDED
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const ble_device_1 = require("./ble-device");
7
+ const ble_interface_1 = __importDefault(require("./ble-interface"));
8
+ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.instantaneousPower = undefined;
12
+ this.balance = undefined;
13
+ this.accTorque = undefined;
14
+ this.currentCrankData = undefined;
15
+ this.prevCrankData = undefined;
16
+ this.rpm = undefined;
17
+ }
18
+ getProfile() {
19
+ return 'cp';
20
+ }
21
+ getServiceUUids() {
22
+ return BleCyclingPowerDevice.services;
23
+ }
24
+ getRpm(crankData) {
25
+ if (!this.prevCrankData)
26
+ this.prevCrankData = { revolutions: 0, time: 0, cntUpdateMissing: -1 };
27
+ const c = this.currentCrankData = crankData;
28
+ const p = this.prevCrankData;
29
+ let rpm = this.rpm;
30
+ let hasUpdate = c.time !== p.time;
31
+ if (hasUpdate) {
32
+ let time = c.time - p.time;
33
+ let revs = c.revolutions - p.revolutions;
34
+ if (c.time < p.time)
35
+ time += 0x10000;
36
+ if (c.revolutions < p.revolutions)
37
+ revs += 0x10000;
38
+ rpm = 1024 * 60 * revs / time;
39
+ }
40
+ else {
41
+ if (p.cntUpdateMissing < 0 || p.cntUpdateMissing > 2) {
42
+ rpm = 0;
43
+ }
44
+ }
45
+ const cntUpdateMissing = p.cntUpdateMissing;
46
+ this.prevCrankData = this.currentCrankData;
47
+ if (hasUpdate)
48
+ this.prevCrankData.cntUpdateMissing = 0;
49
+ else
50
+ this.prevCrankData.cntUpdateMissing = cntUpdateMissing + 1;
51
+ return rpm;
52
+ }
53
+ parsePower(data) {
54
+ try {
55
+ let offset = 4;
56
+ const flags = data.readUInt16LE(0);
57
+ this.instantaneousPower = data.readUInt16LE(2);
58
+ if (flags & 0x1)
59
+ this.balance = data.readUInt8(offset++);
60
+ if (flags & 0x4) {
61
+ this.accTorque = data.readUInt16LE(offset);
62
+ offset += 2;
63
+ }
64
+ if (flags & 0x20) {
65
+ const crankData = {
66
+ revolutions: data.readUInt16LE(offset),
67
+ time: data.readUInt16LE(offset + 2)
68
+ };
69
+ this.rpm = this.getRpm(crankData);
70
+ offset += 4;
71
+ }
72
+ }
73
+ catch (err) {
74
+ }
75
+ const { instantaneousPower, balance, accTorque, rpm } = this;
76
+ return { instantaneousPower, balance, accTorque, rpm, raw: data };
77
+ }
78
+ onData(characteristic, data) {
79
+ if (characteristic.toLocaleLowerCase() === '2a63') {
80
+ const res = this.parsePower(data);
81
+ this.emit('data', res);
82
+ }
83
+ }
84
+ write(characteristic, data) {
85
+ console.log('write', characteristic, data);
86
+ return Promise.resolve(true);
87
+ }
88
+ read(characteristic) {
89
+ console.log('read', characteristic);
90
+ return Promise.resolve(Buffer.from([]));
91
+ }
92
+ }
93
+ exports.default = BleCyclingPowerDevice;
94
+ BleCyclingPowerDevice.services = ['1818'];
95
+ BleCyclingPowerDevice.characteristics = ['2a63', '2a65', '2a5d', '2a3c'];
96
+ ble_interface_1.default.register('BleCyclingPowerDevice', 'cp', BleCyclingPowerDevice, BleCyclingPowerDevice.services);
@@ -7,7 +7,6 @@ const cwABike = {
7
7
  triathlon: 0.29,
8
8
  mountain: 0.57
9
9
  };
10
- const k = 0.01090;
11
10
  const cRR = 0.0036;
12
11
  class IllegalArgumentException extends Error {
13
12
  constructor(message) {
@@ -28,7 +27,7 @@ class C {
28
27
  const _cRR = props.cRR || cRR;
29
28
  const _cwA = props.cwA || cwABike[props.bikeType || 'race'] || cwABike.race;
30
29
  let sl = Math.atan(slope / 100);
31
- let c1 = 0.5 * _rho * _cwA + 2 * k;
30
+ let c1 = 0.5 * _rho * _cwA;
32
31
  let c2 = (sl + _cRR) * m * g;
33
32
  let p = c2 / c1;
34
33
  let q = -1.0 * power / c1;
@@ -70,7 +69,7 @@ class C {
70
69
  let _cRR = props.cRR || cRR;
71
70
  let _cwA = props.cwA || cwABike[props.bikeType || 'race'] || cwABike.race;
72
71
  let sl = Math.sin(Math.atan(slope / 100));
73
- let P = (0.5 * _rho * _cwA + 2 * k) * Math.pow(v, 3.0) + (sl + _cRR) * m * g * v;
72
+ let P = (0.5 * _rho * _cwA) * Math.pow(v, 3.0) + (sl + _cRR) * m * g * v;
74
73
  return P;
75
74
  }
76
75
  static calculateSpeedDaum(gear, rpm, bikeType) {
@@ -1,11 +1,11 @@
1
1
  import { EventLogger } from 'gd-eventlog';
2
2
  import CyclingMode, { IncyclistBikeData } from '../CyclingMode';
3
- import DeviceAdapterBase, { Bike, DeviceAdapter, DeviceData } from '../Device';
3
+ import IncyclistDevice, { Bike, DeviceAdapter, DeviceData } from '../Device';
4
4
  import { User } from '../types/user';
5
5
  interface DaumAdapter {
6
6
  getCurrentBikeData(): Promise<any>;
7
7
  }
8
- export default class DaumAdapterBase extends DeviceAdapterBase implements DeviceAdapter, DaumAdapter, Bike {
8
+ export default class DaumAdapterBase extends IncyclistDevice implements DeviceAdapter, DaumAdapter, Bike {
9
9
  bike: any;
10
10
  ignoreHrm: boolean;
11
11
  ignoreBike: boolean;
@@ -13,7 +13,7 @@ export default class DaumAdapterBase extends DeviceAdapterBase implements Device
13
13
  distanceInternal: number;
14
14
  paused: boolean;
15
15
  stopped: boolean;
16
- daumRunData: IncyclistBikeData;
16
+ cyclingData: IncyclistBikeData;
17
17
  deviceData: DeviceData;
18
18
  currentRequest: any;
19
19
  requests: Array<any>;
@@ -56,7 +56,7 @@ export default class DaumAdapterBase extends DeviceAdapterBase implements Device
56
56
  update(): Promise<void>;
57
57
  sendRequests(): Promise<void>;
58
58
  bikeSync(): Promise<void>;
59
- updateData(prev: any, bikeData: any): void;
59
+ updateData(prev: any, bikeData: any): IncyclistBikeData;
60
60
  transformData(): DeviceData;
61
61
  sendRequest(request: any): Promise<any>;
62
62
  refreshRequests(): void;
@@ -22,7 +22,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
22
22
  const Device_1 = __importStar(require("../Device"));
23
23
  const ERGCyclingMode_1 = __importDefault(require("./ERGCyclingMode"));
24
24
  const SmartTrainerCyclingMode_1 = __importDefault(require("./SmartTrainerCyclingMode"));
25
- const PowerMeterCyclingMode_1 = __importDefault(require("./PowerMeterCyclingMode"));
25
+ const DaumPowerMeterCyclingMode_1 = __importDefault(require("./DaumPowerMeterCyclingMode"));
26
26
  const utils_1 = require("../utils");
27
27
  class DaumAdapterBase extends Device_1.default {
28
28
  constructor(props, bike) {
@@ -34,7 +34,7 @@ class DaumAdapterBase extends Device_1.default {
34
34
  this.bike = bike;
35
35
  this.stopped = false;
36
36
  this.paused = false;
37
- this.daumRunData = {
37
+ this.cyclingData = {
38
38
  isPedalling: false,
39
39
  time: 0,
40
40
  power: 0,
@@ -67,7 +67,7 @@ class DaumAdapterBase extends Device_1.default {
67
67
  this.cyclingMode.setSettings(settings);
68
68
  }
69
69
  getSupportedCyclingModes() {
70
- return [ERGCyclingMode_1.default, SmartTrainerCyclingMode_1.default, PowerMeterCyclingMode_1.default];
70
+ return [ERGCyclingMode_1.default, SmartTrainerCyclingMode_1.default, DaumPowerMeterCyclingMode_1.default];
71
71
  }
72
72
  getCyclingMode() {
73
73
  if (!this.cyclingMode)
@@ -128,7 +128,7 @@ class DaumAdapterBase extends Device_1.default {
128
128
  this.distanceInternal = undefined;
129
129
  this.paused = false;
130
130
  this.stopped = false;
131
- this.daumRunData = {
131
+ this.cyclingData = {
132
132
  isPedalling: false,
133
133
  time: 0,
134
134
  power: 0,
@@ -229,12 +229,15 @@ class DaumAdapterBase extends Device_1.default {
229
229
  this.updateBusy = true;
230
230
  this.getCurrentBikeData()
231
231
  .then(bikeData => {
232
- this.updateData(this.daumRunData, bikeData);
232
+ this.updateData(this.cyclingData, bikeData);
233
233
  this.transformData();
234
234
  this.updateBusy = false;
235
235
  })
236
236
  .catch(err => {
237
237
  this.logEvent({ message: 'bike update error', error: err.message, stack: err.stack });
238
+ const { isPedalling, power, pedalRpm, speed, distanceInternal, heartrate, slope } = this.cyclingData;
239
+ this.updateData(this.cyclingData, { isPedalling, power, pedalRpm, speed, distanceInternal, heartrate, slope });
240
+ this.transformData();
238
241
  this.updateBusy = false;
239
242
  });
240
243
  });
@@ -289,27 +292,28 @@ class DaumAdapterBase extends Device_1.default {
289
292
  data.time = bikeData.time;
290
293
  if (bikeData.slope)
291
294
  data.slope = bikeData.slope;
292
- this.daumRunData = this.getCyclingMode().updateData(data);
295
+ this.cyclingData = this.getCyclingMode().updateData(data);
296
+ return this.cyclingData;
293
297
  }
294
298
  transformData() {
295
- if (this.daumRunData === undefined)
299
+ if (this.cyclingData === undefined)
296
300
  return;
297
301
  let distance = 0;
298
- if (this.distanceInternal !== undefined && this.daumRunData.distanceInternal !== undefined) {
299
- distance = utils_1.intVal(this.daumRunData.distanceInternal - this.distanceInternal);
302
+ if (this.distanceInternal !== undefined && this.cyclingData.distanceInternal !== undefined) {
303
+ distance = utils_1.intVal(this.cyclingData.distanceInternal - this.distanceInternal);
300
304
  }
301
- if (this.daumRunData.distanceInternal !== undefined)
302
- this.distanceInternal = this.daumRunData.distanceInternal;
305
+ if (this.cyclingData.distanceInternal !== undefined)
306
+ this.distanceInternal = this.cyclingData.distanceInternal;
303
307
  let data = {
304
- speed: utils_1.floatVal(this.daumRunData.speed),
305
- slope: utils_1.floatVal(this.daumRunData.slope),
306
- power: utils_1.intVal(this.daumRunData.power),
307
- cadence: utils_1.intVal(this.daumRunData.pedalRpm),
308
- heartrate: utils_1.intVal(this.daumRunData.heartrate),
308
+ speed: utils_1.floatVal(this.cyclingData.speed),
309
+ slope: utils_1.floatVal(this.cyclingData.slope),
310
+ power: utils_1.intVal(this.cyclingData.power),
311
+ cadence: utils_1.intVal(this.cyclingData.pedalRpm),
312
+ heartrate: utils_1.intVal(this.cyclingData.heartrate),
309
313
  distance,
310
314
  timestamp: Date.now(),
311
- deviceTime: this.daumRunData.time,
312
- deviceDistanceCounter: this.daumRunData.distanceInternal
315
+ deviceTime: this.cyclingData.time,
316
+ deviceDistanceCounter: this.cyclingData.distanceInternal
313
317
  };
314
318
  if (this.ignoreHrm)
315
319
  delete data.heartrate;
@@ -350,7 +354,7 @@ class DaumAdapterBase extends Device_1.default {
350
354
  });
351
355
  }
352
356
  refreshRequests() {
353
- if (!this.daumRunData.isPedalling || this.daumRunData.pedalRpm === 0)
357
+ if (!this.cyclingData.isPedalling || this.cyclingData.pedalRpm === 0)
354
358
  return;
355
359
  let bikeRequest = this.getCyclingMode().sendBikeUpdate({ refresh: true }) || {};
356
360
  const prev = this.requests[this.requests.length - 1] || {};
@@ -361,7 +365,7 @@ class DaumAdapterBase extends Device_1.default {
361
365
  }
362
366
  processClientRequest(request) {
363
367
  if (request.slope !== undefined) {
364
- this.daumRunData.slope = request.slope;
368
+ this.cyclingData.slope = request.slope;
365
369
  }
366
370
  return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
367
371
  let bikeRequest = this.getCyclingMode().sendBikeUpdate(request);
@@ -0,0 +1,8 @@
1
+ import CyclingMode, { UpdateRequest } from "../CyclingMode";
2
+ import PowerMeterCyclingMode from "../modes/power-meter";
3
+ export default class DaumPowerMeterCyclingMode extends PowerMeterCyclingMode implements CyclingMode {
4
+ prevRequest: UpdateRequest;
5
+ hasBikeUpdate: boolean;
6
+ getBikeInitRequest(): UpdateRequest;
7
+ sendBikeUpdate(request: UpdateRequest): UpdateRequest;
8
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const power_meter_1 = __importDefault(require("../modes/power-meter"));
7
+ class DaumPowerMeterCyclingMode extends power_meter_1.default {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.hasBikeUpdate = false;
11
+ }
12
+ getBikeInitRequest() {
13
+ return { slope: 0 };
14
+ }
15
+ sendBikeUpdate(request) {
16
+ super.sendBikeUpdate(request);
17
+ this.prevRequest = {};
18
+ return {};
19
+ }
20
+ }
21
+ exports.default = DaumPowerMeterCyclingMode;
@@ -1,17 +1,14 @@
1
- import { EventLogger } from "gd-eventlog";
2
- import CyclingMode, { CyclingModeBase, CyclingModeProperty, IncyclistBikeData, UpdateRequest } from "../CyclingMode";
1
+ import CyclingMode, { CyclingModeProperty, IncyclistBikeData, UpdateRequest } from "../CyclingMode";
3
2
  import DaumAdapter from "./DaumAdapter";
3
+ import PowerBasedCyclingModeBase from "../modes/power-base";
4
4
  export declare type ERGEvent = {
5
5
  rpmUpdated?: boolean;
6
6
  gearUpdated?: boolean;
7
7
  starting?: boolean;
8
8
  tsStart?: number;
9
9
  };
10
- export default class ERGCyclingMode extends CyclingModeBase implements CyclingMode {
11
- logger: EventLogger;
12
- data: IncyclistBikeData;
10
+ export default class ERGCyclingMode extends PowerBasedCyclingModeBase implements CyclingMode {
13
11
  prevRequest: UpdateRequest;
14
- prevUpdateTS: number;
15
12
  hasBikeUpdate: boolean;
16
13
  chain: number[];
17
14
  cassette: number[];
@@ -3,9 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const gd_eventlog_1 = require("gd-eventlog");
7
6
  const CyclingMode_1 = require("../CyclingMode");
8
7
  const calculations_1 = __importDefault(require("../calculations"));
8
+ const power_base_1 = __importDefault(require("../modes/power-base"));
9
9
  const config = {
10
10
  name: "ERG",
11
11
  description: "Calculates speed based on power and slope. Power is either set by workout or calculated based on gear and cadence",
@@ -14,15 +14,12 @@ const config = {
14
14
  { key: 'startPower', name: 'Starting Power', description: 'Initial power in Watts at start of training', type: CyclingMode_1.CyclingModeProperyType.Integer, default: 50, min: 25, max: 800 },
15
15
  ]
16
16
  };
17
- class ERGCyclingMode extends CyclingMode_1.CyclingModeBase {
17
+ class ERGCyclingMode extends power_base_1.default {
18
18
  constructor(adapter, props) {
19
19
  super(adapter, props);
20
- this.prevUpdateTS = 0;
21
20
  this.hasBikeUpdate = false;
22
21
  this.event = {};
23
- this.logger = adapter.logger || new gd_eventlog_1.EventLogger('ERGMode');
24
- this.data = {};
25
- this.logger.logEvent({ message: 'constructor', props });
22
+ this.initLogger('ERGMode');
26
23
  }
27
24
  getName() {
28
25
  return config.name;
@@ -132,7 +129,6 @@ class ERGCyclingMode extends CyclingMode_1.CyclingModeBase {
132
129
  const prevRequest = this.prevRequest || {};
133
130
  const data = this.data || {};
134
131
  const bikeType = this.getSetting('bikeType').toLowerCase();
135
- console.log('~~~ bikeType', bikeType);
136
132
  delete this.event.gearUpdated;
137
133
  delete this.event.rpmUpdated;
138
134
  if (prevData === {} || prevData.speed === undefined || prevData.speed === 0) {
@@ -140,32 +136,25 @@ class ERGCyclingMode extends CyclingMode_1.CyclingModeBase {
140
136
  this.event.tsStart = Date.now();
141
137
  }
142
138
  try {
143
- let rpm = bikeData.pedalRpm || 0;
144
- let gear = bikeData.gear || 0;
139
+ const rpm = bikeData.pedalRpm || 0;
140
+ const gear = bikeData.gear || 0;
145
141
  let power = bikeData.power || 0;
146
- let slope = (prevData.slope !== undefined ? prevData.slope : prevRequest.slope || 0);
147
- let speed;
148
- let m = this.adapter.getWeight();
149
- let distanceInternal = prevData.distanceInternal || 0;
150
- let ts = Date.now();
151
- let duration = this.prevUpdateTS === 0 ? 0 : ((ts - this.prevUpdateTS) / 1000);
152
- if (rpm === 0 || bikeData.isPedalling === false) {
153
- speed = 0;
142
+ const slope = (prevData.slope !== undefined ? prevData.slope : prevRequest.slope || 0);
143
+ const distanceInternal = prevData.distanceInternal || 0;
144
+ if (!bikeData.pedalRpm || bikeData.isPedalling === false) {
154
145
  power = 0;
155
146
  }
156
- else {
157
- speed = calculations_1.default.calculateSpeed(m, power, slope, { bikeType });
158
- let v = speed / 3.6;
159
- distanceInternal += Math.round(v * duration);
160
- }
147
+ const m = this.getWeight();
148
+ const t = this.getTimeSinceLastUpdate();
149
+ const { speed, distance } = this.calculateSpeedAndDistance(power, slope, m, t, { bikeType });
161
150
  data.speed = parseFloat(speed.toFixed(1));
162
151
  data.power = Math.round(power);
163
- data.distanceInternal = distanceInternal;
152
+ data.distanceInternal = Math.round(distanceInternal + distance);
164
153
  data.slope = slope;
165
154
  data.pedalRpm = rpm;
166
155
  data.gear = gear;
167
- if (data.time !== undefined)
168
- data.time += duration;
156
+ if (data.time !== undefined && !(this.event.starting && !bikeData.pedalRpm))
157
+ data.time += t;
169
158
  else
170
159
  data.time = 0;
171
160
  data.heartrate = bikeData.heartrate;
@@ -176,7 +165,6 @@ class ERGCyclingMode extends CyclingMode_1.CyclingModeBase {
176
165
  if (rpm && rpm !== prevData.pedalRpm) {
177
166
  this.event.rpmUpdated = true;
178
167
  }
179
- this.prevUpdateTS = ts;
180
168
  }
181
169
  catch (err) {
182
170
  this.logger.logEvent({ message: 'error', fn: 'updateData()', error: err.message || err });
@@ -188,7 +176,7 @@ class ERGCyclingMode extends CyclingMode_1.CyclingModeBase {
188
176
  calculateTargetPower(request, updateMode = true) {
189
177
  const bikeType = this.getSetting('bikeType').toLowerCase();
190
178
  const defaultPower = this.getSetting('startPower');
191
- let m = this.adapter.getWeight();
179
+ let m = this.getWeight();
192
180
  const prevData = this.data || {};
193
181
  let target;
194
182
  if (prevData.pedalRpm && prevData.gear && (!updateMode || prevData.pedalRpm !== 0)) {
@@ -109,7 +109,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
109
109
  startState.startProg = true;
110
110
  }
111
111
  if (!startState.setGear) {
112
- yield this.bike.setGear(this.daumRunData.gear || (opts.gear || 10));
112
+ yield this.bike.setGear(this.cyclingData.gear || (opts.gear || 10));
113
113
  startState.setGear = true;
114
114
  }
115
115
  const startRequest = this.getCyclingMode().getBikeInitRequest();
@@ -1,7 +1,7 @@
1
1
  import CyclingMode, { CyclingModeProperty, IncyclistBikeData, Settings, UpdateRequest } from "../../CyclingMode";
2
2
  import DaumAdapter from "../DaumAdapter";
3
- import PowerMeterCyclingMode from "../PowerMeterCyclingMode";
4
- export default class DaumClassicCyclingMode extends PowerMeterCyclingMode implements CyclingMode {
3
+ import DaumPowerMeterCyclingMode from "../DaumPowerMeterCyclingMode";
4
+ export default class DaumClassicCyclingMode extends DaumPowerMeterCyclingMode implements CyclingMode {
5
5
  constructor(adapter: DaumAdapter, props?: Settings);
6
6
  getName(): string;
7
7
  getDescription(): string;
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const gd_eventlog_1 = require("gd-eventlog");
7
7
  const CyclingMode_1 = require("../../CyclingMode");
8
- const PowerMeterCyclingMode_1 = __importDefault(require("../PowerMeterCyclingMode"));
8
+ const DaumPowerMeterCyclingMode_1 = __importDefault(require("../DaumPowerMeterCyclingMode"));
9
9
  const config = {
10
10
  name: "Daum Classic",
11
11
  description: "The device calculates speed and power based on slope. Incyclist will not modify any values recived from the device\nThis mode will not respect maximum power and/or workout limits",
@@ -13,7 +13,7 @@ const config = {
13
13
  { key: 'bikeType', name: 'Bike Type', description: '', type: CyclingMode_1.CyclingModeProperyType.SingleSelect, options: ['Race', 'Mountain'], default: 'Race' },
14
14
  ]
15
15
  };
16
- class DaumClassicCyclingMode extends PowerMeterCyclingMode_1.default {
16
+ class DaumClassicCyclingMode extends DaumPowerMeterCyclingMode_1.default {
17
17
  constructor(adapter, props) {
18
18
  super(adapter, props);
19
19
  this.logger = adapter ? adapter.logger : undefined;
@@ -98,7 +98,7 @@ class DaumPremiumDevice extends DaumAdapter_1.default {
98
98
  info.person = yield this.bike.setPerson(user);
99
99
  }
100
100
  if (!this.getCyclingMode().getModeProperty('eppSupport')) {
101
- const gear = yield this.bike.setGear(this.daumRunData.gear || (opts.gear || 10));
101
+ const gear = yield this.bike.setGear(this.cyclingData.gear || (opts.gear || 10));
102
102
  return gear;
103
103
  }
104
104
  return;
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const net_1 = __importDefault(require("net"));
7
7
  const gd_eventlog_1 = require("gd-eventlog");
8
- const TIMEOUT_OPEN = 1000;
9
8
  var __responses = {};
10
9
  class TcpSocketPort {
11
10
  constructor(props) {
@@ -0,0 +1,20 @@
1
+ import { IncyclistBikeData, Settings, CyclingModeBase } from '../CyclingMode';
2
+ import { DeviceAdapter } from '../Device';
3
+ import { EventLogger } from 'gd-eventlog';
4
+ export default class PowerBasedCyclingModeBase extends CyclingModeBase {
5
+ data: IncyclistBikeData;
6
+ prevUpdateTS: number;
7
+ logger: EventLogger;
8
+ constructor(adapter: DeviceAdapter, props?: Settings);
9
+ initLogger(defaultLogName: any): void;
10
+ getWeight(): any;
11
+ getTimeSinceLastUpdate(): number;
12
+ calculateSpeedAndDistance(power: number, slope: number, m: number, t: number, props?: {}): {
13
+ speed: number;
14
+ distance: number;
15
+ };
16
+ calculatePowerAndDistance(speed: number, slope: number, m: number, t: number, props?: {}): {
17
+ power: number;
18
+ distance: number;
19
+ };
20
+ }