Skip to main content

Remote — remote

A handheld remote, and the one input whose buttons already mean something.

This is the distinction from keypad, and the whole reason it is a separate contract. A keypad reports that key 3 was clicked, and key 3 means whatever a rule says it means — which is correct for a Pico on a wall, where the buttons are blank and the intent lives in the project. A remote is the opposite: it has Play, Vol + and a d-pad printed on it, the person holding it already knows what they will do, and making somebody author fifty rules to say so is the programming step this contract exists to delete.

So a remote emits named commands from a fixed vocabulary, and the vocabulary is deliberately the command names room, media_player and tv already use. A volume_up from a remote bound to the Living Room is room::volume_up in the Living Room — the pathfinder already knows which device owns that room's volume, and it changes when somebody watches something else. Nothing about the remote had to be reprogrammed, because the remote never named a device.

That is the property worth protecting: a remote addresses a room, never a device. Point it at a device and it is a learning remote with a macro list, which is the thing every one of these systems was built to replace.

Not every button is universal, and pretending otherwise is how contracts like this go wrong. A softkey, a colored teletext key and a "List" button mean nothing outside the box that shipped them, so they do not get forced into the enum — they arrive as custom, carrying the label the device prints on itself, and a rule binds them exactly as it would a keypad's key. One contract, two honest halves: what the house can route on its own, and what still needs somebody to say.

Like keypad, this resolves to no commands at all. There is nothing to ask of a remote.

Capabilities​

Declared in the driver manifest under [[proxy]] capabilities. Anything not declared takes the default below.

CapabilityTypeDefaultMeaning
custom_labelsstring""What the non-universal keys are called, comma separated, in the order the device reports them —
"Soft Lft,Red,Green,List". These are the labels a custom notification carries, and a rule editor
offers them by name rather than by index.
has_batteryboolfalse
has_channelboolfalseChannel up/down, which is not the same as skip — see channel_up
has_dimmingboolfalseBrighter and dimmer keys. A four-button dimmer's middle pair, and the reason they are here rather
than folded into volume: room::dim_up is relative to wherever each light already is, which is the
one thing an absolute level cannot express — see that command's note. A remote with has_repeat
gets a ramp from the same rule for free.
has_dpadboolfalseArrows and a select key
has_holdboolfalseTells a held key from a tapped one, which is what turns a volume step into a ramp
has_menuboolfalseMenu, guide, info, exit — the keys that open something
has_numericboolfalseDigits 0-9, and usually enter
has_powerboolfalseDiscrete on and off keys rather than a single toggle
has_repeatboolfalseReports repeatedly while a key is held
has_transportboolfalsePlay, pause, stop and the scan/skip keys
has_volumeboolfalse

Notifications​

battery_changed​

Only present when has_battery is declared true.

ParameterTypeNotes
percentu8 0–100

command​

A button with a universal meaning was used. This is the notification the house routes without being told how: command names an intent that room, media_player or tv already accepts, so it resolves against whatever the room is currently doing.

action is what was done to the key, and it matters as much as which key it was. A click on volume_up is a step; a hold on it is a ramp, and the consumer answers that with media_player::hold { what = "volume_up" } rather than by re-sending forty steps — see that command's note on why those are not the same thing. release closes a hold; repeat is for hardware that streams while a key is down, which a step-per-tick rule wants and a ramp does not.

The vocabulary is closed on purpose. An open string would mean every consumer carrying a table of spellings, and the first remote that said vol_up instead of volume_up would fail silently at the far end. A button that does not fit sends custom instead, which is exactly what that is for.

ParameterTypeNotes
actionone of click · double · hold · release · repeat
commandone of play (needs has_transport) · pause (needs has_transport) · play_pause (needs has_transport) · stop (needs has_transport) · record (needs has_transport) · skip_forward (needs has_transport) · skip_back (needs has_transport) · scan_forward (needs has_transport) · scan_reverse (needs has_transport) · up (needs has_dpad) · down (needs has_dpad) · left (needs has_dpad) · right (needs has_dpad) · select (needs has_dpad) · back (needs has_menu) · exit (needs has_menu) · menu (needs has_menu) · home (needs has_menu) · guide (needs has_menu) · info (needs has_menu) · volume_up (needs has_volume) · volume_down (needs has_volume) · mute_toggle (needs has_volume) · dim_up (needs has_dimming) · dim_down (needs has_dimming) · channel_up (needs has_channel) · channel_down (needs has_channel) · previous_channel (needs has_channel) · power_on (needs has_power) · power_off (needs has_power) · power_toggle (needs has_power) · enter (needs has_numeric)

custom​

A button with no universal meaning: a softkey, a colored key, a vendor's own function. It carries the label the device prints, so a rule reads "Red" rather than "key 46", and an index so two keys printed the same are still distinguishable.

This is the escape hatch that keeps the command vocabulary honest. Without it, every device- specific button would either be dropped or crammed into the enum under a name nothing else uses — and an enum that means something different per device is a string with extra steps.

ParameterTypeNotes
actionone of click · double · hold · release · repeat
indexu32 ≥1Position in custom_labels, from 1.
labelstringWhat the device prints on it.

digit​

Only present when has_numeric is declared true.

A number key. Separate from command because a digit is a value rather than an intent — ten more entries in that enum would say the same thing ten times, and a consumer that wants to build a channel number wants to accumulate an integer, not switch on "digit_7".

ParameterTypeNotes
actionone of click · double · hold · release · repeat
valueu8 0–9

online_changed​

ParameterTypeNotes
onlinebool

State​

Last-known values core keeps for a binding of this proxy.

KeyTypeMeaning
batteryu8
last_commandstringWhat the remote last sent, action included — "volume_up hold". A remote that is working and a remote that is not look identical until this is on screen.
onlinebool