incyclist-devices 1.3.0 → 1.4.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.
- 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 +7 -3
- package/lib/ant/AntAdapter.js +23 -3
- package/lib/ant/AntScanner.d.ts +15 -6
- package/lib/ant/AntScanner.js +372 -128
- package/lib/ant/antfe/AntFEAdapter.d.ts +1 -1
- package/lib/ant/antfe/AntFEAdapter.js +191 -92
- package/lib/ant/anthrm/AntHrmAdapter.d.ts +3 -1
- package/lib/ant/anthrm/AntHrmAdapter.js +70 -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 +47 -8
- 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 +18 -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 +57 -10
- package/lib/daum/premium/bike.d.ts +63 -52
- package/lib/daum/premium/bike.js +254 -207
- package/lib/daum/premium/tcpserial.d.ts +18 -14
- package/lib/daum/premium/tcpserial.js +44 -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/FEDevice.d.ts +0 -1
- package/lib/ant/antfe/FEDevice.js +0 -7
- 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,7 +165,13 @@ 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
|
+
clearInterval(iv);
|
|
170
|
+
this.forceClose();
|
|
171
|
+
reject(this.state.error);
|
|
172
|
+
this.state = { opened: false, closed: true, busy: false };
|
|
173
|
+
}
|
|
174
|
+
else if (this.isConnected()) {
|
|
160
175
|
this.state.connecting = false;
|
|
161
176
|
resolve(true);
|
|
162
177
|
clearInterval(iv);
|
|
@@ -164,8 +179,9 @@ class Daum8i {
|
|
|
164
179
|
else {
|
|
165
180
|
if (Date.now() > tTimeout) {
|
|
166
181
|
this.state.connecting = false;
|
|
167
|
-
|
|
182
|
+
this.forceClose();
|
|
168
183
|
clearInterval(iv);
|
|
184
|
+
reject(new Error('timeout'));
|
|
169
185
|
}
|
|
170
186
|
}
|
|
171
187
|
}, 100);
|
|
@@ -177,10 +193,10 @@ class Daum8i {
|
|
|
177
193
|
this.state.opening = undefined;
|
|
178
194
|
this.state.opened = true;
|
|
179
195
|
this.state.busy = false;
|
|
180
|
-
this.
|
|
196
|
+
this.logger.logEvent({ message: "port opened", port: this.portName });
|
|
181
197
|
}
|
|
182
198
|
onPortClose() {
|
|
183
|
-
this.
|
|
199
|
+
this.logger.logEvent({ message: "port closed", port: this.portName });
|
|
184
200
|
this.error = undefined;
|
|
185
201
|
this.connected = false;
|
|
186
202
|
if (this.state.opening) {
|
|
@@ -190,81 +206,56 @@ class Daum8i {
|
|
|
190
206
|
else {
|
|
191
207
|
this.state = { opened: false, closed: true, busy: false };
|
|
192
208
|
}
|
|
209
|
+
this.sp.removeAllListeners();
|
|
193
210
|
this.sp = undefined;
|
|
194
211
|
if (this.queue !== undefined)
|
|
195
212
|
this.queue.clear();
|
|
196
213
|
}
|
|
214
|
+
getLogState() {
|
|
215
|
+
let s = undefined;
|
|
216
|
+
const { sending, busy, opening, connecting, writeBusy, waitingForStart, waitingForAck, waitingForEnd, retry } = this.state;
|
|
217
|
+
if (sending) {
|
|
218
|
+
s = {};
|
|
219
|
+
s.command = sending.command;
|
|
220
|
+
s.payload = sending.payload;
|
|
221
|
+
}
|
|
222
|
+
return { sending: s, busy, writeBusy, opening, connecting, waitingForStart, waitingForEnd, waitingForAck, retry };
|
|
223
|
+
}
|
|
197
224
|
onPortError(error) {
|
|
198
|
-
this.
|
|
225
|
+
this.logger.logEvent({ message: "port error:", port: this.portName, error: error.message, connected: this.connected, state: this.getLogState() });
|
|
199
226
|
this.error = error;
|
|
200
227
|
if (this.blocked) {
|
|
201
228
|
if (!this.state.closed) {
|
|
202
|
-
if (this.sp)
|
|
229
|
+
if (this.sp) {
|
|
230
|
+
this.sp.removeAllListeners();
|
|
203
231
|
this.sp.close();
|
|
232
|
+
this.sp = undefined;
|
|
233
|
+
}
|
|
204
234
|
this.state = { opened: false, closed: true, busy: false };
|
|
205
235
|
}
|
|
206
236
|
return;
|
|
207
237
|
}
|
|
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
238
|
if (this.state.closing) {
|
|
215
239
|
if (error.message === 'Port is not open') {
|
|
216
240
|
this.state = { opened: false, closed: true, busy: false };
|
|
217
241
|
return;
|
|
218
242
|
}
|
|
219
243
|
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
|
-
}
|
|
244
|
+
this.forceClose();
|
|
229
245
|
}
|
|
230
246
|
}
|
|
231
247
|
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
|
-
}
|
|
248
|
+
if (this.state.connecting) {
|
|
249
|
+
this.state.error = error;
|
|
259
250
|
}
|
|
260
251
|
else {
|
|
261
252
|
this.onPortOpen();
|
|
262
253
|
}
|
|
263
254
|
}
|
|
264
255
|
else if (this.state.sending) {
|
|
265
|
-
this.
|
|
266
|
-
this.
|
|
267
|
-
|
|
256
|
+
this.state.error = error;
|
|
257
|
+
this.forceClose(false);
|
|
258
|
+
return;
|
|
268
259
|
}
|
|
269
260
|
this.state.busy = false;
|
|
270
261
|
}
|
|
@@ -286,36 +277,46 @@ class Daum8i {
|
|
|
286
277
|
}, 50);
|
|
287
278
|
});
|
|
288
279
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
280
|
+
forceClose(updateState = false) {
|
|
281
|
+
const sp = this.sp;
|
|
282
|
+
if (!this.sp)
|
|
283
|
+
return;
|
|
284
|
+
this.sp.removeAllListeners();
|
|
285
|
+
try {
|
|
286
|
+
sp.unpipe();
|
|
287
|
+
sp.flush();
|
|
296
288
|
}
|
|
289
|
+
catch (_a) { }
|
|
290
|
+
sp.close();
|
|
291
|
+
this.connected = false;
|
|
292
|
+
if (updateState)
|
|
293
|
+
this.state = { opened: false, closed: true, busy: false };
|
|
294
|
+
}
|
|
295
|
+
close() {
|
|
296
|
+
this.logger.logEvent({ message: 'close request', port: this.portName });
|
|
297
|
+
var sp = this.sp;
|
|
297
298
|
let connected = this.connected;
|
|
298
299
|
try {
|
|
299
300
|
if (connected) {
|
|
300
|
-
if (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
301
|
+
if (sp) {
|
|
302
|
+
sp.unpipe();
|
|
303
|
+
sp.flush();
|
|
304
|
+
sp.close();
|
|
304
305
|
}
|
|
305
|
-
this.connected = false;
|
|
306
306
|
if (this.queue !== undefined) {
|
|
307
307
|
this.queue.clear();
|
|
308
308
|
this.queue = undefined;
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
else {
|
|
312
|
-
if (
|
|
313
|
-
|
|
312
|
+
if (sp)
|
|
313
|
+
sp.close();
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
316
|
catch (err) {
|
|
317
|
-
this.
|
|
317
|
+
this.logger.logEvent({ message: 'close: Exception', port: this.portName, error: err.message });
|
|
318
318
|
}
|
|
319
|
+
this.connected = false;
|
|
319
320
|
const start = Date.now();
|
|
320
321
|
if (this.state.closing === undefined)
|
|
321
322
|
this.state.closing = { start, timeout: start + this.getTimeoutValue(), retry: 0, maxRetries: MAX_RETRIES };
|
|
@@ -327,7 +328,7 @@ class Daum8i {
|
|
|
327
328
|
this.state.busy = false;
|
|
328
329
|
}
|
|
329
330
|
sendTimeout(message) {
|
|
330
|
-
this.
|
|
331
|
+
this.logger.logEvent({ message: `sendCommand:${message || 'timeout'}`, port: this.portName, cmd: this.cmdCurrent });
|
|
331
332
|
delete this.state.commandsInQueue[this.cmdCurrent.command];
|
|
332
333
|
if (this.cmdCurrent.callbackErr !== undefined) {
|
|
333
334
|
let cb = this.cmdCurrent.callbackErr;
|
|
@@ -337,29 +338,39 @@ class Daum8i {
|
|
|
337
338
|
cb(408, { message: message || "timeout" });
|
|
338
339
|
}
|
|
339
340
|
}
|
|
340
|
-
|
|
341
|
+
checkForResponse() {
|
|
341
342
|
const d = Date.now();
|
|
342
343
|
const s = this.state.sending;
|
|
343
344
|
if (s === undefined)
|
|
344
|
-
return;
|
|
345
|
+
return false;
|
|
346
|
+
const rejectFn = s.reject;
|
|
347
|
+
const reject = (err) => {
|
|
348
|
+
if (rejectFn && typeof rejectFn === 'function') {
|
|
349
|
+
rejectFn(err);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const error = this.state.error;
|
|
353
|
+
if (error !== undefined) {
|
|
354
|
+
reject(error);
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
345
357
|
try {
|
|
346
|
-
if (!this.state.sending)
|
|
347
|
-
return;
|
|
348
358
|
if (this.state.waitingForACK) {
|
|
349
359
|
const timeoutACK = this.state.ack ? this.state.ack.timeout : this.state.sending.timeout;
|
|
350
360
|
if (d < timeoutACK)
|
|
351
|
-
return;
|
|
361
|
+
return true;
|
|
352
362
|
reject(new Error('ACK timeout'));
|
|
353
|
-
return;
|
|
363
|
+
return false;
|
|
354
364
|
}
|
|
355
365
|
if (d < this.state.sending.timeout)
|
|
356
|
-
return;
|
|
357
|
-
reject(new Error('timeout'));
|
|
358
|
-
return;
|
|
366
|
+
return true;
|
|
367
|
+
reject(new Error('RESP timeout'));
|
|
368
|
+
return false;
|
|
359
369
|
}
|
|
360
370
|
catch (err) {
|
|
361
|
-
this.
|
|
371
|
+
this.logger.logEvent({ message: 'checkForResponse: Exception', port: this.portName, error: err.message, stack: err.stack });
|
|
362
372
|
}
|
|
373
|
+
return true;
|
|
363
374
|
}
|
|
364
375
|
getTimeoutValue(cmd) {
|
|
365
376
|
let timeout = DEFAULT_TIMEOUT;
|
|
@@ -374,103 +385,153 @@ class Daum8i {
|
|
|
374
385
|
}
|
|
375
386
|
onData(data) {
|
|
376
387
|
let cmd = '';
|
|
377
|
-
if (
|
|
378
|
-
|
|
388
|
+
if (this.state.waitingForEnd) {
|
|
389
|
+
cmd = this.state.partialCmd;
|
|
379
390
|
}
|
|
391
|
+
const bufferData = Buffer.isBuffer(data) ? data : Buffer.from(data, 'latin1');
|
|
380
392
|
const s = this.state.sending;
|
|
381
393
|
if (s === undefined) {
|
|
382
394
|
if (this.state.input === undefined)
|
|
383
|
-
this.state.input =
|
|
395
|
+
this.state.input = bufferData;
|
|
384
396
|
return;
|
|
385
397
|
}
|
|
386
398
|
const { portName, resolve } = this.state.sending;
|
|
387
399
|
let incoming;
|
|
388
400
|
if (this.state.input !== undefined) {
|
|
389
|
-
const arr = [this.state.input,
|
|
401
|
+
const arr = [this.state.input, bufferData];
|
|
390
402
|
incoming = Buffer.concat(arr);
|
|
391
403
|
}
|
|
392
404
|
else {
|
|
393
|
-
incoming =
|
|
405
|
+
incoming = bufferData;
|
|
394
406
|
}
|
|
407
|
+
const response = [...incoming];
|
|
408
|
+
this.logger.logEvent({ message: 'sendCommand:RECV', data: (0, utils_1.hexstr)(response) });
|
|
395
409
|
for (let i = 0; i < incoming.length; i++) {
|
|
410
|
+
const getRemaining = () => {
|
|
411
|
+
let remaining = '';
|
|
412
|
+
const done = i === (incoming.length - 1);
|
|
413
|
+
if (!done) {
|
|
414
|
+
for (let j = i + 1; j < incoming.length; j++)
|
|
415
|
+
remaining += String.fromCharCode(incoming.readUInt8(j));
|
|
416
|
+
}
|
|
417
|
+
return remaining;
|
|
418
|
+
};
|
|
396
419
|
const c = incoming.readUInt8(i);
|
|
397
420
|
if (c === 0x06) {
|
|
398
|
-
this.
|
|
421
|
+
this.logger.logEvent({ message: "sendCommand:ACK received:", port: portName });
|
|
399
422
|
this.state.waitingForStart = true;
|
|
400
423
|
this.state.waitingForACK = false;
|
|
424
|
+
const remaining = getRemaining();
|
|
425
|
+
if (remaining && remaining !== '')
|
|
426
|
+
return this.onData(remaining);
|
|
401
427
|
}
|
|
402
428
|
else if (c === 0x15) {
|
|
403
429
|
this.state.waitingForStart = true;
|
|
404
430
|
this.state.waitingForACK = false;
|
|
405
|
-
this.
|
|
431
|
+
this.logger.logEvent({ message: "sendCommand:NAK received:", port: portName });
|
|
432
|
+
const remaining = getRemaining();
|
|
433
|
+
if (remaining && remaining !== '')
|
|
434
|
+
return this.onData(remaining);
|
|
406
435
|
}
|
|
407
436
|
else if (c === 0x01) {
|
|
408
437
|
this.state.waitingForEnd = true;
|
|
409
438
|
}
|
|
410
439
|
else if (c === 0x17) {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
440
|
+
const remaining = getRemaining();
|
|
441
|
+
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) });
|
|
442
|
+
this.state.waitingForEnd = false;
|
|
443
|
+
const cmdStr = cmd.substring(0, cmd.length - 2);
|
|
444
|
+
const checksumExtracted = cmd.slice(-2);
|
|
445
|
+
const checksumCalculated = (0, utils_1.checkSum)((0, utils_1.getAsciiArrayFromStr)(cmdStr), []);
|
|
446
|
+
if (checksumExtracted === checksumCalculated) {
|
|
447
|
+
this.sendACK();
|
|
448
|
+
if (this.state.sending && this.state.sending.responseCheckIv) {
|
|
449
|
+
clearInterval(this.state.sending.responseCheckIv);
|
|
450
|
+
}
|
|
451
|
+
this.state = {
|
|
452
|
+
sending: undefined,
|
|
453
|
+
busy: false,
|
|
454
|
+
writeBusy: false,
|
|
455
|
+
waitingForStart: false,
|
|
456
|
+
waitingForEnd: false,
|
|
457
|
+
waitingForACK: false,
|
|
458
|
+
};
|
|
459
|
+
const payload = cmd.substring(3, cmd.length - 2);
|
|
460
|
+
resolve(payload);
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
this.sendNAK();
|
|
464
|
+
}
|
|
425
465
|
cmd = '';
|
|
466
|
+
if (remaining)
|
|
467
|
+
return this.onData(remaining);
|
|
426
468
|
}
|
|
427
469
|
else {
|
|
428
470
|
if (this.state.waitingForEnd)
|
|
429
471
|
cmd += String.fromCharCode(c);
|
|
430
472
|
}
|
|
431
473
|
}
|
|
474
|
+
if (this.state.waitingForEnd) {
|
|
475
|
+
this.state.partialCmd = cmd;
|
|
476
|
+
}
|
|
432
477
|
}
|
|
433
|
-
sendDaum8iCommand(command, queryType, payload
|
|
478
|
+
sendDaum8iCommand(command, queryType, payload) {
|
|
479
|
+
const tsRequest = Date.now();
|
|
434
480
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
435
481
|
if (this.blocked)
|
|
436
|
-
reject(new Error('blocked'));
|
|
482
|
+
return reject(new Error('blocked'));
|
|
437
483
|
if (!this.state.busy) {
|
|
438
484
|
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
485
|
}
|
|
449
486
|
else {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
487
|
+
const message = (0, utils_1.buildMessage)(command, payload);
|
|
488
|
+
this.logger.logEvent({ message: 'sendCommand:waiting', port: this.portName, cmd: command, hex: (0, utils_1.hexstr)(message) });
|
|
489
|
+
const busyWait = () => {
|
|
490
|
+
return new Promise((done) => {
|
|
491
|
+
let start = Date.now();
|
|
492
|
+
let timeout = start + 5000;
|
|
493
|
+
const iv = setInterval(() => {
|
|
494
|
+
if (this.state.busy) {
|
|
495
|
+
if (Date.now() > timeout) {
|
|
496
|
+
clearInterval(iv);
|
|
497
|
+
done(false);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
clearInterval(iv);
|
|
502
|
+
done(true);
|
|
503
|
+
}
|
|
504
|
+
}, 10);
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
const res = yield busyWait();
|
|
508
|
+
if (!res) {
|
|
509
|
+
this.logger.logEvent({ message: 'sendCommand:busy timeout', port: this.portName, cmd: command, hex: (0, utils_1.hexstr)(message), duration: Date.now() - tsRequest });
|
|
510
|
+
return reject(new Error('BUSY timeout'));
|
|
457
511
|
}
|
|
458
512
|
this.state.busy = true;
|
|
459
513
|
}
|
|
514
|
+
const writeDone = () => {
|
|
515
|
+
this.state.sending = undefined;
|
|
516
|
+
this.state.writeBusy = false;
|
|
517
|
+
this.state.busy = false;
|
|
518
|
+
this.state.sending = undefined;
|
|
519
|
+
this.state.waitingForStart = false;
|
|
520
|
+
this.state.waitingForEnd = false;
|
|
521
|
+
this.state.waitingForACK = false;
|
|
522
|
+
};
|
|
460
523
|
const port = this.sp;
|
|
461
524
|
const portName = this.portName;
|
|
462
525
|
this.state.received = [];
|
|
463
526
|
try {
|
|
464
|
-
const message = utils_1.buildMessage(command, payload);
|
|
527
|
+
const message = (0, utils_1.buildMessage)(command, payload);
|
|
465
528
|
const start = Date.now();
|
|
466
529
|
const timeout = start + this.getTimeoutValue();
|
|
467
|
-
this.
|
|
530
|
+
this.logger.logEvent({ message: "sendCommand:sending:", port: this.portName, cmd: command, hex: (0, utils_1.hexstr)(message) });
|
|
468
531
|
this.state.writeBusy = true;
|
|
469
|
-
if (!this.connected) {
|
|
470
|
-
this.
|
|
471
|
-
|
|
472
|
-
this.state.busy = false;
|
|
473
|
-
this.state.sending = undefined;
|
|
532
|
+
if (!this.connected || port === undefined) {
|
|
533
|
+
this.logger.logEvent({ message: "sendCommand:error: not connected", port: this.portName });
|
|
534
|
+
writeDone();
|
|
474
535
|
return reject(new Error('not connected'));
|
|
475
536
|
}
|
|
476
537
|
port.write(message);
|
|
@@ -478,34 +539,18 @@ class Daum8i {
|
|
|
478
539
|
this.state.writeBusy = false;
|
|
479
540
|
this.state.retry = 0;
|
|
480
541
|
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
|
-
});
|
|
542
|
+
this.state.sending = { command, payload, start, timeout, port, portName, tsRequest, resolve, reject };
|
|
543
|
+
const iv = this.state.sending.responseCheckIv = setInterval(() => {
|
|
544
|
+
const stillWaiting = this.checkForResponse();
|
|
545
|
+
if (!stillWaiting) {
|
|
546
|
+
clearInterval(iv);
|
|
547
|
+
writeDone();
|
|
548
|
+
}
|
|
549
|
+
}, 10);
|
|
503
550
|
}
|
|
504
551
|
catch (err) {
|
|
505
|
-
this.
|
|
506
|
-
|
|
507
|
-
this.state.busy = false;
|
|
508
|
-
this.state.sending = undefined;
|
|
552
|
+
this.logger.logEvent({ message: "sendCommand:error:", port: portName, error: err.message, stack: err.stack });
|
|
553
|
+
writeDone();
|
|
509
554
|
reject(err);
|
|
510
555
|
}
|
|
511
556
|
}));
|
|
@@ -518,7 +563,7 @@ class Daum8i {
|
|
|
518
563
|
}
|
|
519
564
|
catch (err) { }
|
|
520
565
|
this.state.writeBusy = false;
|
|
521
|
-
this.
|
|
566
|
+
this.logger.logEvent({ message: "sendCommand:sending ACK", port, queue: this.state.commandsInQueue });
|
|
522
567
|
}
|
|
523
568
|
sendNAK() {
|
|
524
569
|
const port = this.portName;
|
|
@@ -526,22 +571,22 @@ class Daum8i {
|
|
|
526
571
|
this.sp.write([0x15]);
|
|
527
572
|
}
|
|
528
573
|
catch (err) { }
|
|
529
|
-
this.
|
|
574
|
+
this.logger.logEvent({ message: "sendCommand:sending NAK", port });
|
|
530
575
|
}
|
|
531
|
-
sendReservedDaum8iCommand(command, cmdType, data
|
|
576
|
+
sendReservedDaum8iCommand(command, cmdType, data) {
|
|
532
577
|
let cmdData = [];
|
|
533
|
-
const key = utils_1.getReservedCommandKey(command);
|
|
534
|
-
utils_1.append(cmdData, utils_1.Int16ToIntArray(key));
|
|
578
|
+
const key = (0, utils_1.getReservedCommandKey)(command);
|
|
579
|
+
(0, utils_1.append)(cmdData, (0, utils_1.Int16ToIntArray)(key));
|
|
535
580
|
if (data !== undefined && data.length > 0) {
|
|
536
|
-
utils_1.append(cmdData, utils_1.Int16ToIntArray(data.length));
|
|
537
|
-
utils_1.append(cmdData, data);
|
|
581
|
+
(0, utils_1.append)(cmdData, (0, utils_1.Int16ToIntArray)(data.length));
|
|
582
|
+
(0, utils_1.append)(cmdData, data);
|
|
538
583
|
}
|
|
539
584
|
else {
|
|
540
|
-
utils_1.append(cmdData, utils_1.Int16ToIntArray(0));
|
|
585
|
+
(0, utils_1.append)(cmdData, (0, utils_1.Int16ToIntArray)(0));
|
|
541
586
|
}
|
|
542
|
-
return this.sendDaum8iCommand('M70', cmdType, utils_1.bin2esc(cmdData))
|
|
587
|
+
return this.sendDaum8iCommand('M70', cmdType, (0, utils_1.bin2esc)(cmdData))
|
|
543
588
|
.then((resData) => {
|
|
544
|
-
const cmd = utils_1.esc2bin(resData);
|
|
589
|
+
const cmd = (0, utils_1.esc2bin)(resData);
|
|
545
590
|
cmd.splice(0, 4);
|
|
546
591
|
return cmd;
|
|
547
592
|
});
|
|
@@ -567,7 +612,7 @@ class Daum8i {
|
|
|
567
612
|
else if (str === '7')
|
|
568
613
|
deviceType = 'lyps';
|
|
569
614
|
else
|
|
570
|
-
throw (new Error(`unknown device type ${typeof str === 'string' ? utils_1.ascii(str.charAt(0)) : str}`));
|
|
615
|
+
throw (new Error(`unknown device type ${typeof str === 'string' ? (0, utils_1.ascii)(str.charAt(0)) : str}`));
|
|
571
616
|
return deviceType;
|
|
572
617
|
});
|
|
573
618
|
}
|
|
@@ -576,13 +621,13 @@ class Daum8i {
|
|
|
576
621
|
.then((str) => {
|
|
577
622
|
let deviceType;
|
|
578
623
|
if (str === '0')
|
|
579
|
-
deviceType =
|
|
624
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.ALLROUND;
|
|
580
625
|
else if (str === '1')
|
|
581
|
-
deviceType =
|
|
626
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.RACE;
|
|
582
627
|
else if (str === '2')
|
|
583
|
-
deviceType =
|
|
628
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.MOUNTAIN;
|
|
584
629
|
else {
|
|
585
|
-
throw (new Error(`unknown actual device type ${typeof str === 'string' ? utils_1.ascii(str.charAt(0)) : str}`));
|
|
630
|
+
throw (new Error(`unknown actual device type ${typeof str === 'string' ? (0, utils_1.ascii)(str.charAt(0)) : str}`));
|
|
586
631
|
}
|
|
587
632
|
this.state.actualBikeType = deviceType;
|
|
588
633
|
return deviceType;
|
|
@@ -591,16 +636,16 @@ class Daum8i {
|
|
|
591
636
|
setActualBikeType(actualBikeType) {
|
|
592
637
|
let bikeType;
|
|
593
638
|
switch (actualBikeType) {
|
|
594
|
-
case
|
|
639
|
+
case constants_1.ACTUAL_BIKE_TYPE.ALLROUND:
|
|
595
640
|
bikeType = '0';
|
|
596
641
|
break;
|
|
597
|
-
case
|
|
642
|
+
case constants_1.ACTUAL_BIKE_TYPE.RACE:
|
|
598
643
|
bikeType = '1';
|
|
599
644
|
break;
|
|
600
|
-
case
|
|
645
|
+
case constants_1.ACTUAL_BIKE_TYPE.TRIATHLON:
|
|
601
646
|
bikeType = '1';
|
|
602
647
|
break;
|
|
603
|
-
case
|
|
648
|
+
case constants_1.ACTUAL_BIKE_TYPE.MOUNTAIN:
|
|
604
649
|
bikeType = '2';
|
|
605
650
|
break;
|
|
606
651
|
default:
|
|
@@ -610,11 +655,11 @@ class Daum8i {
|
|
|
610
655
|
.then((str) => {
|
|
611
656
|
let deviceType;
|
|
612
657
|
if (str === '0')
|
|
613
|
-
deviceType =
|
|
658
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.ALLROUND;
|
|
614
659
|
else if (str === '1')
|
|
615
|
-
deviceType =
|
|
660
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.RACE;
|
|
616
661
|
else if (str === '2')
|
|
617
|
-
deviceType =
|
|
662
|
+
deviceType = constants_1.ACTUAL_BIKE_TYPE.MOUNTAIN;
|
|
618
663
|
else
|
|
619
664
|
throw (new Error('unknown actual device type'));
|
|
620
665
|
this.state.actualBikeType = deviceType;
|
|
@@ -624,12 +669,12 @@ class Daum8i {
|
|
|
624
669
|
getTrainingData() {
|
|
625
670
|
return this.sendDaum8iCommand('X70', 'AF', [])
|
|
626
671
|
.then((data) => {
|
|
627
|
-
const td = utils_1.parseTrainingData(data);
|
|
672
|
+
const td = (0, utils_1.parseTrainingData)(data);
|
|
628
673
|
return td;
|
|
629
674
|
});
|
|
630
675
|
}
|
|
631
676
|
setLoadControl(enabled) {
|
|
632
|
-
const val = enabled ? utils_1.ascii('1') : utils_1.ascii('0');
|
|
677
|
+
const val = enabled ? (0, utils_1.ascii)('1') : (0, utils_1.ascii)('0');
|
|
633
678
|
return this.sendDaum8iCommand('S20', 'BF', [val])
|
|
634
679
|
.then((data) => {
|
|
635
680
|
const res = data === '1';
|
|
@@ -644,7 +689,7 @@ class Daum8i {
|
|
|
644
689
|
});
|
|
645
690
|
}
|
|
646
691
|
setSlope(slope) {
|
|
647
|
-
this.
|
|
692
|
+
this.logger.logEvent({ message: 'setSlope not implemted' });
|
|
648
693
|
return;
|
|
649
694
|
}
|
|
650
695
|
setPower(power) {
|
|
@@ -681,23 +726,25 @@ class Daum8iTcp extends Daum8i {
|
|
|
681
726
|
static getClassName() { return "Daum8i"; }
|
|
682
727
|
getType() { return "Daum8iTcp"; }
|
|
683
728
|
static setSerialPort(spClass) { }
|
|
729
|
+
getInterface() { return constants_1.BIKE_INTERFACE.TCPIP; }
|
|
684
730
|
static setNetImpl(netClass) {
|
|
685
731
|
net = netClass;
|
|
686
732
|
}
|
|
687
733
|
static getSupportedInterfaces() {
|
|
688
|
-
return [
|
|
734
|
+
return [constants_1.BIKE_INTERFACE.TCPIP];
|
|
689
735
|
}
|
|
690
736
|
}
|
|
691
737
|
exports.Daum8iTcp = Daum8iTcp;
|
|
692
738
|
class Daum8iSerial extends Daum8i {
|
|
693
739
|
static getClassName() { return "Daum8i"; }
|
|
694
740
|
getType() { return "Daum8iSerial"; }
|
|
741
|
+
getInterface() { return constants_1.BIKE_INTERFACE.SERIAL; }
|
|
695
742
|
static setSerialPort(spClass) {
|
|
696
743
|
__SerialPort = spClass;
|
|
697
744
|
}
|
|
698
745
|
static setNetImpl(netClass) { }
|
|
699
746
|
static getSupportedInterfaces() {
|
|
700
|
-
return [
|
|
747
|
+
return [constants_1.BIKE_INTERFACE.SERIAL];
|
|
701
748
|
}
|
|
702
749
|
}
|
|
703
750
|
exports.Daum8iSerial = Daum8iSerial;
|