docs(readme): the app list as sources, the remote command script, current versioning (t47 D)
t46 F2: the status line still cited `v2026.10.08`. It now describes the scheme (`vYYYY.MM.DD`, plus `vYYYY.MM.DD.N` for a second release in the same day) and links to the Releases section, so it cannot go stale again. The other dated reference stays: "v2026.10.09 shipped that way" is the historical example that motivated the write-back, and it is accurate. New "Sources (the app list in a dropdown)" section: source_list from the Apps map (with the built-in fallback named, so a card is never empty), `source` resolved exactly like the Current App sensor, and `media_player.select_source` by name — accepting a raw package id and any case, erroring on an unknown name — with a copy-pasteable service call. It also points at the Select source script as the override for the "more than launching an app" case. New "Remote command script" subsection: the four variables in a table (command, num_repeats, delay_secs, hold_secs) with their meanings and defaults, and a copy-pasteable script that forwards the call to an IR bridge. It states that all four are always present including defaults, and that unset changes nothing. Corrected the two claims UNIT A invalidated: the command table no longer says select_source has no native path, and the paragraph no longer says it is offered only while a script is configured. Every fenced YAML block in the README still parses with a real parser (5 now), and tests/test_readme.py is green.
This commit is contained in:
1 parent
c3e4c7855c
commit
1c6c223f27
1 file changed
+81
-9
@@ -9,7 +9,9 @@ This is a **Shield-only fork** of [ltomes/ha-nvidia-shield](https://github.com/l
|
|||||||
ADB as the state source, and no dependency on separate `androidtv` / `androidtv_remote`
|
ADB as the state source, and no dependency on separate `androidtv` / `androidtv_remote`
|
||||||
integrations.
|
integrations.
|
||||||
|
|
||||||
> **Status:** early fork, actively rebuilt. Releases are date-based (`v2026.10.08`).
|
> **Status:** early fork, actively rebuilt. Releases are date-based
|
||||||
|
> (`vYYYY.MM.DD`, plus `vYYYY.MM.DD.N` for a second release in the same day) —
|
||||||
|
> see [Releases](#releases) for how a push becomes one.
|
||||||
> Expect rough edges until the MVP phases land. The build-out plan is in
|
> Expect rough edges until the MVP phases land. The build-out plan is in
|
||||||
> [`docs/MVP_PLAN.md`](docs/MVP_PLAN.md); device research is in
|
> [`docs/MVP_PLAN.md`](docs/MVP_PLAN.md); device research is in
|
||||||
> [`docs/RESEARCH_SHIELD.md`](docs/RESEARCH_SHIELD.md).
|
> [`docs/RESEARCH_SHIELD.md`](docs/RESEARCH_SHIELD.md).
|
||||||
@@ -286,7 +288,8 @@ helper the flow calls is a coroutine and its dedup only runs when awaited.
|
|||||||
transport on or off
|
transport on or off
|
||||||
- **Shield address / ADB port** — the Shield's IP, and the ADB port if you
|
- **Shield address / ADB port** — the Shield's IP, and the ADB port if you
|
||||||
changed it from 5555
|
changed it from 5555
|
||||||
- **Command scripts** — one optional script per command; see below
|
- **Command scripts** — one optional script per command, plus one for the remote
|
||||||
|
entity; see below
|
||||||
|
|
||||||
### Command scripts (per-command overrides)
|
### Command scripts (per-command overrides)
|
||||||
|
|
||||||
@@ -301,13 +304,14 @@ command**:
|
|||||||
| `volume_up`, `volume_down` | volume step | — |
|
| `volume_up`, `volume_down` | volume step | — |
|
||||||
| `volume_set` | absolute volume (there is no native path — the protocol has VOLUME_UP/DOWN/MUTE only) | `level` |
|
| `volume_set` | absolute volume (there is no native path — the protocol has VOLUME_UP/DOWN/MUTE only) | `level` |
|
||||||
| `volume_mute` | mute/unmute | `is_volume_muted` |
|
| `volume_mute` | mute/unmute | `is_volume_muted` |
|
||||||
| `select_source` | source selection (no native path) | `app_name` |
|
| `select_source` | source selection (the app list drives it natively; a script overrides) | `app_name` |
|
||||||
|
|
||||||
A command with a script calls the script **instead of** the protocol/ADB path, never
|
A command with a script calls the script **instead of** the protocol/ADB path, never
|
||||||
both. Left unset — the default — every command behaves exactly as it did before, and
|
both. Left unset — the default — every command behaves exactly as it did before, and
|
||||||
clearing a selector on the Configure page restores that. `volume_set` and
|
clearing a selector on the Configure page restores that. Two of the seven appear as
|
||||||
`select_source` only appear as services while their script is configured, because
|
services only when there is something to do: `volume_set`, which has no native path at
|
||||||
there is nothing native to fall back on.
|
all, and `select_source`, which is offered once the integration has sources to offer
|
||||||
|
(the app list below) — or a script.
|
||||||
|
|
||||||
The scripts are ordinary Home Assistant scripts. This block covers all three awkward
|
The scripts are ordinary Home Assistant scripts. This block covers all three awkward
|
||||||
cases: a speaker switch owning the volume, an AVR owning the input, and a mute that
|
cases: a speaker switch owning the volume, an AVR owning the input, and a mute that
|
||||||
@@ -350,9 +354,77 @@ Then set `script.shield_volume` as **Volume set script**, `script.shield_source`
|
|||||||
**Select source script** and so on on the Configure page. Scripts are set there, not
|
**Select source script** and so on on the Configure page. Scripts are set there, not
|
||||||
in the YAML seed above — the seed only carries the address and the transport choice.
|
in the YAML seed above — the seed only carries the address and the transport choice.
|
||||||
|
|
||||||
A script that fails surfaces as an error on the service call that triggered it (the
|
A script that fails surfaces as a translated error on the service call that triggered
|
||||||
command is not retried over protocol/ADB), because a silent no-op is the one outcome
|
it (the command is not retried over protocol/ADB), because a silent no-op is the one
|
||||||
that leaves you guessing.
|
outcome that leaves you guessing.
|
||||||
|
|
||||||
|
### Sources (the app list in a dropdown)
|
||||||
|
|
||||||
|
The media player's source list is your **Apps** map — the same map the Browse tree and
|
||||||
|
app-name resolution use. With no map configured it falls back to a small built-in list
|
||||||
|
(TiviMate, Wholphin, Netflix, YouTube), so a universal-media-player card always has
|
||||||
|
something to show:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# a media-player card, or anything that reads source_list
|
||||||
|
type: media-control
|
||||||
|
entity: media_player.living_room_shield
|
||||||
|
```
|
||||||
|
|
||||||
|
- **`source_list`** — the app names. They come from the map (in the order it lists
|
||||||
|
them), so editing the map renames the dropdown entries.
|
||||||
|
- **`source`** — the app currently on screen, resolved exactly like the Current App
|
||||||
|
sensor: your map first, then the cached device label, then the raw package.
|
||||||
|
- **`media_player.select_source`** — picks one **by name** and launches it over the
|
||||||
|
protocol, the same path `play_media` uses for apps. A raw package id works too (that
|
||||||
|
is what the Browse tree publishes), names match case-insensitively, and a name that
|
||||||
|
is not in the list is an error rather than a silent no-op:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
action: media_player.select_source
|
||||||
|
target:
|
||||||
|
entity_id: media_player.living_room_shield
|
||||||
|
data:
|
||||||
|
source: TiviMate
|
||||||
|
```
|
||||||
|
|
||||||
|
Selecting a source is sometimes more than launching an app — an AVR input, a speaker
|
||||||
|
switch. That is what the **Select source script** above is for: with one configured it
|
||||||
|
replaces the native launch entirely.
|
||||||
|
|
||||||
|
### Remote command script
|
||||||
|
|
||||||
|
`remote.send_command` sends protocol keys: repeats, long presses (`START_LONG`/
|
||||||
|
`END_LONG`) and inter-repeat delays. Some setups need that call to go somewhere else —
|
||||||
|
an IR bridge, a macro, a second device — so one optional **Remote command script**
|
||||||
|
replaces the whole key path when it is set. It receives the service's own parameters,
|
||||||
|
named as they are on the service:
|
||||||
|
|
||||||
|
| Variable | Meaning |
|
||||||
|
| --- | --- |
|
||||||
|
| `command` | the list of key commands as submitted, e.g. `["HOME", "KEYCODE_DPAD_CENTER"]` |
|
||||||
|
| `num_repeats` | how many times to send them (default `1`) |
|
||||||
|
| `delay_secs` | the delay between repeats in seconds (default `0.0`) |
|
||||||
|
| `hold_secs` | the requested long-press duration (default `0.0`) — the script owns the key semantics, so it decides what "hold" means |
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
script:
|
||||||
|
shield_remote: # select as "Remote command script"
|
||||||
|
alias: Shield remote (IR bridge)
|
||||||
|
sequence:
|
||||||
|
- action: remote.send_command
|
||||||
|
target:
|
||||||
|
entity_id: remote.living_room_bridge
|
||||||
|
data:
|
||||||
|
command: "{{ command }}" # a list: pass it through
|
||||||
|
num_repeats: "{{ num_repeats }}"
|
||||||
|
delay_secs: "{{ delay_secs }}"
|
||||||
|
hold_secs: "{{ hold_secs }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
All four variables are always present, including their defaults, so a script can rely
|
||||||
|
on the shape. Unset — the default — nothing changes: keys go out over the protocol
|
||||||
|
exactly as before.
|
||||||
|
|
||||||
## Entities
|
## Entities
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user