incyclist-devices 2.0.0-beta.1 → 2.0.0
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.
- package/README.MD +238 -0
- package/lib/adapters.d.ts +1 -0
- package/lib/adapters.js +19 -0
- package/lib/antv2/adapter-factory.d.ts +8 -7
- package/lib/antv2/adapter-factory.js +4 -2
- package/lib/antv2/adapter.d.ts +3 -2
- package/lib/antv2/adapter.js +15 -4
- package/lib/antv2/ant-interface.d.ts +6 -2
- package/lib/antv2/ant-interface.js +27 -21
- package/lib/antv2/binding.d.ts +1 -1
- package/lib/antv2/binding.js +1 -1
- package/lib/antv2/fe/adapter.d.ts +12 -9
- package/lib/antv2/fe/adapter.js +67 -27
- package/lib/antv2/hr/adapter.d.ts +6 -5
- package/lib/antv2/hr/adapter.js +19 -16
- package/lib/antv2/index.d.ts +2 -2
- package/lib/antv2/pwr/adapter.d.ts +6 -4
- package/lib/antv2/pwr/adapter.js +24 -16
- package/lib/antv2/sensor-factory.d.ts +2 -2
- package/lib/antv2/types.d.ts +5 -2
- package/lib/antv2/types.js +3 -0
- package/lib/antv2/utils.d.ts +3 -0
- package/lib/antv2/utils.js +12 -1
- package/lib/base/adpater.d.ts +14 -2
- package/lib/base/adpater.js +43 -4
- package/lib/ble/adapter-factory.d.ts +18 -16
- package/lib/ble/adapter-factory.js +54 -45
- package/lib/ble/base/adapter.d.ts +53 -0
- package/lib/ble/{adapter.js → base/adapter.js} +111 -9
- package/lib/ble/base/comms-utils.d.ts +7 -0
- package/lib/ble/base/comms-utils.js +91 -0
- package/lib/ble/{ble-comms.d.ts → base/comms.d.ts} +27 -17
- package/lib/ble/{ble-comms.js → base/comms.js} +179 -53
- package/lib/ble/bindings/index.d.ts +2 -0
- package/lib/ble/bindings/index.js +8 -0
- package/lib/ble/bindings/linux.d.ts +15 -0
- package/lib/ble/bindings/linux.js +39 -0
- package/lib/ble/bindings/mock.d.ts +9 -0
- package/lib/ble/bindings/mock.js +108 -0
- package/lib/ble/bindings/types.d.ts +57 -0
- package/lib/ble/bindings/types.js +96 -0
- package/lib/ble/ble-interface.d.ts +34 -46
- package/lib/ble/ble-interface.js +242 -345
- package/lib/ble/ble-peripheral.d.ts +4 -2
- package/lib/ble/ble-peripheral.js +39 -8
- package/lib/ble/consts.d.ts +1 -0
- package/lib/ble/consts.js +2 -1
- package/lib/ble/cp/adapter.d.ts +1 -2
- package/lib/ble/cp/adapter.js +2 -15
- package/lib/ble/cp/comm.d.ts +8 -5
- package/lib/ble/cp/comm.js +12 -27
- package/lib/ble/elite/adapter.d.ts +1 -2
- package/lib/ble/elite/adapter.js +12 -19
- package/lib/ble/elite/comms.d.ts +8 -4
- package/lib/ble/elite/comms.js +12 -25
- package/lib/ble/fm/adapter.d.ts +3 -2
- package/lib/ble/fm/adapter.js +129 -70
- package/lib/ble/fm/comms.d.ts +8 -8
- package/lib/ble/fm/comms.js +33 -55
- package/lib/ble/fm/types.d.ts +5 -0
- package/lib/ble/hr/adapter.d.ts +1 -4
- package/lib/ble/hr/adapter.js +1 -18
- package/lib/ble/hr/comm.d.ts +6 -2
- package/lib/ble/hr/comm.js +6 -2
- package/lib/ble/hr/mock.d.ts +7 -0
- package/lib/ble/hr/mock.js +47 -0
- package/lib/ble/index.d.ts +2 -1
- package/lib/ble/index.js +5 -5
- package/lib/ble/peripheral-cache.d.ts +43 -0
- package/lib/ble/peripheral-cache.js +107 -0
- package/lib/ble/tacx/adapter.d.ts +1 -1
- package/lib/ble/tacx/adapter.js +20 -14
- package/lib/ble/tacx/comms.d.ts +6 -6
- package/lib/ble/tacx/comms.js +10 -43
- package/lib/ble/types.d.ts +54 -27
- package/lib/ble/types.js +0 -17
- package/lib/ble/utils.d.ts +15 -5
- package/lib/ble/utils.js +25 -66
- package/lib/ble/wahoo/adapter.d.ts +1 -1
- package/lib/ble/wahoo/adapter.js +12 -10
- package/lib/ble/wahoo/comms.d.ts +7 -6
- package/lib/ble/wahoo/comms.js +15 -17
- package/lib/index.d.ts +10 -7
- package/lib/index.js +21 -25
- package/lib/interfaces.d.ts +2 -1
- package/lib/interfaces.js +4 -0
- package/lib/modes/power-base.js +4 -0
- package/lib/serial/adapter.d.ts +5 -0
- package/lib/serial/adapter.js +19 -0
- package/lib/serial/bindings/tcp.d.ts +2 -1
- package/lib/serial/bindings/tcp.js +19 -5
- package/lib/serial/daum/DaumAdapter.d.ts +1 -1
- package/lib/serial/daum/DaumAdapter.js +16 -10
- package/lib/serial/daum/premium/adapter.d.ts +1 -0
- package/lib/serial/daum/premium/adapter.js +9 -2
- package/lib/serial/daum/premium/comms.js +10 -3
- package/lib/serial/daum/premium/mock.js +0 -1
- package/lib/serial/index.d.ts +3 -3
- package/lib/serial/index.js +2 -2
- package/lib/serial/kettler/ergo-racer/adapter.d.ts +1 -4
- package/lib/serial/kettler/ergo-racer/adapter.js +15 -39
- package/lib/serial/serial-interface.d.ts +3 -1
- package/lib/serial/serial-interface.js +43 -17
- package/lib/simulator/Simulator.d.ts +2 -0
- package/lib/simulator/Simulator.js +8 -5
- package/lib/types/adapter.d.ts +10 -3
- package/lib/types/device.d.ts +3 -0
- package/lib/types/interface.d.ts +7 -3
- package/package.json +3 -5
- package/lib/ble/adapter.d.ts +0 -41
- package/lib/ble/ble.d.ts +0 -57
- package/lib/ble/ble.js +0 -48
- package/lib/device.d.ts +0 -0
- package/lib/device.js +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import BleAdapter from "./base/adapter";
|
|
2
|
+
import BlePeripheralConnector from "./ble-peripheral";
|
|
3
|
+
import { BleCharacteristic, BlePeripheral } from "./types";
|
|
4
|
+
export interface PeripheralState {
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
isConfigured: boolean;
|
|
7
|
+
isInterrupted: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface PeripheralCacheItem {
|
|
10
|
+
address: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
id?: string;
|
|
13
|
+
ts: number;
|
|
14
|
+
peripheral: BlePeripheral;
|
|
15
|
+
state?: PeripheralState;
|
|
16
|
+
characteristics?: BleCharacteristic[];
|
|
17
|
+
connector?: BlePeripheralConnector;
|
|
18
|
+
}
|
|
19
|
+
export default class BlePeripheralCache {
|
|
20
|
+
peripherals: PeripheralCacheItem[];
|
|
21
|
+
findAdapter(adapter: BleAdapter): PeripheralCacheItem;
|
|
22
|
+
getConnector(peripheral: BlePeripheral): BlePeripheralConnector;
|
|
23
|
+
getPeripheral(query: {
|
|
24
|
+
id?: string;
|
|
25
|
+
address?: string;
|
|
26
|
+
name?: string;
|
|
27
|
+
}): BlePeripheral;
|
|
28
|
+
handleStopScan(): void;
|
|
29
|
+
find(query: {
|
|
30
|
+
name?: string;
|
|
31
|
+
id?: string;
|
|
32
|
+
address?: string;
|
|
33
|
+
peripheral?: BlePeripheral;
|
|
34
|
+
}): PeripheralCacheItem;
|
|
35
|
+
filter(services: string[]): PeripheralCacheItem[];
|
|
36
|
+
protected _findIndex(query: {
|
|
37
|
+
name?: string;
|
|
38
|
+
id?: string;
|
|
39
|
+
address?: string;
|
|
40
|
+
}): number;
|
|
41
|
+
add(item: PeripheralCacheItem): PeripheralCacheItem;
|
|
42
|
+
remove(query: PeripheralCacheItem | BlePeripheral): void;
|
|
43
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
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_peripheral_1 = __importDefault(require("./ble-peripheral"));
|
|
7
|
+
class BlePeripheralCache {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.peripherals = [];
|
|
10
|
+
}
|
|
11
|
+
findAdapter(adapter) {
|
|
12
|
+
return this.find(adapter.getSettings());
|
|
13
|
+
}
|
|
14
|
+
getConnector(peripheral) {
|
|
15
|
+
const info = this.find({ address: peripheral.address });
|
|
16
|
+
if (!info) {
|
|
17
|
+
const item = this.add({ address: peripheral.address, ts: Date.now(), peripheral });
|
|
18
|
+
return item.connector;
|
|
19
|
+
}
|
|
20
|
+
return info.connector;
|
|
21
|
+
}
|
|
22
|
+
getPeripheral(query) {
|
|
23
|
+
const info = this.find(query);
|
|
24
|
+
return info ? info.peripheral : undefined;
|
|
25
|
+
}
|
|
26
|
+
handleStopScan() {
|
|
27
|
+
const ongoing = this.peripherals.filter(i => i.state && i.state.isLoading);
|
|
28
|
+
if (ongoing)
|
|
29
|
+
ongoing.forEach(i => { i.state.isInterrupted = true; });
|
|
30
|
+
}
|
|
31
|
+
find(query) {
|
|
32
|
+
const { peripheral } = query;
|
|
33
|
+
const { name, address, id } = peripheral ? peripheral : query;
|
|
34
|
+
if (!name && !address && !id)
|
|
35
|
+
throw new Error('illegal query, one of <id>,<name>,<address> needs to be provided');
|
|
36
|
+
if (address)
|
|
37
|
+
return this.peripherals.find(i => i.address === address);
|
|
38
|
+
else if (name)
|
|
39
|
+
return this.peripherals.find(i => i.name === name);
|
|
40
|
+
else if (id)
|
|
41
|
+
return this.peripherals.find(i => i.id === id);
|
|
42
|
+
}
|
|
43
|
+
filter(services) {
|
|
44
|
+
if (services.length === 0) {
|
|
45
|
+
return this.peripherals;
|
|
46
|
+
}
|
|
47
|
+
return this.peripherals.filter(i => {
|
|
48
|
+
const announced = i.peripheral.services.map(s => s.uuid);
|
|
49
|
+
const requested = services;
|
|
50
|
+
return (announced.find(s => requested.includes(s)));
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
_findIndex(query) {
|
|
54
|
+
const { name, address, id } = query;
|
|
55
|
+
if (!name && !address && !id)
|
|
56
|
+
throw new Error('illegal query, one of <id>,<name>,<address> needs to be provided');
|
|
57
|
+
if (address)
|
|
58
|
+
return this.peripherals.findIndex(i => i.address === address);
|
|
59
|
+
else if (name)
|
|
60
|
+
return this.peripherals.findIndex(i => i.name === name);
|
|
61
|
+
else if (id)
|
|
62
|
+
return this.peripherals.findIndex(i => i.id === id);
|
|
63
|
+
}
|
|
64
|
+
add(item) {
|
|
65
|
+
const { address, name, id } = item;
|
|
66
|
+
const { ts, peripheral, state, characteristics } = item;
|
|
67
|
+
const cachedItem = this.find({ address, name, id });
|
|
68
|
+
if (cachedItem) {
|
|
69
|
+
cachedItem.ts = ts;
|
|
70
|
+
cachedItem.peripheral = peripheral;
|
|
71
|
+
if (state)
|
|
72
|
+
cachedItem.state = state;
|
|
73
|
+
if (characteristics) {
|
|
74
|
+
cachedItem.characteristics = characteristics;
|
|
75
|
+
}
|
|
76
|
+
if (!cachedItem.connector) {
|
|
77
|
+
cachedItem.connector = item.connector || new ble_peripheral_1.default(cachedItem.peripheral);
|
|
78
|
+
}
|
|
79
|
+
return cachedItem;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const newItem = Object.assign({}, item);
|
|
83
|
+
if (newItem.peripheral && !newItem.connector)
|
|
84
|
+
newItem.connector = new ble_peripheral_1.default(item.peripheral);
|
|
85
|
+
this.peripherals.push(newItem);
|
|
86
|
+
return newItem;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
remove(query) {
|
|
90
|
+
const item = query;
|
|
91
|
+
const isCacheItem = item.peripheral !== undefined;
|
|
92
|
+
let cachedItemIdx;
|
|
93
|
+
if (isCacheItem) {
|
|
94
|
+
const { address, name, id } = item;
|
|
95
|
+
cachedItemIdx = this._findIndex({ address, name, id });
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const peripheral = query;
|
|
99
|
+
const { address } = peripheral;
|
|
100
|
+
cachedItemIdx = this._findIndex({ address });
|
|
101
|
+
}
|
|
102
|
+
if (cachedItemIdx == -1)
|
|
103
|
+
return;
|
|
104
|
+
this.peripherals.splice(cachedItemIdx);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.default = BlePeripheralCache;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BleFmAdapter } from '../fm';
|
|
2
|
-
import BleAdapter from '../adapter';
|
|
2
|
+
import BleAdapter from '../base/adapter';
|
|
3
3
|
import { DeviceProperties } from '../../types/device';
|
|
4
4
|
import { BleDeviceSettings, BleStartProperties } from '../types';
|
|
5
5
|
export default class BleTacxFEAdapter extends BleFmAdapter {
|
package/lib/ble/tacx/adapter.js
CHANGED
|
@@ -40,44 +40,50 @@ class BleTacxFEAdapter extends fm_1.BleFmAdapter {
|
|
|
40
40
|
}
|
|
41
41
|
start(props = {}) {
|
|
42
42
|
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
if (this.started)
|
|
44
|
+
return true;
|
|
45
|
+
if (this.ble.isScanning()) {
|
|
46
|
+
this.logger.logEvent({ message: 'stop previous scan', isScanning: this.ble.isScanning() });
|
|
45
47
|
yield this.ble.stopScan();
|
|
48
|
+
}
|
|
49
|
+
const connected = yield this.connect();
|
|
50
|
+
if (!connected)
|
|
51
|
+
throw new Error(`could not start device, reason:could not connect`);
|
|
52
|
+
this.logger.logEvent({ message: 'start requested', protocol: this.getProtocolName(), props });
|
|
46
53
|
try {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.device = bleDevice;
|
|
54
|
+
const comms = this.device;
|
|
55
|
+
if (comms) {
|
|
56
|
+
this.device = comms;
|
|
51
57
|
const mode = this.getCyclingMode();
|
|
52
58
|
if (mode && mode.getSetting('bikeType')) {
|
|
53
59
|
const bikeType = mode.getSetting('bikeType').toLowerCase();
|
|
54
|
-
|
|
60
|
+
comms.setCrr(fm_1.cRR);
|
|
55
61
|
switch (bikeType) {
|
|
56
62
|
case 'race':
|
|
57
|
-
|
|
63
|
+
comms.setCw(fm_1.cwABike.race);
|
|
58
64
|
break;
|
|
59
65
|
case 'triathlon':
|
|
60
|
-
|
|
66
|
+
comms.setCw(fm_1.cwABike.triathlon);
|
|
61
67
|
break;
|
|
62
68
|
case 'mountain':
|
|
63
|
-
|
|
69
|
+
comms.setCw(fm_1.cwABike.mountain);
|
|
64
70
|
break;
|
|
65
71
|
}
|
|
66
72
|
}
|
|
67
73
|
const { user, wheelDiameter, gearRatio, bikeWeight = adpater_1.DEFAULT_BIKE_WEIGHT } = props || {};
|
|
68
74
|
const userWeight = (user && user.weight ? user.weight : adpater_1.DEFAULT_USER_WEIGHT);
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
comms.sendTrackResistance(0.0);
|
|
76
|
+
comms.sendUserConfiguration(userWeight, bikeWeight, wheelDiameter, gearRatio);
|
|
71
77
|
const startRequest = this.getCyclingMode().getBikeInitRequest();
|
|
72
78
|
yield this.sendUpdate(startRequest);
|
|
73
|
-
|
|
79
|
+
comms.on('data', (data) => {
|
|
74
80
|
this.onDeviceData(data);
|
|
75
81
|
});
|
|
76
82
|
this.resetData();
|
|
77
83
|
this.stopped = false;
|
|
78
84
|
this.started = true;
|
|
79
85
|
this.paused = false;
|
|
80
|
-
if (
|
|
86
|
+
if (comms.features.heartrate && !this.hasCapability(capabilities_1.IncyclistCapability.HeartRate)) {
|
|
81
87
|
this.capabilities.push(capabilities_1.IncyclistCapability.HeartRate);
|
|
82
88
|
}
|
|
83
89
|
return true;
|
package/lib/ble/tacx/comms.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import { LegacyProfile } from "../../antv2/types";
|
|
2
3
|
import { CrankData } from "../cp";
|
|
3
4
|
import { IndoorBikeData } from "../fm";
|
|
4
5
|
import BleFitnessMachineDevice from "../fm/comms";
|
|
5
|
-
import { IBlePeripheralConnector } from "../types";
|
|
6
|
+
import { BleProtocol, IBlePeripheralConnector } from "../types";
|
|
6
7
|
import { BleFeBikeData } from "./types";
|
|
7
8
|
export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineDevice {
|
|
9
|
+
static protocol: BleProtocol;
|
|
8
10
|
static services: string[];
|
|
9
11
|
static characteristics: string[];
|
|
10
12
|
static PROFILE: string;
|
|
@@ -19,15 +21,13 @@ export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineD
|
|
|
19
21
|
tacxRx: string;
|
|
20
22
|
tacxTx: string;
|
|
21
23
|
constructor(props?: any);
|
|
22
|
-
isMatching(characteristics: string[]): boolean;
|
|
24
|
+
static isMatching(characteristics: string[]): boolean;
|
|
23
25
|
setCharacteristicUUIDs(uuids: string[]): void;
|
|
24
26
|
subscribeAll(conn?: IBlePeripheralConnector): Promise<void>;
|
|
25
27
|
init(): Promise<boolean>;
|
|
26
|
-
getProfile():
|
|
28
|
+
getProfile(): LegacyProfile;
|
|
29
|
+
getProtocol(): BleProtocol;
|
|
27
30
|
getServiceUUids(): string[];
|
|
28
|
-
isBike(): boolean;
|
|
29
|
-
isPower(): boolean;
|
|
30
|
-
isHrm(): boolean;
|
|
31
31
|
requestControl(): Promise<boolean>;
|
|
32
32
|
parseCrankData(crankData: any): {
|
|
33
33
|
rpm?: undefined;
|
package/lib/ble/tacx/comms.js
CHANGED
|
@@ -12,6 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const _1 = require(".");
|
|
15
16
|
const consts_1 = require("../consts");
|
|
16
17
|
const comms_1 = __importDefault(require("../fm/comms"));
|
|
17
18
|
const utils_1 = require("../utils");
|
|
@@ -50,7 +51,7 @@ class TacxAdvancedFitnessMachineDevice extends comms_1.default {
|
|
|
50
51
|
this.tacxRx = consts_1.TACX_FE_C_RX;
|
|
51
52
|
this.tacxTx = consts_1.TACX_FE_C_TX;
|
|
52
53
|
}
|
|
53
|
-
isMatching(characteristics) {
|
|
54
|
+
static isMatching(characteristics) {
|
|
54
55
|
if (!characteristics)
|
|
55
56
|
return false;
|
|
56
57
|
const hasTacxCP = characteristics.find(c => (0, utils_1.matches)(c, consts_1.TACX_FE_C_RX)) !== undefined &&
|
|
@@ -66,36 +67,8 @@ class TacxAdvancedFitnessMachineDevice extends comms_1.default {
|
|
|
66
67
|
});
|
|
67
68
|
}
|
|
68
69
|
subscribeAll(conn) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const timeout = Date.now() + 5500;
|
|
72
|
-
const iv = setInterval(() => {
|
|
73
|
-
const subscriptionStatus = characteristics.map(c => this.subscribedCharacteristics.find(s => s === c) !== undefined);
|
|
74
|
-
const done = subscriptionStatus.filter(s => s === true).length === characteristics.length;
|
|
75
|
-
if (done || Date.now() > timeout) {
|
|
76
|
-
clearInterval(iv);
|
|
77
|
-
resolve();
|
|
78
|
-
}
|
|
79
|
-
}, 100);
|
|
80
|
-
try {
|
|
81
|
-
const connector = conn || this.ble.getConnector(this.peripheral);
|
|
82
|
-
for (let i = 0; i < characteristics.length; i++) {
|
|
83
|
-
const c = characteristics[i];
|
|
84
|
-
const isAlreadySubscribed = connector.isSubscribed(c);
|
|
85
|
-
if (!isAlreadySubscribed) {
|
|
86
|
-
connector.removeAllListeners(c);
|
|
87
|
-
connector.on(c, (uuid, data) => {
|
|
88
|
-
this.onData(uuid, data);
|
|
89
|
-
});
|
|
90
|
-
connector.subscribe(c);
|
|
91
|
-
this.subscribedCharacteristics.push(c);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
catch (err) {
|
|
96
|
-
this.logEvent({ message: 'Error', fn: 'subscribeAll()', error: err.message, stack: err.stack });
|
|
97
|
-
}
|
|
98
|
-
});
|
|
70
|
+
const characteristics = [consts_1.CSC_MEASUREMENT, consts_1.CSP_MEASUREMENT, consts_1.INDOOR_BIKE_DATA, consts_1.FTMS_STATUS, consts_1.FTMS_CP, consts_1.TACX_FE_C_RX];
|
|
71
|
+
return this.subscribeMultiple(characteristics, conn);
|
|
99
72
|
}
|
|
100
73
|
init() {
|
|
101
74
|
const _super = Object.create(null, {
|
|
@@ -103,8 +76,7 @@ class TacxAdvancedFitnessMachineDevice extends comms_1.default {
|
|
|
103
76
|
});
|
|
104
77
|
return __awaiter(this, void 0, void 0, function* () {
|
|
105
78
|
try {
|
|
106
|
-
yield _super.initDevice.call(this);
|
|
107
|
-
return true;
|
|
79
|
+
return yield _super.initDevice.call(this);
|
|
108
80
|
}
|
|
109
81
|
catch (err) {
|
|
110
82
|
this.logEvent({ message: 'error', fn: 'TacxAdvancedFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
|
|
@@ -113,20 +85,14 @@ class TacxAdvancedFitnessMachineDevice extends comms_1.default {
|
|
|
113
85
|
});
|
|
114
86
|
}
|
|
115
87
|
getProfile() {
|
|
116
|
-
return
|
|
88
|
+
return 'Smart Trainer';
|
|
89
|
+
}
|
|
90
|
+
getProtocol() {
|
|
91
|
+
return _1.BleTacxComms.protocol;
|
|
117
92
|
}
|
|
118
93
|
getServiceUUids() {
|
|
119
94
|
return TacxAdvancedFitnessMachineDevice.services;
|
|
120
95
|
}
|
|
121
|
-
isBike() {
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
isPower() {
|
|
125
|
-
return true;
|
|
126
|
-
}
|
|
127
|
-
isHrm() {
|
|
128
|
-
return this.hasService('180d');
|
|
129
|
-
}
|
|
130
96
|
requestControl() {
|
|
131
97
|
return __awaiter(this, void 0, void 0, function* () {
|
|
132
98
|
return true;
|
|
@@ -660,6 +626,7 @@ class TacxAdvancedFitnessMachineDevice extends comms_1.default {
|
|
|
660
626
|
}
|
|
661
627
|
}
|
|
662
628
|
exports.default = TacxAdvancedFitnessMachineDevice;
|
|
629
|
+
TacxAdvancedFitnessMachineDevice.protocol = 'tacx';
|
|
663
630
|
TacxAdvancedFitnessMachineDevice.services = [consts_1.TACX_FE_C_BLE];
|
|
664
631
|
TacxAdvancedFitnessMachineDevice.characteristics = ['2acc', '2ad2', '2ad6', '2ad8', '2ad9', '2ada', consts_1.TACX_FE_C_RX, consts_1.TACX_FE_C_TX];
|
|
665
632
|
TacxAdvancedFitnessMachineDevice.PROFILE = PROFILE_ID;
|
package/lib/ble/types.d.ts
CHANGED
|
@@ -1,27 +1,67 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import EventEmitter from "events";
|
|
4
|
+
import { EventLogger } from "gd-eventlog";
|
|
5
|
+
import { DeviceProperties, DeviceSettings, DeviceStartProperties, IncyclistScanProps } from "../types/device";
|
|
6
|
+
import { InterfaceProps } from "../types/interface";
|
|
7
|
+
export type BleProtocol = 'hr' | 'fm' | 'cp' | 'tacx' | 'wahoo' | 'elite';
|
|
8
|
+
export type BleInterfaceState = 'unknown' | 'resetting' | 'unsupported' | 'unauthorized' | 'poweredOff' | 'poweredOn';
|
|
9
|
+
export interface BleBinding extends EventEmitter {
|
|
10
|
+
startScanning(serviceUUIDs?: string[], allowDuplicates?: boolean, callback?: (error?: Error) => void): void;
|
|
11
|
+
stopScanning(callback?: () => void): void;
|
|
12
|
+
_bindings: any;
|
|
13
|
+
state: BleInterfaceState;
|
|
14
|
+
on(eventName: string | symbol, listener: (...args: any[]) => void): this;
|
|
15
|
+
}
|
|
16
|
+
export interface BleScanProps extends IncyclistScanProps {
|
|
17
|
+
protocol?: BleProtocol;
|
|
18
|
+
protocols?: BleProtocol[];
|
|
19
|
+
isBackgroundScan?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface BleDeviceConstructProps extends BleDeviceProps {
|
|
22
|
+
log?: boolean;
|
|
23
|
+
logger?: EventLogger;
|
|
24
|
+
peripheral?: BlePeripheral;
|
|
25
|
+
}
|
|
5
26
|
export interface BleDeviceSettings extends DeviceSettings {
|
|
6
27
|
id?: string;
|
|
7
|
-
|
|
8
|
-
|
|
28
|
+
protocol: BleProtocol;
|
|
29
|
+
profile?: string;
|
|
9
30
|
address?: string;
|
|
31
|
+
name?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface BleDetectedDevice extends BleDeviceSettings {
|
|
34
|
+
peripheral: BlePeripheral;
|
|
10
35
|
}
|
|
11
36
|
export interface BleDeviceProperties extends DeviceProperties {
|
|
12
37
|
wheelDiameter?: number;
|
|
13
38
|
gearRatio?: number;
|
|
14
39
|
}
|
|
15
|
-
export interface BleStartProperties extends
|
|
40
|
+
export interface BleStartProperties extends DeviceStartProperties {
|
|
41
|
+
wheelDiameter?: number;
|
|
42
|
+
gearRatio?: number;
|
|
16
43
|
restart?: boolean;
|
|
44
|
+
scanOnly?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface BleInterfaceProps extends InterfaceProps {
|
|
47
|
+
binding?: BleBinding;
|
|
48
|
+
timeout?: number;
|
|
49
|
+
reconnect?: boolean;
|
|
17
50
|
}
|
|
51
|
+
export type BleService = {
|
|
52
|
+
uuid: string;
|
|
53
|
+
};
|
|
54
|
+
export type DiscoverResult = {
|
|
55
|
+
services: BleService[];
|
|
56
|
+
characteristics: BleCharacteristic[];
|
|
57
|
+
};
|
|
18
58
|
export interface BlePeripheral extends EventEmitter, BlePeripheralIdentifier {
|
|
19
|
-
services:
|
|
59
|
+
services: [];
|
|
20
60
|
advertisement: any;
|
|
21
61
|
state: string;
|
|
22
62
|
connectAsync(): Promise<void>;
|
|
23
63
|
disconnect(cb: (err?: Error) => void): Promise<void>;
|
|
24
|
-
discoverSomeServicesAndCharacteristicsAsync(serviceUUIDs: string[], characteristicUUIDs: string[]): Promise<
|
|
64
|
+
discoverSomeServicesAndCharacteristicsAsync(serviceUUIDs: string[], characteristicUUIDs: string[]): Promise<DiscoverResult>;
|
|
25
65
|
}
|
|
26
66
|
export interface IBlePeripheralConnector {
|
|
27
67
|
connect(): Promise<void>;
|
|
@@ -43,9 +83,12 @@ export interface IBlePeripheralConnector {
|
|
|
43
83
|
export interface BleCharacteristic extends EventEmitter {
|
|
44
84
|
uuid: string;
|
|
45
85
|
properties: string[];
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
86
|
+
_serviceUuid?: string;
|
|
87
|
+
name?: string;
|
|
88
|
+
subscribe(callback: (err: Error | undefined) => void): void;
|
|
89
|
+
unsubscribe(callback: (err: Error | undefined) => void): void;
|
|
90
|
+
read(callback: (err: Error | undefined, data: Buffer) => void): void;
|
|
91
|
+
write(data: Buffer, withoutResponse: boolean, callback?: (err: Error | undefined) => void): void;
|
|
49
92
|
}
|
|
50
93
|
export type BleDeviceProps = {
|
|
51
94
|
id?: string;
|
|
@@ -54,7 +97,7 @@ export type BleDeviceProps = {
|
|
|
54
97
|
services?: string[];
|
|
55
98
|
peripheral?: BlePeripheral;
|
|
56
99
|
};
|
|
57
|
-
export type
|
|
100
|
+
export type BleCommsConnectProps = {
|
|
58
101
|
timeout?: number;
|
|
59
102
|
reconnect?: boolean;
|
|
60
103
|
};
|
|
@@ -83,19 +126,3 @@ export type BleDeviceInfo = {
|
|
|
83
126
|
model?: string;
|
|
84
127
|
serialNo?: string;
|
|
85
128
|
};
|
|
86
|
-
export declare abstract class BleDeviceCommsClass extends EventEmitter {
|
|
87
|
-
static services: string[];
|
|
88
|
-
id?: string;
|
|
89
|
-
address?: string;
|
|
90
|
-
name?: string;
|
|
91
|
-
connectState: ConnectState;
|
|
92
|
-
getConnectState(): ConnectState;
|
|
93
|
-
isConnected(): boolean;
|
|
94
|
-
abstract getProfile(): string;
|
|
95
|
-
abstract getServiceUUids(): string[];
|
|
96
|
-
abstract connect(props?: ConnectProps): Promise<boolean>;
|
|
97
|
-
abstract disconnect(): Promise<boolean>;
|
|
98
|
-
abstract getDeviceInfo(): Promise<BleDeviceInfo>;
|
|
99
|
-
abstract getServices(): string[];
|
|
100
|
-
setCharacteristicUUIDs(uuids: string[]): void;
|
|
101
|
-
}
|
package/lib/ble/types.js
CHANGED
|
@@ -1,19 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BleDeviceCommsClass = void 0;
|
|
4
|
-
const stream_1 = require("stream");
|
|
5
|
-
class BleDeviceCommsClass extends stream_1.EventEmitter {
|
|
6
|
-
constructor() {
|
|
7
|
-
super(...arguments);
|
|
8
|
-
this.connectState = { isConnecting: false, isConnected: false, isDisconnecting: false };
|
|
9
|
-
}
|
|
10
|
-
getConnectState() {
|
|
11
|
-
return this.connectState;
|
|
12
|
-
}
|
|
13
|
-
isConnected() {
|
|
14
|
-
return this.connectState.isConnected;
|
|
15
|
-
}
|
|
16
|
-
setCharacteristicUUIDs(uuids) { }
|
|
17
|
-
}
|
|
18
|
-
exports.BleDeviceCommsClass = BleDeviceCommsClass;
|
|
19
|
-
BleDeviceCommsClass.services = [];
|
package/lib/ble/utils.d.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LegacyProfile } from "../antv2/types";
|
|
2
|
+
import { BleCharacteristic, BlePeripheral, BleProtocol } from "./types";
|
|
3
|
+
type MappingRecord = {
|
|
4
|
+
profile: LegacyProfile;
|
|
5
|
+
protocol: BleProtocol;
|
|
6
|
+
};
|
|
7
|
+
export declare function mapLegacyProfile(profile: string): MappingRecord;
|
|
2
8
|
export declare function uuid(s: string): string;
|
|
3
9
|
export declare function matches(uuid1: string, uuid2: string): boolean;
|
|
4
|
-
export declare function
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
export declare function getPeripheralInfo(p: BlePeripheral): {
|
|
11
|
+
id: string;
|
|
12
|
+
name: any;
|
|
13
|
+
address: string;
|
|
14
|
+
services: any;
|
|
15
|
+
};
|
|
16
|
+
export declare function getCharachteristicsInfo(c: BleCharacteristic): string;
|
|
17
|
+
export {};
|
package/lib/ble/utils.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getCharachteristicsInfo = exports.getPeripheralInfo = exports.matches = exports.uuid = exports.mapLegacyProfile = void 0;
|
|
4
|
+
function mapLegacyProfile(profile) {
|
|
5
|
+
switch (profile) {
|
|
6
|
+
case 'Smart Trainer': return { profile: 'Smart Trainer', protocol: 'fm' };
|
|
7
|
+
case 'Elite Smart Trainer': return { profile: 'Smart Trainer', protocol: 'elite' };
|
|
8
|
+
case 'Heartrate Monitor': return { profile: 'Heartrate Monitor', protocol: 'hr' };
|
|
9
|
+
case 'Power Meter': return { profile: 'Power Meter', protocol: 'cp' };
|
|
10
|
+
case 'Tacx Smart Trainer': return { profile: 'Smart Trainer', protocol: 'tacx' };
|
|
11
|
+
case 'Wahoo Smart Trainer': return { profile: 'Smart Trainer', protocol: 'wahoo' };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.mapLegacyProfile = mapLegacyProfile;
|
|
4
15
|
function uuid(s) {
|
|
5
16
|
if (s) {
|
|
6
17
|
if (s.includes('-')) {
|
|
@@ -24,72 +35,20 @@ function matches(uuid1, uuid2) {
|
|
|
24
35
|
return false;
|
|
25
36
|
}
|
|
26
37
|
exports.matches = matches;
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
details.sort((a, b) => b.priority - a.priority);
|
|
32
|
-
return details[0].class;
|
|
33
|
-
}
|
|
34
|
-
exports.getBestDeviceMatch = getBestDeviceMatch;
|
|
35
|
-
function getDevicesFromServices(deviceTypes, services) {
|
|
36
|
-
if (!deviceTypes || !Array.isArray(deviceTypes) || deviceTypes.length === 0) {
|
|
37
|
-
return [];
|
|
38
|
-
}
|
|
39
|
-
const get = (deviceTypes, fnCompare) => {
|
|
40
|
-
const types = deviceTypes.filter(DeviceType => {
|
|
41
|
-
const C = DeviceType;
|
|
42
|
-
let found = false;
|
|
43
|
-
if (C.services)
|
|
44
|
-
found = C.services.find((s) => fnCompare(s));
|
|
45
|
-
return found;
|
|
46
|
-
});
|
|
47
|
-
return types;
|
|
48
|
-
};
|
|
49
|
-
if (typeof services === 'string') {
|
|
50
|
-
return get(deviceTypes, (s) => matches(s, services));
|
|
51
|
-
}
|
|
52
|
-
if (Array.isArray(services)) {
|
|
53
|
-
const sids = services.map(uuid);
|
|
54
|
-
return get(deviceTypes, s => {
|
|
55
|
-
const res = sids.find((service) => matches(s, service));
|
|
56
|
-
return res !== undefined;
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
return [];
|
|
60
|
-
}
|
|
61
|
-
exports.getDevicesFromServices = getDevicesFromServices;
|
|
62
|
-
function getServicesFromDeviceTypes(deviceTypes) {
|
|
63
|
-
let services = [];
|
|
64
|
-
try {
|
|
65
|
-
if (!deviceTypes || !Array.isArray(deviceTypes) || deviceTypes.length === 0) {
|
|
66
|
-
return [];
|
|
67
|
-
}
|
|
68
|
-
deviceTypes.forEach(DeviceType => {
|
|
69
|
-
if (DeviceType.services) {
|
|
70
|
-
const dtServices = DeviceType.services;
|
|
71
|
-
dtServices.forEach(s => {
|
|
72
|
-
if (!services.find(s2 => s2 === s))
|
|
73
|
-
services.push(s);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
});
|
|
38
|
+
function getPeripheralInfo(p) {
|
|
39
|
+
const { id, name, address, advertisement, services } = p;
|
|
40
|
+
if (advertisement) {
|
|
41
|
+
return { id, name: advertisement.localName, address, services: advertisement.serviceUuids };
|
|
77
42
|
}
|
|
78
|
-
|
|
79
|
-
|
|
43
|
+
else {
|
|
44
|
+
return { id, name, address, services };
|
|
80
45
|
}
|
|
81
|
-
return services;
|
|
82
46
|
}
|
|
83
|
-
exports.
|
|
84
|
-
function
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
dServices.forEach(s => {
|
|
90
|
-
if (!services.find(s2 => s2 === s))
|
|
91
|
-
services.push(s);
|
|
92
|
-
});
|
|
93
|
-
return services;
|
|
47
|
+
exports.getPeripheralInfo = getPeripheralInfo;
|
|
48
|
+
function getCharachteristicsInfo(c) {
|
|
49
|
+
const { uuid, properties, name, _serviceUuid } = c;
|
|
50
|
+
const nameStr = name ? ` (${name})` : '';
|
|
51
|
+
const serviceStr = _serviceUuid ? `${_serviceUuid}:` : '';
|
|
52
|
+
return `${serviceStr}${uuid}${nameStr} ${properties}`;
|
|
94
53
|
}
|
|
95
|
-
exports.
|
|
54
|
+
exports.getCharachteristicsInfo = getCharachteristicsInfo;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BleFmAdapter } from '../fm';
|
|
2
|
-
import BleAdapter from '../adapter';
|
|
2
|
+
import BleAdapter from '../base/adapter';
|
|
3
3
|
import { BleDeviceProperties, BleDeviceSettings, BleStartProperties } from '../types';
|
|
4
4
|
export default class BleWahooAdapter extends BleFmAdapter {
|
|
5
5
|
constructor(settings: BleDeviceSettings, props?: BleDeviceProperties);
|