iobroker.alias-workbench 0.9.8 → 0.9.10
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/LICENSE +1 -1
- package/README.md +27 -2
- package/admin/css/werkbank.css +8 -3
- package/admin/i18n/de.json +12 -588
- package/admin/i18n/en.json +12 -588
- package/admin/i18n/es.json +14 -0
- package/admin/i18n/fr.json +14 -0
- package/admin/i18n/it.json +14 -0
- package/admin/i18n/nl.json +14 -0
- package/admin/i18n/pl.json +14 -0
- package/admin/i18n/pt.json +14 -0
- package/admin/i18n/ru.json +14 -0
- package/admin/i18n/uk.json +14 -0
- package/admin/i18n/zh-cn.json +14 -0
- package/admin/js/detail.js +31 -6
- package/admin/js/entwurf.js +47 -17
- package/admin/js/ergebnis.js +49 -4
- package/admin/js/erkennung.js +133 -2
- package/admin/js/musterwahl.js +40 -6
- package/admin/js/quellentausch.js +179 -19
- package/admin/js/schreiben.js +98 -3
- package/admin/js/sprache.js +10 -3
- package/admin/js/vorlagen.js +12 -2
- package/admin/js/vorlagenblatt.js +123 -20
- package/admin/js/werte.js +63 -1
- package/admin/js/zuordnung.js +29 -35
- package/admin/js/zustandsliste.js +37 -4
- package/admin/jsonConfig.json +13 -157
- package/admin/sprachen/de.json +607 -0
- package/admin/sprachen/en.json +607 -0
- package/admin/vorlagen/messpunkt.json +2 -1
- package/admin/vorlagen/tasmota-lampe.json +2 -1
- package/admin/vorlagen/tasmota-mehrfach.json +2 -1
- package/admin/vorlagen/tasmota-rgb.json +2 -1
- package/admin/vorlagen/tasmota-steckdose.json +2 -1
- package/io-package.json +47 -47
- package/package.json +2 -2
|
@@ -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
|
+
}
|
package/admin/js/detail.js
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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 =
|
|
380
|
-
|
|
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')));
|
package/admin/js/entwurf.js
CHANGED
|
@@ -9,7 +9,7 @@ import { txt, tr } from './sprache.js';
|
|
|
9
9
|
import './enums.js';
|
|
10
10
|
import { zusatzName, setzeModus, zeichneBaum, merkeKlappstand } from './baum.js';
|
|
11
11
|
import { kindZustaende, aliasQuellen, holeWerte,
|
|
12
|
-
mitVorspann, schreibQuelle
|
|
12
|
+
mitVorspann, schreibQuelle, zeileAusAlias
|
|
13
13
|
} from './werte.js';
|
|
14
14
|
import { erkenneEntwurf } from './erkennung.js';
|
|
15
15
|
import { vorschlag , pruefeVorlage, zeigeAbozahl } from './vorlagen.js';
|
|
@@ -58,6 +58,17 @@ export function merkeHakenVorgabe(e) {
|
|
|
58
58
|
return e;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/* Was von `common.name` als Beschriftung uebrig bleibt.
|
|
62
|
+
|
|
63
|
+
Gleicht der Name dem Zeilennamen, ist er keine eigene Beschriftung,
|
|
64
|
+
sondern die Vorgabe - dann bleibt das Feld leer. Dieselbe Regel gilt
|
|
65
|
+
in `zeileAusAlias` (werte.js) und damit an allen vier Stellen, die
|
|
66
|
+
eine Zeile aus einem Alias-Objekt bauen. */
|
|
67
|
+
function beschriftungAus(name, zeilenname) {
|
|
68
|
+
var nm = txt(name);
|
|
69
|
+
return (nm && nm !== zeilenname) ? nm : '';
|
|
70
|
+
}
|
|
71
|
+
|
|
61
72
|
export function baueEntwurf(kanal) {
|
|
62
73
|
var istAlias = (kanal.indexOf('alias.') === 0);
|
|
63
74
|
var e = { kanal: kanal, states: [], want: null, wantAuto: null, alleMuster: false };
|
|
@@ -106,7 +117,18 @@ export function baueEntwurf(kanal) {
|
|
|
106
117
|
srcW: istAlias ? schreibQuelle(o) : (c.write ? id : ''),
|
|
107
118
|
f: (typeof a.read === 'string') ? a.read : '',
|
|
108
119
|
fw: (typeof a.write === 'string') ? a.write : '',
|
|
109
|
-
|
|
120
|
+
/* Dieselbe Regel wie ueberall sonst: „leer, wenn sie dem
|
|
121
|
+
Zeilennamen gleicht".
|
|
122
|
+
|
|
123
|
+
Hier stand `istAlias ? txt(c.name) : …` ohne diese Pruefung.
|
|
124
|
+
Folge: Wo `common.name` dem Punktnamen gleicht - bei fast jedem
|
|
125
|
+
Alias, den die Werkbank selbst angelegt hat -, zeigte „Alias
|
|
126
|
+
bearbeiten" den Namen und „Alias anlegen" ein leeres Feld.
|
|
127
|
+
Derselbe Alias, zwei Ansichten, zwei Antworten (U21, gemessen
|
|
128
|
+
12.09.2026). Geschrieben wurde in beiden Faellen dasselbe; zu
|
|
129
|
+
sehen war es trotzdem. */
|
|
130
|
+
caption: istAlias ? beschriftungAus(c.name, kurzName)
|
|
131
|
+
: kanalBeschriftung(kanal, kurzName),
|
|
110
132
|
manuell: false
|
|
111
133
|
});
|
|
112
134
|
});
|
|
@@ -1167,18 +1189,33 @@ export function bestandVorrang(e, aliasId) {
|
|
|
1167
1189
|
her, nachdem der Bestand ihn ueberschrieben hat. */
|
|
1168
1190
|
on: s.on
|
|
1169
1191
|
};
|
|
1192
|
+
var ist = zeileAusAlias(o, s.n);
|
|
1193
|
+
/* Rolle und Typ NUR, wenn sie im Alias ueberhaupt stehen.
|
|
1194
|
+
|
|
1195
|
+
`zeileAusAlias` liefert an dieser Stelle `''` - fuer die anderen
|
|
1196
|
+
drei Aufrufer richtig, hier nicht: ein Alias ohne eigene Rolle
|
|
1197
|
+
soll die der Vorlage behalten, statt sie gegen einen Leerstring zu
|
|
1198
|
+
tauschen. Das ist der eine Unterschied, der beim Zusammenlegen der
|
|
1199
|
+
fuenf Stellen erhalten bleiben musste (Y5) - wer ihn wegraeumt,
|
|
1200
|
+
nimmt jedem vorlagenbasierten Alias seine Rollen. */
|
|
1170
1201
|
if (c.role !== undefined) { s.role = c.role; }
|
|
1171
1202
|
if (c.type !== undefined) { s.typ = c.type; }
|
|
1172
|
-
s.unit =
|
|
1203
|
+
s.unit = ist.unit;
|
|
1173
1204
|
s.states = c.states;
|
|
1174
1205
|
/* Die Beschriftung gehoert dem Nutzer - sie wird auch spaeter vom
|
|
1175
|
-
Vorlagen-Abgleich nicht angefasst (Ricardo, 25.08.2026).
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1206
|
+
Vorlagen-Abgleich nicht angefasst (Ricardo, 25.08.2026).
|
|
1207
|
+
|
|
1208
|
+
Seit dem 12.09.2026 gilt hier dieselbe Regel wie ueberall sonst:
|
|
1209
|
+
gleicht sie dem Zeilennamen, bleibt das Feld leer. Vorher stand
|
|
1210
|
+
hier `if (c.name !== undefined) s.caption = txt(c.name)` - und
|
|
1211
|
+
weil `vomAliasUebernehmen` danach laeuft und verwirft, hing es
|
|
1212
|
+
an der Reihenfolge, welche der beiden Antworten man zu sehen
|
|
1213
|
+
bekam (U21). */
|
|
1214
|
+
if (c.name !== undefined) { s.caption = ist.caption; }
|
|
1215
|
+
s.f = ist.f;
|
|
1216
|
+
s.fw = ist.fw;
|
|
1180
1217
|
if (q.read) { s.srcR = q.read; }
|
|
1181
|
-
s.srcW =
|
|
1218
|
+
s.srcW = ist.srcW;
|
|
1182
1219
|
s.on = true;
|
|
1183
1220
|
s.ausBestand = true;
|
|
1184
1221
|
});
|
|
@@ -1209,14 +1246,7 @@ export function bestandsAbweichung(s, aliasId) {
|
|
|
1209
1246
|
if (!s || !s.n || !s.on || !aliasId) { return []; }
|
|
1210
1247
|
var o = S.objects[aliasId + '.' + s.n];
|
|
1211
1248
|
if (!o || !o.common) { return []; }
|
|
1212
|
-
var
|
|
1213
|
-
var ist = {
|
|
1214
|
-
role: c.role || '', typ: c.type || '', unit: c.unit || '',
|
|
1215
|
-
f: (typeof a.read === 'string') ? a.read : '',
|
|
1216
|
-
fw: (typeof a.write === 'string') ? a.write : '',
|
|
1217
|
-
srcR: q.read || '',
|
|
1218
|
-
srcW: schreibQuelle(o)
|
|
1219
|
-
};
|
|
1249
|
+
var ist = zeileAusAlias(o, s.n);
|
|
1220
1250
|
var raus = [];
|
|
1221
1251
|
['role', 'typ', 'unit', 'f', 'fw', 'srcR', 'srcW'].forEach(function (k) {
|
|
1222
1252
|
var jetzt = s[k] || '';
|
package/admin/js/ergebnis.js
CHANGED
|
@@ -705,6 +705,27 @@ var warumAuf = false;
|
|
|
705
705
|
neuE.roh = rohJetzt;
|
|
706
706
|
neuE.vorschlag = true;
|
|
707
707
|
neuE.tplName = e.tplName; neuE.grund = e.grund; neuE.ziel = e.ziel;
|
|
708
|
+
/* Ordner und Name getrennt mitgeben, nicht nur das fertige Ziel.
|
|
709
|
+
|
|
710
|
+
`setzeZiel` rechnet den Ordner nur aus, solange keiner dasteht —
|
|
711
|
+
und dabei liest es das letzte Segment von `e.ziel` als
|
|
712
|
+
Geraetenamen. Bei einem Geraet mit mehreren Ausgaengen ist das
|
|
713
|
+
letzte Segment aber der AUSGANG (`…Garten-Ventilinsel.POWER2`),
|
|
714
|
+
und der Ordner bekam ihn angehaengt. Jeder Druck auf diesen
|
|
715
|
+
Knopf schob den Ablageort eine Ebene tiefer, und geschrieben
|
|
716
|
+
wurde er auch so: gemessen 12.09.2026 am Testsystem entstanden
|
|
717
|
+
nach drei Klicks vier Ordner statt einem
|
|
718
|
+
(`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`).
|
|
719
|
+
|
|
720
|
+
Der Ausgangswechsel eine Stelle weiter oben macht es seit jeher
|
|
721
|
+
richtig — hier dieselbe Form. Im Aliasmodus sind beide Felder
|
|
722
|
+
`undefined`; dann bleibt alles wie bisher, `setzeZiel` steigt
|
|
723
|
+
dort ohnehin sofort aus. `ordnerVonHand` gehoert mit, sonst
|
|
724
|
+
verliert der Raumvorschlag die Entscheidung, wer den Ordner
|
|
725
|
+
gesetzt hat (E41). */
|
|
726
|
+
neuE.zielOrdner = e.zielOrdner;
|
|
727
|
+
neuE.zielName = e.zielName;
|
|
728
|
+
neuE.ordnerVonHand = e.ordnerVonHand;
|
|
708
729
|
if (fest) { neuE.vonHandGewaehlt = false; neuE.ausBestand = true; }
|
|
709
730
|
if (vorh && S.objects[vorh]) { bestandVorrang(neuE, vorh); }
|
|
710
731
|
S.entwurf = neuE; S.openRow = null; zeichneErgebnis();
|
|
@@ -827,15 +848,32 @@ var warumAuf = false;
|
|
|
827
848
|
ba.hidden = !mehr && !mehrK;
|
|
828
849
|
if (mehr) {
|
|
829
850
|
ba.textContent = tr('write.createAll', e.instanzen.length);
|
|
851
|
+
/* Dieselbe Rechnung wie beim Schreiben, samt Kollisionsschutz.
|
|
852
|
+
|
|
853
|
+
Zwei Kanaele koennen nach der Saeuberung denselben Namen
|
|
854
|
+
ergeben („Licht Bar" und „Licht, Bar" beide `Licht_Bar`); der
|
|
855
|
+
Schreibpfad haengt dann `_2` an. Ohne dieselbe Rechnung stuende
|
|
856
|
+
im Hinweis zweimal derselbe Name und danach etwas anderes am
|
|
857
|
+
System - genau die Luecke, die G31 beschreibt (12.09.2026). */
|
|
858
|
+
var belegt = {};
|
|
830
859
|
ba.title = e.instanzen.map(function (n) {
|
|
831
|
-
|
|
860
|
+
var nm = (String(n) === String(e.instanz)) ? e.zielName : ausgangName(e, n);
|
|
861
|
+
if (belegt[nm]) {
|
|
862
|
+
var z = 1, n2;
|
|
863
|
+
do { z++; n2 = nm + '_' + z; } while (belegt[n2]);
|
|
864
|
+
nm = n2;
|
|
865
|
+
}
|
|
866
|
+
belegt[nm] = 1;
|
|
867
|
+
return (e.zielOrdner || '') + '.' + nm;
|
|
832
868
|
}).join(String.fromCharCode(10));
|
|
833
869
|
} else if (mehrK) {
|
|
834
870
|
ba.textContent = tr('write.createPerChannel', e.kanalGeraete.length);
|
|
835
871
|
/* Im Hinweis stehen die Namen, die entstehen wuerden — sonst
|
|
836
872
|
klickt man auf eine Zahl und weiss nicht, was danach dasteht. */
|
|
837
873
|
ba.title = e.kanalGeraete.map(function (k) {
|
|
838
|
-
|
|
874
|
+
/* Die Kennung, nicht den Anzeigenamen - so heisst das Objekt
|
|
875
|
+
hinterher wirklich (G31). */
|
|
876
|
+
return (e.zielOrdner || '') + '.' + (k.kennung || k.name) + ' (' + k.typ + ')';
|
|
839
877
|
}).join(String.fromCharCode(10));
|
|
840
878
|
}
|
|
841
879
|
ba.disabled = false;
|
|
@@ -1050,9 +1088,16 @@ var warumAuf = false;
|
|
|
1050
1088
|
function verkabeleDialoge() {
|
|
1051
1089
|
var bc = $('#btn-checks'), bd = $('#btn-dry'), bw = $('#btn-dry-write');
|
|
1052
1090
|
if (bc) { bc.addEventListener('click', function () { $('#dlg-checks').showModal(); }); }
|
|
1053
|
-
|
|
1091
|
+
/* Beim Oeffnen von Hand faengt der Dialog frisch an - ein alter
|
|
1092
|
+
Sendepunkt-Fehler von vorhin hat dann nichts mehr zu sagen (H17).
|
|
1093
|
+
Aus dem Rueckruf heraus wird zeigeTrockenlauf direkt gerufen, dort
|
|
1094
|
+
bleibt die Meldung also stehen. */
|
|
1095
|
+
var frisch = function (alle) {
|
|
1096
|
+
return function () { S.mqFehler = null; zeigeTrockenlauf(alle); };
|
|
1097
|
+
};
|
|
1098
|
+
if (bd) { bd.addEventListener('click', frisch(false)); }
|
|
1054
1099
|
var ba2 = $('#btn-dry-alle');
|
|
1055
|
-
if (ba2) { ba2.addEventListener('click',
|
|
1100
|
+
if (ba2) { ba2.addEventListener('click', frisch(true)); }
|
|
1056
1101
|
if (bw) { bw.addEventListener('click', schreibeObjekte); }
|
|
1057
1102
|
var bdel = $('#btn-del'), bdg = $('#btn-del-go');
|
|
1058
1103
|
if (bdel) { bdel.addEventListener('click', zeigeLoeschen); }
|
package/admin/js/erkennung.js
CHANGED
|
@@ -61,11 +61,25 @@ export function rolleTrifft(r, rolle) {
|
|
|
61
61
|
Ableitung bekam so ein Punkt gar keine: er belegte seinen Platz nie,
|
|
62
62
|
liess sich beliebig oft hinzufuegen, und die Rolle fehlte auch in der
|
|
63
63
|
Auswahlliste — der Platz war auf keinem Weg zu befuellen. */
|
|
64
|
+
/* Der fehlende Anfangsanker zaehlt nicht gegen den Platz.
|
|
65
|
+
|
|
66
|
+
`vacuumCleaner.MAP_URL` schreibt `/vacuum\.map\.url$/` - ohne `^`.
|
|
67
|
+
Gemeint ist derselbe eine Rollenname wie bei den anderen; der Platz
|
|
68
|
+
blieb aber ohne Rolle, weil hier beide Anker verlangt wurden
|
|
69
|
+
(gemessen 12.09.2026 ueber alle 53 Muster: ausser MAP_URL traf es
|
|
70
|
+
nur `media.COVER`, und dessen Ausdruck `/^media\.cover(\..*)$/`
|
|
71
|
+
beschreibt wirklich keinen einen Namen - der Platz hat dafuer eine
|
|
72
|
+
`defaultRole`).
|
|
73
|
+
|
|
74
|
+
Das Endezeichen bleibt Pflicht: ohne `$` waere `/^level\.dimmer/`
|
|
75
|
+
auch von `level.dimmer.irgendwas` erfuellt, und dann ist es kein
|
|
76
|
+
Name mehr, sondern ein Praefix. */
|
|
64
77
|
export function rolleAusAusdruck(r) {
|
|
65
78
|
var q = ausdruckText(r);
|
|
66
79
|
if (!q) { return ''; }
|
|
67
|
-
if (q.
|
|
68
|
-
|
|
80
|
+
if (q.slice(-1) !== '$') { return ''; }
|
|
81
|
+
if (q.charAt(0) === '^') { q = q.slice(1); }
|
|
82
|
+
var t = q.slice(0, -1).split(String.fromCharCode(92)).join('');
|
|
69
83
|
return /^[A-Za-z0-9_]+([.][A-Za-z0-9_]+)*$/.test(t) ? t : '';
|
|
70
84
|
}
|
|
71
85
|
|
|
@@ -201,6 +215,123 @@ export function musterVon(typ) {
|
|
|
201
215
|
return D.patterns[typ] || (TYP_ZU_MUSTER[typ] ? D.patterns[TYP_ZU_MUSTER[typ]] : null) || null;
|
|
202
216
|
}
|
|
203
217
|
|
|
218
|
+
/* Welchen Platz trifft eine Rolle im gewaehlten Muster?
|
|
219
|
+
|
|
220
|
+
Gibt den ganzen Platz zurueck, nicht nur seinen Namen - denn er
|
|
221
|
+
traegt mehr als die Rolle: `type` sagt, welchen Datentyp der
|
|
222
|
+
type-detector dort erwartet. Am 11.09.2026 stand in einer eigenen
|
|
223
|
+
Vorlage `value.power.consumption` mit Typ `mixed`. Die Rolle war
|
|
224
|
+
richtig, der Platz CONSUMPTION verlangt aber `number` - der Punkt
|
|
225
|
+
fiel durch, kein Platz blieb belegt, und das ganze Geraet wurde
|
|
226
|
+
statt als `electricity` nur noch als `info` erkannt. Am Bildschirm
|
|
227
|
+
stand dazu nichts weiter als „passt nicht".
|
|
228
|
+
|
|
229
|
+
Dieselbe Suche stand vorher zweimal im Code (detail.js und
|
|
230
|
+
vorlagenblatt.js), beide Male ohne den Typ anzusehen. */
|
|
231
|
+
export function plaetzeFuerRolle(musterName, rolle) {
|
|
232
|
+
if (!rolle) { return []; }
|
|
233
|
+
var mu = musterName && musterVon(musterName);
|
|
234
|
+
if (!mu) { return []; }
|
|
235
|
+
return mu.states.filter(function (st) {
|
|
236
|
+
return st.role && rolleTrifft(st.role, rolle);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* Der Platz, den eine Rolle trifft - und zwar der, dessen Datentyp
|
|
241
|
+
auch passt.
|
|
242
|
+
|
|
243
|
+
Dieselbe Rolle kann mehrere Plaetze treffen: das blinds-Muster hat
|
|
244
|
+
DIRECTION (boolean, /^indicator\.direction$/) und daneben
|
|
245
|
+
DIRECTION_ENUM (number, /^(indicator|value)\.direction$/). Homematic
|
|
246
|
+
meldet die Fahrtrichtung als Zahl (0 steht, 1 faehrt auf, 2 faehrt
|
|
247
|
+
zu, 3 unbekannt), und der Detector legt sie richtig auf
|
|
248
|
+
DIRECTION_ENUM. Wer nur die Rolle vergleicht und den ersten Treffer
|
|
249
|
+
nimmt, landet auf DIRECTION und meldet einen Konflikt, den es nicht
|
|
250
|
+
gibt - genau das tat diese Funktion am 11.09.2026 einen halben Tag
|
|
251
|
+
lang, samt einer "begruendeten Ausnahme" im Test, die keine war. */
|
|
252
|
+
export function platzFuerRolle(musterName, rolle, typ) {
|
|
253
|
+
var alle = plaetzeFuerRolle(musterName, rolle);
|
|
254
|
+
if (!alle.length) { return null; }
|
|
255
|
+
if (typ) {
|
|
256
|
+
for (var i = 0; i < alle.length; i++) {
|
|
257
|
+
if (typPasstZuPlatz(alle[i], typ)) { return alle[i]; }
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return alle[0];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Alle Datentypen, die eine Rolle in diesem Muster annehmen darf -
|
|
264
|
+
ueber alle Plaetze, die sie trifft. Bei der Fahrtrichtung sind das
|
|
265
|
+
boolean und number: beide Formen sind richtig, nur auf verschiedenen
|
|
266
|
+
Plaetzen. */
|
|
267
|
+
export function typenFuerRolle(musterName, rolle) {
|
|
268
|
+
var raus = [];
|
|
269
|
+
plaetzeFuerRolle(musterName, rolle).forEach(function (st) {
|
|
270
|
+
typenVomPlatz(st).forEach(function (t) {
|
|
271
|
+
if (raus.indexOf(t) === -1) { raus.push(t); }
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
return raus;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/* Welche angehakten Zeilen treffen ihren Platz in der Rolle, aber nicht
|
|
278
|
+
im Datentyp?
|
|
279
|
+
|
|
280
|
+
Ein solcher Punkt faellt lautlos aus dem Muster - und wenn es ein
|
|
281
|
+
Pflichtplatz war, greift das Muster gar nicht mehr. Dann hat auf
|
|
282
|
+
einmal KEINE Zeile einen Platz, und die Oberflaeche beschuldigte alle:
|
|
283
|
+
am Bastelzimmer_Licht standen nach einem Typwechsel an SET alle acht
|
|
284
|
+
Zeilen getoent da, das Musterfeld sagte „✕ SET fehlt", und die
|
|
285
|
+
Wahrheit stand nur in der aufgeklappten SET-Zeile (Ricardo,
|
|
286
|
+
12.09.2026).
|
|
287
|
+
|
|
288
|
+
Hier steht die Frage einmal, damit Musterfeld, Legende und Zeile
|
|
289
|
+
dieselbe Antwort geben. `pflicht` sagt, ob der betroffene Platz ein
|
|
290
|
+
Pflichtplatz ist - nur dann kippt das ganze Muster. */
|
|
291
|
+
export function typKonflikte(states, musterName) {
|
|
292
|
+
var mu = musterName && musterVon(musterName);
|
|
293
|
+
if (!mu) { return []; }
|
|
294
|
+
var raus = [];
|
|
295
|
+
(states || []).forEach(function (s) {
|
|
296
|
+
if (!s.on || !s.role || !s.typ) { return; }
|
|
297
|
+
var moegliche = typenFuerRolle(musterName, s.role);
|
|
298
|
+
if (!moegliche.length || moegliche.indexOf(s.typ) > -1) { return; }
|
|
299
|
+
var platz = platzFuerRolle(musterName, s.role);
|
|
300
|
+
if (!platz) { return; }
|
|
301
|
+
raus.push({ n: s.n, typ: s.typ, erwartet: moegliche, platz: platz.name,
|
|
302
|
+
pflicht: !!platz.required });
|
|
303
|
+
});
|
|
304
|
+
return raus;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/* Die Datentypen, die ein Platz zulaesst - als Liste.
|
|
308
|
+
|
|
309
|
+
Drei Faelle, gemessen am type-detector 6.0.1: 622 Plaetze nennen
|
|
310
|
+
genau einen Typ, 28 nennen mehrere (mediaPlayer/STATE etwa
|
|
311
|
+
["boolean","number"]), 82 nennen gar keinen - WORKING und ERROR
|
|
312
|
+
zum Beispiel. Wer `String(platz.type)` nimmt, macht aus den 28 den
|
|
313
|
+
Typ "boolean,number", und den gibt es nicht. */
|
|
314
|
+
export function typenVomPlatz(platz) {
|
|
315
|
+
if (!platz || !platz.type) { return []; }
|
|
316
|
+
return Array.isArray(platz.type) ? platz.type.slice() : [String(platz.type)];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/* Der Typ, den ein Platz *vorgibt* - nur wenn er eindeutig ist. Wo ein
|
|
320
|
+
Platz mehrere zulaesst, gibt es nichts vorzugeben: dann ist jede der
|
|
321
|
+
erlaubten Formen richtig, und die Wahl bleibt beim Nutzer. */
|
|
322
|
+
export function typVomPlatz(platz) {
|
|
323
|
+
var t = typenVomPlatz(platz);
|
|
324
|
+
return t.length === 1 ? t[0] : '';
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/* Passt ein eingestellter Typ zu dem, was der Platz zulaesst? Ohne
|
|
328
|
+
Vorgabe passt jeder; ohne eingestellten Typ wird nicht geurteilt. */
|
|
329
|
+
export function typPasstZuPlatz(platz, typ) {
|
|
330
|
+
var t = typenVomPlatz(platz);
|
|
331
|
+
if (!t.length || !typ) { return true; }
|
|
332
|
+
return t.indexOf(String(typ)) > -1;
|
|
333
|
+
}
|
|
334
|
+
|
|
204
335
|
/* Welche Rolle faende im gewaehlten Muster einen Platz? */
|
|
205
336
|
export function plaetzeFuerRollen(musterName) {
|
|
206
337
|
var raus = {};
|
package/admin/js/musterwahl.js
CHANGED
|
@@ -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, typKonflikte } 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,35 @@ 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
|
-
|
|
142
|
-
|
|
141
|
+
/* Ein Pflichtplatz kann auch deshalb leer sein, weil die Zeile
|
|
142
|
+
dafuer im falschen Datentyp steht - die Rolle stimmt, der Typ
|
|
143
|
+
nicht, und der Punkt faellt aus dem Muster. „SET fehlt" ist dann
|
|
144
|
+
die falsche Auskunft: SET ist da. Der Typ-Grund geht vor, wo es
|
|
145
|
+
einen gibt (Ricardo, 12.09.2026, am Bastelzimmer_Licht). */
|
|
146
|
+
var konflikt = typKonflikte(pruefE.states, m)
|
|
147
|
+
.filter(function (x) { return fehlend.indexOf(x.platz) > -1; })[0];
|
|
148
|
+
if (konflikt) {
|
|
149
|
+
mark = tr('pattern.fitsNotType', konflikt.platz, konflikt.typ,
|
|
150
|
+
konflikt.erwartet.join(tr('pattern.typeOr')));
|
|
151
|
+
} else if (fehlend.length) {
|
|
152
|
+
mark = '✕ ' + tr('pattern.missing', fehlend.join(', '));
|
|
153
|
+
} else {
|
|
154
|
+
/* Kein Pflichtplatz fehlt und trotzdem passt nichts - dann liegt
|
|
155
|
+
es an einer Zeile, die ihren Platz trifft, aber im falschen
|
|
156
|
+
Datentyp steht. Bis 11.09.2026 stand hier nur „passt nicht",
|
|
157
|
+
und genau dieser Fall (electricity hat keinen einzigen
|
|
158
|
+
Pflichtplatz) kostete Ricardo eine Stunde Suche: Rolle
|
|
159
|
+
value.power.consumption richtig, Typ mixed statt number, der
|
|
160
|
+
Punkt fiel lautlos aus dem Muster. */
|
|
161
|
+
mark = tr('pattern.doesNotFit');
|
|
162
|
+
(pruefE.states || []).some(function (st) {
|
|
163
|
+
var moegliche = typenFuerRolle(m, st.role);
|
|
164
|
+
if (!st.typ || !moegliche.length || moegliche.indexOf(st.typ) > -1) { return false; }
|
|
165
|
+
var pl = platzFuerRolle(m, st.role);
|
|
166
|
+
mark = tr('pattern.fitsNotType', pl.name, st.typ, moegliche.join(tr('pattern.typeOr')));
|
|
167
|
+
return true;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
143
170
|
} else {
|
|
144
171
|
var g = r[0].states.filter(function (x) { return x.id; }).length;
|
|
145
172
|
mark = tr('pattern.slotsTaken', g, r[0].states.length);
|
|
@@ -281,9 +308,16 @@ export function baueMusterwahl(e, haupt, pflichtFehlt) {
|
|
|
281
308
|
Auswahlfeld. */
|
|
282
309
|
var mBeschriften = function () {
|
|
283
310
|
/* Im Feld der Beiname, der rohe Name im Tooltip - fuer beides
|
|
284
|
-
nebeneinander ist das Feld zu schmal.
|
|
285
|
-
|
|
286
|
-
|
|
311
|
+
nebeneinander ist das Feld zu schmal.
|
|
312
|
+
|
|
313
|
+
Die Marke nennt seit 11.09.2026 auch den Grund, wenn ein Muster
|
|
314
|
+
an einem falschen Datentyp scheitert („✕ CONSUMPTION: Typ mixed
|
|
315
|
+
statt number"). Das ist laenger als „passt nicht" und wird im
|
|
316
|
+
schmalen Feld abgeschnitten - deshalb steht sie zusaetzlich im
|
|
317
|
+
Tooltip, wo sie ganz lesbar ist. */
|
|
318
|
+
var marke = e.want ? markeFuer(e.want) : '';
|
|
319
|
+
sel.value = e.want ? ((musterName(e.want) || e.want) + ' ' + marke) : '';
|
|
320
|
+
sel.title = e.want ? (e.want + (marke ? ' ' + marke : '')) : '';
|
|
287
321
|
};
|
|
288
322
|
mBeschriften();
|
|
289
323
|
|