iobroker.alias-workbench 0.8.1 → 0.8.3
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 +277 -217
- package/admin/alias-workbench.png +0 -0
- package/admin/alias-workbench.svg +13 -0
- package/admin/css/werkbank.css +69 -0
- package/admin/i18n/de.json +15 -1
- package/admin/i18n/en.json +15 -1
- package/admin/js/baum.js +12 -2
- package/admin/js/detail.js +119 -7
- package/admin/js/entwurf.js +93 -5
- package/admin/js/ergebnis.js +21 -6
- package/admin/js/erkennung.js +87 -0
- package/admin/js/quellentausch.js +18 -2
- package/admin/js/schreiben.js +54 -11
- package/admin/js/vorlagen.js +13 -4
- package/admin/js/werte.js +20 -0
- package/admin/js/zielleiste.js +75 -4
- package/admin/js/zuordnung.js +113 -7
- package/admin/js/zustandsliste.js +72 -17
- package/admin/tab.html +11 -0
- package/io-package.json +27 -1
- package/package.json +1 -1
package/admin/js/erkennung.js
CHANGED
|
@@ -22,6 +22,89 @@ export function rolleAusAusdruck(r) {
|
|
|
22
22
|
|
|
23
23
|
export function rolleVonPlatz(st) { return st.defaultRole || rolleAusAusdruck(st.role); }
|
|
24
24
|
|
|
25
|
+
/* Alle Schreibweisen, die ein Platz annimmt — nicht nur seine Vorgabe.
|
|
26
|
+
|
|
27
|
+
Der LOWBAT-Platz nennt als Vorgabe `indicator.maintenance.lowbat`,
|
|
28
|
+
sein Ausdruck erlaubt aber vier Formen:
|
|
29
|
+
|
|
30
|
+
/^indicator(\.maintenance)?\.(lowbat|battery)$/
|
|
31
|
+
|
|
32
|
+
Nur die Vorgabe in die Auswahlliste zu stellen hiess: Wer die Rolle
|
|
33
|
+
sucht, die sein eigenes Geraet traegt, findet sie nicht. hm-rpc
|
|
34
|
+
schreibt `indicator.lowbat`, alle elf Homematic-Vorlagen benutzen sie,
|
|
35
|
+
und die ioBroker-Rollenliste fuehrt beide nebeneinander — nur die
|
|
36
|
+
Werkbank kannte eine davon nicht (Ricardo, 06.09.2026).
|
|
37
|
+
|
|
38
|
+
Ausmultipliziert werden genau zwei Formen, weil nur die im Detector
|
|
39
|
+
vorkommen: Alternativen `(a|b)` und optionale Gruppen `(…)?`. Alles
|
|
40
|
+
andere — Zeichenklassen, `.*`, Verschachtelung — gibt leer zurueck;
|
|
41
|
+
dann bleibt es bei der Vorgaberolle. Lieber eine Schreibweise zu wenig
|
|
42
|
+
als eine erfundene in der Liste. */
|
|
43
|
+
export function schreibweisenAus(r) {
|
|
44
|
+
if (!r) { return []; }
|
|
45
|
+
var q = (r.source !== undefined) ? r.source : String(r);
|
|
46
|
+
if (q.charAt(0) !== '^' || q.slice(-1) !== '$') { return []; }
|
|
47
|
+
q = q.slice(1, -1);
|
|
48
|
+
|
|
49
|
+
var teile = [''];
|
|
50
|
+
var rest = q;
|
|
51
|
+
var sicher = 0;
|
|
52
|
+
while (rest && sicher++ < 40) {
|
|
53
|
+
var g = /^\(([^()]*)\)(\?)?/.exec(rest);
|
|
54
|
+
if (g) {
|
|
55
|
+
var wahl = g[1].split('|');
|
|
56
|
+
if (g[2]) { wahl = wahl.concat(['']); } /* optional: auch weglassen */
|
|
57
|
+
var neu = [];
|
|
58
|
+
teile.forEach(function (v) {
|
|
59
|
+
wahl.forEach(function (w) { neu.push(v + w.split('\\').join('')); });
|
|
60
|
+
});
|
|
61
|
+
teile = neu;
|
|
62
|
+
rest = rest.slice(g[0].length);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
var lit = /^(\\.|[A-Za-z0-9_.])+/.exec(rest);
|
|
66
|
+
if (!lit) { return []; } /* etwas Unbekanntes */
|
|
67
|
+
var text = lit[0].split('\\').join('');
|
|
68
|
+
teile = teile.map(function (v) { return v + text; });
|
|
69
|
+
rest = rest.slice(lit[0].length);
|
|
70
|
+
}
|
|
71
|
+
if (rest) { return []; }
|
|
72
|
+
|
|
73
|
+
var gut = [];
|
|
74
|
+
teile.forEach(function (t) {
|
|
75
|
+
if (/^[A-Za-z0-9_]+([.][A-Za-z0-9_]+)*$/.test(t) && gut.indexOf(t) === -1) { gut.push(t); }
|
|
76
|
+
});
|
|
77
|
+
return gut;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Rollen, die der Detector aus Ruecksicht auf alte Adapter noch annimmt,
|
|
81
|
+
die aber nicht mehr benutzt werden sollen. Aus der Tabelle „Deprecated
|
|
82
|
+
role aliases" in ioBroker.docs (docs/en/dev/stateroles.md, gelesen am
|
|
83
|
+
06.09.2026) — dort steht zu jeder auch, was stattdessen gilt.
|
|
84
|
+
|
|
85
|
+
Sie stehen hier, weil die Zerlegung oben sonst gerade sie in die
|
|
86
|
+
Auswahlliste holt: `indicator(\.maintenance)?\.(lowbat|battery)`
|
|
87
|
+
erlaubt eben auch `indicator.battery`. Eine laengere Liste ist kein
|
|
88
|
+
Gewinn, wenn die Haelfte davon veraltet ist.
|
|
89
|
+
|
|
90
|
+
Vorgaberollen des Detectors werden NICHT gefiltert: was er selbst als
|
|
91
|
+
Vorgabe fuehrt, gilt, auch wenn die Doku es anders saehe. Gefiltert
|
|
92
|
+
wird nur, was diese Zerlegung zusaetzlich vorschlaegt. */
|
|
93
|
+
var VERALTET = {};
|
|
94
|
+
('action.close action.close.blind action.close.tilt action.home action.next ' +
|
|
95
|
+
'action.open action.open.blind action.open.tilt action.pause action.play ' +
|
|
96
|
+
'action.prev action.stop action.stop.blind action.stop.tilt ' +
|
|
97
|
+
'indicator.battery indicator.fire indicator.flood ' +
|
|
98
|
+
'indicator.maintenance.battery indicator.unreach ' +
|
|
99
|
+
'level.thermostat sensor.co sensor.fire sensor.flood ' +
|
|
100
|
+
'state.active state.alarm.co state.alarm.fire state.alarm.flood state.co ' +
|
|
101
|
+
'state.door state.fire state.flood state.light state.motion state.window ' +
|
|
102
|
+
'switch.active switch.autofocus switch.autowhitebalance switch.boost ' +
|
|
103
|
+
'switch.brightness switch.nightmode switch.party ' +
|
|
104
|
+
'value.accuracy value.brush value.brush.side value.elevation ' +
|
|
105
|
+
'value.latitude value.longitude value.radius value.sensors'
|
|
106
|
+
).split(' ').forEach(function (r) { VERALTET[r] = 1; });
|
|
107
|
+
|
|
25
108
|
export var ROLLEN = (function () {
|
|
26
109
|
if (!D) { return []; }
|
|
27
110
|
var m = {};
|
|
@@ -29,6 +112,10 @@ export var ROLLEN = (function () {
|
|
|
29
112
|
D.patterns[t].states.forEach(function (st) {
|
|
30
113
|
var r = rolleVonPlatz(st);
|
|
31
114
|
if (r) { m[r] = 1; }
|
|
115
|
+
/* Dazu, was der Platz sonst noch annimmt — ohne das Veraltete. */
|
|
116
|
+
schreibweisenAus(st.role).forEach(function (x) {
|
|
117
|
+
if (!VERALTET[x]) { m[x] = 1; }
|
|
118
|
+
});
|
|
32
119
|
});
|
|
33
120
|
});
|
|
34
121
|
['state', 'text', 'json', 'value'].forEach(function (r) { m[r] = 1; });
|
|
@@ -23,7 +23,7 @@ import { tr, txt } from './sprache.js';
|
|
|
23
23
|
import { socket } from './verbindung.js';
|
|
24
24
|
import { aliasQuellen, kindZustaende } from './werte.js';
|
|
25
25
|
import { holeZweig, indexNeu } from './objekte.js';
|
|
26
|
-
import { waehle } from './entwurf.js';
|
|
26
|
+
import { waehle, knotenDa } from './entwurf.js';
|
|
27
27
|
import { zeichneErgebnis } from './ergebnis.js';
|
|
28
28
|
|
|
29
29
|
/* Die Punkte des Alias, die ueberhaupt eine Quelle haben. */
|
|
@@ -325,7 +325,7 @@ export function zeigeTausch() {
|
|
|
325
325
|
/* Wie bei zeigeVerlegen und zeigeLoeschen: an der Quelle ist
|
|
326
326
|
S.current die Quelle, gemeint ist das Ziel des Entwurfs (T1). */
|
|
327
327
|
var ziel = (S.entwurf && (S.entwurf.ziel || S.entwurf.kanal)) || S.current;
|
|
328
|
-
if (!ziel || ziel.indexOf('alias.') !== 0 || !
|
|
328
|
+
if (!ziel || ziel.indexOf('alias.') !== 0 || !knotenDa(ziel)) { return; }
|
|
329
329
|
S.tauschZiel = ziel;
|
|
330
330
|
S.tauschNeu = '';
|
|
331
331
|
S.tauschWeg = {};
|
|
@@ -355,6 +355,22 @@ function zeichneTausch() {
|
|
|
355
355
|
var z1 = el('div');
|
|
356
356
|
z1.appendChild(el('b', null, tr('swap.from') + ' '));
|
|
357
357
|
z1.appendChild(el('span', 'sn', alt || tr('swap.unknown')));
|
|
358
|
+
/* Den Namen dahinter, wo er mehr sagt als die Kennung.
|
|
359
|
+
|
|
360
|
+
`hm-rpc.0.0000DBE9A2B8AF` sagt einem nichts; woran man das Geraet
|
|
361
|
+
erkennt, steht allein im Namen (Ricardo, 06.09.2026). Dieselbe Regel
|
|
362
|
+
wie im Baum: gleicht der Name dem letzten Stueck der Kennung, bringt
|
|
363
|
+
er nichts und bleibt weg.
|
|
364
|
+
|
|
365
|
+
Ist das Geraet weg — der Normalfall bei „Geraet kaputt" —, gibt es
|
|
366
|
+
kein Objekt und damit keinen Namen mehr. Dann steht dort wie bisher
|
|
367
|
+
nur die Kennung, und die Zeile darunter sagt, dass es sie nicht mehr
|
|
368
|
+
gibt. */
|
|
369
|
+
var altObj = alt && S.objects[alt];
|
|
370
|
+
var altName = altObj ? txt(altObj.common && altObj.common.name).trim() : '';
|
|
371
|
+
if (altName && altName !== String(alt).split('.').pop()) {
|
|
372
|
+
z1.appendChild(el('span', 'leise', ' ' + altName));
|
|
373
|
+
}
|
|
358
374
|
kopf.appendChild(z1);
|
|
359
375
|
if (alt && !S.objects[alt] && !kindZustaende(alt).length) {
|
|
360
376
|
kopf.appendChild(el('div', 'hint', tr('swap.gone')));
|
package/admin/js/schreiben.js
CHANGED
|
@@ -18,7 +18,9 @@ import {
|
|
|
18
18
|
ordnerUnterAlias,
|
|
19
19
|
gemeinsameKanaele,
|
|
20
20
|
kennungtauglich,
|
|
21
|
-
entwurfFuer
|
|
21
|
+
entwurfFuer,
|
|
22
|
+
aliasFuer,
|
|
23
|
+
knotenDa
|
|
22
24
|
} from './entwurf.js';
|
|
23
25
|
import { zeichneErgebnis } from './ergebnis.js';
|
|
24
26
|
|
|
@@ -162,8 +164,22 @@ export function objektText(o, geordnet) {
|
|
|
162
164
|
return JSON.stringify(geordnet ? ordne(k, '') : k, null, 2);
|
|
163
165
|
}
|
|
164
166
|
|
|
167
|
+
/* Der gespeicherte Stand zu einer Kennung.
|
|
168
|
+
|
|
169
|
+
Aufzaehlungen liegen nicht in `S.objects` - die Werkbank haelt sie in
|
|
170
|
+
einem eigenen Vorrat, weil der Admin sie getrennt ausliefert. Der
|
|
171
|
+
Trockenlauf las trotzdem nur `S.objects`, und so blieb die Spalte
|
|
172
|
+
„bisher" bei jeder Aufzaehlung leer: verglichen wurde gegen nichts,
|
|
173
|
+
also stand rechts jede Zeile als neu da - auch die zehn Mitglieder,
|
|
174
|
+
die laengst drin waren (Ricardo, 08.09.2026). */
|
|
175
|
+
export function bestandsObjekt(id) {
|
|
176
|
+
if (S.objects[id]) { return S.objects[id]; }
|
|
177
|
+
if (String(id).indexOf('enum.') === 0 && enums[id]) { return enums[id]; }
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
|
|
165
181
|
export function unveraendert(id, obj) {
|
|
166
|
-
var alt =
|
|
182
|
+
var alt = bestandsObjekt(id);
|
|
167
183
|
if (!alt) { return false; }
|
|
168
184
|
var putz = function (x) {
|
|
169
185
|
var k = JSON.parse(JSON.stringify(x || {}));
|
|
@@ -300,7 +316,9 @@ export function baueObjekte(e) {
|
|
|
300
316
|
das wird nicht ungefragt geloescht. */
|
|
301
317
|
export function verwaiste(e) {
|
|
302
318
|
var ziel = e.ziel || e.kanal;
|
|
303
|
-
|
|
319
|
+
/* Auch ohne Kanalobjekt kann darunter ein Alias liegen - dann gibt es
|
|
320
|
+
dort auch verwaiste Punkte zu finden. */
|
|
321
|
+
if (!knotenDa(ziel)) { return []; }
|
|
304
322
|
var behalten = {};
|
|
305
323
|
e.states.forEach(function (st) {
|
|
306
324
|
if (st.on && st.n) { behalten[ziel + '.' + st.n] = 1; }
|
|
@@ -472,7 +490,8 @@ export function zeigeTrockenlauf(alleAusgaenge) {
|
|
|
472
490
|
verspraeche er eine Wirkung, die er nicht hat. */
|
|
473
491
|
var vergleichbar = liste.filter(function (x) { return !x.neu && !x.gleich; });
|
|
474
492
|
var rohAnders = vergleichbar.some(function (x) {
|
|
475
|
-
|
|
493
|
+
var b0 = bestandsObjekt(x.id);
|
|
494
|
+
return objektText(b0, false) !== objektText(b0, true)
|
|
476
495
|
|| objektText(x.obj, false) !== objektText(x.obj, true);
|
|
477
496
|
});
|
|
478
497
|
if (vergleichbar.length && rohAnders) {
|
|
@@ -488,6 +507,20 @@ export function zeigeTrockenlauf(alleAusgaenge) {
|
|
|
488
507
|
}
|
|
489
508
|
body.appendChild(kopf);
|
|
490
509
|
|
|
510
|
+
/* Dieselbe Auskunft wie in der Zielleiste, noch einmal hier - der
|
|
511
|
+
Trockenlauf ist die letzte Stelle vor dem Schreiben, und wer den
|
|
512
|
+
Balken oben ueberliest, soll es spaetestens jetzt sehen: es gibt
|
|
513
|
+
schon einen Alias auf diese Quelle, und der bleibt stehen. */
|
|
514
|
+
var zwQuelle = S.entwurf && S.entwurf.kanal;
|
|
515
|
+
var zwZiel = S.entwurf && (S.entwurf.ziel || S.entwurf.kanal);
|
|
516
|
+
var zwAlt = zwQuelle ? aliasFuer(zwQuelle) : null;
|
|
517
|
+
if (zwAlt && S.objects[zwAlt] && zwAlt !== zwZiel) {
|
|
518
|
+
var zwK = el('div', 'aside w');
|
|
519
|
+
zwK.style.marginBottom = '11px';
|
|
520
|
+
zwK.appendChild(el('b', null, tr('target.twinExists', zwAlt)));
|
|
521
|
+
body.appendChild(zwK);
|
|
522
|
+
}
|
|
523
|
+
|
|
491
524
|
if (weg.length) {
|
|
492
525
|
var wk = el('div', 'card');
|
|
493
526
|
wk.style.marginBottom = '11px';
|
|
@@ -657,7 +690,7 @@ export function zeigeTrockenlauf(alleAusgaenge) {
|
|
|
657
690
|
var vgl = el('div', 'dvgl');
|
|
658
691
|
vgl.appendChild(el('span', 'dkopf', tr('write.diffOld')));
|
|
659
692
|
vgl.appendChild(el('span', 'dkopf', tr('write.diffNew')));
|
|
660
|
-
zeilenVergleich(objektText(
|
|
693
|
+
zeilenVergleich(objektText(bestandsObjekt(x.id), !S.trockenRoh),
|
|
661
694
|
objektText(x.obj, !S.trockenRoh))
|
|
662
695
|
.forEach(function (z) {
|
|
663
696
|
vgl.appendChild(el('span', 'dz l ' + z.art, z.l === undefined ? '' : z.l));
|
|
@@ -678,7 +711,7 @@ export function zeigeTrockenlauf(alleAusgaenge) {
|
|
|
678
711
|
var zt = $('#dry-titel');
|
|
679
712
|
if (zt) {
|
|
680
713
|
var zielName = S.entwurf.ziel || S.entwurf.kanal;
|
|
681
|
-
zt.textContent = (
|
|
714
|
+
zt.textContent = (knotenDa(zielName) ? tr('write.dryTitleUpdate') : tr('write.dryTitleCreate')) +
|
|
682
715
|
(entwuerfe.length > 1 ? tr('write.dryOutputs', entwuerfe.length) : '');
|
|
683
716
|
}
|
|
684
717
|
/* Beim Oeffnen wieder herstellen: der Dialog wird wiederverwendet, und
|
|
@@ -714,7 +747,7 @@ function geschwisterVon(ziel) {
|
|
|
714
747
|
|
|
715
748
|
export function zeigeLoeschen() {
|
|
716
749
|
var ziel = (S.entwurf && (S.entwurf.ziel || S.entwurf.kanal)) || S.current;
|
|
717
|
-
if (!ziel || ziel.indexOf('alias.') !== 0 || !
|
|
750
|
+
if (!ziel || ziel.indexOf('alias.') !== 0 || !knotenDa(ziel)) { return; }
|
|
718
751
|
S.loeschZiel = ziel;
|
|
719
752
|
S.loeschAlleAusgaenge = false;
|
|
720
753
|
zeichneLoeschen();
|
|
@@ -986,17 +1019,27 @@ export function sucheInSkripten(kennung, fertig) {
|
|
|
986
1019
|
} catch { fertigMit(); }
|
|
987
1020
|
}
|
|
988
1021
|
|
|
989
|
-
export function zeigeVerlegen() {
|
|
1022
|
+
export function zeigeVerlegen(altVorgabe, zielVorgabe) {
|
|
990
1023
|
/* Der Knopf steht auch an der Quelle, sobald es den Alias gibt (T1).
|
|
991
1024
|
Dort ist S.current die Quelle, nicht der Alias - gemeint ist immer
|
|
992
1025
|
das Ziel des Entwurfs. Genauso haelt es zeigeLoeschen; zeigeTausch
|
|
993
1026
|
tat es bis 05.09.2026 nicht, und beide Knoepfe waren an der Quelle
|
|
994
|
-
sichtbar, aber wirkungslos: kein Dialog, keine Meldung.
|
|
995
|
-
|
|
1027
|
+
sichtbar, aber wirkungslos: kein Dialog, keine Meldung.
|
|
1028
|
+
|
|
1029
|
+
Die zwei Vorgaben kommen vom Knopf „stattdessen verlegen" in der
|
|
1030
|
+
Zielleiste: dort ist das Ziel des Entwurfs der NEUE Pfad, den es
|
|
1031
|
+
noch gar nicht gibt - ohne Vorgabe stiege der Dialog gleich in der
|
|
1032
|
+
ersten Zeile wieder aus. Verlegt wird der vorhandene Alias
|
|
1033
|
+
(`altVorgabe`), und die Felder stehen schon auf dem, was in der
|
|
1034
|
+
Zielleiste getippt wurde (`zielVorgabe`). */
|
|
1035
|
+
var alt = (typeof altVorgabe === 'string' && altVorgabe) ||
|
|
1036
|
+
(S.entwurf && (S.entwurf.ziel || S.entwurf.kanal)) || S.current;
|
|
996
1037
|
if (!alt || alt.indexOf('alias.') !== 0 || !S.objects[alt]) { return; }
|
|
997
1038
|
S.verlegeZiel = alt;
|
|
998
1039
|
|
|
999
|
-
var
|
|
1040
|
+
var vorbelegt = (typeof zielVorgabe === 'string' && zielVorgabe &&
|
|
1041
|
+
zielVorgabe.indexOf('alias.') === 0) ? zielVorgabe : alt;
|
|
1042
|
+
var teile = vorbelegt.split('.');
|
|
1000
1043
|
var name0 = teile.pop();
|
|
1001
1044
|
var ordner0 = teile.join('.');
|
|
1002
1045
|
|
package/admin/js/vorlagen.js
CHANGED
|
@@ -370,8 +370,17 @@ export function schreibZiel(z, kanal, auf) {
|
|
|
370
370
|
return befehlMoeglich(kanal, pfad) ? (kanal + '.' + pfad) : '';
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
-
/* Vorlage auf einen Kanal anwenden → Entwurf.
|
|
374
|
-
|
|
373
|
+
/* Vorlage auf einen Kanal anwenden → Entwurf.
|
|
374
|
+
|
|
375
|
+
`auchOhneTreffer` laesst einen Entwurf auch dann entstehen, wenn keine
|
|
376
|
+
einzige Zeile der Vorlage eine Quelle am Geraet findet. Das gilt nur fuer
|
|
377
|
+
die Wahl von Hand: Genau dafuer ist das Auswahlfeld gedacht — „sonst steht
|
|
378
|
+
man bei einem Geraet, das noch nichts gesendet hat, ohne jede Moeglichkeit
|
|
379
|
+
da". Bis 06.09.2026 fiel gerade dieser Fall durch das Sieb unten, und der
|
|
380
|
+
Wechsel scheiterte still (Ricardo). Die automatische Erkennung ruft ohne
|
|
381
|
+
die Fahne auf und bleibt unveraendert — dort waere ein Entwurf ohne eine
|
|
382
|
+
einzige Zeile ein Fehlgriff. */
|
|
383
|
+
export function wendeAn(v, kanal, gruende, instanz, auchOhneTreffer) {
|
|
375
384
|
var auf = function (t) { return setzeInstanz(t, v, instanz); };
|
|
376
385
|
var e = { kanal: kanal, states: [], want: v.geraetetyp, wantAuto: v.geraetetyp,
|
|
377
386
|
alleMuster: false, vorschlag: true, roh: false,
|
|
@@ -499,7 +508,7 @@ export function wendeAn(v, kanal, gruende, instanz) {
|
|
|
499
508
|
});
|
|
500
509
|
});
|
|
501
510
|
|
|
502
|
-
return e.states.length ? e : null;
|
|
511
|
+
return (e.states.length || auchOhneTreffer) ? e : null;
|
|
503
512
|
}
|
|
504
513
|
|
|
505
514
|
/* Beste Vorlage suchen und anwenden. */
|
|
@@ -521,7 +530,7 @@ export function vorschlag(kanal, vorlagenId, instanz) {
|
|
|
521
530
|
gewaehlt = treffer[0];
|
|
522
531
|
}
|
|
523
532
|
|
|
524
|
-
var e = wendeAn(gewaehlt.vorlage, kanal, gewaehlt.gruende, gewaehlt.instanz);
|
|
533
|
+
var e = wendeAn(gewaehlt.vorlage, kanal, gewaehlt.gruende, gewaehlt.instanz, !!vorlagenId);
|
|
525
534
|
if (!e) { return null; }
|
|
526
535
|
if (!vorlagenId && gewaehlt.passt) {
|
|
527
536
|
var gleichAuf = treffer.filter(function (t) { return t.punkte === gewaehlt.punkte; });
|
package/admin/js/werte.js
CHANGED
|
@@ -93,6 +93,26 @@ export function holeWerte(kanal, extraIds, fertig) {
|
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
/* Nur diese Kennungen, ohne den Rundumschlag ueber einen Kanal.
|
|
97
|
+
|
|
98
|
+
Gebraucht dort, wo Zeilen erst spaeter dazukommen und ihre Quelle
|
|
99
|
+
ausserhalb des angeklickten Knotens liegt - dann ist der Kanal
|
|
100
|
+
laengst abgefragt, und ein zweites `getForeignStates` darauf braechte
|
|
101
|
+
nichts als Last. */
|
|
102
|
+
export function holeEinzelne(ids, fertig) {
|
|
103
|
+
var eindeutig = {};
|
|
104
|
+
(ids || []).forEach(function (i) { if (i) { eindeutig[i] = 1; } });
|
|
105
|
+
var liste = Object.keys(eindeutig);
|
|
106
|
+
if (!liste.length) { if (typeof fertig === 'function') { fertig(false); } return; }
|
|
107
|
+
var offen = liste.length, etwas = false;
|
|
108
|
+
liste.forEach(function (id) {
|
|
109
|
+
socket.emit('getState', id, function (err, st) {
|
|
110
|
+
if (!err && st) { S.werte[id] = st; etwas = true; }
|
|
111
|
+
if (--offen <= 0 && typeof fertig === 'function') { fertig(etwas); }
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
96
116
|
/* ================== Formel und Wert ================== */
|
|
97
117
|
export function auswerten(formel, roh) {
|
|
98
118
|
if (roh === undefined || roh === null) { return { ok: false, txt: tr('detail.noValue') }; }
|
package/admin/js/zielleiste.js
CHANGED
|
@@ -11,8 +11,9 @@ 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 } from './entwurf.js';
|
|
14
|
+
import { aliasFuer, ordnerUnterAlias, kennungtauglich, knotenDa } from './entwurf.js';
|
|
15
15
|
import { zeichneErgebnis, entwurfAngefasst, angebotFrisch } from './ergebnis.js';
|
|
16
|
+
import { zeigeVerlegen } from './schreiben.js';
|
|
16
17
|
|
|
17
18
|
export function baueZielleiste(host, e) {
|
|
18
19
|
var istQuelle = S.current.indexOf('alias.') !== 0;
|
|
@@ -224,7 +225,23 @@ export function baueZielleiste(host, e) {
|
|
|
224
225
|
});
|
|
225
226
|
iO.addEventListener('change', uebernehmen);
|
|
226
227
|
iO.addEventListener('keydown', function (ev) {
|
|
227
|
-
|
|
228
|
+
/* Escape heisst „doch nicht" — die Liste zu machen reicht dafuer
|
|
229
|
+
nicht, der getippte Text muss auch weg. Sonst steht er weiter im
|
|
230
|
+
Feld und wird beim Verlassen uebernommen: Wer Escape drueckt und
|
|
231
|
+
danebenklickt, legt den Alias unter einem Ordner an, den er
|
|
232
|
+
gerade verworfen zu haben glaubte.
|
|
233
|
+
|
|
234
|
+
Musterfeld (`musterwahl.js`, ruft mBeschriften) und
|
|
235
|
+
Aufzaehlungsfeld (`zuordnung.js`, setzt ei.value zurueck) machen
|
|
236
|
+
das laengst; hier und im Namensfeld daneben fehlte es
|
|
237
|
+
(Ricardo, 06.09.2026). */
|
|
238
|
+
if (ev.key === 'Escape') {
|
|
239
|
+
iO.value = (e.zielOrdner === 'alias.0') ? '' : e.zielOrdner.slice('alias.0.'.length);
|
|
240
|
+
xBtn.hidden = !iO.value;
|
|
241
|
+
schliessen();
|
|
242
|
+
iO.blur();
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
228
245
|
if (ev.key === 'ArrowDown' || ev.key === 'ArrowUp') {
|
|
229
246
|
if (vlist.hidden) { malen(true); return; }
|
|
230
247
|
ev.preventDefault();
|
|
@@ -263,6 +280,14 @@ export function baueZielleiste(host, e) {
|
|
|
263
280
|
var iN2 = el('input', 'tx');
|
|
264
281
|
iN2.type = 'text';
|
|
265
282
|
iN2.value = e.zielName;
|
|
283
|
+
/* Dasselbe fuer den Namen. Hier gab es bisher gar keinen
|
|
284
|
+
Tastenhandler — Escape tat nichts, der getippte Name blieb stehen
|
|
285
|
+
und wurde beim Verlassen uebernommen (Ricardo, 06.09.2026). */
|
|
286
|
+
iN2.addEventListener('keydown', function (ev) {
|
|
287
|
+
if (ev.key !== 'Escape') { return; }
|
|
288
|
+
iN2.value = e.zielName;
|
|
289
|
+
iN2.blur();
|
|
290
|
+
});
|
|
266
291
|
iN2.addEventListener('change', function () {
|
|
267
292
|
/* Dieselbe Regel wie im Vorschlag und im Verlege-Dialog. Die eigene
|
|
268
293
|
Fassung hier liess Punkte und doppelte Unterstriche stehen - ein
|
|
@@ -278,7 +303,10 @@ export function baueZielleiste(host, e) {
|
|
|
278
303
|
/* Beide Faelle, an einer Stelle. Vorher stand „wird neu angelegt"
|
|
279
304
|
oben im Kopf und „gibt es schon" hier — zwei Formulierungen fuer
|
|
280
305
|
dieselbe Auskunft, an zwei Orten. */
|
|
281
|
-
|
|
306
|
+
/* `knotenDa`, nicht `S.objects`: ein Alias, dessen Punkte von Hand
|
|
307
|
+
angelegt wurden, hat oft kein Kanalobjekt - der Chip meldete dort
|
|
308
|
+
„wird neu angelegt", obwohl geaendert wird (Ricardo, 08.09.2026). */
|
|
309
|
+
var gibtsZiel = knotenDa(e.ziel);
|
|
282
310
|
var ch2 = el('span', 'chip ' + (gibtsZiel ? 'warn' : 'ok'),
|
|
283
311
|
gibtsZiel ? tr('target.exists') : tr('result.newlyCreated'));
|
|
284
312
|
ch2.style.marginLeft = '7px';
|
|
@@ -291,7 +319,13 @@ export function baueZielleiste(host, e) {
|
|
|
291
319
|
Aenderung folgen, und der Blick ist beim angefassten Feld, nicht
|
|
292
320
|
beim anderen. Der Text nennt deshalb die Wirkung woanders. */
|
|
293
321
|
var angebot = null;
|
|
294
|
-
|
|
322
|
+
/* Frueher hing hier zusaetzlich `!aliasFuer(e.kanal)` - an einem
|
|
323
|
+
Geraet, das schon einen Alias hat, kam die Frage also nie. Gedacht
|
|
324
|
+
war das als „am fertigen Alias wird nicht mehr geraten"; in
|
|
325
|
+
Wahrheit ist gerade das der Fall, in dem sie gebraucht wird: wer
|
|
326
|
+
den Ordner eines vorhandenen Alias umschreibt, zieht um, und der
|
|
327
|
+
Raum soll mit (Ricardo, 06.09.2026). */
|
|
328
|
+
if (e.zuletzt === 'ordner') {
|
|
295
329
|
var otx = String(e.zielOrdner || '').slice('alias.0.'.length);
|
|
296
330
|
if (otx && otx.indexOf('.') === -1) {
|
|
297
331
|
var vorhandenerRaum = enumListe('rooms', true).filter(function (r) {
|
|
@@ -322,6 +356,42 @@ export function baueZielleiste(host, e) {
|
|
|
322
356
|
setTimeout(function () { iO.focus(); }, 0);
|
|
323
357
|
}
|
|
324
358
|
|
|
359
|
+
/* Der Zwilling: es gibt schon einen Alias auf diese Quelle, und das
|
|
360
|
+
Ziel zeigt woandershin.
|
|
361
|
+
|
|
362
|
+
Die Werkbank weiss das in diesem Moment - `aliasFuer` liefert den
|
|
363
|
+
alten Pfad -, sagte es aber nirgends. Am Chip stand nur „wird neu
|
|
364
|
+
angelegt", was stimmt und die Haelfte verschweigt: der alte bleibt
|
|
365
|
+
stehen, und aus einem Umbenennen des Ordners wird lautlos ein
|
|
366
|
+
zweiter Alias auf dieselbe Quelle (Ricardo, 06.09.2026, am
|
|
367
|
+
Bastelzimmer_Decklenlicht_RGB).
|
|
368
|
+
|
|
369
|
+
Verboten wird nichts. Zwei Aliase auf eine Quelle sind ein
|
|
370
|
+
ordentlicher Fall - einer fuers Licht, einer fuer den Verbrauch;
|
|
371
|
+
„alle anlegen" tut bei mehreren Ausgaengen nichts anderes. Es
|
|
372
|
+
fehlte die Auskunft, nicht die Sperre. Wer wirklich einen zweiten
|
|
373
|
+
will, drueckt denselben Knopf wie bisher und weiss jetzt, was er
|
|
374
|
+
tut; wer umziehen wollte, hat den Weg dafuer daneben.
|
|
375
|
+
|
|
376
|
+
Ohne Rueckprobe ueber `quelleVon`: an einem Homematic-Kanal
|
|
377
|
+
(…B8AF.0) zeigt die Quelle des Alias auf das Geraet (…B8AF), die
|
|
378
|
+
Probe schluege fehl und der Hinweis bliebe genau dort aus, wo er
|
|
379
|
+
gebraucht wird. `aliasFuer` ist dieselbe Funktion, mit der die
|
|
380
|
+
Werkbank auch „zum Alias →" und ihre Zielvorschlaege bestimmt -
|
|
381
|
+
irrt sie hier, irrt sie dort ebenso. Und der Hinweis haelt
|
|
382
|
+
niemanden auf. */
|
|
383
|
+
var zwilling = null;
|
|
384
|
+
var vorhAlias = aliasFuer(e.kanal);
|
|
385
|
+
if (vorhAlias && S.objects[vorhAlias] && vorhAlias !== e.ziel) {
|
|
386
|
+
var zw = el('div', 'uebernahme zwilling');
|
|
387
|
+
zw.appendChild(el('span', 'zq', tr('target.twinExists', vorhAlias)));
|
|
388
|
+
var vb = el('button', 'btn mini', tr('target.moveInstead'));
|
|
389
|
+
vb.title = tr('target.moveInsteadHint');
|
|
390
|
+
vb.addEventListener('click', function () { zeigeVerlegen(vorhAlias, e.ziel); });
|
|
391
|
+
zw.appendChild(vb);
|
|
392
|
+
zwilling = zw;
|
|
393
|
+
}
|
|
394
|
+
|
|
325
395
|
/* Das Angebot ganz ans Ende der Leiste.
|
|
326
396
|
|
|
327
397
|
Zuerst hing es direkt hinter dem Ordnerfeld - und weil es eine
|
|
@@ -329,6 +399,7 @@ export function baueZielleiste(host, e) {
|
|
|
329
399
|
Namensfeld stand ploetzlich darunter statt daneben. Eine Zeile,
|
|
330
400
|
die umbricht, gehoert hinter das, was in der Zeile bleiben soll. */
|
|
331
401
|
if (angebot) { zb.appendChild(angebot); }
|
|
402
|
+
if (zwilling) { zb.appendChild(zwilling); }
|
|
332
403
|
|
|
333
404
|
zb.appendChild(ergebnis);
|
|
334
405
|
|
package/admin/js/zuordnung.js
CHANGED
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
} from './aufzaehlungen.js';
|
|
15
15
|
import { enumVorlagen, katalogFehlt, ikonCache, ikonErlaubt, ikonNachtrag,
|
|
16
16
|
ikonTaugt, vorlageZu, holeIkon } from './katalog.js';
|
|
17
|
-
import { kindZustaende, aliasQuellen } from './werte.js';
|
|
18
|
-
import { aliasFuer, zielId } from './entwurf.js';
|
|
17
|
+
import { kindZustaende, aliasQuellen, holeEinzelne } from './werte.js';
|
|
18
|
+
import { aliasFuer, zielId, knotenDa } from './entwurf.js';
|
|
19
19
|
import { zeichneErgebnis, entwurfAngefasst, angebotFrisch } from './ergebnis.js';
|
|
20
20
|
|
|
21
21
|
|
|
@@ -394,7 +394,11 @@ export function enumZeile(host, e) {
|
|
|
394
394
|
export function setzeEnums(e) {
|
|
395
395
|
if (e.raum !== undefined && e.funktion !== undefined) { return; }
|
|
396
396
|
var ziel = e.ziel || e.kanal;
|
|
397
|
-
|
|
397
|
+
/* Gibt es den Alias, gelten SEINE Aufzaehlungen - auch wenn sein Kanal
|
|
398
|
+
kein eigenes Objekt hat. Sonst wurden Raum und Funktion geraten und
|
|
399
|
+
als „vorgeschlagen" angezeigt, obwohl beide laengst zugeordnet
|
|
400
|
+
waren (Ricardo, 08.09.2026). */
|
|
401
|
+
var da = knotenDa(ziel);
|
|
398
402
|
|
|
399
403
|
if (e.raum === undefined) {
|
|
400
404
|
var r = da ? (enumsVon(ziel, 'rooms')[0] || '') : '';
|
|
@@ -499,7 +503,21 @@ export function setzeZiel(e) {
|
|
|
499
503
|
export function uebernehmeBestand(e) {
|
|
500
504
|
if (!e.ziel || e.bestandGeprueft === e.ziel) { return; }
|
|
501
505
|
e.bestandGeprueft = e.ziel;
|
|
502
|
-
|
|
506
|
+
/* Gefragt ist, ob es unter dem Ziel schon einen Alias gibt - nicht, ob
|
|
507
|
+
das Ziel selbst ein Objekt ist. Das ist nicht dasselbe: wer seine
|
|
508
|
+
Punkte von Hand im Admin anlegt, bekommt `alias.0.X.Y.PUNKT`, ohne
|
|
509
|
+
dass `alias.0.X.Y` als Kanal entsteht. Der Baum zeigt so einen
|
|
510
|
+
Knoten trotzdem, weil er sich aus den Kennungen aufbaut - `knotenDa`
|
|
511
|
+
ist genau dafuer da.
|
|
512
|
+
|
|
513
|
+
Mit der alten Frage stieg der ganze Bestandsabgleich dort aus:
|
|
514
|
+
`alias.0.Bastelzimmer.Klima` und `alias.0.Solar.Einstellungen.Bilanz`
|
|
515
|
+
haben kein Kanalobjekt, und ein Aktualisieren haette ihre Namen
|
|
516
|
+
durch die blossen Punktnamen ersetzt - „Strompreis fuer die
|
|
517
|
+
Ersparnisrechnung" waere zu „Strompreis_ct_kWh" geworden. Rollen,
|
|
518
|
+
Formeln und Schreibrichtung waeren ebenso durchgefallen
|
|
519
|
+
(Ricardo, 08.09.2026). */
|
|
520
|
+
if (!knotenDa(e.ziel)) { return; }
|
|
503
521
|
/* Im Aliasmodus ist der Entwurf schon der Bestand. */
|
|
504
522
|
if (e.kanal === e.ziel) { return; }
|
|
505
523
|
|
|
@@ -533,9 +551,35 @@ export function uebernehmeBestand(e) {
|
|
|
533
551
|
z.states = c.states || undefined;
|
|
534
552
|
z.f = (typeof a.read === 'string') ? a.read : '';
|
|
535
553
|
z.fw = (typeof a.write === 'string') ? a.write : '';
|
|
554
|
+
/* Die Beschriftung steht im Alias und gehoert dem Nutzer.
|
|
555
|
+
|
|
556
|
+
Sie fehlte hier als einzige - `bestandVorrang` holt sie laengst
|
|
557
|
+
(`s.caption = txt(c.name)`), diese Zwillingsfunktion nicht. Also
|
|
558
|
+
blieb `caption` leer, im aufgeklappten Feld stand nichts, und ein
|
|
559
|
+
„Alias aktualisieren" haette den Namen durch den blossen
|
|
560
|
+
Zeilennamen ersetzt: aus „Netzbezug (+) / Einspeisung (-)" waere
|
|
561
|
+
„Bezug" geworden (Ricardo, 07.09.2026, an alias.0.Solar.Netz).
|
|
562
|
+
Gleicht die Beschriftung dem Zeilennamen, bleibt sie leer - so
|
|
563
|
+
haelt es der Zweig darunter, der neue Zeilen anlegt, auch. */
|
|
564
|
+
var nm2 = txt(c.name);
|
|
565
|
+
z.caption = (nm2 && nm2 !== z.n) ? nm2 : '';
|
|
536
566
|
if (q2.read) { z.srcR = q2.read; }
|
|
567
|
+
/* Und dieselbe Schreibregel wie im Bestandsvorrang.
|
|
568
|
+
|
|
569
|
+
Hier stand die Schreibquelle nur fuer das getrennte Paar; sonst
|
|
570
|
+
blieb stehen, was der Vorschlag aus der Quelle abgeleitet hatte.
|
|
571
|
+
Bei einem Nur-Lese-Alias auf einen beschreibbaren Punkt hiess das:
|
|
572
|
+
die Quelle sagt `write: true`, der Alias sagt `write: false` - und
|
|
573
|
+
die Werkbank meldete eine Abweichung, die sie selbst erzeugt hatte,
|
|
574
|
+
und haette den Alias beim Aktualisieren schreibbar gemacht.
|
|
575
|
+
|
|
576
|
+
Belegt ist das Schreiben durch `common.write` oder durch eine
|
|
577
|
+
hinterlegte Schreibformel; bei getrennten Quellen zaehlt, was in
|
|
578
|
+
`alias.id.write` steht. */
|
|
579
|
+
z.srcW = q2.einfach
|
|
580
|
+
? ((c.write === true || typeof a.write === 'string') ? (q2.write || '') : '')
|
|
581
|
+
: (q2.write || '');
|
|
537
582
|
if (q2.write && !q2.einfach && q2.write !== q2.read) {
|
|
538
|
-
z.srcW = q2.write;
|
|
539
583
|
/* Die Gegenzeile eines Paars ist keine eigene mehr - ihre Quelle
|
|
540
584
|
steckt jetzt als Schreibquelle in dieser Zeile. */
|
|
541
585
|
e.states.forEach(function (x) {
|
|
@@ -577,6 +621,21 @@ export function uebernehmeBestand(e) {
|
|
|
577
621
|
stehen; neue Punkte bekommen den neuen Namen. */
|
|
578
622
|
if (q.read && kenntQuelle[q.read] && !S.objects[e.ziel + '.' + kenntQuelle[q.read].n]) {
|
|
579
623
|
var vorhanden = kenntQuelle[q.read];
|
|
624
|
+
/* Die Zeile bekommt den Namen aus dem Alias — und damit einen
|
|
625
|
+
anderen, als die Erkennung eben gesehen hat. `platzVon` kennt
|
|
626
|
+
noch den Vorlagennamen, die Zeile heisst jetzt anders, und die
|
|
627
|
+
Platzpruefung findet nichts: Am `Bastelzimmer_Licht` stand nach
|
|
628
|
+
einem Wechsel auf die Steckdosen-Vorlage „kein Platz im
|
|
629
|
+
Steckdose-Muster" an ON_ACTUAL, obwohl der Platz ACTUAL frei
|
|
630
|
+
besetzt war. Nach jedem beliebigen Neuzeichnen war es weg
|
|
631
|
+
(Ricardo, 06.09.2026).
|
|
632
|
+
|
|
633
|
+
`bestandZog` loest genau dafuer das einmalige Nachzeichnen aus.
|
|
634
|
+
Gesetzt wurde es bisher nur in `vomAliasUebernehmen` — und das
|
|
635
|
+
steigt bei gesetzter Vorlage sofort aus, damit der Vorlagenstand
|
|
636
|
+
gilt. Die Umbenennung findet aber trotzdem statt, also gehoert
|
|
637
|
+
die Fahne hierher. */
|
|
638
|
+
if (vorhanden.n !== n) { e.bestandZog = true; }
|
|
580
639
|
vorhanden.n = n;
|
|
581
640
|
vorhanden.on = true;
|
|
582
641
|
vorhanden.ausBestand = true;
|
|
@@ -590,7 +649,22 @@ export function uebernehmeBestand(e) {
|
|
|
590
649
|
role: c.role || '', typ: c.type || '', unit: c.unit || '',
|
|
591
650
|
states: c.states || undefined,
|
|
592
651
|
wr: !!c.write,
|
|
593
|
-
srcR: q.read || '',
|
|
652
|
+
srcR: q.read || '',
|
|
653
|
+
/* Dieselbe Schreibregel wie oben und im Bestandsvorrang.
|
|
654
|
+
|
|
655
|
+
Hier stand `q.einfach ? '' : (q.write || '')` - bei schlichtem
|
|
656
|
+
`alias.id` also immer leer, ohne `common.write` ueberhaupt
|
|
657
|
+
anzusehen. Es trifft jeden Alias, bei dem MEHRERE Punkte auf
|
|
658
|
+
denselben Quellpunkt zeigen: die eine Vorschlagszeile bekommt
|
|
659
|
+
der erste von ihnen, alle weiteren landen hier. Am
|
|
660
|
+
`alias.0.Badezimmer.Rollladen` zeigen OPEN, CLOSE, SET und pct
|
|
661
|
+
alle auf `…Bad.level`; CLOSE lief oben durch und behielt seine
|
|
662
|
+
Schreibquelle, OPEN, SET und pct verloren sie - ein
|
|
663
|
+
Aktualisieren haette den Rollladen ueber den Alias unfahrbar
|
|
664
|
+
gemacht (Ricardo, 08.09.2026). */
|
|
665
|
+
srcW: q.einfach
|
|
666
|
+
? ((c.write === true || typeof a.write === 'string') ? (q.write || '') : '')
|
|
667
|
+
: (q.write || ''),
|
|
594
668
|
f: (typeof a.read === 'string') ? a.read : '',
|
|
595
669
|
fw: (typeof a.write === 'string') ? a.write : '',
|
|
596
670
|
caption: (nm && nm !== n) ? nm : '',
|
|
@@ -612,6 +686,38 @@ export function uebernehmeBestand(e) {
|
|
|
612
686
|
e.bestandNachgezeichnet = true;
|
|
613
687
|
setTimeout(function () { if (S.entwurf === e) { zeichneErgebnis(); } }, 0);
|
|
614
688
|
}
|
|
689
|
+
|
|
690
|
+
/* Und die Werte zu den eben ergaenzten Zeilen nachholen.
|
|
691
|
+
|
|
692
|
+
`waehle` holt die Werte, bevor es diese Zeilen ueberhaupt gibt: es
|
|
693
|
+
fragt den angeklickten Kanal ab und die Quellen, die der Entwurf zu
|
|
694
|
+
dem Zeitpunkt kennt. Was hier dazukommt, steht nur im Alias - und
|
|
695
|
+
seine Quelle kann irgendwo liegen. Solange sie unter demselben
|
|
696
|
+
Knoten liegt, faellt nichts auf, weil `getForeignStates` sie
|
|
697
|
+
mitgenommen hat. Liegt sie woanders, blieb die Zeile ohne Wert und
|
|
698
|
+
behauptete „Quelle liefert nichts", obwohl der Alias einwandfrei
|
|
699
|
+
arbeitet.
|
|
700
|
+
|
|
701
|
+
Gefunden am 07.09.2026 (Ricardo) an `alias.0.Solar.Netz`: drei
|
|
702
|
+
Punkte aus `0_userdata`, zwei aus `mqtt-client`. Nach einem
|
|
703
|
+
Reiterwechsel und dem ersten Klick auf den Knoten standen genau die
|
|
704
|
+
beiden mqtt-Zeilen leer; ein zweiter Klick heilte es, weil der Wert
|
|
705
|
+
dann schon im Vorrat lag. Der Mitschnitt zeigte, dass nach der
|
|
706
|
+
mqtt-Kennung nie gefragt wurde.
|
|
707
|
+
|
|
708
|
+
Einmal je Entwurf, und nur, wenn wirklich etwas fehlt. */
|
|
709
|
+
if (!e.bestandWerte) {
|
|
710
|
+
var fehlen = [];
|
|
711
|
+
e.states.forEach(function (s) {
|
|
712
|
+
if (s.srcR && !S.werte[s.srcR] && fehlen.indexOf(s.srcR) === -1) { fehlen.push(s.srcR); }
|
|
713
|
+
});
|
|
714
|
+
if (fehlen.length) {
|
|
715
|
+
e.bestandWerte = true;
|
|
716
|
+
holeEinzelne(fehlen, function (etwas) {
|
|
717
|
+
if (etwas && S.entwurf === e) { zeichneErgebnis(); }
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
}
|
|
615
721
|
}
|
|
616
722
|
|
|
617
723
|
export function unterschiede(e) {
|
|
@@ -652,7 +758,7 @@ export function unterschiede(e) {
|
|
|
652
758
|
Grundlinie — dann zaehlt, was sich gegenueber dem Gespeicherten
|
|
653
759
|
aendert. Gibt es ihn noch nicht, ist es der Vorschlag der
|
|
654
760
|
Vorlage. */
|
|
655
|
-
var aliasDa =
|
|
761
|
+
var aliasDa = knotenDa(zielBasis);
|
|
656
762
|
|
|
657
763
|
e.states.forEach(function (s) {
|
|
658
764
|
if (s.manuell) { raus.push({ n: s.n || '(ohne Namen)', was: tr('diff.newByHand') }); return; }
|