incyclist-devices 1.4.25 → 1.4.28

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.
@@ -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 = ble_interface_1.default.getInstance({ 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);
@@ -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;
@@ -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) {
@@ -37,17 +37,27 @@ class PowerBasedCyclingModeBase extends CyclingMode_1.CyclingModeBase {
37
37
  let powerToMaintainSpeed = calculations_1.default.calculatePower(m, vPrev, slope, props);
38
38
  const powerDelta = powerToMaintainSpeed - power;
39
39
  const Ekin = EkinPrev - powerDelta * t;
40
- const v = Math.sqrt(2 * Ekin / m);
41
- const speed = v * 3.6;
42
- const distance = v * t;
43
- this.data.speed = speed;
44
- return { speed, distance };
40
+ if (Ekin > 0) {
41
+ const v = Math.sqrt(2 * Ekin / m);
42
+ const speed = v * 3.6;
43
+ const distance = v * t;
44
+ this.data.speed = speed;
45
+ return { speed, distance };
46
+ }
47
+ else {
48
+ const v = vPrev * 0.5;
49
+ const speed = v * 3.6;
50
+ const distance = v * t;
51
+ this.data.speed = speed;
52
+ return { speed, distance };
53
+ }
45
54
  }
46
55
  calculatePowerAndDistance(speed, slope, m, t, props = {}) {
47
56
  const prevData = this.data || {};
48
57
  const vPrev = (prevData.speed || 0) / 3.6;
49
58
  const EkinPrev = 1 / 2 * m * vPrev * vPrev;
50
- const Ekin = 1 / 2 * m * speed * speed;
59
+ const vTarget = (speed || 0) / 3.6;
60
+ const Ekin = 1 / 2 * m * vTarget * vTarget;
51
61
  const powerDelta = t !== 0 ? (EkinPrev - Ekin) / t : 0;
52
62
  const powerToMaintainSpeed = calculations_1.default.calculatePower(m, vPrev, slope, props);
53
63
  const power = powerToMaintainSpeed - powerDelta;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.25",
3
+ "version": "1.4.28",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",
@@ -22,6 +22,7 @@
22
22
  "typescript": "^4.5.2"
23
23
  },
24
24
  "scripts": {
25
+ "lint": "eslint . --ext .ts",
25
26
  "build": "tsc",
26
27
  "test": "jest --coverage",
27
28
  "dev": "nodemon --watch src -e ts,js --exec npm run build"