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 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.6",
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",
@@ -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.STATE.getId = getState.id;
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 = false;
233
+ attr.invert = !!adapterData.adapter.config.blindsInvert;
234
234
  }
235
235
 
236
236
  //add commands, if present:
@@ -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.6",
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.2.0",
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.3.10",
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.2.0",
56
+ "mocha": "^10.3.0",
57
57
  "proxyquire": "^2.1.3",
58
58
  "sinon": "^17.0.1",
59
59
  "sinon-chai": "^3.7.0"