iobroker.e3oncan 0.6.13 → 0.6.14
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 +17 -7
- package/io-package.json +14 -14
- package/lib/didsE3Writables.json +15 -0
- package/lib/storage.js +4 -2
- package/main.js +35 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,18 +15,22 @@
|
|
|
15
15
|
# Basic concept
|
|
16
16
|
Viessmann E3 series devices (One Base) are doing a lot of data exchange on CAN bus.
|
|
17
17
|
|
|
18
|
-
This adapter can listen to this communication and extract many useful information. The often used energy meter E380 CA is
|
|
18
|
+
This adapter can listen to this communication and extract many useful information. The often used energy meter E380 CA also is supported.
|
|
19
19
|
|
|
20
|
-
In parallel
|
|
20
|
+
In parallel **reading of datapoints** (ReadByDid) is supported. Informations not available via listening can be actively requested. The UDSonCAN protocol is also used by other equipment, e.g. by well known WAGO gateway.
|
|
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
|
-
|
|
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.
|
|
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
|
|
|
28
28
|
During first start of adapter instance a device scan will be done providing a list of all available devices for configuration dialog.
|
|
29
|
-
A scan for datapoints of each device
|
|
29
|
+
A scan for datapoints of each device should be done during first setup.
|
|
30
|
+
|
|
31
|
+
Important parts of this adpater are based on the project [open3e](https://github.com/open3e).
|
|
32
|
+
|
|
33
|
+
A python based implementation of a pure listening approach using MQTT messaging is also availabe, see [E3onCAN](https://github.com/MyHomeMyData/E3onCAN).
|
|
30
34
|
|
|
31
35
|
# Getting started
|
|
32
36
|
|
|
@@ -85,8 +89,8 @@ You may use datapoints informations on tab "LIST OF DATAPOINTS" for reference (o
|
|
|
85
89
|
|
|
86
90
|
## What is different to open3e project?
|
|
87
91
|
* Obviously, the main differece is the direct integration to ioBroker. Configuration can be done via dialogs, data get's directly listed in object trees.
|
|
88
|
-
* **WriteByDid is supported for all data types** but restricted to datapoints on device specific white list, see info section of devices. You need to do a datapoint scan to enable writing. Writing of data is triggered by storing the datapoint with ack=false - yes, it's that simple! The datapoint will be read again from device two seconds after writing. If datapoint not get's acknowledged, please take a look to the logs.
|
|
89
92
|
* In addition to open3e real time collecting of data via listening is supported.
|
|
93
|
+
* Writing of data is much simpler. Just change the data in corresponding state and press Save button.
|
|
90
94
|
|
|
91
95
|
## May open3e be used in parallel?
|
|
92
96
|
Yes, that is possible under certain conditions:
|
|
@@ -98,6 +102,12 @@ Yes, that is possible under certain conditions:
|
|
|
98
102
|
Placeholder for the next version (at the beginning of the line):
|
|
99
103
|
### **WORK IN PROGRESS**
|
|
100
104
|
-->
|
|
105
|
+
### 0.6.14 (2024-01-22)
|
|
106
|
+
* (MyHomeMyData) Replace '.' by '_' in datapoint ids to avoid unwanted sub structure in data states
|
|
107
|
+
* (MyHomeMyData) Added more informations about white list for writables in Readme.
|
|
108
|
+
* (MyHomeMyData) Recognize loss of CAN connection.
|
|
109
|
+
* (MyHomeMyData) Improved handling of info.connection.
|
|
110
|
+
|
|
101
111
|
### 0.6.13 (2024-01-20)
|
|
102
112
|
* (MyHomeMyData) Now supports multiple definitions of same schedule on a device
|
|
103
113
|
* (MyHomeMyData) Added unit test cases for codecs
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "e3oncan",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.14",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.6.14": {
|
|
7
|
+
"en": "Replace '.' by '_' in datapoint ids to avoid unwanted sub structure in data states\nAdded more informations about white list for writables in Readme.\nRecognize loss of CAN connection.\nImproved handling of info.connection.",
|
|
8
|
+
"de": "Ersetzen Sie '.' durch '_' in Datapoint ids, um unerwünschte Unterstruktur in Datenzuständen zu vermeiden\nWeitere Informationen zur Weißen Liste für schreibbare in Readme.\nErkennen Verlust der CAN-Verbindung.\nVerbesserte Handhabung von info.connection.",
|
|
9
|
+
"ru": "Заменить '.' на '_' в идентификаторах точки данных, чтобы избежать нежелательной субструктуры в состояниях данных\nДобавлено больше информации о белом списке для редакций в Readme.\nУзнать потерю соединения CAN.\nУлучшена обработка info.connection.",
|
|
10
|
+
"pt": "Substituir '.' por '_' em datapoint ids para evitar subestrutura indesejada em estados de dados\nAdicionado mais informações sobre lista branca para writables em Readme.\nReconhecer a perda de conexão CAN.\nMelhor manuseio de info.connection.",
|
|
11
|
+
"nl": "Vervang '.' door '_' in datapoint ids om ongewenste substructuur in data states te voorkomen\nToegevoegd meer informatie over witte lijst voor schrijfsels in Readme.\nHerkennen verlies van KAN verbinding.\nVerbeterde behandeling van info.connectie.",
|
|
12
|
+
"fr": "Remplacer '.' par '_' dans les identifiants de points de données pour éviter une sous-structure indésirable dans les états de données\nAjout de plus d'informations sur la liste blanche pour les écritures dans Readme.\nReconnaître la perte de connexion CAN.\nAmélioration de la gestion d'info.connection.",
|
|
13
|
+
"it": "Sostituire '.' da '_' in datapoint ids per evitare la struttura sub indesiderata in stati di dati\nAggiunto più informazioni su white list per writables in Readme.\nRiconoscere la perdita di connessione CAN.\nGestione migliorata di info.connection.",
|
|
14
|
+
"es": "Reemplazar '.' por '_' en datospoint ids para evitar la subestructura no deseada en los estados de datos\nAgregó más información sobre la lista blanca para writables en Readme.\nReconocer la pérdida de conexión CAN.\nMejor manejo de info.conexión.",
|
|
15
|
+
"pl": "Zastąp '.' przez' _ 'w idach punktów danych, aby uniknąć niepożądanej podstruktury w stanach danych\nDodano więcej informacji na temat białej listy pism w Readme.\nRozpoznaj utratę połączenia CAN.\nUlepszone obchodzenie się z info.connection.",
|
|
16
|
+
"uk": "Замініть \".\" по \"_\" у полицях даних, щоб уникнути небажаної структури під даних\nДодайте більше інформації про білий список для життєздатних в Readme.\nВизначте втрату з'єднання CAN.\nПокращення обробки інформації.",
|
|
17
|
+
"zh-cn": "在数据点编号中将“.”改为“_”,以避免数据状态中不必要的子结构\n在Readme中添加了更多关于白名单的可写信息.\n识别失去的CAN连接.\n完善信息联通处理."
|
|
18
|
+
},
|
|
6
19
|
"0.6.13": {
|
|
7
20
|
"en": "Now supports multiple definitions of same schedule on a device \nAdded unit test cases for codecs",
|
|
8
21
|
"de": "Jetzt unterstützt mehrere Definitionen desselben Zeitplans auf einem Gerät\nHinzugefügte Einheit Testfälle für Codecs",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "Początkowa wersja npm",
|
|
81
94
|
"uk": "Початкова версія npm",
|
|
82
95
|
"zh-cn": "初始 npm 版本"
|
|
83
|
-
},
|
|
84
|
-
"0.6.6": {
|
|
85
|
-
"en": "initial npm release",
|
|
86
|
-
"de": "Erstveröffentlichung auf npm",
|
|
87
|
-
"ru": "Начальная версия",
|
|
88
|
-
"pt": "lançamento inicial",
|
|
89
|
-
"nl": "Eerste uitgave",
|
|
90
|
-
"fr": "Première version",
|
|
91
|
-
"it": "Versione iniziale",
|
|
92
|
-
"es": "Versión inicial",
|
|
93
|
-
"pl": "Pierwsze wydanie",
|
|
94
|
-
"uk": "Початкова версія",
|
|
95
|
-
"zh-cn": "首次出版"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"title": "Viessmann E3 CAN do",
|
package/lib/didsE3Writables.json
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"434": "MixerSixCircuitRoomTemperatureSetpoint",
|
|
14
14
|
"435": "VentilationStageTargetVolumeFlow",
|
|
15
15
|
"436": "MixerSevenCircuitRoomTemperatureSetpoint",
|
|
16
|
+
"437": "BypassOperationState",
|
|
16
17
|
"438": "MixerEightCircuitRoomTemperatureSetpoint",
|
|
17
18
|
"451": "ExternalAlternatingCurrentPowerSetpoint",
|
|
18
19
|
"491": "DomesticHotWaterCirculationPump",
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
"525": "ExternalModulationSetpoint",
|
|
24
25
|
"527": "FlowTemperatureTargetSetpoint",
|
|
25
26
|
"528": "ExternalTargetFlowTemperatureSetpoint",
|
|
27
|
+
"531": "DomesticHotWaterOperationState",
|
|
26
28
|
"533": "VentilationTargetOperationLevel",
|
|
27
29
|
"537": "ExternalMixerOneCircuitTargetOperationMode",
|
|
28
30
|
"538": "ExternalDomesticHotWaterTargetOperationMode",
|
|
@@ -101,6 +103,14 @@
|
|
|
101
103
|
"1265": "FanTargetSpeedMeta",
|
|
102
104
|
"1363": "FuelCellTargetOperationMode",
|
|
103
105
|
"1394": "SolarChargingDomesticHotWaterSetpoint",
|
|
106
|
+
"1415": "MixerOneCircuitOperationState",
|
|
107
|
+
"1416": "MixerTwoCircuitOperationState",
|
|
108
|
+
"1417": "MixerThreeCircuitOperationState",
|
|
109
|
+
"1418": "MixerFourCircuitOperationState",
|
|
110
|
+
"1419": "MixerFiveCircuitOperationState",
|
|
111
|
+
"1420": "MixerSixCircuitOperationState",
|
|
112
|
+
"1421": "MixerSevenCircuitOperationState",
|
|
113
|
+
"1422": "MixerEightCircuitOperationState",
|
|
104
114
|
"1439": "NoiseReductionTimeScheduleMonday",
|
|
105
115
|
"1440": "NoiseReductionTimeScheduleTuesday",
|
|
106
116
|
"1441": "NoiseReductionTimeScheduleWednesday",
|
|
@@ -109,6 +119,7 @@
|
|
|
109
119
|
"1444": "NoiseReductionTimeScheduleSaturday",
|
|
110
120
|
"1445": "NoiseReductionTimeScheduleSunday",
|
|
111
121
|
"1505": "SolarStagnationTemperatureOffset",
|
|
122
|
+
"1552": "ElectricalEnergyStorageOperationState",
|
|
112
123
|
"1555": "MixerOneCircuitFixedValueFlowTemperatureSetpoint",
|
|
113
124
|
"1556": "MixerTwoCircuitFixedValueFlowTemperatureSetpoint",
|
|
114
125
|
"1557": "MixerThreeCircuitFixedValueFlowTemperatureSetpoint",
|
|
@@ -121,6 +132,8 @@
|
|
|
121
132
|
"1587": "ExternalAlternatingCurrentPowerSetpointMetaData",
|
|
122
133
|
"1588": "AlternatingCurrentPowerSetpoint",
|
|
123
134
|
"1589": "AlternatingCurrentPowerSetpointMetaData",
|
|
135
|
+
"1590": "ElectricalEnergySystemOperationState",
|
|
136
|
+
"1591": "ElectricalEnergyInverterOperationState",
|
|
124
137
|
"1604": "GatewayExternalTargetFlowTemperatureSetpoint",
|
|
125
138
|
"1605": "GatewayExternalHeatEngineTargetOperationMode",
|
|
126
139
|
"1612": "ExternalMixerTwoCircuitTargetOperationMode",
|
|
@@ -373,6 +386,7 @@
|
|
|
373
386
|
"2327": "VentilationTargetVolumeFlow",
|
|
374
387
|
"2345": "CompressorSetpointPercent",
|
|
375
388
|
"2353": "TargetDemandHeatProducer",
|
|
389
|
+
"2372": "VentilationControllerOperationState",
|
|
376
390
|
"2373": "VentilationAirVolumeFlowBalancingOffset",
|
|
377
391
|
"2417": "MixerOneCircuitTargetValueRelativeHumidityCooling",
|
|
378
392
|
"2418": "MixerTwoCircuitTargetValueRelativeHumidityCooling",
|
|
@@ -400,6 +414,7 @@
|
|
|
400
414
|
"2878": "SubcoolingSetpoint",
|
|
401
415
|
"2883": "ExpansionValveMaximumOperatingPressureTemperatureSetpoint",
|
|
402
416
|
"2985": "ExternalHeaterTemperatureSetpoint",
|
|
417
|
+
"2986": "ExternalHeaterOperationState",
|
|
403
418
|
"3037": "ElectricityPriceTimeScheduleMonday",
|
|
404
419
|
"3038": "ElectricityPriceTimeScheduleTuesday",
|
|
405
420
|
"3039": "ElectricityPriceTimeScheduleWednesday",
|
package/lib/storage.js
CHANGED
|
@@ -280,7 +280,8 @@ class storage {
|
|
|
280
280
|
if (typeof(obj) == 'object') {
|
|
281
281
|
if (Object.keys(obj).length <= 100) {
|
|
282
282
|
for (const [key, itm] of Object.entries(obj)) {
|
|
283
|
-
await storeObjectTree(ctx, String(stateId)+'.'+String(key),itm);
|
|
283
|
+
await storeObjectTree(ctx, String(stateId)+'.'+String(key).replace('.','_'),itm);
|
|
284
|
+
// No '.' in state id allowed to avoid sub structure
|
|
284
285
|
}
|
|
285
286
|
} else {
|
|
286
287
|
ctx.log.error('Did valuation aborted. Too many members ('+String(Object.keys(obj).length)+') '+stateId+'.'+String(did));
|
|
@@ -306,7 +307,7 @@ class storage {
|
|
|
306
307
|
ctx.log.warn('Could not retreive codec for '+ctxWorker.config.stateBase+'.'+String(did)+'. err='+e.message);
|
|
307
308
|
codec = 'RawCodec';
|
|
308
309
|
}
|
|
309
|
-
idStr = cdi.id;
|
|
310
|
+
idStr = cdi.id.replace('.','_'); // No '.' in state allowed to avoid sub structure
|
|
310
311
|
common = true;
|
|
311
312
|
try {
|
|
312
313
|
val = await codec.decode(data);
|
|
@@ -316,6 +317,7 @@ class storage {
|
|
|
316
317
|
ctx.log.warn('Codec failed: '+ctxWorker.canIDhex+'.'+String(did)+'. err='+e.message);
|
|
317
318
|
}
|
|
318
319
|
} else {
|
|
320
|
+
// did length is diffetent from common did length => device specific did
|
|
319
321
|
idStr = 'DeviceSpecific';
|
|
320
322
|
val = raw;
|
|
321
323
|
common = false;
|
package/main.js
CHANGED
|
@@ -33,6 +33,7 @@ class E3oncan extends utils.Adapter {
|
|
|
33
33
|
name: 'e3oncan',
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
this.stoppingInstance = false; // true during unLoad()
|
|
36
37
|
this.e380Collect = null; // E380 always is assigned to external bus
|
|
37
38
|
this.E3CollectInt = {}; // Dict of collect devices on internal bus
|
|
38
39
|
this.E3CollectExt = {}; // Dict of collect devices on external bus
|
|
@@ -43,6 +44,8 @@ class E3oncan extends utils.Adapter {
|
|
|
43
44
|
this.channelExtName = '';
|
|
44
45
|
this.channelInt = null;
|
|
45
46
|
this.channelIntName = '';
|
|
47
|
+
this.cntCanConnDesired = 0; // Number of activated CAN connections in config
|
|
48
|
+
this.cntCanConnActual = 0; // Number if actualy connected CAN buses
|
|
46
49
|
|
|
47
50
|
this.udsWorkers = {};
|
|
48
51
|
this.udsTimeout = 7500; // Timeout (ms) for normal UDS communication
|
|
@@ -89,8 +92,9 @@ class E3oncan extends utils.Adapter {
|
|
|
89
92
|
|
|
90
93
|
// @ts-ignore
|
|
91
94
|
if (this.config.canExtActivated) {
|
|
95
|
+
this.cntCanConnDesired++;
|
|
92
96
|
// @ts-ignore
|
|
93
|
-
[this.channelExt, this.channelExtName] = await this.connectToCan(this.channelExt, this.config.canExtName, this.onCanMsgExt);
|
|
97
|
+
[this.channelExt, this.channelExtName] = await this.connectToCan(this.channelExt, this.config.canExtName, this.onCanMsgExt, this.onCanExtStopped);
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
// Setup internal CAN bus if required
|
|
@@ -98,8 +102,14 @@ class E3oncan extends utils.Adapter {
|
|
|
98
102
|
|
|
99
103
|
// @ts-ignore
|
|
100
104
|
if (this.config.canIntActivated) {
|
|
105
|
+
this.cntCanConnDesired++;
|
|
101
106
|
// @ts-ignore
|
|
102
|
-
[this.channelInt, this.channelIntName] = await this.connectToCan(this.channelInt, this.config.canIntName, this.onCanMsgInt);
|
|
107
|
+
[this.channelInt, this.channelIntName] = await this.connectToCan(this.channelInt, this.config.canIntName, this.onCanMsgInt, this.onCanIntStopped);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (this.cntCanConnActual == this.cntCanConnDesired) {
|
|
111
|
+
// All configured CAN connections are established
|
|
112
|
+
await this.setState('info.connection', true, true);
|
|
103
113
|
}
|
|
104
114
|
|
|
105
115
|
// Setup E380 collect worker:
|
|
@@ -119,14 +129,15 @@ class E3oncan extends utils.Adapter {
|
|
|
119
129
|
|
|
120
130
|
// Setup CAN busses
|
|
121
131
|
|
|
122
|
-
async connectToCan(channel, name, onMsg) {
|
|
132
|
+
async connectToCan(channel, name, onMsg, onStop) {
|
|
123
133
|
let chName = name;
|
|
124
134
|
if (!channel) {
|
|
125
135
|
try {
|
|
126
136
|
channel = can.createRawChannel(name, true);
|
|
127
137
|
await channel.addListener('onMessage', onMsg, this);
|
|
138
|
+
await channel.addListener('onStopped', onStop, this);
|
|
128
139
|
await channel.start();
|
|
129
|
-
|
|
140
|
+
this.cntCanConnActual++;
|
|
130
141
|
await this.log.info('CAN-Adapter connected: '+name);
|
|
131
142
|
} catch (e) {
|
|
132
143
|
await this.log.error(`Could not connect to CAN-Adapter "${name}" - err=${e.message}`);
|
|
@@ -148,7 +159,6 @@ class E3oncan extends utils.Adapter {
|
|
|
148
159
|
channel = null;
|
|
149
160
|
}
|
|
150
161
|
}
|
|
151
|
-
return([channel,'']);
|
|
152
162
|
}
|
|
153
163
|
|
|
154
164
|
// Setup E380 collect worker:
|
|
@@ -247,6 +257,7 @@ class E3oncan extends utils.Adapter {
|
|
|
247
257
|
*/
|
|
248
258
|
async onUnload(callback) {
|
|
249
259
|
try {
|
|
260
|
+
this.stoppingInstance = true;
|
|
250
261
|
// Stop UDS workers:
|
|
251
262
|
for (const worker of Object.values(this.E3UdsWorkers)) await worker.stop(this);
|
|
252
263
|
for (const worker of Object.values(this.udsScanWorker.workers)) await worker.stop(this);
|
|
@@ -261,6 +272,7 @@ class E3oncan extends utils.Adapter {
|
|
|
261
272
|
await this.disconnectFromCan(this.channelExt,this.config.canExtName);
|
|
262
273
|
// @ts-ignore
|
|
263
274
|
await this.disconnectFromCan(this.channelInt,this.config.canIntName);
|
|
275
|
+
this.setState('info.connection', false, true);
|
|
264
276
|
|
|
265
277
|
callback();
|
|
266
278
|
} catch (e) {
|
|
@@ -455,6 +467,24 @@ class E3oncan extends utils.Adapter {
|
|
|
455
467
|
}
|
|
456
468
|
}
|
|
457
469
|
|
|
470
|
+
onCanExtStopped() {
|
|
471
|
+
if (!this.stoppingInstance) {
|
|
472
|
+
// External CAN connection was terminated unexpectedly
|
|
473
|
+
this.log.error('External CAN bus was stopped.');
|
|
474
|
+
}
|
|
475
|
+
this.cntCanConnActual--;
|
|
476
|
+
this.setState('info.connection', false, true);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
onCanIntStopped() {
|
|
480
|
+
if (!this.stoppingInstance) {
|
|
481
|
+
// External CAN connection was terminated unexpectedly
|
|
482
|
+
this.log.error('Internal CAN bus was stopped.');
|
|
483
|
+
}
|
|
484
|
+
this.cntCanConnActual--;
|
|
485
|
+
this.setState('info.connection', false, true);
|
|
486
|
+
}
|
|
487
|
+
|
|
458
488
|
onCanMsgExt(msg) {
|
|
459
489
|
if ( (this.e380Collect) && (this.e380Collect.config.canID.includes(msg.id)) ) { this.e380Collect.msgCollect(this, msg); }
|
|
460
490
|
if (this.E3CollectExt[msg.id]) this.E3CollectExt[msg.id].msgCollect(this, msg);
|