iobroker.yamaha 2.8.0 → 2.9.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.
package/README.md CHANGED
@@ -14,23 +14,32 @@ legacy XML protocol of the oldest pre-2010 models — behind one object tree.
14
14
 
15
15
  ## Features
16
16
 
17
- - **Three protocols, one adapter** — YNCA, MusicCast (Yamaha Extended Control) and the legacy XML protocol of the pre-2010 models
18
- - **Protocols run in parallel** — a MusicCast receiver combines YNCA amplifier control with MusicCast multiroom, equalizer and media on one object tree
17
+ - **Three protocols, one adapter** — YNCA, MusicCast (Yamaha Extended Control) and the legacy XML
18
+ protocol of the pre-2010 models, used in parallel on one object tree
19
19
  - **Instant updates** — MusicCast pushes its changes, YNCA reports over its live connection
20
- - **Self-healing connections** — an offline receiver joins once it answers; a single protocol reconnects on its own while the others keep running
21
- - **Typed datapoints** — booleans, dropdowns and numbers with unit and range instead of raw text
22
- - **Now playing, per zone** — one player block per zone shows source, playback state, title, artist, cover art and the transport buttons for whatever that zone is playing; zones 2–4 carry their own block
23
- - **Presets and favourites** — recall tuner presets and stored network/USB favourites by number, step through presets, save the current station to a preset slot or bookmark it, and read the stored lists with their names (MusicCast); recently-played recall on MusicCast devices
24
- - **Menu browsing** — page through the Net Radio, media-server and USB menus like with the remote: the visible menu lines as datapoints, select-by-line, and a path datapoint that navigates to a favourite in one write
25
- - **Scenes with their names** — recall a scene by number or by its title from a dropdown that shows the names the receiver reports, per zone — plus a scene list for visualizations
26
- - **On-screen remote** — cursor pad and menu keys as datapoints, on **all three protocols**: the same words drive a 2024 MusicCast device, a YNCA receiver and a pre-2010 XML model
27
- - **Setup datapoints of the 2010 receiver generation** — speaker configuration, HDMI and lip-sync settings, trigger assignment per input, subwoofer trim, YPAO volume and the RDS clock, on the models that report them
28
- - **What the receiver declares** — dropdowns show the receiver's own lists where it has them (the XML input list, the `desc.xml` programs, the MusicCast input, program and menu lists), a list derived from proof where it has none (the YNCA inputs a receiver answers for), and the documented values of its generation plus every value it ever reported for the rest. The per-device memory carries the version of that discovery logic and is re-learned after a release that changes it
29
- - **Device-wide MusicCast settings** — automatic standby, display brightness and the HDMI outputs, readable and writable where the device offers them
30
- - **Clock & alarm view** — MusicCast desk-audio devices show their clock and alarm settings
31
- - **Capability-driven** — states are generated from what each device reports, no hardcoded model list
20
+ - **Capability-driven** — the object tree is built from what each device reports, no hardcoded model list
21
+ - **Now playing, per zone** — one player block per zone, whatever that zone is listening to, with
22
+ menu browsing, presets and favourites
23
+ - **Multi-zone and multiroom** — zones 2–4 with their own player and scenes, party mode, MusicCast groups
32
24
  - **Automatic discovery** — an empty device list finds and sets up MusicCast devices at startup
33
- - **Device manager** — receivers as admin cards with model, address, live protocol indicators and a device-type icon (receiver, stereo, speaker, soundbar, CD)
25
+ - **Self-healing connections** — a single protocol reconnects on its own while the others keep running
26
+
27
+ ## Documentation
28
+
29
+ The **[Wiki](https://github.com/iobroker-community-adapters/ioBroker.yamaha/wiki)** has the full
30
+ documentation in English and German:
31
+
32
+ | | |
33
+ |---|---|
34
+ | **[Upgrade](https://github.com/iobroker-community-adapters/ioBroker.yamaha/wiki/Upgrade)** | coming from yamaha 0.5.x, from `musiccast`, or from an earlier 2.x — **read this first if you already run one of them** |
35
+ | **[Setup](https://github.com/iobroker-community-adapters/ioBroker.yamaha/wiki/Setup)** | finding your device, manual entry, what happens on the first start |
36
+ | **[Protocols](https://github.com/iobroker-community-adapters/ioBroker.yamaha/wiki/Protocols)** | why your device can more or less than someone else's |
37
+ | **[Datapoints](https://github.com/iobroker-community-adapters/ioBroker.yamaha/wiki/Datapoints)** | what is in the object tree and where to find it |
38
+ | **[Devices](https://github.com/iobroker-community-adapters/ioBroker.yamaha/wiki/Devices)** | which Yamaha devices work, and what each class can do |
39
+ | **[Troubleshooting](https://github.com/iobroker-community-adapters/ioBroker.yamaha/wiki/Troubleshooting)** | sorted by symptom |
40
+
41
+ A short version ships with the adapter and is shown in the admin ([English](docs/en/README.md) ·
42
+ [Deutsch](docs/de/README.md)).
34
43
 
35
44
  ## Sentry / Error reporting
36
45
 
@@ -46,63 +55,18 @@ For details and how to disable it, see the [Sentry plugin documentation](https:/
46
55
 
47
56
  > The adapter CANNOT be installed via GitHub: The adapter must be installed via the ioBroker repository (stable or latest).
48
57
 
49
- ## Ports
50
-
51
- - **UDP 41100 (listening)** — MusicCast devices push their change events to this port on the ioBroker host.
52
- - **UDP 1900 (multicast, outgoing)** — the SSDP discovery search at startup.
53
- - **TCP 50000 (outgoing)** — the YNCA control connection to each receiver.
54
- - **TCP 80 (outgoing)** — the MusicCast and XML protocol requests to each device.
55
-
56
58
  ## Configuration
57
59
 
58
- Devices are managed in the admin as cards. **Leave the list empty** and the adapter finds MusicCast devices on the network by itself at startup, or add devices by IP via the **"+" dialog** to run only those. Discovery searches on every network interface by default; the optional **network interface** selector confines it to one.
59
-
60
- Older Yamaha receivers (before ~2010, the XML protocol) do not announce themselves on the network and must be added manually. The **XML query interval** sets how often they are polled (default 60 seconds).
61
-
62
- The **Volume as 0–100 %** switch decides what the `volume` datapoints mean. Off (the default) each one carries the scale the receiver itself shows: decibels where the receiver has a decibel display, its own step count where it has none — the datapoint's unit and range say which, and they can differ from zone to zone because the receiver declares them per zone. On, every volume datapoint, in every zone and on every device, carries 0–100 % instead — the range most VIS widgets expect. The adapter converts in both directions, so the receiver is always sent the value it expects.
63
-
64
- The **Data points** section switches whole groups of datapoints on or off — **Playback & browsing**, **Tuner**, **Multiroom**, **HDMI**, **Scenes**, **Sound**, **Advanced** and **Clock & alarm**. A switched-off group is removed from the tree and not even queried, which also speeds up the startup; the amplifier core (power, volume, mute, input, sound program, sleep) always stays on.
65
-
66
- ## State Tree
67
-
68
- Each receiver becomes one device node with themed groups — the same groups the
69
- **Data points** switches control. Only what your device reports is created.
70
-
71
- - **Amplifier core** (always on) — power, volume, mute, input, sound program, sleep, plus the device info with model, firmware, IP address and connection.
72
- - **`player`** — ONE "now playing" block per zone: `player.source` says what the zone is listening to, and playback state, artist, album, track, cover art, times and the transport buttons always describe exactly that — whatever source is playing. Zones 2–4 get their own block under `multiroom.zoneN.player`. The source folders keep only what is genuinely their own: preset recall & save for net radio/server/USB, the MusicCast favourite/recent/playlist/queue lists under `player.netPlayer`, the CD drive states, Bluetooth pairing and the AirPlay volume interlock. The `player.browse` folder mirrors the device's media menu: the eight visible lines (folders and titles marked by symbol), `selectLine` acts like OK on the remote, page/back/root buttons, a `rows` JSON for widgets and a `path` datapoint that walks e.g. `Bookmarks>Radio Paradise` on one write. Beside it, `remote.cursor` (and `remote.menu` where the protocol has it) is the on-screen remote itself — `up`, `down`, `left`, `right`, `select`, `return`, `home` mean the same on every receiver, whichever protocol it speaks.
73
- - **`tuner`** — one band, one frequency (kHz on every generation) and one preset for AM, FM and DAB, plus RDS texts and reception flags; only genuinely DAB-specific detail (service, ensemble, DLS, …) sits under `tuner.dab`.
74
- - **`multiroom`** — zones 2–4 (each with its own player and scene block), Zone B, the all-zones switches (master power, party mode) and the MusicCast device group in its own `multiroom.group` folder.
75
- - **`hdmi`** — the HDMI outputs and the two lip-sync offsets.
76
- - **`scene`** — a recall dropdown carrying the titles the receiver reports (writable by number or title) and a `scene.list` JSON with every scene slot — titled where the device reports titles; zones with their own scenes carry theirs under `multiroom.zoneN.scene`.
77
- - **`sound`** — tone and sound processing: bass/treble, DSP modes, enhancer, the equalizer in its own `sound.equalizer` folder and the current audio signal under `sound.signal` on MusicCast devices.
78
- - **`advanced`** — setup-level datapoints: maximum/initial volume, the speaker configuration (A/B switches included) under `advanced.speakers`, input names.
79
- - **`clock`** — the clock and alarm settings of MusicCast desk-audio devices (read-only).
80
-
81
- ## Troubleshooting
60
+ Devices are managed in the admin as cards. **Leave the list empty** and the adapter finds MusicCast
61
+ devices on the network by itself at startup, or add devices by IP via the **"+" dialog**. Older
62
+ receivers (before ~2010) do not announce themselves and must be added by hand.
82
63
 
83
- ### Upgrading from 1.x
64
+ The **Data points** section switches whole groups of datapoints on or off; the amplifier core (power,
65
+ volume, mute, input, sound program, sleep) always stays on. The **Volume as 0–100 %** switch turns
66
+ every volume datapoint into a percentage — the range most VIS widgets expect.
84
67
 
85
- Version 2.0.0 reworks the object tree. On the first start the adapter removes the old datapoints itself and creates the new ones: the per-source player copies become one `player` block per zone, the scene name datapoints become the recall dropdown plus `scene.list`, the two tuner frequencies become one `tuner.frequency` in kHz, the equalizer and signal info move under `sound.equalizer`/`sound.signal`, the lip-sync offsets under `hdmi`, and the speaker A/B switches under `advanced.speakers`. Point scripts and visualizations at the new paths.
86
-
87
- ### Upgrading from 0.5.x
88
-
89
- Version 1.0.0 is a complete rebuild. On the first start after the update the old datapoints (`volume`, `power`, `Commands.*`, `Realtime.*`, …) are removed and your receiver is recreated as a device; its IP address is carried over automatically. Point scripts and visualizations at the new paths — for example `yamaha.0.<device>.power` instead of `yamaha.0.power`.
90
-
91
- ### Receiver is not found automatically
92
-
93
- Only MusicCast devices announce themselves on the network — older receivers must be added manually via the **"+" dialog**. If discovery comes up empty on a host with several network interfaces, check the **network interface** setting.
94
-
95
- ### Datapoints are missing
96
-
97
- Check the group's toggle in the **Data points** settings, and remember the tree only carries what your device reports. Zone datapoints sit under `multiroom`, not at the top level.
98
-
99
- ### Values update slowly
100
-
101
- If MusicCast changes only refresh every few minutes, another application is occupying UDP port 41100 and the adapter fell back to polling — the startup log notes this.
102
-
103
- ### First start takes a while
104
-
105
- On the very first contact the adapter asks the receiver which functions it supports — up to half a minute per YNCA device. The answers are remembered per device (and survive restarts), so every later start brings the device online in seconds and refreshes the current values in the background. A firmware update or a different device behind the same address is detected and re-asked automatically.
68
+ Details on all settings, the object tree and the ports the adapter uses are in the
69
+ [Wiki](https://github.com/iobroker-community-adapters/ioBroker.yamaha/wiki/Setup).
106
70
 
107
71
  ## Changelog
108
72
 
@@ -110,6 +74,18 @@ On the very first contact the adapter asks the receiver which functions it suppo
110
74
  Placeholder for the next version (at the beginning of the line):
111
75
  ### **WORK IN PROGRESS**
112
76
  -->
77
+ ### 2.9.0 (2026-09-12)
78
+
79
+ - (krobipd) New: Devices you enter by hand and devices the network search finds now run side by side — entering one receiver no longer takes every found one out of the instance
80
+ - (krobipd) New: Setting "Search the network for devices" — automatically while your device list is empty (as before), always next to it, or never
81
+ - (krobipd) New: Every device card can be edited. Give a found receiver the fixed address you assigned it and it becomes one of your entered devices, keeping its whole object tree
82
+ - (krobipd) New: Each card shows where its address came from, and "Volume as 0–100 %" is now set per device instead of once for the whole instance — every receiver keeps what it had
83
+ - (krobipd) Fixed: hdmi.aspect and hdmi.resolution were missing on every receiver from 2012 on — the models moved those settings to another subunit and the adapter only ever asked the old one
84
+ - (krobipd) Fixed: Receivers from 2010/2011 were offered a 4K video resolution their model does not support
85
+ - (krobipd) Fixed: A write to a receiver could be dropped without a trace while another of its protocols was reconnecting
86
+ - (krobipd) Fixed: Deleting a device and adding the same one again left it with the wrong icon until the next restart, and a pending write could recreate the deleted device object
87
+ - (krobipd) Changed: A MusicCast receiver's datapoints now update only when their value really changed — automations tied to them stop firing for no reason
88
+
113
89
  ### 2.8.0 (2026-09-11)
114
90
 
115
91
  - (krobipd) Fixed: A volume written to a MusicCast receiver now arrives exactly — the adapter reads the receiver's own step declaration instead of guessing a ratio (#623)
@@ -141,11 +117,6 @@ On the very first contact the adapter asks the receiver which functions it suppo
141
117
  - (krobipd) Improved: a receiver is set up from its own declaration of zones and inputs, so it comes online faster and is learned again by itself after an update that changes how it is read
142
118
  - (krobipd) Improved: the first connection to a YNCA receiver asks fewer questions, so its datapoints appear sooner
143
119
 
144
- ### 2.5.2 (2026-09-07)
145
-
146
- - (krobipd) Improved: 174 more datapoints explain themselves — volume and tone now say which scale they use, the stored lists say what is inside them, and the menu rows say what they are for
147
- - (krobipd) Improved: a receiver's "Connected" now says what it means — a device on network standby answers as well, so it is not the same as being switched on
148
-
149
120
  [Older changelogs can be found there](CHANGELOG_OLD.md)
150
121
 
151
122
  ## History
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "XML-Abfrageintervall (Sekunden)",
6
6
  "tooltip_xmlPollInterval": "Wie oft der Adapter Receiver mit dem alten XML-Protokoll abfragt (Modelle vor ~2010). Diese Geräte melden Änderungen nicht von selbst. Ohne Wirkung auf YNCA- oder MusicCast-Geräte.",
7
7
  "volumeAsPercent": "Lautstärke als 0–100 %",
8
- "volumeAsPercent_help": "Aus: Jeder Lautstärke-Datenpunkt trägt die Skala, die der Receiver selbst anzeigt — Dezibel oder seine eigene Schrittzahl. Ein: Alle tragen stattdessen 0–100 %, Hauptzone wie jede weitere Zone — der Bereich, den die meisten VIS-Widgets erwarten. Der Adapter rechnet in beide Richtungen um, der Receiver bekommt also immer den Wert, den er erwartet.",
8
+ "volumeAsPercent_help": "Aus: Die Lautstärke-Datenpunkte dieses Geräts tragen die Skala, die der Receiver selbst anzeigt — Dezibel oder seine eigene Schrittzahl. Ein: Sie tragen stattdessen 0–100 %, Hauptzone wie jede weitere Zone dieses Geräts — der Bereich, den die meisten VIS-Widgets erwarten. Der Adapter rechnet in beide Richtungen um, der Receiver bekommt also immer den Wert, den er erwartet.",
9
9
  "supportHeader": "Entwicklung unterstützen",
10
10
  "aboutInfo": "Wenn dir dieser Adapter nützt, kannst du seine Entwicklung unterstützen:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "Wie laut die Zone spielt, in der Dezibel-Skala, die der Receiver selbst anzeigt.",
602
602
  "descVolumeNumeric": "Wie laut die Zone spielt, in der Zahlen-Skala, die der Receiver selbst anzeigt.",
603
- "descVolumePercent": "Wie laut die Zone spielt, als Prozentsatz des Bereichs, den der Receiver annimmt — 0 % ist seine leiseste, 100 % seine lauteste Einstellung."
603
+ "descVolumePercent": "Wie laut die Zone spielt, als Prozentsatz des Bereichs, den der Receiver annimmt — 0 % ist seine leiseste, 100 % seine lauteste Einstellung.",
604
+ "trackRating": "Titelbewertung",
605
+ "descTrackRating": "Bewertet den laufenden Titel mit Daumen hoch oder Daumen runter.",
606
+ "label_discovery": "Netzsuche nach Geräten",
607
+ "tooltip_discovery": "Automatisch sucht, solange unten kein Gerät eingetragen ist — so war es bisher. Immer sucht zusätzlich zu den eingetragenen Geräten. Nie überlässt der Liste unten das Feld.",
608
+ "discoveryAuto": "Automatisch (solange die Liste leer ist)",
609
+ "discoveryAlways": "Immer",
610
+ "discoveryNever": "Nie",
611
+ "sourceManual": "Von Hand eingetragen",
612
+ "sourceDiscovered": "Im Netzwerk gefunden"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "XML query interval (seconds)",
6
6
  "tooltip_xmlPollInterval": "How often the adapter polls receivers that use the old XML protocol (models before ~2010). These devices do not report changes on their own. Has no effect on YNCA or MusicCast devices.",
7
7
  "volumeAsPercent": "Volume as 0–100 %",
8
- "volumeAsPercent_help": "Off: every volume datapoint carries the scale the receiver itself shows — decibels, or its own step count. On: all of them, the main zone and every other zone, carry 0–100 % instead, the range most VIS widgets expect. The adapter converts both ways, so the receiver is always sent the value it expects.",
8
+ "volumeAsPercent_help": "Off: this device's volume datapoints carry the scale the receiver itself shows — decibels, or its own step count. On: they carry 0–100 % instead, the main zone and every other zone of this device, the range most VIS widgets expect. The adapter converts both ways, so the receiver is always sent the value it expects.",
9
9
  "supportHeader": "Support development",
10
10
  "aboutInfo": "If this adapter is useful to you, you can support its development:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "How loud the zone plays, in the decibel scale the receiver itself shows.",
602
602
  "descVolumeNumeric": "How loud the zone plays, in the plain number scale the receiver itself shows.",
603
- "descVolumePercent": "How loud the zone plays, as a percentage of the range the receiver accepts — 0 % is its quietest setting, 100 % its loudest."
603
+ "descVolumePercent": "How loud the zone plays, as a percentage of the range the receiver accepts — 0 % is its quietest setting, 100 % its loudest.",
604
+ "trackRating": "Track rating",
605
+ "descTrackRating": "Rates the track now playing with a thumb up or a thumb down.",
606
+ "label_discovery": "Search the network for devices",
607
+ "tooltip_discovery": "Auto searches while no device is entered below - what the adapter always did. Always searches next to the devices you entered. Never leaves the list below in charge.",
608
+ "discoveryAuto": "Automatically (while the list is empty)",
609
+ "discoveryAlways": "Always",
610
+ "discoveryNever": "Never",
611
+ "sourceManual": "Entered by hand",
612
+ "sourceDiscovered": "Found on the network"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "Intervalo de consulta XML (segundos)",
6
6
  "tooltip_xmlPollInterval": "Con qué frecuencia el adaptador consulta receptores con el antiguo protocolo XML (modelos anteriores a ~2010). Estos equipos no comunican cambios por sí mismos. Sin efecto en YNCA o MusicCast.",
7
7
  "volumeAsPercent": "Volumen como 0–100 %",
8
- "volumeAsPercent_help": "Desactivado: cada punto de datos de volumen usa la escala que el propio receptor muestra — decibelios o su propio recuento de pasos. Activado: todos ellos, la zona principal y cada zona adicional, usan 0–100 %, el rango que esperan la mayoría de los widgets VIS. El adaptador convierte en ambos sentidos, así que el receptor siempre recibe el valor que espera.",
8
+ "volumeAsPercent_help": "Desactivado: los datos de volumen de este dispositivo usan la escala que muestra el propio receptor — decibelios o su propio número de pasos. Activado: usan 0–100 %, la zona principal y todas las demás zonas de este dispositivo, el rango que esperan la mayoría de los widgets VIS. El adaptador convierte en ambos sentidos.",
9
9
  "supportHeader": "Apoyar el desarrollo",
10
10
  "aboutInfo": "Si este adaptador te resulta útil, puedes apoyar su desarrollo:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "Lo alto que suena la zona, en la escala de decibelios que muestra el propio receptor.",
602
602
  "descVolumeNumeric": "Lo alto que suena la zona, en la escala numérica que muestra el propio receptor.",
603
- "descVolumePercent": "Qué tan alto suena la zona, como porcentaje del rango que acepta el receptor — 0 % es su ajuste más bajo, 100 % el más alto."
603
+ "descVolumePercent": "Qué tan alto suena la zona, como porcentaje del rango que acepta el receptor — 0 % es su ajuste más bajo, 100 % el más alto.",
604
+ "trackRating": "Valoración de la pista",
605
+ "descTrackRating": "Valora la pista en reproducción con un pulgar arriba o abajo.",
606
+ "label_discovery": "Buscar dispositivos en la red",
607
+ "tooltip_discovery": "Automático busca mientras no haya ningún dispositivo en la lista, como hasta ahora. Siempre busca además de los dispositivos indicados. Nunca deja solo la lista.",
608
+ "discoveryAuto": "Automático (mientras la lista esté vacía)",
609
+ "discoveryAlways": "Siempre",
610
+ "discoveryNever": "Nunca",
611
+ "sourceManual": "Introducido a mano",
612
+ "sourceDiscovered": "Encontrado en la red"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "Intervalle d'interrogation XML (secondes)",
6
6
  "tooltip_xmlPollInterval": "Fréquence d'interrogation des amplis utilisant l'ancien protocole XML (modèles avant ~2010). Ces appareils ne signalent pas les changements d'eux-mêmes. Sans effet sur YNCA ou MusicCast.",
7
7
  "volumeAsPercent": "Volume en 0–100 %",
8
- "volumeAsPercent_help": "Désactivé : chaque point de données de volume utilise l'échelle que l'ampli affiche lui-même — décibels ou son propre nombre de pas. Activé : tous, la zone principale comme chaque autre zone, utilisent 0–100 %, la plage attendue par la plupart des widgets VIS. L'adaptateur convertit dans les deux sens, l'ampli reçoit donc toujours la valeur qu'il attend.",
8
+ "volumeAsPercent_help": "Désactivé : les points de données de volume de cet appareil utilisent l'échelle affichée par l'ampli — décibels ou son propre nombre de pas. Activé : ils utilisent 0–100 %, la zone principale comme toutes les autres zones de cet appareil, la plage attendue par la plupart des widgets VIS. L'adaptateur convertit dans les deux sens.",
9
9
  "supportHeader": "Soutenir le développement",
10
10
  "aboutInfo": "Si cet adaptateur vous est utile, vous pouvez soutenir son développement :",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "Le niveau sonore de la zone, dans l'échelle en décibels affichée par l'ampli lui-même.",
602
602
  "descVolumeNumeric": "Le niveau sonore de la zone, dans l'échelle numérique affichée par l'ampli lui-même.",
603
- "descVolumePercent": "Le volume de la zone, en pourcentage de la plage que l'ampli accepte — 0 % est son réglage le plus bas, 100 % le plus fort."
603
+ "descVolumePercent": "Le volume de la zone, en pourcentage de la plage que l'ampli accepte — 0 % est son réglage le plus bas, 100 % le plus fort.",
604
+ "trackRating": "Note du morceau",
605
+ "descTrackRating": "Note le morceau en cours avec un pouce levé ou baissé.",
606
+ "label_discovery": "Rechercher les appareils sur le réseau",
607
+ "tooltip_discovery": "Automatique cherche tant qu'aucun appareil n'est saisi ci-dessous, comme jusqu'ici. Toujours cherche en plus des appareils saisis. Jamais laisse la liste seule.",
608
+ "discoveryAuto": "Automatique (tant que la liste est vide)",
609
+ "discoveryAlways": "Toujours",
610
+ "discoveryNever": "Jamais",
611
+ "sourceManual": "Saisi à la main",
612
+ "sourceDiscovered": "Trouvé sur le réseau"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "Intervallo di interrogazione XML (secondi)",
6
6
  "tooltip_xmlPollInterval": "Con quale frequenza l'adattatore interroga i ricevitori con il vecchio protocollo XML (modelli prima del ~2010). Questi dispositivi non segnalano da soli le modifiche. Nessun effetto su YNCA o MusicCast.",
7
7
  "volumeAsPercent": "Volume come 0–100 %",
8
- "volumeAsPercent_help": "Disattivato: ogni datapoint del volume usa la scala che il ricevitore stesso mostra — decibel o il suo conteggio di passi. Attivato: tutti, la zona principale e ogni altra zona, usano 0–100 %, l'intervallo che la maggior parte dei widget VIS si aspetta. L'adattatore converte in entrambe le direzioni, quindi il ricevitore riceve sempre il valore che si aspetta.",
8
+ "volumeAsPercent_help": "Disattivato: i datapoint del volume di questo dispositivo usano la scala mostrata dal ricevitore — decibel o il suo conteggio di passi. Attivato: usano 0–100 %, la zona principale e ogni altra zona di questo dispositivo, l'intervallo che la maggior parte dei widget VIS si aspetta. L'adattatore converte in entrambe le direzioni.",
9
9
  "supportHeader": "Sostieni lo sviluppo",
10
10
  "aboutInfo": "Se questo adattatore ti è utile, puoi sostenere il suo sviluppo:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "Quanto forte suona la zona, nella scala in decibel che il ricevitore stesso mostra.",
602
602
  "descVolumeNumeric": "Quanto forte suona la zona, nella scala numerica che il ricevitore stesso mostra.",
603
- "descVolumePercent": "Quanto forte suona la zona, come percentuale dell'intervallo che il ricevitore accetta — 0 % è l'impostazione più bassa, 100 % la più alta."
603
+ "descVolumePercent": "Quanto forte suona la zona, come percentuale dell'intervallo che il ricevitore accetta — 0 % è l'impostazione più bassa, 100 % la più alta.",
604
+ "trackRating": "Valutazione del brano",
605
+ "descTrackRating": "Valuta il brano in riproduzione con pollice su o pollice giù.",
606
+ "label_discovery": "Cerca i dispositivi in rete",
607
+ "tooltip_discovery": "Automatico cerca finché non è indicato alcun dispositivo, come finora. Sempre cerca anche accanto ai dispositivi indicati. Mai lascia fare al solo elenco.",
608
+ "discoveryAuto": "Automatico (finché l'elenco è vuoto)",
609
+ "discoveryAlways": "Sempre",
610
+ "discoveryNever": "Mai",
611
+ "sourceManual": "Inserito a mano",
612
+ "sourceDiscovered": "Trovato in rete"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "XML-opvraaginterval (seconden)",
6
6
  "tooltip_xmlPollInterval": "Hoe vaak de adapter receivers met het oude XML-protocol opvraagt (modellen van vóór ~2010). Deze apparaten melden wijzigingen niet zelf. Geen effect op YNCA- of MusicCast-apparaten.",
7
7
  "volumeAsPercent": "Volume als 0–100 %",
8
- "volumeAsPercent_help": "Uit: elk volume-datapunt gebruikt de schaal die de receiver zelf toont — decibel of zijn eigen stappen. Aan: allemaal, de hoofdzone en elke andere zone, gebruiken 0–100 %, het bereik dat de meeste VIS-widgets verwachten. De adapter rekent beide kanten op, dus de receiver krijgt altijd de waarde die hij verwacht.",
8
+ "volumeAsPercent_help": "Uit: de volume-datapunten van dit apparaat gebruiken de schaal die de receiver zelf toont — decibel of zijn eigen stappen. Aan: ze gebruiken 0–100 %, de hoofdzone en elke andere zone van dit apparaat, het bereik dat de meeste VIS-widgets verwachten. De adapter rekent beide kanten op om.",
9
9
  "supportHeader": "Ontwikkeling steunen",
10
10
  "aboutInfo": "Als deze adapter nuttig voor je is, kun je de ontwikkeling steunen:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "Hoe hard de zone speelt, in de decibelschaal die de receiver zelf toont.",
602
602
  "descVolumeNumeric": "Hoe hard de zone speelt, in de getalschaal die de receiver zelf toont.",
603
- "descVolumePercent": "Hoe hard de zone speelt, als percentage van het bereik dat de receiver accepteert — 0 % is de zachtste stand, 100 % de hardste."
603
+ "descVolumePercent": "Hoe hard de zone speelt, als percentage van het bereik dat de receiver accepteert — 0 % is de zachtste stand, 100 % de hardste.",
604
+ "trackRating": "Nummerbeoordeling",
605
+ "descTrackRating": "Beoordeelt het spelende nummer met duim omhoog of omlaag.",
606
+ "label_discovery": "Zoek apparaten in het netwerk",
607
+ "tooltip_discovery": "Automatisch zoekt zolang er geen apparaat is ingevoerd, zoals tot nu toe. Altijd zoekt naast de ingevoerde apparaten. Nooit laat alleen de lijst het werk doen.",
608
+ "discoveryAuto": "Automatisch (zolang de lijst leeg is)",
609
+ "discoveryAlways": "Altijd",
610
+ "discoveryNever": "Nooit",
611
+ "sourceManual": "Handmatig ingevoerd",
612
+ "sourceDiscovered": "Gevonden in het netwerk"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "Interwał odpytywania XML (sekundy)",
6
6
  "tooltip_xmlPollInterval": "Jak często adapter odpytuje amplitunery ze starym protokołem XML (modele sprzed ~2010). Te urządzenia nie zgłaszają zmian samodzielnie. Bez wpływu na urządzenia YNCA i MusicCast.",
7
7
  "volumeAsPercent": "Głośność jako 0–100 %",
8
- "volumeAsPercent_help": "Wyłączone: każdy punkt danych głośności używa skali, którą pokazuje sam amplituner — decybeli albo własnej liczby kroków. Włączone: wszystkie, strefa główna i każda inna strefa, używają 0–100 %, czyli zakresu oczekiwanego przez większość widżetów VIS. Adapter przelicza w obie strony, więc amplituner zawsze dostaje wartość, której oczekuje.",
8
+ "volumeAsPercent_help": "Wyłączone: punkty danych głośności tego urządzenia używają skali pokazywanej przez amplituner — decybeli lub własnej liczby kroków. Włączone: używają 0–100 %, strefa główna i każda inna strefa tego urządzenia zakres oczekiwany przez większość widżetów VIS. Adapter przelicza w obie strony.",
9
9
  "supportHeader": "Wesprzyj rozwój",
10
10
  "aboutInfo": "Jeśli ten adapter jest dla Ciebie przydatny, możesz wesprzeć jego rozwój:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "Jak głośno gra strefa, w skali decybelowej pokazywanej przez sam amplituner.",
602
602
  "descVolumeNumeric": "Jak głośno gra strefa, w skali liczbowej pokazywanej przez sam amplituner.",
603
- "descVolumePercent": "Jak głośno gra strefa, jako procent zakresu, który przyjmuje amplituner — 0 % to ustawienie najcichsze, 100 % najgłośniejsze."
603
+ "descVolumePercent": "Jak głośno gra strefa, jako procent zakresu, który przyjmuje amplituner — 0 % to ustawienie najcichsze, 100 % najgłośniejsze.",
604
+ "trackRating": "Ocena utworu",
605
+ "descTrackRating": "Ocenia odtwarzany utwór kciukiem w górę lub w dół.",
606
+ "label_discovery": "Wyszukiwanie urządzeń w sieci",
607
+ "tooltip_discovery": "Automatycznie szuka, dopóki lista jest pusta — tak było dotychczas. Zawsze szuka obok wpisanych urządzeń. Nigdy pozostawia samą listę.",
608
+ "discoveryAuto": "Automatycznie (dopóki lista jest pusta)",
609
+ "discoveryAlways": "Zawsze",
610
+ "discoveryNever": "Nigdy",
611
+ "sourceManual": "Wpisane ręcznie",
612
+ "sourceDiscovered": "Znalezione w sieci"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "Intervalo de consulta XML (segundos)",
6
6
  "tooltip_xmlPollInterval": "Com que frequência o adaptador consulta recetores com o antigo protocolo XML (modelos anteriores a ~2010). Estes aparelhos não comunicam alterações por si. Sem efeito em YNCA ou MusicCast.",
7
7
  "volumeAsPercent": "Volume como 0–100 %",
8
- "volumeAsPercent_help": "Desligado: cada ponto de dados de volume usa a escala que o próprio receptor mostra — decibéis ou a sua própria contagem de passos. Ligado: todos eles, a zona principal e todas as outras zonas, usam 0–100 %, o intervalo que a maioria dos widgets VIS espera. O adaptador converte nos dois sentidos, por isso o receptor recebe sempre o valor que espera.",
8
+ "volumeAsPercent_help": "Desligado: os datapoints de volume deste dispositivo usam a escala que o receptor mostra — decibéis ou a sua própria contagem de passos. Ligado: usam 0–100 %, a zona principal e todas as outras zonas deste dispositivo, o intervalo que a maioria dos widgets VIS espera. O adaptador converte nos dois sentidos.",
9
9
  "supportHeader": "Apoiar o desenvolvimento",
10
10
  "aboutInfo": "Se este adaptador lhe é útil, pode apoiar o seu desenvolvimento:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "Quão alto a zona toca, na escala de decibéis que o próprio recetor mostra.",
602
602
  "descVolumeNumeric": "Quão alto a zona toca, na escala numérica que o próprio recetor mostra.",
603
- "descVolumePercent": "Quão alto a zona toca, como percentagem do intervalo que o receptor aceita — 0 % é a definição mais baixa, 100 % a mais alta."
603
+ "descVolumePercent": "Quão alto a zona toca, como percentagem do intervalo que o receptor aceita — 0 % é a definição mais baixa, 100 % a mais alta.",
604
+ "trackRating": "Avaliação da faixa",
605
+ "descTrackRating": "Avalia a faixa em reprodução com polegar para cima ou para baixo.",
606
+ "label_discovery": "Procurar dispositivos na rede",
607
+ "tooltip_discovery": "Automático procura enquanto não houver dispositivo na lista, como até agora. Sempre procura além dos dispositivos indicados. Nunca deixa só a lista.",
608
+ "discoveryAuto": "Automático (enquanto a lista estiver vazia)",
609
+ "discoveryAlways": "Sempre",
610
+ "discoveryNever": "Nunca",
611
+ "sourceManual": "Introduzido manualmente",
612
+ "sourceDiscovered": "Encontrado na rede"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "Интервал опроса XML (секунды)",
6
6
  "tooltip_xmlPollInterval": "Как часто адаптер опрашивает ресиверы со старым XML-протоколом (модели до ~2010). Эти устройства не сообщают об изменениях сами. Не влияет на устройства YNCA и MusicCast.",
7
7
  "volumeAsPercent": "Громкость как 0–100 %",
8
- "volumeAsPercent_help": "Выкл.: каждый датапоинт громкости использует шкалу, которую показывает сам ресивер — децибелы или его собственные шаги. Вкл.: все они, главная зона и каждая другая зона, используют 0–100 % — диапазон, который ожидает большинство виджетов VIS. Адаптер пересчитывает в обе стороны, поэтому ресивер всегда получает ожидаемое значение.",
8
+ "volumeAsPercent_help": "Выкл.: точки данных громкости этого устройства используют шкалу, которую показывает сам ресивер, — децибелы или его собственные шаги. Вкл.: они используют 0–100 %, основная зона и каждая другая зона этого устройства — диапазон, который ожидает большинство VIS-виджетов. Адаптер пересчитывает в обе стороны.",
9
9
  "supportHeader": "Поддержать разработку",
10
10
  "aboutInfo": "Если этот адаптер вам полезен, вы можете поддержать его разработку:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "Насколько громко играет зона, в шкале децибел, которую показывает сам ресивер.",
602
602
  "descVolumeNumeric": "Насколько громко играет зона, в числовой шкале, которую показывает сам ресивер.",
603
- "descVolumePercent": "Насколько громко играет зона, в процентах от диапазона, который принимает ресивер: 0 % — самая тихая настройка, 100 % — самая громкая."
603
+ "descVolumePercent": "Насколько громко играет зона, в процентах от диапазона, который принимает ресивер: 0 % — самая тихая настройка, 100 % — самая громкая.",
604
+ "trackRating": "Оценка трека",
605
+ "descTrackRating": "Оценивает текущий трек: палец вверх или палец вниз.",
606
+ "label_discovery": "Поиск устройств в сети",
607
+ "tooltip_discovery": "Автоматически ищет, пока список пуст, — так было всегда. Всегда ищет вдобавок к указанным устройствам. Никогда оставляет только список.",
608
+ "discoveryAuto": "Автоматически (пока список пуст)",
609
+ "discoveryAlways": "Всегда",
610
+ "discoveryNever": "Никогда",
611
+ "sourceManual": "Добавлено вручную",
612
+ "sourceDiscovered": "Найдено в сети"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "Інтервал опитування XML (секунди)",
6
6
  "tooltip_xmlPollInterval": "Як часто адаптер опитує ресивери зі старим XML-протоколом (моделі до ~2010). Ці пристрої не повідомляють про зміни самостійно. Не впливає на пристрої YNCA та MusicCast.",
7
7
  "volumeAsPercent": "Гучність як 0–100 %",
8
- "volumeAsPercent_help": "Вимкнено: кожен датапоінт гучності використовує шкалу, яку показує сам ресивер — децибели або власні кроки. Увімкнено: усі вони, головна зона й кожна інша зона, використовують 0–100 % — діапазон, який очікує більшість віджетів VIS. Адаптер перераховує в обидва боки, тож ресивер завжди отримує очікуване значення.",
8
+ "volumeAsPercent_help": "Вимк.: точки даних гучності цього пристрою використовують шкалу, яку показує сам ресивер, — децибели або власні кроки. Увімк.: вони використовують 0–100 %, головна зона й кожна інша зона цього пристрою — діапазон, який очікує більшість VIS-віджетів. Адаптер перераховує в обидва боки.",
9
9
  "supportHeader": "Підтримати розробку",
10
10
  "aboutInfo": "Якщо цей адаптер вам корисний, ви можете підтримати його розробку:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "Наскільки гучно грає зона, у шкалі децибел, яку показує сам ресивер.",
602
602
  "descVolumeNumeric": "Наскільки гучно грає зона, у числовій шкалі, яку показує сам ресивер.",
603
- "descVolumePercent": "Наскільки гучно грає зона, у відсотках від діапазону, який приймає ресивер: 0 % — найтихіше налаштування, 100 % — найгучніше."
603
+ "descVolumePercent": "Наскільки гучно грає зона, у відсотках від діапазону, який приймає ресивер: 0 % — найтихіше налаштування, 100 % — найгучніше.",
604
+ "trackRating": "Оцінка треку",
605
+ "descTrackRating": "Оцінює поточний трек: палець угору або палець униз.",
606
+ "label_discovery": "Пошук пристроїв у мережі",
607
+ "tooltip_discovery": "Автоматично шукає, доки список порожній, — так було досі. Завжди шукає додатково до вказаних пристроїв. Ніколи залишає лише список.",
608
+ "discoveryAuto": "Автоматично (доки список порожній)",
609
+ "discoveryAlways": "Завжди",
610
+ "discoveryNever": "Ніколи",
611
+ "sourceManual": "Додано вручну",
612
+ "sourceDiscovered": "Знайдено в мережі"
604
613
  }
@@ -5,7 +5,7 @@
5
5
  "label_xmlPollInterval": "XML 查询间隔(秒)",
6
6
  "tooltip_xmlPollInterval": "适配器轮询使用旧 XML 协议的功放(约 2010 年前的型号)的频率。这些设备不会自行报告更改。对 YNCA 或 MusicCast 设备无影响。",
7
7
  "volumeAsPercent": "音量显示为 0–100 %",
8
- "volumeAsPercent_help": "关闭:每个音量数据点使用功放自己显示的刻度——分贝或它自己的步进数。开启:所有数据点,主区域和每个其他区域,都改用 0–100 %,这是大多数 VIS 控件所期望的范围。适配器双向换算,因此功放始终收到它期望的数值。",
8
+ "volumeAsPercent_help": "关闭:本设备的音量数据点使用功放自身显示的刻度——分贝或其步进计数。开启:改用 0–100 %,主区与本设备的每个分区都一样,这是多数 VIS 控件所期望的范围。适配器双向换算。",
9
9
  "supportHeader": "支持开发",
10
10
  "aboutInfo": "如果此适配器对你有用,你可以支持它的开发:",
11
11
  "donateKofi": "Ko-fi",
@@ -600,5 +600,14 @@
600
600
  "docLinkLabelEn": "Wiki (English)",
601
601
  "descVolumeDb": "该区域的音量,采用功放自身显示的分贝刻度。",
602
602
  "descVolumeNumeric": "该区域的音量,采用功放自身显示的数字刻度。",
603
- "descVolumePercent": "该区域的播放音量,以功放可接受范围的百分比表示——0 % 为最小,100 % 为最大。"
603
+ "descVolumePercent": "该区域的播放音量,以功放可接受范围的百分比表示——0 % 为最小,100 % 为最大。",
604
+ "trackRating": "曲目评分",
605
+ "descTrackRating": "为正在播放的曲目点赞或点踩。",
606
+ "label_discovery": "在网络中搜索设备",
607
+ "tooltip_discovery": "自动:列表为空时搜索,与以往一致。始终:在已填写设备之外继续搜索。从不:只使用下方列表。",
608
+ "discoveryAuto": "自动(列表为空时)",
609
+ "discoveryAlways": "始终",
610
+ "discoveryNever": "从不",
611
+ "sourceManual": "手动添加",
612
+ "sourceDiscovered": "网络中发现"
604
613
  }
@@ -41,6 +41,32 @@
41
41
  "lg": 12,
42
42
  "xl": 12
43
43
  },
44
+ "discovery": {
45
+ "newLine": true,
46
+ "type": "select",
47
+ "label": "label_discovery",
48
+ "tooltip": "tooltip_discovery",
49
+ "options": [
50
+ {
51
+ "label": "discoveryAuto",
52
+ "value": "auto"
53
+ },
54
+ {
55
+ "label": "discoveryAlways",
56
+ "value": "always"
57
+ },
58
+ {
59
+ "label": "discoveryNever",
60
+ "value": "never"
61
+ }
62
+ ],
63
+ "default": "auto",
64
+ "xs": 12,
65
+ "sm": 12,
66
+ "md": 6,
67
+ "lg": 6,
68
+ "xl": 6
69
+ },
44
70
  "networkInterface": {
45
71
  "newLine": true,
46
72
  "type": "ip",
@@ -69,17 +95,6 @@
69
95
  "lg": 4,
70
96
  "xl": 4
71
97
  },
72
- "volumeAsPercent": {
73
- "newLine": true,
74
- "type": "checkbox",
75
- "label": "volumeAsPercent",
76
- "help": "volumeAsPercent_help",
77
- "xs": 12,
78
- "sm": 12,
79
- "md": 8,
80
- "lg": 6,
81
- "xl": 6
82
- },
83
98
  "_datapointsHeader": {
84
99
  "newLine": true,
85
100
  "type": "header",
@@ -52,6 +52,17 @@ function buildDeviceForm(usedIps) {
52
52
  validatorNoSaveOnError: true,
53
53
  sm: 12,
54
54
  md: 6
55
+ },
56
+ // Per device, not per instance: the adapter serves several receivers, and one of them
57
+ // wanting percent says nothing about the others. Same switch as on the card — one value,
58
+ // two places to reach it.
59
+ volumeAsPercent: {
60
+ newLine: true,
61
+ type: "checkbox",
62
+ label: (0, import_i18n.t)("volumeAsPercent"),
63
+ help: (0, import_i18n.t)("volumeAsPercent_help"),
64
+ sm: 12,
65
+ md: 12
55
66
  }
56
67
  }
57
68
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/device-management-helpers.ts"],
4
- "sourcesContent": ["import type { JsonFormSchema } from \"@iobroker/dm-utils\";\nimport { t } from \"./lib/i18n\";\nimport { sanitizeId } from \"./lib/pure-helpers\";\nimport { TRANSPORT_LABELS } from \"./lib/ready-line\";\n\n/** Object-id segments the adapter reserves for its own tree \u2014 a device may not take them. */\nconst RESERVED_IDS = new Set([\"info\"]);\n/** IPv4 dotted-quad \u2014 the single source for both the frontend validator and the backend check. */\nconst IP_RE = /^(\\d{1,3}\\.){3}\\d{1,3}$/;\n\n/** The transports shown as card indicators \u2014 the single source shared with the ready-log line. */\nexport const TRANSPORTS = TRANSPORT_LABELS;\n\n/** One raw manual device row from `native.devices` (the name is optional). */\nexport interface ManualRow {\n /** Display name, or empty/absent when the user left it blank. */\n name?: string;\n /** The device IP address. */\n ip: string;\n}\n\n/** A running device as shown on a card, plus which source it came from (routes edit/delete). */\nexport interface CardDevice {\n /** The id-safe device id (object-tree path segment). */\n id: string;\n /** The device IP address. */\n ip: string;\n /** The card header name. */\n name: string;\n /** Where it lives: the manual `native.devices` table, or the auto-discovery store. */\n source: \"manual\" | \"discovered\";\n}\n\n/**\n * The id the object tree uses for a manual row: its name, or the ip when the name is blank.\n *\n * @param row the manual device row\n * @returns the id-safe device id\n */\nexport function rowId(row: ManualRow): string {\n return sanitizeId(row.name && row.name.length > 0 ? row.name : row.ip);\n}\n\n/**\n * The add/edit form for one receiver: a display name and the IP address. The IP field\n * carries a live validator against a valid dotted-quad that is not already in use (the OK\n * button greys out on a clash). Labels are resolved translation objects so the embedded\n * form is language-correct.\n *\n * @param usedIps the IPs taken by OTHER devices (the edited device excluded)\n * @returns the jsonConfig panel schema for one device\n */\nexport function buildDeviceForm(usedIps: readonly string[]): JsonFormSchema {\n const ipList = JSON.stringify([...usedIps]);\n return {\n type: \"panel\",\n items: {\n name: {\n type: \"text\",\n label: t(\"columnName\"),\n sm: 12,\n md: 6,\n },\n ip: {\n type: \"text\",\n label: t(\"columnIp\"),\n validator: `!!(data.ip && ${IP_RE.toString()}.test(data.ip)) && !${ipList}.includes(data.ip)`,\n validatorErrorText: t(\"invalidIp\"),\n validatorNoSaveOnError: true,\n sm: 12,\n md: 6,\n },\n },\n } as unknown as JsonFormSchema;\n}\n\n/**\n * A duplicate-IP/name or invalid-value clash against the other rows, as a ready-to-show\n * message \u2014 the backend safety net behind the form validator (the dialog validator may not\n * fire in every admin version; this never lets a bad row through). Each failure mode gets\n * its own message: a malformed IP is not the same problem as a name that is reserved or\n * already taken \u2014 reporting \"invalid IP\" for a name clash sends the user hunting in the\n * wrong field.\n *\n * @param rows the current manual rows\n * @param candidate the row being added/edited\n * @param exceptIndex the row position to ignore (the row being edited), or -1\n * @returns a translated clash message, or null when the row is fine\n */\nexport function findClash(\n rows: readonly ManualRow[],\n candidate: ManualRow,\n exceptIndex: number,\n): ioBroker.StringOrTranslated | null {\n if (!IP_RE.test(candidate.ip)) {\n return t(\"invalidIp\");\n }\n const id = rowId(candidate);\n if (id === \"\" || RESERVED_IDS.has(id)) {\n return t(\"invalidName\");\n }\n for (let i = 0; i < rows.length; i++) {\n if (i === exceptIndex) {\n continue;\n }\n if (rows[i].ip === candidate.ip || rowId(rows[i]) === id) {\n return t(\"duplicateDevice\");\n }\n }\n return null;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAkB;AAClB,0BAA2B;AAC3B,wBAAiC;AAGjC,MAAM,eAAe,oBAAI,IAAI,CAAC,MAAM,CAAC;AAErC,MAAM,QAAQ;AAGP,MAAM,aAAa;AA4BnB,SAAS,MAAM,KAAwB;AAC5C,aAAO,gCAAW,IAAI,QAAQ,IAAI,KAAK,SAAS,IAAI,IAAI,OAAO,IAAI,EAAE;AACvE;AAWO,SAAS,gBAAgB,SAA4C;AAC1E,QAAM,SAAS,KAAK,UAAU,CAAC,GAAG,OAAO,CAAC;AAC1C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,MACL,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,WAAO,eAAE,YAAY;AAAA,QACrB,IAAI;AAAA,QACJ,IAAI;AAAA,MACN;AAAA,MACA,IAAI;AAAA,QACF,MAAM;AAAA,QACN,WAAO,eAAE,UAAU;AAAA,QACnB,WAAW,iBAAiB,MAAM,SAAS,CAAC,uBAAuB,MAAM;AAAA,QACzE,wBAAoB,eAAE,WAAW;AAAA,QACjC,wBAAwB;AAAA,QACxB,IAAI;AAAA,QACJ,IAAI;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;AAeO,SAAS,UACd,MACA,WACA,aACoC;AACpC,MAAI,CAAC,MAAM,KAAK,UAAU,EAAE,GAAG;AAC7B,eAAO,eAAE,WAAW;AAAA,EACtB;AACA,QAAM,KAAK,MAAM,SAAS;AAC1B,MAAI,OAAO,MAAM,aAAa,IAAI,EAAE,GAAG;AACrC,eAAO,eAAE,aAAa;AAAA,EACxB;AACA,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,MAAM,aAAa;AACrB;AAAA,IACF;AACA,QAAI,KAAK,CAAC,EAAE,OAAO,UAAU,MAAM,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI;AACxD,iBAAO,eAAE,iBAAiB;AAAA,IAC5B;AAAA,EACF;AACA,SAAO;AACT;",
4
+ "sourcesContent": ["import type { JsonFormSchema } from \"@iobroker/dm-utils\";\nimport { t } from \"./lib/i18n\";\nimport { sanitizeId } from \"./lib/pure-helpers\";\nimport { TRANSPORT_LABELS } from \"./lib/ready-line\";\n\n/** Object-id segments the adapter reserves for its own tree \u2014 a device may not take them. */\nconst RESERVED_IDS = new Set([\"info\"]);\n/** IPv4 dotted-quad \u2014 the single source for both the frontend validator and the backend check. */\nconst IP_RE = /^(\\d{1,3}\\.){3}\\d{1,3}$/;\n\n/** The transports shown as card indicators \u2014 the single source shared with the ready-log line. */\nexport const TRANSPORTS = TRANSPORT_LABELS;\n\n/** One raw manual device row from `native.devices` (the name is optional). */\nexport interface ManualRow {\n /** Display name, or empty/absent when the user left it blank. */\n name?: string;\n /** The device IP address. */\n ip: string;\n}\n\n/** A running device as shown on a card, plus which source it came from (routes edit/delete). */\nexport interface CardDevice {\n /** The id-safe device id (object-tree path segment). */\n id: string;\n /** The device IP address. */\n ip: string;\n /** The card header name. */\n name: string;\n /** Where it lives: the manual `native.devices` table, or the auto-discovery store. */\n source: \"manual\" | \"discovered\";\n}\n\n/**\n * The id the object tree uses for a manual row: its name, or the ip when the name is blank.\n *\n * @param row the manual device row\n * @returns the id-safe device id\n */\nexport function rowId(row: ManualRow): string {\n return sanitizeId(row.name && row.name.length > 0 ? row.name : row.ip);\n}\n\n/**\n * The add/edit form for one receiver: a display name, the IP address and whether its volume\n * datapoints read 0\u2013100 %. The IP field\n * carries a live validator against a valid dotted-quad that is not already in use (the OK\n * button greys out on a clash). Labels are resolved translation objects so the embedded\n * form is language-correct.\n *\n * @param usedIps the IPs taken by OTHER devices (the edited device excluded)\n * @returns the jsonConfig panel schema for one device\n */\nexport function buildDeviceForm(usedIps: readonly string[]): JsonFormSchema {\n const ipList = JSON.stringify([...usedIps]);\n return {\n type: \"panel\",\n items: {\n name: {\n type: \"text\",\n label: t(\"columnName\"),\n sm: 12,\n md: 6,\n },\n ip: {\n type: \"text\",\n label: t(\"columnIp\"),\n validator: `!!(data.ip && ${IP_RE.toString()}.test(data.ip)) && !${ipList}.includes(data.ip)`,\n validatorErrorText: t(\"invalidIp\"),\n validatorNoSaveOnError: true,\n sm: 12,\n md: 6,\n },\n // Per device, not per instance: the adapter serves several receivers, and one of them\n // wanting percent says nothing about the others. Same switch as on the card \u2014 one value,\n // two places to reach it.\n volumeAsPercent: {\n newLine: true,\n type: \"checkbox\",\n label: t(\"volumeAsPercent\"),\n help: t(\"volumeAsPercent_help\"),\n sm: 12,\n md: 12,\n },\n },\n } as unknown as JsonFormSchema;\n}\n\n/**\n * A duplicate-IP/name or invalid-value clash against the other rows, as a ready-to-show\n * message \u2014 the backend safety net behind the form validator (the dialog validator may not\n * fire in every admin version; this never lets a bad row through). Each failure mode gets\n * its own message: a malformed IP is not the same problem as a name that is reserved or\n * already taken \u2014 reporting \"invalid IP\" for a name clash sends the user hunting in the\n * wrong field.\n *\n * @param rows the current manual rows\n * @param candidate the row being added/edited\n * @param exceptIndex the row position to ignore (the row being edited), or -1\n * @returns a translated clash message, or null when the row is fine\n */\nexport function findClash(\n rows: readonly ManualRow[],\n candidate: ManualRow,\n exceptIndex: number,\n): ioBroker.StringOrTranslated | null {\n if (!IP_RE.test(candidate.ip)) {\n return t(\"invalidIp\");\n }\n const id = rowId(candidate);\n if (id === \"\" || RESERVED_IDS.has(id)) {\n return t(\"invalidName\");\n }\n for (let i = 0; i < rows.length; i++) {\n if (i === exceptIndex) {\n continue;\n }\n if (rows[i].ip === candidate.ip || rowId(rows[i]) === id) {\n return t(\"duplicateDevice\");\n }\n }\n return null;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAkB;AAClB,0BAA2B;AAC3B,wBAAiC;AAGjC,MAAM,eAAe,oBAAI,IAAI,CAAC,MAAM,CAAC;AAErC,MAAM,QAAQ;AAGP,MAAM,aAAa;AA4BnB,SAAS,MAAM,KAAwB;AAC5C,aAAO,gCAAW,IAAI,QAAQ,IAAI,KAAK,SAAS,IAAI,IAAI,OAAO,IAAI,EAAE;AACvE;AAYO,SAAS,gBAAgB,SAA4C;AAC1E,QAAM,SAAS,KAAK,UAAU,CAAC,GAAG,OAAO,CAAC;AAC1C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,MACL,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,WAAO,eAAE,YAAY;AAAA,QACrB,IAAI;AAAA,QACJ,IAAI;AAAA,MACN;AAAA,MACA,IAAI;AAAA,QACF,MAAM;AAAA,QACN,WAAO,eAAE,UAAU;AAAA,QACnB,WAAW,iBAAiB,MAAM,SAAS,CAAC,uBAAuB,MAAM;AAAA,QACzE,wBAAoB,eAAE,WAAW;AAAA,QACjC,wBAAwB;AAAA,QACxB,IAAI;AAAA,QACJ,IAAI;AAAA,MACN;AAAA;AAAA;AAAA;AAAA,MAIA,iBAAiB;AAAA,QACf,SAAS;AAAA,QACT,MAAM;AAAA,QACN,WAAO,eAAE,iBAAiB;AAAA,QAC1B,UAAM,eAAE,sBAAsB;AAAA,QAC9B,IAAI;AAAA,QACJ,IAAI;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;AAeO,SAAS,UACd,MACA,WACA,aACoC;AACpC,MAAI,CAAC,MAAM,KAAK,UAAU,EAAE,GAAG;AAC7B,eAAO,eAAE,WAAW;AAAA,EACtB;AACA,QAAM,KAAK,MAAM,SAAS;AAC1B,MAAI,OAAO,MAAM,aAAa,IAAI,EAAE,GAAG;AACrC,eAAO,eAAE,aAAa;AAAA,EACxB;AACA,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,MAAM,aAAa;AACrB;AAAA,IACF;AACA,QAAI,KAAK,CAAC,EAAE,OAAO,UAAU,MAAM,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI;AACxD,iBAAO,eAAE,iBAAiB;AAAA,IAC5B;AAAA,EACF;AACA,SAAO;AACT;",
6
6
  "names": []
7
7
  }