incyclist-devices 1.4.42 → 1.4.45

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 (47) hide show
  1. package/lib/CyclingMode.js +1 -0
  2. package/lib/Device.js +1 -0
  3. package/lib/DeviceProtocol.js +1 -0
  4. package/lib/DeviceSupport.js +25 -8
  5. package/lib/ant/AntAdapter.js +1 -0
  6. package/lib/ant/AntScanner.js +24 -7
  7. package/lib/ant/antfe/AntFEAdapter.js +7 -7
  8. package/lib/ant/anthrm/AntHrmAdapter.js +1 -1
  9. package/lib/ant/antpwr/pwr-adapter.js +1 -1
  10. package/lib/ant/utils.js +3 -1
  11. package/lib/ble/ble-device.d.ts +10 -3
  12. package/lib/ble/ble-device.js +144 -32
  13. package/lib/ble/ble-interface.d.ts +22 -4
  14. package/lib/ble/ble-interface.js +224 -167
  15. package/lib/ble/ble.d.ts +20 -1
  16. package/lib/ble/ble.js +3 -1
  17. package/lib/ble/fm.d.ts +11 -1
  18. package/lib/ble/fm.js +109 -11
  19. package/lib/ble/hrm.d.ts +0 -1
  20. package/lib/ble/hrm.js +1 -4
  21. package/lib/ble/incyclist-protocol.js +24 -8
  22. package/lib/ble/pwr.d.ts +1 -1
  23. package/lib/ble/pwr.js +14 -4
  24. package/lib/calculations.js +1 -0
  25. package/lib/daum/DaumAdapter.js +29 -13
  26. package/lib/daum/SmartTrainerCyclingMode.js +1 -0
  27. package/lib/daum/classic/DaumClassicAdapter.js +1 -1
  28. package/lib/daum/classic/DaumClassicProtocol.js +23 -7
  29. package/lib/daum/classic/bike.js +26 -26
  30. package/lib/daum/classic/utils.js +1 -0
  31. package/lib/daum/constants.js +1 -0
  32. package/lib/daum/premium/DaumPremiumAdapter.js +1 -1
  33. package/lib/daum/premium/DaumPremiumProtocol.js +23 -7
  34. package/lib/daum/premium/bike.js +18 -17
  35. package/lib/daum/premium/utils.js +1 -0
  36. package/lib/kettler/comms.d.ts +1 -0
  37. package/lib/kettler/comms.js +2 -1
  38. package/lib/kettler/ergo-racer/adapter.js +25 -9
  39. package/lib/kettler/ergo-racer/protocol.d.ts +1 -1
  40. package/lib/kettler/ergo-racer/protocol.js +23 -7
  41. package/lib/modes/power-meter.js +1 -0
  42. package/lib/simulator/Simulator.d.ts +1 -1
  43. package/lib/simulator/Simulator.js +24 -7
  44. package/lib/types/route.js +1 -0
  45. package/lib/types/user.js +1 -0
  46. package/lib/utils.js +3 -1
  47. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CyclingModeBase = exports.CyclingModeProperyType = void 0;
3
4
  var CyclingModeProperyType;
4
5
  (function (CyclingModeProperyType) {
5
6
  CyclingModeProperyType["Integer"] = "Integer";
package/lib/Device.js CHANGED
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_USER_WEIGHT = exports.DEFAULT_BIKE_WEIGHT = void 0;
3
4
  exports.DEFAULT_BIKE_WEIGHT = 10;
4
5
  exports.DEFAULT_USER_WEIGHT = 75;
5
6
  class IncyclistDevice {
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.INTERFACE = void 0;
3
4
  exports.INTERFACE = {
4
5
  SERIAL: 'serial',
5
6
  ANT: 'ant',
@@ -1,32 +1,49 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
5
18
  var __importStar = (this && this.__importStar) || function (mod) {
6
19
  if (mod && mod.__esModule) return mod;
7
20
  var result = {};
8
- if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
9
- result["default"] = mod;
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
10
23
  return result;
11
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
12
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.BleFitnessMachineDevice = exports.BleCyclingPowerDevice = exports.BleHrmDevice = exports.BleInterface = exports.CyclingModeProperyType = exports.BleProtocol = exports.AntScanner = exports.Protocols = exports.Device = exports.INTERFACE = exports.DeviceRegistry = exports.DeviceProtocolBase = void 0;
13
30
  const DeviceRegistry_1 = __importDefault(require("./DeviceRegistry"));
14
31
  exports.DeviceRegistry = DeviceRegistry_1.default;
15
32
  const Device_1 = __importDefault(require("./Device"));
16
33
  exports.Device = Device_1.default;
17
34
  const DeviceProtocol_1 = __importStar(require("./DeviceProtocol"));
18
35
  exports.DeviceProtocolBase = DeviceProtocol_1.default;
19
- exports.INTERFACE = DeviceProtocol_1.INTERFACE;
36
+ Object.defineProperty(exports, "INTERFACE", { enumerable: true, get: function () { return DeviceProtocol_1.INTERFACE; } });
20
37
  const Simulator_1 = __importDefault(require("./simulator/Simulator"));
21
38
  const DaumPremiumProtocol_1 = __importDefault(require("./daum/premium/DaumPremiumProtocol"));
22
39
  const DaumClassicProtocol_1 = __importDefault(require("./daum/classic/DaumClassicProtocol"));
23
40
  const protocol_1 = __importDefault(require("./kettler/ergo-racer/protocol"));
24
41
  const AntScanner_1 = require("./ant/AntScanner");
25
- exports.AntScanner = AntScanner_1.AntScanner;
42
+ Object.defineProperty(exports, "AntScanner", { enumerable: true, get: function () { return AntScanner_1.AntScanner; } });
26
43
  const incyclist_protocol_1 = __importDefault(require("./ble/incyclist-protocol"));
27
44
  exports.BleProtocol = incyclist_protocol_1.default;
28
45
  const CyclingMode_1 = require("./CyclingMode");
29
- exports.CyclingModeProperyType = CyclingMode_1.CyclingModeProperyType;
46
+ Object.defineProperty(exports, "CyclingModeProperyType", { enumerable: true, get: function () { return CyclingMode_1.CyclingModeProperyType; } });
30
47
  const ble_interface_1 = __importDefault(require("./ble/ble-interface"));
31
48
  exports.BleInterface = ble_interface_1.default;
32
49
  const hrm_1 = __importDefault(require("./ble/hrm"));
@@ -3,6 +3,7 @@ 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
+ exports.DEFAULT_UPDATE_FREQUENCY = void 0;
6
7
  const Device_1 = __importDefault(require("../Device"));
7
8
  exports.DEFAULT_UPDATE_FREQUENCY = 1000;
8
9
  class AntAdapter extends Device_1.default {
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -8,17 +31,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
31
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
32
  });
10
33
  };
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
34
  var __importDefault = (this && this.__importDefault) || function (mod) {
19
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
20
36
  };
21
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.AntScanner = exports.AntProtocol = void 0;
22
39
  const gd_eventlog_1 = require("gd-eventlog");
23
40
  const DeviceProtocol_1 = __importStar(require("../DeviceProtocol"));
24
41
  const AntHrmAdapter_1 = __importDefault(require("./anthrm/AntHrmAdapter"));
@@ -52,7 +52,7 @@ class AntFEAdapter extends AntAdapter_1.default {
52
52
  getDisplayName() {
53
53
  const { DeviceID, ManId, ComputedHeartRate } = this.deviceData;
54
54
  const hrmStr = ComputedHeartRate ? ` (${ComputedHeartRate})` : '';
55
- return `${utils_1.getBrand(ManId)} FE ${DeviceID}${hrmStr}`;
55
+ return `${(0, utils_1.getBrand)(ManId)} FE ${DeviceID}${hrmStr}`;
56
56
  }
57
57
  onAttached() {
58
58
  this.logger.logEvent({ message: 'Device connected' });
@@ -233,7 +233,7 @@ class AntFEAdapter extends AntAdapter_1.default {
233
233
  trackResistanceSent: false,
234
234
  userSent: false,
235
235
  };
236
- utils_2.runWithRetries(() => __awaiter(this, void 0, void 0, function* () {
236
+ (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () {
237
237
  if (this.isStopped())
238
238
  resolve(false);
239
239
  try {
@@ -299,18 +299,18 @@ class AntFEAdapter extends AntAdapter_1.default {
299
299
  try {
300
300
  const isReset = (!request || request.reset || Object.keys(request).length === 0);
301
301
  if (request.slope !== undefined) {
302
- yield utils_2.runWithRetries(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTrackResistance(request.slope); }), 2, 100);
302
+ yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTrackResistance(request.slope); }), 2, 100);
303
303
  }
304
304
  if (request.targetPower !== undefined) {
305
- yield utils_2.runWithRetries(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(request.targetPower); }), 2, 100);
305
+ yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(request.targetPower); }), 2, 100);
306
306
  }
307
307
  else if (request.maxPower !== undefined) {
308
308
  if (this.data.power && this.data.power > request.maxPower)
309
- yield utils_2.runWithRetries(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(request.maxPower); }), 2, 100);
309
+ yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(request.maxPower); }), 2, 100);
310
310
  }
311
311
  else if (request.minPower !== undefined) {
312
312
  if (this.data.power && this.data.power < request.minPower)
313
- yield utils_2.runWithRetries(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(request.minPower); }), 2, 100);
313
+ yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(request.minPower); }), 2, 100);
314
314
  }
315
315
  }
316
316
  catch (err) {
@@ -395,7 +395,7 @@ class AntFEAdapter extends AntAdapter_1.default {
395
395
  this.currentCmd = this.queue.dequeue();
396
396
  this.currentCmd.tsStart = Date.now();
397
397
  const { msg, logStr } = this.currentCmd;
398
- this.logger.logEvent({ message: "sending", cmd: logStr, msg: utils_2.hexstr(msg), queueSize: this.queue.size() });
398
+ this.logger.logEvent({ message: "sending", cmd: logStr, msg: (0, utils_2.hexstr)(msg), queueSize: this.queue.size() });
399
399
  if (this.stick)
400
400
  this.stick.write(msg);
401
401
  }
@@ -43,7 +43,7 @@ class AntHrmAdapter extends AntAdapter_1.default {
43
43
  getDisplayName() {
44
44
  const { DeviceID, manID, ComputedHeartRate } = this.deviceData;
45
45
  const hrmStr = ComputedHeartRate ? ` (${ComputedHeartRate})` : '';
46
- return `${utils_1.getBrand(manID)} Hrm ${DeviceID}${hrmStr}`;
46
+ return `${(0, utils_1.getBrand)(manID)} Hrm ${DeviceID}${hrmStr}`;
47
47
  }
48
48
  onDeviceData(deviceData) {
49
49
  if (!this.started)
@@ -48,7 +48,7 @@ class AntFEAdapter extends AntAdapter_1.default {
48
48
  }
49
49
  getDisplayName() {
50
50
  const { DeviceID, ManId } = this.deviceData;
51
- return `${utils_1.getBrand(ManId)} PWR ${DeviceID}`;
51
+ return `${(0, utils_1.getBrand)(ManId)} PWR ${DeviceID}`;
52
52
  }
53
53
  getCyclingMode() {
54
54
  if (!this.mode)
package/lib/ant/utils.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getBrand = (manId) => {
3
+ exports.getBrand = void 0;
4
+ const getBrand = (manId) => {
4
5
  if (manId === undefined)
5
6
  return "ANT+";
6
7
  switch (manId) {
@@ -19,3 +20,4 @@ exports.getBrand = (manId) => {
19
20
  return "ANT+";
20
21
  }
21
22
  };
23
+ exports.getBrand = getBrand;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { EventLogger } from "gd-eventlog";
3
- import { BleInterfaceClass, BleDeviceClass, BlePeripheral, BleDeviceProps, ConnectProps } from "./ble";
3
+ import { BleInterfaceClass, BleDeviceClass, BlePeripheral, BleDeviceProps, ConnectProps, BleDeviceInfo } from "./ble";
4
4
  interface BleDeviceConstructProps extends BleDeviceProps {
5
5
  log?: boolean;
6
6
  logger?: EventLogger;
@@ -15,17 +15,24 @@ export declare abstract class BleDevice extends BleDeviceClass {
15
15
  characteristics: any[];
16
16
  state?: string;
17
17
  logger?: EventLogger;
18
+ deviceInfo: BleDeviceInfo;
19
+ isSubscribed: boolean;
18
20
  constructor(props?: BleDeviceConstructProps);
19
21
  logEvent(event: any): void;
20
22
  setInterface(ble: BleInterfaceClass): void;
21
23
  private cleanupListeners;
22
24
  private onDisconnect;
23
25
  waitForConnectFinished(timeout: any): Promise<unknown>;
26
+ hasService(serviceUuid: any): boolean;
27
+ init(): Promise<boolean>;
24
28
  connect(props?: ConnectProps): Promise<boolean>;
25
29
  disconnect(): Promise<boolean>;
26
30
  abstract getProfile(): string;
27
31
  abstract onData(characteristic: string, data: Buffer): void;
28
- abstract write(characteristic: string, data: Buffer): Promise<boolean>;
29
- abstract read(characteristic: string): Promise<Buffer>;
32
+ subscribeAll(device?: this): Promise<void>;
33
+ subscribe(characteristicUuid: string): Promise<boolean>;
34
+ write(characteristicUuid: string, data: Buffer, withoutResponse: boolean): Promise<boolean>;
35
+ read(characteristicUuid: string): Promise<Buffer>;
36
+ getDeviceInfo(): Promise<BleDeviceInfo>;
30
37
  }
31
38
  export {};
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.BleDevice = void 0;
12
13
  const gd_eventlog_1 = require("gd-eventlog");
13
14
  const ble_1 = require("./ble");
14
15
  const CONNECT_WAIT_TIMEOUT = 10000;
@@ -16,12 +17,14 @@ class BleDevice extends ble_1.BleDeviceClass {
16
17
  constructor(props) {
17
18
  super();
18
19
  this.characteristics = [];
20
+ this.deviceInfo = {};
19
21
  this.id = props.id;
20
22
  this.address = props.address;
21
23
  this.name = props.name;
22
24
  this.services = props.services;
23
25
  this.ble = props.ble;
24
26
  this.characteristics = [];
27
+ this.isSubscribed = false;
25
28
  if (props.peripheral) {
26
29
  const { id, address, advertisement, state } = props.peripheral;
27
30
  this.peripheral = props.peripheral;
@@ -58,11 +61,14 @@ class BleDevice extends ble_1.BleDeviceClass {
58
61
  c.unsubscribe();
59
62
  c.removeAllListeners('data');
60
63
  });
64
+ this.isSubscribed = false;
61
65
  }
62
66
  }
63
67
  onDisconnect() {
64
68
  this.state = "disconnected";
65
69
  if (!this.connectState.isDisconnecting) {
70
+ this.peripheral.state = 'disconnected';
71
+ this.connectState.isConnected = false;
66
72
  this.connect();
67
73
  }
68
74
  this.emit('disconnected');
@@ -88,12 +94,19 @@ class BleDevice extends ble_1.BleDeviceClass {
88
94
  }, 100);
89
95
  });
90
96
  }
97
+ hasService(serviceUuid) {
98
+ return this.services && this.services.find(s => s === serviceUuid || (0, ble_1.uuid)(serviceUuid)) !== undefined;
99
+ }
100
+ init() {
101
+ return this.getDeviceInfo().then(() => true);
102
+ }
91
103
  connect(props) {
92
104
  return __awaiter(this, void 0, void 0, function* () {
93
105
  const connectPeripheral = (peripheral) => __awaiter(this, void 0, void 0, function* () {
94
106
  this.connectState.isConnecting = true;
95
107
  const connected = this.ble.findConnected(peripheral);
96
- if (!connected) {
108
+ if (peripheral.state !== 'connected') {
109
+ this.isSubscribed = false;
97
110
  try {
98
111
  yield peripheral.connectAsync();
99
112
  }
@@ -102,38 +115,41 @@ class BleDevice extends ble_1.BleDeviceClass {
102
115
  }
103
116
  }
104
117
  try {
105
- this.cleanupListeners();
118
+ if (!this.characteristics)
119
+ this.characteristics = [];
106
120
  if (!connected) {
107
- this.logEvent({ message: 'connect: discover characteristics start' });
108
- const res = yield peripheral.discoverSomeServicesAndCharacteristicsAsync([], []);
109
- const { characteristics } = res;
110
- this.logEvent({ message: 'connect: discover characteristics result',
111
- result: characteristics.map(c => ({ uuid: ble_1.uuid(c.uuid), properties: c.properties.join(','), service: ble_1.uuid(c._serviceUuid) }))
112
- });
113
- this.characteristics = characteristics;
121
+ if (!this.characteristics || this.characteristics.length === 0) {
122
+ this.logEvent({ message: 'connect: discover characteristics start' });
123
+ const res = yield peripheral.discoverSomeServicesAndCharacteristicsAsync([], []);
124
+ const { characteristics } = res;
125
+ this.logEvent({ message: 'connect: discover characteristics result',
126
+ result: characteristics.map(c => ({ uuid: (0, ble_1.uuid)(c.uuid), properties: c.properties.join(','), service: (0, ble_1.uuid)(c._serviceUuid) }))
127
+ });
128
+ this.characteristics = characteristics;
129
+ }
130
+ else {
131
+ }
114
132
  }
115
133
  else {
116
134
  this.characteristics = connected.characteristics;
117
135
  }
136
+ let device;
137
+ if (!connected) {
138
+ this.ble.addConnectedDevice(this);
139
+ device = this;
140
+ }
141
+ else {
142
+ device = connected;
143
+ }
144
+ this.peripheral.once('disconnect', () => { this.onDisconnect(); });
145
+ yield this.subscribeAll(device);
118
146
  this.connectState.isConnecting = false;
119
147
  this.connectState.isConnected = true;
120
148
  this.state = "connected";
121
149
  this.emit('connected');
122
- this.ble.addConnectedDevice(this);
123
- this.peripheral.once('disconnect', () => { this.onDisconnect(); });
124
- this.characteristics.forEach(c => {
125
- if (c.properties.find(p => p === 'notify')) {
126
- c.on('data', (data, _isNotification) => {
127
- this.onData(ble_1.uuid(c.uuid), data);
128
- });
129
- if (!connected) {
130
- this.logEvent({ message: 'subscribe', device: this.name, address: this.address, service: c._serviceUuid, characteristic: c.uuid });
131
- c.subscribe((err) => {
132
- if (err)
133
- this.logEvent({ message: 'cannot subscribe', device: this.name, address: this.address, service: c._serviceUuid, characteristic: c.uuid, error: err.message || err });
134
- });
135
- }
136
- }
150
+ this.init().then((isInitialized) => {
151
+ if (isInitialized)
152
+ this.emit('deviceInfo', this.deviceInfo);
137
153
  });
138
154
  }
139
155
  catch (err) {
@@ -147,13 +163,9 @@ class BleDevice extends ble_1.BleDeviceClass {
147
163
  yield this.waitForConnectFinished(CONNECT_WAIT_TIMEOUT);
148
164
  }
149
165
  if (this.connectState.isConnected) {
150
- this.characteristics.forEach(c => {
151
- if (c.properties.find(p => p === 'notify')) {
152
- c.on('data', (data, _isNotification) => {
153
- this.onData(ble_1.uuid(c.uuid), data);
154
- });
155
- }
156
- });
166
+ if (!this.isSubscribed) {
167
+ yield this.subscribeAll();
168
+ }
157
169
  return true;
158
170
  }
159
171
  this.connectState.isConnecting = true;
@@ -174,7 +186,7 @@ class BleDevice extends ble_1.BleDeviceClass {
174
186
  if (this.ble.isScanning()) {
175
187
  yield this.ble.stopScan();
176
188
  }
177
- const devices = yield this.ble.scan({ device: this });
189
+ const devices = yield this.ble.scan({ requested: this });
178
190
  if (devices && devices.length > 0) {
179
191
  this.peripheral = devices[0].peripheral;
180
192
  yield connectPeripheral(this.peripheral);
@@ -226,5 +238,105 @@ class BleDevice extends ble_1.BleDeviceClass {
226
238
  }
227
239
  });
228
240
  }
241
+ subscribeAll(device = this) {
242
+ return __awaiter(this, void 0, void 0, function* () {
243
+ if (this.isSubscribed)
244
+ return;
245
+ const cnt = this.characteristics.length;
246
+ for (let i = 0; i < cnt; i++) {
247
+ try {
248
+ const c = this.characteristics[i];
249
+ const isNotify = c.properties.find(p => p === 'notify');
250
+ if (isNotify) {
251
+ c.on('data', (data, _isNotification) => {
252
+ this.onData((0, ble_1.uuid)(c.uuid), data);
253
+ });
254
+ if (!device.isSubscribed) {
255
+ this.logEvent({ message: 'subscribe', device: this.name, address: this.address, service: c._serviceUuid, characteristic: c.uuid });
256
+ try {
257
+ yield this.subscribe(c.uuid);
258
+ }
259
+ catch (err) {
260
+ this.logEvent({ message: 'cannot subscribe', device: this.name, address: this.address, service: c._serviceUuid, characteristic: c.uuid, error: err.message || err });
261
+ }
262
+ }
263
+ }
264
+ }
265
+ catch (err) {
266
+ console.log('~~~ error', err);
267
+ }
268
+ }
269
+ this.isSubscribed = true;
270
+ });
271
+ }
272
+ subscribe(characteristicUuid) {
273
+ return new Promise((resolve, reject) => {
274
+ const characteristic = this.characteristics.find(c => c.uuid === characteristicUuid || (0, ble_1.uuid)(c.uuid) === characteristicUuid);
275
+ if (!characteristic) {
276
+ reject(new Error('Characteristic not found'));
277
+ return;
278
+ }
279
+ characteristic.subscribe((err) => {
280
+ if (err)
281
+ reject(err);
282
+ else
283
+ resolve(true);
284
+ });
285
+ });
286
+ }
287
+ write(characteristicUuid, data, withoutResponse) {
288
+ return new Promise((resolve, reject) => {
289
+ const characteristic = this.characteristics.find(c => c.uuid === characteristicUuid || (0, ble_1.uuid)(c.uuid) === characteristicUuid);
290
+ if (!characteristic) {
291
+ reject(new Error('Characteristic not found'));
292
+ return;
293
+ }
294
+ characteristic.write(data, withoutResponse, (err) => {
295
+ if (err)
296
+ reject(err);
297
+ else
298
+ resolve(true);
299
+ });
300
+ });
301
+ }
302
+ read(characteristicUuid) {
303
+ return new Promise((resolve, reject) => {
304
+ const characteristic = this.characteristics.find(c => c.uuid === characteristicUuid || (0, ble_1.uuid)(c.uuid) === characteristicUuid);
305
+ if (!characteristic) {
306
+ reject(new Error('Characteristic not found'));
307
+ return;
308
+ }
309
+ characteristic.read((err, data) => {
310
+ if (err && data instanceof Error)
311
+ reject(err);
312
+ else if (data instanceof Error)
313
+ reject(data);
314
+ else
315
+ resolve(data);
316
+ });
317
+ });
318
+ }
319
+ getDeviceInfo() {
320
+ return __awaiter(this, void 0, void 0, function* () {
321
+ const info = this.deviceInfo;
322
+ const readValue = (c) => __awaiter(this, void 0, void 0, function* () {
323
+ try {
324
+ const b = yield this.read(c);
325
+ return b ? b.toString() : undefined;
326
+ }
327
+ catch (_a) {
328
+ return undefined;
329
+ }
330
+ });
331
+ info.model = info.model || (yield readValue('2a24'));
332
+ info.serialNo = info.serialNo || (yield readValue('2a25'));
333
+ info.fwRevision = info.fwRevision || (yield readValue('2a26'));
334
+ info.hwRevision = info.hwRevision || (yield readValue('2a27'));
335
+ info.swRevision = info.swRevision || (yield readValue('2a28'));
336
+ info.manufacturer = info.manufacturer || (yield readValue('2a29'));
337
+ this.deviceInfo = info;
338
+ return info;
339
+ });
340
+ }
229
341
  }
230
342
  exports.BleDevice = BleDevice;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { EventLogger } from 'gd-eventlog';
3
- import { BleInterfaceClass, ConnectProps, ScanProps, BleDeviceClass, BlePeripheral, BleBinding } from './ble';
3
+ import { BleInterfaceClass, ConnectProps, ScanProps, BleDeviceClass, BlePeripheral, BleBinding, BleCharacteristic, BleDeviceDescription } from './ble';
4
4
  export interface ScanState {
5
5
  isScanning: boolean;
6
6
  isConnecting: boolean;
@@ -13,6 +13,11 @@ export interface ConnectState {
13
13
  timeout?: NodeJS.Timeout;
14
14
  isInitSuccess: boolean;
15
15
  }
16
+ export interface PeripheralState {
17
+ isLoading: boolean;
18
+ isConfigured: boolean;
19
+ isInterrupted: boolean;
20
+ }
16
21
  export interface BleDeviceInfo {
17
22
  device: BleDeviceClass;
18
23
  isConnected: boolean;
@@ -23,12 +28,19 @@ export interface BleDeviceClassInfo {
23
28
  services: string[];
24
29
  id: string;
25
30
  }
31
+ export interface PeripheralCacheItem {
32
+ address: string;
33
+ ts: number;
34
+ peripheral: BlePeripheral;
35
+ state?: PeripheralState;
36
+ characteristics?: BleCharacteristic[];
37
+ }
26
38
  export default class BleInterface extends BleInterfaceClass {
27
39
  scanState: ScanState;
28
40
  connectState: ConnectState;
29
41
  devices: BleDeviceInfo[];
42
+ peripheralCache: any[];
30
43
  logger: EventLogger;
31
- deviceCache: any[];
32
44
  static deviceClasses: BleDeviceClassInfo[];
33
45
  static _instance: BleInterface;
34
46
  static getInstance(props?: {
@@ -52,9 +64,15 @@ export default class BleInterface extends BleInterfaceClass {
52
64
  getServicesFromDeviceTypes(deviceTypes: (typeof BleDeviceClass)[]): string[];
53
65
  getServicesFromDevice(device: BleDeviceClass): string[];
54
66
  waitForConnectFinished(timeout: any): Promise<unknown>;
55
- connectDevice(requested: BleDeviceClass, timeout?: number): Promise<BleDeviceClass>;
67
+ addPeripheralToCache(peripheral: any, props?: {}): void;
68
+ getCharacteristics(peripheral: any): Promise<any>;
69
+ getDeviceClasses(peripheral: any, props?: {
70
+ deviceTypes?: (typeof BleDeviceClass)[];
71
+ profile?: string;
72
+ }): (typeof BleDeviceClass)[];
73
+ createDevice(DeviceClass: (typeof BleDeviceClass), peripheral: BlePeripheral, characteristics?: BleCharacteristic[]): any;
74
+ connectDevice(requested: BleDeviceClass | BleDeviceDescription, timeout?: number): Promise<BleDeviceClass>;
56
75
  waitForScanFinished(timeout: any): Promise<unknown>;
57
- addPeripheralToCache(peripheral: BlePeripheral): void;
58
76
  scan(props: ScanProps): Promise<BleDeviceClass[]>;
59
77
  stopScan(): Promise<boolean>;
60
78
  isScanning(): boolean;