iobroker.alias-workbench 0.9.11 → 0.9.12
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 +52 -4
- package/admin/css/werkbank.css +42 -6
- package/admin/js/detail.js +10 -4
- package/admin/js/entwurf.js +404 -188
- package/admin/js/enums.js +2 -2
- package/admin/js/ergebnis.js +122 -22
- package/admin/js/erkennung.js +7 -0
- package/admin/js/mqtt.js +52 -3
- package/admin/js/objekte.js +13 -0
- package/admin/js/pruefungen.js +9 -6
- package/admin/js/schreiben.js +54 -25
- package/admin/js/werte.js +1 -1
- package/admin/js/zielleiste.js +8 -2
- package/admin/js/zuordnung.js +40 -12
- package/admin/js/zustandsliste.js +34 -17
- package/admin/sprachen/de.json +13 -10
- package/admin/sprachen/en.json +13 -10
- package/admin/tab.html +44 -44
- package/admin/vorlagen/messpunkt.json +1 -0
- package/admin/vorlagen/tasmota-lampe.json +1 -0
- package/admin/vorlagen/tasmota-mehrfach.json +1 -0
- package/admin/vorlagen/tasmota-steckdose.json +1 -0
- package/io-package.json +25 -16
- package/package.json +1 -1
package/admin/js/enums.js
CHANGED
|
@@ -40,8 +40,8 @@ export function ladeEnums(danach) {
|
|
|
40
40
|
/* Den alten Stand behalten. Er ist vielleicht veraltet, aber
|
|
41
41
|
veraltet ist naeher an der Wahrheit als leer. */
|
|
42
42
|
unbekannt = true;
|
|
43
|
-
console.warn('[alias-workbench]
|
|
44
|
-
(err || '
|
|
43
|
+
console.warn('[alias-workbench] Enumerations not loaded: ' +
|
|
44
|
+
(err || 'no answer'));
|
|
45
45
|
if (versuch < 3) {
|
|
46
46
|
versuch++;
|
|
47
47
|
wiederTimer = setTimeout(function () {
|
package/admin/js/ergebnis.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { S } from './zustand.js';
|
|
2
2
|
import './start.js';
|
|
3
3
|
import { socket } from './verbindung.js';
|
|
4
|
-
import { D, $, el
|
|
4
|
+
import { D, $, el } from './basis.js';
|
|
5
5
|
import { tr, sprachtext } from './sprache.js';
|
|
6
6
|
import './einstellungen.js';
|
|
7
7
|
import './enums.js';
|
|
@@ -27,13 +27,17 @@ import {
|
|
|
27
27
|
mitNachfrage,
|
|
28
28
|
geraeteDarunter,
|
|
29
29
|
aliasFuer,
|
|
30
|
+
ausgangsQuellen,
|
|
30
31
|
quellenVerteilung,
|
|
31
32
|
quelleHier,
|
|
32
33
|
tipptGerade,
|
|
33
34
|
opt,
|
|
34
35
|
vorlagenAbweichung,
|
|
35
36
|
vorlageAnwenden,
|
|
36
|
-
bestandVorrang
|
|
37
|
+
bestandVorrang,
|
|
38
|
+
kanalGruppen,
|
|
39
|
+
aufteilBehaelter,
|
|
40
|
+
rohEntwurf
|
|
37
41
|
} from './entwurf.js';
|
|
38
42
|
import { setzeEnums, setzeZiel, unterschiede } from './zuordnung.js';
|
|
39
43
|
import './detail.js';
|
|
@@ -512,15 +516,21 @@ var warumAuf = false;
|
|
|
512
516
|
sg.style.borderColor = 'var(--line-strong)';
|
|
513
517
|
sg.style.background = 'var(--surface-2)';
|
|
514
518
|
}
|
|
515
|
-
var hd = el('div', 'hd'
|
|
519
|
+
var hd = el('div', 'hd');
|
|
520
|
+
/* Der Name steht in einer eigenen Spanne, damit er sich kuerzen
|
|
521
|
+
laesst. Die Kopfzeile bricht nicht mehr um: vorher nahm sich der
|
|
522
|
+
Hinweis rechts eine eigene Zeile, sobald Marken dazukamen und der
|
|
523
|
+
Name lang wurde („Homematic Rollladenaktor" + von Hand gewaehlt +
|
|
524
|
+
erzwungen). Jetzt weicht stattdessen der Name zurueck — vollstaendig
|
|
525
|
+
steht er im Tooltip und im Auswahlfeld darunter (Ricardo, 17.09.2026). */
|
|
526
|
+
var hdText = e.vorschlag
|
|
516
527
|
? tr('tpl.identifiedAs', e.tplName)
|
|
517
|
-
: tr('tpl.noneDetected')
|
|
528
|
+
: tr('tpl.noneDetected');
|
|
529
|
+
var hdName = el('span', 'tname', hdText);
|
|
530
|
+
hdName.title = hdText;
|
|
531
|
+
hd.appendChild(hdName);
|
|
518
532
|
if (e.vorlageVersion) {
|
|
519
|
-
var vv2 = el('span',
|
|
520
|
-
vv2.style.fontFamily = 'var(--mono)';
|
|
521
|
-
vv2.style.fontSize = '10.5px';
|
|
522
|
-
vv2.style.fontWeight = '400';
|
|
523
|
-
vv2.style.color = 'var(--ink-3)';
|
|
533
|
+
var vv2 = el('span', 'tid', ' · ' + e.vorlage + ' v' + e.vorlageVersion);
|
|
524
534
|
hd.appendChild(vv2);
|
|
525
535
|
}
|
|
526
536
|
if (e.vonHandGewaehlt) {
|
|
@@ -571,13 +581,22 @@ var warumAuf = false;
|
|
|
571
581
|
Breite, die eine Liste braucht. */
|
|
572
582
|
var warumKopf = null, warumLeib = null;
|
|
573
583
|
if (gruende.length || weggelassen.length) {
|
|
574
|
-
warumKopf = el('div', 'wkopf');
|
|
575
584
|
/* Ohne Vorlage waere „Warum diese Vorlage" die falsche Frage —
|
|
576
585
|
dann steht hier, warum keine greift. */
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
586
|
+
var warumText = tr(e.vorschlag ? 'tpl.whyThis' : 'tpl.whyNone');
|
|
587
|
+
warumKopf = el('div', 'wkopf' + (warumAuf ? ' auf' : ''));
|
|
588
|
+
/* Statt „Warum diese Vorlage +" nur ein Fragezeichen: der Satz
|
|
589
|
+
steht im Tooltip und spart die halbe Kopfzeile. Was weggelassen
|
|
590
|
+
wurde, bleibt als kurze Marke stehen — dass Punkte fehlen, soll
|
|
591
|
+
niemand erst suchen muessen (Ricardo, 17.09.2026). */
|
|
592
|
+
if (weggelassen.length) {
|
|
593
|
+
warumKopf.appendChild(el('span', 'chip mut',
|
|
594
|
+
tr('tpl.skippedChip', weggelassen.length)));
|
|
595
|
+
warumText = tr('tpl.skippedHead', weggelassen.length) + ' — ' + warumText;
|
|
596
|
+
}
|
|
597
|
+
warumKopf.appendChild(el('span', 'fragez', '?'));
|
|
598
|
+
warumKopf.title = warumText;
|
|
599
|
+
warumKopf.setAttribute('aria-label', warumText);
|
|
581
600
|
warumKopf.tabIndex = 0;
|
|
582
601
|
var um2 = function () { warumAuf = !warumAuf; zeichneErgebnis(); };
|
|
583
602
|
warumKopf.addEventListener('click', um2);
|
|
@@ -634,6 +653,25 @@ var warumAuf = false;
|
|
|
634
653
|
v2.zielOrdner = e.zielOrdner;
|
|
635
654
|
v2.zielName = ausgangName(v2, selA.value);
|
|
636
655
|
v2.ziel = v2.zielOrdner + '.' + v2.zielName;
|
|
656
|
+
/* Dieser Weg fragte bisher gar nicht nach dem Bestand -
|
|
657
|
+
deshalb sah derselbe Ausgang je nach Weg anders aus:
|
|
658
|
+
ueber den Baum kamen die Haken eines fremden Alias, hier
|
|
659
|
+
die Vorgaben der Vorlage. Jetzt stellen alle drei Wege
|
|
660
|
+
dieselbe Frage (C13, 16.09.2026).
|
|
661
|
+
|
|
662
|
+
Und die Zielzeile folgt derselben Antwort. Sie wird hier von
|
|
663
|
+
Hand zusammengesetzt und laeuft nicht durch `setzeZiel`;
|
|
664
|
+
ohne diese Zeilen zeigte sie beim Umschalten weiter auf
|
|
665
|
+
`…POWER2` und meldete „wird neu angelegt", waehrend
|
|
666
|
+
`SUNLU` daneben stand. */
|
|
667
|
+
var vorhA2 = aliasFuer(S.current, ausgangsQuellen(v2));
|
|
668
|
+
if (vorhA2) {
|
|
669
|
+
var t2 = vorhA2.split('.');
|
|
670
|
+
v2.zielName = t2.pop();
|
|
671
|
+
v2.zielOrdner = t2.join('.');
|
|
672
|
+
v2.ziel = vorhA2;
|
|
673
|
+
}
|
|
674
|
+
if (vorhA2 && S.objects[vorhA2]) { bestandVorrang(v2, vorhA2); }
|
|
637
675
|
S.entwurf = v2; S.openRow = null; zeichneErgebnis();
|
|
638
676
|
}
|
|
639
677
|
});
|
|
@@ -650,7 +688,10 @@ var warumAuf = false;
|
|
|
650
688
|
das Ausgangsfeld daneben blieb ungestylt in der Browserschrift. */
|
|
651
689
|
var selV = el('select', 'tx');
|
|
652
690
|
|
|
653
|
-
|
|
691
|
+
/* Greift eine Vorlage, ist der erste Eintrag kein Titel, sondern
|
|
692
|
+
eine Wahl: sie wieder loswerden. „— Vorlage wechseln —" stand
|
|
693
|
+
wie eine Handlung da, tat aber nichts (Ricardo, 17.09.2026). */
|
|
694
|
+
selV.appendChild(opt('', e.vorschlag ? tr('tpl.none') : tr('tpl.choose')));
|
|
654
695
|
S.VORLAGEN.forEach(function (v) {
|
|
655
696
|
var t = pruefeVorlage(v, S.current);
|
|
656
697
|
/* Auch nicht passende bleiben waehlbar — mit Grund daneben. Sonst
|
|
@@ -663,7 +704,35 @@ var warumAuf = false;
|
|
|
663
704
|
selV.appendChild(o);
|
|
664
705
|
});
|
|
665
706
|
selV.addEventListener('change', function () {
|
|
666
|
-
if (!selV.value) {
|
|
707
|
+
if (!selV.value) {
|
|
708
|
+
/* „keine Vorlage": den Rohentwurf nehmen. Ziel, Raum und
|
|
709
|
+
Funktion bleiben — die hat der Mensch eingestellt, nicht die
|
|
710
|
+
Vorlage. `angefasst` verhindert, dass der naechste
|
|
711
|
+
eintreffende Messwert die Vorlage wieder heranzieht. */
|
|
712
|
+
if (!e.vorschlag) { return; }
|
|
713
|
+
var r = rohEntwurf(S.current);
|
|
714
|
+
if (!r) { selV.value = e.vorlage || ''; return; }
|
|
715
|
+
r.ziel = e.ziel; r.zielOrdner = e.zielOrdner; r.zielName = e.zielName;
|
|
716
|
+
r.raum = e.raum; r.funktion = e.funktion;
|
|
717
|
+
r.raumHer = e.raumHer; r.funktionHer = e.funktionHer;
|
|
718
|
+
/* Der Ausgang wird NICHT uebernommen. Er ist keine Eigenschaft
|
|
719
|
+
des Geraets, sondern des `mehrfach`-Blocks der Vorlage:
|
|
720
|
+
`instanzenVon` gibt ohne ihn `[null]` zurueck. Wurde die
|
|
721
|
+
Vorlage abgewaehlt, gibt es keinen Platzhalter mehr und damit
|
|
722
|
+
nichts zu waehlen. Bis 17.09.2026 erbte der Rohentwurf die
|
|
723
|
+
Ausgaenge der alten Vorlage: der Kasten blieb stehen, und wer
|
|
724
|
+
ihn benutzte, holte die abgewaehlte Vorlage kommentarlos
|
|
725
|
+
zurueck — der Ausgang-Zweig ruft `vorschlag` mit leerem
|
|
726
|
+
`e.vorlage` und laesst neu erkennen (gemessen an
|
|
727
|
+
`hm.ZWEIKANAL`: nach dem Umschalten auf `Licht_Esstisch`
|
|
728
|
+
stand `hm-schaltaktor-mehrfach` wieder im Feld). Die beiden
|
|
729
|
+
Kanaele laufen ohne Vorlage ueber „Unterordner je Kanal". */
|
|
730
|
+
S.entwurf = r;
|
|
731
|
+
S.openRow = null;
|
|
732
|
+
entwurfAngefasst();
|
|
733
|
+
zeichneErgebnis();
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
667
736
|
var v = vorschlag(S.current, selV.value);
|
|
668
737
|
if (v) {
|
|
669
738
|
v.ziel = e.ziel;
|
|
@@ -751,7 +820,11 @@ var warumAuf = false;
|
|
|
751
820
|
neuE.zielName = e.zielName;
|
|
752
821
|
neuE.ordnerVonHand = e.ordnerVonHand;
|
|
753
822
|
if (fest) { neuE.vonHandGewaehlt = false; neuE.ausBestand = true; }
|
|
754
|
-
|
|
823
|
+
/* Wie beim ersten Aufbau: am Mehrfachgeraet zaehlt der Alias
|
|
824
|
+
DIESES Ausgangs (C13). */
|
|
825
|
+
var vorhW = aliasFuer(S.current, ausgangsQuellen(neuE)) ||
|
|
826
|
+
((neuE.instanz === null || neuE.instanz === undefined) ? vorh : null);
|
|
827
|
+
if (vorhW && S.objects[vorhW]) { bestandVorrang(neuE, vorhW); }
|
|
755
828
|
S.entwurf = neuE; S.openRow = null; zeichneErgebnis();
|
|
756
829
|
});
|
|
757
830
|
/* An der Quelle bleibt die Musterwahl im Vorlagenkasten, wo sie
|
|
@@ -844,7 +917,22 @@ var warumAuf = false;
|
|
|
844
917
|
var bd = $('#btn-dry');
|
|
845
918
|
var ba = $('#btn-dry-alle');
|
|
846
919
|
var mehr = e.instanzen && e.instanzen.length > 1;
|
|
847
|
-
|
|
920
|
+
/* Welche Unterordner entstuenden — nach den Haken, dieselbe Rechnung
|
|
921
|
+
wie der Schreibweg (C51). */
|
|
922
|
+
var grp = mehr ? [] : kanalGruppen(e).filter(function (g) { return !g.eigen; });
|
|
923
|
+
/* Zwei Kanaele mit Haken genuegen — auch wenn einer davon der
|
|
924
|
+
Wartungskanal ist.
|
|
925
|
+
|
|
926
|
+
Zwischenzeitlich zaehlte `.0` hier nicht mit, damit der Knopf nicht
|
|
927
|
+
an jedem Fuehler steht. Das ergab aber eine Unstimmigkeit, die beim
|
|
928
|
+
Benutzen auffaellt: fuer den INHALT zaehlte der Kanal (er bekommt
|
|
929
|
+
seinen Ordner), fuer den ANLASS nicht — man hakt etwas an und
|
|
930
|
+
nichts passiert. Ricardo am 17.09.2026: „zählt ist ja eher ne
|
|
931
|
+
Expertenfunktion, da weiss man schon was man macht." Also eine
|
|
932
|
+
Regel statt zweier. */
|
|
933
|
+
var typVonK = {};
|
|
934
|
+
(e.kanalGeraete || []).forEach(function (k) { typVonK[k.id] = k.typ; });
|
|
935
|
+
var mehrK = !mehr && grp.length > 1;
|
|
848
936
|
/* Die Knoepfe gehoeren zum Modus, nicht nur zum Objekt: Im Modus
|
|
849
937
|
„Alias anlegen" wird angelegt, nicht verwaltet — Verlegen, Quelle
|
|
850
938
|
tauschen und Entfernen haben dort nichts zu suchen. Im Modus
|
|
@@ -891,13 +979,25 @@ var warumAuf = false;
|
|
|
891
979
|
return (e.zielOrdner || '') + '.' + nm;
|
|
892
980
|
}).join(String.fromCharCode(10));
|
|
893
981
|
} else if (mehrK) {
|
|
894
|
-
ba.textContent = tr('write.createPerChannel',
|
|
982
|
+
ba.textContent = tr('write.createPerChannel', grp.length);
|
|
895
983
|
/* Im Hinweis stehen die Namen, die entstehen wuerden — sonst
|
|
896
984
|
klickt man auf eine Zahl und weiss nicht, was danach dasteht. */
|
|
897
|
-
|
|
985
|
+
/* Dieselbe Rechnung wie der Schreibweg (schreiben.js, `ordner`):
|
|
986
|
+
ein Behaelter fuer das Geraet, darunter je Kanal einer. Hier
|
|
987
|
+
stand nur `zielOrdner` — also eine Ebene zu wenig. Am
|
|
988
|
+
Geschirrspueler versprach der Hinweis `alias.0.Befehle`,
|
|
989
|
+
entstanden waere `alias.0.Geschirrspueler.Befehle`; am
|
|
990
|
+
Wohnzimmer_Dimmer las man `alias.0.1`, `alias.0.2`, `alias.0.3`
|
|
991
|
+
— drei Aliase, nach blanken Kanalnummern benannt, direkt unter
|
|
992
|
+
alias.0. Gefunden im Lauf vom 16.09.2026 (C15). */
|
|
993
|
+
var ordnerK = aufteilBehaelter(e);
|
|
994
|
+
ba.title = grp.map(function (g) {
|
|
898
995
|
/* Die Kennung, nicht den Anzeigenamen - so heisst das Objekt
|
|
899
|
-
hinterher wirklich (G31).
|
|
900
|
-
|
|
996
|
+
hinterher wirklich (G31). Dahinter, was hineinkommt: die
|
|
997
|
+
Zahl der angehakten Zeilen — daran sieht man vor dem Klick,
|
|
998
|
+
dass nichts Erfundenes dabei ist. */
|
|
999
|
+
return ordnerK + '.' + (g.kennung || g.name)
|
|
1000
|
+
+ ' (' + g.zeilen.length + (typVonK[g.id] ? ', ' + typVonK[g.id] : '') + ')';
|
|
901
1001
|
}).join(String.fromCharCode(10));
|
|
902
1002
|
}
|
|
903
1003
|
ba.disabled = false;
|
package/admin/js/erkennung.js
CHANGED
|
@@ -226,6 +226,13 @@ export function musterVon(typ) {
|
|
|
226
226
|
statt als `electricity` nur noch als `info` erkannt. Am Bildschirm
|
|
227
227
|
stand dazu nichts weiter als „passt nicht".
|
|
228
228
|
|
|
229
|
+
Zur Rolle selbst: `value.power.consumption` ist in der Rollenliste von
|
|
230
|
+
ioBroker durchgestrichen, der type-detector 6.0.x erkennt CONSUMPTION
|
|
231
|
+
aber NUR mit genau dieser Rolle (typePatterns.js, Muster `consumption`).
|
|
232
|
+
Die mitgelieferten Vorlagen behalten sie deshalb bewusst; jede traegt
|
|
233
|
+
den Grund im Feld `_rolle`. Role note for reviewers: the deprecated role
|
|
234
|
+
is kept on purpose because the type-detector requires it.
|
|
235
|
+
|
|
229
236
|
Dieselbe Suche stand vorher zweimal im Code (detail.js und
|
|
230
237
|
vorlagenblatt.js), beide Male ohne den Typ anzusehen. */
|
|
231
238
|
export function plaetzeFuerRolle(musterName, rolle) {
|
package/admin/js/mqtt.js
CHANGED
|
@@ -149,6 +149,38 @@ export function befehlsWissen(name) {
|
|
|
149
149
|
return null;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
/* Welche Zeilen haengen ueberhaupt am Telemetrietakt?
|
|
153
|
+
|
|
154
|
+
Betroffen ist nur die eine Bauform: aus `tele/...` lesen und nach
|
|
155
|
+
`cmnd/...` schreiben. Wer aus `stat/POWER1` liest, bekommt die Antwort
|
|
156
|
+
bei jedem Befehl sofort — SetOption59 aendert daran nichts.
|
|
157
|
+
|
|
158
|
+
Ricardos Steckdosenleiste hat keine einzige solche Zeile: seine Aliase
|
|
159
|
+
lesen alle aus `stat.POWERn`. Trotzdem stand der SetOption59-Block an
|
|
160
|
+
der Karte und die Pruefung meldete "alle in Ordnung", als waere etwas
|
|
161
|
+
geprueft worden. Beides ist jetzt an diese Frage gebunden
|
|
162
|
+
(Ricardo, 16.09.2026). */
|
|
163
|
+
export function telegesteuert(e) {
|
|
164
|
+
if (!e || !e.states) { return []; }
|
|
165
|
+
return e.states.filter(function (x) {
|
|
166
|
+
if (!x.on || !x.srcW || !x.srcR) { return false; }
|
|
167
|
+
return /\.tele\./.test(x.srcR) && /\.cmnd\./.test(x.srcW);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* Wie oft meldet das Geraet von sich aus? Steht in tele/STATE.
|
|
172
|
+
|
|
173
|
+
Ohne diese Zahl stand im Hinweis "minutenlang" — das unterstellt die
|
|
174
|
+
Tasmota-Vorgabe von 300 Sekunden. An Ricardos Leiste sind es zehn
|
|
175
|
+
(gemessen 16.09.2026: tele/STATE im Zehnsekundentakt). Wer eine Zahl
|
|
176
|
+
nennt, soll die richtige nennen. */
|
|
177
|
+
export function telePeriode(kanal) {
|
|
178
|
+
var id = hatPunkt(kanal, 'tele.STATE');
|
|
179
|
+
var j = id ? jsonVon(id) : null;
|
|
180
|
+
var n = j && Number(j.TelePeriod);
|
|
181
|
+
return (n && isFinite(n)) ? n : null;
|
|
182
|
+
}
|
|
183
|
+
|
|
152
184
|
/* Meldet das Geraet Aenderungen sofort? Das haengt an SetOption59.
|
|
153
185
|
|
|
154
186
|
Die Bitmaske aus StatusLOG zu entziffern waere moeglich, ist aber
|
|
@@ -281,7 +313,12 @@ export function mqttKarte(host, kanal) {
|
|
|
281
313
|
ch.appendChild(th);
|
|
282
314
|
if (l.fehlen.length) { ch.appendChild(el('span', 'chip warn', tr('mq.missing', l.fehlen.length))); }
|
|
283
315
|
if (l.stumm.length) { ch.appendChild(el('span', 'chip bad', tr('mq.mute', l.stumm.length))); }
|
|
284
|
-
|
|
316
|
+
/* Nur warnen, wo es jemanden trifft: Ohne eine Zeile, die aus tele
|
|
317
|
+
liest und nach cmnd schreibt, ist SetOption59 folgenlos. */
|
|
318
|
+
var telZ = telegesteuert(S.entwurf);
|
|
319
|
+
if (l.sofort === false && telZ.length) {
|
|
320
|
+
ch.appendChild(el('span', 'chip warn', tr('mq.instantOffShort')));
|
|
321
|
+
}
|
|
285
322
|
ch.insertBefore(klappZeichen(mqttAuf), ch.firstChild);
|
|
286
323
|
ch.classList.add('klappbar');
|
|
287
324
|
ch.addEventListener('click', function () { mqttAuf = !mqttAuf; zeichneErgebnis(); });
|
|
@@ -379,7 +416,13 @@ export function mqttKarte(host, kanal) {
|
|
|
379
416
|
}
|
|
380
417
|
b.appendChild(leiste);
|
|
381
418
|
|
|
382
|
-
/* Sofortige Rueckmeldung — Zustand und, wenn noetig, der Schalter.
|
|
419
|
+
/* Sofortige Rueckmeldung — Zustand und, wenn noetig, der Schalter.
|
|
420
|
+
|
|
421
|
+
Nur, wenn ueberhaupt eine Zeile am Telemetrietakt haengt. An einem
|
|
422
|
+
Geraet, dessen Aliase alle aus `stat/...` lesen, ist SetOption59
|
|
423
|
+
folgenlos, und ein Block darueber ist bloss Betrieb. */
|
|
424
|
+
if (!telZ.length) { host.appendChild(k); return; }
|
|
425
|
+
|
|
383
426
|
var sk = el('div');
|
|
384
427
|
sk.style.marginTop = '11px';
|
|
385
428
|
sk.style.paddingTop = '10px';
|
|
@@ -423,8 +466,14 @@ export function mqttKarte(host, kanal) {
|
|
|
423
466
|
if (lauf) { bp.disabled = true; be.disabled = true; }
|
|
424
467
|
}
|
|
425
468
|
sk.appendChild(sl);
|
|
469
|
+
/* Der Hinweis nennt die betroffenen Zeilen und den wirklichen Takt,
|
|
470
|
+
statt pauschal "minutenlang" zu behaupten. */
|
|
471
|
+
var telNamen = telZ.map(function (x) { return x.n; }).join(', ');
|
|
472
|
+
var takt = telePeriode(kanal);
|
|
426
473
|
var hinweis = l.sofort === true ? tr('mq.instantHintOn')
|
|
427
|
-
: (l.sofort === false
|
|
474
|
+
: (l.sofort === false
|
|
475
|
+
? (takt ? tr('mq.instantHintOffTakt', telNamen, takt) : tr('mq.instantHintOff', telNamen))
|
|
476
|
+
: tr('mq.instantHintUnknown'));
|
|
428
477
|
/* Woher der Befund stammt, gehoert dazu — sonst weiss niemand, ob er
|
|
429
478
|
von eben ist oder von vorgestern. */
|
|
430
479
|
var alter = (l.sofort === null) ? '' : so59Alter(kanal);
|
package/admin/js/objekte.js
CHANGED
|
@@ -151,6 +151,19 @@ export function horcheAufObjekte() {
|
|
|
151
151
|
return;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/* Nur die vier Arten, aus denen der Baum besteht.
|
|
155
|
+
|
|
156
|
+
Beim Laden holt `ladeObjekte` gezielt `ARTEN`, beim Nachziehen
|
|
157
|
+
wurde dagegen alles aufgenommen: eine geaenderte Instanz, ein
|
|
158
|
+
Adapter-Update, `system.config` nach dem Umstellen der Sprache.
|
|
159
|
+
Der Zaehler in der Kopfzeile ging dadurch von 3145 auf 3146, und
|
|
160
|
+
mit jeder Stunde offenem Reiter wurden es mehr (A4, 17.09.2026).
|
|
161
|
+
Wechselt ein Objekt seine Art, faellt es hier ebenfalls heraus. */
|
|
162
|
+
if (obj && ARTEN.indexOf(obj.type) === -1) {
|
|
163
|
+
if (S.objects[id] === undefined) { return; }
|
|
164
|
+
obj = null;
|
|
165
|
+
}
|
|
166
|
+
|
|
154
167
|
/* Alles Uebrige: nur was zaehlt, nicht jeder Schreibvorgang. */
|
|
155
168
|
var vorher = kern(S.objects[id]);
|
|
156
169
|
if (vorher === nachher) { return; }
|
package/admin/js/pruefungen.js
CHANGED
|
@@ -5,7 +5,7 @@ import { $, el } from './basis.js';
|
|
|
5
5
|
import { tr } from './sprache.js';
|
|
6
6
|
import { wertVon, zielKann } from './werte.js';
|
|
7
7
|
import './erkennung.js';
|
|
8
|
-
import { sofortRueckmeldung, mqttEinstellung } from './mqtt.js';
|
|
8
|
+
import { sofortRueckmeldung, mqttEinstellung, telegesteuert } from './mqtt.js';
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
/* Kommt die Rueckmeldung sofort oder erst mit der naechsten Telemetrie?
|
|
@@ -21,11 +21,14 @@ import { sofortRueckmeldung, mqttEinstellung } from './mqtt.js';
|
|
|
21
21
|
da, tele/STATE kam erst nach der naechsten Telemetrie — bei
|
|
22
22
|
TelePeriod 300 also bis zu fuenf Minuten spaeter. */
|
|
23
23
|
export function pruefungRueckmeldung(e) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
/* Dieselbe Frage wie die MQTT-Karte, damit beide nicht auseinander
|
|
25
|
+
laufen (Ricardo, 16.09.2026). */
|
|
26
|
+
var lahm = telegesteuert(e);
|
|
27
|
+
/* Kein Haken, sondern ein Punkt: Hier wurde nichts geprueft, weil es
|
|
28
|
+
nichts zu pruefen gab. „alle in Ordnung" las sich, als haette die
|
|
29
|
+
Werkbank etwas nachgesehen - an Ricardos Steckdosenleiste lesen alle
|
|
30
|
+
Zeilen aus stat/..., SetOption59 ist dort folgenlos. */
|
|
31
|
+
if (!lahm.length) { return { s: 'mut', t: tr('check.feedback'), d: tr('check.feedbackNone') }; }
|
|
29
32
|
/* Nur warnen, wenn es wirklich langsam ist. Mit SetOption59 meldet
|
|
30
33
|
das Geraet jede Aenderung sofort — dann ist die Bauform zwar
|
|
31
34
|
dieselbe, aber kein Problem. Gemessen: drei Sekunden. */
|
package/admin/js/schreiben.js
CHANGED
|
@@ -16,9 +16,10 @@ import { ausgangName, vorschlag } from './vorlagen.js';
|
|
|
16
16
|
import {
|
|
17
17
|
waehle,
|
|
18
18
|
ordnerUnterAlias,
|
|
19
|
-
gemeinsameKanaele,
|
|
20
19
|
kennungtauglich,
|
|
21
|
-
|
|
20
|
+
kanalGruppen,
|
|
21
|
+
teilEntwurf,
|
|
22
|
+
aufteilBehaelter,
|
|
22
23
|
aliasFuer,
|
|
23
24
|
knotenDa,
|
|
24
25
|
aboLoesen
|
|
@@ -434,8 +435,8 @@ export function zuSchreiben(alleAusgaenge) {
|
|
|
434
435
|
/* Raum und Funktion gehoeren an jeden Kanal, nicht nur an den
|
|
435
436
|
gezeigten.
|
|
436
437
|
|
|
437
|
-
Die Teil-Entwuerfe entstehen
|
|
438
|
-
|
|
438
|
+
Die Teil-Entwuerfe entstehen aus `teilEntwurf` bzw. `vorschlag` und
|
|
439
|
+
trugen keins von beidem. `enumAenderungen` baute
|
|
439
440
|
deshalb fuer keinen einzigen Kanal ein Enum-Objekt: Wer oben einen
|
|
440
441
|
Raum einstellte und „Alle erzeugen" drueckte, bekam Kanaele ohne
|
|
441
442
|
Raum — der Einzelweg setzte ihn, der Sammelweg nicht.
|
|
@@ -461,25 +462,46 @@ export function zuSchreiben(alleAusgaenge) {
|
|
|
461
462
|
return v;
|
|
462
463
|
};
|
|
463
464
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
465
|
+
/* Greift eine Mehrfachvorlage, gilt IHR Weg — die Ausgaenge stehen im
|
|
466
|
+
`%N%` der Vorlage, nicht in den Kanaelen des Geraets. Ohne diese
|
|
467
|
+
Ausnahme kaperte die Kanal-Aufteilung den Vorlagenweg: „Alle 2
|
|
468
|
+
erzeugen" lieferte am NEQ1660737 `…Licht_Bar_Esstisch.Licht_Bar.
|
|
469
|
+
Licht_Bar.STATE` und dazu den Wartungskanal mitten hinein
|
|
470
|
+
(17.09.2026). Die Beschriftung hatte den Fall ausgenommen, der
|
|
471
|
+
Schreibweg nicht — zwei Stellen, eine Bedingung. */
|
|
472
|
+
var mehrfach = S.entwurf.instanzen && S.entwurf.instanzen.length > 1;
|
|
473
|
+
var gruppen = (alleAusgaenge && !mehrfach) ? kanalGruppen(S.entwurf) : [];
|
|
474
|
+
if (gruppen.filter(function (g) { return !g.eigen; }).length > 1) {
|
|
475
|
+
/* Ein Behaelter fuer das Geraet, darunter je Kanal einer — die
|
|
476
|
+
Struktur der Quelle, abgebildet nach den Haken (C51).
|
|
477
|
+
|
|
478
|
+
Die Teil-Entwuerfe kamen bis 17.09.2026 frisch aus `entwurfFuer`:
|
|
479
|
+
sie hakten an, was das Muster des Kanals hergab, und lasen den
|
|
480
|
+
Entwurf oben gar nicht. Damit entstand, was niemand gewaehlt
|
|
481
|
+
hatte, und was jemand gewaehlt hatte, fiel weg. */
|
|
482
|
+
var ordner = aufteilBehaelter(S.entwurf);
|
|
483
|
+
return gruppen.map(function (g) {
|
|
484
|
+
var v = teilEntwurf(S.entwurf, g);
|
|
485
|
+
if (!v || !v.states.length) { return null; }
|
|
486
|
+
if (g.eigen) {
|
|
487
|
+
/* Punkte, die direkt am Geraet haengen, bleiben im Behaelter —
|
|
488
|
+
sonst verschwaenden sie beim Aufteilen. */
|
|
489
|
+
v.zielOrdner = S.entwurf.zielOrdner;
|
|
490
|
+
v.zielName = S.entwurf.zielName;
|
|
491
|
+
v.ziel = ordner;
|
|
492
|
+
} else {
|
|
493
|
+
v.zielOrdner = ordner;
|
|
494
|
+
/* Die Kennung, nicht der Anzeigename. „Licht Bar, oben" ergab eine
|
|
495
|
+
Kennung mit Leerzeichen und Komma, „Kueche.Decke" sogar eine
|
|
496
|
+
zusaetzliche Ebene samt Zwischenordner. Und der js-controller
|
|
497
|
+
lehnt so etwas nicht ab, er saeubert still: aus
|
|
498
|
+
`alias.0.wb[pruef]` wurde `alias.0.wb_pruef_`, der Rueckruf
|
|
499
|
+
meldete `null`. Das Objekt entstuende also unter einer anderen
|
|
500
|
+
Kennung als angezeigt (gemessen 08.09.2026). Der Name bleibt
|
|
501
|
+
davon unberuehrt — er steht als Beschriftung im Objekt. */
|
|
502
|
+
v.zielName = g.kennung || g.name;
|
|
503
|
+
v.ziel = ordner + '.' + v.zielName;
|
|
504
|
+
}
|
|
483
505
|
uebernehmeBestand(v);
|
|
484
506
|
return enumsUebertragen(v);
|
|
485
507
|
}).filter(Boolean);
|
|
@@ -1307,7 +1329,14 @@ export function zeigeVerlegen(altVorgabe, zielVorgabe) {
|
|
|
1307
1329
|
Zielleiste getippt wurde (`zielVorgabe`). */
|
|
1308
1330
|
var alt = (typeof altVorgabe === 'string' && altVorgabe) ||
|
|
1309
1331
|
(S.entwurf && (S.entwurf.ziel || S.entwurf.kanal)) || S.current;
|
|
1310
|
-
|
|
1332
|
+
/* `knotenDa`, nicht `S.objects[alt]`: ein Alias muss kein eigenes
|
|
1333
|
+
Kanalobjekt haben (E31). Der Knopf stand an so einem Alias schon
|
|
1334
|
+
da - `ergebnis.js` fragt `knotenDa` -, der Dialog stieg hier aber
|
|
1335
|
+
still aus: kein Fenster, keine Meldung. Produktiv betraf das
|
|
1336
|
+
`alias.0.Solar.Einstellungen.Bilanz` und `alias.0.NSPanel.1.Helligkeit`
|
|
1337
|
+
(T25, 18.09.2026). Verlegt wird ohnehin alles unter dem Pfad; ein
|
|
1338
|
+
fehlender Kanal fehlt danach am neuen Ort genauso. */
|
|
1339
|
+
if (!alt || alt.indexOf('alias.') !== 0 || !knotenDa(alt)) { return; }
|
|
1311
1340
|
S.verlegeZiel = alt;
|
|
1312
1341
|
|
|
1313
1342
|
var vorbelegt = (typeof zielVorgabe === 'string' && zielVorgabe &&
|
|
@@ -1739,7 +1768,7 @@ export function verlegeAlias(alt, neu) {
|
|
|
1739
1768
|
markiert hatte. Wer danach nochmal verlegen wollte, fand keinen
|
|
1740
1769
|
Knopf und musste den Alias erst wieder anklicken. `waehle` baut
|
|
1741
1770
|
den Entwurf neu auf, und damit steht auch der Knopf wieder da. */
|
|
1742
|
-
if (zielId &&
|
|
1771
|
+
if (zielId && knotenDa(zielId)) { waehle(zielId); }
|
|
1743
1772
|
else { zeichneErgebnis(); }
|
|
1744
1773
|
});
|
|
1745
1774
|
}
|
package/admin/js/werte.js
CHANGED
|
@@ -285,7 +285,7 @@ export function auswerten(formel, roh) {
|
|
|
285
285
|
var gedauert = performance.now() - t0;
|
|
286
286
|
if (gedauert > GEDULD_MS) {
|
|
287
287
|
formelGesperrt[formel] = Math.round(gedauert);
|
|
288
|
-
console.warn('[alias-workbench]
|
|
288
|
+
console.warn('[alias-workbench] Formula blocked after ' + Math.round(gedauert) + ' ms: ' + formel);
|
|
289
289
|
return { ok: false, txt: tr('detail.formulaTooSlow', Math.round(gedauert)), fehler: true };
|
|
290
290
|
}
|
|
291
291
|
if (sch !== null) {
|
package/admin/js/zielleiste.js
CHANGED
|
@@ -11,7 +11,7 @@ import { el } from './basis.js';
|
|
|
11
11
|
import { tr } from './sprache.js';
|
|
12
12
|
import { enumListe } from './aufzaehlungen.js';
|
|
13
13
|
import { enumZeile, setzeZiel } from './zuordnung.js';
|
|
14
|
-
import { aliasFuer, ordnerUnterAlias, kennungtauglich, knotenDa } from './entwurf.js';
|
|
14
|
+
import { aliasFuer, ausgangsQuellen, ordnerUnterAlias, kennungtauglich, knotenDa } from './entwurf.js';
|
|
15
15
|
import { zeichneErgebnis, entwurfAngefasst, angebotFrisch } from './ergebnis.js';
|
|
16
16
|
import { zeigeVerlegen } from './schreiben.js';
|
|
17
17
|
|
|
@@ -381,7 +381,13 @@ export function baueZielleiste(host, e) {
|
|
|
381
381
|
irrt sie hier, irrt sie dort ebenso. Und der Hinweis haelt
|
|
382
382
|
niemanden auf. */
|
|
383
383
|
var zwilling = null;
|
|
384
|
-
|
|
384
|
+
/* Dieselbe Frage wie die Vorbelegung, also auch dieselbe Antwort:
|
|
385
|
+
am Mehrfachgeraet der Alias DIESES Ausgangs. Sonst nennt der
|
|
386
|
+
Hinweis einen anderen Alias als den, dessen Stand oben in der
|
|
387
|
+
Liste steht - zwei Aussagen auf einem Bildschirm, die sich
|
|
388
|
+
widersprechen (C13). */
|
|
389
|
+
var vorhAlias = aliasFuer(e.kanal, ausgangsQuellen(e)) ||
|
|
390
|
+
((e.instanz === null || e.instanz === undefined) ? aliasFuer(e.kanal) : null);
|
|
385
391
|
if (vorhAlias && S.objects[vorhAlias] && vorhAlias !== e.ziel) {
|
|
386
392
|
var zw = el('div', 'uebernahme zwilling');
|
|
387
393
|
zw.appendChild(el('span', 'zq', tr('target.twinExists', vorhAlias)));
|
package/admin/js/zuordnung.js
CHANGED
|
@@ -16,7 +16,8 @@ import { enumVorlagen, katalogFehlt, ikonCache, ikonErlaubt, ikonNachtrag,
|
|
|
16
16
|
ikonTaugt, vorlageZu, holeIkon } from './katalog.js';
|
|
17
17
|
import { kindZustaende, aliasQuellen, holeEinzelne,
|
|
18
18
|
zeileAusAlias } from './werte.js';
|
|
19
|
-
import { aliasFuer, zielId, knotenDa
|
|
19
|
+
import { aliasFuer, ausgangsQuellen, zielId, knotenDa,
|
|
20
|
+
aboErgaenzen, quellenVonEntwurf } from './entwurf.js';
|
|
20
21
|
import { zeichneErgebnis, entwurfAngefasst, angebotFrisch } from './ergebnis.js';
|
|
21
22
|
|
|
22
23
|
|
|
@@ -475,18 +476,35 @@ export function setzeZiel(e) {
|
|
|
475
476
|
/* Mehrere Ausgaenge: das Geraet wird zum Ordner, jeder Ausgang
|
|
476
477
|
ein Kanal darin. Ein folder darueber, kein device — sonst
|
|
477
478
|
rutscht die Erkennung hoch und macht aus dreien wieder eins. */
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
479
|
+
/* Gibt es den Alias fuer GENAU DIESEN Ausgang, ist er das Ziel —
|
|
480
|
+
mit seinem eigenen Namen, nicht mit dem der Ausgangsnummer.
|
|
481
|
+
|
|
482
|
+
Hier stand: „Wie der einzelne Ausgang heisst, kann die Werkbank
|
|
483
|
+
nicht wissen." Das galt, solange sie nur nach dem GERAET fragen
|
|
484
|
+
konnte. Seit `ausgangsQuellen` weiss sie es: Ricardos `RF1000`
|
|
485
|
+
liest aus `stat.POWER1` und ist damit Ausgang 1. Vorher schlug
|
|
486
|
+
die Zielzeile `…Steckdosenleiste.POWER1` vor — eine Kennung, die
|
|
487
|
+
es gar nicht gibt —, meldete „wird neu angelegt" und haette beim
|
|
488
|
+
Klick einen zweiten Alias neben `RF1000` gesetzt (C13,
|
|
489
|
+
16.09.2026). */
|
|
490
|
+
var vorhAus = aliasFuer(S.current, ausgangsQuellen(e));
|
|
491
|
+
if (vorhAus) {
|
|
492
|
+
var ta = vorhAus.split('.');
|
|
493
|
+
e.zielName = ta.pop();
|
|
494
|
+
e.zielOrdner = ta.join('.');
|
|
486
495
|
} else {
|
|
487
|
-
|
|
496
|
+
if (vorhanden) {
|
|
497
|
+
/* Kein Alias fuer diesen Ausgang, aber einer am Geraet: der gibt
|
|
498
|
+
wenigstens den Ordner vor. Der Name kommt aus der
|
|
499
|
+
Ausgangsnummer — hier entsteht wirklich etwas Neues. */
|
|
500
|
+
var tm = vorhanden.split('.');
|
|
501
|
+
tm.pop();
|
|
502
|
+
e.zielOrdner = tm.join('.');
|
|
503
|
+
} else {
|
|
504
|
+
e.zielOrdner = zt0.join('.') + '.' + geraet;
|
|
505
|
+
}
|
|
506
|
+
e.zielName = ausgangName(e, e.instanz);
|
|
488
507
|
}
|
|
489
|
-
e.zielName = ausgangName(e, e.instanz);
|
|
490
508
|
} else if (vorhanden) {
|
|
491
509
|
var te = vorhanden.split('.');
|
|
492
510
|
e.zielName = te.pop();
|
|
@@ -583,7 +601,10 @@ export function uebernehmeBestand(e) {
|
|
|
583
601
|
function vomAliasUebernehmen(z, o) {
|
|
584
602
|
var c = o.common || {}, q2 = aliasQuellen(o);
|
|
585
603
|
var ist = zeileAusAlias(o, z.n);
|
|
586
|
-
|
|
604
|
+
/* Dieselbe Frage wie in `bestandVorrang`: ohne Vorlage gibt es keinen
|
|
605
|
+
Vorlagenwert. Sonst verglich die Zeile gegen den Rohentwurf und
|
|
606
|
+
nannte das „weicht von der Vorlage ab" (17.09.2026). */
|
|
607
|
+
if (!z.vorlagenWert && e.vorschlag && e.vorlage) {
|
|
587
608
|
z.vorlagenWert = {
|
|
588
609
|
on: z.on, role: z.role, typ: z.typ, unit: z.unit, caption: z.caption,
|
|
589
610
|
f: z.f, fw: z.fw, srcR: z.srcR, srcW: z.srcW, states: z.states
|
|
@@ -768,6 +789,13 @@ export function uebernehmeBestand(e) {
|
|
|
768
789
|
});
|
|
769
790
|
}
|
|
770
791
|
}
|
|
792
|
+
/* Geholt ist nur der erste Wert - mitlaufen tut er erst mit einem Abo.
|
|
793
|
+
Die Zeilen aus dem Alias lesen oft aus einem anderen Knoten als dem
|
|
794
|
+
angeklickten (J9, 18.09.2026: `Stromzaehler` zeigte drei Zeilen „aus
|
|
795
|
+
Solar.Netz" stundenlang auf dem Stand vom Anklicken). Ergaenzt wird
|
|
796
|
+
nur, was noch nicht laeuft; bei jedem Zeichnen zu rufen kostet also
|
|
797
|
+
nichts. */
|
|
798
|
+
if (S.entwurf === e && e.kanal === S.current) { aboErgaenzen(quellenVonEntwurf(e)); }
|
|
771
799
|
}
|
|
772
800
|
|
|
773
801
|
export function unterschiede(e) {
|