iobroker.lovelace 4.1.6 → 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 +4 -3
- package/io-package.json +9 -9
- package/lib/converters/cover.js +2 -2
- package/lib/converters/light.js +12 -0
- package/lib/modules/entityRegistry.js +106 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -473,6 +473,10 @@ 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
|
+
|
|
476
480
|
### 4.1.6 (2024-03-07)
|
|
477
481
|
* (Garfonso) remove exessive logging
|
|
478
482
|
* (Garfonso) improve fix for crash again.
|
|
@@ -488,9 +492,6 @@ After that checkout modified version in `./build` folder. Then.
|
|
|
488
492
|
* (Garfonso) fix: lamp icons now turn gray on switch off.
|
|
489
493
|
* (Garfonso) fix: notifications via sendTo work again.
|
|
490
494
|
|
|
491
|
-
### 4.1.2 (2024-01-09)
|
|
492
|
-
* (Garfonso) fix: time in timestamp display
|
|
493
|
-
|
|
494
495
|
## License
|
|
495
496
|
|
|
496
497
|
Copyright 2019-2024, bluefox <dogafox@gmail.com>
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
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
|
+
},
|
|
6
14
|
"4.1.6": {
|
|
7
15
|
"en": "remove exessive logging\nimprove fix for crash again.",
|
|
8
16
|
"de": "exessive log ausgabe entfernen\nverbesserung der reparatur für crash.",
|
|
@@ -49,14 +57,6 @@
|
|
|
49
57
|
"pl": "fix: czas wyświetlania znacznika czasu",
|
|
50
58
|
"uk": "виправити: час в часовому режимі відображення",
|
|
51
59
|
"zh-cn": "修正:时间戳显示的时间"
|
|
52
|
-
},
|
|
53
|
-
"4.1.1": {
|
|
54
|
-
"en": "changed: determining user id\nchanged: history attributes handling\nadded: handle browser_mod/recall_id service call.\nchanged: all states are strings!",
|
|
55
|
-
"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!"
|
|
56
|
-
},
|
|
57
|
-
"4.1.0": {
|
|
58
|
-
"en": "add an option to show users on login screen (off by default)",
|
|
59
|
-
"de": "Neu Option um Benutzer auf dem Login-Bildschirm anzuzeigen"
|
|
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
|
@@ -234,6 +234,9 @@ function _lightAdvancedAddHueAndSat(states, objects, entity) {
|
|
|
234
234
|
targetAttributes = entity.context.STATE.storedValues;
|
|
235
235
|
}
|
|
236
236
|
state = state || {val: 0};
|
|
237
|
+
if (!targetAttributes.hs_color) {
|
|
238
|
+
targetAttributes.hs_color = [0, 100];
|
|
239
|
+
}
|
|
237
240
|
targetAttributes.hs_color[1] = state.val / attr.max * 100;
|
|
238
241
|
targetAttributes.color_mode = HS;
|
|
239
242
|
};
|
|
@@ -277,6 +280,9 @@ async function _lightAdvancedAddRGBSingle(states, objects, entity) {
|
|
|
277
280
|
targetAttributes.color_mode = RGB;
|
|
278
281
|
if (states.white) {
|
|
279
282
|
targetAttributes.color_mode = RGBW;
|
|
283
|
+
if (!targetAttributes.rgbw_color) {
|
|
284
|
+
targetAttributes.rgbw_color = [r,g,b,0];
|
|
285
|
+
}
|
|
280
286
|
targetAttributes.rgbw_color[0] = r;
|
|
281
287
|
targetAttributes.rgbw_color[1] = g;
|
|
282
288
|
targetAttributes.rgbw_color[2] = b;
|
|
@@ -552,6 +558,12 @@ async function fillLightEntityFromStates(states, objects, entity) {
|
|
|
552
558
|
if (entity.state !== 'on') {
|
|
553
559
|
targetAttributes = entity.context.STATE.storedValues;
|
|
554
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
|
+
}
|
|
555
567
|
targetAttributes.rgbw_color[3] = val / attr.max * 255;
|
|
556
568
|
targetAttributes.color_mode = RGBW;
|
|
557
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"
|