incyclist-devices 1.4.28 → 1.4.31

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.
@@ -17,7 +17,6 @@ class BleInterface extends ble_1.BleInterfaceClass {
17
17
  this.scanState = { isScanning: false, timeout: undefined };
18
18
  this.connectState = { isConnecting: false, isConnected: false, isOpened: false };
19
19
  this.devices = [];
20
- console.log('BleInterface constructor', props);
21
20
  if (props.logger)
22
21
  this.logger = props.logger;
23
22
  else if (props.log) {
@@ -50,7 +49,9 @@ class BleInterface extends ble_1.BleInterfaceClass {
50
49
  if (this.logger) {
51
50
  this.logger.logEvent(event);
52
51
  }
53
- console.log(event);
52
+ if (process.env.BLE_DEBUG) {
53
+ console.log(event);
54
+ }
54
55
  }
55
56
  onStateChange(state) {
56
57
  if (state !== ble_1.BleState.POWERED_ON) {
@@ -93,7 +94,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
93
94
  self.connectState.isOpened = false;
94
95
  self.connectState.isConnected = false;
95
96
  self.connectState.isConnecting = false;
96
- this.logEvent({ message: 'connect result: error', error: err.message });
97
+ self.logEvent({ message: 'connect result: error', error: err.message });
97
98
  return reject(new Error(err.message));
98
99
  }
99
100
  };
package/lib/ble/hrm.js CHANGED
@@ -75,7 +75,7 @@ class HrmAdapter extends Device_1.default {
75
75
  this.paused = false;
76
76
  this.device = device;
77
77
  this.ble = protocol.ble;
78
- this.logger = new gd_eventlog_1.EventLogger('BleHrm');
78
+ this.logger = new gd_eventlog_1.EventLogger('Ble-HR');
79
79
  }
80
80
  isBike() { return false; }
81
81
  isHrm() { return true; }
@@ -25,7 +25,7 @@ const DeviceRegistry_1 = __importDefault(require("../DeviceRegistry"));
25
25
  const ble_1 = require("./ble");
26
26
  const ble_interface_1 = __importDefault(require("./ble-interface"));
27
27
  const hrm_1 = __importStar(require("./hrm"));
28
- const pwr_1 = __importDefault(require("./pwr"));
28
+ const pwr_1 = __importStar(require("./pwr"));
29
29
  const supportedDeviceTypes = [hrm_1.default, pwr_1.default];
30
30
  class BleProtocol extends DeviceProtocol_1.default {
31
31
  constructor(binding) {
@@ -58,6 +58,9 @@ class BleProtocol extends DeviceProtocol_1.default {
58
58
  case 'hr':
59
59
  case 'heartrate monitor':
60
60
  return new hrm_1.HrmAdapter(fromDevice ? bleDevice : new hrm_1.default(props()), this);
61
+ case 'cp':
62
+ case 'power meter':
63
+ return new pwr_1.PwrAdapter(fromDevice ? bleDevice : new pwr_1.default(props()), this);
61
64
  }
62
65
  }
63
66
  getName() { return 'BLE'; }
package/lib/ble/pwr.d.ts CHANGED
@@ -1,9 +1,18 @@
1
1
  /// <reference types="node" />
2
2
  import { BleDevice } from './ble-device';
3
+ import BleInterface from './ble-interface';
4
+ import BleProtocol from './incyclist-protocol';
5
+ import { BleDeviceClass } from './ble';
6
+ import DeviceAdapter, { DeviceData } from '../Device';
7
+ import { DeviceProtocol } from '../DeviceProtocol';
8
+ import { EventLogger } from 'gd-eventlog';
9
+ import CyclingMode from '../CyclingMode';
10
+ import { IncyclistBikeData } from '../CyclingMode';
3
11
  declare type PowerData = {
4
12
  instantaneousPower?: number;
5
13
  balance?: number;
6
14
  accTorque?: number;
15
+ time: number;
7
16
  rpm: number;
8
17
  raw?: Buffer;
9
18
  };
@@ -18,15 +27,51 @@ export default class BleCyclingPowerDevice extends BleDevice {
18
27
  instantaneousPower: number;
19
28
  balance: number;
20
29
  accTorque: number;
30
+ rpm: number;
31
+ timeOffset: number;
32
+ time: number;
21
33
  currentCrankData: CrankData;
22
34
  prevCrankData: CrankData;
23
- rpm: number;
35
+ constructor(props?: any);
24
36
  getProfile(): string;
25
37
  getServiceUUids(): string[];
26
- getRpm(crankData: any): number;
38
+ parseCrankData(crankData: any): {
39
+ rpm: number;
40
+ time: any;
41
+ };
27
42
  parsePower(data: Buffer): PowerData;
28
43
  onData(characteristic: string, data: Buffer): void;
29
44
  write(characteristic: any, data: any): Promise<boolean>;
30
45
  read(characteristic: any): Promise<Buffer>;
46
+ reset(): void;
47
+ }
48
+ export declare class PwrAdapter extends DeviceAdapter {
49
+ device: BleCyclingPowerDevice;
50
+ ignore: boolean;
51
+ ble: BleInterface;
52
+ protocol: DeviceProtocol;
53
+ paused: boolean;
54
+ logger: EventLogger;
55
+ mode: CyclingMode;
56
+ distanceInternal: number;
57
+ constructor(device: BleDeviceClass, protocol: BleProtocol);
58
+ isBike(): boolean;
59
+ isHrm(): boolean;
60
+ isPower(): boolean;
61
+ getProfile(): string;
62
+ getName(): string;
63
+ getDisplayName(): string;
64
+ getCyclingMode(): CyclingMode;
65
+ getDefaultCyclingMode(): CyclingMode;
66
+ getPort(): string;
67
+ setIgnoreBike(ignore: any): void;
68
+ setIgnorePower(ignore: any): void;
69
+ onDeviceData(deviceData: PowerData): void;
70
+ mapData(deviceData: PowerData): IncyclistBikeData;
71
+ transformData(bikeData: IncyclistBikeData): DeviceData;
72
+ start(props?: any): Promise<any>;
73
+ stop(): Promise<boolean>;
74
+ pause(): Promise<boolean>;
75
+ resume(): Promise<boolean>;
31
76
  }
32
77
  export {};
package/lib/ble/pwr.js CHANGED
@@ -1,19 +1,33 @@
1
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
+ };
2
11
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
13
  };
5
14
  Object.defineProperty(exports, "__esModule", { value: true });
6
15
  const ble_device_1 = require("./ble-device");
7
16
  const ble_interface_1 = __importDefault(require("./ble-interface"));
17
+ const Device_1 = __importDefault(require("../Device"));
18
+ const gd_eventlog_1 = require("gd-eventlog");
19
+ const power_meter_1 = __importDefault(require("../modes/power-meter"));
8
20
  class BleCyclingPowerDevice extends ble_device_1.BleDevice {
9
- constructor() {
10
- super(...arguments);
21
+ constructor(props) {
22
+ super(props);
11
23
  this.instantaneousPower = undefined;
12
24
  this.balance = undefined;
13
25
  this.accTorque = undefined;
26
+ this.rpm = undefined;
27
+ this.timeOffset = 0;
28
+ this.time = undefined;
14
29
  this.currentCrankData = undefined;
15
30
  this.prevCrankData = undefined;
16
- this.rpm = undefined;
17
31
  }
18
32
  getProfile() {
19
33
  return 'cp';
@@ -21,7 +35,7 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
21
35
  getServiceUUids() {
22
36
  return BleCyclingPowerDevice.services;
23
37
  }
24
- getRpm(crankData) {
38
+ parseCrankData(crankData) {
25
39
  if (!this.prevCrankData)
26
40
  this.prevCrankData = { revolutions: 0, time: 0, cntUpdateMissing: -1 };
27
41
  const c = this.currentCrankData = crankData;
@@ -31,8 +45,10 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
31
45
  if (hasUpdate) {
32
46
  let time = c.time - p.time;
33
47
  let revs = c.revolutions - p.revolutions;
34
- if (c.time < p.time)
48
+ if (c.time < p.time) {
35
49
  time += 0x10000;
50
+ this.timeOffset += 0x10000;
51
+ }
36
52
  if (c.revolutions < p.revolutions)
37
53
  revs += 0x10000;
38
54
  rpm = 1024 * 60 * revs / time;
@@ -48,7 +64,7 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
48
64
  this.prevCrankData.cntUpdateMissing = 0;
49
65
  else
50
66
  this.prevCrankData.cntUpdateMissing = cntUpdateMissing + 1;
51
- return rpm;
67
+ return { rpm, time: this.timeOffset + c.time };
52
68
  }
53
69
  parsePower(data) {
54
70
  try {
@@ -66,14 +82,16 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
66
82
  revolutions: data.readUInt16LE(offset),
67
83
  time: data.readUInt16LE(offset + 2)
68
84
  };
69
- this.rpm = this.getRpm(crankData);
85
+ const { rpm, time } = this.parseCrankData(crankData);
86
+ this.rpm = rpm;
87
+ this.time = time;
70
88
  offset += 4;
71
89
  }
72
90
  }
73
91
  catch (err) {
74
92
  }
75
- const { instantaneousPower, balance, accTorque, rpm } = this;
76
- return { instantaneousPower, balance, accTorque, rpm, raw: data };
93
+ const { instantaneousPower, balance, accTorque, rpm, time } = this;
94
+ return { instantaneousPower, balance, accTorque, rpm, time, raw: data };
77
95
  }
78
96
  onData(characteristic, data) {
79
97
  if (characteristic.toLocaleLowerCase() === '2a63') {
@@ -89,8 +107,137 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
89
107
  console.log('read', characteristic);
90
108
  return Promise.resolve(Buffer.from([]));
91
109
  }
110
+ reset() {
111
+ this.instantaneousPower = undefined;
112
+ this.balance = undefined;
113
+ this.accTorque = undefined;
114
+ this.rpm = undefined;
115
+ this.timeOffset = 0;
116
+ this.time = undefined;
117
+ this.currentCrankData = undefined;
118
+ this.prevCrankData = undefined;
119
+ }
92
120
  }
93
121
  exports.default = BleCyclingPowerDevice;
94
122
  BleCyclingPowerDevice.services = ['1818'];
95
123
  BleCyclingPowerDevice.characteristics = ['2a63', '2a65', '2a5d', '2a3c'];
96
124
  ble_interface_1.default.register('BleCyclingPowerDevice', 'cp', BleCyclingPowerDevice, BleCyclingPowerDevice.services);
125
+ class PwrAdapter extends Device_1.default {
126
+ constructor(device, protocol) {
127
+ super(protocol);
128
+ this.ignore = false;
129
+ this.paused = false;
130
+ this.distanceInternal = 0;
131
+ this.device = device;
132
+ this.ble = protocol.ble;
133
+ this.mode = this.getDefaultCyclingMode();
134
+ this.logger = new gd_eventlog_1.EventLogger('Ble-CP');
135
+ }
136
+ isBike() { return true; }
137
+ isHrm() { return false; }
138
+ isPower() { return true; }
139
+ getProfile() {
140
+ return 'Power Meter';
141
+ }
142
+ getName() {
143
+ return `${this.device.name}`;
144
+ }
145
+ getDisplayName() {
146
+ const { name, instantaneousPower: power } = this.device;
147
+ const powerStr = power ? ` (${power})` : '';
148
+ return `${name}${powerStr}`;
149
+ }
150
+ getCyclingMode() {
151
+ if (!this.mode)
152
+ this.mode = this.getDefaultCyclingMode();
153
+ return this.mode;
154
+ }
155
+ getDefaultCyclingMode() {
156
+ return new power_meter_1.default(this);
157
+ }
158
+ getPort() {
159
+ return 'ble';
160
+ }
161
+ setIgnoreBike(ignore) {
162
+ this.ignore = ignore;
163
+ }
164
+ setIgnorePower(ignore) {
165
+ this.ignore = ignore;
166
+ }
167
+ onDeviceData(deviceData) {
168
+ this.logger.logEvent({ message: 'onDeviceData', data: deviceData });
169
+ let incyclistData = this.mapData(deviceData);
170
+ incyclistData = this.getCyclingMode().updateData(incyclistData);
171
+ const data = this.transformData(incyclistData);
172
+ if (this.onDataFn && !this.ignore && !this.paused)
173
+ this.onDataFn(data);
174
+ }
175
+ mapData(deviceData) {
176
+ const data = {
177
+ isPedalling: false,
178
+ power: 0,
179
+ pedalRpm: 0,
180
+ speed: 0,
181
+ heartrate: 0,
182
+ distanceInternal: 0,
183
+ slope: undefined,
184
+ time: undefined
185
+ };
186
+ data.power = (deviceData.instantaneousPower !== undefined ? deviceData.instantaneousPower : data.power);
187
+ data.pedalRpm = (deviceData.rpm !== undefined ? deviceData.rpm : data.pedalRpm);
188
+ data.time = (deviceData.time !== undefined ? deviceData.time : data.time);
189
+ data.isPedalling = data.pedalRpm > 0 || (data.pedalRpm === undefined && data.power > 0);
190
+ return data;
191
+ }
192
+ transformData(bikeData) {
193
+ if (this.ignore) {
194
+ return {};
195
+ }
196
+ if (bikeData === undefined)
197
+ return;
198
+ let distance = 0;
199
+ if (this.distanceInternal !== undefined && bikeData.distanceInternal !== undefined) {
200
+ distance = Math.round(bikeData.distanceInternal - this.distanceInternal);
201
+ }
202
+ if (bikeData.distanceInternal !== undefined)
203
+ this.distanceInternal = bikeData.distanceInternal;
204
+ let data = {
205
+ speed: bikeData.speed,
206
+ slope: bikeData.slope,
207
+ power: bikeData.power !== undefined ? Math.round(bikeData.power) : undefined,
208
+ cadence: bikeData.pedalRpm !== undefined ? Math.round(bikeData.pedalRpm) : undefined,
209
+ distance,
210
+ timestamp: Date.now()
211
+ };
212
+ return data;
213
+ }
214
+ start(props) {
215
+ return __awaiter(this, void 0, void 0, function* () {
216
+ this.logger.logEvent({ message: 'start requested', props });
217
+ try {
218
+ const bleDevice = yield this.ble.connectDevice(this.device);
219
+ if (bleDevice) {
220
+ this.device = bleDevice;
221
+ bleDevice.on('data', (data) => {
222
+ this.onDeviceData(data);
223
+ });
224
+ return true;
225
+ }
226
+ }
227
+ catch (err) {
228
+ this.logger.logEvent({ message: 'start result: error', error: err.message });
229
+ return false;
230
+ }
231
+ });
232
+ }
233
+ stop() {
234
+ return __awaiter(this, void 0, void 0, function* () {
235
+ this.distanceInternal = 0;
236
+ this.device.reset();
237
+ return this.device.disconnect();
238
+ });
239
+ }
240
+ pause() { this.paused = true; return Promise.resolve(true); }
241
+ resume() { this.paused = false; return Promise.resolve(true); }
242
+ }
243
+ exports.PwrAdapter = PwrAdapter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.28",
3
+ "version": "1.4.31",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",