iobroker.lovelace 5.0.1 → 5.0.3

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,15 @@ After that checkout modified version in `./build` folder. Then.
473
473
  PLACEHOLDER for the next version:
474
474
  ### **WORK IN PROGRESS**
475
475
  -->
476
+ ### 5.0.3 (2025-10-10)
477
+ * (Garfonso) make sure only existing themes are selectable in control.theme states.
478
+ * (Garfonso) bring back support for frontend_es5.
479
+
480
+ ### 5.0.2 (2025-10-02)
481
+ * (Garfonso) some light entities did not restore their proper state on switch on. Fixed.
482
+ * (Garfonso) process folders-Objects for auto entities, too. (pirate-weather support)
483
+ * (Garfonso) prepare support for effects in light entities (will need new type-detector version).
484
+
476
485
  ### 5.0.1 (2025-09-09)
477
486
  * (Garfonso) settings from entity registry are now loaded on startup
478
487
  * (Garfonso) logbook: prevent entries from the future
@@ -495,12 +504,6 @@ After that checkout modified version in `./build` folder. Then.
495
504
  ### 4.1.15 (2025-03-10)
496
505
  * (Garfonso) repaired image loading, again.
497
506
 
498
- ### 4.1.14 (2025-03-10)
499
- * (Garfonso) repaired image loading. Fixes #577
500
-
501
- ### 4.1.13 (2025-03-06)
502
- * (Garfonso) reworked image sending. Now weather icons work for normal users, too. Also, weather images are transferred from our server, so no access to admin is needed anymore.
503
-
504
507
  ## License
505
508
 
506
509
  Copyright 2019-2025, bluefox <dogafox@gmail.com>
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lovelace",
4
- "version": "5.0.1",
4
+ "version": "5.0.3",
5
5
  "news": {
6
+ "5.0.3": {
7
+ "en": "make sure only existing themes are selectable in control.theme states.\nbring back support for frontend_es5.",
8
+ "de": "sicher stellen, dass nur vorhandene themen in der steuerung über states wählbar sind.\nunterstützung für frontend_es5 wiederhergestellt.",
9
+ "ru": "убедитесь, что только существующие темы поддаются выбору. темы государств.\nподдержка интерфейса frontend_es5.",
10
+ "pt": "certifique-se de que apenas os temas existentes são selecionáveis no controle. estados temáticos.\ntrazer suporte para frontend_es5.",
11
+ "nl": "zorg ervoor dat alleen bestaande thema's zijn geselecteerd in controle. thema staat.\nondersteuning voor frontend_es5 terugbrengen.",
12
+ "fr": "assurez-vous que seuls les thèmes existants peuvent être sélectionnés dans le contrôle. les états thématiques.\nramener le support de frontend_es5.",
13
+ "it": "assicurarsi che solo i temi esistenti siano selezionabili in controllo. stati tematici.\nriportare il supporto per frontend_es5.",
14
+ "es": "asegúrese de que sólo los temas existentes son seleccionables en control. estados temáticos.\ntraer apoyo para frontend_es5.",
15
+ "pl": "upewnij się, że tylko istniejące motywy są wybierane pod kontrolą. stan tematyczny.\nprzywrócić wsparcie dla frontend _ es5.",
16
+ "uk": "переконайтеся, що тільки існуючі теми вибираються в управлінні. тематичні стани.\nповернути підтримку фронтенд_es5.",
17
+ "zh-cn": "确保控制中只选择现有主题。 主题状态.\n带回对前端_es5的支持."
18
+ },
19
+ "5.0.2": {
20
+ "en": "some light entities did not restore their proper state on switch on. Fixed.\nprocess folders-Objects for auto entities, too. (pirate-weather support)\nprepare support for effects in light entities (will need new type-detector version).",
21
+ "de": "einige Licht entities haben ihren Zustand beim Einschalten nicht wiederhergestellt. Behoben.\nOrdner-Objekte auch für Auto-Entitäten bearbeiten. (Pirate-Wetter-Unterstützung)\ndie unterstützung von effekten in Licht entities vorbereitet (benötigt neue typ-detektor-version).",
22
+ "ru": "некоторые легкие сущности не восстановили свое надлежащее состояние при включении. Исправлено.\nтакже обрабатывают папки-объекты для автообъектов. (поддержка пиратской погоды)\nподготовить поддержку эффектов в легких объектах (требуется новая версия детектора типа).",
23
+ "pt": "algumas entidades de luz não restauraram seu estado adequado no interruptor ligado. Consertado.\npastas de processo-Objects para entidades auto, também. (suporte de pirate-weather)\npreparar suporte para efeitos em entidades leves (necessitará de uma nova versão do detector de tipo).",
24
+ "nl": "sommige lichte entiteiten hebben hun juiste staat bij het inschakelen niet hersteld. Vast.\nproces mappen-objecten voor auto-entiteiten, ook. (Pirate-weather support)\nvoorbereiding van ondersteuning voor effecten in lichte entiteiten (zal nieuwe type-detector versie nodig hebben).",
25
+ "fr": "certaines entités lumineuses n'ont pas rétabli leur état d'activation. Corrigé.\ntraiter les dossiers-Objects pour les entités auto, aussi. (soutien en temps de pluie)\npréparer le support des effets dans les entités lumineuses (il faudra une nouvelle version de détecteur de type).",
26
+ "it": "alcune entità leggere non hanno ripristinato il loro stato corretto all'accensione. Risolto.\nprocess folders-Objects per entità auto, troppo. (Supporto pirata-matrimoniale)\npreparare il supporto per gli effetti in entità leggere (sarà necessario una nuova versione di tipo-detector).",
27
+ "es": "algunas entidades de luz no restauraron su estado adecuado encendido encendido encendido. Arreglado.\ncarpetas de proceso-Objetos para entidades de automóviles, también. (Apoyo de piratería-tetera)\npreparar soporte para efectos en entidades ligeras (necesitará nueva versión tipo-detector).",
28
+ "pl": "niektóre jednostki świetlne nie przywróciły swojego stanu włączania. Naprawione.\nfoldery procesu- Obiekty dla podmiotów samochodowych, też. (wsparcie pirackiej pogody)\nprzygotować wsparcie dla efektów w jednostkach świetlnych (potrzeba nowej wersji czujnika typu).",
29
+ "uk": "деякі світлові особи не відновили належний стан на перемикачі. Фіксований.\nобробляє папки-об'єкти для автооб'єктів. (приватно-пожежна підтримка)\nпідготувати підтримку ефектів у легких суб’єктах (необхідно потрібна нова версія-детектора).",
30
+ "zh-cn": "一些轻实体没有在开关时恢复正常状态。 固定着.\n用于自动实体的处理文件夹-对象。 (发作天气支持)\n为光实体中的效果准备支持(需要新的类型检测器版本)."
31
+ },
6
32
  "5.0.1": {
7
33
  "en": "* (Garfonso) settings from entity registry are now loaded on startup\n* (Garfonso) logbook: prevent entries from the future\n* (Garfonso) icons should now work as before, again.\n* (Garfonso) script entities now can be used again.\n* (Garfonso) subscribe to all object ids in a template.\n* (Garfonso) Update dependencies.",
8
34
  "de": "* (Garfonso) Einstellungen aus der Entitätsregistrierung werden nun beim Start geladen\n* (Garfonso) Logbuch: Einträge aus der Zukunft verhindern\n* (Garfonso) Icons sollten nun wieder wie zuvor funktionieren.\n* (Garfonso) Skriptentitäten können nun wieder verwendet werden.\n* (Garfonso) alle Objekt-IDs in einer Vorlage abonnieren.\n* (Garfonso) Aktualisieren von Abhängigkeiten.",
@@ -67,32 +93,6 @@
67
93
  "pl": "przerabiane wysyłanie obrazów. Teraz ikony pogodowe działają również dla zwykłych użytkowników. Również obrazy pogody są transfered z naszego serwera, więc nie jest już potrzebny dostęp do admin.",
68
94
  "uk": "переробляти посилку зображення. Ікони погоди працюють для нормальних користувачів. Крім того, погодні зображення передаються з нашого сервера, тому не потрібно доступу до адміну.",
69
95
  "zh-cn": "重新工作图像发送 。 现在天气图标也为正常用户服务. 还有天气图像是从我们的服务器传输的,所以不再需要访问管理员了."
70
- },
71
- "4.1.11": {
72
- "en": "convert string state values to numbers, where necessary.",
73
- "de": "string-zustandswerte gegebenenfalls in zahlen umwandeln.",
74
- "ru": "конвертировать значения состояния строки в числа, когда это необходимо.",
75
- "pt": "converter valores de estado de cadeia para números, quando necessário.",
76
- "nl": "converteer string state waarden naar getallen, waar nodig.",
77
- "fr": "convertir les valeurs d'état de chaîne en nombres, si nécessaire.",
78
- "it": "convertire i valori di stato della stringa in numeri, ove necessario.",
79
- "es": "convertir valores de estado de cadena a números, cuando sea necesario.",
80
- "pl": "w razie potrzeby przekonwertować wartości stanu string do liczb.",
81
- "uk": "перетворюйте значення стану рядків до чисел, де необхідно.",
82
- "zh-cn": "必要时将字符串状态值转换为数字."
83
- },
84
- "4.1.10": {
85
- "en": "device icons work again (if authorization is required).\ndefault user sometimes was not found in system.",
86
- "de": "gerätesymbole funktionieren wieder (wenn authorisierung notwendig).\nder eingestellte standard-benutzer wurde manchmal nicht im system gefunden.",
87
- "ru": "иконки устройства снова работают.\nпользователь по умолчанию иногда не был найден в системе.",
88
- "pt": "ícones do dispositivo funcionam novamente.\nusuário padrão às vezes não foi encontrado no sistema.",
89
- "nl": "apparaatpictogrammen werken opnieuw.\nde standaardgebruiker werd soms niet gevonden in het systeem.",
90
- "fr": "les icônes du périphérique fonctionnent à nouveau.\nl'utilisateur par défaut n'a parfois pas été trouvé dans le système.",
91
- "it": "le icone del dispositivo funzionano di nuovo.\nutente predefinito a volte non è stato trovato nel sistema.",
92
- "es": "los iconos del dispositivo funcionan de nuevo.\nusuario predeterminado a veces no se encontró en el sistema.",
93
- "pl": "ikony urządzenia działają ponownie.\ndomyślny użytkownik czasami nie został znaleziony w systemie.",
94
- "uk": "знову працюють іконки пристрою.\nне знайдено типовий користувач.",
95
- "zh-cn": "设备图标再次工作.\n默认用户有时在系统中找不到 ."
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -80,7 +80,7 @@ function clearOrRestoreAttributes(entity) {
80
80
  entity.attributes[attr] = entity.context.STATE.storedValues[attr];
81
81
  }
82
82
  }
83
- //adapterData.log.debug(`Stored old values for next switch on: ${JSON.stringify(entity.context.STATE.storedValues)}`);
83
+ //adapterData.log.debug(`Restored old values from previous switch off: ${JSON.stringify(entity.attributes)}`);
84
84
  } else {
85
85
  for (const attr of attributesToNullOnOff) {
86
86
  if (entity.attributes[attr] !== undefined) {
@@ -88,7 +88,9 @@ function clearOrRestoreAttributes(entity) {
88
88
  entity.attributes[attr] = null;
89
89
  }
90
90
  }
91
- //adapterData.log.debug(`Restored old values from previous switch off: ${JSON.stringify(entity.attributes)}`);
91
+ /*adapterData.log.debug(
92
+ `Stored old values for next switch on: ${JSON.stringify(entity.context.STATE.storedValues)}`,
93
+ );*/
92
94
  }
93
95
  }
94
96
 
@@ -108,8 +110,11 @@ function _lightAdvancedAddState(states, objects, entity) {
108
110
  if (!state) {
109
111
  state = { val: null };
110
112
  }
113
+ const oldState = entity.state;
111
114
  entity.state = state.val ? 'on' : 'off';
112
- clearOrRestoreAttributes(entity);
115
+ if (oldState !== entity.state) {
116
+ clearOrRestoreAttributes(entity);
117
+ }
113
118
  };
114
119
 
115
120
  //prevent zigbee 'available' to become getId:
@@ -248,8 +253,11 @@ function _lightAdvancedAddBrightness(states, objects, entity) {
248
253
  }
249
254
 
250
255
  if (states.state === states.brightness) {
256
+ const oldState = entity.state;
251
257
  entity.state = targetAttributes.brightness > 0 ? 'on' : 'off';
252
- clearOrRestoreAttributes(entity);
258
+ if (oldState !== entity.state) {
259
+ clearOrRestoreAttributes(entity);
260
+ }
253
261
 
254
262
  if (entity.attributes.color_mode === ONOFF) {
255
263
  entity.attributes.color_mode = BRIGHTNESS;
@@ -490,9 +498,6 @@ async function _setLightAdvancedAttributesToIOBStates(data, entity, user) {
490
498
  if (data.service_data.brightness_pct >= 0) {
491
499
  const attr = entity.context.ATTRIBUTES.find(a => a.attribute === 'brightness');
492
500
  entity.attributes.brightness = (data.service_data.brightness_pct / 100) * 255;
493
- if (!entity.context.STATE.isBoolean) {
494
- entity.state = data.service_data.brightness_pct > 0 ? 'on' : 'off';
495
- }
496
501
  if (!entity.attributes.color_mode || entity.attributes.color_mode === ONOFF) {
497
502
  entity.attributes.color_mode = BRIGHTNESS;
498
503
  }
@@ -631,6 +636,7 @@ function convertControlToStates(control) {
631
636
  if (!states.brightness) {
632
637
  states.brightness = findState('BRIGHTNESS');
633
638
  }
639
+ states.effect = findState('EFFECT');
634
640
  break;
635
641
  case Types.dimmer:
636
642
  states.state = findState('ON_SET');
@@ -643,10 +649,12 @@ function convertControlToStates(control) {
643
649
  }
644
650
  states.brightness = findState('SET');
645
651
  states.brightnessRead = findState('ACTUAL');
652
+ states.effect = findState('EFFECT');
646
653
  break;
647
654
  case Types.light:
648
655
  states.state = findState('SET');
649
656
  states.stateRead = findState('ACTUAL');
657
+ states.effect = findState('EFFECT');
650
658
  break;
651
659
  }
652
660
  states.color_temp = findState('TEMPERATURE');
@@ -733,9 +741,7 @@ async function fillLightEntityFromStates(states, objects, entity) {
733
741
 
734
742
  if (states.effect) {
735
743
  const effect_attr = entity.context.ATTRIBUTES.find(a => a.attributes === 'effect');
736
- effect_attr.states = (objects[effect_attr.getId] &&
737
- objects[effect_attr.getId].common &&
738
- objects[effect_attr.getId].common.states) || { 0: 'Please', 1: 'Fill', 2: 'States' };
744
+ effect_attr.states = objects[effect_attr.getId]?.common?.states || { 0: 'Please', 1: 'Fill', 2: 'States' };
739
745
  entity.attributes.effect_list = Object.values(effect_attr.states);
740
746
  effect_attr.getParser = (entity, attr, state) => {
741
747
  state = state || { val: 0 };
@@ -767,10 +773,14 @@ async function fillLightEntityFromStates(states, objects, entity) {
767
773
  });
768
774
  entity.context.STATE.getParser = function (entity, attr, state) {
769
775
  state = state || { val: null };
776
+ const oldState = entity.state;
770
777
  entity.state = state.val > ((stateObj && stateObj.common && stateObj.common.min) || 0) ? 'on' : 'off';
771
778
  if (!entity.attributes.color_mode) {
772
779
  entity.attributes.color_mode = ONOFF;
773
780
  }
781
+ if (oldState !== entity.state) {
782
+ clearOrRestoreAttributes(entity);
783
+ }
774
784
  };
775
785
  }
776
786
 
package/lib/server.js CHANGED
@@ -1377,6 +1377,7 @@ class WebServer {
1377
1377
  const _states = await this.adapter.getObjectViewAsync('system', 'state', params);
1378
1378
  const _channels = await this.adapter.getObjectViewAsync('system', 'channel', params);
1379
1379
  const _devices = await this.adapter.getObjectViewAsync('system', 'device', params);
1380
+ const _folders = await this.adapter.getObjectViewAsync('system', 'folder', {});
1380
1381
  const _enums = await this.adapter.getObjectViewAsync('system', 'enum', {});
1381
1382
  if (_devices && _devices.rows) {
1382
1383
  for (let i = 0; i < _devices.rows.length; i++) {
@@ -1411,6 +1412,17 @@ class WebServer {
1411
1412
  }
1412
1413
  }
1413
1414
  }
1415
+ if (_folders && _folders.rows) {
1416
+ for (let i = 0; i < _folders.rows.length; i++) {
1417
+ if (
1418
+ _folders.rows[i].value &&
1419
+ _folders.rows[i].value._id &&
1420
+ !ignoreIds.find(reg => reg.test(_folders.rows[i].value._id))
1421
+ ) {
1422
+ objects[_folders.rows[i].value._id] = _folders.rows[i].value;
1423
+ }
1424
+ }
1425
+ }
1414
1426
  if (_enums && _enums.rows) {
1415
1427
  for (let i = 0; i < _enums.rows.length; i++) {
1416
1428
  if (_enums.rows[i].value && _enums.rows[i].value._id) {
@@ -1932,8 +1944,20 @@ class WebServer {
1932
1944
  for (const themeName of Object.keys(this._themes)) {
1933
1945
  states[themeName] = themeName;
1934
1946
  }
1935
- await this.adapter.extendObjectAsync(`${this.adapter.namespace}.control.theme`, { common: { states } });
1936
- await this.adapter.extendObjectAsync(`${this.adapter.namespace}.control.themeDark`, { common: { states } });
1947
+ const themeState = await this.adapter.getObjectAsync(`${this.adapter.namespace}.control.theme`);
1948
+ if (themeState && themeState.common) {
1949
+ themeState.common.states = states;
1950
+ await this.adapter.setObject(`${this.adapter.namespace}.control.theme`, themeState);
1951
+ } else {
1952
+ this.log.warn(`State ${this.adapter.namespace}.control.theme missing`);
1953
+ }
1954
+ const themeDarkState = await this.adapter.getObjectAsync(`${this.adapter.namespace}.control.themeDark`);
1955
+ if (themeDarkState && themeDarkState.common) {
1956
+ themeDarkState.common.states = states;
1957
+ await this.adapter.setObject(`${this.adapter.namespace}.control.themeDark`, themeDarkState);
1958
+ } else {
1959
+ this.log.warn(`State ${this.adapter.namespace}.control.themeDark missing`);
1960
+ }
1937
1961
 
1938
1962
  const state = await this.adapter.getStateAsync(`${this.adapter.namespace}.control.theme`);
1939
1963
  // remember the currently selected theme, if valid. Select default otherwise.
@@ -2265,6 +2289,12 @@ class WebServer {
2265
2289
  const filePath = req.url.replace(/.*\/frontend_latest\//, 'frontend_latest/');
2266
2290
  res.setHeader('Cache-Control', `public, max-age=${staticOptions.maxAge}`);
2267
2291
  res.sendFile(`${getRootPath()}${filePath}`);
2292
+ } else if (req.url.includes('/frontend_es5/')) {
2293
+ //serve frontend:
2294
+ //remove all from before frontend_es5.
2295
+ const filePath = req.url.replace(/.*\/frontend_es5\//, 'frontend_es5/');
2296
+ res.setHeader('Cache-Control', `public, max-age=${staticOptions.maxAge}`);
2297
+ res.sendFile(`${getRootPath()}${filePath}`);
2268
2298
  } else if (req.url.includes('/static/icons/')) {
2269
2299
  //iobroker icons:
2270
2300
  const filePath = req.url.replace(/.*\/static\/icons\//, '');
@@ -2407,7 +2437,7 @@ class WebServer {
2407
2437
  });
2408
2438
 
2409
2439
  this._app.use((req, res) => {
2410
- this.log.debug(`Unknown request for ${req.url}`);
2440
+ this.log.info(`Unknown request for ${req.url}`);
2411
2441
  //res.send('unknown');
2412
2442
  res.send(this._renderIndex());
2413
2443
  });
@@ -3098,7 +3128,7 @@ class WebServer {
3098
3128
  }
3099
3129
  }
3100
3130
  if (!result) {
3101
- console.warn(`Unknown request: ${JSON.stringify(message)}`);
3131
+ this.log.info(`Unknown request: ${JSON.stringify(message)}`);
3102
3132
  ws.send(
3103
3133
  JSON.stringify({
3104
3134
  id: message.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.lovelace",
3
- "version": "5.0.1",
3
+ "version": "5.0.3",
4
4
  "description": "With this adapter you can build visualization for ioBroker with Home Assistant Lovelace UI",
5
5
  "author": {
6
6
  "name": "bluefox",