iobroker.e3oncan 0.6.15 → 0.6.16

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 CHANGED
@@ -21,7 +21,7 @@ In parallel **reading of datapoints** (ReadByDid) is supported. Informations not
21
21
 
22
22
  **Writing of datapoints** via UDSonCAN (WriteByDid) is supported as well. By writing to datapoints it's possible to change setpoints, schedules and so on. It's even possible to add new schedules e.g. for domestic hot water circulation pump.
23
23
 
24
- Writing of data is triggered by storing the corresponding state with `Acknowledged` not checked (ack=false) - yes, it's that simple! The datapoint will be read again from device and stored in the state two seconds after writing. If state not get's acknowledged, please take a look to the logs.
24
+ Writing of data is triggered by storing the corresponding state with `Acknowledged` not checked (ack=false) - yes, it's that simple! The datapoint will be read again from device and stored in the state 2.5 seconds after writing. If state not get's acknowledged, please take a look to the logs.
25
25
 
26
26
  Writing is restricted to a set of datapoints using a **white list**. The list is stored in the info section of each device, e.g. at `e3oncan.0.vitocal.info.udsDidsWritable`. You can add more datapoints by editing this state. Make sure, **not** to check `Acknowledged` when saving the state.
27
27
 
@@ -39,13 +39,13 @@ A python based implementation of a pure listening approach using MQTT messaging
39
39
  * Currently only Linux based systems are supported.
40
40
  * CAN adapter is up and visible in system, e.g. as "can0" (use ifconfig to check).
41
41
  * Refer to open3e project for further details
42
- * **Make sure, open3e is not running during initial setup!** This could cause communication errors in both applications.
42
+ * **Make sure, no other UDSonCAN client (e.g. Open3Eclient.py) is running during initial setup!** This could cause communication errors in both applications.
43
43
 
44
44
  All services provided by this adapter are based on device list of your specific Viessmann E3 setup. Therefore you have to follow following steps for first setup:
45
45
 
46
46
  **Configuration**
47
47
  * When installation of adapter has finished a confuration dialog will show up to configure up to two CAN bus adapters (tab "CAN ADAPTER")
48
- * Edit name of adapter and check the "Connect to adapter" checkbox at least the external adapter
48
+ * Edit name of adapter and check the "Connect to adapter" checkbox at least for the external adapter
49
49
  * When you're done, press "SAVE" button to apply the changes. This step is **mandatory**. The instance will restart and connect to the CAN adapter.
50
50
  * Go to tab "LIST OF UDS DEVICES" and do a scan for devices available on bus by pressing the scan button. **This will take a few seconds.** You may watch the activities in a 2nd browser tab by looking on the logging info of the adapter.
51
51
  * You may change the naming of the devices at 2nd column. Those names will be used to store all collected data in ioBoker's object tree. Again press "SAVE" button when you did your changes.
@@ -65,11 +65,11 @@ You may use datapoints informations on tab "LIST OF DATAPOINTS" for reference (o
65
65
  | ID | Data| Unit |
66
66
  | ------|:--- |------|
67
67
  | 0x250 | Active Power L1, L2, L3, Total | W |
68
- | 0x252 | Reactive Power L1, L2, L3, Total | W |
68
+ | 0x252 | Reactive Power L1, L2, L3, Total | VA |
69
69
  | 0x254 | Current, L1, L2, L3, cosPhi | A, - |
70
70
  | 0x256 | Voltage, L1, L2, L3, Frequency | V, Hz |
71
71
  | 0x258 | Cumulated Import, Export | kWh |
72
- | 0x25A | Total Active Power, Total Reactive Power | W |
72
+ | 0x25A | Total Active Power, Total Reactive Power | W, VA |
73
73
  | 0x25C | Cumulated Import | kWh |
74
74
 
75
75
  # Hints and limitations
@@ -102,6 +102,10 @@ Yes, that is possible under certain conditions:
102
102
  Placeholder for the next version (at the beginning of the line):
103
103
  ### **WORK IN PROGRESS**
104
104
  -->
105
+ ### 0.6.16 (2024-01-27)
106
+ * (MyHomeMyData) Improvements based on findings in review as of 2024-01-25
107
+ * (MyHomeMyData) Checkbox for data collectiton on internal bus is now checked per default
108
+
105
109
  ### 0.6.15 (2024-01-23)
106
110
  * (MyHomeMyData) Fix for Utf8 codec for handling of special characters, e.g. umlauts
107
111
 
@@ -560,7 +560,7 @@
560
560
  "tooltip": "Activate communication",
561
561
  "filter": false,
562
562
  "sort": false,
563
- "default": false
563
+ "default": true
564
564
  },
565
565
  { "type": "selectSendTo",
566
566
  "title": "Select device",
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "e3oncan",
4
- "version": "0.6.15",
4
+ "version": "0.6.16",
5
5
  "news": {
6
+ "0.6.16": {
7
+ "en": "Improvements based on findings in review as of 2024-01-25\nCheckbox for data collectiton on internal bus is now checked per default",
8
+ "de": "Verbesserungen auf der Grundlage der Ergebnisse in der Überprüfung ab 2024-01-25\nCheckbox für Datensammler im internen Bus wird nun standardmäßig überprüft",
9
+ "ru": "Совершенствование на основе результатов, рассмотренных на 2024-01-25 годы\nCheckbox для сбора данных на внутреннем автобусе теперь проверяется по умолчанию",
10
+ "pt": "Aperfeiçoamentos baseados em achados em revisão a partir de 2024-01-25\nCaixa de seleção para coleta de dados no ônibus interno é agora verificada por padrão",
11
+ "nl": "Verbeteringen op basis van de resultaten van het onderzoek per 2024-01-25\nCheckbox voor gegevensverzameling op interne bus is nu standaard aangevinkt",
12
+ "fr": "Améliorations fondées sur les conclusions de l'examen en 2024-01-25\nLa case à cocher pour les données collectiton sur le bus interne est maintenant cochée par défaut",
13
+ "it": "Miglioramenti basati sui risultati in esame a partire dal 2024-01-25\nLa casella di controllo per i dati collettivi sul bus interno è ora controllata per impostazione predefinita",
14
+ "es": "Mejoras basadas en los resultados examinados al 2024-01-25\nCheckbox for data collectiton on internal bus is now check per default",
15
+ "pl": "Poprawki oparte na ustaleniach w przeglądzie z 2024- 01- 25\nSkrzynka kontrolna dla kolekcji danych w autobusie wewnętrznym jest teraz sprawdzana na domyślnym",
16
+ "uk": "Удосконалення на основі пошуку в рецензії на 2024-01-25\nCheckbox для збору даних у внутрішньому автобусі тепер перевіряється за замовчуванням",
17
+ "zh-cn": "根据截至2024-01-25年审查结果作出的改进\n内部总线上数据集合的复选框现在按默认检查"
18
+ },
6
19
  "0.6.15": {
7
20
  "en": "Fix for Utf8 codec for handling of special characters, e.g. umlauts",
8
21
  "de": "Fix für Utf8-Codec zum Umgang mit Sonderzeichen, z.B. umlauts",
@@ -80,19 +93,6 @@
80
93
  "pl": "Usunięto kod dla Rawmode ponieważ nigdy nie jest aktywowany",
81
94
  "uk": "Видалити код для Rawmode, тому що він ніколи не активований",
82
95
  "zh-cn": "删除了Rawmode的代码,因为它从未被激活"
83
- },
84
- "0.6.9": {
85
- "en": "Bugfix: Only Linux is supported",
86
- "de": "Bugfix: Nur Linux wird unterstützt",
87
- "ru": "Исправление: Только Linux поддерживается",
88
- "pt": "Bugfix: Apenas o Linux é suportado",
89
- "nl": "Bugfix: Alleen Linux wordt ondersteund",
90
- "fr": "Correction : Seul Linux est pris en charge",
91
- "it": "Bugfix: Solo Linux è supportato",
92
- "es": "Bugfix: Sólo Linux es compatible",
93
- "pl": "Bugfix: Tylko Linux jest obsługiwany",
94
- "uk": "Помилки: Тільки Linux підтримується",
95
- "zh-cn": "错误修正 : 仅支持 Linux"
96
96
  }
97
97
  },
98
98
  "title": "Viessmann E3 CAN do",
package/lib/canCollect.js CHANGED
@@ -57,7 +57,7 @@ class collect {
57
57
  await this.storage.setOpMode('standby');
58
58
 
59
59
  // Stop Timeout:
60
- if (this.timeoutHandle) await clearTimeout(this.timeoutHandle);
60
+ if (this.timeoutHandle) await ctx.clearTimeout(this.timeoutHandle);
61
61
  this.timeoutHandle = null;
62
62
 
63
63
  this.stat.state = 'stopped';
@@ -71,10 +71,6 @@ class collect {
71
71
  }
72
72
  }
73
73
 
74
- sleep(milliseconds) {
75
- return new Promise(resolve => setTimeout(resolve, milliseconds));
76
- }
77
-
78
74
  async msgCollect(ctx, msg) {
79
75
 
80
76
  if (await this.storage.getOpMode() == 'standby') return; // No communication in mode 'standby'
@@ -109,7 +105,7 @@ class collect {
109
105
  this.data.databytes = this.data.databytes.concat(candata.slice(1));
110
106
  if (this.data.databytes.length >= this.data.len) {
111
107
  // All data received
112
- if (this.timeoutHandle) await clearTimeout(this.timeoutHandle);
108
+ if (this.timeoutHandle) await ctx.clearTimeout(this.timeoutHandle);
113
109
  this.stat.cntCommOk += 1;
114
110
  if (!(this.data.did in this.ts)) { this.ts[this.data.did] = tsNow; }
115
111
  if ( (this.config.delay == 0) || ((tsNow >= this.ts[this.data.did])) ) {
@@ -162,7 +158,7 @@ class collect {
162
158
  this.data.databytes = candata.slice(5);
163
159
  this.data.len = candata[4];
164
160
  }
165
- this.timeoutHandle = setTimeout(this.onTimeout, this.config.timeout, ctx, this);
161
+ this.timeoutHandle = ctx.setTimeout(this.onTimeout, this.config.timeout, ctx, this);
166
162
  this.data.collecting = true;
167
163
  break;
168
164
  case 0xb5:
@@ -181,7 +177,7 @@ class collect {
181
177
  this.data.D0expected = candata[0]+1;
182
178
  this.data.databytes = candata.slice(4);
183
179
  this.data.len = D3-0xb0;
184
- this.timeoutHandle = setTimeout(this.onTimeout, this.config.timeout, ctx, this);
180
+ this.timeoutHandle = ctx.setTimeout(this.onTimeout, this.config.timeout, ctx, this);
185
181
  this.data.collecting = true;
186
182
  break;
187
183
  default:
package/lib/canUds.js CHANGED
@@ -9,21 +9,21 @@ class scheduleLoop {
9
9
  this.schedHandle = null;
10
10
  }
11
11
 
12
- async startSchedule() {
12
+ async startSchedule(ctx) {
13
13
  if (this.schedule == 0) {
14
14
  await this.ctxGlobal.log.silly('UDS schedule one time: '+this.ctxLocal.canIDhex+'.'+JSON.stringify(this.dids));
15
15
  await this.ctxLocal.pushCmnd(this.ctxGlobal, 'read', this.dids);
16
16
  this.schedHandle = null;
17
17
  } else {
18
- this.schedHandle = setInterval(async () => {
18
+ this.schedHandle = ctx.setInterval(async () => {
19
19
  await this.loop();
20
20
  }, this.schedule*1000);
21
21
  }
22
22
  }
23
23
 
24
- async stopSchedule() {
24
+ async stopSchedule(ctx) {
25
25
  try {
26
- if (this.schedHandle) await clearInterval(this.schedHandle);
26
+ if (this.schedHandle) await ctx.clearInterval(this.schedHandle);
27
27
  await this.ctxGlobal.log.silly('UDS schedule stopped: '+String(this.schedule)+' '+this.ctxLocal.canIDhex+'.'+JSON.stringify(this.dids));
28
28
  } catch (e) {
29
29
  // Dod nothing
@@ -110,7 +110,6 @@ class uds {
110
110
  type: 'channel',
111
111
  common: {
112
112
  name: this.config.stateBase+' commands',
113
- role: 'device'
114
113
  },
115
114
  native: {},
116
115
  });
@@ -139,7 +138,7 @@ class uds {
139
138
  if (opMode == 'normal') {
140
139
  for (const sched of Object.values(this.schedules)) {
141
140
  // Start schedules on startup and do one-time schedules
142
- await sched.startSchedule();
141
+ await sched.startSchedule(ctx);
143
142
  }
144
143
  }
145
144
  if (opMode == 'normal') {
@@ -147,7 +146,7 @@ class uds {
147
146
  } else {
148
147
  await ctx.log.silly('UDS worker started in mode '+opMode+' on '+this.config.stateBase);
149
148
  }
150
- this.cmndsHandle = setInterval(async () => {
149
+ this.cmndsHandle = ctx.setInterval(async () => {
151
150
  await this.cmndsLoop(ctx);
152
151
  }, this.cmndsUpdateTime);
153
152
  }
@@ -164,18 +163,18 @@ class uds {
164
163
 
165
164
  // Stop loops:
166
165
  for (const sched of Object.values(this.schedules)) {
167
- await sched.stopSchedule();
166
+ await sched.stopSchedule(ctx);
168
167
  }
169
- if (this.cmndsHandle) await clearInterval(this.cmndsHandle);
168
+ if (this.cmndsHandle) await ctx.clearInterval(this.cmndsHandle);
170
169
 
171
170
  // Stop Timeout:
172
- if (this.timeoutHandle) await clearTimeout(this.timeoutHandle);
171
+ if (this.timeoutHandle) await ctx.clearTimeout(this.timeoutHandle);
173
172
  this.timeoutHandle = null;
174
173
 
175
174
  // Stop worker:
176
175
  this.callback = null;
177
176
  if (opMode == 'normal') {
178
- await ctx.unsubscribeStates(ctx.namespace+'.'+this.config.stateBase+'.*');
177
+ ctx.unsubscribeStates(ctx.namespace+'.'+this.config.stateBase+'.*');
179
178
  await ctx.log.info('UDS worker stopped on '+this.config.stateBase);
180
179
  } else {
181
180
  await ctx.log.silly('UDS worker stopped in mode '+opMode+' on '+this.config.stateBase);
@@ -201,12 +200,12 @@ class uds {
201
200
  this.data.state = comState;
202
201
  }
203
202
 
204
- async setDidDone(coolDownTime) {
203
+ async setDidDone(ctx, coolDownTime) {
205
204
  // Finalize communication for recent did
206
205
  this.coolDownTs = new Date().getTime()+coolDownTime;
207
206
  if (this.cmndsQueue.length == 0) this.busy = false;
208
207
  await this.setComState(0);
209
- if (this.timeoutHandle) await clearTimeout(this.timeoutHandle);
208
+ if (this.timeoutHandle) await ctx.clearTimeout(this.timeoutHandle);
210
209
  }
211
210
 
212
211
  async setDidStart(ctx, did, mode, len) {
@@ -228,9 +227,9 @@ class uds {
228
227
  }
229
228
  const tsNow = new Date().getTime();
230
229
  const minWaiting = this.coolDownTs - tsNow;
231
- if (minWaiting > 0) await this.sleep(minWaiting);
230
+ if (minWaiting > 0) await this.sleep(ctx, minWaiting);
232
231
  this.busy = true;
233
- this.timeoutHandle = await setTimeout(this.onTimeout, this.config.timeout, ctx, this);
232
+ this.timeoutHandle = await ctx.setTimeout(this.onTimeout, this.config.timeout, ctx, this);
234
233
  this.data.did = did;
235
234
  this.data.tsRequest = tsNow;
236
235
  }
@@ -269,8 +268,8 @@ class uds {
269
268
  }
270
269
  }
271
270
 
272
- sleep(milliseconds) {
273
- return new Promise(resolve => setTimeout(resolve, milliseconds));
271
+ sleep(ctx, milliseconds) {
272
+ return new Promise(resolve => ctx.setTimeout(resolve, milliseconds));
274
273
  }
275
274
 
276
275
  async cmndsLoop(ctx) {
@@ -309,7 +308,7 @@ class uds {
309
308
  ctxLocal.stat.cntCommTimeoutPerDid[did] = 1;
310
309
  }
311
310
  if (ctxLocal.callback) await ctxLocal.callback(ctxGlobal, ctxLocal, ['timeout', {'did':ctxLocal.data.did,'didInfo':{'id':'','len':0},'val':''}]);
312
- await ctxLocal.setDidDone(0);
311
+ await ctxLocal.setDidDone(ctxGlobal, 0);
313
312
  }
314
313
 
315
314
  async onUdsStateChange(ctx, ctxWorker, id, state) {
@@ -369,7 +368,7 @@ class uds {
369
368
  byteArr = await this.storage.encodeDataCAN(ctx, this, did, await JSON.parse(state.val));
370
369
  if (byteArr) {
371
370
  await this.pushCmnd(ctx, 'write', [[did,byteArr]]);
372
- setTimeout(function(ctxWorker,did){ctxWorker.cmndsQueue.push({'mode':'read', 'did': did});},2500,this,did); // Read value after 2500 ms
371
+ ctx.setTimeout(function(ctxWorker,did){ctxWorker.cmndsQueue.push({'mode':'read', 'did': did});},2500,this,did); // Read value after 2500 ms
373
372
  } else {
374
373
  ctx.log.error('User command UDS WriteByDid on '+this.config.stateBase+': Encoding of data failed.');
375
374
  }
@@ -382,7 +381,7 @@ class uds {
382
381
  byteArr = this.storage.toByteArray(await JSON.parse(state.val));
383
382
  if (byteArr) {
384
383
  await this.pushCmnd(ctx, 'write', [[did,byteArr]]);
385
- setTimeout(function(ctxWorker,did){ctxWorker.cmndsQueue.push({'mode':'read', 'did': did});},2500,this,did); // Read value after 2500 ms
384
+ ctx.setTimeout(function(ctxWorker,did){ctxWorker.cmndsQueue.push({'mode':'read', 'did': did});},2500,this,did); // Read value after 2500 ms
386
385
  } else {
387
386
  ctx.log.error('User command UDS WriteByDid on '+this.config.stateBase+': Encoding of data failed.');
388
387
  }
@@ -397,7 +396,7 @@ class uds {
397
396
  byteArr = await this.storage.encodeDataCAN(ctx, this, did, await JSON.parse(state.val));
398
397
  if (byteArr) {
399
398
  await this.pushCmnd(ctx, 'write', [[did,byteArr]]);
400
- setTimeout(function(ctxWorker,did){ctxWorker.cmndsQueue.push({'mode':'read', 'did': did});},2500,this,did); // Read value after 2500 ms
399
+ ctx.setTimeout(function(ctxWorker,did){ctxWorker.cmndsQueue.push({'mode':'read', 'did': did});},2500,this,did); // Read value after 2500 ms
401
400
  } else {
402
401
  ctx.log.error('User command UDS WriteByDid on '+this.config.stateBase+': Encoding of data failed.');
403
402
  }
@@ -434,7 +433,7 @@ class uds {
434
433
  byteArr = await ctxWorker.storage.encodeDataCAN(ctx, ctxWorker, did, treeDict);
435
434
  if (byteArr) {
436
435
  await ctxWorker.pushCmnd(ctx, 'write', [[did,byteArr]]);
437
- setTimeout(function(ctxWorker,did){ctxWorker.cmndsQueue.push({'mode':'read', 'did': did});},2500,ctxWorker,did); // Read value after 2500 ms
436
+ ctx.setTimeout(function(ctxWorker,did){ctxWorker.cmndsQueue.push({'mode':'read', 'did': did});},2500,ctxWorker,did); // Read value after 2500 ms
438
437
  } else {
439
438
  ctx.log.error('User command UDS WriteByDid on '+ctxWorker.config.stateBase+': Encoding of data failed.');
440
439
  }
@@ -540,7 +539,7 @@ class uds {
540
539
  } else {
541
540
  ctx.log.error('UDS worker error on '+this.config.stateBase+': Negative response reading did '+String(this.data.did)+'. Code=0x'+Number(candata[3]).toString(16));
542
541
  }
543
- await this.setDidDone(0);
542
+ await this.setDidDone(ctx, 0);
544
543
  break;
545
544
  }
546
545
  if ( (candata.length == 8) && ((candata[0] >> 4) == 0) && (candata[1] == this.readByDidProt.SIDrx) ) {
@@ -554,7 +553,7 @@ class uds {
554
553
  this.data.len = candata[0]-3;
555
554
  this.data.databytes = candata.slice(4,4+this.data.len);
556
555
  this.storage.decodeDataCAN(ctx, this, this.data.did, this.data.databytes.slice(0,this.data.len));
557
- await this.setDidDone(0);
556
+ await this.setDidDone(ctx, 0);
558
557
  break;
559
558
  } else {
560
559
  // Did does not match
@@ -564,7 +563,7 @@ class uds {
564
563
  } else {
565
564
  ctx.log.error('UDS worker on '+this.config.stateBase+': Did mismatch MF. Expected='+String(this.data.did)+'; Received='+String(didRx));
566
565
  }
567
- await this.setDidDone(1000);
566
+ await this.setDidDone(ctx, 1000);
568
567
  break;
569
568
  }
570
569
  }
@@ -589,7 +588,7 @@ class uds {
589
588
  } else {
590
589
  ctx.log.error('UDS worker on '+this.config.stateBase+': Did mismatch MF. Expected='+String(this.data.did)+'; Received='+String(didRx));
591
590
  }
592
- await this.setDidDone(1000);
591
+ await this.setDidDone(ctx, 1000);
593
592
  break;
594
593
  }
595
594
  }
@@ -600,7 +599,7 @@ class uds {
600
599
  }
601
600
  await this.calcStat();
602
601
  this.stat.cntCommBadProtocol += 1;
603
- await this.setDidDone(2500);
602
+ await this.setDidDone(ctx, 2500);
604
603
  break;
605
604
 
606
605
  case 2: // waitForCFrbd
@@ -614,7 +613,7 @@ class uds {
614
613
  await this.calcStat();
615
614
  ctx.log.silly('UDS worker on '+this.config.stateBase+': MF completed. candata: '+this.storage.arr2Hex(candata));
616
615
  this.storage.decodeDataCAN(ctx, this, this.data.did, this.data.databytes.slice(0,this.data.len));
617
- await this.setDidDone(0);
616
+ await this.setDidDone(ctx, 0);
618
617
  } else {
619
618
  // More data to come
620
619
  this.data.D0 += 1;
@@ -628,7 +627,7 @@ class uds {
628
627
  ctx.log.error('UDS worker on '+this.config.stateBase+': Bad frame. candata: '+this.storage.arr2Hex(candata));
629
628
  }
630
629
  this.stat.cntCommBadProtocol += 1;
631
- await this.setDidDone(2500);
630
+ await this.setDidDone(ctx, 2500);
632
631
  }
633
632
  break;
634
633
 
@@ -637,7 +636,7 @@ class uds {
637
636
  // Negative response
638
637
  this.stat.cntCommNR += 1;
639
638
  ctx.log.error('UDS worker error on '+this.config.stateBase+': Negative response writing did '+String(this.data.did)+'. Code=0x'+Number(candata[3]).toString(16));
640
- await this.setDidDone(0);
639
+ await this.setDidDone(ctx, 0);
641
640
  break;
642
641
  }
643
642
  if ( (candata.length == 8) && (candata[0] == 0x03) && (candata[1] == this.writeByDidProt.SIDrx) ) {
@@ -649,7 +648,7 @@ class uds {
649
648
  ctx.log.silly('UDS worker on '+this.config.stateBase+': writeByDid SF confirmation received.');
650
649
  await this.calcStat();
651
650
  this.storage.storeStatistics(ctx, this, false);
652
- await this.setDidDone(0);
651
+ await this.setDidDone(ctx, 0);
653
652
  break;
654
653
  } else {
655
654
  // Did does not match
@@ -657,14 +656,14 @@ class uds {
657
656
  ctx.log.error('UDS worker on '+this.config.stateBase+': Did mismatch writeByDid SF. Expected='+String(this.data.did)+'; Received='+String(didRx));
658
657
  await this.calcStat();
659
658
  this.storage.storeStatistics(ctx, this, true);
660
- await this.setDidDone(1000);
659
+ await this.setDidDone(ctx, 1000);
661
660
  break;
662
661
  }
663
662
  }
664
663
  ctx.log.error('UDS worker on '+this.config.stateBase+': Bad frame for writeByDid SF. candata: '+this.storage.arr2Hex(candata));
665
664
  this.stat.cntCommBadProtocol += 1;
666
665
  await this.calcStat();
667
- await this.setDidDone(2500);
666
+ await this.setDidDone(ctx, 2500);
668
667
  break;
669
668
 
670
669
  case 4: // waitForFFFwbd
@@ -672,7 +671,7 @@ class uds {
672
671
  // Negative response
673
672
  this.stat.cntCommNR += 1;
674
673
  ctx.log.error('UDS worker error on '+this.config.stateBase+': Negative response writing did '+String(this.data.did)+'. Code=0x'+Number(candata[3]).toString(16));
675
- await this.setDidDone(0);
674
+ await this.setDidDone(ctx, 0);
676
675
  break;
677
676
  }
678
677
  if ( (candata.length == 8) && (candata[0] == 0x30) && (candata[1] == 0x00) ) {
@@ -682,7 +681,7 @@ class uds {
682
681
  if ((ST<20) || (ST>127)) ST=50; // Accept ST 20 .. 127 ms. Default to 50 ms.
683
682
  while (this.data.txPos < this.data.len) {
684
683
  // More data to send
685
- await this.sleep(ST);
684
+ await this.sleep(ctx, ST);
686
685
  const frame = [this.data.D0].concat(this.data.databytes.slice(this.data.txPos,this.data.txPos+7));
687
686
  await this.sendFrame(ctx, frame);
688
687
  this.data.txPos += 7;
@@ -695,7 +694,7 @@ class uds {
695
694
  ctx.log.error('UDS worker on '+this.config.stateBase+': Bad frame for writeByDid MF. candata: '+this.storage.arr2Hex(candata));
696
695
  this.stat.cntCommBadProtocol += 1;
697
696
  await this.calcStat();
698
- await this.setDidDone(2500);
697
+ await this.setDidDone(ctx, 2500);
699
698
  break;
700
699
 
701
700
  default:
@@ -705,7 +704,7 @@ class uds {
705
704
  } else {
706
705
  ctx.log.error('UDS worker on '+this.config.stateBase+': Bad state value: '+String(await this.getComState()));
707
706
  }
708
- await this.setDidDone(2500);
707
+ await this.setDidDone(ctx, 2500);
709
708
  }
710
709
  this.commBusy = false;
711
710
  }
@@ -208,7 +208,7 @@ describe('codecs.js => O3EInt8().encode()', () => {
208
208
  codecEncode('Positive Number, scale=10, signed=false', [0xfb], E3.O3Ecodecs.O3EInt8, 1, 'test5', {scale:10.0,signed:false,offset: 0}, 25.1);
209
209
  });
210
210
 
211
- describe('codecs.js => O3EInt16().decode()', () => {
211
+ describe('codecs.js => O3EInt16().encode()', () => {
212
212
  codecEncode('Positive Number, scale=10, signed=true ', [0x32,0x00], E3.O3Ecodecs.O3EInt16, 2, 'test1', {scale:10.0,signed:true, offset: 0}, 5);
213
213
  codecEncode('Positive Number, scale=10, signed=true ', [0xff,0x7f], E3.O3Ecodecs.O3EInt16, 2, 'test2', {scale:10.0,signed:true, offset: 0}, (2**15-1)/10);
214
214
  codecEncode('Negative Number, scale=10, signed=true ', [0x00,0x80], E3.O3Ecodecs.O3EInt16, 2, 'test3', {scale:10.0,signed:true, offset: 0}, -(2**15)/10);
package/lib/storage.js CHANGED
@@ -136,7 +136,6 @@ class storage {
136
136
  type: 'device',
137
137
  common: {
138
138
  name: this.config.stateBase,
139
- role: 'device'
140
139
  },
141
140
  native: {},
142
141
  });
@@ -145,7 +144,6 @@ class storage {
145
144
  type: 'channel',
146
145
  common: {
147
146
  name: this.config.stateBase+' informations',
148
- role: 'channel'
149
147
  },
150
148
  native: {},
151
149
  });
@@ -154,7 +152,7 @@ class storage {
154
152
  type: 'state',
155
153
  common: {
156
154
  name: this.config.stateBase+' statistics about communication',
157
- role: 'state',
155
+ role: 'info.status',
158
156
  type: 'json',
159
157
  read: true,
160
158
  write: true,
@@ -169,7 +167,6 @@ class storage {
169
167
  type: 'channel',
170
168
  common: {
171
169
  name: this.config.stateBase+' JSON',
172
- role: 'channel for json data'
173
170
  },
174
171
  native: {},
175
172
  });
@@ -178,7 +175,6 @@ class storage {
178
175
  type: 'channel',
179
176
  common: {
180
177
  name: this.config.stateBase+' TREE',
181
- role: 'channel for tree data'
182
178
  },
183
179
  native: {},
184
180
  });
@@ -187,7 +183,6 @@ class storage {
187
183
  type: 'channel',
188
184
  common: {
189
185
  name: this.config.stateBase+' RAW',
190
- role: 'channel for raw data'
191
186
  },
192
187
  native: {},
193
188
  });
@@ -230,7 +225,7 @@ class storage {
230
225
  if (['standby','normal','udsDidScan'].includes(await this.getOpMode())) {
231
226
  const ts = new Date().getTime();
232
227
  if ( (!forceStore) && (ts < ctxWorker.stat.nextTs) ) return; // Min. time step not reached. Do not store.
233
- if (ctxWorker.stat) await ctx.setStateAsync(ctxWorker.config.stateBase+'.info.'+this.config.statId, JSON.stringify(ctxWorker.stat), true);
228
+ if (ctxWorker.stat) ctx.setStateAsync(ctxWorker.config.stateBase+'.info.'+this.config.statId, JSON.stringify(ctxWorker.stat), true);
234
229
  ctxWorker.stat.nextTs = ts+ctxWorker.stat.tsMinStep;
235
230
  }
236
231
  }
@@ -262,7 +257,7 @@ class storage {
262
257
  common: {
263
258
  name: idStr,
264
259
  type: 'string',
265
- role: 'state',
260
+ role: 'json',
266
261
  read: true,
267
262
  write: true,
268
263
  },
@@ -280,8 +275,8 @@ class storage {
280
275
  if (typeof(obj) == 'object') {
281
276
  if (Object.keys(obj).length <= 100) {
282
277
  for (const [key, itm] of Object.entries(obj)) {
283
- await storeObjectTree(ctx, String(stateId)+'.'+String(key).replace('.','_'),itm);
284
- // No '.' in state id allowed to avoid sub structure
278
+ await storeObjectTree(ctx, String(stateId)+'.'+String(key).replace(ctx.FORBIDDEN_CHARS,'_').replace('.','_'),itm);
279
+ // No FORBIDDEN_CHARS and no '.' in state id allowed
285
280
  }
286
281
  } else {
287
282
  ctx.log.error('Did valuation aborted. Too many members ('+String(Object.keys(obj).length)+') '+stateId+'.'+String(did));
@@ -307,7 +302,8 @@ class storage {
307
302
  ctx.log.warn('Could not retreive codec for '+ctxWorker.config.stateBase+'.'+String(did)+'. err='+e.message);
308
303
  codec = 'RawCodec';
309
304
  }
310
- idStr = cdi.id.replace('.','_'); // No '.' in state allowed to avoid sub structure
305
+ idStr = cdi.id.replace(ctx.FORBIDDEN_CHARS,'_').replace('.','_');
306
+ // No FORBIDDEN_CHARS and no '.' in state allowed
311
307
  common = true;
312
308
  try {
313
309
  val = await codec.decode(data);
package/lib/udsScan.js CHANGED
@@ -210,14 +210,14 @@ class udsScan {
210
210
  for (const baseAddr of Object(this.udsScanAddrRange).values()) {
211
211
  for (const addr of Object(range(Number(this.udsScanAddrSpan), Number(baseAddr))).values()) {
212
212
  await this.startupScanUdsDevice(ctx, addr);
213
- await this.sleep(50);
213
+ await this.sleep(ctx, 50);
214
214
  }
215
215
  }
216
216
  // eslint-disable-next-line no-case-declarations
217
217
  const tsAbort = new Date().getTime() + this.udsMaxTrialsDevScan*this.udsTimeoutDevScan+250;
218
218
  await ctx.log.info('UDS device scan: Waiting for scans to complete.');
219
219
  while ( (this.cntUdsScansActive > 0) && (new Date().getTime() < tsAbort) ) {
220
- await this.sleep(100);
220
+ await this.sleep(ctx, 100);
221
221
  }
222
222
 
223
223
  // Stop all scan workers:
@@ -304,14 +304,14 @@ class udsScan {
304
304
  const dids = range(udsMaxCntDids, 256);
305
305
  for (const addr of Object(udsAddrs).values()) {
306
306
  await this.startupScanUdsDids(ctx, addr, dids);
307
- await this.sleep(50);
307
+ await this.sleep(ctx, 50);
308
308
  }
309
309
  let cntDoneLast = -1;
310
310
  await logStatus(ctx, this);
311
311
  let ts = new Date().getTime();
312
312
  const tsAbort = ts + this.udsScanDidsCntTotal*500;
313
313
  while ( (this.cntUdsScansActive > 0) && (new Date().getTime() < tsAbort) ) {
314
- await this.sleep(100);
314
+ await this.sleep(ctx, 100);
315
315
  if ((new Date().getTime() - ts) >= 10000) {
316
316
  ts += 10000;
317
317
  await logStatus(ctx, this);
@@ -342,8 +342,8 @@ class udsScan {
342
342
  }
343
343
  }
344
344
 
345
- sleep(milliseconds) {
346
- return new Promise(resolve => setTimeout(resolve, milliseconds));
345
+ sleep(ctx, milliseconds) {
346
+ return new Promise(resolve => ctx.setTimeout(resolve, milliseconds));
347
347
  }
348
348
 
349
349
  }
package/main.js CHANGED
@@ -257,6 +257,7 @@ class E3oncan extends utils.Adapter {
257
257
  */
258
258
  async onUnload(callback) {
259
259
  try {
260
+ const tStart = new Date().getTime();
260
261
  this.stoppingInstance = true;
261
262
  // Stop UDS workers:
262
263
  for (const worker of Object.values(this.E3UdsWorkers)) await worker.stop(this);
@@ -273,6 +274,7 @@ class E3oncan extends utils.Adapter {
273
274
  // @ts-ignore
274
275
  await this.disconnectFromCan(this.channelInt,this.config.canIntName);
275
276
  this.setState('info.connection', false, true);
277
+ this.log.debug('onUnload() took '+String(new Date().getTime()-tStart)+' ms to complete.');
276
278
 
277
279
  callback();
278
280
  } catch (e) {
@@ -320,7 +322,7 @@ class E3oncan extends utils.Adapter {
320
322
  }
321
323
 
322
324
  sleep(milliseconds) {
323
- return new Promise(resolve => setTimeout(resolve, milliseconds));
325
+ return new Promise(resolve => this.setTimeout(resolve, milliseconds));
324
326
  }
325
327
 
326
328
  // If you need to accept messages in your adapter, uncomment the following block and the corresponding line in the constructor.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.e3oncan",
3
- "version": "0.6.15",
3
+ "version": "0.6.16",
4
4
  "description": "Collect data on CAN bus for Viessmann E3 devices, e.g. Vitocal, Vitocharge, Energy Meter E380",
5
5
  "author": {
6
6
  "name": "Juergen",