iobroker.e3oncan 0.6.14 → 0.6.15
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 +3 -0
- package/io-package.json +14 -14
- package/lib/canUds.js +31 -34
- package/lib/codecs.js +17 -7
- package/lib/codecs.test.js +56 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -102,6 +102,9 @@ 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.15 (2024-01-23)
|
|
106
|
+
* (MyHomeMyData) Fix for Utf8 codec for handling of special characters, e.g. umlauts
|
|
107
|
+
|
|
105
108
|
### 0.6.14 (2024-01-22)
|
|
106
109
|
* (MyHomeMyData) Replace '.' by '_' in datapoint ids to avoid unwanted sub structure in data states
|
|
107
110
|
* (MyHomeMyData) Added more informations about white list for writables in Readme.
|
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.15",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.6.15": {
|
|
7
|
+
"en": "Fix for Utf8 codec for handling of special characters, e.g. umlauts",
|
|
8
|
+
"de": "Fix für Utf8-Codec zum Umgang mit Sonderzeichen, z.B. umlauts",
|
|
9
|
+
"ru": "Fix for Utf8 codec для обработки специальных символов, например, umlauts",
|
|
10
|
+
"pt": "Fix para Codec Utf8 para manipulação de caracteres especiais, por exemplo, umlauts",
|
|
11
|
+
"nl": "Fix voor Utf8 codec voor het hanteren van speciale tekens, bijvoorbeeld umlauts",
|
|
12
|
+
"fr": "Correction pour Codec Utf8 pour la manipulation de caractères spéciaux, p.ex. umlauts",
|
|
13
|
+
"it": "Fissaggio per Codice Utf8 per la gestione di caratteri speciali, ad esempio umlauts",
|
|
14
|
+
"es": "Corrección Utf8 codec para el manejo de caracteres especiales, por ejemplo umlauts",
|
|
15
|
+
"pl": "Napraw dla Kod Utf8 do obsługi znaków specjalnych, np. umlautów",
|
|
16
|
+
"uk": "Фіксація Utf8 кодека для обробки спеціальних символів, наприклад, umlauts",
|
|
17
|
+
"zh-cn": "修复 Utf8 处理特殊字符的编码器, 例如 umlauts"
|
|
18
|
+
},
|
|
6
19
|
"0.6.14": {
|
|
7
20
|
"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
21
|
"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.",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "Bugfix: Tylko Linux jest obsługiwany",
|
|
81
94
|
"uk": "Помилки: Тільки Linux підтримується",
|
|
82
95
|
"zh-cn": "错误修正 : 仅支持 Linux"
|
|
83
|
-
},
|
|
84
|
-
"0.6.8": {
|
|
85
|
-
"en": "Initial npm version",
|
|
86
|
-
"de": "Ursprüngliche npm-Version",
|
|
87
|
-
"ru": "Первоначальная версия npm",
|
|
88
|
-
"pt": "Versão inicial npm",
|
|
89
|
-
"nl": "Eerste npm-versie",
|
|
90
|
-
"fr": "Version initiale npm",
|
|
91
|
-
"it": "Versione npm iniziale",
|
|
92
|
-
"es": "Versión inicial npm",
|
|
93
|
-
"pl": "Początkowa wersja npm",
|
|
94
|
-
"uk": "Початкова версія npm",
|
|
95
|
-
"zh-cn": "初始 npm 版本"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"title": "Viessmann E3 CAN do",
|
package/lib/canUds.js
CHANGED
|
@@ -365,17 +365,21 @@ class uds {
|
|
|
365
365
|
switch (dcs.channel) {
|
|
366
366
|
case 'json':
|
|
367
367
|
// Change in json data
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
368
|
+
try {
|
|
369
|
+
byteArr = await this.storage.encodeDataCAN(ctx, this, did, await JSON.parse(state.val));
|
|
370
|
+
if (byteArr) {
|
|
371
|
+
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
|
|
373
|
+
} else {
|
|
374
|
+
ctx.log.error('User command UDS WriteByDid on '+this.config.stateBase+': Encoding of data failed.');
|
|
375
|
+
}
|
|
376
|
+
} catch(e) {
|
|
377
|
+
ctx.log.error('WriteByDid(): Encoding of data failed on '+this.config.stateBase+'.'+String(did)+'; err='+JSON.stringify(e));
|
|
374
378
|
}
|
|
375
379
|
break;
|
|
376
380
|
case 'raw':
|
|
377
381
|
// Change in raw data
|
|
378
|
-
byteArr = this.storage.toByteArray(JSON.parse(state.val));
|
|
382
|
+
byteArr = this.storage.toByteArray(await JSON.parse(state.val));
|
|
379
383
|
if (byteArr) {
|
|
380
384
|
await this.pushCmnd(ctx, 'write', [[did,byteArr]]);
|
|
381
385
|
setTimeout(function(ctxWorker,did){ctxWorker.cmndsQueue.push({'mode':'read', 'did': did});},2500,this,did); // Read value after 2500 ms
|
|
@@ -389,12 +393,16 @@ class uds {
|
|
|
389
393
|
lenBaseId = ctx.namespace.length+dcs.device.length+dcs.channel.length+dcs.state.length+3;
|
|
390
394
|
if (id.length == lenBaseId) {
|
|
391
395
|
// Scalar value w/o sub structure
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
396
|
+
try {
|
|
397
|
+
byteArr = await this.storage.encodeDataCAN(ctx, this, did, await JSON.parse(state.val));
|
|
398
|
+
if (byteArr) {
|
|
399
|
+
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
|
|
401
|
+
} else {
|
|
402
|
+
ctx.log.error('User command UDS WriteByDid on '+this.config.stateBase+': Encoding of data failed.');
|
|
403
|
+
}
|
|
404
|
+
} catch(e) {
|
|
405
|
+
ctx.log.error('WriteByDid(): Encoding of data failed on '+this.config.stateBase+'.'+String(did)+'; err='+JSON.stringify(e));
|
|
398
406
|
}
|
|
399
407
|
break;
|
|
400
408
|
}
|
|
@@ -402,21 +410,6 @@ class uds {
|
|
|
402
410
|
// Build json object for complete object tree of changed did:
|
|
403
411
|
await ctx.getStatesOf(dcs.device,dcs.device+'.'+dcs.channel,async function(err,obj) {
|
|
404
412
|
// Get all states for changed device.channel
|
|
405
|
-
/*
|
|
406
|
-
// Probalby better solution based on numbers as marker for arrays. But not working yet.
|
|
407
|
-
function isNumber(value) { return /^\d+$/.test(value); }
|
|
408
|
-
function insertDictSubVal(dict, keyArr, isArray, val) {
|
|
409
|
-
if (keyArr.length == 1) {
|
|
410
|
-
const key = keyArr[0];
|
|
411
|
-
if (isArray) dict[key].push(val); else dict[key] = val;
|
|
412
|
-
} else {
|
|
413
|
-
const key = keyArr.shift();
|
|
414
|
-
const nextIsArray = (((keyArr.length) && (isNumber(keyArr[0]))) ? true : false);
|
|
415
|
-
if (!(key in dict)) if (nextIsArray) dict[key] = []; else dict[key] = {};
|
|
416
|
-
insertDictSubVal(dict[key],keyArr, nextIsArray, val);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
*/
|
|
420
413
|
function insertDictSubVal(dict, keyArr, val) {
|
|
421
414
|
const listLabels = ['ListEntries','Schedules','TopologyElement'];
|
|
422
415
|
if (keyArr.length == 1) {
|
|
@@ -437,12 +430,16 @@ class uds {
|
|
|
437
430
|
insertDictSubVal(treeDict, label.split('.'), val);
|
|
438
431
|
}
|
|
439
432
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
433
|
+
try {
|
|
434
|
+
byteArr = await ctxWorker.storage.encodeDataCAN(ctx, ctxWorker, did, treeDict);
|
|
435
|
+
if (byteArr) {
|
|
436
|
+
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
|
|
438
|
+
} else {
|
|
439
|
+
ctx.log.error('User command UDS WriteByDid on '+ctxWorker.config.stateBase+': Encoding of data failed.');
|
|
440
|
+
}
|
|
441
|
+
} catch(e) {
|
|
442
|
+
ctx.log.error('WriteByDid(): Encoding of data failed on '+ctxWorker.config.stateBase+'.'+String(did)+'; err='+JSON.stringify(e));
|
|
446
443
|
}
|
|
447
444
|
});
|
|
448
445
|
break;
|
package/lib/codecs.js
CHANGED
|
@@ -205,18 +205,28 @@ class O3EUtf8 {
|
|
|
205
205
|
this.id = idStr;
|
|
206
206
|
this.offset = _args.offset;
|
|
207
207
|
}
|
|
208
|
+
|
|
208
209
|
encode(data) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
let result;
|
|
211
|
+
try {
|
|
212
|
+
result = Object.values(new TextEncoder().encode(data));
|
|
213
|
+
} catch(e) {
|
|
214
|
+
throw new Error('O3EUtf8.encode(): Conversion from Utf8 failed '+this.id+'; err='+JSON.stringify(e));
|
|
215
|
+
}
|
|
216
|
+
if (result.length > this.string_len) throw new Error('O3EUtf8.encode(): Result too long: '+this.id+' - '+String(result.length)+' > '+String(this.string_len));
|
|
212
217
|
return result.concat(Array.from(Array(this.string_len-result.length), () => 0));
|
|
213
218
|
|
|
214
219
|
}
|
|
215
220
|
decode(string_bin) {
|
|
216
|
-
let
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
221
|
+
let i = string_bin.slice(this.offset).indexOf(0);
|
|
222
|
+
if (i == -1) { i = string_bin.length-this.offset; }
|
|
223
|
+
let result;
|
|
224
|
+
try {
|
|
225
|
+
result = new TextDecoder().decode(new Uint8Array(string_bin.slice(this.offset,i)));
|
|
226
|
+
} catch(e) {
|
|
227
|
+
throw new Error('O3EUtf8.decode(): Conversion to Utf8 failed '+this.id+'; err='+JSON.stringify(e));
|
|
228
|
+
}
|
|
229
|
+
return result;
|
|
220
230
|
}
|
|
221
231
|
|
|
222
232
|
__len__() {
|
package/lib/codecs.test.js
CHANGED
|
@@ -38,6 +38,62 @@ function codecEncode(descr, expected, codec, len, id, args, val) {
|
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
// Utf8:
|
|
42
|
+
describe('codecs.js => O3EUtf8()', () => {
|
|
43
|
+
const raw_hex1 = '4865697a6bc3b6727065720000000000000000000000000000000000000000000000000000000000';
|
|
44
|
+
const raw1 = E3.toByteArray(raw_hex1);
|
|
45
|
+
const txt1 = 'Heizkörper';
|
|
46
|
+
it(`Decode ${JSON.stringify(txt1)}`, () => {
|
|
47
|
+
const f = new E3.O3Ecodecs.O3EUtf8(raw1.length,'test1Utf08', {offset:0});
|
|
48
|
+
const result = f.decode(raw1);
|
|
49
|
+
expect(JSON.stringify(result)).to.equal(JSON.stringify(txt1));
|
|
50
|
+
});
|
|
51
|
+
it(`Encode ${JSON.stringify(raw1)}`, () => {
|
|
52
|
+
const f = new E3.O3Ecodecs.O3EUtf8(raw1.length,'test2Utf08', {offset:0});
|
|
53
|
+
const result = f.encode(txt1);
|
|
54
|
+
expect(JSON.stringify(raw1)).to.equal(JSON.stringify(result));
|
|
55
|
+
});
|
|
56
|
+
const raw_hex2 = '4675c39f626f64656e6865697a756e67000000000000000000000000000000000000000000000000';
|
|
57
|
+
const raw2 = E3.toByteArray(raw_hex2);
|
|
58
|
+
const txt2 = 'Fußbodenheizung';
|
|
59
|
+
it(`Decode ${JSON.stringify(txt2)}`, () => {
|
|
60
|
+
const f = new E3.O3Ecodecs.O3EUtf8(raw2.length,'test3Utf08', {offset:0});
|
|
61
|
+
const result = f.decode(raw2);
|
|
62
|
+
expect(JSON.stringify(result)).to.equal(JSON.stringify(txt2));
|
|
63
|
+
});
|
|
64
|
+
it(`Encode ${JSON.stringify(raw2)}`, () => {
|
|
65
|
+
const f = new E3.O3Ecodecs.O3EUtf8(raw2.length,'test4Utf08', {offset:0});
|
|
66
|
+
const result = f.encode(txt2);
|
|
67
|
+
expect(JSON.stringify(raw2)).to.equal(JSON.stringify(result));
|
|
68
|
+
});
|
|
69
|
+
const raw_hex3 = '00000000000000000000000000000000000000000000000000000000000000000000000000000000';
|
|
70
|
+
const raw3 = E3.toByteArray(raw_hex3);
|
|
71
|
+
const txt3 = '';
|
|
72
|
+
it(`Decode ${JSON.stringify(txt3)}`, () => {
|
|
73
|
+
const f = new E3.O3Ecodecs.O3EUtf8(raw3.length,'test5Utf08', {offset:0});
|
|
74
|
+
const result = f.decode(raw3);
|
|
75
|
+
expect(JSON.stringify(result)).to.equal(JSON.stringify(txt3));
|
|
76
|
+
});
|
|
77
|
+
it(`Encode ${JSON.stringify(raw3)}`, () => {
|
|
78
|
+
const f = new E3.O3Ecodecs.O3EUtf8(raw3.length,'test5Utf08', {offset:0});
|
|
79
|
+
const result = f.encode(txt3);
|
|
80
|
+
expect(JSON.stringify(raw3)).to.equal(JSON.stringify(result));
|
|
81
|
+
});
|
|
82
|
+
const raw_hex4 = '4675c39f';
|
|
83
|
+
const raw4 = E3.toByteArray(raw_hex4);
|
|
84
|
+
const txt4 = 'Fuß';
|
|
85
|
+
it(`Decode ${JSON.stringify(txt4)}`, () => {
|
|
86
|
+
const f = new E3.O3Ecodecs.O3EUtf8(raw4.length,'test6Utf08', {offset:0});
|
|
87
|
+
const result = f.decode(raw4);
|
|
88
|
+
expect(JSON.stringify(result)).to.equal(JSON.stringify(txt4));
|
|
89
|
+
});
|
|
90
|
+
it(`Encode ${JSON.stringify(raw4)}`, () => {
|
|
91
|
+
const f = new E3.O3Ecodecs.O3EUtf8(raw4.length,'test6Utf08', {offset:0});
|
|
92
|
+
const result = f.encode(txt4);
|
|
93
|
+
expect(JSON.stringify(raw4)).to.equal(JSON.stringify(result));
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
41
97
|
// val2byteArray:
|
|
42
98
|
describe('codecs.js => val2byteArr()', () => {
|
|
43
99
|
let val = -1;
|