incyclist-devices 2.0.38 → 2.1.1

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 (192) hide show
  1. package/lib/adapters.d.ts +1 -1
  2. package/lib/antv2/adapter-factory.d.ts +4 -13
  3. package/lib/antv2/adapter.d.ts +16 -33
  4. package/lib/antv2/adapter.js +68 -112
  5. package/lib/antv2/ant-interface.d.ts +3 -11
  6. package/lib/antv2/ant-interface.js +1 -1
  7. package/lib/antv2/base/adapter.d.ts +62 -0
  8. package/lib/antv2/base/adapter.js +360 -0
  9. package/lib/antv2/base/ant-interface.d.ts +35 -0
  10. package/lib/antv2/base/ant-interface.js +285 -0
  11. package/lib/antv2/base/binding.d.ts +13 -0
  12. package/lib/antv2/base/binding.js +27 -0
  13. package/lib/antv2/cad/adapter.d.ts +10 -0
  14. package/lib/antv2/cad/adapter.js +25 -0
  15. package/lib/antv2/cad/index.d.ts +2 -0
  16. package/lib/antv2/cad/index.js +7 -0
  17. package/lib/antv2/consts.d.ts +2 -0
  18. package/lib/antv2/consts.js +5 -0
  19. package/lib/antv2/factories/adapter-factory.d.ts +14 -0
  20. package/lib/antv2/factories/adapter-factory.js +65 -0
  21. package/lib/antv2/factories/sensor-factory.d.ts +5 -0
  22. package/lib/antv2/factories/sensor-factory.js +22 -0
  23. package/lib/antv2/fe/adapter.d.ts +25 -26
  24. package/lib/antv2/fe/adapter.js +212 -218
  25. package/lib/antv2/hr/adapter.d.ts +6 -14
  26. package/lib/antv2/hr/adapter.js +7 -55
  27. package/lib/antv2/hr copy/adapter.d.ts +11 -0
  28. package/lib/antv2/hr copy/adapter.js +30 -0
  29. package/lib/antv2/hr copy/index.d.ts +2 -0
  30. package/lib/antv2/hr copy/index.js +7 -0
  31. package/lib/antv2/index.d.ts +5 -4
  32. package/lib/antv2/index.js +4 -2
  33. package/lib/antv2/pwr/adapter.d.ts +9 -29
  34. package/lib/antv2/pwr/adapter.js +20 -130
  35. package/lib/antv2/types.d.ts +23 -3
  36. package/lib/base/adpater.d.ts +42 -45
  37. package/lib/base/adpater.js +144 -110
  38. package/lib/base/consts.d.ts +4 -0
  39. package/lib/base/consts.js +9 -0
  40. package/lib/ble/adapter-factory.d.ts +4 -4
  41. package/lib/ble/base/adapter.d.ts +6 -24
  42. package/lib/ble/base/adapter.js +4 -94
  43. package/lib/ble/ble-interface.d.ts +2 -3
  44. package/lib/ble/cp/adapter.d.ts +6 -11
  45. package/lib/ble/cp/adapter.js +9 -12
  46. package/lib/ble/elite/adapter.d.ts +8 -8
  47. package/lib/ble/elite/adapter.js +6 -2
  48. package/lib/ble/fm/adapter.d.ts +11 -11
  49. package/lib/ble/fm/adapter.js +26 -20
  50. package/lib/ble/hr/adapter.d.ts +3 -4
  51. package/lib/ble/hr/adapter.js +2 -2
  52. package/lib/ble/tacx/adapter.d.ts +2 -3
  53. package/lib/ble/tacx/adapter.js +8 -8
  54. package/lib/ble/types.d.ts +1 -2
  55. package/lib/ble/wahoo/adapter.d.ts +2 -2
  56. package/lib/ble/wahoo/adapter.js +6 -6
  57. package/lib/ble/wahoo/comms.js +16 -16
  58. package/lib/factories/adapters.d.ts +7 -0
  59. package/lib/factories/adapters.js +49 -0
  60. package/lib/factories/index.d.ts +3 -0
  61. package/lib/factories/index.js +10 -0
  62. package/lib/factories/interfaces.d.ts +7 -0
  63. package/lib/factories/interfaces.js +27 -0
  64. package/lib/index.d.ts +8 -9
  65. package/lib/index.js +5 -8
  66. package/lib/interfaces.d.ts +1 -1
  67. package/lib/modes/ant-fe-adv-st-mode.d.ts +12 -0
  68. package/lib/modes/ant-fe-adv-st-mode.js +83 -0
  69. package/lib/modes/antble-erg.d.ts +31 -0
  70. package/lib/modes/antble-erg.js +28 -0
  71. package/lib/modes/antble-smarttrainer.d.ts +23 -0
  72. package/lib/modes/antble-smarttrainer.js +65 -0
  73. package/lib/modes/base.d.ts +29 -0
  74. package/lib/modes/{cycling-mode.js → base.js} +23 -26
  75. package/lib/modes/daum-classic-standard.d.ts +17 -0
  76. package/lib/modes/daum-classic-standard.js +54 -0
  77. package/lib/modes/daum-erg.d.ts +49 -0
  78. package/lib/{serial/daum/ERGCyclingMode.js → modes/daum-erg.js} +45 -73
  79. package/lib/modes/daum-power.d.ts +5 -0
  80. package/lib/{serial/daum/DaumPowerMeterCyclingMode.js → modes/daum-power.js} +1 -10
  81. package/lib/modes/daum-premium-standard.d.ts +24 -0
  82. package/lib/{serial/daum/premium/modes/daum-classic.js → modes/daum-premium-standard.js} +26 -38
  83. package/lib/modes/daum-smarttrainer.d.ts +83 -0
  84. package/lib/{serial/daum/SmartTrainerCyclingMode.js → modes/daum-smarttrainer.js} +23 -26
  85. package/lib/modes/kettler-erg.d.ts +44 -0
  86. package/lib/{serial/kettler/ergo-racer/modes/erg.js → modes/kettler-erg.js} +12 -23
  87. package/lib/modes/power-base.d.ts +28 -3
  88. package/lib/modes/power-base.js +184 -7
  89. package/lib/modes/power-meter.d.ts +11 -16
  90. package/lib/modes/power-meter.js +15 -54
  91. package/lib/modes/simulator.d.ts +38 -10
  92. package/lib/modes/simulator.js +14 -46
  93. package/lib/modes/{cycling-mode.d.ts → types.d.ts} +22 -30
  94. package/lib/modes/types.js +56 -0
  95. package/lib/serial/SinglePathScanner.d.ts +17 -0
  96. package/lib/serial/SinglePathScanner.js +87 -0
  97. package/lib/serial/adapter-factory.d.ts +8 -6
  98. package/lib/serial/adapter.d.ts +6 -11
  99. package/lib/serial/adapter.js +5 -2
  100. package/lib/serial/base/adapter.d.ts +17 -0
  101. package/lib/serial/base/adapter.js +67 -0
  102. package/lib/serial/base/comms.d.ts +62 -0
  103. package/lib/serial/base/comms.js +280 -0
  104. package/lib/serial/base/serial-interface.d.ts +36 -0
  105. package/lib/serial/base/serial-interface.js +288 -0
  106. package/lib/serial/base/serial-scanner.d.ts +16 -0
  107. package/lib/serial/base/serial-scanner.js +87 -0
  108. package/lib/serial/base/serialport.d.ts +17 -0
  109. package/lib/serial/base/serialport.js +87 -0
  110. package/lib/serial/comms.d.ts +2 -2
  111. package/lib/serial/daum/DaumAdapter.d.ts +26 -35
  112. package/lib/serial/daum/DaumAdapter.js +214 -161
  113. package/lib/serial/daum/classic/PROTOCOL_NAME.d.ts +2 -0
  114. package/lib/serial/daum/classic/PROTOCOL_NAME.js +5 -0
  115. package/lib/serial/daum/classic/adapter.d.ts +13 -26
  116. package/lib/serial/daum/classic/adapter.js +72 -176
  117. package/lib/serial/daum/classic/comms.d.ts +21 -17
  118. package/lib/serial/daum/classic/comms.js +41 -14
  119. package/lib/serial/daum/classic/consts.d.ts +2 -0
  120. package/lib/serial/daum/classic/consts.js +5 -0
  121. package/lib/serial/daum/classic/mock.d.ts +4 -0
  122. package/lib/serial/daum/classic/mock.js +18 -7
  123. package/lib/serial/daum/classic/types.d.ts +8 -10
  124. package/lib/serial/daum/classic/utils.d.ts +1 -2
  125. package/lib/serial/daum/consts.d.ts +0 -0
  126. package/lib/serial/daum/consts.js +0 -0
  127. package/lib/serial/daum/premium/adapter.d.ts +17 -15
  128. package/lib/serial/daum/premium/adapter.js +86 -109
  129. package/lib/serial/daum/premium/comms.d.ts +7 -7
  130. package/lib/serial/daum/premium/comms.js +25 -16
  131. package/lib/serial/daum/premium/mock.d.ts +5 -1
  132. package/lib/serial/daum/premium/mock.js +17 -7
  133. package/lib/serial/daum/premium/types.d.ts +32 -17
  134. package/lib/serial/daum/premium/types.js +8 -8
  135. package/lib/serial/daum/premium/utils.d.ts +2 -3
  136. package/lib/serial/daum/premium/utils.js +3 -3
  137. package/lib/serial/daum/types.d.ts +14 -0
  138. package/lib/serial/daum/types.js +13 -0
  139. package/lib/serial/factories/adapter-factory.d.ts +14 -0
  140. package/lib/serial/factories/adapter-factory.js +30 -0
  141. package/lib/serial/index.d.ts +8 -5
  142. package/lib/serial/index.js +15 -15
  143. package/lib/serial/kettler/comms.d.ts +1 -1
  144. package/lib/serial/kettler/ergo-racer/adapter.d.ts +11 -16
  145. package/lib/serial/kettler/ergo-racer/adapter.js +10 -12
  146. package/lib/serial/kettler/types.d.ts +8 -0
  147. package/lib/serial/kettler/types.js +2 -0
  148. package/lib/serial/serial-interface.d.ts +2 -32
  149. package/lib/serial/serial-interface.js +4 -78
  150. package/lib/serial/serial-scanner.d.ts +16 -0
  151. package/lib/serial/serial-scanner.js +87 -0
  152. package/lib/serial/serialport.d.ts +1 -13
  153. package/lib/serial/types.d.ts +45 -0
  154. package/lib/serial/types.js +9 -0
  155. package/lib/simulator/Simulator.d.ts +13 -19
  156. package/lib/simulator/Simulator.js +10 -51
  157. package/lib/types/Command.d.ts +8 -0
  158. package/lib/types/Command.js +2 -0
  159. package/lib/types/adapter.d.ts +34 -24
  160. package/lib/types/command.d.ts +0 -8
  161. package/lib/types/command.js +0 -2
  162. package/lib/types/data.d.ts +12 -1
  163. package/lib/types/device.d.ts +8 -23
  164. package/lib/types/device.js +9 -8
  165. package/lib/types/index.d.ts +6 -0
  166. package/lib/types/index.js +22 -0
  167. package/lib/types/route.d.ts +0 -19
  168. package/lib/types/route.js +0 -2
  169. package/lib/types/types.d.ts +8 -0
  170. package/lib/types/types.js +2 -0
  171. package/lib/utils/utils.d.ts +2 -1
  172. package/lib/utils/utils.js +22 -4
  173. package/package.json +3 -3
  174. package/lib/antv2/modes/ant-fe-adv-st-mode.d.ts +0 -9
  175. package/lib/antv2/modes/ant-fe-adv-st-mode.js +0 -51
  176. package/lib/antv2/modes/ant-fe-erg-mode.d.ts +0 -6
  177. package/lib/antv2/modes/ant-fe-erg-mode.js +0 -14
  178. package/lib/antv2/modes/ant-fe-st-mode.d.ts +0 -5
  179. package/lib/antv2/modes/ant-fe-st-mode.js +0 -13
  180. package/lib/modes/ble-erg-mode.d.ts +0 -18
  181. package/lib/modes/ble-erg-mode.js +0 -148
  182. package/lib/modes/ble-st-mode.d.ts +0 -15
  183. package/lib/modes/ble-st-mode.js +0 -96
  184. package/lib/serial/daum/DaumPowerMeterCyclingMode.d.ts +0 -8
  185. package/lib/serial/daum/ERGCyclingMode.d.ts +0 -26
  186. package/lib/serial/daum/SmartTrainerCyclingMode.d.ts +0 -42
  187. package/lib/serial/daum/classic/modes/daum-classic.d.ts +0 -13
  188. package/lib/serial/daum/classic/modes/daum-classic.js +0 -97
  189. package/lib/serial/daum/constants.d.ts +0 -19
  190. package/lib/serial/daum/constants.js +0 -22
  191. package/lib/serial/daum/premium/modes/daum-classic.d.ts +0 -14
  192. package/lib/serial/kettler/ergo-racer/modes/erg.d.ts +0 -25
@@ -12,31 +12,18 @@ 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 adapter_1 = require("../adapter");
16
- const utils_1 = require("../utils");
17
- const gd_eventlog_1 = require("gd-eventlog");
18
- const ant_fe_st_mode_1 = __importDefault(require("../modes/ant-fe-st-mode"));
19
- const ant_fe_erg_mode_1 = __importDefault(require("../modes/ant-fe-erg-mode"));
20
- const ant_fe_adv_st_mode_1 = __importDefault(require("../modes/ant-fe-adv-st-mode"));
21
- const utils_2 = require("../../utils/utils");
22
- const sensor_factory_1 = __importDefault(require("../sensor-factory"));
15
+ const adapter_1 = __importDefault(require("../base/adapter"));
16
+ const ant_fe_adv_st_mode_1 = __importDefault(require("../../modes/ant-fe-adv-st-mode"));
17
+ const utils_1 = require("../../utils/utils");
23
18
  const capabilities_1 = require("../../types/capabilities");
24
- const adpater_1 = require("../../base/adpater");
19
+ const consts_1 = require("../../base/consts");
20
+ const antble_erg_1 = __importDefault(require("../../modes/antble-erg"));
21
+ const antble_smarttrainer_1 = __importDefault(require("../../modes/antble-smarttrainer"));
25
22
  const DEFAULT_BIKE_WEIGHT_MOUNTAIN = 14.5;
26
23
  const MAX_RETRIES = 3;
27
- class AntFEAdapter extends adapter_1.ControllableAntAdapter {
24
+ class AntFEAdapter extends adapter_1.default {
28
25
  constructor(settings, props) {
29
- if (settings.protocol && settings.profile !== AntFEAdapter.INCYCLIST_PROFILE_NAME)
30
- throw new Error('Incorrect Profile');
31
- if (!settings.protocol && settings.profile !== AntFEAdapter.ANT_PROFILE_NAME)
32
- throw new Error('Incorrect Profile');
33
26
  super(settings, props);
34
- this.deviceData = {
35
- DeviceID: this.sensor.getDeviceID()
36
- };
37
- this.dataMsgCount = 0;
38
- this.logger = new gd_eventlog_1.EventLogger('Ant+FE');
39
- this.isReconnecting = false;
40
27
  this.startProps = {};
41
28
  this.sensorConnected = false;
42
29
  this.capabilities = [
@@ -44,52 +31,23 @@ class AntFEAdapter extends adapter_1.ControllableAntAdapter {
44
31
  capabilities_1.IncyclistCapability.Control
45
32
  ];
46
33
  }
47
- createSensor(settings) {
48
- const sensor = sensor_factory_1.default.create(AntFEAdapter.ANT_PROFILE_NAME, Number(settings.deviceID));
49
- return sensor;
50
- }
51
- getName() {
52
- if (this.settings.name)
53
- return this.settings.name;
54
- const deviceID = this.sensor.getDeviceID();
55
- return `Ant+FE ${deviceID}`;
56
- }
57
- getUniqueName() {
58
- if (this.settings.name)
59
- return this.settings.name;
60
- const { DeviceID, ManId } = this.deviceData;
61
- const brand = (0, utils_1.getBrand)(ManId);
62
- if (brand)
63
- return `${brand} FE ${DeviceID}`;
64
- else
65
- return `${this.getName()}`;
66
- }
67
34
  getDisplayName() {
68
35
  const { InstantaneousPower } = this.deviceData;
69
36
  const pwrStr = InstantaneousPower ? ` (${InstantaneousPower})` : '';
70
37
  return `${this.getUniqueName()}${pwrStr}`;
71
38
  }
72
- getSupportedCyclingModes() {
73
- return [ant_fe_st_mode_1.default, ant_fe_erg_mode_1.default, ant_fe_adv_st_mode_1.default];
74
- }
75
- getDefaultCyclingMode() {
76
- return new ant_fe_st_mode_1.default(this);
39
+ getDefaultReconnectDelay() {
40
+ return 2000;
77
41
  }
78
- getLogData(data, excludeList) {
79
- const logData = JSON.parse(JSON.stringify(data));
80
- excludeList.forEach((key) => {
81
- delete logData[key];
82
- });
83
- return logData;
42
+ isReconnecting() {
43
+ return this.promiseReconnect !== null && this.promiseReconnect !== undefined;
84
44
  }
85
45
  sendUpdate(request, forced = false) {
86
46
  return __awaiter(this, void 0, void 0, function* () {
87
- if ((this.paused || this.isReconnecting) && !forced)
47
+ if ((this.paused || this.isReconnecting()) && !forced)
88
48
  return;
89
49
  let isReset = request.reset && Object.keys(request).length === 1;
90
50
  const update = isReset ? this.getCyclingMode().getBikeInitRequest() : this.getCyclingMode().sendBikeUpdate(request);
91
- if (!update)
92
- return;
93
51
  this.logEvent({ message: 'send bike update requested', update, request });
94
52
  try {
95
53
  const fe = this.sensor;
@@ -112,199 +70,226 @@ class AntFEAdapter extends adapter_1.ControllableAntAdapter {
112
70
  });
113
71
  }
114
72
  onDeviceData(deviceData) {
115
- this.dataMsgCount++;
116
- this.lastDataTS = Date.now();
117
73
  super.onDeviceData(deviceData);
118
- if (!this.started || this.isStopped())
119
- return;
120
- if (!this.ivDataTimeout && this.dataMsgCount > 0) {
121
- this.startDataTimeoutCheck();
122
- }
123
- try {
124
- const logData = this.getLogData(deviceData, ['PairedDevices', 'RawData']);
125
- this.logEvent({ message: 'onDeviceData', data: logData, paused: this.paused });
126
- if (!this.canSendUpdate())
127
- return;
128
- let incyclistData = this.mapToCycleModeData(deviceData);
129
- incyclistData = this.getCyclingMode().updateData(incyclistData);
130
- this.data = this.transformData(incyclistData);
131
- this.emitData(this.data);
74
+ if (deviceData.HeartRate && !this.hasCapability(capabilities_1.IncyclistCapability.HeartRate)) {
75
+ this.capabilities.push(capabilities_1.IncyclistCapability.HeartRate);
76
+ this.emit('device-info', this.getSettings(), { capabilities: this.capabilities });
132
77
  }
133
- catch (err) {
134
- this.logEvent({ message: 'error', fn: 'onDeviceData()', error: err.message || err, stack: err.stack });
135
- }
136
- }
137
- canSendUpdate() {
138
- if (!this.hasDataListeners() || this.paused)
139
- return false;
140
- return super.canSendUpdate();
141
78
  }
142
- mapToCycleModeData(deviceData) {
79
+ mapData(deviceData) {
143
80
  const data = {
144
81
  isPedalling: false,
145
82
  power: 0,
146
- pedalRpm: undefined,
83
+ pedalRpm: 0,
147
84
  speed: 0,
148
- heartrate: 0,
149
- distanceInternal: 0,
150
- slope: undefined,
151
- time: undefined
152
85
  };
153
86
  data.speed = (deviceData.VirtualSpeed !== undefined ? deviceData.VirtualSpeed : (deviceData.RealSpeed || 0)) * 3.6;
154
87
  data.slope = (deviceData.Incline !== undefined ? deviceData.Incline : data.slope);
155
88
  data.power = (deviceData.InstantaneousPower !== undefined ? deviceData.InstantaneousPower : data.power);
156
- data.time = (deviceData.ElapsedTime !== undefined ? deviceData.ElapsedTime : data.time);
157
89
  data.pedalRpm = (deviceData.Cadence !== undefined ? deviceData.Cadence : data.pedalRpm);
158
- data.isPedalling = data.pedalRpm > 0 || (data.pedalRpm === undefined && data.power > 0);
90
+ data.isPedalling = data.pedalRpm > 0 || data.power > 0;
91
+ if (deviceData.HeartRate !== undefined)
92
+ data.heartrate = deviceData.HeartRate;
93
+ if (deviceData.Distance !== undefined)
94
+ data.distanceInternal = deviceData.Distance;
95
+ if (deviceData.ElapsedTime !== undefined)
96
+ data.time = deviceData.ElapsedTime;
159
97
  return data;
160
98
  }
161
- transformData(bikeData) {
162
- if (bikeData === undefined)
163
- return;
164
- let distance = 0;
165
- if (this.distanceInternal !== undefined && bikeData.distanceInternal !== undefined) {
166
- distance = bikeData.distanceInternal - this.distanceInternal;
167
- }
168
- if (bikeData.distanceInternal !== undefined)
169
- this.distanceInternal = bikeData.distanceInternal;
170
- const data = {
171
- speed: bikeData.speed,
172
- slope: bikeData.slope,
173
- power: bikeData.power !== undefined ? Math.round(bikeData.power) : undefined,
174
- cadence: bikeData.pedalRpm !== undefined ? Math.round(bikeData.pedalRpm) : undefined,
175
- heartrate: bikeData.heartrate !== undefined ? Math.round(bikeData.heartrate) : undefined,
176
- distance,
99
+ transformData(adapterData, deviceData) {
100
+ const data = Object.assign(this.data, {
101
+ power: adapterData.power,
102
+ speed: adapterData.speed,
103
+ cadence: adapterData.pedalRpm,
177
104
  timestamp: Date.now()
178
- };
179
- return data;
105
+ });
106
+ if (adapterData.distanceInternal !== undefined) {
107
+ if (data.internalDistanceCounter !== undefined)
108
+ data.distance = adapterData.distanceInternal - data.internalDistanceCounter;
109
+ data.internalDistanceCounter = adapterData.distanceInternal;
110
+ }
111
+ if (deviceData.Distance)
112
+ data.deviceDistanceCounter = deviceData.Distance;
113
+ if (adapterData.heartrate)
114
+ data.heartrate = adapterData.heartrate;
115
+ if (adapterData.slope)
116
+ data.slope = adapterData.slope;
117
+ if (adapterData.time)
118
+ data.deviceTime = adapterData.time;
119
+ this.data = data;
180
120
  }
181
121
  start(props) {
122
+ return __awaiter(this, void 0, void 0, function* () {
123
+ const isReconnect = (props === null || props === void 0 ? void 0 : props.reconnect) || false;
124
+ const startProps = Object.assign({}, props || {});
125
+ delete startProps.reconnect;
126
+ return yield this.performStart(props, isReconnect);
127
+ });
128
+ }
129
+ performStart(props, isReconnect) {
182
130
  return __awaiter(this, void 0, void 0, function* () {
183
131
  const wasPaused = this.paused;
184
132
  const wasStopped = this.stopped;
185
- this.startProps = props || {};
133
+ this.startProps = props;
186
134
  if (wasPaused)
187
135
  this.resume();
188
- if (wasStopped)
189
- this.stopped = false;
136
+ this.stopped = false;
190
137
  if (this.started && !wasPaused && !wasStopped) {
191
138
  return true;
192
139
  }
193
140
  const connected = yield this.connect();
194
141
  if (!connected)
195
142
  throw new Error(`could not start device, reason:could not connect`);
196
- this.logEvent({ message: 'starting device', props, isStarted: this.started, isReconnecting: this.isReconnecting });
197
- const opts = props || {};
198
- const { args = {}, user = {} } = opts;
199
- return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
200
- const { startupTimeout = 20000, reconnectTimeout = 2000 } = props || {};
201
- const totalTimeout = Math.min(startupTimeout + 10000, startupTimeout * 2);
202
- let to;
203
- const stopTimeoutCheck = () => {
204
- if (to) {
205
- clearTimeout(to);
206
- to = null;
207
- }
208
- };
209
- to = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
210
- reject(new Error(`could not start device, reason:timeout`));
211
- this.started = false;
212
- to = null;
213
- }), totalTimeout);
143
+ this.logEvent({ message: 'starting device', props, isStarted: this.started, isReconnecting: isReconnect });
144
+ const { startupTimeout = this.getDefaultStartupTimeout(), reconnectTimeout = this.getDefaultReconnectDelay() } = props || {};
145
+ const totalTimeout = Math.min(startupTimeout + 10000, startupTimeout * 2);
146
+ let status = { timeout: false, sensorStarted: false, hasData: false, userSent: false, slopeSent: false };
147
+ const doStart = () => __awaiter(this, void 0, void 0, function* () {
214
148
  this.setFEDefaultTimeout();
215
149
  let success = false;
216
- let status = { userSent: false, slopeSent: false };
217
150
  let retry = 0;
218
- let hasData = false;
219
- while (!success && retry < MAX_RETRIES) {
220
- retry++;
221
- if (!this.sensorConnected) {
222
- this.logEvent({ message: 'start sensor', props });
223
- this.sensorConnected = yield this.ant.startSensor(this.sensor, this.onDeviceData.bind(this));
224
- if (this.sensorConnected) {
225
- this.logEvent({ message: 'sensor started', props });
226
- }
227
- }
228
- if (this.sensorConnected && !hasData) {
229
- try {
230
- yield this.waitForData(startupTimeout);
231
- hasData = true;
232
- }
233
- catch (err) {
234
- stopTimeoutCheck();
235
- try {
236
- yield yield this.ant.stopSensor(this.sensor);
237
- this.sensorConnected = false;
238
- }
239
- catch (_a) { }
240
- this.started = false;
241
- return reject(new Error('could not start device, reason:no data received'));
242
- }
151
+ if (isReconnect) {
152
+ status.userSent = true;
153
+ status.slopeSent = true;
154
+ }
155
+ while (!success && retry < MAX_RETRIES && !status.timeout) {
156
+ if (retry !== 0) {
157
+ console.log('~~~ RETRY', status);
243
158
  }
244
- status = { userSent: false, slopeSent: false };
245
- if (!hasData) {
246
- yield (0, utils_2.sleep)(reconnectTimeout);
159
+ retry++;
160
+ yield this.initSensor(status, props);
161
+ yield this.waitForInitialData(status, startupTimeout);
162
+ yield this.sendInititalUserMessage(status, props);
163
+ yield this.sendInitialRequest(status, props);
164
+ if (!status.hasData) {
165
+ yield this.stopSensor();
166
+ yield (0, utils_1.sleep)(reconnectTimeout);
247
167
  continue;
248
168
  }
249
- if (!this.isReconnecting) {
250
- try {
251
- const fe = this.sensor;
252
- const mode = this.getCyclingMode();
253
- const bikeType = mode ? mode.getSetting('bikeType').toLowerCase() : 'race';
254
- const defaultBikeWeight = bikeType === 'mountain' ? DEFAULT_BIKE_WEIGHT_MOUNTAIN : adpater_1.DEFAULT_BIKE_WEIGHT;
255
- const userWeight = args.userWeight || user.weight || adpater_1.DEFAULT_USER_WEIGHT;
256
- const bikeWeight = args.bikeWeight || defaultBikeWeight;
257
- status.userSent = status.userSent || (yield fe.sendUserConfiguration(userWeight, bikeWeight, args.wheelDiameter, args.gearRatio));
258
- if (!status.slopeSent) {
259
- const startRequest = this.getCyclingMode().getBikeInitRequest();
260
- if (startRequest) {
261
- if (startRequest.targetPower !== undefined && startRequest.targetPower !== null) {
262
- status.slopeSent = yield fe.sendTargetPower(startRequest.targetPower);
263
- }
264
- else if (startRequest.slope !== undefined && startRequest.slope !== null) {
265
- status.slopeSent = yield fe.sendTrackResistance(startRequest.slope);
266
- }
267
- else {
268
- status.slopeSent = true;
269
- }
270
- }
271
- else {
272
- status.slopeSent = yield fe.sendTrackResistance(0.0);
273
- }
274
- }
275
- }
276
- catch (err) {
277
- this.logEvent({ message: 'sending FE message error', error: err.message });
278
- this.started = false;
279
- }
280
- success = status.userSent && status.slopeSent;
281
- }
282
- else {
283
- success = true;
284
- }
169
+ success = status.sensorStarted && status.hasData && status.userSent && status.slopeSent;
285
170
  }
286
171
  if (success) {
287
172
  this.logEvent({ message: 'ANT FE start success' });
288
173
  this.started = true;
289
174
  this.paused = false;
290
- stopTimeoutCheck();
291
- resolve(true);
175
+ return true;
292
176
  }
293
177
  else {
294
- this.logEvent({ message: 'ANT FE start failed' });
295
- stopTimeoutCheck();
296
- if (!hasData) {
297
- reject(new Error('could not start device, reason: no data received'));
178
+ this.started = false;
179
+ if (!status.sensorStarted) {
180
+ this.logEvent({ message: 'ANT FE start failed', reason: 'could not connect' });
181
+ throw new Error('could not start device, reason:could not connect');
298
182
  }
299
- else if (this.sensorConnected) {
300
- reject(new Error('could not start device, reason: could not send FE commands'));
183
+ else if (!status.hasData) {
184
+ this.logEvent({ message: 'ANT FE start failed', reason: 'no data received' });
185
+ throw new Error('could not start device, reason:no data received');
301
186
  }
302
187
  else {
303
- reject(new Error('could not start device, reason: could not connect'));
188
+ this.logEvent({ message: 'ANT FE start failed', reason: 'could not send FE commands' });
189
+ throw new Error('could not start device, reason:could not send FE commands');
304
190
  }
191
+ }
192
+ });
193
+ try {
194
+ yield (0, utils_1.runWithTimeout)(doStart(), totalTimeout);
195
+ }
196
+ catch (err) {
197
+ if (err.message === 'Timeout') {
305
198
  this.started = false;
199
+ status.timeout = true;
200
+ throw new Error(`could not start device, reason:timeout`);
201
+ }
202
+ throw err;
203
+ }
204
+ return true;
205
+ });
206
+ }
207
+ waitForInitialData(status, startupTimeout) {
208
+ return __awaiter(this, void 0, void 0, function* () {
209
+ if ((status.sensorStarted && status.hasData) || !status.sensorStarted || status.timeout)
210
+ return;
211
+ this.logEvent({ message: 'wait for sensor data', });
212
+ status.hasData = yield this.waitForData(startupTimeout);
213
+ if (status.hasData)
214
+ this.logEvent({ message: 'sensor data received', });
215
+ });
216
+ }
217
+ stopSensor() {
218
+ return __awaiter(this, void 0, void 0, function* () {
219
+ if (!this.sensorConnected)
220
+ return;
221
+ try {
222
+ yield yield this.ant.stopSensor(this.sensor);
223
+ this.sensorConnected = false;
224
+ }
225
+ catch (_a) { }
226
+ });
227
+ }
228
+ initSensor(status, props) {
229
+ return __awaiter(this, void 0, void 0, function* () {
230
+ status.sensorStarted = this.sensorConnected;
231
+ if (status.sensorStarted || status.timeout)
232
+ return;
233
+ this.logEvent({ message: 'start sensor', props });
234
+ try {
235
+ this.sensorConnected = yield this.startSensor();
236
+ if (this.sensorConnected) {
237
+ this.logEvent({ message: 'sensor started', props });
238
+ status.sensorStarted = true;
306
239
  }
307
- }));
240
+ }
241
+ catch (err) {
242
+ this.logEvent({ message: 'start sensor failed', reason: err.message, props });
243
+ }
244
+ });
245
+ }
246
+ sendInititalUserMessage(status, props) {
247
+ return __awaiter(this, void 0, void 0, function* () {
248
+ if (!status.sensorStarted || !status.hasData || status.userSent || status.timeout)
249
+ return;
250
+ const opts = props || {};
251
+ const { args = {}, user = {} } = opts;
252
+ const fe = this.sensor;
253
+ try {
254
+ const mode = this.getCyclingMode();
255
+ const bikeType = mode ? mode.getSetting('bikeType').toLowerCase() : 'race';
256
+ const defaultBikeWeight = bikeType === 'mountain' ? DEFAULT_BIKE_WEIGHT_MOUNTAIN : consts_1.DEFAULT_BIKE_WEIGHT;
257
+ const userWeight = args.userWeight || user.weight || consts_1.DEFAULT_USER_WEIGHT;
258
+ const bikeWeight = args.bikeWeight || defaultBikeWeight;
259
+ status.userSent = status.userSent || (yield fe.sendUserConfiguration(userWeight, bikeWeight, args.wheelDiameter, args.gearRatio));
260
+ }
261
+ catch (err) {
262
+ this.logEvent({ message: 'sending FE message error', error: err.message });
263
+ status.userSent = false;
264
+ }
265
+ });
266
+ }
267
+ sendInitialRequest(status, props) {
268
+ return __awaiter(this, void 0, void 0, function* () {
269
+ if (!status.sensorStarted || !status.hasData || status.slopeSent || status.timeout)
270
+ return;
271
+ const fe = this.sensor;
272
+ try {
273
+ const startRequest = this.getCyclingMode().getBikeInitRequest();
274
+ if (startRequest) {
275
+ if (startRequest.targetPower !== undefined && startRequest.targetPower !== null) {
276
+ status.slopeSent = yield fe.sendTargetPower(startRequest.targetPower);
277
+ }
278
+ else if (startRequest.slope !== undefined && startRequest.slope !== null) {
279
+ status.slopeSent = yield fe.sendTrackResistance(startRequest.slope);
280
+ }
281
+ else {
282
+ status.slopeSent = true;
283
+ }
284
+ }
285
+ else {
286
+ status.slopeSent = yield fe.sendTrackResistance(0.0);
287
+ }
288
+ }
289
+ catch (err) {
290
+ this.logEvent({ message: 'sending FE message error', error: err.message });
291
+ status.slopeSent = false;
292
+ }
308
293
  });
309
294
  }
310
295
  setFEDefaultTimeout() {
@@ -319,43 +304,52 @@ class AntFEAdapter extends adapter_1.ControllableAntAdapter {
319
304
  reconnect() {
320
305
  return __awaiter(this, void 0, void 0, function* () {
321
306
  this.logEvent({ message: 'reconnect to device' });
322
- this.isReconnecting = true;
323
- try {
324
- yield this.stop();
325
- yield this.start(this.startProps);
326
- this.started = true;
327
- this.isReconnecting = false;
328
- this.logEvent({ message: 'reconnect success' });
329
- return true;
330
- }
331
- catch (err) {
332
- this.logEvent({ message: 'reconnect failed' });
333
- this.isReconnecting = false;
334
- return false;
307
+ if (this.promiseReconnect) {
308
+ return yield this.promiseReconnect;
335
309
  }
310
+ const doReconnect = () => __awaiter(this, void 0, void 0, function* () {
311
+ try {
312
+ yield this.stop();
313
+ yield this.performStart(this.startProps, true);
314
+ this.started = true;
315
+ this.logEvent({ message: 'reconnect success' });
316
+ return true;
317
+ }
318
+ catch (err) {
319
+ this.logEvent({ message: 'reconnect failed' });
320
+ return false;
321
+ }
322
+ });
323
+ this.promiseReconnect = doReconnect();
324
+ const res = yield this.promiseReconnect;
325
+ this.promiseReconnect = null;
326
+ return res;
336
327
  });
337
328
  }
338
329
  sendInitCommands() {
339
330
  return __awaiter(this, void 0, void 0, function* () {
340
331
  if (this.started && !this.stopped) {
341
332
  try {
342
- if (this.getCyclingMode() instanceof ant_fe_erg_mode_1.default) {
333
+ if (this.getCyclingMode() instanceof antble_erg_1.default) {
343
334
  const power = this.data.power;
344
335
  const request = power ? { targetPower: power } : this.getCyclingMode().getBikeInitRequest();
345
336
  yield this.sendUpdate(request, true);
346
337
  return true;
347
338
  }
348
339
  }
349
- catch (_a) {
340
+ catch (err) {
341
+ console.log(err);
350
342
  return false;
351
343
  }
352
344
  }
353
- else {
354
- return false;
355
- }
345
+ return false;
356
346
  });
357
347
  }
358
348
  }
359
349
  AntFEAdapter.INCYCLIST_PROFILE_NAME = 'Smart Trainer';
360
350
  AntFEAdapter.ANT_PROFILE_NAME = 'FE';
351
+ AntFEAdapter.controllers = {
352
+ modes: [antble_smarttrainer_1.default, antble_erg_1.default, ant_fe_adv_st_mode_1.default],
353
+ default: antble_smarttrainer_1.default
354
+ };
361
355
  exports.default = AntFEAdapter;
@@ -1,19 +1,11 @@
1
- import { HeartRateSensorState, ISensor, Profile } from "incyclist-ant-plus";
2
- import AntAdapter from "../adapter";
1
+ import { HeartRateSensorState, Profile } from "incyclist-ant-plus";
2
+ import AntAdapter from "../base/adapter";
3
3
  import { AntDeviceProperties, AntDeviceSettings, LegacyProfile } from "../types";
4
- type HeartRateSensorData = {
5
- heartrate: number;
6
- };
7
- export default class AntHrAdapter extends AntAdapter<HeartRateSensorState, HeartRateSensorData> {
8
- static INCYCLIST_PROFILE_NAME: LegacyProfile;
9
- static ANT_PROFILE_NAME: Profile;
4
+ export default class AntHrAdapter extends AntAdapter<HeartRateSensorState> {
5
+ protected static INCYCLIST_PROFILE_NAME: LegacyProfile;
6
+ protected static ANT_PROFILE_NAME: Profile;
10
7
  constructor(settings: AntDeviceSettings, props?: AntDeviceProperties);
11
- createSensor(settings: AntDeviceSettings): ISensor;
12
- getName(): string;
13
- getUniqueName(): string;
14
8
  getDisplayName(): string;
15
- onDeviceData(deviceData: HeartRateSensorState): void;
16
- mapData(deviceData: HeartRateSensorState): void;
9
+ mapToAdapterData(deviceData: HeartRateSensorState): void;
17
10
  hasData(): boolean;
18
11
  }
19
- export {};
@@ -3,71 +3,23 @@ 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
- const adapter_1 = __importDefault(require("../adapter"));
7
- const utils_1 = require("../utils");
8
- const gd_eventlog_1 = require("gd-eventlog");
9
- const sensor_factory_1 = __importDefault(require("../sensor-factory"));
10
- const capabilities_1 = require("../../types/capabilities");
6
+ const adapter_1 = __importDefault(require("../base/adapter"));
7
+ const types_1 = require("../../types");
11
8
  class AntHrAdapter extends adapter_1.default {
12
9
  constructor(settings, props) {
13
- if (settings.protocol && settings.profile !== AntHrAdapter.INCYCLIST_PROFILE_NAME)
14
- throw new Error('Incorrect Profile');
15
- if (!settings.protocol && settings.profile !== AntHrAdapter.ANT_PROFILE_NAME)
16
- throw new Error('Incorrect Profile');
17
10
  super(settings, props);
18
- this.deviceData = {
19
- DeviceID: this.sensor.getDeviceID()
20
- };
21
- this.logger = new gd_eventlog_1.EventLogger('Ant+Hrm');
22
- this.capabilities = [capabilities_1.IncyclistCapability.HeartRate];
23
- }
24
- createSensor(settings) {
25
- return sensor_factory_1.default.create(AntHrAdapter.ANT_PROFILE_NAME, Number(settings.deviceID));
26
- }
27
- getName() {
28
- if (this.settings.name)
29
- return this.settings.name;
30
- const deviceID = this.sensor.getDeviceID();
31
- return `Ant+HR ${deviceID}`;
32
- }
33
- getUniqueName() {
34
- if (this.settings.name)
35
- return this.settings.name;
36
- const { DeviceID, ManId } = this.deviceData;
37
- const brand = (0, utils_1.getBrand)(ManId);
38
- if (brand)
39
- return `${brand} HR ${DeviceID}`;
40
- else
41
- return `${this.getName()}`;
11
+ this.capabilities = [types_1.IncyclistCapability.HeartRate];
42
12
  }
43
13
  getDisplayName() {
44
14
  const { ComputedHeartRate } = this.deviceData;
45
15
  const hrmStr = ComputedHeartRate ? ` (${ComputedHeartRate})` : '';
46
16
  return `${this.getUniqueName()}${hrmStr}`;
47
17
  }
48
- onDeviceData(deviceData) {
49
- this.dataMsgCount++;
50
- this.lastDataTS = Date.now();
51
- super.onDeviceData(deviceData);
52
- if (!this.started)
53
- return;
54
- if (!this.ivDataTimeout)
55
- this.startDataTimeoutCheck();
56
- try {
57
- if (!this.canSendUpdate())
58
- return;
59
- this.logEvent({ message: 'onDeviceData', data: deviceData });
60
- if (this.paused)
61
- return;
62
- this.mapData(deviceData);
63
- this.emitData(this.data);
64
- }
65
- catch (err) {
66
- }
67
- }
68
- mapData(deviceData) {
69
- if (deviceData.ComputedHeartRate)
18
+ mapToAdapterData(deviceData) {
19
+ if (deviceData.ComputedHeartRate) {
70
20
  this.data.heartrate = deviceData.ComputedHeartRate;
21
+ this.data.timestamp = Date.now();
22
+ }
71
23
  }
72
24
  hasData() {
73
25
  return this.deviceData.ComputedHeartRate !== undefined && this.deviceData.ComputedHeartRate !== null;
@@ -0,0 +1,11 @@
1
+ import { HeartRateSensorState, Profile } from "incyclist-ant-plus";
2
+ import AntAdapter from "../base/adapter";
3
+ import { AntDeviceProperties, AntDeviceSettings, LegacyProfile } from "../types";
4
+ export default class AntHrAdapter extends AntAdapter<HeartRateSensorState> {
5
+ protected static INCYCLIST_PROFILE_NAME: LegacyProfile;
6
+ protected static ANT_PROFILE_NAME: Profile;
7
+ constructor(settings: AntDeviceSettings, props?: AntDeviceProperties);
8
+ getDisplayName(): string;
9
+ mapToAdapterData(deviceData: HeartRateSensorState): void;
10
+ hasData(): boolean;
11
+ }