diff --git a/README.md b/README.md index 4cb6e55..27fa24c 100644 --- a/README.md +++ b/README.md @@ -419,6 +419,14 @@ already submitted. The two pairing rows appear only while that transport still n pairing (a skip leaves its row there to retry; a successful pairing removes it), and the menu's description names what is still to pair. +Turning **Add the Nvidia Remote Protocol** on in the **Main setup** row of the +*options* page does not silently enable a client that cannot connect: an entry that has +never completed a pairing is taken to the same **Pair the remote protocol** step, and +its **Continue without pairing** escape turns the option back off. Pairing is remembered +per entry, so switching the transport off and on again on a paired entry asks for no new +PIN (the certificate from the first pairing is reused — see +[is my transport paired?](#is-my-protocol-transport-paired-connected-or-not-running-at-all)). + ### The Apps table The **Apps** row opens a small editor rather than one long form. Home Assistant has no @@ -767,6 +775,88 @@ All four variables are always present, including their defaults, so a script can on the shape. Unset — the default — nothing changes: keys go out over the protocol exactly as before. +### The remote entity: the app / activity picker + +The `remote` entity speaks Home Assistant's own remote contract, matching the +`androidtv_remote` entity it replaces — so a replaced setup keeps its automations +**and** gets the app picker the frontend only renders for a remote that declares it: + +| Piece | Value | +| --- | --- | +| `supported_features` | includes `RemoteEntityFeature.ACTIVITY` — without that flag Home Assistant offers **no activity picker at all**, which is why the remote card can look empty | +| `activity_list` | the friendly app names, in your order: your **Apps table** (or the built-in table when you have none), plus the apps **ADB discovery** actually found on the device | +| `current_activity` | the app on screen as a friendly name: the protocol's current-app push when it arrives, the ADB foreground reading otherwise. `None` while nothing is known — no activity is ever invented | +| `turn_on` with `activity:` | wakes the Shield when it reports itself off, then launches that app over the protocol | + +```yaml +# launch Netflix by the name from the activity list / Apps table +action: remote.turn_on +target: + entity_id: remote.living_room +data: + activity: Netflix +``` + +An `activity` resolves in this order: a **name** from the activity list +(case-insensitive), then a **package id** or a **detail link** (`https://…`, +`market://…`) passed through unchanged — that is how an app your table does not carry +is still launchable, and what the other integration does with a name it does not know. +Anything else raises a clear error naming the value instead of silently doing nothing. +Leaving `activity` out (or empty) keeps the old behaviour exactly: wake through the +configured script, else `POWER` when the device reports it is off. + +**Where the list comes from, and why.** `androidtvremote2` exposes **no app-list API +at all** (measured against the installed library) — which is exactly why +`androidtv_remote` keeps a user-maintained app map. This integration has the same kind +of source *plus* something the other one lacks: ADB discovery, so the picker can offer +what is actually installed and name it through the one chain (your Apps table → the +device's own label → the built-in table → the package id). Apps nothing can name are +not listed as bare package ids; pass their id to `activity` if you need them. + +#### Is my protocol transport paired, connected, or not running at all? + +The library offers no `is_paired` / `is_connected`, so the remote entity publishes what +can be **proven** (Developer Tools > States, or +`state_attr('remote.living_room', 'protocol_state')`): + +| Attribute | Meaning | +| --- | --- | +| `protocol_state` | `off` (no transport configured), `never_connected`, `connected`, `disconnected`, or `auth_rejected` | +| `protocol_connected` | `true` only while the device reports the protocol session up | +| `protocol_ever_authenticated` | `true` once a session connected **or any push arrived** — the only proof of a paired client the library gives | +| `protocol_current_app_seen` / `protocol_is_on_seen` / `protocol_volume_seen` | whether each device push has **ever** arrived (sticky: the state cache expires, these do not) | +| `protocol_last_error` / `protocol_failures` | the last protocol connect/send failure verbatim, and how many sends could **not** run | +| `protocol_certificate` | `present` / `missing` — the certificate from your setup pairing, which is why enabling the transport on a paired entry asks for **no new PIN** | +| `power_on_route` / `power_off_route` | `protocol`, or `script: