iobroker.alias-workbench 0.9.0 → 0.9.7
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 +77 -0
- package/admin/geraetewissen/tasmota-befehle.json +3 -1
- package/admin/i18n/de.json +17 -6
- package/admin/i18n/en.json +17 -6
- package/admin/js/aufzaehlungen.js +11 -1
- package/admin/js/baum.js +90 -32
- package/admin/js/detail.js +18 -3
- package/admin/js/entwurf.js +176 -42
- package/admin/js/enums.js +50 -7
- package/admin/js/ergebnis.js +47 -10
- package/admin/js/katalog.js +12 -3
- package/admin/js/mqtt.js +76 -13
- package/admin/js/musterwahl.js +10 -0
- package/admin/js/objekte.js +29 -3
- package/admin/js/pruefungen.js +10 -2
- package/admin/js/quellentausch.js +31 -2
- package/admin/js/schreiben.js +209 -24
- package/admin/js/sprache.js +51 -7
- package/admin/js/start.js +32 -2
- package/admin/js/vorlagen.js +92 -4
- package/admin/js/vorlagenblatt.js +193 -23
- package/admin/js/werte.js +113 -6
- package/admin/js/zuordnung.js +30 -9
- package/admin/js/zustandsliste.js +14 -10
- package/admin/tab.html +17 -3
- package/admin/vorlagen/hm-dimmer.json +1 -1
- package/admin/vorlagen/hm-schaltaktor-lampe.json +2 -2
- package/admin/vorlagen/hm-schaltaktor-mehrfach.json +2 -2
- package/admin/vorlagen/hm-schaltaktor-steckdose.json +2 -2
- package/io-package.json +92 -1
- package/package.json +1 -1
package/admin/js/mqtt.js
CHANGED
|
@@ -38,10 +38,28 @@ export function mqttEinstellung(id) {
|
|
|
38
38
|
if (!o || !o.common) { return null; }
|
|
39
39
|
var cu = o.common.custom || {};
|
|
40
40
|
var k = null;
|
|
41
|
-
|
|
41
|
+
/* Drei Bedingungen, nicht eine.
|
|
42
|
+
|
|
43
|
+
`cu[x]` kann `null` sein — ioBroker raeumt den Eintrag nicht weg,
|
|
44
|
+
wenn eine Instanz verschwindet. Der Zugriff auf `.topic` riss dann
|
|
45
|
+
die ganze Ergebnisansicht mit (gemessen 09.09.2026).
|
|
46
|
+
|
|
47
|
+
Und `enabled` kam hier gar nicht vor: `{ enabled: false,
|
|
48
|
+
publish: true }` galt als sendefaehig, obwohl die Instanz diesen
|
|
49
|
+
Punkt nicht bedient. Fehlt das Feld, gilt der Eintrag als an — so
|
|
50
|
+
legt der Admin es an, wenn man die Verknuepfung setzt. */
|
|
51
|
+
Object.keys(cu).forEach(function (x) {
|
|
52
|
+
if (!k && /^mqtt/.test(x) && cu[x] && cu[x].enabled !== false) { k = x; }
|
|
53
|
+
});
|
|
42
54
|
if (!k) {
|
|
43
|
-
/* Manche Objekte tragen das Thema nur in native.
|
|
44
|
-
|
|
55
|
+
/* Manche Objekte tragen das Thema nur in native — ioBroker.mqtt und
|
|
56
|
+
sonoff tun das. Fuer sie ist `publish` schlicht UNBEKANNT, nicht
|
|
57
|
+
nein: Frueher stand hier `false`, die Pruefung meldete „kann nicht
|
|
58
|
+
senden", der Chip stand rot, und der Knopf „senden erlauben"
|
|
59
|
+
schrieb das Objekt unveraendert zurueck — eine Meldung, die sich
|
|
60
|
+
nicht abstellen liess (gemessen 09.09.2026). `null` heisst: wir
|
|
61
|
+
wissen es nicht, also nicht behaupten. */
|
|
62
|
+
if (o.native && o.native.topic) { return { instanz: null, topic: o.native.topic, publish: null }; }
|
|
45
63
|
return null;
|
|
46
64
|
}
|
|
47
65
|
return { instanz: k, topic: cu[k].topic || (o.native || {}).topic || '', publish: !!cu[k].publish,
|
|
@@ -110,6 +128,12 @@ export function tasmotaBefehle(kanal) {
|
|
|
110
128
|
var liste = [];
|
|
111
129
|
Object.keys(aus).forEach(function (f) {
|
|
112
130
|
if (weg.indexOf(f) > -1) { return; }
|
|
131
|
+
/* Aus dem Schluessel wird eine Kennung UND ein MQTT-Thema. Ein `#`
|
|
132
|
+
oder `+` darin ergaebe ein Wildcard-Abo, ein Punkt eine
|
|
133
|
+
zusaetzliche Ebene im Objektbaum. Der Inhalt kommt vom Broker,
|
|
134
|
+
also von aussen — erreichbar ueber jeden fremden Publisher auf
|
|
135
|
+
demselben Broker. Tasmota-Befehle heissen ohnehin alle so. */
|
|
136
|
+
if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(f)) { return; }
|
|
113
137
|
if (aus[f] !== null && typeof aus[f] === 'object' && !Array.isArray(aus[f])) { return; }
|
|
114
138
|
liste.push({ name: f, wert: aus[f] });
|
|
115
139
|
});
|
|
@@ -143,13 +167,21 @@ export function befehlsWissen(name) {
|
|
|
143
167
|
naechste Befehl die Antwort. Gemessen: nachfragen → „eingeschaltet",
|
|
144
168
|
einmal schalten → wieder „unbekannt", obwohl sich am Geraet nichts
|
|
145
169
|
geaendert hatte. Der Befund war praktisch nie stabil zu sehen. */
|
|
146
|
-
export function sofortRueckmeldung(kanal) {
|
|
170
|
+
export function sofortRueckmeldung(kanal, merken) {
|
|
147
171
|
var id = hatPunkt(kanal, 'stat.RESULT');
|
|
148
172
|
if (id) {
|
|
149
173
|
var j = jsonVon(id);
|
|
150
174
|
if (j && j.SetOption59 !== undefined) {
|
|
151
175
|
var w = String(j.SetOption59).toUpperCase() === 'ON';
|
|
152
|
-
|
|
176
|
+
/* Gemerkt wird nur nach einer Abfrage, nicht beim Zeichnen.
|
|
177
|
+
|
|
178
|
+
Vorher schrieb diese Funktion aus dem Zeichenpfad heraus ein
|
|
179
|
+
Objekt — ein Waechter verhinderte nur das Mehrfachschreiben,
|
|
180
|
+
der Fehler wurde verschluckt, und der Wert stand lokal schon.
|
|
181
|
+
Das widerspricht der Zusage, dass die Pruefungen nichts
|
|
182
|
+
anfassen: Wer die rechte Seite ansieht, aendert nichts.
|
|
183
|
+
`so59()` ruft mit `merken = true`, alle anderen lesen nur. */
|
|
184
|
+
if (merken) { merkeSo59(kanal, w); }
|
|
153
185
|
return w;
|
|
154
186
|
}
|
|
155
187
|
}
|
|
@@ -203,7 +235,10 @@ export function mqttLage(kanal) {
|
|
|
203
235
|
var id = hatPunkt(kanal, 'cmnd.' + x.name);
|
|
204
236
|
if (!id) { fehlen.push(x); return; }
|
|
205
237
|
var m = mqttEinstellung(id);
|
|
206
|
-
|
|
238
|
+
/* `publish === null` heisst unbekannt (Thema nur in `native`) —
|
|
239
|
+
so ein Punkt kommt zu den vorhandenen, nicht zu den stummen.
|
|
240
|
+
„Senden erlauben" haette an ihm ohnehin nichts zu schreiben. */
|
|
241
|
+
if (m && m.publish === false) { stumm.push({ name: x.name, id: id }); } else { da.push(x.name); }
|
|
207
242
|
});
|
|
208
243
|
}
|
|
209
244
|
/* Auch cmnd-Punkte, die es schon gibt, ohne dass sie im Zustand
|
|
@@ -215,7 +250,7 @@ export function mqttLage(kanal) {
|
|
|
215
250
|
if (stumm.some(function (x) { return x.name === name; })) { return; }
|
|
216
251
|
if (da.indexOf(name) > -1) { return; }
|
|
217
252
|
var m = mqttEinstellung(id);
|
|
218
|
-
if (m &&
|
|
253
|
+
if (m && m.publish === false) { stumm.push({ name: name, id: id }); }
|
|
219
254
|
});
|
|
220
255
|
return { geraet: g, befehle: b, fehlen: fehlen, stumm: stumm, da: da,
|
|
221
256
|
sofort: sofortRueckmeldung(kanal) };
|
|
@@ -509,7 +544,7 @@ function so59(kanal, knopf, wert) {
|
|
|
509
544
|
setTimeout(function () {
|
|
510
545
|
holeZweig(kanal + '.', function () {
|
|
511
546
|
delete so59Laeuft[kanal];
|
|
512
|
-
so59Stumm[kanal] = (sofortRueckmeldung(kanal) === null);
|
|
547
|
+
so59Stumm[kanal] = (sofortRueckmeldung(kanal, true) === null);
|
|
513
548
|
zeichneErgebnis();
|
|
514
549
|
});
|
|
515
550
|
}, 4000);
|
|
@@ -556,6 +591,18 @@ function mqttFragen(kanal, _knopf) {
|
|
|
556
591
|
/* Status 5 gleich mit: dort steht die IP, und die fehlt an
|
|
557
592
|
jedem Geraet, das seit dem Einbinden nicht neu gestartet
|
|
558
593
|
ist — tele/INFO2 kommt nur beim Start. */
|
|
594
|
+
/* Wie alt sind die Quellen JETZT?
|
|
595
|
+
|
|
596
|
+
Vorher wurde nur die Merkstelle geleert. Ein `stat.RESULT`,
|
|
597
|
+
das retained von vorgestern dasteht, reichte danach fuer
|
|
598
|
+
die gruene Rueckmeldung — auch wenn das Geraet aus ist und
|
|
599
|
+
gar nicht antwortet (gemessen 09.09.2026). Gewertet wird
|
|
600
|
+
jetzt nur, was nach dem Senden hereinkam. */
|
|
601
|
+
var vorTs = {};
|
|
602
|
+
['stat.STATUS11', 'tele.STATE', 'stat.RESULT'].forEach(function (q) {
|
|
603
|
+
var qid = hatPunkt(kanal, q);
|
|
604
|
+
if (qid && S.werte[qid]) { vorTs[q] = S.werte[qid].ts || 0; }
|
|
605
|
+
});
|
|
559
606
|
socket.emit('setState', id, { val: '5', ack: false }, function () {});
|
|
560
607
|
socket.emit('setState', id, { val: '11', ack: false }, function () {
|
|
561
608
|
setTimeout(function () {
|
|
@@ -569,7 +616,12 @@ function mqttFragen(kanal, _knopf) {
|
|
|
569
616
|
holeZweig(kanal + '.', function () {
|
|
570
617
|
delete abfrageLaeuft[kanal];
|
|
571
618
|
var bb = tasmotaBefehle(kanal);
|
|
572
|
-
|
|
619
|
+
/* Nur wenn die Quelle, aus der die Liste stammt, seit
|
|
620
|
+
dem Senden frisch geworden ist. */
|
|
621
|
+
var qid = bb && hatPunkt(kanal, bb.woher);
|
|
622
|
+
var jetzt = (qid && S.werte[qid]) ? (S.werte[qid].ts || 0) : 0;
|
|
623
|
+
var frisch = bb && jetzt > (vorTs[bb.woher] || 0);
|
|
624
|
+
mqttAbfrage[kanal] = (frisch && bb.befehle.length) ? bb.befehle.length : 0;
|
|
573
625
|
zeichneErgebnis();
|
|
574
626
|
});
|
|
575
627
|
}, 5000);
|
|
@@ -606,7 +658,18 @@ function mqttCustom(g, thema) {
|
|
|
606
658
|
export function mqttEinzelnStill(kanal, name, fertig) {
|
|
607
659
|
var bau = mqttPunktBauen(kanal, name, 'neu');
|
|
608
660
|
if (!bau) { return fertig && fertig(); }
|
|
609
|
-
socket.emit('setObject', bau.id, bau.obj, function () {
|
|
661
|
+
socket.emit('setObject', bau.id, bau.obj, function (err) {
|
|
662
|
+
/* Ein abgelehntes Schreiben ist kein Erfolg.
|
|
663
|
+
|
|
664
|
+
Der Rueckruf nahm `err` frueher nicht einmal entgegen und trug das
|
|
665
|
+
Objekt trotzdem in den eigenen Bestand ein. Danach hielt
|
|
666
|
+
`pruefeSchreiben` den Sendepunkt fuer vorhanden, die Sperre griff
|
|
667
|
+
nicht mehr, und „Jetzt anlegen" schrieb `alias.id.write` auf eine
|
|
668
|
+
Kennung, die es in der Datenbank nie gab — genau der Fehler, den
|
|
669
|
+
der js-controller sich dauerhaft merkt und nur durch Loeschen und
|
|
670
|
+
Neuanlegen vergisst. Der Zwilling `mqttEinzeln` prueft ihn seit
|
|
671
|
+
jeher richtig (gemessen 09.09.2026). */
|
|
672
|
+
if (err) { return fertig && fertig(err); }
|
|
610
673
|
uebernimmObjekt(bau.id, bau.obj);
|
|
611
674
|
if (fertig) { fertig(); }
|
|
612
675
|
});
|
|
@@ -622,7 +685,7 @@ function mqttPunktBauen(kanal, name, was) {
|
|
|
622
685
|
if (!alt0) { return null; }
|
|
623
686
|
obj = JSON.parse(JSON.stringify(alt0));
|
|
624
687
|
var cu0 = obj.common.custom || {};
|
|
625
|
-
Object.keys(cu0).forEach(function (i) { if (/^mqtt/.test(i)) { cu0[i].publish = true; } });
|
|
688
|
+
Object.keys(cu0).forEach(function (i) { if (/^mqtt/.test(i) && cu0[i]) { cu0[i].publish = true; } });
|
|
626
689
|
obj.common.custom = cu0;
|
|
627
690
|
} else {
|
|
628
691
|
var w0 = befehlsWissen(name) || {};
|
|
@@ -656,7 +719,7 @@ export function mqttEinzeln(kanal, name, was, knopf) {
|
|
|
656
719
|
if (!alt) { return; }
|
|
657
720
|
obj = JSON.parse(JSON.stringify(alt));
|
|
658
721
|
var cu = obj.common.custom || {};
|
|
659
|
-
Object.keys(cu).forEach(function (i) { if (/^mqtt/.test(i)) { cu[i].publish = true; } });
|
|
722
|
+
Object.keys(cu).forEach(function (i) { if (/^mqtt/.test(i) && cu[i]) { cu[i].publish = true; } });
|
|
660
723
|
obj.common.custom = cu;
|
|
661
724
|
} else {
|
|
662
725
|
var w = befehlsWissen(name) || {};
|
|
@@ -846,7 +909,7 @@ function mqttZuSchreiben() {
|
|
|
846
909
|
if (!alt) { return; }
|
|
847
910
|
var kopie = JSON.parse(JSON.stringify(alt));
|
|
848
911
|
var cu = kopie.common.custom || {};
|
|
849
|
-
Object.keys(cu).forEach(function (i) { if (/^mqtt/.test(i)) { cu[i].publish = true; } });
|
|
912
|
+
Object.keys(cu).forEach(function (i) { if (/^mqtt/.test(i) && cu[i]) { cu[i].publish = true; } });
|
|
850
913
|
kopie.common.custom = cu;
|
|
851
914
|
raus.push({ id: x.id, obj: kopie, neu: false });
|
|
852
915
|
});
|
package/admin/js/musterwahl.js
CHANGED
|
@@ -112,6 +112,16 @@ export function baueMusterwahl(e, haupt, pflichtFehlt) {
|
|
|
112
112
|
var markeCache = {};
|
|
113
113
|
function bewerte(m) {
|
|
114
114
|
if (markeCache[m] !== undefined) { return markeCache[m]; }
|
|
115
|
+
/* Die angebotene Liste ist gefiltert — der gewaehlte Typ nicht:
|
|
116
|
+
`mBeschriften` ruft `markeFuer(e.want)` direkt, und `e.want` kommt
|
|
117
|
+
ungeprueft aus `v.geraetetyp`. Eine eingelesene Vorlage mit dem
|
|
118
|
+
Musternamen eines neueren type-detector liess `musterVon(m).states`
|
|
119
|
+
werfen, und der Entwurf wurde gar nicht erst gezeichnet — die
|
|
120
|
+
rechte Seite blieb leer (gemessen 09.09.2026). */
|
|
121
|
+
if (!musterVon(m)) {
|
|
122
|
+
markeCache[m] = { mark: tr('pattern.doesNotFit'), passt: false, belegt: 0 };
|
|
123
|
+
return markeCache[m];
|
|
124
|
+
}
|
|
115
125
|
/* Die Vorschau muss vorhersagen, was das Auswaehlen wirklich tut.
|
|
116
126
|
Beim Vorschlag werden Lampe und Steckdose samt Rollen neu gebaut -
|
|
117
127
|
also auch hier gegen den umgebauten Entwurf pruefen. Sonst stuende
|
package/admin/js/objekte.js
CHANGED
|
@@ -81,6 +81,19 @@ export function nachziehenErledigt() {
|
|
|
81
81
|
nachziehBaum = false;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/* Nach einem Abbruch sind beim Server alle Abos weg.
|
|
85
|
+
|
|
86
|
+
`subscribeObjects` und `subscribe` gelten nur fuer die Sitzung, die
|
|
87
|
+
sie gestellt hat — der WebSocket-Shim des Admin erneuert von sich aus
|
|
88
|
+
nichts (das Wort `subscribe` kommt in seinem Quelltext kein einziges
|
|
89
|
+
Mal vor). Der `objectChange`-Horcher wird hier ausdruecklich NICHT
|
|
90
|
+
noch einmal angemeldet: der haengt am Socket-Objekt und hat den
|
|
91
|
+
Abbruch ueberlebt. Nur die Anmeldung beim Server fehlt. */
|
|
92
|
+
export function abosErneuern() {
|
|
93
|
+
if (horcht) { socket.emit('subscribeObjects', '*'); }
|
|
94
|
+
(S.abo || []).forEach(function (m) { socket.emit('subscribe', m); });
|
|
95
|
+
}
|
|
96
|
+
|
|
84
97
|
export function horcheAufObjekte() {
|
|
85
98
|
if (horcht) { return; }
|
|
86
99
|
horcht = true;
|
|
@@ -95,11 +108,20 @@ export function horcheAufObjekte() {
|
|
|
95
108
|
var kern = function (o) {
|
|
96
109
|
return o ? JSON.stringify([o.type, o.common, o.native]) : null;
|
|
97
110
|
};
|
|
98
|
-
var vorher = kern(S.objects[id]);
|
|
99
111
|
var nachher = kern(obj);
|
|
100
|
-
if (vorher === nachher) { return; }
|
|
101
112
|
|
|
102
|
-
/* Aufzaehlungen
|
|
113
|
+
/* Aufzaehlungen zuerst — und zwar VOR dem Vergleich mit `S.objects`.
|
|
114
|
+
|
|
115
|
+
Der Vergleich unten fragt `S.objects[id]`, und dort liegen
|
|
116
|
+
Aufzaehlungen nie. Beim Loeschen einer Aufzaehlung sind alter und
|
|
117
|
+
neuer Wert deshalb beide `null`, der Frueheinstieg griff, und
|
|
118
|
+
`delete enums[id]` wurde nie erreicht. Die geloeschte Aufzaehlung
|
|
119
|
+
blieb im Vorrat stehen, und der naechste Alias mit diesem Raum
|
|
120
|
+
kopierte sie samt aller alten Mitglieder zurueck an ihren Platz.
|
|
121
|
+
Gemessen 09.09.2026 am Testsystem: `enum.rooms.WBP7` war am System
|
|
122
|
+
geloescht und waere mit zwei fremden Mitgliedern wieder entstanden.
|
|
123
|
+
|
|
124
|
+
Aufzaehlungen gehen einen eigenen Weg.
|
|
103
125
|
|
|
104
126
|
Sie gehoeren nicht in `objects` - dort stuenden sie im Geraetebaum,
|
|
105
127
|
wo sie nichts zu suchen haben. Nachziehen muss man sie aber, und
|
|
@@ -128,6 +150,10 @@ export function horcheAufObjekte() {
|
|
|
128
150
|
return;
|
|
129
151
|
}
|
|
130
152
|
|
|
153
|
+
/* Alles Uebrige: nur was zaehlt, nicht jeder Schreibvorgang. */
|
|
154
|
+
var vorher = kern(S.objects[id]);
|
|
155
|
+
if (vorher === nachher) { return; }
|
|
156
|
+
|
|
131
157
|
var gabEs = S.objects[id] !== undefined;
|
|
132
158
|
if (obj) { S.objects[id] = obj; } else { delete S.objects[id]; }
|
|
133
159
|
if (gabEs !== (S.objects[id] !== undefined)) { nachziehBaum = true; }
|
package/admin/js/pruefungen.js
CHANGED
|
@@ -68,7 +68,7 @@ export function pruefungDopplung(e) {
|
|
|
68
68
|
export function pruefungSenden(e) {
|
|
69
69
|
var ziele = e.states.filter(function (x) { return x.on && x.srcW; });
|
|
70
70
|
if (!ziele.length) { return { s: 'mut', t: tr('check.publish'), d: tr('check.noWritePath') }; }
|
|
71
|
-
var mqtt = [], stumm = [], fehlt = [];
|
|
71
|
+
var mqtt = [], stumm = [], fehlt = [], unklar = [];
|
|
72
72
|
ziele.forEach(function (x) {
|
|
73
73
|
/* Drei Faelle, nicht zwei: den Punkt gibt es gar nicht, es gibt ihn
|
|
74
74
|
und er ist stumm, oder er sendet. Der erste kam dazu, seit die
|
|
@@ -77,11 +77,19 @@ export function pruefungSenden(e) {
|
|
|
77
77
|
var m = mqttEinstellung(x.srcW);
|
|
78
78
|
if (!m) { return; }
|
|
79
79
|
mqtt.push(x);
|
|
80
|
-
|
|
80
|
+
/* Nur ein ausdrueckliches Nein ist ein Nein. `null` heisst
|
|
81
|
+
unbekannt: Objekte von ioBroker.mqtt und sonoff tragen das Thema
|
|
82
|
+
nur in `native`, ohne `custom`-Block — ueber ihre Sendefaehigkeit
|
|
83
|
+
sagt das nichts. Vorher stand dort fest `false`, und die Pruefung
|
|
84
|
+
meldete rot „kann nicht senden", ohne dass sich etwas daran
|
|
85
|
+
aendern liess (gemessen 09.09.2026). */
|
|
86
|
+
if (m.publish === false) { stumm.push(x.n); }
|
|
87
|
+
else if (m.publish === null) { unklar.push(x.n); }
|
|
81
88
|
});
|
|
82
89
|
if (fehlt.length) { return { s: 'bad', t: tr('check.publish'), d: tr('check.sendPointMissing', fehlt.join(', ')) }; }
|
|
83
90
|
if (!mqtt.length) { return { s: 'mut', t: tr('check.publish'), d: tr('check.notMqtt') }; }
|
|
84
91
|
if (stumm.length) { return { s: 'bad', t: tr('check.publish'), d: tr('check.cannotSend', stumm.join(', ')) }; }
|
|
92
|
+
if (unklar.length) { return { s: 'mut', t: tr('check.publish'), d: tr('check.sendUnknown', unklar.join(', ')) }; }
|
|
85
93
|
return { s: 'ok', t: tr('check.publish'), d: tr('check.canSend', mqtt.length) };
|
|
86
94
|
}
|
|
87
95
|
|
|
@@ -162,7 +162,15 @@ export function tauschPlan(kanal, neuKanal) {
|
|
|
162
162
|
}
|
|
163
163
|
if (!zeile.neuW && zeile.altW) {
|
|
164
164
|
var gw = geraten(zeile.altW, neuKanal);
|
|
165
|
-
|
|
165
|
+
/* Was hier geraten wird, muss ein anderer Punkt sein als die
|
|
166
|
+
Lesequelle. Bei getrennten Quellen heissen Melder und Befehl oft
|
|
167
|
+
gleich - `stat.POWER` und `cmnd.POWER` -, und das Raten greift
|
|
168
|
+
nach dem Namen: aus der Schreibquelle `cmnd.POWER` wurde am
|
|
169
|
+
neuen Geraet `stat.POWER`, also genau der Melder. Der Alias
|
|
170
|
+
haette danach seinen Befehl ins Status-Thema geschickt; das
|
|
171
|
+
Geraet schaltet nicht und die Rueckmeldung ist verfaelscht
|
|
172
|
+
(gemessen 09.09.2026). Lieber kein Treffer als dieser. */
|
|
173
|
+
if (gw && gw !== zeile.neuR) { zeile.neuW = gw; }
|
|
166
174
|
}
|
|
167
175
|
/* Bei einfacher Quelle gilt die Lesequelle fuer beides. */
|
|
168
176
|
if (zeile.einfach && zeile.neuR) { zeile.neuW = zeile.neuR; }
|
|
@@ -191,7 +199,19 @@ export function tauschObjekte(kanal, neuKanal, plan, weg) {
|
|
|
191
199
|
delete neu.ts; delete neu.from; delete neu.user; delete neu.acl; delete neu._id;
|
|
192
200
|
var a = neu.common.alias || {};
|
|
193
201
|
if (z.neuW && z.neuW !== z.neuR) { a.id = { read: z.neuR, write: z.neuW }; }
|
|
194
|
-
else { a.id = z.neuR; }
|
|
202
|
+
else if (z.einfach) { a.id = z.neuR; }
|
|
203
|
+
else {
|
|
204
|
+
/* Getrennte Quellen ohne Schreibtreffer: die Objektform bleibt.
|
|
205
|
+
|
|
206
|
+
Eine blosse Zeichenkette heisst fuer den js-controller „lesen
|
|
207
|
+
und schreiben auf dieselbe Kennung". Aus einem Alias, der den
|
|
208
|
+
Zustand liest und den Befehl woanders hinschickt, wurde damit
|
|
209
|
+
einer, der auf den Melder schreibt - und aus einem bewusst nur
|
|
210
|
+
lesenden Punkt bei `common.write: true` sogar ein schreibender.
|
|
211
|
+
Ohne Treffer bleibt `write` einfach weg: dann schreibt der Alias
|
|
212
|
+
nirgendwohin, und das ist die ehrliche Auskunft. */
|
|
213
|
+
a.id = { read: z.neuR };
|
|
214
|
+
}
|
|
195
215
|
neu.common.alias = a;
|
|
196
216
|
raus.push({ id: z.id, neu: false, obj: neu });
|
|
197
217
|
});
|
|
@@ -461,6 +481,15 @@ function zeichneTausch() {
|
|
|
461
481
|
rechts.appendChild(paarZeile(tr('write.diffNew'),
|
|
462
482
|
z.neuR + (z.neuW && z.neuW !== z.neuR ? ' → ' + z.neuW : ''),
|
|
463
483
|
'sn', gleich ? 'var(--ink-3)' : 'var(--ok)'));
|
|
484
|
+
/* Lesequelle gefunden, Schreibquelle nicht — das gehoert gesagt.
|
|
485
|
+
Sonst steht nur die neue Lesequelle in Gruen da, und dass der
|
|
486
|
+
Punkt danach nirgendwohin schreibt, merkt man erst am Geraet. */
|
|
487
|
+
if (z.altW && z.altW !== z.altR && !z.neuW) {
|
|
488
|
+
var kw = el('div');
|
|
489
|
+
kw.style.color = 'var(--bad)';
|
|
490
|
+
kw.textContent = tr('swap.noWriteMatch');
|
|
491
|
+
rechts.appendChild(kw);
|
|
492
|
+
}
|
|
464
493
|
} else {
|
|
465
494
|
var fehlt = el('div');
|
|
466
495
|
fehlt.style.color = 'var(--bad)';
|