iobroker.alias-workbench 0.9.10 → 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 +66 -4
- package/admin/css/werkbank.css +122 -6
- package/admin/js/baum.js +8 -0
- package/admin/js/detail.js +63 -10
- package/admin/js/entwurf.js +416 -190
- package/admin/js/enums.js +2 -2
- package/admin/js/ergebnis.js +156 -23
- package/admin/js/erkennung.js +7 -0
- package/admin/js/mqtt.js +75 -5
- package/admin/js/musterwahl.js +196 -29
- package/admin/js/objekte.js +44 -0
- package/admin/js/pruefungen.js +37 -8
- package/admin/js/schreiben.js +150 -74
- package/admin/js/verwendung.js +478 -0
- package/admin/js/vorlagen.js +75 -6
- package/admin/js/vorlagenblatt.js +134 -17
- package/admin/js/vorschlagen.js +50 -17
- package/admin/js/werte.js +96 -6
- package/admin/js/zielleiste.js +8 -2
- package/admin/js/zuordnung.js +43 -13
- package/admin/js/zustand.js +3 -0
- package/admin/js/zustandsliste.js +56 -20
- package/admin/sprachen/de.json +64 -10
- package/admin/sprachen/en.json +64 -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 +38 -29
- 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,17 +27,22 @@ 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';
|
|
40
44
|
import { zeigeTausch, tauscheAus } from './quellentausch.js';
|
|
45
|
+
import { baueVerwendungKarte } from './verwendung.js';
|
|
41
46
|
|
|
42
47
|
import { baueChecks } from './pruefungen.js';
|
|
43
48
|
import {
|
|
@@ -141,7 +146,15 @@ var warumAuf = false;
|
|
|
141
146
|
}
|
|
142
147
|
|
|
143
148
|
export function entwurfAngefasst() {
|
|
144
|
-
if (S.entwurf) {
|
|
149
|
+
if (S.entwurf) {
|
|
150
|
+
S.entwurf.angefasst = true;
|
|
151
|
+
/* Die Aussicht „was passt nach dem Raten" haengt allein an den
|
|
152
|
+
Zeilen. Sie wird einmal gerechnet und gemerkt; eine Zeilen-
|
|
153
|
+
aenderung ist der einzige Anlass, sie fallen zu lassen. Beim
|
|
154
|
+
blossen Neuzeichnen bleibt sie stehen - das Raten liest keine
|
|
155
|
+
Messwerte, es kaeme dasselbe heraus. */
|
|
156
|
+
S.entwurf.rateAussicht = null;
|
|
157
|
+
}
|
|
145
158
|
}
|
|
146
159
|
|
|
147
160
|
export function neuZeichnenOderAufbauen(danach) {
|
|
@@ -323,6 +336,21 @@ var warumAuf = false;
|
|
|
323
336
|
will, musste ihn bisher im Quellenbaum von Hand wiederfinden.
|
|
324
337
|
Umgekehrt gilt dasselbe: steht man am Geraet und will nachsehen,
|
|
325
338
|
was daraus geworden ist, fuehrt der zweite Knopf hin. */
|
|
339
|
+
/* Zeigt ein Punkt auf eine Quelle, die es nicht gibt, gehoert das
|
|
340
|
+
nach oben - nicht nur in die Zeile und in den Pruefungen-Kasten.
|
|
341
|
+
Der js-controller repariert diesen Zustand nie von allein. */
|
|
342
|
+
var insLeere = (S.entwurf && S.entwurf.states || []).filter(function (s) {
|
|
343
|
+
return s.on && s.srcR && !S.objects[s.srcR];
|
|
344
|
+
});
|
|
345
|
+
if (insLeere.length) {
|
|
346
|
+
sub.appendChild(document.createTextNode(' '));
|
|
347
|
+
var ml = el('span', 'chip bad', insLeere.length === 1
|
|
348
|
+
? tr('result.sourceGone1')
|
|
349
|
+
: tr('result.sourceGoneN', insLeere.length));
|
|
350
|
+
ml.title = insLeere.map(function (s) { return s.n + ' → ' + s.srcR; }).join('\n');
|
|
351
|
+
sub.appendChild(ml);
|
|
352
|
+
}
|
|
353
|
+
|
|
326
354
|
var sprung = null, sprungZiel = null, sprungModus = null;
|
|
327
355
|
if (S.current.indexOf('alias.') === 0) {
|
|
328
356
|
sprungZiel = quelleVon(S.current);
|
|
@@ -488,15 +516,21 @@ var warumAuf = false;
|
|
|
488
516
|
sg.style.borderColor = 'var(--line-strong)';
|
|
489
517
|
sg.style.background = 'var(--surface-2)';
|
|
490
518
|
}
|
|
491
|
-
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
|
|
492
527
|
? tr('tpl.identifiedAs', e.tplName)
|
|
493
|
-
: tr('tpl.noneDetected')
|
|
528
|
+
: tr('tpl.noneDetected');
|
|
529
|
+
var hdName = el('span', 'tname', hdText);
|
|
530
|
+
hdName.title = hdText;
|
|
531
|
+
hd.appendChild(hdName);
|
|
494
532
|
if (e.vorlageVersion) {
|
|
495
|
-
var vv2 = el('span',
|
|
496
|
-
vv2.style.fontFamily = 'var(--mono)';
|
|
497
|
-
vv2.style.fontSize = '10.5px';
|
|
498
|
-
vv2.style.fontWeight = '400';
|
|
499
|
-
vv2.style.color = 'var(--ink-3)';
|
|
533
|
+
var vv2 = el('span', 'tid', ' · ' + e.vorlage + ' v' + e.vorlageVersion);
|
|
500
534
|
hd.appendChild(vv2);
|
|
501
535
|
}
|
|
502
536
|
if (e.vonHandGewaehlt) {
|
|
@@ -547,13 +581,22 @@ var warumAuf = false;
|
|
|
547
581
|
Breite, die eine Liste braucht. */
|
|
548
582
|
var warumKopf = null, warumLeib = null;
|
|
549
583
|
if (gruende.length || weggelassen.length) {
|
|
550
|
-
warumKopf = el('div', 'wkopf');
|
|
551
584
|
/* Ohne Vorlage waere „Warum diese Vorlage" die falsche Frage —
|
|
552
585
|
dann steht hier, warum keine greift. */
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
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);
|
|
557
600
|
warumKopf.tabIndex = 0;
|
|
558
601
|
var um2 = function () { warumAuf = !warumAuf; zeichneErgebnis(); };
|
|
559
602
|
warumKopf.addEventListener('click', um2);
|
|
@@ -610,6 +653,25 @@ var warumAuf = false;
|
|
|
610
653
|
v2.zielOrdner = e.zielOrdner;
|
|
611
654
|
v2.zielName = ausgangName(v2, selA.value);
|
|
612
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); }
|
|
613
675
|
S.entwurf = v2; S.openRow = null; zeichneErgebnis();
|
|
614
676
|
}
|
|
615
677
|
});
|
|
@@ -626,7 +688,10 @@ var warumAuf = false;
|
|
|
626
688
|
das Ausgangsfeld daneben blieb ungestylt in der Browserschrift. */
|
|
627
689
|
var selV = el('select', 'tx');
|
|
628
690
|
|
|
629
|
-
|
|
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')));
|
|
630
695
|
S.VORLAGEN.forEach(function (v) {
|
|
631
696
|
var t = pruefeVorlage(v, S.current);
|
|
632
697
|
/* Auch nicht passende bleiben waehlbar — mit Grund daneben. Sonst
|
|
@@ -639,7 +704,35 @@ var warumAuf = false;
|
|
|
639
704
|
selV.appendChild(o);
|
|
640
705
|
});
|
|
641
706
|
selV.addEventListener('change', function () {
|
|
642
|
-
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
|
+
}
|
|
643
736
|
var v = vorschlag(S.current, selV.value);
|
|
644
737
|
if (v) {
|
|
645
738
|
v.ziel = e.ziel;
|
|
@@ -727,7 +820,11 @@ var warumAuf = false;
|
|
|
727
820
|
neuE.zielName = e.zielName;
|
|
728
821
|
neuE.ordnerVonHand = e.ordnerVonHand;
|
|
729
822
|
if (fest) { neuE.vonHandGewaehlt = false; neuE.ausBestand = true; }
|
|
730
|
-
|
|
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); }
|
|
731
828
|
S.entwurf = neuE; S.openRow = null; zeichneErgebnis();
|
|
732
829
|
});
|
|
733
830
|
/* An der Quelle bleibt die Musterwahl im Vorlagenkasten, wo sie
|
|
@@ -820,7 +917,22 @@ var warumAuf = false;
|
|
|
820
917
|
var bd = $('#btn-dry');
|
|
821
918
|
var ba = $('#btn-dry-alle');
|
|
822
919
|
var mehr = e.instanzen && e.instanzen.length > 1;
|
|
823
|
-
|
|
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;
|
|
824
936
|
/* Die Knoepfe gehoeren zum Modus, nicht nur zum Objekt: Im Modus
|
|
825
937
|
„Alias anlegen" wird angelegt, nicht verwaltet — Verlegen, Quelle
|
|
826
938
|
tauschen und Entfernen haben dort nichts zu suchen. Im Modus
|
|
@@ -867,13 +979,25 @@ var warumAuf = false;
|
|
|
867
979
|
return (e.zielOrdner || '') + '.' + nm;
|
|
868
980
|
}).join(String.fromCharCode(10));
|
|
869
981
|
} else if (mehrK) {
|
|
870
|
-
ba.textContent = tr('write.createPerChannel',
|
|
982
|
+
ba.textContent = tr('write.createPerChannel', grp.length);
|
|
871
983
|
/* Im Hinweis stehen die Namen, die entstehen wuerden — sonst
|
|
872
984
|
klickt man auf eine Zahl und weiss nicht, was danach dasteht. */
|
|
873
|
-
|
|
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) {
|
|
874
995
|
/* Die Kennung, nicht den Anzeigenamen - so heisst das Objekt
|
|
875
|
-
hinterher wirklich (G31).
|
|
876
|
-
|
|
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] : '') + ')';
|
|
877
1001
|
}).join(String.fromCharCode(10));
|
|
878
1002
|
}
|
|
879
1003
|
ba.disabled = false;
|
|
@@ -971,6 +1095,15 @@ var warumAuf = false;
|
|
|
971
1095
|
/* --- Änderungen gegenüber dem, was gespeichert ist --- */
|
|
972
1096
|
baueDiffKarte(host, e);
|
|
973
1097
|
|
|
1098
|
+
/* --- Wo wird das benutzt? ---
|
|
1099
|
+
|
|
1100
|
+
Nur an einem Alias, den es schon gibt: an einem Entwurf, der noch
|
|
1101
|
+
nicht geschrieben ist, kann ihn niemand nennen. */
|
|
1102
|
+
var vAlias = e.ziel || e.kanal;
|
|
1103
|
+
if (vAlias && String(vAlias).indexOf('alias.') === 0 && S.objects[vAlias]) {
|
|
1104
|
+
baueVerwendungKarte(host, vAlias, quelleVon(vAlias));
|
|
1105
|
+
}
|
|
1106
|
+
|
|
974
1107
|
/* --- Prüfungen, Fusszeile, Knopfleiste --- */
|
|
975
1108
|
setzeKnoepfe(e, haupt, pflichtFehlt);
|
|
976
1109
|
}
|
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);
|
|
@@ -655,6 +704,27 @@ function mqttCustom(g, thema) {
|
|
|
655
704
|
zurueckzulesen ist ein Wettlauf: die Sicht hinkt dem frisch
|
|
656
705
|
geschriebenen Objekt einen Wimpernschlag hinterher, und der
|
|
657
706
|
Trockenlauf sperrte weiter wegen eines Punktes, den es laengst gab. */
|
|
707
|
+
/* Der Typ eines Sendepunktes: `mixed`, sobald eine Schreibformel im
|
|
708
|
+
Spiel ist.
|
|
709
|
+
|
|
710
|
+
Sonst rechnet der js-controller den Formelwert beim Schreiben auf den
|
|
711
|
+
Typ des Ziels zurueck, und die Formel war umsonst: `POWER` traegt im
|
|
712
|
+
Befehlswissen `typ: boolean` UND `schreibformel: val ? "ON" : "OFF"`.
|
|
713
|
+
Aus dem "ON" wurde am boolean-Ziel wieder true, auf der Leitung stand
|
|
714
|
+
true statt ON. Geschaltet hat die Tasmota trotzdem — sie nimmt beides —,
|
|
715
|
+
aber die Formel stand nutzlos im Alias, und der von der Werkbank
|
|
716
|
+
angelegte Punkt sah anders aus als jeder von mqtt-client angelegte
|
|
717
|
+
(die sind alle `mixed`). Am Produktivsystem war es genau EINER von 196
|
|
718
|
+
(Ricardo, 15.09.2026, an alias.0.Bastelzimmer.Deckenlicht).
|
|
719
|
+
|
|
720
|
+
Keine Ausnahme fuer POWER, sondern eine Regel, die sich selbst
|
|
721
|
+
durchsetzt — sie gilt ebenso fuer `Fade` und `LedTable`. Wo keine
|
|
722
|
+
Formel steht, bleibt der genaue Typ: aus `number` zieht der Admin
|
|
723
|
+
Min, Max und Einheit. */
|
|
724
|
+
function punktTyp(w) {
|
|
725
|
+
return w.schreibformel ? 'mixed' : (w.typ || 'mixed');
|
|
726
|
+
}
|
|
727
|
+
|
|
658
728
|
export function mqttEinzelnStill(kanal, name, fertig) {
|
|
659
729
|
var bau = mqttPunktBauen(kanal, name, 'neu');
|
|
660
730
|
if (!bau) { return fertig && fertig(); }
|
|
@@ -694,7 +764,7 @@ function mqttPunktBauen(kanal, name, was) {
|
|
|
694
764
|
var common0 = {
|
|
695
765
|
name: name,
|
|
696
766
|
role: w0.rolle || 'state',
|
|
697
|
-
type: w0
|
|
767
|
+
type: punktTyp(w0),
|
|
698
768
|
read: true, write: true,
|
|
699
769
|
desc: tr('mq.createdBy'),
|
|
700
770
|
custom: mqttCustom(g, thema0)
|
|
@@ -728,7 +798,7 @@ export function mqttEinzeln(kanal, name, was, knopf) {
|
|
|
728
798
|
var common = {
|
|
729
799
|
name: name,
|
|
730
800
|
role: w.rolle || 'state',
|
|
731
|
-
type: w
|
|
801
|
+
type: punktTyp(w),
|
|
732
802
|
read: true, write: true,
|
|
733
803
|
desc: tr('mq.createdBy'),
|
|
734
804
|
custom: mqttCustom(g, thema)
|