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,347 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const gd_eventlog_1 = require("gd-eventlog");
13
+ const ble_1 = require("./ble");
14
+ class BleInterface extends ble_1.BleInterfaceClass {
15
+ constructor(props = {}) {
16
+ super(props);
17
+ this.scanState = { isScanning: false, timeout: undefined };
18
+ this.connectState = { isConnecting: false, isConnected: false, isOpened: false };
19
+ this.devices = [];
20
+ console.log('BleInterface constructor', props);
21
+ if (props.logger)
22
+ this.logger = props.logger;
23
+ else if (props.log) {
24
+ this.logger = new gd_eventlog_1.EventLogger('BLE');
25
+ }
26
+ }
27
+ static getInstance(props = {}) {
28
+ if (!BleInterface._instance) {
29
+ BleInterface._instance = new BleInterface(props);
30
+ }
31
+ else {
32
+ if (props.binding) {
33
+ BleInterface._instance.setBinding(props.binding);
34
+ }
35
+ if (props.logger) {
36
+ BleInterface._instance.logger = props.logger;
37
+ }
38
+ if (props.log && !BleInterface._instance.logger) {
39
+ BleInterface._instance.logger = new gd_eventlog_1.EventLogger('BLE');
40
+ }
41
+ }
42
+ return BleInterface._instance;
43
+ }
44
+ static register(id, type, Class, services) {
45
+ if (this.deviceClasses.find(i => i.id === id))
46
+ return;
47
+ this.deviceClasses.push({ id, type, Class, services });
48
+ }
49
+ logEvent(event) {
50
+ if (this.logger) {
51
+ this.logger.logEvent(event);
52
+ }
53
+ console.log(event);
54
+ }
55
+ onStateChange(state) {
56
+ if (state !== ble_1.BleState.POWERED_ON) {
57
+ this.connectState.isConnected = false;
58
+ }
59
+ else {
60
+ this.connectState.isConnected = true;
61
+ }
62
+ }
63
+ onError(err) {
64
+ this.logEvent({ message: 'error', error: err.message, stack: err.stack });
65
+ }
66
+ connect(props = {}) {
67
+ const timeout = props.timeout || 2000;
68
+ return new Promise((resolve, reject) => {
69
+ if (this.connectState.isConnected) {
70
+ return resolve(true);
71
+ }
72
+ this.logEvent({ message: 'connect request' });
73
+ if (!this.getBinding())
74
+ return Promise.reject(new Error('no binding defined'));
75
+ if (!this.connectState.isOpened) {
76
+ this.connectState.timeout = setTimeout(() => {
77
+ this.connectState.isConnected = false;
78
+ this.connectState.isConnecting = false;
79
+ this.connectState.timeout = null;
80
+ this.logEvent({ message: 'connect result: timeout' });
81
+ reject(new Error('timeout'));
82
+ }, timeout);
83
+ try {
84
+ const binding = this.getBinding()._bindings;
85
+ const binding_init_original = binding.init.bind(binding);
86
+ const self = this;
87
+ binding.init = function () {
88
+ try {
89
+ binding_init_original();
90
+ self.connectState.isOpened = true;
91
+ }
92
+ catch (err) {
93
+ self.connectState.isOpened = false;
94
+ self.connectState.isConnected = false;
95
+ self.connectState.isConnecting = false;
96
+ this.logEvent({ message: 'connect result: error', error: err.message });
97
+ return reject(new Error(err.message));
98
+ }
99
+ };
100
+ this.getBinding().once('error', (err) => {
101
+ this.connectState.isConnected = true;
102
+ this.connectState.isConnecting = false;
103
+ this.logEvent({ message: 'connect result: error', error: err.message });
104
+ this.getBinding().on('error', this.onError.bind(this));
105
+ return reject(err);
106
+ });
107
+ this.getBinding().on('stateChange', (state) => {
108
+ if (state === ble_1.BleState.POWERED_ON) {
109
+ clearTimeout(this.connectState.timeout);
110
+ this.connectState.timeout = null;
111
+ this.getBinding().removeAllListeners('stateChange');
112
+ this.getBinding().on('stateChange', this.onStateChange.bind(this));
113
+ this.connectState.isConnected = true;
114
+ this.connectState.isConnecting = false;
115
+ this.logEvent({ message: 'connect result: success' });
116
+ return resolve(true);
117
+ }
118
+ });
119
+ }
120
+ catch (err) {
121
+ this.connectState.isConnected = false;
122
+ this.connectState.isConnecting = false;
123
+ if (this.connectState.timeout)
124
+ clearTimeout(this.connectState.timeout);
125
+ this.connectState.timeout = null;
126
+ this.logEvent({ message: 'connect result: error', error: err.message });
127
+ return reject(new Error('bluetooth unavailable, cause: ' + err.message));
128
+ }
129
+ }
130
+ });
131
+ }
132
+ disconnect() {
133
+ return __awaiter(this, void 0, void 0, function* () {
134
+ if (!this.connectState.isConnected) {
135
+ return Promise.resolve(true);
136
+ }
137
+ if (!this.getBinding())
138
+ return Promise.reject(new Error('no binding defined'));
139
+ this.logEvent({ message: 'disconnect request' });
140
+ if (this.scanState.isScanning) {
141
+ yield this.stopScan();
142
+ }
143
+ const connectedDevices = this.devices.filter(d => d.isConnected);
144
+ for (let i = 0; i < connectedDevices.length; i++) {
145
+ const d = connectedDevices[i];
146
+ const device = d.device;
147
+ yield device.disconnect();
148
+ }
149
+ this.connectState.isConnected = false;
150
+ this.connectState.isConnecting = false;
151
+ if (this.connectState.timeout) {
152
+ clearTimeout(this.connectState.timeout);
153
+ this.connectState.timeout = null;
154
+ }
155
+ this.logEvent({ message: 'disconnect result: success' });
156
+ return true;
157
+ });
158
+ }
159
+ isConnected() {
160
+ return this.connectState.isConnected;
161
+ }
162
+ getDevicesFromServices(deviceTypes, services) {
163
+ if (!deviceTypes || !Array.isArray(deviceTypes) || deviceTypes.length === 0) {
164
+ return [];
165
+ }
166
+ const get = (deviceTypes, fnCompare) => {
167
+ return deviceTypes.filter(DeviceType => {
168
+ const C = DeviceType;
169
+ if (!C.services)
170
+ return false;
171
+ return C.services.find((s) => fnCompare(s));
172
+ });
173
+ };
174
+ if (typeof services === 'string') {
175
+ return get(deviceTypes, (s) => s === services);
176
+ }
177
+ if (Array.isArray(services)) {
178
+ return get(deviceTypes, s => services.includes(s));
179
+ }
180
+ return [];
181
+ }
182
+ getServicesFromDeviceTypes(deviceTypes) {
183
+ if (!deviceTypes || !Array.isArray(deviceTypes) || deviceTypes.length === 0) {
184
+ return [];
185
+ }
186
+ const services = [];
187
+ deviceTypes.forEach(DeviceType => {
188
+ if (DeviceType.services) {
189
+ const dtServices = DeviceType.services;
190
+ dtServices.forEach(s => {
191
+ if (!services.find(s2 => s2 === s))
192
+ services.push(s);
193
+ });
194
+ }
195
+ });
196
+ return services;
197
+ }
198
+ getServicesFromDevice(device) {
199
+ if (!device)
200
+ return [];
201
+ const services = [];
202
+ const dServices = device.getServiceUUids();
203
+ dServices.forEach(s => {
204
+ if (!services.find(s2 => s2 === s))
205
+ services.push(s);
206
+ });
207
+ return services;
208
+ }
209
+ connectDevice(requested, timeout = 2000) {
210
+ return __awaiter(this, void 0, void 0, function* () {
211
+ const devices = yield this.scan({ timeout, device: requested });
212
+ const { id, address, name } = requested;
213
+ if (devices.length === 0)
214
+ throw new Error('device not found');
215
+ if (devices[0]) {
216
+ const connected = yield devices[0].connect();
217
+ if (connected) {
218
+ return devices[0];
219
+ }
220
+ else {
221
+ throw new Error('connect failed');
222
+ }
223
+ }
224
+ });
225
+ }
226
+ scan(props) {
227
+ return __awaiter(this, void 0, void 0, function* () {
228
+ const { timeout = 5000, deviceTypes = [], device } = props;
229
+ const scanForDevice = (device !== null && device !== undefined);
230
+ const services = this.getServicesFromDeviceTypes(deviceTypes);
231
+ const bleBinding = this.getBinding();
232
+ if (!bleBinding)
233
+ return Promise.reject(new Error('no binding defined'));
234
+ if (!this.isConnected()) {
235
+ yield this.connect();
236
+ }
237
+ const detectedPeripherals = {};
238
+ if (scanForDevice)
239
+ this.logEvent({ message: 'search device request', device, deviceTypes });
240
+ else
241
+ this.logEvent({ message: 'scan start', services });
242
+ return new Promise((resolve, reject) => {
243
+ if (this.scanState.isScanning) {
244
+ this.logEvent({ message: 'scan result: already scanning' });
245
+ return reject(new Error('scanning already in progress'));
246
+ }
247
+ this.scanState.isScanning = true;
248
+ bleBinding.startScanning(services, true, (err) => {
249
+ if (err) {
250
+ this.logEvent({ message: 'scan result: error', error: err.message });
251
+ this.scanState.isScanning = false;
252
+ return reject(err);
253
+ }
254
+ bleBinding.on('discover', (peripheral) => {
255
+ if (!peripheral || !peripheral.advertisement)
256
+ return;
257
+ if (!detectedPeripherals[peripheral.id]) {
258
+ detectedPeripherals[peripheral.id] = peripheral;
259
+ let DeviceClasses;
260
+ if (scanForDevice && (!deviceTypes || deviceTypes.length === 0)) {
261
+ const classes = BleInterface.deviceClasses.map(c => c.Class);
262
+ DeviceClasses = this.getDevicesFromServices(classes, peripheral.advertisement.serviceUuids);
263
+ }
264
+ else {
265
+ DeviceClasses = this.getDevicesFromServices(deviceTypes, peripheral.advertisement.serviceUuids);
266
+ }
267
+ let cntFound = 0;
268
+ DeviceClasses.forEach(DeviceClass => {
269
+ if (!DeviceClass)
270
+ return;
271
+ if (scanForDevice && cntFound > 0)
272
+ return;
273
+ const C = DeviceClass;
274
+ const d = new C({ peripheral });
275
+ d.setInterface(this);
276
+ if (scanForDevice) {
277
+ if ((device.id && d.id === device.id) || (device.address && d.address === device.address) || (device.name && d.name === device.name))
278
+ cntFound++;
279
+ }
280
+ else
281
+ cntFound++;
282
+ if (cntFound > 0) {
283
+ this.logEvent({ message: 'scan: device found', device: d.name, services: d.services.join(',') });
284
+ this.devices.push({ device: d, isConnected: false });
285
+ this.emit('device', d);
286
+ }
287
+ if (scanForDevice && cntFound > 0) {
288
+ if (this.scanState.timeout) {
289
+ clearTimeout(this.scanState.timeout);
290
+ this.scanState.timeout = null;
291
+ bleBinding.stopScanning(() => {
292
+ this.scanState.isScanning = false;
293
+ });
294
+ }
295
+ resolve([d]);
296
+ }
297
+ });
298
+ }
299
+ });
300
+ });
301
+ this.scanState.timeout = setTimeout(() => {
302
+ this.scanState.timeout = null;
303
+ this.logEvent({ message: 'scan result: devices found', devices: this.devices.map(i => i.device.name) });
304
+ resolve(this.devices.map(i => i.device));
305
+ bleBinding.stopScanning(() => {
306
+ this.scanState.isScanning = false;
307
+ });
308
+ }, timeout);
309
+ });
310
+ });
311
+ }
312
+ stopScan() {
313
+ if (!this.scanState.isScanning) {
314
+ return Promise.resolve(true);
315
+ }
316
+ if (!this.getBinding())
317
+ return Promise.reject(new Error('no binding defined'));
318
+ this.logEvent({ message: 'scan stop request' });
319
+ return new Promise(resolve => {
320
+ this.getBinding().stopScanning(() => {
321
+ this.scanState.isScanning = false;
322
+ this.logEvent({ message: 'scan stop result: success' });
323
+ resolve(true);
324
+ });
325
+ });
326
+ }
327
+ isScanning() {
328
+ return this.scanState.isScanning;
329
+ }
330
+ addConnectedDevice(device) {
331
+ const existigDevice = this.devices.find(i => i.device.id === device.id);
332
+ if (existigDevice) {
333
+ existigDevice.isConnected = true;
334
+ return;
335
+ }
336
+ this.devices.push({ device, isConnected: true });
337
+ }
338
+ removeConnectedDevice(device) {
339
+ const existigDevice = this.devices.find(i => i.device.id === device.id);
340
+ if (existigDevice) {
341
+ existigDevice.isConnected = false;
342
+ return;
343
+ }
344
+ }
345
+ }
346
+ exports.default = BleInterface;
347
+ BleInterface.deviceClasses = [];
@@ -0,0 +1,81 @@
1
+ /// <reference types="node" />
2
+ import EventEmitter from "events";
3
+ export declare type ConnectProps = {
4
+ timeout?: number;
5
+ };
6
+ export interface BleDeviceIdentifier {
7
+ id?: string;
8
+ address?: string;
9
+ name?: string;
10
+ }
11
+ export declare abstract class BleDeviceClass extends EventEmitter {
12
+ static services: string[];
13
+ id?: string;
14
+ address?: string;
15
+ name?: string;
16
+ peripheral?: BlePeripheral;
17
+ abstract getProfile(): string;
18
+ abstract getServiceUUids(): string[];
19
+ abstract connect(props?: ConnectProps): Promise<boolean>;
20
+ abstract disconnect(): Promise<boolean>;
21
+ }
22
+ export interface BleBinding extends EventEmitter {
23
+ startScanning(serviceUUIDs?: string[], allowDuplicates?: boolean, callback?: (error?: Error) => void): void;
24
+ stopScanning(callback?: () => void): void;
25
+ _bindings: any;
26
+ }
27
+ export declare type ScanProps = {
28
+ timeout?: number;
29
+ deviceTypes?: (typeof BleDeviceClass)[];
30
+ device?: BleDeviceClass;
31
+ };
32
+ export declare class BleBindingWrapper {
33
+ protected binding: BleBinding;
34
+ constructor(binding: BleBinding);
35
+ open(): {
36
+ err: Error;
37
+ opened: boolean;
38
+ };
39
+ get(): BleBinding;
40
+ }
41
+ export declare abstract class BleInterfaceClass extends EventEmitter {
42
+ binding: BleBinding;
43
+ constructor(props?: {
44
+ binding?: BleBinding;
45
+ });
46
+ abstract connect(props: ConnectProps): Promise<boolean>;
47
+ abstract scan(props: ScanProps): Promise<BleDeviceClass[]>;
48
+ abstract stopScan(): Promise<boolean>;
49
+ abstract disconnect(): Promise<boolean>;
50
+ abstract isScanning(): boolean;
51
+ abstract addConnectedDevice(device: BleDeviceClass): void;
52
+ abstract removeConnectedDevice(device: BleDeviceClass): void;
53
+ getBinding(): BleBinding;
54
+ setBinding(binding: BleBinding): void;
55
+ }
56
+ export interface BlePeripheral extends EventEmitter, BleDeviceIdentifier {
57
+ services: string[];
58
+ advertisement: any;
59
+ state: string;
60
+ connectAsync(): Promise<void>;
61
+ disconnect(cb: (err?: Error) => void): Promise<void>;
62
+ discoverSomeServicesAndCharacteristicsAsync(serviceUUIDs: string[], characteristicUUIDs: string[]): Promise<any>;
63
+ }
64
+ export interface BleCharacteristic extends EventEmitter {
65
+ }
66
+ export declare type BleDeviceProps = {
67
+ id?: string;
68
+ address?: string;
69
+ name?: string;
70
+ services?: string[];
71
+ ble: BleInterfaceClass;
72
+ peripheral?: BlePeripheral;
73
+ };
74
+ export declare enum BleState {
75
+ UNKNOWN = "unknown",
76
+ RESETTING = "resetting",
77
+ UNSUPPORTED = "unsupported",
78
+ UNAUTHORIZED = "unauthorized",
79
+ POWERED_OFF = "poweredOff",
80
+ POWERED_ON = "poweredOn"
81
+ }
package/lib/ble/ble.js ADDED
@@ -0,0 +1,51 @@
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 events_1 = __importDefault(require("events"));
7
+ class BleDeviceClass extends events_1.default {
8
+ }
9
+ exports.BleDeviceClass = BleDeviceClass;
10
+ BleDeviceClass.services = [];
11
+ class BleBindingWrapper {
12
+ constructor(binding) {
13
+ this.binding = binding;
14
+ this.binding = binding;
15
+ }
16
+ open() {
17
+ const binding = this.binding._bindings;
18
+ const binding_init = binding.init.bind(binding);
19
+ try {
20
+ binding_init();
21
+ return { err: null, opened: true };
22
+ }
23
+ catch (err) {
24
+ const error = err;
25
+ const opened = false;
26
+ return { err: error, opened };
27
+ }
28
+ }
29
+ get() {
30
+ return this.binding;
31
+ }
32
+ }
33
+ exports.BleBindingWrapper = BleBindingWrapper;
34
+ class BleInterfaceClass extends events_1.default {
35
+ constructor(props = {}) {
36
+ super();
37
+ this.setBinding(props.binding);
38
+ }
39
+ getBinding() { return this.binding; }
40
+ setBinding(binding) { this.binding = binding; }
41
+ }
42
+ exports.BleInterfaceClass = BleInterfaceClass;
43
+ var BleState;
44
+ (function (BleState) {
45
+ BleState["UNKNOWN"] = "unknown";
46
+ BleState["RESETTING"] = "resetting";
47
+ BleState["UNSUPPORTED"] = "unsupported";
48
+ BleState["UNAUTHORIZED"] = "unauthorized";
49
+ BleState["POWERED_OFF"] = "poweredOff";
50
+ BleState["POWERED_ON"] = "poweredOn";
51
+ })(BleState = exports.BleState || (exports.BleState = {}));
@@ -0,0 +1,48 @@
1
+ /// <reference types="node" />
2
+ import { BleDevice } from './ble-device';
3
+ import BleInterface from './ble-interface';
4
+ import DeviceAdapter from '../Device';
5
+ import { DeviceProtocol } from '../DeviceProtocol';
6
+ import { BleDeviceClass } from './ble';
7
+ import BleProtocol from './incyclist-protocol';
8
+ import { EventLogger } from 'gd-eventlog';
9
+ declare type HrmData = {
10
+ heartrate: number;
11
+ rr: number;
12
+ raw: string;
13
+ };
14
+ export default class BleHrmDevice extends BleDevice {
15
+ static services: string[];
16
+ static characteristics: string[];
17
+ heartrate: number;
18
+ rr: number;
19
+ constructor(props?: any);
20
+ getProfile(): string;
21
+ getServiceUUids(): string[];
22
+ parseHrm(data: Buffer): HrmData;
23
+ onData(characteristic: string, data: Buffer): void;
24
+ write(characteristic: any, data: any): Promise<boolean>;
25
+ read(characteristic: any): Promise<Buffer>;
26
+ }
27
+ export declare class HrmAdapter extends DeviceAdapter {
28
+ device: BleHrmDevice;
29
+ ignore: boolean;
30
+ ble: BleInterface;
31
+ protocol: DeviceProtocol;
32
+ paused: boolean;
33
+ logger: EventLogger;
34
+ constructor(device: BleDeviceClass, protocol: BleProtocol);
35
+ isBike(): boolean;
36
+ isHrm(): boolean;
37
+ isPower(): boolean;
38
+ getProfile(): string;
39
+ getName(): string;
40
+ getDisplayName(): string;
41
+ getPort(): string;
42
+ setIgnoreHrm(ignore: any): void;
43
+ start(props?: any): Promise<any>;
44
+ stop(): Promise<boolean>;
45
+ pause(): Promise<boolean>;
46
+ resume(): Promise<boolean>;
47
+ }
48
+ export {};
package/lib/ble/hrm.js ADDED
@@ -0,0 +1,128 @@
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 __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const ble_device_1 = require("./ble-device");
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
+ class BleHrmDevice extends ble_device_1.BleDevice {
20
+ constructor(props) {
21
+ super(props);
22
+ this.heartrate = undefined;
23
+ this.rr = undefined;
24
+ }
25
+ getProfile() {
26
+ return 'Heartrate Monitor';
27
+ }
28
+ getServiceUUids() {
29
+ return BleHrmDevice.services;
30
+ }
31
+ parseHrm(data) {
32
+ try {
33
+ const ab = new Uint8Array(data);
34
+ const flags = ab[0];
35
+ let offset = 1;
36
+ if (flags % 1 === 0) {
37
+ this.heartrate = ab[1];
38
+ }
39
+ else {
40
+ this.heartrate = ab[1] + ab[2] * 256;
41
+ offset = 2;
42
+ }
43
+ if (flags % 0xF) {
44
+ this.rr = (ab[offset + 1] + ab[offset + 2] * 256) / 1024;
45
+ }
46
+ }
47
+ catch (err) {
48
+ }
49
+ const { heartrate, rr } = this;
50
+ return { heartrate, rr, raw: data.toString('hex') };
51
+ }
52
+ onData(characteristic, data) {
53
+ if (characteristic.toLocaleLowerCase() === '2a37') {
54
+ const res = this.parseHrm(data);
55
+ this.emit('data', res);
56
+ }
57
+ }
58
+ write(characteristic, data) {
59
+ console.log('write', characteristic, data);
60
+ return Promise.resolve(true);
61
+ }
62
+ read(characteristic) {
63
+ console.log('read', characteristic);
64
+ return Promise.resolve(Buffer.from([]));
65
+ }
66
+ }
67
+ exports.default = BleHrmDevice;
68
+ BleHrmDevice.services = ['180d'];
69
+ BleHrmDevice.characteristics = ['2a37', '2a38', '2a39', '2a3c'];
70
+ ble_interface_1.default.register('BleHrmDevice', 'hr', BleHrmDevice, BleHrmDevice.services);
71
+ class HrmAdapter extends Device_1.default {
72
+ constructor(device, protocol) {
73
+ super(protocol);
74
+ this.ignore = false;
75
+ this.paused = false;
76
+ this.device = device;
77
+ this.ble = protocol.ble;
78
+ this.logger = new gd_eventlog_1.EventLogger('BleHrm');
79
+ }
80
+ isBike() { return false; }
81
+ isHrm() { return true; }
82
+ isPower() { return false; }
83
+ getProfile() {
84
+ return 'Heartrate Monitor';
85
+ }
86
+ getName() {
87
+ return `${this.device.name}`;
88
+ }
89
+ getDisplayName() {
90
+ const { name, heartrate: hrm } = this.device;
91
+ const hrmStr = hrm ? ` (${hrm})` : '';
92
+ return `${name}${hrmStr}`;
93
+ }
94
+ getPort() {
95
+ return 'ble';
96
+ }
97
+ setIgnoreHrm(ignore) {
98
+ this.ignore = ignore;
99
+ }
100
+ start(props) {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ this.logger.logEvent({ message: 'start requested', props });
103
+ try {
104
+ const bleDevice = yield this.ble.connectDevice(this.device);
105
+ if (bleDevice) {
106
+ this.device = bleDevice;
107
+ bleDevice.on('data', (data) => {
108
+ if (this.onDataFn && !this.ignore && !this.paused)
109
+ this.onDataFn(data);
110
+ });
111
+ return true;
112
+ }
113
+ }
114
+ catch (err) {
115
+ this.logger.logEvent({ message: 'start result: error', error: err.message });
116
+ return false;
117
+ }
118
+ });
119
+ }
120
+ stop() {
121
+ return __awaiter(this, void 0, void 0, function* () {
122
+ return this.device.disconnect();
123
+ });
124
+ }
125
+ pause() { this.paused = true; return Promise.resolve(true); }
126
+ resume() { this.paused = false; return Promise.resolve(true); }
127
+ }
128
+ exports.HrmAdapter = HrmAdapter;
@@ -0,0 +1,31 @@
1
+ import { EventLogger } from "gd-eventlog";
2
+ import DeviceProtocolBase, { DeviceProtocol, DeviceSettings, ScanProps, Device } from "../DeviceProtocol";
3
+ import { BleBinding, BleDeviceClass } from "./ble";
4
+ import BleInterface from "./ble-interface";
5
+ interface BleDeviceSettings extends DeviceSettings {
6
+ id?: string;
7
+ profile: string;
8
+ address?: string;
9
+ protocol: string;
10
+ interface: string;
11
+ }
12
+ export default class BleProtocol extends DeviceProtocolBase implements DeviceProtocol {
13
+ static _defaultBinding: BleBinding;
14
+ static _instances: BleProtocol[];
15
+ logger: EventLogger;
16
+ ble: BleInterface;
17
+ constructor(binding?: BleBinding);
18
+ static setDefaultBinding(binding: BleBinding): void;
19
+ setBinding(binding: BleBinding): void;
20
+ createDevice(bleDevice: BleDeviceClass | BleDeviceSettings): Device;
21
+ getName(): string;
22
+ getInterfaces(): Array<string>;
23
+ isBike(): boolean;
24
+ isHrm(): boolean;
25
+ isPower(): boolean;
26
+ add(settings: BleDeviceSettings): Device;
27
+ scan(props: ScanProps): Promise<void>;
28
+ stopScan(): Promise<void>;
29
+ isScanning(): boolean;
30
+ }
31
+ export {};