Television

The TV at the root of one HDMI tree. A CEC bus has at most one TV, and the TV is always at physical address 0.0.0.0 and logical address 0, so spec.cec.bus identifies the TV and no address is needed. When a CECBus in Control finds a TV and no Television names that bus, the operator creates a Television with the bus’s own name and the equipment.liken.sh/discovered label. The operator owns only that object: a labeled Television under another name is a person’s. To adopt the discovered Television, apply your own Television under the bus’s name, with the spec you want. The object keeps the label, and the operator keeps it for as long as no other Television names the same bus. A Television of another name that names the same bus also works: the operator then deletes the discovered one.

spec

The protocol block and the power a person asks for. A person writes every field.

Field Type Required Description
cec object no The TV is on a CEC bus. The node workload reads the TV’s power over that bus and sends the TV its power commands.
power string no The power the operator drives the TV to. The node workload applies each generation of the spec once: each spec edit is a new metadata.generation, and it never asserts a generation again, so a person who turns the TV off with its own remote is not overruled. To ask for the same value again, edit the spec, such as by removing this field and adding it back. A new object applies its spec.power when it is created, so a Television deleted and created again, by a GitOps prune or a restore, applies its spec.power again. The node workload that sends the bus’s commands reads the TV’s power first, and sends nothing when the TV already reports the state, unless it sent the TV a command in the last 15 seconds: a TV answers its old state for a while after a command. It sends Image View On for On, or Standby to the TV alone for Standby, and reads the power every second until the TV reports the new state. A TV takes seconds to change state and reports ToOn or ToStandby while it does. When 10 seconds pass and no read showed the new state or the transition toward it, the node workload sends the command again. One generation gets at most three commands, and an application stops reading after 30 seconds. A new generation cancels an application of an older one. status.powerGeneration and the PowerApplied condition report the result. An absent field is no request, and the operator leaves the TV where it is. When two Televisions name one bus, the operator applies only the spec.power of the one in charge, which the InCharge condition names. When that one is deleted, the other takes over, and the operator applies its spec.power once then, as it does for a new object. Quote the value On in YAML, as power: “On”: kubectl reads an unquoted On as the boolean true, and the API server refuses it. Image View On also asks the TV to show a source, so a TV can switch to the input of the adapter’s Display when it wakes. One of: On, Standby.

spec.cec

The TV is on a CEC bus. The node workload reads the TV’s power over that bus and sends the TV its power commands.

Field Type Required Description
bus string yes The CECBus the TV is on. The bus must be in Control for the operator to read the TV’s power or send it a command, because Listen sends nothing.

status

What the bus reports about the TV, and what the operator applied.

Field Type Required Description
cec object no The TV as the adapters of its CECBus found it. The operator copies each fact from the TV’s entry in the CECBus’s status.devices. A fact the TV has not stated is absent: one TV answers its power status in standby and does not answer Give OSD Name.
power string no The power status the TV last reported: On, Standby, ToOn, or ToStandby. No timer asks the TV for its power, because a question on the wire is traffic, and some TVs answer traffic they did not expect by switching their own input. An adapter in Control asks the TV with Give Device Power Status when it joins the bus, before and after each command it sends the TV, and once for each press of the remote’s power button. Between those reads the power follows what the bus carries: a Report Power Status the TV sends an adapter, a Standby to the TV or to every device, which means Standby, and a Routing Change, a Set Stream Path, or a Request Active Source from the TV, or an Active Source from any device, which means On. An adapter in Control hears only the broadcasts and the messages to its own address, so a TV that a person turns off or on with its own remote and that sends none of these keeps its old power here until the next read. A press of the remote’s power button reads the TV first, so its decision does not depend on this field. A TV in a deep standby or an eco mode can stop answering. After two questions in a row without an answer, this field is absent and Reachable is False; one missed answer keeps the last power, because a TV that wakes can miss one. The operator does not report Standby for a TV that did not answer.
activeSource string no The physical address of the last Active Source the CECBus carried: the one that the first adapter in spec.adapters with a current entry that reports an Active Source reports. An adapter that has heard none is passed over. CEC has no query for the TV’s input. A TV that switches to its own apps, or to an input with no CEC, sends nothing, so this field states the last CEC source, and it does not state what the TV shows.
activeDisplay string no The Display at the physical address in activeSource, which is the machine output the TV last switched to over CEC. The operator looks first at the Displays that the CECBus’s adapters name, then at the other Displays of the machines the CECBus names, and takes the first by name when two match. It is absent when no Display has that address, such as when a streaming player or a game console is the active source, and when activeSource is absent. It states the last CEC source, the way activeSource does, and it does not state what the TV shows.
powerGeneration integer no The metadata.generation whose spec.power the node workload applied. The node workload applies a generation when it differs from this field, so a restart of the node workload applies no generation twice.
session object no The Receiver session that uses this TV. The operator’s Deployment writes it under a field manager of its own, so no other writer of the status removes it, and a person’s apply of the spec never reaches it. It is status and not spec because no person asks for it, and a status write changes no metadata.generation, so it asks nothing of spec.power. The operator reads the Display that the session’s input names as its monitor, and finds the Television whose status.displays lists that Display. It writes a new wokeAt only for a change it sees happen while it runs: a Play that starts on a standing session, a screen that wakes, the remote’s power button that turns the room on, or a session that appears with its Play or its screen already on, such as a Play on a Player with no standing session. It writes a new standbyAt only when the remote’s power button turns the room off. In its first pass after a start the operator adopts each session it finds here, with the session’s awake state and the wokeAt and standbyAt this field already holds for the same Player and Display, and wakes nothing and sends nothing to standby. A session of the same Player and Display that returns while its removal waits is the same session, and is adopted the same way. The node workload whose adapter speaks for the Display then wakes the TV and makes the Display the active source, or puts the TV in standby. When the Receiver’s session ends, its Receiver is deleted, or its Receiver’s address changes, the operator removes this field 60 seconds later, unless a session of the same Player starts first, so a session the media operator lifts and writes again for a moment keeps its wake and wakes nothing. A removal the API server refuses is tried again after 10 seconds. An operator that stops removes nothing, and the next operator adopts the session.
wokeAt string no The status.session.wokeAt of the last wake the node workload started or settled. The node workload writes it before its first command, as a started mark, so a node workload that restarts during the wake, or after it, sends nothing more for it. The WakeApplied condition states the result.
standbyAt string no The status.session.standbyAt of the last standby the node workload started or settled. The node workload writes it before its first command, as a started mark, so a node workload that restarts during the standby, or after it, sends nothing more for it. The StandbyApplied condition states the result.
screenAsk object no The last ask for the session’s Player’s screen that the node workload whose adapter speaks for the session’s Display heard on the bus. It writes the field under a field manager of its own. The media operator watches the Television objects and relays each new ask once to the Player’s screen. An ask already here when the media operator starts is older than the start, and the media operator relays nothing for it. Wake: the TV broadcast Set Stream Path for the Display while the session sleeps, which a TV sends when a person picks the input in its source menu. Sleep: the room got a Standby while the session holds it awake, broadcast by any device or sent to the adapter by the TV, which a TV sends when a person turns it off. HDMI-CEC 1.3a, CEC 13.3.2, allows a playback device to ignore Standby, and liken follows it so the room goes dark with the TV. The screen sleeps only while nothing plays.
powerRead object no The node workload’s answer to the last status.session.powerReadAt. The node workload whose adapter sends the bus’s commands writes it under a field manager of its own, after one Give Device Power Status to the TV.
displays []object no The Displays whose pictures reach this TV: the Display that each adapter of the CECBus names in spec.adapters[].display, while the bus is in Control and the Display has a physical address from its EDID. The operator derives the list. Each such adapter announces its Display’s physical address on this bus, so that Display’s picture enters this tree. A Display that no adapter names is not listed, even on a machine the bus names: that machine’s other HDMI output can go to another TV, and a physical address does not name its tree.
conditions []object no Reachable: the TV answers its power status on its CECBus. It is Unknown while the bus is in Listen or has not finished a scan, Unknown with the reason Stale when an adapter’s entry is stale, and False when the bus does not exist, when no adapter finds a TV, or when the TV acknowledges its address and does not answer. InCharge: whether this Television speaks for the TV of its bus; of two Televisions on one bus, the one not in charge names the one that is. PowerApplied: whether the TV reported the state that spec.power asked for, with the command the node workload sent, the number of commands, and the power the TV last reported. WakeApplied: what the last wake of status.session did. The node workload acts only on a wake it sees arrive: a wokeAt that is already in status.session when the node workload starts sends nothing, and the log says so. Before its first command the node workload writes the wokeAt in status.wokeAt and this condition as Unknown with the reason Waking. The wake sends Image View On the way spec.power does, then Image View On and Active Source for the Display’s physical address. A wake that answers the TV’s own Set Stream Path for the Display, heard in the 2 minutes before while the route still leads there, sends Active Source alone in each claim: the TV is on and already shows the input. Apart from that, each Active Source the adapter sends to claim the input for a person, in a wake or for a home press, follows an Image View On, as HDMI-CEC 1.3a asks of a source, because the source does not know whether the TV is in standby, and a TV that shows its own apps switches on that pair. A Standby that the adapter heard another device send the TV in the last 15 seconds counts as a recent command, so the wake then sends Image View On without trusting a power read that can still answer On. For 30 seconds after, when another source device claims the input with a bare Active Source, such as a streaming player that wakes with the room, the adapter waits 2 seconds and sends its claim again, at most twice for one wake. After that, the adapter sends no more claims for that wake. A route that a person moves ends the guard at once with no claim, because the adapter claims the input for a person and never against one: a Routing Change that leads away from the Display, which a receiver’s front panel sends, a Set Stream Path from the TV for another address, which its source menu sends, the TV’s own Active Source for 0.0.0.0, which it sends for its tuner or apps, and a Standby. A Routing Information neither ends the guard nor counts as a claim, because a switch sends it when it comes out of standby or answers a Routing Change (HDMI-CEC 1.3a, CEC 13.2.2), and the route it reports can be from before the room woke. An Active Source from another adapter of the bus ends the guard at once too. At the end of the guard the adapter reads the TV’s power again. The condition is True when the TV reported On both times and the last Active Source on the bus is the session’s Display. spec.power goes first: a wake does not start while a generation of spec.power is not applied yet, and it starts once status.powerGeneration catches up. A new generation of spec.power that arrives while a wake runs stops the wake for good, because a person’s edit is newer than the wake. The reason is Unconfirmed when the TV did not report On, SourceTaken when another source holds the input at the end, Chosen for a guard that a person’s choice of route ended, Refused when the adapter could not send, Stopped for a wake that the session’s sleep, a change of the bus, or a stop of the node workload ended, Superseded for a wake that a new generation of spec.power or another adapter’s Active Source ended, and TooLate for a wake that had not started 2 minutes after the node workload first saw it, which sends nothing. StandbyApplied: what the last standby of status.session did. The node workload whose adapter speaks for the session’s Display sends it, and acts only on a standbyAt it sees arrive: a standbyAt that is already in status.session when the node workload starts sends nothing, and the log says so. Before its first command the node workload writes the standbyAt in status.standbyAt and this condition as Unknown with the reason EnteringStandby. It sends Standby to the TV alone the way spec.power does: it reads the TV’s power first and sends nothing when the TV already reports Standby, and one standby gets at most three commands. The condition is True with the reason Confirmed when the TV reported Standby. spec.power goes first, by the rule of the wake. The reason is Unconfirmed when the TV did not report Standby, Refused when the adapter could not send, Stopped for a standby that a later wake, a change of the bus, or a stop of the node workload ended, Superseded for a standby that a new generation of spec.power ended, and TooLate for a standby that had not started 2 minutes after the node workload first saw it, which sends nothing.

status.cec

The TV as the adapters of its CECBus found it. The operator copies each fact from the TV’s entry in the CECBus’s status.devices. A fact the TV has not stated is absent: one TV answers its power status in standby and does not answer Give OSD Name.

Field Type Required Description
physicalAddress string no The TV’s physical address, 0.0.0.0.
logicalAddress integer yes The TV’s logical address, 0.
osdName string no The name the TV reports, at most 14 characters.
vendor string no The TV’s IEEE OUI, as six hex digits.
cecVersion string no The CEC version the TV reports: 1.3a, 1.4, or 2.0.

status.session

The Receiver session that uses this TV. The operator’s Deployment writes it under a field manager of its own, so no other writer of the status removes it, and a person’s apply of the spec never reaches it. It is status and not spec because no person asks for it, and a status write changes no metadata.generation, so it asks nothing of spec.power. The operator reads the Display that the session’s input names as its monitor, and finds the Television whose status.displays lists that Display. It writes a new wokeAt only for a change it sees happen while it runs: a Play that starts on a standing session, a screen that wakes, the remote’s power button that turns the room on, or a session that appears with its Play or its screen already on, such as a Play on a Player with no standing session. It writes a new standbyAt only when the remote’s power button turns the room off. In its first pass after a start the operator adopts each session it finds here, with the session’s awake state and the wokeAt and standbyAt this field already holds for the same Player and Display, and wakes nothing and sends nothing to standby. A session of the same Player and Display that returns while its removal waits is the same session, and is adopted the same way. The node workload whose adapter speaks for the Display then wakes the TV and makes the Display the active source, or puts the TV in standby. When the Receiver’s session ends, its Receiver is deleted, or its Receiver’s address changes, the operator removes this field 60 seconds later, unless a session of the same Player starts first, so a session the media operator lifts and writes again for a moment keeps its wake and wakes nothing. A removal the API server refuses is tried again after 10 seconds. An operator that stops removes nothing, and the next operator adopts the session.

Field Type Required Description
player string yes The Player that holds the Receiver’s session, as namespace/name.
display string yes The Display whose picture the session’s input carries: the monitor of that input in the Receiver’s spec.inputs.
awake boolean no Whether the session holds the room awake. It is true from a wake until the remote’s power button turns the room off or the Play and the screen are both off. When it goes false, a wake in progress stops, so the adapter claims no input in a room a person turned off. Only a new standbyAt puts the TV in standby. When it goes false with no new standbyAt, the Player’s screen went dark, and the adapter that speaks for the Display sends the TV Inactive Source for the Display’s physical address while the route still leads to the Display, so the TV can show another source or its own tuner (HDMI-CEC 1.3a, CEC 13.2.2). It then answers no request for the Display until the route leads there again. While it is true, the adapter that speaks for the Display answers a Request Active Source, and a Set Stream Path for the Display’s physical address, with Active Source for the Display, and sends no Image View On with it, so an answer to a receiver wakes no TV that a person turned off. A TV that boots, and a receiver that wakes with it, broadcast Request Active Source, and a TV that hears no answer picks an input of its own, such as its built-in home screen. The adapter does not answer a Request Active Source after the route moved away from the Display: an Active Source from another source, a Routing Change or a Routing Information for an input that does not lead to the Display, a Set Stream Path for another address, or a Standby. The source the route leads to is the active source and answers itself. The exceptions are a wake that has not sent its own Active Source yet, and a Routing Information during a wake, because the route the adapter last heard can be from before the room woke. While it is false, the adapter never answers with Active Source, so it takes no input from a person who watches another source. A Set Stream Path for the Display while it is false means a person picked the Player’s input in the TV’s source menu: the adapter sends nothing yet, because the Display has no picture, and asks the Player’s screen to wake through status.screenAsk. The wake that follows sends Active Source alone. The adapter reports its own power as On while this field is true, In transition Standby to On from such a Set Stream Path until the screen wakes, and Standby otherwise, because a playback device with no picture is in standby to the TV.
wokeAt string no When the operator saw the session wake the room, with milliseconds. Each new time is one wake. A wake is a new time and not a change of awake, because a session wakes the room again while it is awake when a person presses the remote’s power button. The node workload uses the time only as the name of one wake: it measures a wake’s age on its own clock.
standbyAt string no When the remote’s power button turned the room off, with milliseconds. Each new time is one standby of the TV. The operator writes it only for a press of the power button that finds the room on: the TV decides whether the room is on when it reports On or ToOn, and the receiver decides when the room has no Television or the TV does not answer. A Play that ends, a screen that sleeps, a session that ends, and an operator restart write none, because a TV in a living room shows other inputs, such as a streaming player, while the room’s player is idle. The same write sets awake to false, and a later wake removes this field. The node workload uses the time only as the name of one standby: it measures a standby’s age on its own clock.
powerReadAt string no When a press of the remote’s power button asked for a fresh read of the TV’s power, with milliseconds. Each new time is one request. No timer asks the TV for its power, and a TV that a person turns on or off with its own remote can send nothing the adapters hear, so status.power can be older than the press. The operator writes a new time for each press while an adapter in Control finds the TV and the session belongs to the pressing Player. That includes a Television that is not Reachable with the reason NoPowerStatus, whose status.power is empty after the TV gave no power at the join scan or on two reads, because such a TV can be on, and waits up to 3 seconds for status.powerRead to answer it. It then decides from the answer, and from status.power when no answer arrives. The node workload whose adapter sends the bus’s commands asks the TV once for each new time. A time that is already here when the node workload starts is older than the wait, and the node workload sends nothing for it. Another write of the session removes the field.
showAt string no When a press of a controller’s home key asked the TV to show the session’s Display, with milliseconds. Each new time is one ask. A TV that shows its own apps is on another input, and the receiver’s input alone does not bring the Player back, so the media operator writes a show in the Receiver’s status.session.inputAsk for a home press, and the operator writes a new time here when this session belongs to the pressing Player, names the same Display, and is awake. It writes nothing for a session that is asleep, because a home press does not wake a room that is off. The node workload whose adapter speaks for the Display asks the TV for its power once, and when the TV reports On or ToOn it sends Image View On and then Active Source for the Display. It sends Image View On even to a TV that reports On, because a TV on an internal app switches on that pair, the sequence One Touch Play sends, and not on a bare Active Source. It sends nothing to a TV in standby, and nothing during a wake, which claims the input itself. A time that is already here when the node workload starts is older than the press, and the node workload sends nothing for it. Another write of the session removes the field.

status.screenAsk

The last ask for the session’s Player’s screen that the node workload whose adapter speaks for the session’s Display heard on the bus. It writes the field under a field manager of its own. The media operator watches the Television objects and relays each new ask once to the Player’s screen. An ask already here when the media operator starts is older than the start, and the media operator relays nothing for it. Wake: the TV broadcast Set Stream Path for the Display while the session sleeps, which a TV sends when a person picks the input in its source menu. Sleep: the room got a Standby while the session holds it awake, broadcast by any device or sent to the adapter by the TV, which a TV sends when a person turns it off. HDMI-CEC 1.3a, CEC 13.3.2, allows a playback device to ignore Standby, and liken follows it so the room goes dark with the TV. The screen sleeps only while nothing plays.

Field Type Required Description
at string yes When the node workload heard the message, with milliseconds. Each new time is one ask.
player string yes The Player whose screen the ask is for, as namespace/name.
screen string yes What the ask asks of the screen. One of: Wake, Sleep.
cause string no The message the node workload heard, in words, for the Deployment’s log line.

status.powerRead

The node workload’s answer to the last status.session.powerReadAt. The node workload whose adapter sends the bus’s commands writes it under a field manager of its own, after one Give Device Power Status to the TV.

Field Type Required Description
at string yes The status.session.powerReadAt that this read answers.
power string no The power status the TV reported: On, Standby, ToOn, or ToStandby. It is absent when the TV did not answer.

status.displays[]

The Displays whose pictures reach this TV: the Display that each adapter of the CECBus names in spec.adapters[].display, while the bus is in Control and the Display has a physical address from its EDID. The operator derives the list. Each such adapter announces its Display’s physical address on this bus, so that Display’s picture enters this tree. A Display that no adapter names is not listed, even on a machine the bus names: that machine’s other HDMI output can go to another TV, and a physical address does not name its tree.

Field Type Required Description
name string yes The Display.
physicalAddress string yes The Display’s physical address, from display-operator, in the dotted form 1.3.0.0.
via object no The Receiver the picture passes through: a Receiver with an input that names this Display’s machine and this Display as its monitor, when the CECBus has an audio system above the Display in the tree. The physical address shows the path: a receiver at 1.0.0.0 is above a Display at 1.3.0.0 and not above one at 2.0.0.0. It is absent when no Receiver is on the path, such as for a Receiver whose optical input names a Display that is connected straight to the TV.

status.displays[].via

The Receiver the picture passes through: a Receiver with an input that names this Display’s machine and this Display as its monitor, when the CECBus has an audio system above the Display in the tree. The physical address shows the path: a receiver at 1.0.0.0 is above a Display at 1.3.0.0 and not above one at 2.0.0.0. It is absent when no Receiver is on the path, such as for a Receiver whose optical input names a Display that is connected straight to the TV.

Field Type Required Description
kind string yes The kind of the object, Receiver.
name string yes The object’s name.

status.conditions[]

Reachable: the TV answers its power status on its CECBus. It is Unknown while the bus is in Listen or has not finished a scan, Unknown with the reason Stale when an adapter’s entry is stale, and False when the bus does not exist, when no adapter finds a TV, or when the TV acknowledges its address and does not answer. InCharge: whether this Television speaks for the TV of its bus; of two Televisions on one bus, the one not in charge names the one that is. PowerApplied: whether the TV reported the state that spec.power asked for, with the command the node workload sent, the number of commands, and the power the TV last reported. WakeApplied: what the last wake of status.session did. The node workload acts only on a wake it sees arrive: a wokeAt that is already in status.session when the node workload starts sends nothing, and the log says so. Before its first command the node workload writes the wokeAt in status.wokeAt and this condition as Unknown with the reason Waking. The wake sends Image View On the way spec.power does, then Image View On and Active Source for the Display’s physical address. A wake that answers the TV’s own Set Stream Path for the Display, heard in the 2 minutes before while the route still leads there, sends Active Source alone in each claim: the TV is on and already shows the input. Apart from that, each Active Source the adapter sends to claim the input for a person, in a wake or for a home press, follows an Image View On, as HDMI-CEC 1.3a asks of a source, because the source does not know whether the TV is in standby, and a TV that shows its own apps switches on that pair. A Standby that the adapter heard another device send the TV in the last 15 seconds counts as a recent command, so the wake then sends Image View On without trusting a power read that can still answer On. For 30 seconds after, when another source device claims the input with a bare Active Source, such as a streaming player that wakes with the room, the adapter waits 2 seconds and sends its claim again, at most twice for one wake. After that, the adapter sends no more claims for that wake. A route that a person moves ends the guard at once with no claim, because the adapter claims the input for a person and never against one: a Routing Change that leads away from the Display, which a receiver’s front panel sends, a Set Stream Path from the TV for another address, which its source menu sends, the TV’s own Active Source for 0.0.0.0, which it sends for its tuner or apps, and a Standby. A Routing Information neither ends the guard nor counts as a claim, because a switch sends it when it comes out of standby or answers a Routing Change (HDMI-CEC 1.3a, CEC 13.2.2), and the route it reports can be from before the room woke. An Active Source from another adapter of the bus ends the guard at once too. At the end of the guard the adapter reads the TV’s power again. The condition is True when the TV reported On both times and the last Active Source on the bus is the session’s Display. spec.power goes first: a wake does not start while a generation of spec.power is not applied yet, and it starts once status.powerGeneration catches up. A new generation of spec.power that arrives while a wake runs stops the wake for good, because a person’s edit is newer than the wake. The reason is Unconfirmed when the TV did not report On, SourceTaken when another source holds the input at the end, Chosen for a guard that a person’s choice of route ended, Refused when the adapter could not send, Stopped for a wake that the session’s sleep, a change of the bus, or a stop of the node workload ended, Superseded for a wake that a new generation of spec.power or another adapter’s Active Source ended, and TooLate for a wake that had not started 2 minutes after the node workload first saw it, which sends nothing. StandbyApplied: what the last standby of status.session did. The node workload whose adapter speaks for the session’s Display sends it, and acts only on a standbyAt it sees arrive: a standbyAt that is already in status.session when the node workload starts sends nothing, and the log says so. Before its first command the node workload writes the standbyAt in status.standbyAt and this condition as Unknown with the reason EnteringStandby. It sends Standby to the TV alone the way spec.power does: it reads the TV’s power first and sends nothing when the TV already reports Standby, and one standby gets at most three commands. The condition is True with the reason Confirmed when the TV reported Standby. spec.power goes first, by the rule of the wake. The reason is Unconfirmed when the TV did not report Standby, Refused when the adapter could not send, Stopped for a standby that a later wake, a change of the bus, or a stop of the node workload ended, Superseded for a standby that a new generation of spec.power ended, and TooLate for a standby that had not started 2 minutes after the node workload first saw it, which sends nothing.

Field Type Required Description
type string yes
status string yes One of: True, False, Unknown.
observedGeneration integer no
reason string no
message string no
lastTransitionTime string yes