iobroker.hassemu 1.29.2 → 1.29.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
@@ -167,6 +167,11 @@ Got scripts that still write to `visUrl`? Update them — write to `manualUrl` i
167
167
  Placeholder for the next version (at the beginning of the line):
168
168
  ### **WORK IN PROGRESS**
169
169
  -->
170
+ ### 1.29.3 (2026-05-12)
171
+
172
+ - The "Connection to Home Assistant failed" popup on Shelly Wall Display 2.6.0+ also stays away when the landing page is shown (no URL configured yet). v1.29.2 only suppressed it when a target URL was set.
173
+ - Replaced the landing-page emblem with the real ioBroker brand mark (power-button "i" inside a ring).
174
+
170
175
  ### 1.29.2 (2026-05-12)
171
176
 
172
177
  - Shelly Wall Display on firmware 2.6.0+ no longer shows the connection-error popup after the page has loaded.
@@ -185,10 +190,6 @@ Got scripts that still write to `visUrl`? Update them — write to `manualUrl` i
185
190
 
186
191
  - The mode dropdowns in admin (global and per-client) no longer crash with "Error in GUI" when opened.
187
192
 
188
- ### 1.28.3 (2026-05-10)
189
-
190
- - Adapter starts faster on installations with many displays, and a single broken client entry no longer keeps the others from being restored. Plus a security tighten-up around the HA login flow.
191
-
192
193
  Older entries are in [CHANGELOG_OLD.md](CHANGELOG_OLD.md).
193
194
 
194
195
  ## Support
@@ -21,7 +21,7 @@ __export(landing_page_exports, {
21
21
  renderLandingPage: () => renderLandingPage
22
22
  });
23
23
  module.exports = __toCommonJS(landing_page_exports);
24
- const LOGO_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="ioBroker"><circle cx="32" cy="32" r="30" fill="#41BDF5"/><path d="M32 12 L12 28 L12 52 L24 52 L24 38 L40 38 L40 52 L52 52 L52 28 Z" fill="#ffffff" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"/><path d="M20 44 Q32 36 44 44" fill="none" stroke="#41BDF5" stroke-width="3" stroke-linecap="round"/><circle cx="20" cy="44" r="3" fill="#41BDF5"/><circle cx="44" cy="44" r="3" fill="#41BDF5"/></svg>';
24
+ const LOGO_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" role="img" aria-label="ioBroker"><circle cx="50" cy="50" r="42" fill="none" stroke="#1F537E" stroke-width="10"/><rect x="44" y="20" width="12" height="60" rx="2" fill="#2B95C6"/><rect x="44" y="26" width="12" height="6" fill="#ffffff"/></svg>';
25
25
  const STRINGS = {
26
26
  en: {
27
27
  htmlLang: "en",
@@ -402,6 +402,34 @@ footer .brand svg { width: 0.95rem; height: 0.95rem; display: block; }
402
402
  <span class="brand" aria-hidden="true">${LOGO_SVG} ioBroker</span>
403
403
  </footer>
404
404
  </main>
405
+ <script>
406
+ (function(){
407
+ // Same connection-status signal as renderRedirectWrapper \u2014 the HA Companion
408
+ // App on Shelly Wall Display FW 2.6.0+ shows "Verbindung zu Home Assistant
409
+ // nicht m\xF6glich" after 10 s if it doesn't see this message. The popup is
410
+ // unrelated to whether a URL is configured, so the landing page must signal
411
+ // "connected" too. Source: home-assistant/android FrontendMessageHandler.kt +
412
+ // FrontendJsBridge.kt + frontend/src/external_app/external_messaging.ts.
413
+ function notifyConnected(){
414
+ try {
415
+ var v1Payload = JSON.stringify({id:1,type:"connection-status",payload:{event:"connected"}});
416
+ if (window.externalApp && typeof window.externalApp.externalBus === "function") {
417
+ window.externalApp.externalBus(v1Payload);
418
+ return;
419
+ }
420
+ if (window.externalAppV2 && typeof window.externalAppV2.postMessage === "function") {
421
+ window.externalAppV2.postMessage(JSON.stringify({
422
+ type:"externalBus",
423
+ payload:{id:1,type:"connection-status",payload:{event:"connected"}}
424
+ }));
425
+ }
426
+ } catch (e) { /* silent \u2014 bridge not present, regular browser */ }
427
+ }
428
+ notifyConnected();
429
+ setTimeout(notifyConnected, 500);
430
+ setTimeout(notifyConnected, 2000);
431
+ })();
432
+ </script>
405
433
  </body>
406
434
  </html>`;
407
435
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/landing-page.ts"],
4
- "sourcesContent": ["/**\n * Landing page served to a display whose redirect URL is not yet configured.\n *\n * Goal: give the end-user a strong visual \"everything is connected, now just\n * pick a URL\" signal \u2014 big green check, three clear steps, adapter-local copy\n * in the ioBroker system language. Auto-refreshes every 15 s so the display\n * jumps to the real URL the moment the state is written.\n */\n\n/**\n * Inline ioBroker / hassemu logo SVG. Mirrors admin/hassemu.svg so the landing\n * page is self-contained (no extra HTTP request, works behind a strict CSP).\n * Background circle is the ioBroker brand blue (#41BDF5); inner glyph is a\n * Home-Assistant-style house with a connection arc \u2014 a deliberate nod to what\n * this adapter does.\n */\nconst LOGO_SVG =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 64 64\" role=\"img\" aria-label=\"ioBroker\">' +\n '<circle cx=\"32\" cy=\"32\" r=\"30\" fill=\"#41BDF5\"/>' +\n '<path d=\"M32 12 L12 28 L12 52 L24 52 L24 38 L40 38 L40 52 L52 52 L52 28 Z\" fill=\"#ffffff\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\"/>' +\n '<path d=\"M20 44 Q32 36 44 44\" fill=\"none\" stroke=\"#41BDF5\" stroke-width=\"3\" stroke-linecap=\"round\"/>' +\n '<circle cx=\"20\" cy=\"44\" r=\"3\" fill=\"#41BDF5\"/>' +\n '<circle cx=\"44\" cy=\"44\" r=\"3\" fill=\"#41BDF5\"/>' +\n '</svg>';\n\n/** Supported languages \u2014 matches the 11 io-package.json translations. */\nexport type LandingLanguage = 'en' | 'de' | 'ru' | 'pt' | 'nl' | 'fr' | 'it' | 'es' | 'pl' | 'uk' | 'zh-cn';\n\n/** One translation bundle for the landing page. */\ninterface LandingStrings {\n htmlLang: string;\n pageTitle: string;\n heading: string;\n subhead: string;\n deviceIdLabel: string;\n ipLabel: string;\n setupTitle: string;\n setupIntro: string;\n step1: string;\n step2: string;\n step3: string;\n autoRefresh: string;\n}\n\n/** Translation table \u2014 EN is the fallback for any missing language. */\nconst STRINGS = {\n en: {\n htmlLang: 'en',\n pageTitle: 'Connected \u00B7 ioBroker',\n heading: 'Display connected',\n subhead: 'This display is linked to ioBroker. Choose a redirect URL to finish setup.',\n deviceIdLabel: 'Device ID',\n ipLabel: 'IP address',\n setupTitle: 'Finish setup',\n setupIntro: 'Set the URL that this display should open on next refresh:',\n step1: 'Open the ioBroker admin and switch to the Objects view.',\n step2: 'Go to this datapoint:',\n step3: 'Enter the URL you want to show here (VIS project, Grafana, dashboard, \u2026).',\n autoRefresh: 'This page refreshes automatically every 15 seconds.',\n },\n de: {\n htmlLang: 'de',\n pageTitle: 'Verbunden \u00B7 ioBroker',\n heading: 'Display verbunden',\n subhead: 'Dieses Display ist mit ioBroker verbunden. W\u00E4hle noch eine Weiterleitungs-URL aus.',\n deviceIdLabel: 'Ger\u00E4te-ID',\n ipLabel: 'IP-Adresse',\n setupTitle: 'Einrichtung abschlie\u00DFen',\n setupIntro: 'Lege fest, welche URL das Display beim n\u00E4chsten Refresh \u00F6ffnen soll:',\n step1: '\u00D6ffne im ioBroker-Admin die Ansicht \u201EObjekte\".',\n step2: 'Navigiere zu diesem Datenpunkt:',\n step3: 'Trage hier die gew\u00FCnschte URL ein (VIS-Projekt, Grafana, Dashboard, \u2026).',\n autoRefresh: 'Diese Seite aktualisiert sich automatisch alle 15 Sekunden.',\n },\n ru: {\n htmlLang: 'ru',\n pageTitle: '\u041F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043E \u00B7 ioBroker',\n heading: '\u0414\u0438\u0441\u043F\u043B\u0435\u0439 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0451\u043D',\n subhead: '\u042D\u0442\u043E\u0442 \u0434\u0438\u0441\u043F\u043B\u0435\u0439 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0451\u043D \u043A ioBroker. \u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 URL \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043D\u0430\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F.',\n deviceIdLabel: 'ID \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u0430',\n ipLabel: 'IP-\u0430\u0434\u0440\u0435\u0441',\n setupTitle: '\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u0435 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438',\n setupIntro: '\u0423\u043A\u0430\u0436\u0438\u0442\u0435 URL, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0434\u0438\u0441\u043F\u043B\u0435\u0439 \u043E\u0442\u043A\u0440\u043E\u0435\u0442 \u043F\u0440\u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0438:',\n step1: '\u041E\u0442\u043A\u0440\u043E\u0439\u0442\u0435 \u0430\u0434\u043C\u0438\u043D\u043A\u0443 ioBroker \u0438 \u043F\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043B \u00AB\u041E\u0431\u044A\u0435\u043A\u0442\u044B\u00BB.',\n step2: '\u041F\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043A \u044D\u0442\u043E\u043C\u0443 \u0434\u0430\u0442\u0430\u043F\u0443\u043D\u043A\u0442\u0443:',\n step3: '\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u0443\u0436\u043D\u044B\u0439 URL (\u043F\u0440\u043E\u0435\u043A\u0442 VIS, Grafana, \u0434\u0430\u0448\u0431\u043E\u0440\u0434 \u0438 \u0442. \u0434.).',\n autoRefresh: '\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u043A\u0430\u0436\u0434\u044B\u0435 15 \u0441\u0435\u043A\u0443\u043D\u0434.',\n },\n pt: {\n htmlLang: 'pt',\n pageTitle: 'Conectado \u00B7 ioBroker',\n heading: 'Display conectado',\n subhead: 'Este display est\u00E1 conectado ao ioBroker. Escolha um URL de redirecionamento.',\n deviceIdLabel: 'ID do dispositivo',\n ipLabel: 'Endere\u00E7o IP',\n setupTitle: 'Concluir configura\u00E7\u00E3o',\n setupIntro: 'Defina o URL que este display deve abrir na pr\u00F3xima atualiza\u00E7\u00E3o:',\n step1: 'Abra o admin do ioBroker e mude para a vis\u00E3o de Objetos.',\n step2: 'Navegue at\u00E9 este datapoint:',\n step3: 'Insira o URL desejado (projeto VIS, Grafana, dashboard, \u2026).',\n autoRefresh: 'Esta p\u00E1gina atualiza automaticamente a cada 15 segundos.',\n },\n nl: {\n htmlLang: 'nl',\n pageTitle: 'Verbonden \u00B7 ioBroker',\n heading: 'Display verbonden',\n subhead: 'Dit display is met ioBroker verbonden. Kies een redirect-URL om de setup af te ronden.',\n deviceIdLabel: 'Apparaat-ID',\n ipLabel: 'IP-adres',\n setupTitle: 'Setup afronden',\n setupIntro: 'Stel de URL in die dit display bij de volgende refresh moet openen:',\n step1: 'Open de ioBroker-admin en ga naar de Objects-weergave.',\n step2: 'Navigeer naar dit datapoint:',\n step3: 'Voer hier de gewenste URL in (VIS-project, Grafana, dashboard, \u2026).',\n autoRefresh: 'Deze pagina vernieuwt zich automatisch elke 15 seconden.',\n },\n fr: {\n htmlLang: 'fr',\n pageTitle: 'Connect\u00E9 \u00B7 ioBroker',\n heading: '\u00C9cran connect\u00E9',\n subhead: \"Cet \u00E9cran est reli\u00E9 \u00E0 ioBroker. Choisissez l'URL de redirection pour terminer la configuration.\",\n deviceIdLabel: \"Identifiant de l'appareil\",\n ipLabel: 'Adresse IP',\n setupTitle: 'Finaliser la configuration',\n setupIntro: \"Indiquez l'URL que cet \u00E9cran doit ouvrir \u00E0 la prochaine actualisation :\",\n step1: \"Ouvrez l'admin ioBroker et passez \u00E0 la vue Objets.\",\n step2: 'Allez sur ce datapoint :',\n step3: \"Saisissez ici l'URL souhait\u00E9e (projet VIS, Grafana, tableau de bord, \u2026).\",\n autoRefresh: 'Cette page se rafra\u00EEchit automatiquement toutes les 15 secondes.',\n },\n it: {\n htmlLang: 'it',\n pageTitle: 'Connesso \u00B7 ioBroker',\n heading: 'Display connesso',\n subhead:\n 'Questo display \u00E8 collegato a ioBroker. Scegli un URL di reindirizzamento per completare la configurazione.',\n deviceIdLabel: 'ID dispositivo',\n ipLabel: 'Indirizzo IP',\n setupTitle: 'Completa la configurazione',\n setupIntro: \"Imposta l'URL che il display deve aprire al prossimo aggiornamento:\",\n step1: \"Apri l'admin di ioBroker e passa alla vista Oggetti.\",\n step2: 'Vai a questo datapoint:',\n step3: \"Inserisci qui l'URL desiderato (progetto VIS, Grafana, dashboard, \u2026).\",\n autoRefresh: 'Questa pagina si aggiorna automaticamente ogni 15 secondi.',\n },\n es: {\n htmlLang: 'es',\n pageTitle: 'Conectado \u00B7 ioBroker',\n heading: 'Pantalla conectada',\n subhead:\n 'Esta pantalla est\u00E1 vinculada a ioBroker. Elige una URL de redirecci\u00F3n para terminar la configuraci\u00F3n.',\n deviceIdLabel: 'ID del dispositivo',\n ipLabel: 'Direcci\u00F3n IP',\n setupTitle: 'Completar configuraci\u00F3n',\n setupIntro: 'Indica la URL que esta pantalla abrir\u00E1 en la pr\u00F3xima actualizaci\u00F3n:',\n step1: 'Abre el admin de ioBroker y cambia a la vista Objetos.',\n step2: 'Navega hasta este datapoint:',\n step3: 'Introduce aqu\u00ED la URL deseada (proyecto VIS, Grafana, panel, \u2026).',\n autoRefresh: 'Esta p\u00E1gina se actualiza autom\u00E1ticamente cada 15 segundos.',\n },\n pl: {\n htmlLang: 'pl',\n pageTitle: 'Po\u0142\u0105czono \u00B7 ioBroker',\n heading: 'Wy\u015Bwietlacz po\u0142\u0105czony',\n subhead: 'Ten wy\u015Bwietlacz jest po\u0142\u0105czony z ioBrokerem. Wybierz adres URL przekierowania.',\n deviceIdLabel: 'ID urz\u0105dzenia',\n ipLabel: 'Adres IP',\n setupTitle: 'Zako\u0144cz konfiguracj\u0119',\n setupIntro: 'Ustaw URL, kt\u00F3ry ma otwiera\u0107 ten wy\u015Bwietlacz przy nast\u0119pnym od\u015Bwie\u017Ceniu:',\n step1: 'Otw\u00F3rz panel ioBroker i przejd\u017A do widoku Obiekt\u00F3w.',\n step2: 'Przejd\u017A do tego datapointu:',\n step3: 'Wpisz tutaj \u017C\u0105dany URL (projekt VIS, Grafana, dashboard, \u2026).',\n autoRefresh: 'Ta strona od\u015Bwie\u017Ca si\u0119 automatycznie co 15 sekund.',\n },\n uk: {\n htmlLang: 'uk',\n pageTitle: \"\u0417'\u0454\u0434\u043D\u0430\u043D\u043E \u00B7 ioBroker\",\n heading: \"\u0414\u0438\u0441\u043F\u043B\u0435\u0439 \u043F\u0456\u0434'\u0454\u0434\u043D\u0430\u043D\u043E\",\n subhead: \"\u0426\u0435\u0439 \u0434\u0438\u0441\u043F\u043B\u0435\u0439 \u0437'\u0454\u0434\u043D\u0430\u043D\u043E \u0437 ioBroker. \u041E\u0431\u0435\u0440\u0456\u0442\u044C URL \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043D\u0430\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044F.\",\n deviceIdLabel: 'ID \u043F\u0440\u0438\u0441\u0442\u0440\u043E\u044E',\n ipLabel: 'IP-\u0430\u0434\u0440\u0435\u0441\u0430',\n setupTitle: '\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0438 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F',\n setupIntro: '\u0412\u043A\u0430\u0436\u0456\u0442\u044C URL, \u044F\u043A\u0438\u0439 \u0434\u0438\u0441\u043F\u043B\u0435\u0439 \u0432\u0456\u0434\u043A\u0440\u0438\u0454 \u043F\u0440\u0438 \u043D\u0430\u0441\u0442\u0443\u043F\u043D\u043E\u043C\u0443 \u043E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u0456:',\n step1: \"\u0412\u0456\u0434\u043A\u0440\u0438\u0439\u0442\u0435 \u0430\u0434\u043C\u0456\u043D ioBroker \u0456 \u043F\u0435\u0440\u0435\u0439\u0434\u0456\u0442\u044C \u0434\u043E \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\u0443 \u00AB\u041E\u0431'\u0454\u043A\u0442\u0438\u00BB.\",\n step2: '\u041F\u0435\u0440\u0435\u0439\u0434\u0456\u0442\u044C \u0434\u043E \u0446\u044C\u043E\u0433\u043E \u0434\u0430\u0442\u0430\u043F\u043E\u0456\u043D\u0442\u0430:',\n step3: '\u0412\u0432\u0435\u0434\u0456\u0442\u044C \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u0438\u0439 URL (\u043F\u0440\u043E\u0454\u043A\u0442 VIS, Grafana, \u0434\u0430\u0448\u0431\u043E\u0440\u0434, \u2026).',\n autoRefresh: '\u0426\u044F \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0430 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E \u043E\u043D\u043E\u0432\u043B\u044E\u0454\u0442\u044C\u0441\u044F \u043A\u043E\u0436\u043D\u0456 15 \u0441\u0435\u043A\u0443\u043D\u0434.',\n },\n 'zh-cn': {\n htmlLang: 'zh-CN',\n pageTitle: '\u5DF2\u8FDE\u63A5 \u00B7 ioBroker',\n heading: '\u663E\u793A\u5668\u5DF2\u8FDE\u63A5',\n subhead: '\u6B64\u663E\u793A\u5668\u5DF2\u8FDE\u63A5\u5230 ioBroker\u3002\u8BF7\u9009\u62E9\u8DF3\u8F6C URL \u4EE5\u5B8C\u6210\u8BBE\u7F6E\u3002',\n deviceIdLabel: '\u8BBE\u5907 ID',\n ipLabel: 'IP \u5730\u5740',\n setupTitle: '\u5B8C\u6210\u8BBE\u7F6E',\n setupIntro: '\u8BBE\u7F6E\u6B64\u663E\u793A\u5668\u4E0B\u6B21\u5237\u65B0\u65F6\u8981\u6253\u5F00\u7684 URL\uFF1A',\n step1: '\u6253\u5F00 ioBroker \u7BA1\u7406\u754C\u9762\u5E76\u5207\u6362\u5230\u300C\u5BF9\u8C61\u300D\u89C6\u56FE\u3002',\n step2: '\u5BFC\u822A\u5230\u6B64\u6570\u636E\u70B9\uFF1A',\n step3: '\u5728\u6B64\u5904\u8F93\u5165\u6240\u9700\u7684 URL\uFF08VIS \u9879\u76EE\u3001Grafana\u3001\u4EEA\u8868\u677F\u7B49\uFF09\u3002',\n autoRefresh: '\u6B64\u9875\u9762\u6BCF 15 \u79D2\u81EA\u52A8\u5237\u65B0\u4E00\u6B21\u3002',\n },\n} as const satisfies Record<LandingLanguage, LandingStrings>;\n\n/**\n * Render the landing page.\n *\n * @param clientId Short client id of this display.\n * @param namespace Adapter namespace (e.g. `hassemu.0`).\n * @param language Desired UI language, resolved from `system.config.language`.\n * @param ip Optional remote IP of the display, shown next to the ID.\n */\nexport function renderLandingPage(\n clientId: string,\n namespace: string,\n language: string = 'en',\n ip: string | null = null,\n): string {\n const s = STRINGS[language as LandingLanguage] ?? STRINGS.en;\n const id = escapeHtml(clientId);\n const ns = escapeHtml(namespace);\n const datapoint = `${ns}.clients.${id}.mode`;\n // v1.16.0 (E3): Loopback-IPs nicht anzeigen \u2014 der End-User sieht sonst\n // \u201Elocalhost\" / \u201E127.0.0.1\" / \u201E::1\" als sein Display-IP, was bei Proxy-\n // Setups verwirrt (Display sitzt am Reverse-Proxy, nicht am Adapter).\n // Ohne IP-Zeile f\u00E4llt die Tabellen-Zeile einfach weg, alles andere bleibt.\n const trimmedIp = ip?.trim() ?? '';\n const isLoopback =\n trimmedIp === '' ||\n trimmedIp === '127.0.0.1' ||\n trimmedIp === '::1' ||\n trimmedIp === '0.0.0.0' ||\n trimmedIp.startsWith('127.');\n const ipLine = isLoopback\n ? ''\n : `<tr><th scope=\"row\">${escapeHtml(s.ipLabel)}</th><td>${escapeHtml(trimmedIp)}</td></tr>`;\n\n return `<!DOCTYPE html>\n<html lang=\"${escapeHtml(s.htmlLang)}\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<meta http-equiv=\"refresh\" content=\"15\">\n<title>${escapeHtml(s.pageTitle)}</title>\n<style>\n:root {\n --bg: #f5f7fa;\n --card-bg: #ffffff;\n --text: #1f2933;\n --muted: #52606d;\n --ok-bg: #16a34a;\n --ok-bg-soft: #dcfce7;\n --ok-text: #14532d;\n --accent: #0369a1;\n --border: #e4e7eb;\n --code-bg: #eef2f7;\n --shadow: 0 4px 18px rgba(15, 23, 42, 0.08);\n}\n@media (prefers-color-scheme: dark) {\n :root {\n --bg: #0f172a;\n --card-bg: #1e293b;\n --text: #f1f5f9;\n --muted: #94a3b8;\n --ok-bg-soft: #052e16;\n --ok-text: #bbf7d0;\n --accent: #38bdf8;\n --border: #334155;\n --code-bg: #0f172a;\n --shadow: 0 4px 18px rgba(0, 0, 0, 0.35);\n }\n}\n* { box-sizing: border-box; }\nhtml, body { height: 100%; }\nbody {\n margin: 0;\n background: var(--bg);\n color: var(--text);\n font: 16px/1.5 system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n}\nmain {\n width: 100%;\n max-width: 44rem;\n background: var(--card-bg);\n border-radius: 12px;\n box-shadow: var(--shadow);\n overflow: hidden;\n}\n.banner {\n background: var(--ok-bg);\n color: #ffffff;\n padding: 1.4rem 1.8rem;\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n.banner .logo {\n width: 3.2rem;\n height: 3.2rem;\n flex-shrink: 0;\n background: #ffffff;\n border-radius: 50%;\n padding: 0.25rem;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n.banner .logo svg { display: block; width: 100%; height: 100%; }\n.banner .check {\n width: 1.8rem;\n height: 1.8rem;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.22);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n font-size: 1.1rem;\n line-height: 1;\n font-weight: 700;\n}\n.banner h1 {\n margin: 0;\n font-size: 1.4rem;\n font-weight: 600;\n letter-spacing: 0.01em;\n}\n.banner p {\n margin: 0.15rem 0 0;\n font-size: 0.95rem;\n opacity: 0.95;\n}\n.content {\n padding: 1.6rem 1.8rem 1.3rem;\n}\n.info {\n margin: 0 0 1.4rem;\n width: 100%;\n border-collapse: collapse;\n font-size: 0.95rem;\n}\n.info th, .info td {\n padding: 0.55rem 0.7rem;\n text-align: left;\n border-bottom: 1px solid var(--border);\n}\n.info th {\n font-weight: 500;\n color: var(--muted);\n white-space: nowrap;\n width: 9rem;\n}\n.info tr:last-child th, .info tr:last-child td {\n border-bottom: none;\n}\n.info code {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n background: var(--code-bg);\n padding: 0.15rem 0.45rem;\n border-radius: 4px;\n font-size: 0.9em;\n}\n.setup h2 {\n margin: 0 0 0.6rem;\n font-size: 1.05rem;\n font-weight: 600;\n color: var(--accent);\n}\n.setup > p {\n margin: 0 0 0.9rem;\n color: var(--muted);\n}\n.steps {\n margin: 0;\n padding-left: 1.4rem;\n color: var(--text);\n}\n.steps li {\n margin: 0.5rem 0;\n}\n.steps code {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n background: var(--code-bg);\n padding: 0.15rem 0.45rem;\n border-radius: 4px;\n font-size: 0.88em;\n word-break: break-all;\n}\nfooter {\n padding: 0.9rem 1.8rem;\n border-top: 1px solid var(--border);\n font-size: 0.8rem;\n color: var(--muted);\n text-align: center;\n}\nfooter .brand {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n margin-left: 0.6rem;\n color: var(--accent);\n font-weight: 500;\n}\nfooter .brand svg { width: 0.95rem; height: 0.95rem; display: block; }\n@media (max-width: 30rem) {\n body { padding: 0; }\n main { border-radius: 0; box-shadow: none; height: 100%; }\n .banner { padding: 1.1rem 1.2rem; }\n .banner h1 { font-size: 1.2rem; }\n .content { padding: 1.2rem 1.2rem 1rem; }\n .info th { width: auto; }\n footer { padding: 0.9rem 1.2rem; }\n}\n</style>\n</head>\n<body>\n<main>\n <div class=\"banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"logo\" aria-hidden=\"true\">${LOGO_SVG}</div>\n <div class=\"check\" aria-hidden=\"true\">\u2713</div>\n <div>\n <h1>${escapeHtml(s.heading)}</h1>\n <p>${escapeHtml(s.subhead)}</p>\n </div>\n </div>\n <div class=\"content\">\n <table class=\"info\">\n <tbody>\n <tr>\n <th scope=\"row\">${escapeHtml(s.deviceIdLabel)}</th>\n <td><code>${id}</code></td>\n </tr>\n ${ipLine}\n </tbody>\n </table>\n <section class=\"setup\">\n <h2>${escapeHtml(s.setupTitle)}</h2>\n <p>${escapeHtml(s.setupIntro)}</p>\n <ol class=\"steps\">\n <li>${escapeHtml(s.step1)}</li>\n <li>${escapeHtml(s.step2)} <code>${escapeHtml(datapoint)}</code></li>\n <li>${escapeHtml(s.step3)}</li>\n </ol>\n </section>\n </div>\n <footer>\n ${escapeHtml(s.autoRefresh)}\n <span class=\"brand\" aria-hidden=\"true\">${LOGO_SVG} ioBroker</span>\n </footer>\n</main>\n</body>\n</html>`;\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/[<>&\"']/g, c => {\n switch (c) {\n case '<':\n return '&lt;';\n case '>':\n return '&gt;';\n case '&':\n return '&amp;';\n case '\"':\n return '&quot;';\n default:\n return '&#39;';\n }\n });\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Landing page served to a display whose redirect URL is not yet configured.\n *\n * Goal: give the end-user a strong visual \"everything is connected, now just\n * pick a URL\" signal \u2014 big green check, three clear steps, adapter-local copy\n * in the ioBroker system language. Auto-refreshes every 15 s so the display\n * jumps to the real URL the moment the state is written.\n */\n\n/**\n * Inline ioBroker brand logo \u2014 the power-button \"i\" inside a ring.\n * Source: github.com/ioBroker organization avatar (the canonical mark used\n * across the project). Two-tone: dark navy outer ring (#1F537E), mid-blue\n * vertical \"i\" (#2B95C6), white power-button gap at the top.\n *\n * Inlined so the landing page works behind a strict CSP and needs no extra\n * HTTP request.\n */\nconst LOGO_SVG =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\" role=\"img\" aria-label=\"ioBroker\">' +\n '<circle cx=\"50\" cy=\"50\" r=\"42\" fill=\"none\" stroke=\"#1F537E\" stroke-width=\"10\"/>' +\n '<rect x=\"44\" y=\"20\" width=\"12\" height=\"60\" rx=\"2\" fill=\"#2B95C6\"/>' +\n '<rect x=\"44\" y=\"26\" width=\"12\" height=\"6\" fill=\"#ffffff\"/>' +\n '</svg>';\n\n/** Supported languages \u2014 matches the 11 io-package.json translations. */\nexport type LandingLanguage = 'en' | 'de' | 'ru' | 'pt' | 'nl' | 'fr' | 'it' | 'es' | 'pl' | 'uk' | 'zh-cn';\n\n/** One translation bundle for the landing page. */\ninterface LandingStrings {\n htmlLang: string;\n pageTitle: string;\n heading: string;\n subhead: string;\n deviceIdLabel: string;\n ipLabel: string;\n setupTitle: string;\n setupIntro: string;\n step1: string;\n step2: string;\n step3: string;\n autoRefresh: string;\n}\n\n/** Translation table \u2014 EN is the fallback for any missing language. */\nconst STRINGS = {\n en: {\n htmlLang: 'en',\n pageTitle: 'Connected \u00B7 ioBroker',\n heading: 'Display connected',\n subhead: 'This display is linked to ioBroker. Choose a redirect URL to finish setup.',\n deviceIdLabel: 'Device ID',\n ipLabel: 'IP address',\n setupTitle: 'Finish setup',\n setupIntro: 'Set the URL that this display should open on next refresh:',\n step1: 'Open the ioBroker admin and switch to the Objects view.',\n step2: 'Go to this datapoint:',\n step3: 'Enter the URL you want to show here (VIS project, Grafana, dashboard, \u2026).',\n autoRefresh: 'This page refreshes automatically every 15 seconds.',\n },\n de: {\n htmlLang: 'de',\n pageTitle: 'Verbunden \u00B7 ioBroker',\n heading: 'Display verbunden',\n subhead: 'Dieses Display ist mit ioBroker verbunden. W\u00E4hle noch eine Weiterleitungs-URL aus.',\n deviceIdLabel: 'Ger\u00E4te-ID',\n ipLabel: 'IP-Adresse',\n setupTitle: 'Einrichtung abschlie\u00DFen',\n setupIntro: 'Lege fest, welche URL das Display beim n\u00E4chsten Refresh \u00F6ffnen soll:',\n step1: '\u00D6ffne im ioBroker-Admin die Ansicht \u201EObjekte\".',\n step2: 'Navigiere zu diesem Datenpunkt:',\n step3: 'Trage hier die gew\u00FCnschte URL ein (VIS-Projekt, Grafana, Dashboard, \u2026).',\n autoRefresh: 'Diese Seite aktualisiert sich automatisch alle 15 Sekunden.',\n },\n ru: {\n htmlLang: 'ru',\n pageTitle: '\u041F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043E \u00B7 ioBroker',\n heading: '\u0414\u0438\u0441\u043F\u043B\u0435\u0439 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0451\u043D',\n subhead: '\u042D\u0442\u043E\u0442 \u0434\u0438\u0441\u043F\u043B\u0435\u0439 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0451\u043D \u043A ioBroker. \u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 URL \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043D\u0430\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F.',\n deviceIdLabel: 'ID \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u0430',\n ipLabel: 'IP-\u0430\u0434\u0440\u0435\u0441',\n setupTitle: '\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u0435 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438',\n setupIntro: '\u0423\u043A\u0430\u0436\u0438\u0442\u0435 URL, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0434\u0438\u0441\u043F\u043B\u0435\u0439 \u043E\u0442\u043A\u0440\u043E\u0435\u0442 \u043F\u0440\u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0438:',\n step1: '\u041E\u0442\u043A\u0440\u043E\u0439\u0442\u0435 \u0430\u0434\u043C\u0438\u043D\u043A\u0443 ioBroker \u0438 \u043F\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043B \u00AB\u041E\u0431\u044A\u0435\u043A\u0442\u044B\u00BB.',\n step2: '\u041F\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043A \u044D\u0442\u043E\u043C\u0443 \u0434\u0430\u0442\u0430\u043F\u0443\u043D\u043A\u0442\u0443:',\n step3: '\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u0443\u0436\u043D\u044B\u0439 URL (\u043F\u0440\u043E\u0435\u043A\u0442 VIS, Grafana, \u0434\u0430\u0448\u0431\u043E\u0440\u0434 \u0438 \u0442. \u0434.).',\n autoRefresh: '\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u043A\u0430\u0436\u0434\u044B\u0435 15 \u0441\u0435\u043A\u0443\u043D\u0434.',\n },\n pt: {\n htmlLang: 'pt',\n pageTitle: 'Conectado \u00B7 ioBroker',\n heading: 'Display conectado',\n subhead: 'Este display est\u00E1 conectado ao ioBroker. Escolha um URL de redirecionamento.',\n deviceIdLabel: 'ID do dispositivo',\n ipLabel: 'Endere\u00E7o IP',\n setupTitle: 'Concluir configura\u00E7\u00E3o',\n setupIntro: 'Defina o URL que este display deve abrir na pr\u00F3xima atualiza\u00E7\u00E3o:',\n step1: 'Abra o admin do ioBroker e mude para a vis\u00E3o de Objetos.',\n step2: 'Navegue at\u00E9 este datapoint:',\n step3: 'Insira o URL desejado (projeto VIS, Grafana, dashboard, \u2026).',\n autoRefresh: 'Esta p\u00E1gina atualiza automaticamente a cada 15 segundos.',\n },\n nl: {\n htmlLang: 'nl',\n pageTitle: 'Verbonden \u00B7 ioBroker',\n heading: 'Display verbonden',\n subhead: 'Dit display is met ioBroker verbonden. Kies een redirect-URL om de setup af te ronden.',\n deviceIdLabel: 'Apparaat-ID',\n ipLabel: 'IP-adres',\n setupTitle: 'Setup afronden',\n setupIntro: 'Stel de URL in die dit display bij de volgende refresh moet openen:',\n step1: 'Open de ioBroker-admin en ga naar de Objects-weergave.',\n step2: 'Navigeer naar dit datapoint:',\n step3: 'Voer hier de gewenste URL in (VIS-project, Grafana, dashboard, \u2026).',\n autoRefresh: 'Deze pagina vernieuwt zich automatisch elke 15 seconden.',\n },\n fr: {\n htmlLang: 'fr',\n pageTitle: 'Connect\u00E9 \u00B7 ioBroker',\n heading: '\u00C9cran connect\u00E9',\n subhead: \"Cet \u00E9cran est reli\u00E9 \u00E0 ioBroker. Choisissez l'URL de redirection pour terminer la configuration.\",\n deviceIdLabel: \"Identifiant de l'appareil\",\n ipLabel: 'Adresse IP',\n setupTitle: 'Finaliser la configuration',\n setupIntro: \"Indiquez l'URL que cet \u00E9cran doit ouvrir \u00E0 la prochaine actualisation :\",\n step1: \"Ouvrez l'admin ioBroker et passez \u00E0 la vue Objets.\",\n step2: 'Allez sur ce datapoint :',\n step3: \"Saisissez ici l'URL souhait\u00E9e (projet VIS, Grafana, tableau de bord, \u2026).\",\n autoRefresh: 'Cette page se rafra\u00EEchit automatiquement toutes les 15 secondes.',\n },\n it: {\n htmlLang: 'it',\n pageTitle: 'Connesso \u00B7 ioBroker',\n heading: 'Display connesso',\n subhead:\n 'Questo display \u00E8 collegato a ioBroker. Scegli un URL di reindirizzamento per completare la configurazione.',\n deviceIdLabel: 'ID dispositivo',\n ipLabel: 'Indirizzo IP',\n setupTitle: 'Completa la configurazione',\n setupIntro: \"Imposta l'URL che il display deve aprire al prossimo aggiornamento:\",\n step1: \"Apri l'admin di ioBroker e passa alla vista Oggetti.\",\n step2: 'Vai a questo datapoint:',\n step3: \"Inserisci qui l'URL desiderato (progetto VIS, Grafana, dashboard, \u2026).\",\n autoRefresh: 'Questa pagina si aggiorna automaticamente ogni 15 secondi.',\n },\n es: {\n htmlLang: 'es',\n pageTitle: 'Conectado \u00B7 ioBroker',\n heading: 'Pantalla conectada',\n subhead:\n 'Esta pantalla est\u00E1 vinculada a ioBroker. Elige una URL de redirecci\u00F3n para terminar la configuraci\u00F3n.',\n deviceIdLabel: 'ID del dispositivo',\n ipLabel: 'Direcci\u00F3n IP',\n setupTitle: 'Completar configuraci\u00F3n',\n setupIntro: 'Indica la URL que esta pantalla abrir\u00E1 en la pr\u00F3xima actualizaci\u00F3n:',\n step1: 'Abre el admin de ioBroker y cambia a la vista Objetos.',\n step2: 'Navega hasta este datapoint:',\n step3: 'Introduce aqu\u00ED la URL deseada (proyecto VIS, Grafana, panel, \u2026).',\n autoRefresh: 'Esta p\u00E1gina se actualiza autom\u00E1ticamente cada 15 segundos.',\n },\n pl: {\n htmlLang: 'pl',\n pageTitle: 'Po\u0142\u0105czono \u00B7 ioBroker',\n heading: 'Wy\u015Bwietlacz po\u0142\u0105czony',\n subhead: 'Ten wy\u015Bwietlacz jest po\u0142\u0105czony z ioBrokerem. Wybierz adres URL przekierowania.',\n deviceIdLabel: 'ID urz\u0105dzenia',\n ipLabel: 'Adres IP',\n setupTitle: 'Zako\u0144cz konfiguracj\u0119',\n setupIntro: 'Ustaw URL, kt\u00F3ry ma otwiera\u0107 ten wy\u015Bwietlacz przy nast\u0119pnym od\u015Bwie\u017Ceniu:',\n step1: 'Otw\u00F3rz panel ioBroker i przejd\u017A do widoku Obiekt\u00F3w.',\n step2: 'Przejd\u017A do tego datapointu:',\n step3: 'Wpisz tutaj \u017C\u0105dany URL (projekt VIS, Grafana, dashboard, \u2026).',\n autoRefresh: 'Ta strona od\u015Bwie\u017Ca si\u0119 automatycznie co 15 sekund.',\n },\n uk: {\n htmlLang: 'uk',\n pageTitle: \"\u0417'\u0454\u0434\u043D\u0430\u043D\u043E \u00B7 ioBroker\",\n heading: \"\u0414\u0438\u0441\u043F\u043B\u0435\u0439 \u043F\u0456\u0434'\u0454\u0434\u043D\u0430\u043D\u043E\",\n subhead: \"\u0426\u0435\u0439 \u0434\u0438\u0441\u043F\u043B\u0435\u0439 \u0437'\u0454\u0434\u043D\u0430\u043D\u043E \u0437 ioBroker. \u041E\u0431\u0435\u0440\u0456\u0442\u044C URL \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043D\u0430\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044F.\",\n deviceIdLabel: 'ID \u043F\u0440\u0438\u0441\u0442\u0440\u043E\u044E',\n ipLabel: 'IP-\u0430\u0434\u0440\u0435\u0441\u0430',\n setupTitle: '\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0438 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F',\n setupIntro: '\u0412\u043A\u0430\u0436\u0456\u0442\u044C URL, \u044F\u043A\u0438\u0439 \u0434\u0438\u0441\u043F\u043B\u0435\u0439 \u0432\u0456\u0434\u043A\u0440\u0438\u0454 \u043F\u0440\u0438 \u043D\u0430\u0441\u0442\u0443\u043F\u043D\u043E\u043C\u0443 \u043E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u0456:',\n step1: \"\u0412\u0456\u0434\u043A\u0440\u0438\u0439\u0442\u0435 \u0430\u0434\u043C\u0456\u043D ioBroker \u0456 \u043F\u0435\u0440\u0435\u0439\u0434\u0456\u0442\u044C \u0434\u043E \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\u0443 \u00AB\u041E\u0431'\u0454\u043A\u0442\u0438\u00BB.\",\n step2: '\u041F\u0435\u0440\u0435\u0439\u0434\u0456\u0442\u044C \u0434\u043E \u0446\u044C\u043E\u0433\u043E \u0434\u0430\u0442\u0430\u043F\u043E\u0456\u043D\u0442\u0430:',\n step3: '\u0412\u0432\u0435\u0434\u0456\u0442\u044C \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u0438\u0439 URL (\u043F\u0440\u043E\u0454\u043A\u0442 VIS, Grafana, \u0434\u0430\u0448\u0431\u043E\u0440\u0434, \u2026).',\n autoRefresh: '\u0426\u044F \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0430 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E \u043E\u043D\u043E\u0432\u043B\u044E\u0454\u0442\u044C\u0441\u044F \u043A\u043E\u0436\u043D\u0456 15 \u0441\u0435\u043A\u0443\u043D\u0434.',\n },\n 'zh-cn': {\n htmlLang: 'zh-CN',\n pageTitle: '\u5DF2\u8FDE\u63A5 \u00B7 ioBroker',\n heading: '\u663E\u793A\u5668\u5DF2\u8FDE\u63A5',\n subhead: '\u6B64\u663E\u793A\u5668\u5DF2\u8FDE\u63A5\u5230 ioBroker\u3002\u8BF7\u9009\u62E9\u8DF3\u8F6C URL \u4EE5\u5B8C\u6210\u8BBE\u7F6E\u3002',\n deviceIdLabel: '\u8BBE\u5907 ID',\n ipLabel: 'IP \u5730\u5740',\n setupTitle: '\u5B8C\u6210\u8BBE\u7F6E',\n setupIntro: '\u8BBE\u7F6E\u6B64\u663E\u793A\u5668\u4E0B\u6B21\u5237\u65B0\u65F6\u8981\u6253\u5F00\u7684 URL\uFF1A',\n step1: '\u6253\u5F00 ioBroker \u7BA1\u7406\u754C\u9762\u5E76\u5207\u6362\u5230\u300C\u5BF9\u8C61\u300D\u89C6\u56FE\u3002',\n step2: '\u5BFC\u822A\u5230\u6B64\u6570\u636E\u70B9\uFF1A',\n step3: '\u5728\u6B64\u5904\u8F93\u5165\u6240\u9700\u7684 URL\uFF08VIS \u9879\u76EE\u3001Grafana\u3001\u4EEA\u8868\u677F\u7B49\uFF09\u3002',\n autoRefresh: '\u6B64\u9875\u9762\u6BCF 15 \u79D2\u81EA\u52A8\u5237\u65B0\u4E00\u6B21\u3002',\n },\n} as const satisfies Record<LandingLanguage, LandingStrings>;\n\n/**\n * Render the landing page.\n *\n * @param clientId Short client id of this display.\n * @param namespace Adapter namespace (e.g. `hassemu.0`).\n * @param language Desired UI language, resolved from `system.config.language`.\n * @param ip Optional remote IP of the display, shown next to the ID.\n */\nexport function renderLandingPage(\n clientId: string,\n namespace: string,\n language: string = 'en',\n ip: string | null = null,\n): string {\n const s = STRINGS[language as LandingLanguage] ?? STRINGS.en;\n const id = escapeHtml(clientId);\n const ns = escapeHtml(namespace);\n const datapoint = `${ns}.clients.${id}.mode`;\n // v1.16.0 (E3): Loopback-IPs nicht anzeigen \u2014 der End-User sieht sonst\n // \u201Elocalhost\" / \u201E127.0.0.1\" / \u201E::1\" als sein Display-IP, was bei Proxy-\n // Setups verwirrt (Display sitzt am Reverse-Proxy, nicht am Adapter).\n // Ohne IP-Zeile f\u00E4llt die Tabellen-Zeile einfach weg, alles andere bleibt.\n const trimmedIp = ip?.trim() ?? '';\n const isLoopback =\n trimmedIp === '' ||\n trimmedIp === '127.0.0.1' ||\n trimmedIp === '::1' ||\n trimmedIp === '0.0.0.0' ||\n trimmedIp.startsWith('127.');\n const ipLine = isLoopback\n ? ''\n : `<tr><th scope=\"row\">${escapeHtml(s.ipLabel)}</th><td>${escapeHtml(trimmedIp)}</td></tr>`;\n\n return `<!DOCTYPE html>\n<html lang=\"${escapeHtml(s.htmlLang)}\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<meta http-equiv=\"refresh\" content=\"15\">\n<title>${escapeHtml(s.pageTitle)}</title>\n<style>\n:root {\n --bg: #f5f7fa;\n --card-bg: #ffffff;\n --text: #1f2933;\n --muted: #52606d;\n --ok-bg: #16a34a;\n --ok-bg-soft: #dcfce7;\n --ok-text: #14532d;\n --accent: #0369a1;\n --border: #e4e7eb;\n --code-bg: #eef2f7;\n --shadow: 0 4px 18px rgba(15, 23, 42, 0.08);\n}\n@media (prefers-color-scheme: dark) {\n :root {\n --bg: #0f172a;\n --card-bg: #1e293b;\n --text: #f1f5f9;\n --muted: #94a3b8;\n --ok-bg-soft: #052e16;\n --ok-text: #bbf7d0;\n --accent: #38bdf8;\n --border: #334155;\n --code-bg: #0f172a;\n --shadow: 0 4px 18px rgba(0, 0, 0, 0.35);\n }\n}\n* { box-sizing: border-box; }\nhtml, body { height: 100%; }\nbody {\n margin: 0;\n background: var(--bg);\n color: var(--text);\n font: 16px/1.5 system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n}\nmain {\n width: 100%;\n max-width: 44rem;\n background: var(--card-bg);\n border-radius: 12px;\n box-shadow: var(--shadow);\n overflow: hidden;\n}\n.banner {\n background: var(--ok-bg);\n color: #ffffff;\n padding: 1.4rem 1.8rem;\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n.banner .logo {\n width: 3.2rem;\n height: 3.2rem;\n flex-shrink: 0;\n background: #ffffff;\n border-radius: 50%;\n padding: 0.25rem;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n.banner .logo svg { display: block; width: 100%; height: 100%; }\n.banner .check {\n width: 1.8rem;\n height: 1.8rem;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.22);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n font-size: 1.1rem;\n line-height: 1;\n font-weight: 700;\n}\n.banner h1 {\n margin: 0;\n font-size: 1.4rem;\n font-weight: 600;\n letter-spacing: 0.01em;\n}\n.banner p {\n margin: 0.15rem 0 0;\n font-size: 0.95rem;\n opacity: 0.95;\n}\n.content {\n padding: 1.6rem 1.8rem 1.3rem;\n}\n.info {\n margin: 0 0 1.4rem;\n width: 100%;\n border-collapse: collapse;\n font-size: 0.95rem;\n}\n.info th, .info td {\n padding: 0.55rem 0.7rem;\n text-align: left;\n border-bottom: 1px solid var(--border);\n}\n.info th {\n font-weight: 500;\n color: var(--muted);\n white-space: nowrap;\n width: 9rem;\n}\n.info tr:last-child th, .info tr:last-child td {\n border-bottom: none;\n}\n.info code {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n background: var(--code-bg);\n padding: 0.15rem 0.45rem;\n border-radius: 4px;\n font-size: 0.9em;\n}\n.setup h2 {\n margin: 0 0 0.6rem;\n font-size: 1.05rem;\n font-weight: 600;\n color: var(--accent);\n}\n.setup > p {\n margin: 0 0 0.9rem;\n color: var(--muted);\n}\n.steps {\n margin: 0;\n padding-left: 1.4rem;\n color: var(--text);\n}\n.steps li {\n margin: 0.5rem 0;\n}\n.steps code {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n background: var(--code-bg);\n padding: 0.15rem 0.45rem;\n border-radius: 4px;\n font-size: 0.88em;\n word-break: break-all;\n}\nfooter {\n padding: 0.9rem 1.8rem;\n border-top: 1px solid var(--border);\n font-size: 0.8rem;\n color: var(--muted);\n text-align: center;\n}\nfooter .brand {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n margin-left: 0.6rem;\n color: var(--accent);\n font-weight: 500;\n}\nfooter .brand svg { width: 0.95rem; height: 0.95rem; display: block; }\n@media (max-width: 30rem) {\n body { padding: 0; }\n main { border-radius: 0; box-shadow: none; height: 100%; }\n .banner { padding: 1.1rem 1.2rem; }\n .banner h1 { font-size: 1.2rem; }\n .content { padding: 1.2rem 1.2rem 1rem; }\n .info th { width: auto; }\n footer { padding: 0.9rem 1.2rem; }\n}\n</style>\n</head>\n<body>\n<main>\n <div class=\"banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"logo\" aria-hidden=\"true\">${LOGO_SVG}</div>\n <div class=\"check\" aria-hidden=\"true\">\u2713</div>\n <div>\n <h1>${escapeHtml(s.heading)}</h1>\n <p>${escapeHtml(s.subhead)}</p>\n </div>\n </div>\n <div class=\"content\">\n <table class=\"info\">\n <tbody>\n <tr>\n <th scope=\"row\">${escapeHtml(s.deviceIdLabel)}</th>\n <td><code>${id}</code></td>\n </tr>\n ${ipLine}\n </tbody>\n </table>\n <section class=\"setup\">\n <h2>${escapeHtml(s.setupTitle)}</h2>\n <p>${escapeHtml(s.setupIntro)}</p>\n <ol class=\"steps\">\n <li>${escapeHtml(s.step1)}</li>\n <li>${escapeHtml(s.step2)} <code>${escapeHtml(datapoint)}</code></li>\n <li>${escapeHtml(s.step3)}</li>\n </ol>\n </section>\n </div>\n <footer>\n ${escapeHtml(s.autoRefresh)}\n <span class=\"brand\" aria-hidden=\"true\">${LOGO_SVG} ioBroker</span>\n </footer>\n</main>\n<script>\n(function(){\n // Same connection-status signal as renderRedirectWrapper \u2014 the HA Companion\n // App on Shelly Wall Display FW 2.6.0+ shows \"Verbindung zu Home Assistant\n // nicht m\u00F6glich\" after 10 s if it doesn't see this message. The popup is\n // unrelated to whether a URL is configured, so the landing page must signal\n // \"connected\" too. Source: home-assistant/android FrontendMessageHandler.kt +\n // FrontendJsBridge.kt + frontend/src/external_app/external_messaging.ts.\n function notifyConnected(){\n try {\n var v1Payload = JSON.stringify({id:1,type:\"connection-status\",payload:{event:\"connected\"}});\n if (window.externalApp && typeof window.externalApp.externalBus === \"function\") {\n window.externalApp.externalBus(v1Payload);\n return;\n }\n if (window.externalAppV2 && typeof window.externalAppV2.postMessage === \"function\") {\n window.externalAppV2.postMessage(JSON.stringify({\n type:\"externalBus\",\n payload:{id:1,type:\"connection-status\",payload:{event:\"connected\"}}\n }));\n }\n } catch (e) { /* silent \u2014 bridge not present, regular browser */ }\n }\n notifyConnected();\n setTimeout(notifyConnected, 500);\n setTimeout(notifyConnected, 2000);\n})();\n</script>\n</body>\n</html>`;\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/[<>&\"']/g, c => {\n switch (c) {\n case '<':\n return '&lt;';\n case '>':\n return '&gt;';\n case '&':\n return '&amp;';\n case '\"':\n return '&quot;';\n default:\n return '&#39;';\n }\n });\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "hassemu",
4
- "version": "1.29.2",
4
+ "version": "1.29.3",
5
5
  "news": {
6
+ "1.29.3": {
7
+ "en": "The connection-error popup on Shelly Wall Display 2.6.0+ also stays away when the landing page is shown. Plus the landing page now uses the real ioBroker brand mark.",
8
+ "de": "Das Verbindungsfehler-Popup auf Shelly Wall Display 2.6.0+ bleibt jetzt auch weg wenn die Landing-Page angezeigt wird. Außerdem trägt die Landing-Page nun das echte ioBroker-Markenzeichen.",
9
+ "ru": "Попап ошибки подключения на Shelly Wall Display 2.6.0+ теперь не появляется и когда показывается стартовая страница. На стартовой странице — настоящий логотип ioBroker.",
10
+ "pt": "O popup de erro de ligação no Shelly Wall Display 2.6.0+ deixa de aparecer também na landing page. Além disso, a landing page mostra agora a marca real do ioBroker.",
11
+ "nl": "De verbindings-foutpopup op Shelly Wall Display 2.6.0+ blijft nu ook weg wanneer de landingspagina wordt getoond. Daarnaast staat het echte ioBroker-merkteken op de landingspagina.",
12
+ "fr": "La popup d'erreur de connexion sur Shelly Wall Display 2.6.0+ ne s'affiche plus non plus lorsque la page d'accueil est visible. La page d'accueil porte désormais la marque officielle ioBroker.",
13
+ "it": "Il popup di errore di connessione su Shelly Wall Display 2.6.0+ non compare più anche quando viene mostrata la landing page. La landing page ora ha il marchio originale ioBroker.",
14
+ "es": "El popup de error de conexión en Shelly Wall Display 2.6.0+ ya no aparece tampoco cuando se muestra la página de inicio. La página de inicio ahora usa la marca oficial de ioBroker.",
15
+ "pl": "Popup błędu połączenia na Shelly Wall Display 2.6.0+ nie pojawia się także gdy wyświetlana jest strona startowa. Strona startowa pokazuje teraz prawdziwe logo ioBroker.",
16
+ "uk": "Попап помилки з'єднання на Shelly Wall Display 2.6.0+ більше не з'являється і коли показується стартова сторінка. На стартовій сторінці справжній логотип ioBroker.",
17
+ "zh-cn": "Shelly Wall Display 2.6.0+ 上的连接错误弹窗在显示落地页时也不再出现。落地页现在使用真正的 ioBroker 品牌标志。"
18
+ },
6
19
  "1.29.2": {
7
20
  "en": "Shelly Wall Display 2.6.0+ no longer shows the connection-error popup after the page loaded. Aura is now auto-detected in the mode dropdown. Landing page carries the ioBroker logo.",
8
21
  "de": "Shelly Wall Display unter Firmware 2.6.0+ zeigt nach geladenem Display kein Verbindungs-Fehler-Popup mehr. Aura wird jetzt automatisch im Mode-Dropdown erkannt. Landing-Page trägt das ioBroker-Logo.",
@@ -80,19 +93,6 @@
80
93
  "pl": "Komunikaty dziennika adaptera są teraz wyłącznie po angielsku, zgodnie ze standardem społeczności ioBroker. Zlokalizowane nazwy stanów, opisy i etykiety (11 języków) oraz strona docelowa pozostają bez zmian.",
81
94
  "uk": "Повідомлення журналу адаптера тепер лише англійською, відповідно до стандарту спільноти ioBroker. Локалізовані назви станів, описи та мітки (11 мов) і цільова сторінка для користувача залишаються без змін.",
82
95
  "zh-cn": "适配器日志消息现在仅为英文,符合 ioBroker 社区标准。本地化的数据点名称、描述和下拉标签(11 种语言)以及用户登录页面保持不变。"
83
- },
84
- "1.28.1": {
85
- "en": "Documentation: changelog entries (v1.27.x–v1.28.0) restored to English — a few bullets had been left in German. No code changes.",
86
- "de": "Dokumentation: Changelog-Einträge (v1.27.x–v1.28.0) auf Englisch korrigiert — einige Bullets waren auf Deutsch geblieben. Keine Code-Änderungen.",
87
- "ru": "Документация: записи журнала изменений (v1.27.x–v1.28.0) восстановлены на английском — несколько пунктов оставались на немецком. Изменений в коде нет.",
88
- "pt": "Documentação: entradas do changelog (v1.27.x–v1.28.0) restauradas para inglês — alguns itens haviam ficado em alemão. Sem alterações no código.",
89
- "nl": "Documentatie: changelog-vermeldingen (v1.27.x–v1.28.0) hersteld naar Engels — enkele punten waren in het Duits gebleven. Geen codewijzigingen.",
90
- "fr": "Documentation : entrées du changelog (v1.27.x–v1.28.0) remises en anglais — quelques points étaient restés en allemand. Aucune modification de code.",
91
- "it": "Documentazione: voci del changelog (v1.27.x–v1.28.0) ripristinate in inglese — alcuni punti erano rimasti in tedesco. Nessuna modifica al codice.",
92
- "es": "Documentación: entradas del changelog (v1.27.x–v1.28.0) restauradas al inglés — algunos puntos quedaron en alemán. Sin cambios en el código.",
93
- "pl": "Dokumentacja: wpisy changelog (v1.27.x–v1.28.0) przywrócone na angielski — kilka punktów pozostało po niemiecku. Bez zmian w kodzie.",
94
- "uk": "Документація: записи changelog (v1.27.x–v1.28.0) відновлено англійською — деякі пункти лишалися німецькою. Без змін у коді.",
95
- "zh-cn": "文档:将 v1.27.x–v1.28.0 的 changelog 条目恢复为英文 — 之前部分条目残留为德文。无代码更改。"
96
96
  }
97
97
  },
98
98
  "titleLang": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.hassemu",
3
- "version": "1.29.2",
3
+ "version": "1.29.3",
4
4
  "description": "Emulates a minimal Home Assistant server so devices expecting a Home Assistant dashboard can display any custom web URL.",
5
5
  "author": {
6
6
  "name": "krobi",