incyclist-devices 1.2.0 → 1.4.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/LICENSE +21 -0
- package/lib/CyclingMode.d.ts +72 -0
- package/lib/CyclingMode.js +66 -0
- package/lib/Device.d.ts +48 -10
- package/lib/Device.js +9 -8
- package/lib/DeviceProtocol.d.ts +40 -12
- package/lib/DeviceProtocol.js +16 -16
- package/lib/DeviceRegistry.d.ts +4 -4
- package/lib/DeviceRegistry.js +10 -10
- package/lib/DeviceSupport.d.ts +4 -3
- package/lib/DeviceSupport.js +32 -8
- package/lib/ant/AntAdapter.d.ts +9 -2
- package/lib/ant/AntAdapter.js +26 -2
- package/lib/ant/AntScanner.d.ts +16 -6
- package/lib/ant/AntScanner.js +379 -138
- package/lib/ant/antfe/AntFEAdapter.d.ts +4 -2
- package/lib/ant/antfe/AntFEAdapter.js +209 -72
- package/lib/ant/anthrm/AntHrmAdapter.d.ts +4 -1
- package/lib/ant/anthrm/AntHrmAdapter.js +73 -19
- package/lib/ant/utils.js +2 -1
- package/lib/calculations.d.ts +12 -13
- package/lib/calculations.js +88 -125
- package/lib/daum/DaumAdapter.d.ts +29 -6
- package/lib/daum/DaumAdapter.js +219 -96
- package/lib/daum/ERGCyclingMode.d.ts +28 -0
- package/lib/daum/ERGCyclingMode.js +207 -0
- package/lib/daum/PowerMeterCyclingMode.d.ts +18 -0
- package/lib/daum/PowerMeterCyclingMode.js +79 -0
- package/lib/daum/SmartTrainerCyclingMode.d.ts +41 -0
- package/lib/daum/SmartTrainerCyclingMode.js +344 -0
- package/lib/daum/classic/DaumClassicAdapter.d.ts +3 -1
- package/lib/daum/classic/DaumClassicAdapter.js +46 -32
- package/lib/daum/classic/DaumClassicCyclingMode.d.ts +13 -0
- package/lib/daum/classic/DaumClassicCyclingMode.js +98 -0
- package/lib/daum/classic/DaumClassicProtocol.d.ts +5 -3
- package/lib/daum/classic/DaumClassicProtocol.js +39 -6
- package/lib/daum/classic/ERGCyclingMode.d.ts +23 -0
- package/lib/daum/classic/ERGCyclingMode.js +171 -0
- package/lib/daum/classic/bike.d.ts +41 -37
- package/lib/daum/classic/bike.js +86 -53
- package/lib/daum/classic/utils.d.ts +3 -3
- package/lib/daum/classic/utils.js +16 -10
- package/lib/daum/indoorbike.d.ts +2 -1
- package/lib/daum/indoorbike.js +23 -21
- package/lib/daum/premium/DaumPremiumAdapter.d.ts +2 -2
- package/lib/daum/premium/DaumPremiumAdapter.js +30 -20
- package/lib/daum/premium/DaumPremiumProtocol.d.ts +11 -2
- package/lib/daum/premium/DaumPremiumProtocol.js +49 -8
- package/lib/daum/premium/bike.d.ts +63 -52
- package/lib/daum/premium/bike.js +258 -207
- package/lib/daum/premium/tcpserial.d.ts +18 -14
- package/lib/daum/premium/tcpserial.js +50 -20
- package/lib/daum/premium/utils.d.ts +2 -2
- package/lib/simulator/Simulator.d.ts +13 -7
- package/lib/simulator/Simulator.js +62 -21
- package/lib/utils.d.ts +3 -1
- package/lib/utils.js +39 -18
- package/package.json +12 -11
- package/lib/ant/AntScanner.unit.tests.d.ts +0 -1
- package/lib/ant/AntScanner.unit.tests.js +0 -25
- package/lib/ant/antfe/AntFEProcessor.d.ts +0 -40
- package/lib/ant/antfe/AntFEProcessor.js +0 -238
- package/lib/ant/antfe/AntHrmProtocol.d.ts +0 -9
- package/lib/ant/antfe/AntHrmProtocol.js +0 -30
- package/lib/ant/antfe/bike.d.ts +0 -47
- package/lib/ant/antfe/bike.js +0 -602
- package/lib/ant/anthrm/anthrm.d.ts +0 -33
- package/lib/ant/anthrm/anthrm.js +0 -523
- package/lib/simulator/Simulator.unit.tests.d.ts +0 -1
- package/lib/simulator/Simulator.unit.tests.js +0 -79
package/lib/daum/premium/bike.js
CHANGED
|
@@ -8,46 +8,50 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.Daum8iSerial = exports.Daum8iTcp = void 0;
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const tcpserial_1 = require("./tcpserial");
|
|
16
|
+
const constants_1 = require("../constants");
|
|
17
|
+
const tcpserial_1 = __importDefault(require("./tcpserial"));
|
|
16
18
|
const utils_1 = require("./utils");
|
|
17
|
-
const utils_2 = require("../../utils");
|
|
18
19
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
19
20
|
const nop = () => { };
|
|
20
21
|
const MAX_RETRIES = 5;
|
|
21
22
|
const DEFAULT_TIMEOUT = 10000;
|
|
22
23
|
const DEFAULT_SEND_DELAY = 1000;
|
|
23
|
-
const OPEN_RETRY_DELAY = 3000;
|
|
24
|
-
const CLOSE_RETRY_TIMEOUT = 5000;
|
|
25
24
|
const TIMEOUT_START = 15000;
|
|
25
|
+
const OPEN_TIMEOUT = 1000;
|
|
26
26
|
const DAUM_PREMIUM_DEFAULT_PORT = 51955;
|
|
27
27
|
const DAUM_PREMIUM_DEFAULT_HOST = '127.0.0.1';
|
|
28
28
|
var __SerialPort = undefined;
|
|
29
29
|
var net = undefined;
|
|
30
|
+
const DEBUG_LOGGER = {
|
|
31
|
+
log: (e, ...args) => console.log(e, ...args),
|
|
32
|
+
logEvent: (event) => console.log(JSON.stringify(event))
|
|
33
|
+
};
|
|
30
34
|
class Daum8i {
|
|
31
35
|
constructor(props) {
|
|
32
|
-
|
|
33
|
-
this.
|
|
34
|
-
this.
|
|
35
|
-
if (
|
|
36
|
-
const port =
|
|
37
|
-
const host =
|
|
38
|
-
this.portName = `${host}
|
|
36
|
+
this.props = props || {};
|
|
37
|
+
this.logger = process.env.DEBUG ? DEBUG_LOGGER : new gd_eventlog_1.EventLogger('DaumPremium');
|
|
38
|
+
this.logger.logEvent({ message: 'new DaumPremium object', props: this.props });
|
|
39
|
+
if (this.props.interface === 'tcpip') {
|
|
40
|
+
const port = this.props.port || DAUM_PREMIUM_DEFAULT_PORT;
|
|
41
|
+
const host = this.props.host || DAUM_PREMIUM_DEFAULT_HOST;
|
|
42
|
+
this.portName = `${host}:51955`;
|
|
39
43
|
this.tcpip = true;
|
|
40
44
|
this.serial = false;
|
|
41
45
|
this.tcpipConnection = { host, port };
|
|
42
46
|
}
|
|
43
47
|
else {
|
|
44
|
-
this.portName =
|
|
48
|
+
this.portName = this.props.port || process.env.COM_PORT;
|
|
45
49
|
this.tcpip = false;
|
|
46
50
|
this.serial = true;
|
|
47
51
|
this.port = this.portName;
|
|
48
52
|
}
|
|
49
|
-
this.settings =
|
|
50
|
-
this.settings.logger = this.
|
|
53
|
+
this.settings = this.props.settings || {};
|
|
54
|
+
this.settings.logger = this.logger;
|
|
51
55
|
this.sendRetryDelay = DEFAULT_SEND_DELAY;
|
|
52
56
|
this.sp = undefined;
|
|
53
57
|
this.connected = false;
|
|
@@ -61,7 +65,6 @@ class Daum8i {
|
|
|
61
65
|
bikeWeight: 10,
|
|
62
66
|
maxPower: 800
|
|
63
67
|
};
|
|
64
|
-
this.processor = new indoorbike_js_1.default(this);
|
|
65
68
|
}
|
|
66
69
|
static getClassName() {
|
|
67
70
|
return "Daum8i";
|
|
@@ -76,7 +79,7 @@ class Daum8i {
|
|
|
76
79
|
net = netClass;
|
|
77
80
|
}
|
|
78
81
|
static getSupportedInterfaces() {
|
|
79
|
-
return [
|
|
82
|
+
return [constants_1.BIKE_INTERFACE.SERIAL, constants_1.BIKE_INTERFACE.TCPIP];
|
|
80
83
|
}
|
|
81
84
|
getPort() {
|
|
82
85
|
return this.portName;
|
|
@@ -85,7 +88,7 @@ class Daum8i {
|
|
|
85
88
|
return this.connected;
|
|
86
89
|
}
|
|
87
90
|
setUser(user, callback) {
|
|
88
|
-
this.
|
|
91
|
+
this.logger.logEvent({ message: "setUser()", user, port: this.portName });
|
|
89
92
|
this.settings.user = user || {};
|
|
90
93
|
var cb = callback || nop;
|
|
91
94
|
cb(200, user);
|
|
@@ -101,43 +104,49 @@ class Daum8i {
|
|
|
101
104
|
unblock() {
|
|
102
105
|
this.blocked = false;
|
|
103
106
|
}
|
|
104
|
-
connect(
|
|
105
|
-
this.
|
|
107
|
+
connect() {
|
|
108
|
+
this.logger.logEvent({ message: "connect()", sp: (this.sp !== undefined), connected: this.connected, blocked: this.blocked, port: this.portName, settings: this.settings });
|
|
106
109
|
if (this.connected || this.blocked) {
|
|
107
110
|
return;
|
|
108
111
|
}
|
|
109
112
|
this.state.busy = true;
|
|
110
113
|
this.state.commandsInQueue = {};
|
|
111
114
|
try {
|
|
115
|
+
if (this.sp !== undefined) {
|
|
116
|
+
try {
|
|
117
|
+
this.sp.removeAllListeners();
|
|
118
|
+
this.sp.close();
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
}
|
|
122
|
+
this.sp = undefined;
|
|
123
|
+
}
|
|
112
124
|
if (this.sp === undefined) {
|
|
113
125
|
if (this.tcpip) {
|
|
114
126
|
const { host, port } = this.tcpipConnection;
|
|
115
|
-
|
|
127
|
+
const { logger } = this.props;
|
|
128
|
+
this.logger.logEvent({ message: "creating TCPSocketPort", host, port });
|
|
129
|
+
this.sp = new tcpserial_1.default({ host, port, net, timeout: OPEN_TIMEOUT, logger });
|
|
116
130
|
}
|
|
117
131
|
else {
|
|
118
132
|
const settings = this.settings.port || {};
|
|
119
133
|
settings.autoOpen = false;
|
|
134
|
+
this.logger.logEvent({ message: "creating SerialPort", port: this.port, settings });
|
|
120
135
|
this.sp = new __SerialPort(this.port, settings);
|
|
121
136
|
}
|
|
122
137
|
this.sp.on('open', this.onPortOpen.bind(this));
|
|
123
138
|
this.sp.on('close', this.onPortClose.bind(this));
|
|
124
139
|
this.sp.on('error', (error) => { this.onPortError(error); });
|
|
125
140
|
this.sp.on('data', (data) => { this.onData(data); });
|
|
126
|
-
this.firstOpen = true;
|
|
127
141
|
}
|
|
128
142
|
const start = Date.now();
|
|
129
143
|
this.state.connecting = true;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
else {
|
|
133
|
-
this.state.opening.start = start;
|
|
134
|
-
this.state.opening.timeout = start + this.getTimeoutValue();
|
|
135
|
-
this.state.opening.retry = this.state.opening.retry + 1;
|
|
136
|
-
}
|
|
144
|
+
this.state.opening = { start, timeout: start + this.getTimeoutValue() };
|
|
145
|
+
this.logger.logEvent({ message: "opening port ..." });
|
|
137
146
|
this.sp.open();
|
|
138
147
|
}
|
|
139
148
|
catch (err) {
|
|
140
|
-
this.
|
|
149
|
+
this.logger.logEvent({ message: "scan:error:", error: err.message, stack: err.stack });
|
|
141
150
|
this.state.busy = false;
|
|
142
151
|
}
|
|
143
152
|
}
|
|
@@ -156,16 +165,26 @@ class Daum8i {
|
|
|
156
165
|
this.connect();
|
|
157
166
|
const tTimeout = Date.now() + TIMEOUT_START;
|
|
158
167
|
const iv = setInterval(() => {
|
|
159
|
-
if (this.
|
|
168
|
+
if (this.state.error !== undefined) {
|
|
169
|
+
console.log('~~ -> error');
|
|
170
|
+
clearInterval(iv);
|
|
171
|
+
this.forceClose();
|
|
172
|
+
reject(this.state.error);
|
|
173
|
+
this.state = { opened: false, closed: true, busy: false };
|
|
174
|
+
}
|
|
175
|
+
else if (this.isConnected()) {
|
|
176
|
+
console.log('~~ -> connected');
|
|
160
177
|
this.state.connecting = false;
|
|
161
178
|
resolve(true);
|
|
162
179
|
clearInterval(iv);
|
|
163
180
|
}
|
|
164
181
|
else {
|
|
165
182
|
if (Date.now() > tTimeout) {
|
|
183
|
+
console.log('~~ -> timeout');
|
|
166
184
|
this.state.connecting = false;
|
|
167
|
-
|
|
185
|
+
this.forceClose();
|
|
168
186
|
clearInterval(iv);
|
|
187
|
+
reject(new Error('timeout'));
|
|
169
188
|
}
|
|
170
189
|
}
|
|
171
190
|
}, 100);
|
|
@@ -177,10 +196,10 @@ class Daum8i {
|
|
|
177
196
|
this.state.opening = undefined;
|
|
178
197
|
this.state.opened = true;
|
|
179
198
|
this.state.busy = false;
|
|
180
|
-
this.
|
|
199
|
+
this.logger.logEvent({ message: "port opened", port: this.portName });
|
|
181
200
|
}
|
|
182
201
|
onPortClose() {
|
|
183
|
-
this.
|
|
202
|
+
this.logger.logEvent({ message: "port closed", port: this.portName });
|
|
184
203
|
this.error = undefined;
|
|
185
204
|
this.connected = false;
|
|
186
205
|
if (this.state.opening) {
|
|
@@ -190,81 +209,56 @@ class Daum8i {
|
|
|
190
209
|
else {
|
|
191
210
|
this.state = { opened: false, closed: true, busy: false };
|
|
192
211
|
}
|
|
212
|
+
this.sp.removeAllListeners();
|
|
193
213
|
this.sp = undefined;
|
|
194
214
|
if (this.queue !== undefined)
|
|
195
215
|
this.queue.clear();
|
|
196
216
|
}
|
|
217
|
+
getLogState() {
|
|
218
|
+
let s = undefined;
|
|
219
|
+
const { sending, busy, opening, connecting, writeBusy, waitingForStart, waitingForAck, waitingForEnd, retry } = this.state;
|
|
220
|
+
if (sending) {
|
|
221
|
+
s = {};
|
|
222
|
+
s.command = sending.command;
|
|
223
|
+
s.payload = sending.payload;
|
|
224
|
+
}
|
|
225
|
+
return { sending: s, busy, writeBusy, opening, connecting, waitingForStart, waitingForEnd, waitingForAck, retry };
|
|
226
|
+
}
|
|
197
227
|
onPortError(error) {
|
|
198
|
-
this.
|
|
228
|
+
this.logger.logEvent({ message: "port error:", port: this.portName, error: error.message, connected: this.connected, state: this.getLogState() });
|
|
199
229
|
this.error = error;
|
|
200
230
|
if (this.blocked) {
|
|
201
231
|
if (!this.state.closed) {
|
|
202
|
-
if (this.sp)
|
|
232
|
+
if (this.sp) {
|
|
233
|
+
this.sp.removeAllListeners();
|
|
203
234
|
this.sp.close();
|
|
235
|
+
this.sp = undefined;
|
|
236
|
+
}
|
|
204
237
|
this.state = { opened: false, closed: true, busy: false };
|
|
205
238
|
}
|
|
206
239
|
return;
|
|
207
240
|
}
|
|
208
|
-
const reconnect = () => {
|
|
209
|
-
if (this.state.opening && !this.state.closing) {
|
|
210
|
-
this.LOG.logEvent({ message: "retry connection:", portName: this.port, connected: this.connected, scanMode: this.scanMode });
|
|
211
|
-
this.connect(true);
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
241
|
if (this.state.closing) {
|
|
215
242
|
if (error.message === 'Port is not open') {
|
|
216
243
|
this.state = { opened: false, closed: true, busy: false };
|
|
217
244
|
return;
|
|
218
245
|
}
|
|
219
246
|
else {
|
|
220
|
-
|
|
221
|
-
if ((retry + 1 < maxRetries)) {
|
|
222
|
-
this.state.closing.retry = retry + 1;
|
|
223
|
-
return setTimeout(() => { this.close(); }, CLOSE_RETRY_TIMEOUT);
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
this.LOG.logEvent({ message: "close request failed - giving up", port: this.portName });
|
|
227
|
-
this.state.closing = undefined;
|
|
228
|
-
}
|
|
247
|
+
this.forceClose();
|
|
229
248
|
}
|
|
230
249
|
}
|
|
231
250
|
else if (this.state.opening) {
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
try {
|
|
235
|
-
if (this.sp)
|
|
236
|
-
this.sp.close();
|
|
237
|
-
}
|
|
238
|
-
catch (err) {
|
|
239
|
-
console.log(err);
|
|
240
|
-
}
|
|
241
|
-
if ((retry + 1) < maxRetries) {
|
|
242
|
-
this.state.opening.retry = retry + 1;
|
|
243
|
-
setTimeout(() => {
|
|
244
|
-
if (!this.state.busy)
|
|
245
|
-
reconnect();
|
|
246
|
-
else {
|
|
247
|
-
const iv = setInterval(() => {
|
|
248
|
-
if (!this.state.busy) {
|
|
249
|
-
clearInterval(iv);
|
|
250
|
-
reconnect();
|
|
251
|
-
}
|
|
252
|
-
}, 50);
|
|
253
|
-
}
|
|
254
|
-
}, OPEN_RETRY_DELAY);
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
this.state.opening = undefined;
|
|
258
|
-
}
|
|
251
|
+
if (this.state.connecting) {
|
|
252
|
+
this.state.error = error;
|
|
259
253
|
}
|
|
260
254
|
else {
|
|
261
255
|
this.onPortOpen();
|
|
262
256
|
}
|
|
263
257
|
}
|
|
264
258
|
else if (this.state.sending) {
|
|
265
|
-
this.
|
|
266
|
-
this.
|
|
267
|
-
|
|
259
|
+
this.state.error = error;
|
|
260
|
+
this.forceClose(false);
|
|
261
|
+
return;
|
|
268
262
|
}
|
|
269
263
|
this.state.busy = false;
|
|
270
264
|
}
|
|
@@ -286,36 +280,47 @@ class Daum8i {
|
|
|
286
280
|
}, 50);
|
|
287
281
|
});
|
|
288
282
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
if (this.
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
283
|
+
forceClose(updateState = false) {
|
|
284
|
+
console.log('~~~ forceClose', updateState);
|
|
285
|
+
const sp = this.sp;
|
|
286
|
+
if (!this.sp)
|
|
287
|
+
return;
|
|
288
|
+
this.sp.removeAllListeners();
|
|
289
|
+
try {
|
|
290
|
+
sp.unpipe();
|
|
291
|
+
sp.flush();
|
|
296
292
|
}
|
|
293
|
+
catch (_a) { }
|
|
294
|
+
sp.close();
|
|
295
|
+
this.connected = false;
|
|
296
|
+
if (updateState)
|
|
297
|
+
this.state = { opened: false, closed: true, busy: false };
|
|
298
|
+
}
|
|
299
|
+
close() {
|
|
300
|
+
this.logger.logEvent({ message: 'close request', port: this.portName });
|
|
301
|
+
var sp = this.sp;
|
|
297
302
|
let connected = this.connected;
|
|
298
303
|
try {
|
|
299
304
|
if (connected) {
|
|
300
|
-
if (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
305
|
+
if (sp) {
|
|
306
|
+
sp.unpipe();
|
|
307
|
+
sp.flush();
|
|
308
|
+
sp.close();
|
|
304
309
|
}
|
|
305
|
-
this.connected = false;
|
|
306
310
|
if (this.queue !== undefined) {
|
|
307
311
|
this.queue.clear();
|
|
308
312
|
this.queue = undefined;
|
|
309
313
|
}
|
|
310
314
|
}
|
|
311
315
|
else {
|
|
312
|
-
if (
|
|
313
|
-
|
|
316
|
+
if (sp)
|
|
317
|
+
sp.close();
|
|
314
318
|
}
|
|
315
319
|
}
|
|
316
320
|
catch (err) {
|
|
317
|
-
this.
|
|
321
|
+
this.logger.logEvent({ message: 'close: Exception', port: this.portName, error: err.message });
|
|
318
322
|
}
|
|
323
|
+
this.connected = false;
|
|
319
324
|
const start = Date.now();
|
|
320
325
|
if (this.state.closing === undefined)
|
|
321
326
|
this.state.closing = { start, timeout: start + this.getTimeoutValue(), retry: 0, maxRetries: MAX_RETRIES };
|
|
@@ -327,7 +332,7 @@ class Daum8i {
|
|
|
327
332
|
this.state.busy = false;
|
|
328
333
|
}
|
|
329
334
|
sendTimeout(message) {
|
|
330
|
-
this.
|
|
335
|
+
this.logger.logEvent({ message: `sendCommand:${message || 'timeout'}`, port: this.portName, cmd: this.cmdCurrent });
|
|
331
336
|
delete this.state.commandsInQueue[this.cmdCurrent.command];
|
|
332
337
|
if (this.cmdCurrent.callbackErr !== undefined) {
|
|
333
338
|
let cb = this.cmdCurrent.callbackErr;
|
|
@@ -337,29 +342,39 @@ class Daum8i {
|
|
|
337
342
|
cb(408, { message: message || "timeout" });
|
|
338
343
|
}
|
|
339
344
|
}
|
|
340
|
-
|
|
345
|
+
checkForResponse() {
|
|
341
346
|
const d = Date.now();
|
|
342
347
|
const s = this.state.sending;
|
|
343
348
|
if (s === undefined)
|
|
344
|
-
return;
|
|
349
|
+
return false;
|
|
350
|
+
const rejectFn = s.reject;
|
|
351
|
+
const reject = (err) => {
|
|
352
|
+
if (rejectFn && typeof rejectFn === 'function') {
|
|
353
|
+
rejectFn(err);
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
const error = this.state.error;
|
|
357
|
+
if (error !== undefined) {
|
|
358
|
+
reject(error);
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
345
361
|
try {
|
|
346
|
-
if (!this.state.sending)
|
|
347
|
-
return;
|
|
348
362
|
if (this.state.waitingForACK) {
|
|
349
363
|
const timeoutACK = this.state.ack ? this.state.ack.timeout : this.state.sending.timeout;
|
|
350
364
|
if (d < timeoutACK)
|
|
351
|
-
return;
|
|
365
|
+
return true;
|
|
352
366
|
reject(new Error('ACK timeout'));
|
|
353
|
-
return;
|
|
367
|
+
return false;
|
|
354
368
|
}
|
|
355
369
|
if (d < this.state.sending.timeout)
|
|
356
|
-
return;
|
|
357
|
-
reject(new Error('timeout'));
|
|
358
|
-
return;
|
|
370
|
+
return true;
|
|
371
|
+
reject(new Error('RESP timeout'));
|
|
372
|
+
return false;
|
|
359
373
|
}
|
|
360
374
|
catch (err) {
|
|
361
|
-
this.
|
|
375
|
+
this.logger.logEvent({ message: 'checkForResponse: Exception', port: this.portName, error: err.message, stack: err.stack });
|
|
362
376
|
}
|
|
377
|
+
return true;
|
|
363
378
|
}
|
|
364
379
|
getTimeoutValue(cmd) {
|
|
365
380
|
let timeout = DEFAULT_TIMEOUT;
|
|
@@ -374,103 +389,153 @@ class Daum8i {
|
|
|
374
389
|
}
|
|
375
390
|
onData(data) {
|
|
376
391
|
let cmd = '';
|
|
377
|
-
if (
|
|
378
|
-
|
|
392
|
+
if (this.state.waitingForEnd) {
|
|
393
|
+
cmd = this.state.partialCmd;
|
|
379
394
|
}
|
|
395
|
+
const bufferData = Buffer.isBuffer(data) ? data : Buffer.from(data, 'latin1');
|
|
380
396
|
const s = this.state.sending;
|
|
381
397
|
if (s === undefined) {
|
|
382
398
|
if (this.state.input === undefined)
|
|
383
|
-
this.state.input =
|
|
399
|
+
this.state.input = bufferData;
|
|
384
400
|
return;
|
|
385
401
|
}
|
|
386
402
|
const { portName, resolve } = this.state.sending;
|
|
387
403
|
let incoming;
|
|
388
404
|
if (this.state.input !== undefined) {
|
|
389
|
-
const arr = [this.state.input,
|
|
405
|
+
const arr = [this.state.input, bufferData];
|
|
390
406
|
incoming = Buffer.concat(arr);
|
|
391
407
|
}
|
|
392
408
|
else {
|
|
393
|
-
incoming =
|
|
409
|
+
incoming = bufferData;
|
|
394
410
|
}
|
|
411
|
+
const response = [...incoming];
|
|
412
|
+
this.logger.logEvent({ message: 'sendCommand:RECV', data: (0, utils_1.hexstr)(response) });
|
|
395
413
|
for (let i = 0; i < incoming.length; i++) {
|
|
414
|
+
const getRemaining = () => {
|
|
415
|
+
let remaining = '';
|
|
416
|
+
const done = i === (incoming.length - 1);
|
|
417
|
+
if (!done) {
|
|
418
|
+
for (let j = i + 1; j < incoming.length; j++)
|
|
419
|
+
remaining += String.fromCharCode(incoming.readUInt8(j));
|
|
420
|
+
}
|
|
421
|
+
return remaining;
|
|
422
|
+
};
|
|
396
423
|
const c = incoming.readUInt8(i);
|
|
397
424
|
if (c === 0x06) {
|
|
398
|
-
this.
|
|
425
|
+
this.logger.logEvent({ message: "sendCommand:ACK received:", port: portName });
|
|
399
426
|
this.state.waitingForStart = true;
|
|
400
427
|
this.state.waitingForACK = false;
|
|
428
|
+
const remaining = getRemaining();
|
|
429
|
+
if (remaining && remaining !== '')
|
|
430
|
+
return this.onData(remaining);
|
|
401
431
|
}
|
|
402
432
|
else if (c === 0x15) {
|
|
403
433
|
this.state.waitingForStart = true;
|
|
404
434
|
this.state.waitingForACK = false;
|
|
405
|
-
this.
|
|
435
|
+
this.logger.logEvent({ message: "sendCommand:NAK received:", port: portName });
|
|
436
|
+
const remaining = getRemaining();
|
|
437
|
+
if (remaining && remaining !== '')
|
|
438
|
+
return this.onData(remaining);
|
|
406
439
|
}
|
|
407
440
|
else if (c === 0x01) {
|
|
408
441
|
this.state.waitingForEnd = true;
|
|
409
442
|
}
|
|
410
443
|
else if (c === 0x17) {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
444
|
+
const remaining = getRemaining();
|
|
445
|
+
this.logger.logEvent({ message: "sendCommand:received:", duration: Date.now() - this.state.sending.tsRequest, port: portName, cmd: `${cmd} [${(0, utils_1.hexstr)(cmd)}]`, remaining: (0, utils_1.hexstr)(remaining) });
|
|
446
|
+
this.state.waitingForEnd = false;
|
|
447
|
+
const cmdStr = cmd.substring(0, cmd.length - 2);
|
|
448
|
+
const checksumExtracted = cmd.slice(-2);
|
|
449
|
+
const checksumCalculated = (0, utils_1.checkSum)((0, utils_1.getAsciiArrayFromStr)(cmdStr), []);
|
|
450
|
+
if (checksumExtracted === checksumCalculated) {
|
|
451
|
+
this.sendACK();
|
|
452
|
+
if (this.state.sending && this.state.sending.responseCheckIv) {
|
|
453
|
+
clearInterval(this.state.sending.responseCheckIv);
|
|
454
|
+
}
|
|
455
|
+
this.state = {
|
|
456
|
+
sending: undefined,
|
|
457
|
+
busy: false,
|
|
458
|
+
writeBusy: false,
|
|
459
|
+
waitingForStart: false,
|
|
460
|
+
waitingForEnd: false,
|
|
461
|
+
waitingForACK: false,
|
|
462
|
+
};
|
|
463
|
+
const payload = cmd.substring(3, cmd.length - 2);
|
|
464
|
+
resolve(payload);
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
this.sendNAK();
|
|
468
|
+
}
|
|
425
469
|
cmd = '';
|
|
470
|
+
if (remaining)
|
|
471
|
+
return this.onData(remaining);
|
|
426
472
|
}
|
|
427
473
|
else {
|
|
428
474
|
if (this.state.waitingForEnd)
|
|
429
475
|
cmd += String.fromCharCode(c);
|
|
430
476
|
}
|
|
431
477
|
}
|
|
478
|
+
if (this.state.waitingForEnd) {
|
|
479
|
+
this.state.partialCmd = cmd;
|
|
480
|
+
}
|
|
432
481
|
}
|
|
433
|
-
sendDaum8iCommand(command, queryType, payload
|
|
482
|
+
sendDaum8iCommand(command, queryType, payload) {
|
|
483
|
+
const tsRequest = Date.now();
|
|
434
484
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
435
485
|
if (this.blocked)
|
|
436
|
-
reject(new Error('blocked'));
|
|
486
|
+
return reject(new Error('blocked'));
|
|
437
487
|
if (!this.state.busy) {
|
|
438
488
|
this.state.busy = true;
|
|
439
|
-
if (!this.connected) {
|
|
440
|
-
reject(new Error('not connected'));
|
|
441
|
-
if (!this.state.connecting) {
|
|
442
|
-
this.saveConnect(true)
|
|
443
|
-
.then(() => { this.state.busy = false; })
|
|
444
|
-
.catch((reason) => { this.state.busy = reason === 'busy'; });
|
|
445
|
-
}
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
489
|
}
|
|
449
490
|
else {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
491
|
+
const message = (0, utils_1.buildMessage)(command, payload);
|
|
492
|
+
this.logger.logEvent({ message: 'sendCommand:waiting', port: this.portName, cmd: command, hex: (0, utils_1.hexstr)(message) });
|
|
493
|
+
const busyWait = () => {
|
|
494
|
+
return new Promise((done) => {
|
|
495
|
+
let start = Date.now();
|
|
496
|
+
let timeout = start + 5000;
|
|
497
|
+
const iv = setInterval(() => {
|
|
498
|
+
if (this.state.busy) {
|
|
499
|
+
if (Date.now() > timeout) {
|
|
500
|
+
clearInterval(iv);
|
|
501
|
+
done(false);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
clearInterval(iv);
|
|
506
|
+
done(true);
|
|
507
|
+
}
|
|
508
|
+
}, 10);
|
|
509
|
+
});
|
|
510
|
+
};
|
|
511
|
+
const res = yield busyWait();
|
|
512
|
+
if (!res) {
|
|
513
|
+
this.logger.logEvent({ message: 'sendCommand:busy timeout', port: this.portName, cmd: command, hex: (0, utils_1.hexstr)(message), duration: Date.now() - tsRequest });
|
|
514
|
+
return reject(new Error('BUSY timeout'));
|
|
457
515
|
}
|
|
458
516
|
this.state.busy = true;
|
|
459
517
|
}
|
|
518
|
+
const writeDone = () => {
|
|
519
|
+
this.state.sending = undefined;
|
|
520
|
+
this.state.writeBusy = false;
|
|
521
|
+
this.state.busy = false;
|
|
522
|
+
this.state.sending = undefined;
|
|
523
|
+
this.state.waitingForStart = false;
|
|
524
|
+
this.state.waitingForEnd = false;
|
|
525
|
+
this.state.waitingForACK = false;
|
|
526
|
+
};
|
|
460
527
|
const port = this.sp;
|
|
461
528
|
const portName = this.portName;
|
|
462
529
|
this.state.received = [];
|
|
463
530
|
try {
|
|
464
|
-
const message = utils_1.buildMessage(command, payload);
|
|
531
|
+
const message = (0, utils_1.buildMessage)(command, payload);
|
|
465
532
|
const start = Date.now();
|
|
466
533
|
const timeout = start + this.getTimeoutValue();
|
|
467
|
-
this.
|
|
534
|
+
this.logger.logEvent({ message: "sendCommand:sending:", port: this.portName, cmd: command, hex: (0, utils_1.hexstr)(message) });
|
|
468
535
|
this.state.writeBusy = true;
|
|
469
|
-
if (!this.connected) {
|
|
470
|
-
this.
|
|
471
|
-
|
|
472
|
-
this.state.busy = false;
|
|
473
|
-
this.state.sending = undefined;
|
|
536
|
+
if (!this.connected || port === undefined) {
|
|
537
|
+
this.logger.logEvent({ message: "sendCommand:error: not connected", port: this.portName });
|
|
538
|
+
writeDone();
|
|
474
539
|
return reject(new Error('not connected'));
|
|
475
540
|
}
|
|
476
541
|
port.write(message);
|
|
@@ -478,34 +543,18 @@ class Daum8i {
|
|
|
478
543
|
this.state.writeBusy = false;
|
|
479
544
|
this.state.retry = 0;
|
|
480
545
|
this.state.ack = { start, timeout };
|
|
481
|
-
this.state.sending = { command, payload, start, timeout, port, portName, resolve, reject };
|
|
482
|
-
this.state.sending.
|
|
483
|
-
this.
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
}
|
|
490
|
-
if (this.state.retryBusy)
|
|
491
|
-
return;
|
|
492
|
-
this.state.retryBusy = true;
|
|
493
|
-
this.state.retry++;
|
|
494
|
-
setTimeout(() => {
|
|
495
|
-
const restart = Date.now();
|
|
496
|
-
this.state.ack = { start: restart, timeout: restart + this.getTimeoutValue() };
|
|
497
|
-
this.LOG.logEvent({ message: "sendCommand:retry:", port: this.portName, cmd: command, hex: utils_1.hexstr(message) });
|
|
498
|
-
port.write(message);
|
|
499
|
-
this.state.retryBusy = false;
|
|
500
|
-
}, this.sendRetryDelay);
|
|
501
|
-
});
|
|
502
|
-
});
|
|
546
|
+
this.state.sending = { command, payload, start, timeout, port, portName, tsRequest, resolve, reject };
|
|
547
|
+
const iv = this.state.sending.responseCheckIv = setInterval(() => {
|
|
548
|
+
const stillWaiting = this.checkForResponse();
|
|
549
|
+
if (!stillWaiting) {
|
|
550
|
+
clearInterval(iv);
|
|
551
|
+
writeDone();
|
|
552
|
+
}
|
|
553
|
+
}, 10);
|
|
503
554
|
}
|
|
504
555
|
catch (err) {
|
|
505
|
-
this.
|
|
506
|
-
|
|
507
|
-
this.state.busy = false;
|
|
508
|
-
this.state.sending = undefined;
|
|
556
|
+
this.logger.logEvent({ message: "sendCommand:error:", port: portName, error: err.message, stack: err.stack });
|
|
557
|
+
writeDone();
|
|
509
558
|
reject(err);
|
|
510
559
|
}
|
|
511
560
|
}));
|
|
@@ -518,7 +567,7 @@ class Daum8i {
|
|
|
518
567
|
}
|
|
519
568
|
catch (err) { }
|
|
520
569
|
this.state.writeBusy = false;
|
|
521
|
-
this.
|
|
570
|
+
this.logger.logEvent({ message: "sendCommand:sending ACK", port, queue: this.state.commandsInQueue });
|
|
522
571
|
}
|
|
523
572
|
sendNAK() {
|
|
524
573
|
const port = this.portName;
|
|
@@ -526,22 +575,22 @@ class Daum8i {
|
|
|
526
575
|
this.sp.write([0x15]);
|
|
527
576
|
}
|
|
528
577
|
catch (err) { }
|
|
529
|
-
this.
|
|
578
|
+
this.logger.logEvent({ message: "sendCommand:sending NAK", port });
|
|
530
579
|
}
|
|
531
|
-
sendReservedDaum8iCommand(command, cmdType, data
|
|
580
|
+
sendReservedDaum8iCommand(command, cmdType, data) {
|
|
532
581
|
let cmdData = [];
|
|
533
|
-
const key = utils_1.getReservedCommandKey(command);
|
|
534
|
-
utils_1.append(cmdData, utils_1.Int16ToIntArray(key));
|
|
582
|
+
const key = (0, utils_1.getReservedCommandKey)(command);
|
|
583
|
+
(0, utils_1.append)(cmdData, (0, utils_1.Int16ToIntArray)(key));
|
|
535
584
|
if (data !== undefined && data.length > 0) {
|
|
536
|
-
utils_1.append(cmdData, utils_1.Int16ToIntArray(data.length));
|
|
537
|
-
utils_1.append(cmdData, data);
|
|
585
|
+
(0, utils_1.append)(cmdData, (0, utils_1.Int16ToIntArray)(data.length));
|
|
586
|
+
(0, utils_1.append)(cmdData, data);
|
|
538
587
|
}
|
|
539
588
|
else {
|
|
540
|
-
utils_1.append(cmdData, utils_1.Int16ToIntArray(0));
|
|
589
|
+
(0, utils_1.append)(cmdData, (0, utils_1.Int16ToIntArray)(0));
|
|
541
590
|
}
|
|
542
|
-
return this.sendDaum8iCommand('M70', cmdType, utils_1.bin2esc(cmdData))
|
|
591
|
+
return this.sendDaum8iCommand('M70', cmdType, (0, utils_1.bin2esc)(cmdData))
|
|
543
592
|
.then((resData) => {
|
|
544
|
-
const cmd = utils_1.esc2bin(resData);
|
|
593
|
+
const cmd = (0, utils_1.esc2bin)(resData);
|
|
545
594
|
cmd.splice(0, 4);
|
|
546
595
|
return cmd;
|
|
547
596
|
});
|
|
@@ -567,7 +616,7 @@ class Daum8i {
|
|
|
567
616
|
else if (str === '7')
|
|
568
617
|
deviceType = 'lyps';
|
|
569
618
|
else
|
|
570
|
-
throw (new Error(`unknown device type ${typeof str === 'string' ? utils_1.ascii(str.charAt(0)) : str}`));
|
|
619
|
+
throw (new Error(`unknown device type ${typeof str === 'string' ? (0, utils_1.ascii)(str.charAt(0)) : str}`));
|
|
571
620
|
return deviceType;
|
|
572
621
|
});
|
|
573
622
|
}
|
|
@@ -576,13 +625,13 @@ class Daum8i {
|
|
|
576
625
|
.then((str) => {
|
|
577
626
|
let deviceType;
|
|
578
627
|
if (str === '0')
|
|
579
|
-
deviceType =
|
|
628
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.ALLROUND;
|
|
580
629
|
else if (str === '1')
|
|
581
|
-
deviceType =
|
|
630
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.RACE;
|
|
582
631
|
else if (str === '2')
|
|
583
|
-
deviceType =
|
|
632
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.MOUNTAIN;
|
|
584
633
|
else {
|
|
585
|
-
throw (new Error(`unknown actual device type ${typeof str === 'string' ? utils_1.ascii(str.charAt(0)) : str}`));
|
|
634
|
+
throw (new Error(`unknown actual device type ${typeof str === 'string' ? (0, utils_1.ascii)(str.charAt(0)) : str}`));
|
|
586
635
|
}
|
|
587
636
|
this.state.actualBikeType = deviceType;
|
|
588
637
|
return deviceType;
|
|
@@ -591,16 +640,16 @@ class Daum8i {
|
|
|
591
640
|
setActualBikeType(actualBikeType) {
|
|
592
641
|
let bikeType;
|
|
593
642
|
switch (actualBikeType) {
|
|
594
|
-
case
|
|
643
|
+
case constants_1.ACTUAL_BIKE_TYPE.ALLROUND:
|
|
595
644
|
bikeType = '0';
|
|
596
645
|
break;
|
|
597
|
-
case
|
|
646
|
+
case constants_1.ACTUAL_BIKE_TYPE.RACE:
|
|
598
647
|
bikeType = '1';
|
|
599
648
|
break;
|
|
600
|
-
case
|
|
649
|
+
case constants_1.ACTUAL_BIKE_TYPE.TRIATHLON:
|
|
601
650
|
bikeType = '1';
|
|
602
651
|
break;
|
|
603
|
-
case
|
|
652
|
+
case constants_1.ACTUAL_BIKE_TYPE.MOUNTAIN:
|
|
604
653
|
bikeType = '2';
|
|
605
654
|
break;
|
|
606
655
|
default:
|
|
@@ -610,11 +659,11 @@ class Daum8i {
|
|
|
610
659
|
.then((str) => {
|
|
611
660
|
let deviceType;
|
|
612
661
|
if (str === '0')
|
|
613
|
-
deviceType =
|
|
662
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.ALLROUND;
|
|
614
663
|
else if (str === '1')
|
|
615
|
-
deviceType =
|
|
664
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.RACE;
|
|
616
665
|
else if (str === '2')
|
|
617
|
-
deviceType =
|
|
666
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.MOUNTAIN;
|
|
618
667
|
else
|
|
619
668
|
throw (new Error('unknown actual device type'));
|
|
620
669
|
this.state.actualBikeType = deviceType;
|
|
@@ -624,12 +673,12 @@ class Daum8i {
|
|
|
624
673
|
getTrainingData() {
|
|
625
674
|
return this.sendDaum8iCommand('X70', 'AF', [])
|
|
626
675
|
.then((data) => {
|
|
627
|
-
const td = utils_1.parseTrainingData(data);
|
|
676
|
+
const td = (0, utils_1.parseTrainingData)(data);
|
|
628
677
|
return td;
|
|
629
678
|
});
|
|
630
679
|
}
|
|
631
680
|
setLoadControl(enabled) {
|
|
632
|
-
const val = enabled ? utils_1.ascii('1') : utils_1.ascii('0');
|
|
681
|
+
const val = enabled ? (0, utils_1.ascii)('1') : (0, utils_1.ascii)('0');
|
|
633
682
|
return this.sendDaum8iCommand('S20', 'BF', [val])
|
|
634
683
|
.then((data) => {
|
|
635
684
|
const res = data === '1';
|
|
@@ -644,7 +693,7 @@ class Daum8i {
|
|
|
644
693
|
});
|
|
645
694
|
}
|
|
646
695
|
setSlope(slope) {
|
|
647
|
-
this.
|
|
696
|
+
this.logger.logEvent({ message: 'setSlope not implemted' });
|
|
648
697
|
return;
|
|
649
698
|
}
|
|
650
699
|
setPower(power) {
|
|
@@ -681,23 +730,25 @@ class Daum8iTcp extends Daum8i {
|
|
|
681
730
|
static getClassName() { return "Daum8i"; }
|
|
682
731
|
getType() { return "Daum8iTcp"; }
|
|
683
732
|
static setSerialPort(spClass) { }
|
|
733
|
+
getInterface() { return constants_1.BIKE_INTERFACE.TCPIP; }
|
|
684
734
|
static setNetImpl(netClass) {
|
|
685
735
|
net = netClass;
|
|
686
736
|
}
|
|
687
737
|
static getSupportedInterfaces() {
|
|
688
|
-
return [
|
|
738
|
+
return [constants_1.BIKE_INTERFACE.TCPIP];
|
|
689
739
|
}
|
|
690
740
|
}
|
|
691
741
|
exports.Daum8iTcp = Daum8iTcp;
|
|
692
742
|
class Daum8iSerial extends Daum8i {
|
|
693
743
|
static getClassName() { return "Daum8i"; }
|
|
694
744
|
getType() { return "Daum8iSerial"; }
|
|
745
|
+
getInterface() { return constants_1.BIKE_INTERFACE.SERIAL; }
|
|
695
746
|
static setSerialPort(spClass) {
|
|
696
747
|
__SerialPort = spClass;
|
|
697
748
|
}
|
|
698
749
|
static setNetImpl(netClass) { }
|
|
699
750
|
static getSupportedInterfaces() {
|
|
700
|
-
return [
|
|
751
|
+
return [constants_1.BIKE_INTERFACE.SERIAL];
|
|
701
752
|
}
|
|
702
753
|
}
|
|
703
754
|
exports.Daum8iSerial = Daum8iSerial;
|