iobroker.alias-workbench 0.10.0 → 0.11.0

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.
Files changed (49) hide show
  1. package/README.md +39 -91
  2. package/admin/css/werkbank.css +15 -0
  3. package/admin/i18n/de.json +701 -1
  4. package/admin/i18n/en.json +701 -1
  5. package/admin/i18n/es.json +701 -1
  6. package/admin/i18n/fr.json +701 -1
  7. package/admin/i18n/it.json +701 -1
  8. package/admin/i18n/nl.json +701 -1
  9. package/admin/i18n/pl.json +701 -1
  10. package/admin/i18n/pt.json +701 -1
  11. package/admin/i18n/ru.json +701 -1
  12. package/admin/i18n/uk.json +701 -1
  13. package/admin/i18n/zh-cn.json +701 -1
  14. package/admin/js/ablage.js +118 -0
  15. package/admin/js/detail.js +64 -3
  16. package/admin/js/entwurf.js +116 -28
  17. package/admin/js/katalog.js +235 -40
  18. package/admin/js/mqtt.js +297 -27
  19. package/admin/js/musternamen.js +70 -26
  20. package/admin/js/objekte.js +2 -0
  21. package/admin/js/schreiben.js +3 -2
  22. package/admin/js/sprache.js +7 -8
  23. package/admin/js/vorlagen.js +8 -3
  24. package/admin/js/vorlagenblatt.js +228 -64
  25. package/admin/js/werte.js +294 -5
  26. package/admin/js/zielleiste.js +19 -10
  27. package/admin/js/zuordnung.js +8 -7
  28. package/admin/js/zustand.js +4 -0
  29. package/admin/js/zustandsliste.js +9 -2
  30. package/admin/vorlagen/hm-dimmer.json +32 -8
  31. package/admin/vorlagen/hm-fensterkontakt-hm.json +20 -5
  32. package/admin/vorlagen/hm-fensterkontakt-hmip.json +28 -7
  33. package/admin/vorlagen/hm-heizgruppe.json +38 -11
  34. package/admin/vorlagen/hm-heizkoerper.json +42 -12
  35. package/admin/vorlagen/hm-rollladen.json +28 -7
  36. package/admin/vorlagen/hm-schaltaktor-lampe.json +24 -6
  37. package/admin/vorlagen/hm-schaltaktor-mehrfach.json +32 -8
  38. package/admin/vorlagen/hm-schaltaktor-steckdose.json +24 -6
  39. package/admin/vorlagen/hm-temperatur-feuchte.json +8 -2
  40. package/admin/vorlagen/hm-wandthermostat.json +36 -9
  41. package/admin/vorlagen/messpunkt.json +40 -10
  42. package/admin/vorlagen/tasmota-lampe.json +48 -12
  43. package/admin/vorlagen/tasmota-mehrfach.json +40 -10
  44. package/admin/vorlagen/tasmota-rgb.json +36 -9
  45. package/admin/vorlagen/tasmota-steckdose.json +56 -14
  46. package/io-package.json +28 -15
  47. package/package.json +2 -2
  48. package/admin/sprachen/de.json +0 -685
  49. package/admin/sprachen/en.json +0 -685
package/README.md CHANGED
@@ -565,12 +565,10 @@ served as they are; editing one and reloading the tab is the whole cycle. On a
565
565
  running installation the admin caches adapter files, so `iobroker upload
566
566
  alias-workbench` after copying is what makes the browser see the change.
567
567
 
568
- There are two dictionaries. `admin/i18n/` belongs to the **settings page**
569
- (jsonConfig with `"i18n": true`, all eleven languages, loaded by the admin
570
- itself). `admin/sprachen/` belongs to the **tab** (German and English, loaded by
571
- `admin/js/sprache.js`; any other language falls back to English). A new tab
572
- language is a new file in `admin/sprachen/` and an entry in `SPRACHEN` in
573
- `admin/js/sprache.js` — nothing else. Watch for strings
568
+ There is one dictionary, `admin/i18n/`, all eleven languages. The admin loads
569
+ it for the settings page (`jsonConfig` with `"i18n": true`). The tab loads the
570
+ same files from `admin/js/sprache.js`. A language that is not in the list falls
571
+ back to English. Watch for strings
574
572
  written straight into `admin/tab.html`: they are replaced at runtime, and one
575
573
  that nobody wired up stays English in every language without anyone noticing.
576
574
 
@@ -579,7 +577,7 @@ modules — there is no build step for them, and styling lives in one file,
579
577
  `admin/css/werkbank.css`. Because a module boundary can be crossed wrongly in
580
578
  ways the browser only notices while running, `npm test` checks before every
581
579
  commit that everything still bundles, that every identifier is declared or
582
- imported, and that both language files carry the same keys.
580
+ imported, and that all eleven language files carry the same keys.
583
581
 
584
582
  ## Background
585
583
 
@@ -592,6 +590,39 @@ imported, and that both language files carry the same keys.
592
590
 
593
591
  ## Changelog
594
592
 
593
+ ### 0.11.0 (2026-10-11)
594
+ **Templates**
595
+ * **Template notes are German and English.** The description, the recognition note and each row note are `{ "de", "en" }`. The tab shows the admin language, otherwise English, otherwise German. The name hint stays one search pattern (`licht|lampe|light|…`): it matches the device name, which does not follow the admin language.
596
+ * **One dictionary for the settings page and the tab.** Both live in `admin/i18n/`, all eleven languages, the same keys. The tab loads that same file. An unknown language falls back to English. The tab used to keep its own dictionary at `admin/sprachen/`, German and English only.
597
+
598
+ **Identifiers**
599
+ * **Object ids no longer contain umlauts.** An id may only contain unaccented letters, digits, `-` and `_`. `Küche` in the name field becomes `Kueche` (`ä`/`Ä` to `ae`/`Ae`, `ö`/`Ö` to `oe`/`Oe`, `ü`/`Ü` to `ue`/`Ue`, `ß` to `ss`). The same applies to "Place under", the move dialog and the name of a new point. Dots in the folder field stay, they separate the levels. An alias whose id already contains an umlaut is left as it is, until the name field is left again.
600
+ * **Rooms and functions keep the umlaut.** The room is still called `Wohnküche`. When the folder is taken from it, the folder is `Wohnkueche` and the path is `alias.0.Wohnkueche.…`.
601
+ * **Typing a folder by hand does not rename the room suggestion.** `Küche` in "Place under" becomes the folder `Kueche`. The question below still names the room `Küche`. Confirming it creates `enum.rooms.Küche`, not `enum.rooms.Kueche`.
602
+
603
+ **Value list and thermostats**
604
+ * **Shipped templates can now be opened row by row**, read-only. Until now the row view was reserved for your own templates: to see which fallback sources, formulas or notes a shipped one carries, you had to make an own copy first — and were left with a copy you never wanted. Every field in the block is disabled, so no working copy is created by looking.
605
+ * The **‚must be present‘ mark** now shows whether the row itself is mandatory, not whether its read path appears in the recognition list — two different questions that had been shown under one word. At the HmIP heating group one row was marked where four are mandatory; the Tasmota templates marked none at all. The same applied to the checkbox in the expanded row, so there was nowhere in the interface showing the truth. Counted across all 16 templates, 15 now show a different number — each matching what the template file says.
606
+ * That checkbox also **silently edited the recognition list**. Ticking SET on the Tasmota light template would have bound it to `stat.POWER`, a point the MQTT adapter only creates once the device has been switched at least once. It now sets only what it says; the recognition list is edited in its own field above.
607
+ * The row overview marks rows that have **fallback read paths** („+3 fallback“). Previously only the first path was shown and the others were invisible until the row was expanded.
608
+ * The **device type** field in the template sheet is now a search field with its own list instead of a 52-entry dropdown. Typing searches both names — `socket` and `Steckdose` both find it — just as the pattern chooser has always done. A dropdown cannot be searched, and since the label starts with the translated name, the browser’s type-ahead never found the raw one.
609
+ * The detail row now has a **value list** field (`common.states`). Until now it could only be inherited from a template — not seen, not created, not changed, although the workbench wrote it all along. Where the source carries one and the draft does not, a button offers to take it over, and "yields" shows the text for the value instead of the bare number. Both deviation comparisons include it; against the existing object in both directions, so a list can no longer disappear silently.
610
+ * **Fixed**: the HmIP radiator and heating-group templates read the valve opening from `1.VALVE_STATE`. On HmIP that is a state code 0-8 (ADAPTION_DONE, TOO_TIGHT, ERROR_POSITION, …), not a percentage — a thermostat reporting code 4 showed "4 %". They now read `1.LEVEL`, which the radiator template already required for detection anyway.
611
+
612
+ **MQTT**
613
+ * The card now says whether the device is reporting: a red "offline" chip when the broker published the last will, a yellow "not reporting" chip when the device claims to be online but no telemetry has arrived within three telemetry periods, and nothing at all when there is no information. Only an explicit offline counts as offline — other firmwares use other words, and an unknown one means "do not know", not "gone". A retained "Online" can be years old: a device that runs for a year never repeats it.
614
+ * "Ask the device" now also fetches the device IP and the telemetry period, and the button appears whenever one of the three is missing — not only when the command list is incomplete. Neither is reported by the device on its own: the IP only in `tele/INFO2` (sent once at boot) or `stat/STATUS5` (on request), the period only on request. Previously a device with a complete command list offered no button at all, so there was no way to get either.
615
+ * The telemetry period was read from `tele/STATE`, where Tasmota does not put it — measured across 36 devices, not one carried the field. It is now asked for and remembered, so the SetOption59 hint names the real number instead of leaving it out.
616
+ * `Status 5` is now requested twice, like `Status 11`: on first contact the MQTT adapter only creates the answer object and discards the value. Captured on the broker — the answer was published, the value never arrived.
617
+ * A Tasmota using the factory FullTopic `%prefix%/%topic%/` is now treated as one device. The MQTT adapters map the topic straight onto the object path, so such a device is spread over `tele.<name>`, `stat.<name>` and `cmnd.<name>` with no node holding it together — the MQTT card did not appear, and a send point created one level up would have been shared with the next device on the same prefix. Both layouts now yield the same relative names, so the shipped templates apply unchanged, and the card says how many branches were joined.
618
+ * Only the factory prefixes `cmnd`/`stat`/`tele` count as a prefix. A structural fallback for renamed ones turned out to merge unrelated nodes — measured against a live installation it joined the L1 phases of eight different AC sources into one device — and Victron data and a renamed Tasmota are indistinguishable in the object tree.
619
+ **Admin enumerations**
620
+ * **The room and function catalogue works again under Admin 8.0.x.** Admin ships 58 room and 62 function templates, translated and with icons; the workbench reads them from its bundles instead of keeping a copy of its own. Since Admin 8.0.x they sit elsewhere and in a different notation — no longer as JSON text in a dedicated "Enums" chunk, but as plain JavaScript inside a shared module of nearly eight megabytes. Two things were in the way: a three-megabyte size limit skipped exactly the right file, and the search pattern required `JSON.parse`. Both notations are now read. Anyone who saw only the existing entries instead of 120 templates under Admin 8 gets them back; under Admin 7 nothing changes.
621
+ * The result is then kept **in the adapter's file area** and is only fetched again when Admin rewrites its bundles — recognised by the bundle names rather than the version number, so an interim build is noticed too. While it is being fetched, a note in the bottom right explains why it takes a few seconds that one time. For storage the workbench creates an `alias-workbench.0` object of type `meta` on first use; the file area does not exist otherwise, because the workbench has no backend.
622
+ * **The pattern names now come from the store as well.** `socket` → “Socket” is also taken from Admin, because the type detector only knows raw type names — and since Admin 8 that map sits in the same shared module as the room catalogue. Both now share one store, so it is fetched once instead of twice. Measured on the second opening of the tab: **404 instead of 2,255 KB under Admin 8.0.14**, 419 instead of 864 KB under Admin 7.8.23, with no request above 100 KB in either case. Both interface languages are taken along, so switching language does not trigger the fetch again.
623
+ * **Fixed: the “n sources” chip counted one device twice** when an alias reads from two nodes, one of which sits below the other. Until now only siblings were merged — so `…Solar_Balkon.stat` and `…Solar_Balkon.tele` were, but `…inverter.HM600.ch0` and `…inverter.HM600` were not. `Solar.Balkon.Einspeisung` therefore showed “4 sources” although the HM600 is a single inverter. A source that sits below another source now counts towards it — under the same condition as before: only if the deeper node has no object of its own (that is how MQTT creates its key levels) or the ancestor is a `device` (that is where Homematic keeps its channels). Two `channel` objects stay separate even when one sits below the other — those are two devices.
624
+ * **Fixed: a German leftover in the English tab.** In the change card a hand-added row without a name showed „(ohne Namen)“ — hardcoded instead of translated, in an otherwise entirely English interface. The text now comes from the language files (`diff.noName`).
625
+
595
626
  ### 0.10.0 (2026-09-20)
596
627
  **Detection and patterns**
597
628
  * Picking another pattern re-ticks the rows and leaves them alone while the new pattern does not apply yet.
@@ -708,90 +739,7 @@ All changes in detail, with cause and measurement: [docs/aenderungen-ausfuehrlic
708
739
  * The README no longer describes how to add the adapter by hand — in the official repository it is picked from the adapter list (E6013)
709
740
  * `dependabot.yml` gets a seven-day cooldown for npm packages: what appears today is proposed a week later. If a compromised release is pulled within that time, it never arrives here (E8915). And `@types/node` stays on its major version — the types must match the Node release the adapter runs on (E8917)
710
741
 
711
- ### 0.9.7
712
- *Versions 0.9.1 to 0.9.6 were local intermediate steps and were never
713
- published — their changes are part of 0.9.7.*
714
-
715
- Seven packages from a code review — 45 fixes between 0.9.0 and this release. The intermediate steps 0.9.1 to 0.9.6 stayed local and were never published; they are summarised here.
716
-
717
- **Data loss and failure paths**
718
- * An enumeration error now stops a move. Previously the old alias was deleted anyway — and afterwards it was gone while the new one sat in no enumeration at all
719
- * A partial failure while deleting no longer turns the retry button into a prop: only what really went is dropped
720
- * Orphaned points are deleted on the second attempt too
721
- * A load error on the enumerations leaves the previous state standing instead of emptying it — and while they are unknown, nothing is written. Before, one hiccup could drop an alias out of every room and function
722
- * A load error on your own templates is reported instead of swallowed; otherwise the next save would have replaced an existing template with version 1
723
-
724
- **Connection and display**
725
- * The tab works again after a dropped connection. The admin's WebSocket fires `connect` once per page lifetime and `reconnect` afterwards — nobody listened, and neither object nor state changes arrived
726
- * Template mode no longer rebuilds itself every second, and where the selection goes, its subscriptions go too
727
- * “Differs from the alias” now also shows in alias mode — where it says the most
728
- * Switching sources quickly no longer fetches the wrong value; the source jump list never appears twice
729
- * Object names follow the admin language; the function match looks at every language and no longer creates a duplicate
730
-
731
- **Templates**
732
- * A broken name hint no longer takes down the whole source view — including the nested form `(a+)+` where the expression engine stalls
733
- * The formula of a fallback source survives updating, an unknown device type no longer throws
734
- * Importing checks more than id and states; a hand-typed id no longer replaces someone else's template
735
- * The `%N%` placeholder only hits the output number now, not every trailing digit
736
- * The blind gets its STOP: a button press has no state to read, and that case was unknown to template application — **not a single** blind alias ever had one
737
- * ON_TIME finds its slot (four templates carried the wrong role)
738
-
739
- **MQTT and Tasmota**
740
- * An empty `custom` entry no longer takes anything down, `enabled: false` counts as switched off
741
- * No more false “cannot publish” for ioBroker.mqtt and sonoff — there, publishing capability is simply unknown, not denied
742
- * “Answer received” only for a real answer; `Vcc` and `Command` are not commands
743
-
744
- **Speed, measured on a production system with 24,786 objects**
745
- * The search box no longer blocks: **236 ms per keystroke → 0**, the whole tree **263 → 67 ms**
746
- * A redraw no longer costs half a second — binary search instead of linear scans: drawing a source **15.8 → 1.6 ms**, an alias with 50 points **51.9 → 14.2 ms**
747
- * A read formula can no longer freeze the tab for good
748
- * What is subscribed is what is read — before, a single alias could subscribe to half an adapter
749
-
750
- ### 0.9.0
751
- * The role list is complete again: the detector hands out the expressions of its slots as text WITH slashes (`/^indicator…$/`), not as a regular expression. Take the slashes for part of the expression and you find neither start nor end afterwards — 210 roles instead of 232, and `indicator.lowbat` of all things was missing, the role every Homematic device writes. In the role picker, no slot of the pattern was offered at all any more, only the line "show all roles"
752
- * From the same cause, BRIGHTNESS lost its role in six colour-light patterns — the slot could be added over and over and could not be filled by any route. Seven places in the code read a slot expression; they all go through one function now, and a test checks the role list against what the detector actually delivers instead of against hand-written expressions
753
- * The deviation card tells the truth again when a point is deselected: it claimed "would not have counted anyway" even for points that do have a slot in the pattern (same cause)
754
- * A point the template lists under a different name now keeps its role and its caption at the source: the workbench has two functions for the same job, and the second one bailed out when a template had matched. At the alias it said `state` and "Lavalampe ACTUAL", at the source `sensor.light` and nothing at all — updating would have overwritten both. What the template wanted instead now shows as a mark on the row, as everywhere else, and can be taken over field by field
755
- * On load, the workbench no longer fetches two files that do not exist: it searched the admin's directory for file names and put `assets/` in front, although whole paths are listed there — and two entries expressly do not live in that folder (`"path": ""`). That produced two 404s in the browser console. It now looks for paths instead of names and strips a leading `./`: the manifest writes `assets/…`, the `index.html` `./assets/…`, and without that step the same file would sit twice in a list that ends after 25 entries
756
- * The readme now mentions two things it used to keep quiet about: that the workbench proposes the read formula itself from recognised JSON — guarded against missing fields, and readable in both directions — and that it maintains roles, the channel role, room and function along with their pictures
757
- * Values now keep running in the alias view: the workbench subscribed to the alias points but displays the values of their sources, so the numbers were fetched once and then stood still. It now subscribes to the sources as well. The header shows how many subscriptions are running — a subscription covers a whole branch, and its tooltip lists them, so it is visible right away if one is ever left behind
758
- * The caption of a row now lives in a tooltip on its id instead of standing next to it — with the marks a row can carry, it had become so crowded that role and value were pushed off to the right. A dotted underline shows where a tooltip waits
759
- * An alias whose points read from more than one node now says so: a chip "n sources" next to "to the source", listing every node with its number of points; the jump button asks where to go instead of silently taking the majority; and the individual rows that read from elsewhere carry a mark naming their adapter. Before, the only way to notice was to open every row. The way back holds too: from a secondary source, "to the alias" is there again — it used to require being at the majority source. Spartas of one and the same device (a Tasmota `stat` and `tele`) do not count as a second source. The choice appears only under "to the source" — jumping to the alias has exactly one destination. Spartas next to each other are merged as well now, not just against the main source — a Tasmota read through `stat` and `tele` counted as two. And both the way back and the row marks now go by the source you are standing at: "to the alias" is there at every source of an alias, including the device above a sparte, and a row is marked when it does not come from here. At the alias itself every row carries its tag — there is no place you are standing, so no source is the normal one; a tie no longer decides anything. The tag names the source, not the adapter, and no entry in the list is highlighted
760
- * Nodes without datapoints are no longer left out of the tree: a channel, device or folder that exists but is empty now stands there greyed out, without a count and not clickable, with a tooltip saying so. Left out, it looked like the node did not exist at all — while in truth the adapter had not created its datapoints. They do not count as hits when filtering
761
-
762
- ### 0.8.3
763
- * The dry run now shows enumerations as a comparison as well: the "before" column stayed empty for them, because enumerations live in their own store and the dry run only looked in the object store. Everything appeared as new, so it was impossible to see that eleven of twelve members were already there
764
- * …and the interface no longer announces a creation where it changes: on such an alias the chip said "will be newly created", the button offered "create alias", the dry run was titled "what would come into being", the room and function were guessed instead of read, orphaned points went unnoticed and move/swap/remove did nothing. All of them asked whether the channel is an object instead of whether the alias exists
765
- * An alias whose channel exists only as an id, not as an object — the usual result of adding points by hand in the admin — is now compared against the stored state at all. Before, the whole comparison bailed out there, and updating would have replaced captions with the bare point names and dropped roles, formulas and write direction along with them
766
- * The same rule was missing a third time, for aliases where several points read from one and the same source datapoint — a blind, where OPEN, CLOSE, SET and pct all go to `level`. Only the first of them kept its write source; the others lost it, and updating would have made the blind unreachable through its alias
767
- * Updating an existing alias no longer overwrites its caption with the bare row name, and no longer turns a read-only alias into a writable one: the function that takes the stored alias over into the draft was missing both rules its twin already had. The false "differs from the stored alias" mark that came with it is gone too
768
- * A line that comes from the stored alias and reads from a source outside the selected node now gets its value: the values were fetched before that line even existed, so it claimed "source delivers nothing" while the alias was working fine. Only showed on aliases assembled from several adapters, and only until the node was clicked a second time
769
-
770
- ### 0.8.2
771
- * A source that already has an alias now says so when the target points elsewhere: "This source already has alias.0.… — that one stays where it is", with a button "move it instead …" that opens the move dialog prefilled. Nothing is forbidden — two aliases on one source remain possible, they are no longer silent
772
- * The same line appears in the dry run, right above what cannot be written
773
- * The offer to take the typed folder as the room now also appears on a device that already has an alias — the very case where the room is meant to come along
774
- * Escape in the target bar's folder and name fields now discards what was typed and puts the old value back; before, the folder field only closed its list and both kept the typed text, which was then taken over on leaving the field
775
- * Tooling: the identifier check script now resolves a relative acorn path against the working directory
776
- * A line whose role the workbench adapted on a pattern or template switch now says so: "differs from the stored alias", with the stored value spelled out below the field and a button to take it back
777
- * A line that takes its name from an existing alias no longer shows a false "no place in the … pattern" mark for one draw
778
- * Switching to a template that finds no source at all now works instead of failing silently — the field no longer shows a template that is not in use
779
- * Swap source: the name of the current source is shown next to its id
780
- * Datapoints without a slot in the pattern get a tinted row; the explanation stands once above the list instead of in every row
781
- * Switching the selection while changes are pending — in the tree, through "to the source →", or in the folder overview — now asks first instead of discarding them silently
782
- * Where the template wants something else, the affected field is tinted in the opened row, the template value is spelled out below it, and a button takes over that one value
783
- * The role list now also offers the other spellings a slot accepts (indicator.lowbat next to indicator.maintenance.lowbat), minus the deprecated ones
784
- * New adapter icon: two offset cards — behind the raw datapoints, in front the finished alias, sorted and named
785
-
786
-
787
- ### 0.8.1
788
- * Published through npm trusted publishing (OIDC); releases are signed with provenance
789
-
790
- ### 0.8.0
791
- * Settings page in eleven languages
792
- * ESLint and a CI workshop; checks run before every commit
793
- * The buttons at the bottom follow the mode
794
- * New description
742
+ Older entries: [CHANGELOG_OLD.md](CHANGELOG_OLD.md).
795
743
 
796
744
  ## License
797
745
 
@@ -1161,3 +1161,18 @@
1161
1161
  .vorschlaege .vz.gruppe .tiefer.rbelegt:hover { color:var(--bad); }
1162
1162
  .vorschlaege .vz.zurueck:hover { background:var(--surface-2); color:var(--ink); }
1163
1163
 
1164
+
1165
+ /* Der Hinweis, waehrend der Katalog geholt wird.
1166
+
1167
+ Beim ersten Oeffnen nach einer Admin-Aktualisierung laedt die
1168
+ Werkbank ein Buendel von mehreren Megabyte. Das dauert ein paar
1169
+ Sekunden und sieht ohne ein Wort dazu wie ein Haenger aus
1170
+ (Ricardo, 07.10.2026). Unten rechts, damit er nichts verdeckt, und
1171
+ er geht von allein wieder weg. */
1172
+ .katalog-laedt {
1173
+ position:fixed; right:16px; bottom:16px; z-index:30; max-width:320px;
1174
+ padding:10px 14px; border:1px solid var(--line-strong); border-radius:6px;
1175
+ background:var(--surface); box-shadow:0 2px 10px rgba(0,0,0,.18);
1176
+ }
1177
+ .katalog-laedt .kl-kopf { font-weight:600; font-size:12.5px; color:var(--ink); }
1178
+ .katalog-laedt .kl-text { margin-top:3px; font-size:11.5px; color:var(--ink-3); }