iobroker.lovelace 4.1.5 → 4.1.8
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 +8 -9
- package/io-package.json +22 -22
- package/lib/converters/cover.js +2 -2
- package/lib/converters/light.js +17 -2
- package/lib/modules/entityRegistry.js +106 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -473,6 +473,14 @@ After that checkout modified version in `./build` folder. Then.
|
|
|
473
473
|
PLACEHOLDER for the next version:
|
|
474
474
|
### **WORK IN PROGRESS**
|
|
475
475
|
-->
|
|
476
|
+
### 4.1.8 (2024-03-11)
|
|
477
|
+
* (Garfonso) prevent even more possible crashes
|
|
478
|
+
* (smarthomejoey) fixed: tilt level and inversion
|
|
479
|
+
|
|
480
|
+
### 4.1.6 (2024-03-07)
|
|
481
|
+
* (Garfonso) remove exessive logging
|
|
482
|
+
* (Garfonso) improve fix for crash again.
|
|
483
|
+
|
|
476
484
|
### 4.1.5 (2024-03-05)
|
|
477
485
|
* (Garfonso) fixed: possible crashes during startup
|
|
478
486
|
|
|
@@ -484,15 +492,6 @@ After that checkout modified version in `./build` folder. Then.
|
|
|
484
492
|
* (Garfonso) fix: lamp icons now turn gray on switch off.
|
|
485
493
|
* (Garfonso) fix: notifications via sendTo work again.
|
|
486
494
|
|
|
487
|
-
### 4.1.2 (2024-01-09)
|
|
488
|
-
* (Garfonso) fix: time in timestamp display
|
|
489
|
-
|
|
490
|
-
### 4.1.1 (2024-01-02)
|
|
491
|
-
* (Garfonso) changed: determining user id
|
|
492
|
-
* (Garfosno) changed: history attributes handling
|
|
493
|
-
* (Garfonso) added: handle browser_mod/recall_id service call.
|
|
494
|
-
* (Garfonso) changed: all states are strings (fixes #483)
|
|
495
|
-
|
|
496
495
|
## License
|
|
497
496
|
|
|
498
497
|
Copyright 2019-2024, bluefox <dogafox@gmail.com>
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "lovelace",
|
|
4
|
-
"version": "4.1.
|
|
4
|
+
"version": "4.1.8",
|
|
5
5
|
"news": {
|
|
6
|
+
"4.1.8": {
|
|
7
|
+
"en": "prevent even more possible crashes\nfixed: tilt level and inversion",
|
|
8
|
+
"de": "noch mehr mögliche abstürzen verhindern\nfixed: tilt level und inversion"
|
|
9
|
+
},
|
|
10
|
+
"4.1.7": {
|
|
11
|
+
"en": "prevent even more possible crashes\nfixed: tilt level and inversion",
|
|
12
|
+
"de": "noch mehr mögliche abstürzen verhindern\nfixed: tilt level und inversion"
|
|
13
|
+
},
|
|
14
|
+
"4.1.6": {
|
|
15
|
+
"en": "remove exessive logging\nimprove fix for crash again.",
|
|
16
|
+
"de": "exessive log ausgabe entfernen\nverbesserung der reparatur für crash.",
|
|
17
|
+
"ru": "удалить exessive logging\nулучшить исправление для аварии снова.",
|
|
18
|
+
"pt": "remover registro exessivo\nmelhorar a correção para acidente novamente.",
|
|
19
|
+
"nl": "exessieve logging verwijderen\nverbeteren fix voor crash opnieuw.",
|
|
20
|
+
"fr": "supprimer l'exploitation exessive\naméliorer la correction pour le crash à nouveau.",
|
|
21
|
+
"it": "rimuovere logging exessive\nmigliorare la correzione per crash di nuovo.",
|
|
22
|
+
"es": "remove exessive logging\nmejorar la solución para el accidente de nuevo.",
|
|
23
|
+
"pl": "usunięcie nadmiernego logowania\npoprawić naprawić ponownie awarii.",
|
|
24
|
+
"uk": "видалити есенціальний журнал\nзнову поліпшуйте фіксацію.",
|
|
25
|
+
"zh-cn": "删除 exessive 日志\n改善再次崩溃的修复."
|
|
26
|
+
},
|
|
6
27
|
"4.1.5": {
|
|
7
28
|
"en": "fixed: possible crashes during startup",
|
|
8
29
|
"de": "behoben: mögliche abstürzen beim start",
|
|
@@ -36,27 +57,6 @@
|
|
|
36
57
|
"pl": "fix: czas wyświetlania znacznika czasu",
|
|
37
58
|
"uk": "виправити: час в часовому режимі відображення",
|
|
38
59
|
"zh-cn": "修正:时间戳显示的时间"
|
|
39
|
-
},
|
|
40
|
-
"4.1.1": {
|
|
41
|
-
"en": "changed: determining user id\nchanged: history attributes handling\nadded: handle browser_mod/recall_id service call.\nchanged: all states are strings!",
|
|
42
|
-
"de": "geändert: bestimmung der benutzer-id\ngeändert: historie für attribute\nhinzugefügt: handle browser_mod/recall_id service call.\ngeändert: alle zustände sind strings!"
|
|
43
|
-
},
|
|
44
|
-
"4.1.0": {
|
|
45
|
-
"en": "add an option to show users on login screen (off by default)",
|
|
46
|
-
"de": "Neu Option um Benutzer auf dem Login-Bildschirm anzuzeigen"
|
|
47
|
-
},
|
|
48
|
-
"4.0.12": {
|
|
49
|
-
"en": "fix lint errors",
|
|
50
|
-
"de": "lint fehler beheben",
|
|
51
|
-
"ru": "исправить ошибки lint",
|
|
52
|
-
"pt": "corrigir erros de lint",
|
|
53
|
-
"nl": "lint fouten",
|
|
54
|
-
"fr": "corriger les erreurs lint",
|
|
55
|
-
"it": "correggere gli errori di lintuizione",
|
|
56
|
-
"es": "corregir errores lint",
|
|
57
|
-
"pl": "błędy lintowe",
|
|
58
|
-
"uk": "виправлено помилки в розмітці",
|
|
59
|
-
"zh-cn": "f 固定错误"
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
"title": "Visualization with Lovelace-UI",
|
package/lib/converters/cover.js
CHANGED
|
@@ -175,7 +175,7 @@ function addTiltLevel(entity, control, objects, name) {
|
|
|
175
175
|
|
|
176
176
|
const getState = control.states.find(s => s.id && s.name === name.replace('SET', 'ACTUAL'));
|
|
177
177
|
if (getState && getState.id) {
|
|
178
|
-
entity.context.
|
|
178
|
+
entity.context.ATTRIBUTES.find(a => a.attribute === 'tilt').getId = getState.id;
|
|
179
179
|
utils.addID2entity(getState.id, entity);
|
|
180
180
|
}
|
|
181
181
|
return true;
|
|
@@ -230,7 +230,7 @@ exports.processBlind = function(id, control, name, room, func, _obj, objects, fo
|
|
|
230
230
|
|
|
231
231
|
if(addTiltLevel(entity, control, objects, 'TILT_SET')) {
|
|
232
232
|
const attr = entity.context.ATTRIBUTES.find(a => a.attribute === 'tilt');
|
|
233
|
-
attr.invert =
|
|
233
|
+
attr.invert = !!adapterData.adapter.config.blindsInvert;
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
//add commands, if present:
|
package/lib/converters/light.js
CHANGED
|
@@ -51,7 +51,7 @@ function clearOrRestoreAttributes(entity) {
|
|
|
51
51
|
entity.attributes[attr] = entity.context.STATE.storedValues[attr];
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
adapterData.log.
|
|
54
|
+
//adapterData.log.debug(`Stored old values for next switch on: ${JSON.stringify(entity.context.STATE.storedValues)}`);
|
|
55
55
|
} else {
|
|
56
56
|
for (const attr of attributesToNullOnOff) {
|
|
57
57
|
if (entity.attributes[attr] !== undefined) {
|
|
@@ -59,7 +59,7 @@ function clearOrRestoreAttributes(entity) {
|
|
|
59
59
|
entity.attributes[attr] = null;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
adapterData.log.
|
|
62
|
+
//adapterData.log.debug(`Restored old values from previous switch off: ${JSON.stringify(entity.attributes)}`);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -208,6 +208,9 @@ function _lightAdvancedAddHueAndSat(states, objects, entity) {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
state = state || {val: 0};
|
|
211
|
+
if (!targetAttributes.hs_color) {
|
|
212
|
+
targetAttributes.hs_color = [0, 100];
|
|
213
|
+
}
|
|
211
214
|
targetAttributes.hs_color[0] = state.val / attr.max * 360;
|
|
212
215
|
targetAttributes.color_mode = HS;
|
|
213
216
|
};
|
|
@@ -231,6 +234,9 @@ function _lightAdvancedAddHueAndSat(states, objects, entity) {
|
|
|
231
234
|
targetAttributes = entity.context.STATE.storedValues;
|
|
232
235
|
}
|
|
233
236
|
state = state || {val: 0};
|
|
237
|
+
if (!targetAttributes.hs_color) {
|
|
238
|
+
targetAttributes.hs_color = [0, 100];
|
|
239
|
+
}
|
|
234
240
|
targetAttributes.hs_color[1] = state.val / attr.max * 100;
|
|
235
241
|
targetAttributes.color_mode = HS;
|
|
236
242
|
};
|
|
@@ -274,6 +280,9 @@ async function _lightAdvancedAddRGBSingle(states, objects, entity) {
|
|
|
274
280
|
targetAttributes.color_mode = RGB;
|
|
275
281
|
if (states.white) {
|
|
276
282
|
targetAttributes.color_mode = RGBW;
|
|
283
|
+
if (!targetAttributes.rgbw_color) {
|
|
284
|
+
targetAttributes.rgbw_color = [r,g,b,0];
|
|
285
|
+
}
|
|
277
286
|
targetAttributes.rgbw_color[0] = r;
|
|
278
287
|
targetAttributes.rgbw_color[1] = g;
|
|
279
288
|
targetAttributes.rgbw_color[2] = b;
|
|
@@ -549,6 +558,12 @@ async function fillLightEntityFromStates(states, objects, entity) {
|
|
|
549
558
|
if (entity.state !== 'on') {
|
|
550
559
|
targetAttributes = entity.context.STATE.storedValues;
|
|
551
560
|
}
|
|
561
|
+
if (!targetAttributes.rgbw_color) {
|
|
562
|
+
targetAttributes.rgbw_color = [
|
|
563
|
+
targetAttributes.rgb_color ? targetAttributes.rgb_color[0] : 0,
|
|
564
|
+
targetAttributes.rgb_color ? targetAttributes.rgb_color[1] : 0,
|
|
565
|
+
targetAttributes.rgb_color ? targetAttributes.rgb_color[2] : 0];
|
|
566
|
+
}
|
|
552
567
|
targetAttributes.rgbw_color[3] = val / attr.max * 255;
|
|
553
568
|
targetAttributes.color_mode = RGBW;
|
|
554
569
|
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const entityData = require('../dataSingleton');
|
|
2
|
+
const {iobState2EntityState} = require('../converters/genericConverter');
|
|
3
|
+
const WebSocket = require('ws').WebSocket;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Class to handle the entity registry.
|
|
7
|
+
* i.e. it needs to keep an array of entities, both manually configured and automatically detected.
|
|
8
|
+
* It needs to send the list upon request from the frontend.
|
|
9
|
+
* It has to store additional settings for each entity, like the history parser, the icon, the friendly name, etc.
|
|
10
|
+
*
|
|
11
|
+
* TODO: It should deprecate the dataSingleton.js file.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
class EntityRegistry {
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.adapter = options.adapter;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
sendLogbookResponse(ws, id, startTime = undefined, endTime = undefined, results = [], partial = false) {
|
|
20
|
+
const message = {
|
|
21
|
+
id: Number(id),
|
|
22
|
+
type: 'event',
|
|
23
|
+
event: {
|
|
24
|
+
events: []
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
if (startTime) {
|
|
28
|
+
message.event.start_time = startTime / 1000;
|
|
29
|
+
}
|
|
30
|
+
if (endTime) {
|
|
31
|
+
message.event.end_time = endTime / 1000;
|
|
32
|
+
}
|
|
33
|
+
if (partial) {
|
|
34
|
+
message.event.partial = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const result of results) {
|
|
38
|
+
let from = undefined;
|
|
39
|
+
if (this.adapter.config.logbookSource === 'user') {
|
|
40
|
+
from = result.state.user;
|
|
41
|
+
}
|
|
42
|
+
if (this.adapter.config.logbookSource === 'adapter') {
|
|
43
|
+
from = result.state.from;
|
|
44
|
+
}
|
|
45
|
+
message.event.events.push({
|
|
46
|
+
when: result.state.ts / 1000,
|
|
47
|
+
state: typeof result.entity.context.STATE.historyParser === 'function' ?
|
|
48
|
+
result.entity.context.STATE.historyParser(id, result.state.val).toString() :
|
|
49
|
+
iobState2EntityState(result.entity, result.state.val).toString(),
|
|
50
|
+
entity_id: result.entity.entity_id,
|
|
51
|
+
context_user_id: from
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//sort by time:
|
|
55
|
+
message.event.events.sort((a, b) => a.when - b.when);
|
|
56
|
+
console.dir(message, {depth: 8});
|
|
57
|
+
ws.send(JSON.stringify(message));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//event_stream -> means implicit subscription (AAAAHHH) -> remember id here and update. Will call unsubscribe message if page is left.
|
|
61
|
+
//unsubscribe is very unspecific: {"type":"unsubscribe_events","subscription":288,"id":289} -> how to pipe that here?
|
|
62
|
+
async processMessage(ws, message) {
|
|
63
|
+
if (message.type === 'config/entity_registry/list_for_display') {
|
|
64
|
+
this._sendResponse(ws, message.id, {entities: entityData.entities, entity_categories: {'0': 'config', '1': 'diagnostic'}});
|
|
65
|
+
} else if (message.type === 'config/entity_registry/get') {
|
|
66
|
+
// config/entity_registry/get
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onStateChange(id, state, websocketServer) {
|
|
71
|
+
if (state) {
|
|
72
|
+
//check if the state update needs to be added to any logbook:
|
|
73
|
+
for (const [msgId, idsToWatch] of Object.entries(this.subscribesToIds)) {
|
|
74
|
+
let active = false;
|
|
75
|
+
if (websocketServer) {
|
|
76
|
+
for (const client of websocketServer.clients) {
|
|
77
|
+
if (client._subscribes.logbook && client.readyState === WebSocket.OPEN) {
|
|
78
|
+
if (client._subscribes.logbook.includes(Number(msgId))) {
|
|
79
|
+
active = true;
|
|
80
|
+
//found a client with active subscription -> update.
|
|
81
|
+
this.adapter.log.debug('Logbook subscription ' + msgId + ' found.');
|
|
82
|
+
|
|
83
|
+
const idAndEntity = idsToWatch.find(entry => id === entry.iobStateId);
|
|
84
|
+
if (idAndEntity) {
|
|
85
|
+
this.adapter.log.debug('Logbook subscription ' + msgId + ' is for right id, sending update.');
|
|
86
|
+
this.sendLogbookResponse(client, msgId, undefined, undefined, [{
|
|
87
|
+
state,
|
|
88
|
+
entity: idAndEntity.entity
|
|
89
|
+
}]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
//clean up not found conversations.
|
|
97
|
+
if (!active) {
|
|
98
|
+
this.adapter.log.debug('Logbook subscription ' + msgId + ' deleted.');
|
|
99
|
+
delete this.subscribesToIds[msgId];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = EntityRegistry;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.lovelace",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.8",
|
|
4
4
|
"description": "With this adapter you can build visualization for ioBroker with Home Assistant Lovelace UI",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "bluefox",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@alcalzone/release-script-plugin-iobroker": "^3.7.0",
|
|
40
40
|
"@alcalzone/release-script-plugin-license": "^3.7.0",
|
|
41
41
|
"@alcalzone/release-script-plugin-manual-review": "^3.7.0",
|
|
42
|
-
"@iobroker/adapter-dev": "^1.
|
|
42
|
+
"@iobroker/adapter-dev": "^1.3.0",
|
|
43
43
|
"@iobroker/testing": "^4.1.0",
|
|
44
44
|
"@types/chai": "^4.3.11",
|
|
45
45
|
"@types/chai-as-promised": "^7.1.8",
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"@types/proxyquire": "^1.3.31",
|
|
50
50
|
"@types/sinon": "^17.0.3",
|
|
51
51
|
"@types/sinon-chai": "^3.2.12",
|
|
52
|
-
"chai": "^4.
|
|
52
|
+
"chai": "^4.4.1",
|
|
53
53
|
"chai-as-promised": "^7.1.1",
|
|
54
54
|
"eslint": "^8.56.0",
|
|
55
55
|
"gulp": "^4.0.2",
|
|
56
|
-
"mocha": "^10.
|
|
56
|
+
"mocha": "^10.3.0",
|
|
57
57
|
"proxyquire": "^2.1.3",
|
|
58
58
|
"sinon": "^17.0.1",
|
|
59
59
|
"sinon-chai": "^3.7.0"
|