iobroker.sigenergy 2.3.2 → 2.3.4
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/README.md +6 -0
- package/io-package.json +13 -13
- package/lib/registers.js +10 -10
- package/main.js +133 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -153,6 +153,12 @@ Status and power readings for the DC charger.
|
|
|
153
153
|
|
|
154
154
|
## Changelog
|
|
155
155
|
|
|
156
|
+
### 2.3.4 (2026-06-12)
|
|
157
|
+
- (ssbingo) fix: correct protocol level detection — use proper register quantities for probes, descend from V2.9 to V2.6, distinguish transport errors from device exceptions to avoid false pre-V2.6 report
|
|
158
|
+
|
|
159
|
+
### 2.3.3 (2026-06-11)
|
|
160
|
+
- (ssbingo) fix: suppress repeated register read warnings after first occurrence for plant/inverter/acCharger/dcCharger/pss/pid; subsequent failures log at debug level only
|
|
161
|
+
|
|
156
162
|
### 2.3.2 (2026-06-10)
|
|
157
163
|
- (ssbingo) fix: show 'pre-V2.6' instead of 'unknown' when device responds but has no extended plant registers; add per-probe debug log with Modbus exception message
|
|
158
164
|
|
package/io-package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "sigenergy",
|
|
4
|
-
"version": "2.3.
|
|
4
|
+
"version": "2.3.4",
|
|
5
5
|
"news": {
|
|
6
|
-
"2.3.
|
|
7
|
-
"en": "(ssbingo) fix:
|
|
8
|
-
"de": "(ssbingo) fix:
|
|
9
|
-
"ru": "(ssbingo) fix:
|
|
10
|
-
"pt": "(ssbingo) fix:
|
|
11
|
-
"nl": "(ssbingo) fix:
|
|
12
|
-
"fr": "(ssbingo) fix:
|
|
13
|
-
"it": "(ssbingo) fix:
|
|
14
|
-
"es": "(ssbingo) fix:
|
|
15
|
-
"pl": "(ssbingo) fix:
|
|
16
|
-
"uk": "(ssbingo) fix:
|
|
17
|
-
"zh-cn": "(ssbingo) fix:
|
|
6
|
+
"2.3.4": {
|
|
7
|
+
"en": "(ssbingo) fix: correct protocol level detection — use proper register quantities for probes, descend from V2.9 to V2.6, distinguish transport errors from device exceptions to avoid false pre-V2.6 report",
|
|
8
|
+
"de": "(ssbingo) fix: Protokollversionserkennung korrigiert — korrekte Registermengen für Probes, absteigende Reihenfolge V2.9→V2.6, Transportfehler von Geräteantworten unterschieden um fehlerhafte pre-V2.6-Meldung zu vermeiden",
|
|
9
|
+
"ru": "(ssbingo) fix: исправлено определение уровня протокола — правильное количество регистров для проб, порядок убывания V2.9→V2.6, разграничение транспортных ошибок и ответов устройства для исключения ложного сообщения pre-V2.6",
|
|
10
|
+
"pt": "(ssbingo) fix: correção da deteção do nível de protocolo — quantidades corretas de registos para sondas, ordem decrescente V2.9→V2.6, distinção entre erros de transporte e exceções do dispositivo para evitar falso relatório pre-V2.6",
|
|
11
|
+
"nl": "(ssbingo) fix: correcte protocolniveaudetectie — juiste registerhoeveelheden voor probes, aflopende volgorde V2.9→V2.6, onderscheid transportfouten van apparaatreacties om vals pre-V2.6-rapport te voorkomen",
|
|
12
|
+
"fr": "(ssbingo) fix: correction de la détection du niveau de protocole — quantités de registres correctes pour les sondes, ordre décroissant V2.9→V2.6, distinction des erreurs de transport des exceptions du périphérique pour éviter un rapport pre-V2.6 erroné",
|
|
13
|
+
"it": "(ssbingo) fix: correzione del rilevamento del livello di protocollo — quantità di registri corrette per le probe, ordine decrescente V2.9→V2.6, distinzione errori di trasporto da eccezioni del dispositivo per evitare falso rapporto pre-V2.6",
|
|
14
|
+
"es": "(ssbingo) fix: corrección de la detección del nivel de protocolo — cantidades correctas de registros para sondas, orden descendente V2.9→V2.6, distinción de errores de transporte de excepciones del dispositivo para evitar informe falso pre-V2.6",
|
|
15
|
+
"pl": "(ssbingo) fix: poprawka wykrywania poziomu protokołu — właściwe ilości rejestrów dla sond, kolejność malejąca V2.9→V2.6, rozróżnienie błędów transportu od wyjątków urządzenia w celu uniknięcia fałszywego raportu pre-V2.6",
|
|
16
|
+
"uk": "(ssbingo) fix: виправлення визначення рівня протоколу — правильна кількість регістрів для проб, порядок спадання V2.9→V2.6, розрізнення транспортних помилок від винятків пристрою для уникнення хибного звіту pre-V2.6",
|
|
17
|
+
"zh-cn": "(ssbingo) fix: 修正协议版本检测 — 使用正确的寄存器数量探测,从 V2.9 降序到 V2.6,区分传输错误和设备异常,避免误报 pre-V2.6"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"titleLang": {
|
package/lib/registers.js
CHANGED
|
@@ -1252,7 +1252,7 @@ const PLANT_READ_REGISTERS = [
|
|
|
1252
1252
|
desc: 'Total oil generator energy (V2.8)',
|
|
1253
1253
|
feature: 'enableCumulativeEnergy',
|
|
1254
1254
|
},
|
|
1255
|
-
// V2.
|
|
1255
|
+
// V2.9 — separate FC04 group (gap > 4 from 30087)
|
|
1256
1256
|
{
|
|
1257
1257
|
addr: 30272,
|
|
1258
1258
|
qty: 2,
|
|
@@ -1261,7 +1261,7 @@ const PLANT_READ_REGISTERS = [
|
|
|
1261
1261
|
gain: 100,
|
|
1262
1262
|
unit: 'kWh',
|
|
1263
1263
|
role: 'value.energy',
|
|
1264
|
-
desc: 'PV total daily generation (V2.
|
|
1264
|
+
desc: 'PV total daily generation (V2.9)',
|
|
1265
1265
|
},
|
|
1266
1266
|
{
|
|
1267
1267
|
addr: 30274,
|
|
@@ -1271,9 +1271,9 @@ const PLANT_READ_REGISTERS = [
|
|
|
1271
1271
|
gain: 100,
|
|
1272
1272
|
unit: 'kWh',
|
|
1273
1273
|
role: 'value.energy',
|
|
1274
|
-
desc: 'PV total generation previous day (V2.
|
|
1274
|
+
desc: 'PV total generation previous day (V2.9)',
|
|
1275
1275
|
},
|
|
1276
|
-
// V2.
|
|
1276
|
+
// V2.8
|
|
1277
1277
|
{
|
|
1278
1278
|
addr: 30276,
|
|
1279
1279
|
qty: 1,
|
|
@@ -1282,7 +1282,7 @@ const PLANT_READ_REGISTERS = [
|
|
|
1282
1282
|
gain: 100,
|
|
1283
1283
|
unit: 'Hz',
|
|
1284
1284
|
role: 'value.frequency',
|
|
1285
|
-
desc: 'Grid code rated frequency (V2.
|
|
1285
|
+
desc: 'Grid code rated frequency (V2.8)',
|
|
1286
1286
|
},
|
|
1287
1287
|
{
|
|
1288
1288
|
addr: 30277,
|
|
@@ -1292,7 +1292,7 @@ const PLANT_READ_REGISTERS = [
|
|
|
1292
1292
|
gain: 100,
|
|
1293
1293
|
unit: 'V',
|
|
1294
1294
|
role: 'value.voltage',
|
|
1295
|
-
desc: 'Grid code rated voltage (V2.
|
|
1295
|
+
desc: 'Grid code rated voltage (V2.8)',
|
|
1296
1296
|
},
|
|
1297
1297
|
{
|
|
1298
1298
|
addr: 30279,
|
|
@@ -1312,7 +1312,7 @@ const PLANT_READ_REGISTERS = [
|
|
|
1312
1312
|
gain: null,
|
|
1313
1313
|
unit: '',
|
|
1314
1314
|
role: 'value',
|
|
1315
|
-
desc: 'Merged alarm 6 (V2.
|
|
1315
|
+
desc: 'Merged alarm 6 (V2.8)',
|
|
1316
1316
|
},
|
|
1317
1317
|
{
|
|
1318
1318
|
addr: 30281,
|
|
@@ -1322,7 +1322,7 @@ const PLANT_READ_REGISTERS = [
|
|
|
1322
1322
|
gain: null,
|
|
1323
1323
|
unit: '',
|
|
1324
1324
|
role: 'value',
|
|
1325
|
-
desc: 'Merged alarm 7 (V2.
|
|
1325
|
+
desc: 'Merged alarm 7 (V2.8)',
|
|
1326
1326
|
},
|
|
1327
1327
|
{
|
|
1328
1328
|
addr: 30282,
|
|
@@ -1332,7 +1332,7 @@ const PLANT_READ_REGISTERS = [
|
|
|
1332
1332
|
gain: 1000,
|
|
1333
1333
|
unit: 'kW',
|
|
1334
1334
|
role: 'value.power',
|
|
1335
|
-
desc: 'General load power (V2.
|
|
1335
|
+
desc: 'General load power (V2.8)',
|
|
1336
1336
|
},
|
|
1337
1337
|
{
|
|
1338
1338
|
addr: 30284,
|
|
@@ -1342,7 +1342,7 @@ const PLANT_READ_REGISTERS = [
|
|
|
1342
1342
|
gain: 1000,
|
|
1343
1343
|
unit: 'kW',
|
|
1344
1344
|
role: 'value.power',
|
|
1345
|
-
desc: 'Total load power (V2.
|
|
1345
|
+
desc: 'Total load power (V2.8)',
|
|
1346
1346
|
},
|
|
1347
1347
|
{
|
|
1348
1348
|
addr: 30286,
|
package/main.js
CHANGED
|
@@ -62,6 +62,12 @@ class Sigenergy extends utils.Adapter {
|
|
|
62
62
|
this._controlRegistersRead = false;
|
|
63
63
|
this._protocolDetected = false;
|
|
64
64
|
this._essPreheatingUnsupported = false;
|
|
65
|
+
this._plantUnsupportedGroups = new Set();
|
|
66
|
+
this._inverterUnsupportedGroups = new Set();
|
|
67
|
+
this._acChargerUnsupportedGroups = new Set();
|
|
68
|
+
this._dcChargerUnsupportedGroups = new Set();
|
|
69
|
+
this._pssUnsupportedGroups = new Set();
|
|
70
|
+
this._pidUnsupportedGroups = new Set();
|
|
65
71
|
|
|
66
72
|
this.on('ready', this.onReady.bind(this));
|
|
67
73
|
this.on('stateChange', this.onStateChange.bind(this));
|
|
@@ -249,8 +255,9 @@ class Sigenergy extends utils.Adapter {
|
|
|
249
255
|
this._controlRegistersRead = true;
|
|
250
256
|
}
|
|
251
257
|
if (!this._protocolDetected) {
|
|
252
|
-
|
|
253
|
-
|
|
258
|
+
// Only latch the flag if detection was conclusive (no transport
|
|
259
|
+
// errors). Otherwise retry on the next poll cycle.
|
|
260
|
+
this._protocolDetected = await this._detectProtocolLevel();
|
|
254
261
|
}
|
|
255
262
|
|
|
256
263
|
const _t0 = Date.now();
|
|
@@ -305,13 +312,13 @@ class Sigenergy extends utils.Adapter {
|
|
|
305
312
|
await this._updatePvStringPowers();
|
|
306
313
|
|
|
307
314
|
await this.setStateAsync('info.connection', { val: true, ack: true });
|
|
308
|
-
// Successful cycle
|
|
315
|
+
// Successful cycle — reset dedup flags so next outage logs at ERROR level again.
|
|
309
316
|
this._pollErrorKey = null;
|
|
310
317
|
this._pollWarnLogged = false;
|
|
311
318
|
this.log.debug(`[poll] cycle completed in ${Date.now() - _pollStart} ms`);
|
|
312
319
|
} catch (err) {
|
|
313
|
-
// Deduplicate: first occurrence
|
|
314
|
-
// Identical subsequent errors
|
|
320
|
+
// Deduplicate: first occurrence — ERROR (visible + Sentry-worthy).
|
|
321
|
+
// Identical subsequent errors — DEBUG, so a broken network does not flood the log.
|
|
315
322
|
const key = `poll:${err.code || err.message}`;
|
|
316
323
|
if (this._pollErrorKey !== key) {
|
|
317
324
|
this.log.error(`Poll error: ${err.message}`);
|
|
@@ -353,7 +360,12 @@ class Sigenergy extends utils.Adapter {
|
|
|
353
360
|
await this._processReadGroup(group, raw, 'plant');
|
|
354
361
|
await this._sleep(100);
|
|
355
362
|
} catch (err) {
|
|
356
|
-
this.
|
|
363
|
+
if (!this._plantUnsupportedGroups.has(group.startAddr)) {
|
|
364
|
+
this._plantUnsupportedGroups.add(group.startAddr);
|
|
365
|
+
this.log.warn(`Plant register read error at ${group.startAddr}: ${err.message}`);
|
|
366
|
+
} else {
|
|
367
|
+
this.log.debug(`[plant] read error at ${group.startAddr}: ${err.message}`);
|
|
368
|
+
}
|
|
357
369
|
}
|
|
358
370
|
}
|
|
359
371
|
}
|
|
@@ -379,7 +391,12 @@ class Sigenergy extends utils.Adapter {
|
|
|
379
391
|
await this._processReadGroup(group, raw, 'inverter');
|
|
380
392
|
await this._sleep(100);
|
|
381
393
|
} catch (err) {
|
|
382
|
-
this.
|
|
394
|
+
if (!this._inverterUnsupportedGroups.has(group.startAddr)) {
|
|
395
|
+
this._inverterUnsupportedGroups.add(group.startAddr);
|
|
396
|
+
this.log.warn(`Inverter register read error at ${group.startAddr}: ${err.message}`);
|
|
397
|
+
} else {
|
|
398
|
+
this.log.debug(`[inverter] read error at ${group.startAddr}: ${err.message}`);
|
|
399
|
+
}
|
|
383
400
|
}
|
|
384
401
|
}
|
|
385
402
|
}
|
|
@@ -402,7 +419,12 @@ class Sigenergy extends utils.Adapter {
|
|
|
402
419
|
await this._processReadGroup(group, raw, 'acCharger');
|
|
403
420
|
await this._sleep(100);
|
|
404
421
|
} catch (err) {
|
|
405
|
-
this.
|
|
422
|
+
if (!this._acChargerUnsupportedGroups.has(group.startAddr)) {
|
|
423
|
+
this._acChargerUnsupportedGroups.add(group.startAddr);
|
|
424
|
+
this.log.warn(`AC Charger register read error at ${group.startAddr}: ${err.message}`);
|
|
425
|
+
} else {
|
|
426
|
+
this.log.debug(`[acCharger] read error at ${group.startAddr}: ${err.message}`);
|
|
427
|
+
}
|
|
406
428
|
}
|
|
407
429
|
}
|
|
408
430
|
}
|
|
@@ -425,7 +447,12 @@ class Sigenergy extends utils.Adapter {
|
|
|
425
447
|
await this._processReadGroup(group, raw, 'dcCharger');
|
|
426
448
|
await this._sleep(100);
|
|
427
449
|
} catch (err) {
|
|
428
|
-
this.
|
|
450
|
+
if (!this._dcChargerUnsupportedGroups.has(group.startAddr)) {
|
|
451
|
+
this._dcChargerUnsupportedGroups.add(group.startAddr);
|
|
452
|
+
this.log.warn(`DC Charger register read error at ${group.startAddr}: ${err.message}`);
|
|
453
|
+
} else {
|
|
454
|
+
this.log.debug(`[dcCharger] read error at ${group.startAddr}: ${err.message}`);
|
|
455
|
+
}
|
|
429
456
|
}
|
|
430
457
|
}
|
|
431
458
|
}
|
|
@@ -445,7 +472,12 @@ class Sigenergy extends utils.Adapter {
|
|
|
445
472
|
await this._processReadGroup(group, raw, 'pss');
|
|
446
473
|
await this._sleep(100);
|
|
447
474
|
} catch (err) {
|
|
448
|
-
this.
|
|
475
|
+
if (!this._pssUnsupportedGroups.has(group.startAddr)) {
|
|
476
|
+
this._pssUnsupportedGroups.add(group.startAddr);
|
|
477
|
+
this.log.warn(`PSS register read error at ${group.startAddr}: ${err.message}`);
|
|
478
|
+
} else {
|
|
479
|
+
this.log.debug(`[pss] read error at ${group.startAddr}: ${err.message}`);
|
|
480
|
+
}
|
|
449
481
|
}
|
|
450
482
|
}
|
|
451
483
|
}
|
|
@@ -465,7 +497,12 @@ class Sigenergy extends utils.Adapter {
|
|
|
465
497
|
await this._processReadGroup(group, raw, 'pid');
|
|
466
498
|
await this._sleep(100);
|
|
467
499
|
} catch (err) {
|
|
468
|
-
this.
|
|
500
|
+
if (!this._pidUnsupportedGroups.has(group.startAddr)) {
|
|
501
|
+
this._pidUnsupportedGroups.add(group.startAddr);
|
|
502
|
+
this.log.warn(`PID register read error at ${group.startAddr}: ${err.message}`);
|
|
503
|
+
} else {
|
|
504
|
+
this.log.debug(`[pid] read error at ${group.startAddr}: ${err.message}`);
|
|
505
|
+
}
|
|
469
506
|
}
|
|
470
507
|
}
|
|
471
508
|
}
|
|
@@ -506,26 +543,61 @@ class Sigenergy extends utils.Adapter {
|
|
|
506
543
|
}
|
|
507
544
|
}
|
|
508
545
|
|
|
546
|
+
/**
|
|
547
|
+
* Detect the Modbus protocol level supported by the device.
|
|
548
|
+
*
|
|
549
|
+
* Design notes (root cause of the former "pre-V2.6" misdetection):
|
|
550
|
+
* 1. Sigenergy firmware rejects reads that do not cover a complete data
|
|
551
|
+
* point. Probing addr 30088 (U64, qty 4) with qty=1 returns Modbus
|
|
552
|
+
* exception 0x02 (ILLEGAL DATA ADDRESS, "combination of reference
|
|
553
|
+
* number and transfer length is invalid"). Every probe therefore
|
|
554
|
+
* reads the FULL quantity of its data point.
|
|
555
|
+
* 2. Probes run in DESCENDING order and stop at the first success, so a
|
|
556
|
+
* single optional/legacy register can no longer cap the result.
|
|
557
|
+
* 3. Probe registers are valid for both "Hybrid Inv." and "PV Inv."
|
|
558
|
+
* (per protocol doc V2.9, table 5-1) and match the official version
|
|
559
|
+
* history: 30272 added in V2.9, 30276 in V2.8, 30194 in V2.7,
|
|
560
|
+
* 30088 in V2.6.
|
|
561
|
+
* 4. A Modbus exception (1/2) means "register not implemented" — that is
|
|
562
|
+
* a conclusive "no". A transport error/timeout is INCONCLUSIVE: it is
|
|
563
|
+
* retried once, and if detection stays inconclusive the whole run is
|
|
564
|
+
* repeated on the next poll cycle instead of reporting pre-V2.6.
|
|
565
|
+
*
|
|
566
|
+
* @returns {Promise<boolean>} true if detection was conclusive
|
|
567
|
+
*/
|
|
509
568
|
async _detectProtocolLevel() {
|
|
510
569
|
const plantId = this.config.plantId || 247;
|
|
511
570
|
const inverterId = this.config.inverterId || 1;
|
|
512
571
|
|
|
513
572
|
const probes = [
|
|
514
|
-
{ addr:
|
|
515
|
-
{ addr:
|
|
516
|
-
{ addr:
|
|
517
|
-
{ addr:
|
|
573
|
+
{ addr: 30272, qty: 2, level: 'V2.9' }, // PV total daily generation (U32)
|
|
574
|
+
{ addr: 30276, qty: 1, level: 'V2.8' }, // [Grid code] Rated frequency (U16)
|
|
575
|
+
{ addr: 30194, qty: 2, level: 'V2.7' }, // Third party inverter active power (S32)
|
|
576
|
+
{ addr: 30088, qty: 4, level: 'V2.6' }, // Plant PV total generation (U64)
|
|
518
577
|
];
|
|
519
578
|
|
|
520
579
|
let detectedLevel = null;
|
|
580
|
+
let inconclusive = false;
|
|
521
581
|
for (const probe of probes) {
|
|
522
|
-
|
|
523
|
-
|
|
582
|
+
if (this._stopped) {
|
|
583
|
+
return false;
|
|
584
|
+
}
|
|
585
|
+
const result = await this._probeRegister(plantId, probe);
|
|
586
|
+
if (result === 'supported') {
|
|
524
587
|
detectedLevel = probe.level;
|
|
525
|
-
} catch (err) {
|
|
526
|
-
this.log.debug(`[protocolProbe] addr=${probe.addr} (${probe.level}): ${err.message}`);
|
|
527
588
|
break;
|
|
528
589
|
}
|
|
590
|
+
if (result === 'error') {
|
|
591
|
+
inconclusive = true;
|
|
592
|
+
}
|
|
593
|
+
await this._sleep(100);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (!detectedLevel && inconclusive) {
|
|
597
|
+
this.log.warn(
|
|
598
|
+
'Protocol level detection inconclusive (communication errors during probing) — will retry on next poll cycle',
|
|
599
|
+
);
|
|
600
|
+
return false;
|
|
529
601
|
}
|
|
530
602
|
|
|
531
603
|
let firmwareVersion = 'unknown';
|
|
@@ -539,6 +611,48 @@ class Sigenergy extends utils.Adapter {
|
|
|
539
611
|
const levelStr = detectedLevel ? `>=${detectedLevel}` : 'pre-V2.6';
|
|
540
612
|
this.log.info(`Detected protocol level: ${levelStr} (firmware: ${firmwareVersion})`);
|
|
541
613
|
await this.setStateAsync('info.protocolLevel', { val: levelStr, ack: true });
|
|
614
|
+
return true;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Probe a single register (full data point) on the device.
|
|
619
|
+
*
|
|
620
|
+
* @param {number} slaveId - Modbus slave id
|
|
621
|
+
* @param {{addr: number, qty: number, level: string}} probe - probe definition
|
|
622
|
+
* @returns {Promise<'supported'|'unsupported'|'error'>} probe result
|
|
623
|
+
*/
|
|
624
|
+
async _probeRegister(slaveId, probe) {
|
|
625
|
+
for (let attempt = 1; attempt <= 2; attempt++) {
|
|
626
|
+
if (this._stopped) {
|
|
627
|
+
return 'error';
|
|
628
|
+
}
|
|
629
|
+
try {
|
|
630
|
+
await this.modbus.readInputRegisters(slaveId, probe.addr, probe.qty);
|
|
631
|
+
this.log.debug(`[protocolProbe] addr=${probe.addr} qty=${probe.qty} (${probe.level}): supported`);
|
|
632
|
+
return 'supported';
|
|
633
|
+
} catch (err) {
|
|
634
|
+
// modbus-serial sets err.modbusCode on Modbus exception responses
|
|
635
|
+
// (1 = ILLEGAL FUNCTION, 2 = ILLEGAL DATA ADDRESS, ...). An
|
|
636
|
+
// exception is an answer FROM the device => register not
|
|
637
|
+
// implemented on this firmware. Anything else (timeout, socket
|
|
638
|
+
// error) is a transport problem and proves nothing.
|
|
639
|
+
if (err && err.modbusCode !== undefined) {
|
|
640
|
+
this.log.debug(
|
|
641
|
+
`[protocolProbe] addr=${probe.addr} qty=${probe.qty} (${probe.level}): ` +
|
|
642
|
+
`not supported (Modbus exception ${err.modbusCode})`,
|
|
643
|
+
);
|
|
644
|
+
return 'unsupported';
|
|
645
|
+
}
|
|
646
|
+
this.log.debug(
|
|
647
|
+
`[protocolProbe] addr=${probe.addr} qty=${probe.qty} (${probe.level}): ` +
|
|
648
|
+
`transport error on attempt ${attempt}/2: ${err.message}`,
|
|
649
|
+
);
|
|
650
|
+
if (attempt < 2) {
|
|
651
|
+
await this._sleep(300);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return 'error';
|
|
542
656
|
}
|
|
543
657
|
|
|
544
658
|
async _readControlRegisters() {
|