iobroker.alias-workbench 0.9.7 → 0.9.9

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.
@@ -0,0 +1,14 @@
1
+ {
2
+ "Add missing icons to functions": "Compléter les icônes manquantes des fonctions",
3
+ "Add missing icons to rooms": "Compléter les icônes manquantes des pièces",
4
+ "Admin ships 62 function and 58 room templates, each with an icon. When the workbench creates an enumeration, it takes the icon from there. Existing enumerations keep whatever they have — unless you allow it to fill in what is missing. Nothing is ever written without the dry run showing it first.": "L'Admin fournit 62 modèles de fonction et 58 modèles de pièce, chacun avec une icône. Lorsque l'établi crée une énumération, il y prend l'icône. Les énumérations existantes conservent ce qu'elles ont — sauf si vous autorisez le complément de ce qui manque. Rien n'est jamais écrit sans que la simulation ne l'ait montré au préalable.",
5
+ "Also replace unusable icon entries": "Remplacer aussi les entrées d'icône inutilisables",
6
+ "Applies when a room has no icon at all and a template of the same name or ID exists.": "S'applique lorsqu'une pièce n'a aucune icône et qu'un modèle du même nom ou du même ID existe.",
7
+ "Icons for rooms and functions": "Icônes pour les pièces et les fonctions",
8
+ "Offer the Admin's room and function templates": "Proposer les modèles de pièce et de fonction de l'Admin",
9
+ "Same for functions. Enumerations mirrored from a HomeMatic CCU never carry an icon.": "Idem pour les fonctions. Les énumérations reprises d'une centrale HomeMatic ne portent jamais d'icône.",
10
+ "The Admin setup wizard leaves a bare name such as \"Playroom\" in the icon field, which no longer resolves to a picture and shows as a broken box. With this on, the workbench replaces it. It overwrites a field that is not empty — the dry run names it explicitly.": "L'assistant de configuration de l'Admin laisse dans le champ d'icône un simple nom tel que « Playroom », qui ne renvoie plus à aucune image et s'affiche comme un cadre cassé. Si cette option est activée, l'établi le remplace. Un champ non vide est alors écrasé — la simulation le signale explicitement.",
11
+ "The Alias Workbench has no running process — everything happens in the Admin tab. These settings control how it writes.": "L'Établi d'alias n'a aucun processus en cours — tout se passe dans l'onglet Admin. Ces réglages déterminent la manière dont il écrit.",
12
+ "The workbench reads them at runtime from the Admin's own bundle instead of keeping a copy that would age with every update. If that fails, the selection lists simply show what already exists — no error, just fewer entries.": "L'établi les lit à l'exécution depuis le bundle de l'Admin plutôt que de conserver une copie qui vieillirait à chaque mise à jour. En cas d'échec, les listes de sélection n'affichent que l'existant — pas d'erreur, simplement moins d'entrées.",
13
+ "Where the templates come from": "D'où viennent les modèles"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "Add missing icons to functions": "Aggiungere le icone mancanti alle funzioni",
3
+ "Add missing icons to rooms": "Aggiungere le icone mancanti alle stanze",
4
+ "Admin ships 62 function and 58 room templates, each with an icon. When the workbench creates an enumeration, it takes the icon from there. Existing enumerations keep whatever they have — unless you allow it to fill in what is missing. Nothing is ever written without the dry run showing it first.": "L'Admin include 62 modelli di funzione e 58 di stanza, ciascuno con un’icona. Quando il banco di lavoro crea un’enumerazione, prende l’icona da lì. Le enumerazioni esistenti mantengono ciò che hanno, a meno che non si consenta di integrare ciò che manca. Nulla viene mai scritto senza che la simulazione lo mostri prima.",
5
+ "Also replace unusable icon entries": "Sostituire anche le voci di icona inutilizzabili",
6
+ "Applies when a room has no icon at all and a template of the same name or ID exists.": "Si applica quando una stanza non ha alcuna icona ed esiste un modello con lo stesso nome o ID.",
7
+ "Icons for rooms and functions": "Icone per stanze e funzioni",
8
+ "Offer the Admin's room and function templates": "Proporre i modelli di stanza e funzione dell’Admin",
9
+ "Same for functions. Enumerations mirrored from a HomeMatic CCU never carry an icon.": "Lo stesso vale per le funzioni. Le enumerazioni rispecchiate da una CCU HomeMatic non hanno mai un’icona.",
10
+ "The Admin setup wizard leaves a bare name such as \"Playroom\" in the icon field, which no longer resolves to a picture and shows as a broken box. With this on, the workbench replaces it. It overwrites a field that is not empty — the dry run names it explicitly.": "La procedura guidata di configurazione dell’Admin lascia nel campo icona un semplice nome come «Playroom», che non rimanda più ad alcuna immagine e appare come un riquadro rotto. Con questa opzione attiva, il banco di lavoro lo sostituisce. Viene così sovrascritto un campo non vuoto: la simulazione lo indica espressamente.",
11
+ "The Alias Workbench has no running process — everything happens in the Admin tab. These settings control how it writes.": "Il Banco di lavoro alias non ha alcun processo in esecuzione — tutto avviene nella scheda Admin. Queste impostazioni determinano come scrive.",
12
+ "The workbench reads them at runtime from the Admin's own bundle instead of keeping a copy that would age with every update. If that fails, the selection lists simply show what already exists — no error, just fewer entries.": "Il banco di lavoro li legge in fase di esecuzione dal bundle dell’Admin, anziché conservare una copia che invecchierebbe a ogni aggiornamento. Se ciò non riesce, gli elenchi di selezione mostrano solo ciò che esiste già: non è un errore, solo meno voci.",
13
+ "Where the templates come from": "Da dove provengono i modelli"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "Add missing icons to functions": "Ontbrekende pictogrammen bij functies aanvullen",
3
+ "Add missing icons to rooms": "Ontbrekende pictogrammen bij ruimtes aanvullen",
4
+ "Admin ships 62 function and 58 room templates, each with an icon. When the workbench creates an enumeration, it takes the icon from there. Existing enumerations keep whatever they have — unless you allow it to fill in what is missing. Nothing is ever written without the dry run showing it first.": "Admin levert 62 functie- en 58 ruimtesjablonen, elk met een pictogram. Wanneer de werkbank een opsomming aanmaakt, neemt zij het pictogram daarvandaan. Bestaande opsommingen behouden wat ze hebben — tenzij u toestaat dat ontbrekende worden aangevuld. Er wordt nooit iets geschreven zonder dat de proefrun het eerst toont.",
5
+ "Also replace unusable icon entries": "Ook onbruikbare pictogramvermeldingen vervangen",
6
+ "Applies when a room has no icon at all and a template of the same name or ID exists.": "Geldt wanneer een ruimte helemaal geen pictogram heeft en er een sjabloon met dezelfde naam of ID bestaat.",
7
+ "Icons for rooms and functions": "Pictogrammen voor ruimtes en functies",
8
+ "Offer the Admin's room and function templates": "De ruimte- en functiesjablonen van Admin aanbieden",
9
+ "Same for functions. Enumerations mirrored from a HomeMatic CCU never carry an icon.": "Hetzelfde voor functies. Opsommingen die vanaf een HomeMatic-CCU worden gespiegeld, hebben nooit een pictogram.",
10
+ "The Admin setup wizard leaves a bare name such as \"Playroom\" in the icon field, which no longer resolves to a picture and shows as a broken box. With this on, the workbench replaces it. It overwrites a field that is not empty — the dry run names it explicitly.": "De installatiewizard van Admin laat in het pictogramveld een kale naam als \"Playroom\" achter, die niet langer naar een afbeelding verwijst en als een kapot kadertje verschijnt. Staat dit aan, dan vervangt de werkbank hem. Daarbij wordt een niet-leeg veld overschreven — de proefrun benoemt dat uitdrukkelijk.",
11
+ "The Alias Workbench has no running process — everything happens in the Admin tab. These settings control how it writes.": "De Alias-werkbank heeft geen draaiend proces — alles gebeurt in het Admin-tabblad. Deze instellingen bepalen hoe er geschreven wordt.",
12
+ "The workbench reads them at runtime from the Admin's own bundle instead of keeping a copy that would age with every update. If that fails, the selection lists simply show what already exists — no error, just fewer entries.": "De werkbank leest ze tijdens het uitvoeren uit de bundel van Admin zelf, in plaats van een kopie bij te houden die bij elke update veroudert. Mislukt dat, dan tonen de keuzelijsten alleen wat er al is — geen fout, alleen minder items.",
13
+ "Where the templates come from": "Waar de sjablonen vandaan komen"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "Add missing icons to functions": "Uzupełniać brakujące ikony funkcji",
3
+ "Add missing icons to rooms": "Uzupełniać brakujące ikony pomieszczeń",
4
+ "Admin ships 62 function and 58 room templates, each with an icon. When the workbench creates an enumeration, it takes the icon from there. Existing enumerations keep whatever they have — unless you allow it to fill in what is missing. Nothing is ever written without the dry run showing it first.": "Admin dostarcza 62 szablony funkcji i 58 szablonów pomieszczeń, każdy z ikoną. Gdy warsztat tworzy wyliczenie, pobiera ikonę stamtąd. Istniejące wyliczenia zachowują to, co mają — chyba że pozwolisz uzupełnić braki. Nic nie jest zapisywane bez uprzedniego pokazania przez próbny przebieg.",
5
+ "Also replace unusable icon entries": "Zastępować także nieprzydatne wpisy ikon",
6
+ "Applies when a room has no icon at all and a template of the same name or ID exists.": "Działa, gdy pomieszczenie nie ma żadnej ikony, a istnieje szablon o tej samej nazwie lub ID.",
7
+ "Icons for rooms and functions": "Ikony dla pomieszczeń i funkcji",
8
+ "Offer the Admin's room and function templates": "Oferować szablony pomieszczeń i funkcji z Admina",
9
+ "Same for functions. Enumerations mirrored from a HomeMatic CCU never carry an icon.": "To samo dotyczy funkcji. Wyliczenia odwzorowane z centrali HomeMatic nigdy nie mają ikony.",
10
+ "The Admin setup wizard leaves a bare name such as \"Playroom\" in the icon field, which no longer resolves to a picture and shows as a broken box. With this on, the workbench replaces it. It overwrites a field that is not empty — the dry run names it explicitly.": "Kreator konfiguracji Admina pozostawia w polu ikony samą nazwę, np. „Playroom”, która nie prowadzi już do żadnego obrazka i wyświetla się jako uszkodzona ramka. Przy włączonej opcji warsztat ją zastępuje. Nadpisywane jest wtedy niepuste pole — próbny przebieg wskazuje to osobno.",
11
+ "The Alias Workbench has no running process — everything happens in the Admin tab. These settings control how it writes.": "Warsztat aliasów nie ma działającego procesu — wszystko dzieje się w zakładce Admina. Te ustawienia określają, jak zapisuje.",
12
+ "The workbench reads them at runtime from the Admin's own bundle instead of keeping a copy that would age with every update. If that fails, the selection lists simply show what already exists — no error, just fewer entries.": "Warsztat odczytuje je w czasie działania z własnego pakietu Admina, zamiast utrzymywać kopię, która starzałaby się z każdą aktualizacją. Jeśli się to nie powiedzie, listy wyboru pokazują tylko to, co już istnieje — to nie błąd, po prostu mniej pozycji.",
13
+ "Where the templates come from": "Skąd pochodzą szablony"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "Add missing icons to functions": "Adicionar ícones em falta às funções",
3
+ "Add missing icons to rooms": "Adicionar ícones em falta às divisões",
4
+ "Admin ships 62 function and 58 room templates, each with an icon. When the workbench creates an enumeration, it takes the icon from there. Existing enumerations keep whatever they have — unless you allow it to fill in what is missing. Nothing is ever written without the dry run showing it first.": "O Admin inclui 62 modelos de função e 58 modelos de divisão, cada um com um ícone. Quando a bancada cria uma enumeração, retira o ícone daí. As enumerações existentes mantêm o que têm — a menos que permita preencher o que falta. Nada é escrito sem que a simulação o mostre primeiro.",
5
+ "Also replace unusable icon entries": "Substituir também entradas de ícone inutilizáveis",
6
+ "Applies when a room has no icon at all and a template of the same name or ID exists.": "Aplica-se quando uma divisão não tem qualquer ícone e existe um modelo com o mesmo nome ou ID.",
7
+ "Icons for rooms and functions": "Ícones para divisões e funções",
8
+ "Offer the Admin's room and function templates": "Oferecer os modelos de divisão e função do Admin",
9
+ "Same for functions. Enumerations mirrored from a HomeMatic CCU never carry an icon.": "O mesmo para as funções. As enumerações espelhadas de uma CCU HomeMatic nunca têm ícone.",
10
+ "The Admin setup wizard leaves a bare name such as \"Playroom\" in the icon field, which no longer resolves to a picture and shows as a broken box. With this on, the workbench replaces it. It overwrites a field that is not empty — the dry run names it explicitly.": "O assistente de configuração do Admin deixa no campo do ícone um nome simples como «Playroom», que já não corresponde a nenhuma imagem e aparece como uma caixa partida. Com esta opção ligada, a bancada substitui-o. Isso sobrescreve um campo que não está vazio — a simulação indica-o explicitamente.",
11
+ "The Alias Workbench has no running process — everything happens in the Admin tab. These settings control how it writes.": "A Bancada de Alias não tem processo em execução — tudo acontece no separador do Admin. Estas definições determinam como escreve.",
12
+ "The workbench reads them at runtime from the Admin's own bundle instead of keeping a copy that would age with every update. If that fails, the selection lists simply show what already exists — no error, just fewer entries.": "A bancada lê-os em tempo de execução a partir do próprio pacote do Admin, em vez de manter uma cópia que envelheceria a cada atualização. Se isso falhar, as listas de seleção mostram apenas o que já existe — não é um erro, apenas menos entradas.",
13
+ "Where the templates come from": "De onde vêm os modelos"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "Add missing icons to functions": "Дополнять отсутствующие значки у функций",
3
+ "Add missing icons to rooms": "Дополнять отсутствующие значки у комнат",
4
+ "Admin ships 62 function and 58 room templates, each with an icon. When the workbench creates an enumeration, it takes the icon from there. Existing enumerations keep whatever they have — unless you allow it to fill in what is missing. Nothing is ever written without the dry run showing it first.": "Admin поставляется с 62 шаблонами функций и 58 шаблонами комнат, у каждого есть значок. Когда верстак создаёт перечисление, он берёт значок оттуда. Существующие перечисления сохраняют то, что у них есть, — если только вы не разрешите дополнить недостающее. Ничего не записывается без того, чтобы пробный прогон сначала это показал.",
5
+ "Also replace unusable icon entries": "Также заменять непригодные записи значков",
6
+ "Applies when a room has no icon at all and a template of the same name or ID exists.": "Действует, когда у комнаты вообще нет значка и существует шаблон с тем же именем или идентификатором.",
7
+ "Icons for rooms and functions": "Значки для комнат и функций",
8
+ "Offer the Admin's room and function templates": "Предлагать шаблоны комнат и функций из Admin",
9
+ "Same for functions. Enumerations mirrored from a HomeMatic CCU never carry an icon.": "То же для функций. Перечисления, зеркалируемые с центрального блока HomeMatic, никогда не содержат значка.",
10
+ "The Admin setup wizard leaves a bare name such as \"Playroom\" in the icon field, which no longer resolves to a picture and shows as a broken box. With this on, the workbench replaces it. It overwrites a field that is not empty — the dry run names it explicitly.": "Мастер настройки Admin оставляет в поле значка голое имя вроде «Playroom», которое больше не ведёт к изображению и отображается как сломанный прямоугольник. Если это включено, верстак заменяет его. При этом перезаписывается непустое поле — пробный прогон называет это отдельно.",
11
+ "The Alias Workbench has no running process — everything happens in the Admin tab. These settings control how it writes.": "У «Верстака алиасов» нет запущенного процесса — всё происходит во вкладке администратора. Эти настройки определяют, как он записывает.",
12
+ "The workbench reads them at runtime from the Admin's own bundle instead of keeping a copy that would age with every update. If that fails, the selection lists simply show what already exists — no error, just fewer entries.": "Верстак читает их во время выполнения из собственного бандла Admin, вместо того чтобы держать копию, устаревающую с каждым обновлением. Если это не удаётся, списки выбора показывают только то, что уже есть, — не ошибка, просто меньше вариантов.",
13
+ "Where the templates come from": "Откуда берутся шаблоны"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "Add missing icons to functions": "Доповнювати відсутні значки функцій",
3
+ "Add missing icons to rooms": "Доповнювати відсутні значки кімнат",
4
+ "Admin ships 62 function and 58 room templates, each with an icon. When the workbench creates an enumeration, it takes the icon from there. Existing enumerations keep whatever they have — unless you allow it to fill in what is missing. Nothing is ever written without the dry run showing it first.": "Admin постачає 62 шаблони функцій і 58 шаблонів кімнат, кожен зі значком. Коли верстак створює перелік, він бере значок звідти. Наявні переліки зберігають те, що мають, — якщо ви не дозволите доповнити відсутнє. Нічого не записується без того, щоб пробний запуск спершу це показав.",
5
+ "Also replace unusable icon entries": "Також замінювати непридатні записи значків",
6
+ "Applies when a room has no icon at all and a template of the same name or ID exists.": "Діє, коли кімната взагалі не має значка й існує шаблон з такою самою назвою або ідентифікатором.",
7
+ "Icons for rooms and functions": "Значки для кімнат і функцій",
8
+ "Offer the Admin's room and function templates": "Пропонувати шаблони кімнат і функцій з Admin",
9
+ "Same for functions. Enumerations mirrored from a HomeMatic CCU never carry an icon.": "Те саме для функцій. Переліки, віддзеркалені з центрального блока HomeMatic, ніколи не містять значка.",
10
+ "The Admin setup wizard leaves a bare name such as \"Playroom\" in the icon field, which no longer resolves to a picture and shows as a broken box. With this on, the workbench replaces it. It overwrites a field that is not empty — the dry run names it explicitly.": "Майстер налаштування Admin залишає в полі значка саму лише назву на кшталт «Playroom», яка більше не веде до зображення й показується як зламаний прямокутник. Якщо цю опцію ввімкнено, верстак її замінює. При цьому перезаписується непорожнє поле — пробний запуск зазначає це окремо.",
11
+ "The Alias Workbench has no running process — everything happens in the Admin tab. These settings control how it writes.": "У «Верстака аліасів» немає запущеного процесу — усе відбувається у вкладці адміністратора. Ці налаштування визначають, як він записує.",
12
+ "The workbench reads them at runtime from the Admin's own bundle instead of keeping a copy that would age with every update. If that fails, the selection lists simply show what already exists — no error, just fewer entries.": "Верстак читає їх під час виконання з власного бандла Admin, замість того щоб тримати копію, яка старіє з кожним оновленням. Якщо це не вдається, списки вибору показують лише наявне — не помилка, просто менше записів.",
13
+ "Where the templates come from": "Звідки беруться шаблони"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "Add missing icons to functions": "为功能补全缺失的图标",
3
+ "Add missing icons to rooms": "为房间补全缺失的图标",
4
+ "Admin ships 62 function and 58 room templates, each with an icon. When the workbench creates an enumeration, it takes the icon from there. Existing enumerations keep whatever they have — unless you allow it to fill in what is missing. Nothing is ever written without the dry run showing it first.": "Admin 自带 62 个功能模板和 58 个房间模板,每个都带有图标。工作台创建枚举时会从那里取用图标。已有的枚举保留原样——除非您允许补全缺失的部分。任何写入都会先由试运行展示。",
5
+ "Also replace unusable icon entries": "同时替换无效的图标条目",
6
+ "Applies when a room has no icon at all and a template of the same name or ID exists.": "仅当房间完全没有图标、且存在同名或同 ID 的模板时生效。",
7
+ "Icons for rooms and functions": "房间和功能的图标",
8
+ "Offer the Admin's room and function templates": "提供 Admin 的房间和功能模板",
9
+ "Same for functions. Enumerations mirrored from a HomeMatic CCU never carry an icon.": "功能同理。从 HomeMatic CCU 镜像而来的枚举从不带图标。",
10
+ "The Admin setup wizard leaves a bare name such as \"Playroom\" in the icon field, which no longer resolves to a picture and shows as a broken box. With this on, the workbench replaces it. It overwrites a field that is not empty — the dry run names it explicitly.": "Admin 的设置向导会在图标字段里留下诸如 \"Playroom\" 这样的裸名称,它已无法解析为图片,显示为一个破损的方框。开启此项后,工作台会将其替换。这会覆盖一个非空字段——试运行会明确指出这一点。",
11
+ "The Alias Workbench has no running process — everything happens in the Admin tab. These settings control how it writes.": "别名工作台没有运行中的进程——一切都在 Admin 选项卡中进行。这些设置决定它如何写入。",
12
+ "The workbench reads them at runtime from the Admin's own bundle instead of keeping a copy that would age with every update. If that fails, the selection lists simply show what already exists — no error, just fewer entries.": "工作台在运行时从 Admin 自身的打包文件中读取,而不是保留一份每次更新都会过时的副本。若读取失败,选择列表只显示已有内容——这不是错误,只是选项更少。",
13
+ "Where the templates come from": "模板来自何处"
14
+ }
@@ -5,7 +5,7 @@ import { socket } from './verbindung.js';
5
5
  import { el } from './basis.js';
6
6
  import { tr } from './sprache.js';
7
7
  import { wertVon, jsonFelder, feldAusFormel, feldFormel, feldWert, jsonVon } from './werte.js';
8
- import { musterVon, erkenneEntwurf, rolleTrifft } from './erkennung.js';
8
+ import { musterVon, erkenneEntwurf, platzFuerRolle, typenFuerRolle } from './erkennung.js';
9
9
  import { musterName } from './musternamen.js';
10
10
  import { rollenFeld } from './rollenwahl.js';
11
11
  import { opt , quellenAuswahl, vorlagenAbweichung, bestandsAbweichung } from './entwurf.js';
@@ -371,24 +371,47 @@ export function detailZeile(e, s, idx) {
371
371
  muster: e.want,
372
372
  belegtVon: belegtVon,
373
373
  breite: '300px',
374
- beiWahl: function (r) { s.role = r; neu(); }
374
+ /* Die Rolle bestimmt den Platz, und der Platz bestimmt den Typ -
375
+ beides steht im selben Datensatz des type-detector. Wer eine
376
+ Rolle waehlt, bekommt deshalb den passenden Typ gleich mit.
377
+ Wer danach den Typ von Hand aendert, behaelt seine Wahl, bis er
378
+ die Rolle erneut wechselt. */
379
+ beiWahl: function (r) {
380
+ s.role = r;
381
+ /* Nur wo die Rolle im Muster genau einen Datentyp zulaesst, gibt
382
+ es etwas vorzugeben. Trifft sie mehrere Plaetze mit
383
+ verschiedenen Typen - wie die Fahrtrichtung boolean und number -
384
+ sind beide richtig, und die Wahl bleibt beim Nutzer. */
385
+ var moegliche = typenFuerRolle(e.want, r);
386
+ if (moegliche.length === 1 && s.typ !== moegliche[0]) { s.typ = moegliche[0]; }
387
+ neu();
388
+ }
375
389
  }));
376
390
 
377
391
  var must = e.want && musterVon(e.want);
378
392
  if (must) {
379
- var treffer = null;
380
- must.states.forEach(function (p) {
381
- if (!treffer && p.role && rolleTrifft(p.role, s.role)) { treffer = p; }
382
- });
393
+ var treffer = platzFuerRolle(e.want, s.role, s.typ);
394
+ var erlaubt = typenFuerRolle(e.want, s.role);
383
395
  var hin = el('div', 'sugg');
384
396
  if (treffer) {
385
397
  hin.appendChild(document.createTextNode(tr('pattern.fitsOn')));
386
398
  hin.appendChild(el('b', null, String(treffer.role)));
387
399
  hin.appendChild(document.createTextNode(tr('pattern.toSlot', treffer.name, musterName(e.want) || e.want)));
400
+ if (erlaubt.length) {
401
+ hin.appendChild(document.createTextNode(
402
+ tr('pattern.expectsType', erlaubt.join(tr('pattern.typeOr')))));
403
+ }
388
404
  } else {
389
405
  hin.textContent = tr('pattern.noPlaceLong', musterName(e.want) || e.want);
390
406
  }
391
407
  rb.appendChild(hin);
408
+ /* Passt der Typ nicht zum Platz, faellt der Punkt aus dem Muster -
409
+ lautlos, denn die Rolle stimmt ja. Genau das ist am 11.09.2026
410
+ an einem Tasmota-Stromzaehler passiert (I33). */
411
+ if (treffer && s.typ && erlaubt.length && erlaubt.indexOf(s.typ) === -1) {
412
+ rb.appendChild(el('div', 'aside w',
413
+ tr('pattern.typeMismatch', treffer.name, erlaubt.join(tr('pattern.typeOr')), s.typ)));
414
+ }
392
415
  }
393
416
  zeigeBeide(zeile(tr('detail.role'), rb), ['role']);
394
417
 
@@ -399,6 +422,8 @@ export function detailZeile(e, s, idx) {
399
422
  ['boolean', 'number', 'string', 'mixed'].forEach(function (t) { selT.appendChild(opt(t, t)); });
400
423
  selT.value = s.typ || 'number';
401
424
  selT.addEventListener('click', function (ev) { ev.stopPropagation(); });
425
+ /* Eine Aenderung von Hand bleibt stehen - bis die Rolle erneut
426
+ gewaehlt wird, dann gilt wieder der Typ des Platzes. */
402
427
  selT.addEventListener('change', function () { s.typ = selT.value; neu(); });
403
428
  var lT = el('label', 'fld');
404
429
  lT.appendChild(el('span', null, tr('detail.type')));
@@ -201,6 +201,93 @@ export function musterVon(typ) {
201
201
  return D.patterns[typ] || (TYP_ZU_MUSTER[typ] ? D.patterns[TYP_ZU_MUSTER[typ]] : null) || null;
202
202
  }
203
203
 
204
+ /* Welchen Platz trifft eine Rolle im gewaehlten Muster?
205
+
206
+ Gibt den ganzen Platz zurueck, nicht nur seinen Namen - denn er
207
+ traegt mehr als die Rolle: `type` sagt, welchen Datentyp der
208
+ type-detector dort erwartet. Am 11.09.2026 stand in einer eigenen
209
+ Vorlage `value.power.consumption` mit Typ `mixed`. Die Rolle war
210
+ richtig, der Platz CONSUMPTION verlangt aber `number` - der Punkt
211
+ fiel durch, kein Platz blieb belegt, und das ganze Geraet wurde
212
+ statt als `electricity` nur noch als `info` erkannt. Am Bildschirm
213
+ stand dazu nichts weiter als „passt nicht".
214
+
215
+ Dieselbe Suche stand vorher zweimal im Code (detail.js und
216
+ vorlagenblatt.js), beide Male ohne den Typ anzusehen. */
217
+ export function plaetzeFuerRolle(musterName, rolle) {
218
+ if (!rolle) { return []; }
219
+ var mu = musterName && musterVon(musterName);
220
+ if (!mu) { return []; }
221
+ return mu.states.filter(function (st) {
222
+ return st.role && rolleTrifft(st.role, rolle);
223
+ });
224
+ }
225
+
226
+ /* Der Platz, den eine Rolle trifft - und zwar der, dessen Datentyp
227
+ auch passt.
228
+
229
+ Dieselbe Rolle kann mehrere Plaetze treffen: das blinds-Muster hat
230
+ DIRECTION (boolean, /^indicator\.direction$/) und daneben
231
+ DIRECTION_ENUM (number, /^(indicator|value)\.direction$/). Homematic
232
+ meldet die Fahrtrichtung als Zahl (0 steht, 1 faehrt auf, 2 faehrt
233
+ zu, 3 unbekannt), und der Detector legt sie richtig auf
234
+ DIRECTION_ENUM. Wer nur die Rolle vergleicht und den ersten Treffer
235
+ nimmt, landet auf DIRECTION und meldet einen Konflikt, den es nicht
236
+ gibt - genau das tat diese Funktion am 11.09.2026 einen halben Tag
237
+ lang, samt einer "begruendeten Ausnahme" im Test, die keine war. */
238
+ export function platzFuerRolle(musterName, rolle, typ) {
239
+ var alle = plaetzeFuerRolle(musterName, rolle);
240
+ if (!alle.length) { return null; }
241
+ if (typ) {
242
+ for (var i = 0; i < alle.length; i++) {
243
+ if (typPasstZuPlatz(alle[i], typ)) { return alle[i]; }
244
+ }
245
+ }
246
+ return alle[0];
247
+ }
248
+
249
+ /* Alle Datentypen, die eine Rolle in diesem Muster annehmen darf -
250
+ ueber alle Plaetze, die sie trifft. Bei der Fahrtrichtung sind das
251
+ boolean und number: beide Formen sind richtig, nur auf verschiedenen
252
+ Plaetzen. */
253
+ export function typenFuerRolle(musterName, rolle) {
254
+ var raus = [];
255
+ plaetzeFuerRolle(musterName, rolle).forEach(function (st) {
256
+ typenVomPlatz(st).forEach(function (t) {
257
+ if (raus.indexOf(t) === -1) { raus.push(t); }
258
+ });
259
+ });
260
+ return raus;
261
+ }
262
+
263
+ /* Die Datentypen, die ein Platz zulaesst - als Liste.
264
+
265
+ Drei Faelle, gemessen am type-detector 6.0.1: 622 Plaetze nennen
266
+ genau einen Typ, 28 nennen mehrere (mediaPlayer/STATE etwa
267
+ ["boolean","number"]), 82 nennen gar keinen - WORKING und ERROR
268
+ zum Beispiel. Wer `String(platz.type)` nimmt, macht aus den 28 den
269
+ Typ "boolean,number", und den gibt es nicht. */
270
+ export function typenVomPlatz(platz) {
271
+ if (!platz || !platz.type) { return []; }
272
+ return Array.isArray(platz.type) ? platz.type.slice() : [String(platz.type)];
273
+ }
274
+
275
+ /* Der Typ, den ein Platz *vorgibt* - nur wenn er eindeutig ist. Wo ein
276
+ Platz mehrere zulaesst, gibt es nichts vorzugeben: dann ist jede der
277
+ erlaubten Formen richtig, und die Wahl bleibt beim Nutzer. */
278
+ export function typVomPlatz(platz) {
279
+ var t = typenVomPlatz(platz);
280
+ return t.length === 1 ? t[0] : '';
281
+ }
282
+
283
+ /* Passt ein eingestellter Typ zu dem, was der Platz zulaesst? Ohne
284
+ Vorgabe passt jeder; ohne eingestellten Typ wird nicht geurteilt. */
285
+ export function typPasstZuPlatz(platz, typ) {
286
+ var t = typenVomPlatz(platz);
287
+ if (!t.length || !typ) { return true; }
288
+ return t.indexOf(String(typ)) > -1;
289
+ }
290
+
204
291
  /* Welche Rolle faende im gewaehlten Muster einen Platz? */
205
292
  export function plaetzeFuerRollen(musterName) {
206
293
  var raus = {};
@@ -10,7 +10,7 @@
10
10
  import { S } from './zustand.js';
11
11
  import { D, el, $ } from './basis.js';
12
12
  import { tr, sprachtext } from './sprache.js';
13
- import { VORSCHAU, musterVon, erkenneEntwurf } from './erkennung.js';
13
+ import { VORSCHAU, musterVon, erkenneEntwurf, platzFuerRolle, typenFuerRolle } from './erkennung.js';
14
14
  import { anMusterAnpassen } from './vorlagen.js';
15
15
  import { ratePlaetze, rateZurueck, rateAnzahl, rateMoeglich } from './vorschlagen.js';
16
16
  import { zeichneErgebnis, entwurfAngefasst, knopfFrisch } from './ergebnis.js';
@@ -138,8 +138,25 @@ export function baueMusterwahl(e, haupt, pflichtFehlt) {
138
138
  if (!r.length) {
139
139
  var fehlend = musterVon(m).states.filter(function (x) { return x.required; })
140
140
  .map(function (x) { return x.name; });
141
- mark = fehlend.length ? ('✕ ' + tr('pattern.missing', fehlend.join(', ')))
142
- : tr('pattern.doesNotFit');
141
+ if (fehlend.length) {
142
+ mark = '✕ ' + tr('pattern.missing', fehlend.join(', '));
143
+ } else {
144
+ /* Kein Pflichtplatz fehlt und trotzdem passt nichts - dann liegt
145
+ es an einer Zeile, die ihren Platz trifft, aber im falschen
146
+ Datentyp steht. Bis 11.09.2026 stand hier nur „passt nicht",
147
+ und genau dieser Fall (electricity hat keinen einzigen
148
+ Pflichtplatz) kostete Ricardo eine Stunde Suche: Rolle
149
+ value.power.consumption richtig, Typ mixed statt number, der
150
+ Punkt fiel lautlos aus dem Muster. */
151
+ mark = tr('pattern.doesNotFit');
152
+ (pruefE.states || []).some(function (st) {
153
+ var moegliche = typenFuerRolle(m, st.role);
154
+ if (!st.typ || !moegliche.length || moegliche.indexOf(st.typ) > -1) { return false; }
155
+ var pl = platzFuerRolle(m, st.role);
156
+ mark = tr('pattern.fitsNotType', pl.name, st.typ, moegliche.join(tr('pattern.typeOr')));
157
+ return true;
158
+ });
159
+ }
143
160
  } else {
144
161
  var g = r[0].states.filter(function (x) { return x.id; }).length;
145
162
  mark = tr('pattern.slotsTaken', g, r[0].states.length);
@@ -281,9 +298,16 @@ export function baueMusterwahl(e, haupt, pflichtFehlt) {
281
298
  Auswahlfeld. */
282
299
  var mBeschriften = function () {
283
300
  /* Im Feld der Beiname, der rohe Name im Tooltip - fuer beides
284
- nebeneinander ist das Feld zu schmal. */
285
- sel.value = e.want ? ((musterName(e.want) || e.want) + ' ' + markeFuer(e.want)) : '';
286
- sel.title = e.want || '';
301
+ nebeneinander ist das Feld zu schmal.
302
+
303
+ Die Marke nennt seit 11.09.2026 auch den Grund, wenn ein Muster
304
+ an einem falschen Datentyp scheitert („✕ CONSUMPTION: Typ mixed
305
+ statt number"). Das ist laenger als „passt nicht" und wird im
306
+ schmalen Feld abgeschnitten - deshalb steht sie zusaetzlich im
307
+ Tooltip, wo sie ganz lesbar ist. */
308
+ var marke = e.want ? markeFuer(e.want) : '';
309
+ sel.value = e.want ? ((musterName(e.want) || e.want) + ' ' + marke) : '';
310
+ sel.title = e.want ? (e.want + (marke ? ' ' + marke : '')) : '';
287
311
  };
288
312
  mBeschriften();
289
313
 
@@ -11,7 +11,9 @@ import { $ } from './basis.js';
11
11
  export var expertenVorgabe = false;
12
12
 
13
13
  /* ================== Sprachen ==================
14
- Woerterbuch als flache Schluessel-Text-Karte unter admin/i18n/.
14
+ Woerterbuch als flache Schluessel-Text-Karte unter admin/sprachen/.
15
+ (Nicht admin/i18n/ - dort liegt das Woerterbuch der Einstellungsseite,
16
+ das der Admin selbst laedt.)
15
17
  Neue Sprache = neue Datei, sonst nichts. Faellt eine Uebersetzung
16
18
  aus, greift Englisch, danach der Schluessel selbst — so bleibt die
17
19
  Oberflaeche bedienbar statt leer. */
@@ -38,7 +40,7 @@ export function ladeSprache(fertig) {
38
40
  var vorgabe = (navigator.language || 'en').slice(0, 2).toLowerCase();
39
41
 
40
42
  function hole(code, ziel, danach) {
41
- fetch('./i18n/' + code + '.json')
43
+ fetch('./sprachen/' + code + '.json')
42
44
  .then(function (r) { return r.ok ? r.json() : {}; })
43
45
  .then(function (d) { Object.keys(d).forEach(function (k) { ziel[k] = d[k]; }); danach(); })
44
46
  .catch(function () { danach(); });
@@ -9,7 +9,7 @@ import { D, $, el, kurz } from './basis.js';
9
9
  import { tr, sprachtext, sprache } from './sprache.js';
10
10
  import { katalogFehlt } from './katalog.js';
11
11
  import { funktionsAuswahl, kennungZuFunktion } from './aufzaehlungen.js';
12
- import { musterVon, rolleTrifft } from './erkennung.js';
12
+ import { musterVon, platzFuerRolle, typenFuerRolle } from './erkennung.js';
13
13
  import { musterZeile, musterName } from './musternamen.js';
14
14
  import { ladeVorlagen, aendereVorlagen, setzeMeta, pruefeVorlage, hinweisTaugt, INSTANZ_ID } from './vorlagen.js';
15
15
  import { kindZustaende, hatPunkt, feldAusFormel } from './werte.js';
@@ -283,9 +283,12 @@ export function zeichneVorlagenBlatt(host) {
283
283
  var st = el('select', 'tx');
284
284
  st.disabled = !eigen;
285
285
  st.appendChild(opt('', tr('tpls.noType')));
286
+ /* Wie im Speichern-Dialog: der Wert ist der Typ, nicht der
287
+ Musterschluessel. musterwahl.js loest es seit laengerem so. */
286
288
  (D ? Object.keys(D.patterns).sort() : []).forEach(function (m) {
287
- var o = opt(m, musterZeile(m));
288
- if (m === v.geraetetyp) { o.selected = true; }
289
+ var typ = D.patterns[m].type || m;
290
+ var o = opt(typ, musterZeile(m));
291
+ if (typ === v.geraetetyp) { o.selected = true; }
289
292
  st.appendChild(o);
290
293
  });
291
294
  st.addEventListener('change', function () {
@@ -543,7 +546,7 @@ function dtFeld(beschriftung, element) {
543
546
 
544
547
  /* Rollenauswahl samt Begruendung. geraetetyp darf leer sein — dann
545
548
  entfaellt nur der Hinweis, welchen Platz die Rolle traefe. */
546
- function rollenBlock(rolle, geraetetyp, setzen) {
549
+ function rollenBlock(rolle, geraetetyp, setzen, typJetzt, setzeTyp) {
547
550
  var rb = el('div');
548
551
  /* Dasselbe durchsuchbare Feld wie am Geraet - ein Aussehen fuer alle
549
552
  Rollenwahlen. Ohne Belegt-Vermerk: in der Vorlage gibt es keinen
@@ -553,24 +556,38 @@ function rollenBlock(rolle, geraetetyp, setzen) {
553
556
  muster: geraetetyp,
554
557
  leerErlaubt: true,
555
558
  breite: '300px',
556
- beiWahl: function (r) { setzen(r); }
559
+ /* Wie am Geraet: der Platz bringt seinen Datentyp mit, also wird er
560
+ beim Waehlen der Rolle gleich gesetzt. Eine Vorlage, deren Rolle
561
+ stimmt und deren Typ nicht, faellt sonst lautlos aus dem Muster. */
562
+ beiWahl: function (r) {
563
+ /* Wie am Geraet: nur ein eindeutiger Typ wird gesetzt. */
564
+ var moegliche = typenFuerRolle(geraetetyp, r);
565
+ if (moegliche.length === 1 && setzeTyp && typJetzt !== moegliche[0]) { setzeTyp(moegliche[0]); }
566
+ setzen(r);
567
+ }
557
568
  }));
558
569
 
559
570
  var must = geraetetyp && musterVon(geraetetyp);
560
571
  if (must) {
561
- var treffer = null;
562
- must.states.forEach(function (pp) {
563
- if (!treffer && pp.role && rolleTrifft(pp.role, rolle)) { treffer = pp; }
564
- });
572
+ var treffer = platzFuerRolle(geraetetyp, rolle, typJetzt);
573
+ var erlaubt = typenFuerRolle(geraetetyp, rolle);
565
574
  var hin = el('div', 'sugg');
566
575
  if (treffer) {
567
576
  hin.appendChild(document.createTextNode(tr('pattern.fitsOn')));
568
577
  hin.appendChild(el('b', null, String(treffer.role)));
569
578
  hin.appendChild(document.createTextNode(tr('pattern.toSlot', treffer.name, musterName(geraetetyp) || geraetetyp)));
579
+ if (erlaubt.length) {
580
+ hin.appendChild(document.createTextNode(
581
+ tr('pattern.expectsType', erlaubt.join(tr('pattern.typeOr')))));
582
+ }
570
583
  } else {
571
584
  hin.textContent = tr('pattern.noPlaceLong', musterName(geraetetyp) || geraetetyp);
572
585
  }
573
586
  rb.appendChild(hin);
587
+ if (treffer && typJetzt && erlaubt.length && erlaubt.indexOf(typJetzt) === -1) {
588
+ rb.appendChild(el('div', 'aside w',
589
+ tr('pattern.typeMismatch', treffer.name, erlaubt.join(tr('pattern.typeOr')), typJetzt)));
590
+ }
574
591
  }
575
592
  return rb;
576
593
  }
@@ -782,7 +799,7 @@ function vZeilenDetail(z, nr) {
782
799
 
783
800
  dtZeile(d, tr('detail.role'), rollenBlock(z.rolle, v.geraetetyp, function (neu) {
784
801
  setzeFeld('rolle', neu);
785
- }));
802
+ }, z.typ, function (t) { setzeFeld('typ', t); }));
786
803
 
787
804
  dtZeile(d, tr('detail.display'), anzeigeBlock(
788
805
  function (was) {
@@ -1222,9 +1239,24 @@ export function vorlagenVorbereiten(e) {
1222
1239
 
1223
1240
  var zeilen = [];
1224
1241
  e.states.forEach(function (s) {
1225
- if (!s.n || !s.srcR) { return; }
1226
- var r = relZu(s.srcR, e.kanal);
1227
- var w = (s.srcW && s.srcW !== s.srcR) ? relZu(s.srcW, e.kanal) : null;
1242
+ /* Eine Zeile braucht wenigstens ein Ziel - lesend oder schreibend.
1243
+ `STOP` am Rollladen hat nur ein Schreibziel: ein Tastendruck hat
1244
+ keinen Zustand zum Lesen. Bis 11.09.2026 stand hier `!s.srcR`,
1245
+ und solche Zeilen fielen beim Speichern lautlos weg. Dass das
1246
+ Anwenden diesen Fall kennt, steht seit dem 09.09.2026 in
1247
+ vorlagen.js - die Gegenrichtung war vergessen worden. */
1248
+ if (!s.n || (!s.srcR && !s.srcW)) { return; }
1249
+ var r = s.srcR ? relZu(s.srcR, e.kanal) : { p: '', abs: false };
1250
+ /* Das Schreibziel gehoert in die Vorlage, auch wenn es derselbe
1251
+ Punkt ist wie der gelesene. Bis 11.09.2026 stand hier zusaetzlich
1252
+ `s.srcW !== s.srcR`, und genau das trifft auf jeden Aktor zu, der
1253
+ seinen eigenen Zustand fuehrt: Rollladen, Dimmer, Thermostat
1254
+ schreiben auf denselben Punkt, den sie lesen (1.LEVEL). Beim
1255
+ Speichern verschwand ihr Schreibweg - der Alias zeigte die
1256
+ Position an und liess sich nicht mehr verstellen. Aufgefallen
1257
+ bei Tasmota nie, weil dort tele.STATE gelesen und cmnd.POWER
1258
+ geschrieben wird. */
1259
+ var w = s.srcW ? relZu(s.srcW, e.kanal) : null;
1228
1260
  var zv = null;
1229
1261
  if (quelle && s.ausVorlage) {
1230
1262
  (quelle.zustaende || []).forEach(function (z) { if (z.name === s.ausVorlage) { zv = z; } });
@@ -1348,9 +1380,11 @@ export function baueVorlage(z) {
1348
1380
  name: r.name,
1349
1381
  rolle: s.role || undefined,
1350
1382
  typ: s.typ || undefined,
1351
- einheit: s.unit || undefined,
1352
- lesen: zPfad(r, k, false, z.zeilen)
1383
+ einheit: s.unit || undefined
1353
1384
  };
1385
+ /* Ohne Lesequelle kein `lesen` - sonst stuende dort ein leerer
1386
+ Pfad, und `wendeAn` suchte einen Punkt namens "". */
1387
+ if (r.lesenRoh) { zu.lesen = zPfad(r, k, false, z.zeilen); }
1354
1388
  if (r.lesenAbs) { zu.absolut = true; }
1355
1389
  if (r.schreibenRoh) { zu.schreiben = zPfad(r, k, true, z.zeilen); }
1356
1390
  if (f) { zu.feld = f; } else if (s.f) { zu.leseformel = s.f; }
@@ -1696,9 +1730,16 @@ export function zeichneVorlagenDialog() {
1696
1730
  lt.appendChild(el('span', 'feldlabel', tr('tpls.deviceType')));
1697
1731
  var st = el('select', 'tx');
1698
1732
  st.appendChild(opt('', tr('tpls.noType')));
1733
+ /* Der Wert ist der Geraetetyp, nicht der Musterschluessel - drei
1734
+ Muster tragen einen anderen Namen als ihr Typ: blinds meldet
1735
+ "blind", mediaPlayer meldet "media", levelSlider meldet "slider".
1736
+ Die Vorlagen fuehren den Typ. Bis 11.09.2026 stand hier der
1737
+ Schluessel, und an jedem Rollladen zeigte der Dialog
1738
+ "- keiner -", obwohl "blind" gesetzt war. */
1699
1739
  (D ? Object.keys(D.patterns).sort() : []).forEach(function (m) {
1700
- var o = opt(m, musterZeile(m));
1701
- if (m === k.geraetetyp) { o.selected = true; }
1740
+ var typ = D.patterns[m].type || m;
1741
+ var o = opt(typ, musterZeile(m));
1742
+ if (typ === k.geraetetyp) { o.selected = true; }
1702
1743
  st.appendChild(o);
1703
1744
  });
1704
1745
  st.addEventListener('change', function () { k.geraetetyp = st.value; zeichneVorlagenDialog(); });