Home automation field notes All concepts

audio

The audio-video blob: eight protocols, one couch

The living room signal path: streaming to subwoofer across eight protocols, an HDMI matrix that retired a seance with a 2010 television, two infrared remotes resurrected from their specifications, and a plug that testifies about a lamp.

The living room audio chain was never designed. It accreted, one reasonable decision at a time, and the result is a signal path that crosses eight protocols between a play button and a bass note: Spotify Connect in the cloud, a streamer on the LAN, a Zigbee remote, a Bluetooth subwoofer, an eARC handshake that has changed hands once, a Chromecast and an operator's set-top box sharing an HDMI matrix, four dialects of infrared, two of them synthesized because the remotes no longer exist and one learned from a remote that only speaks infrared while its Bluetooth is asleep, and Matter over Thread to the button that starts an evening and to the plug that watches whether the projector's lamp agreed to it. None of these devices speak each other's language. All of them answer to the same couch. The address of this page still says audio blob, from the days when the blob only listened; the video half arrived later and the name on the door stayed, the way a town keeps the name of a river that has since moved.

The living room audio path is a monument to the principle that every device may speak only to the device it was designed to speak to, and to nothing else. Eight protocols between a streaming service and a subwoofer. It works, every evening, and nobody who has not seen the diagram would believe why.

Diagram of the living room audio chain: Spotify feeds the
CXN100 streamer over the cloud, the streamer feeds Kali IN-8 active monitors over balanced
XLR and the subwoofer over a stereo RCA pair, a Chromecast and an operator set-top box feed an
HDMI matrix that drives a 2010 Sony TV and a 2008 Epson projector and hands audio back to the
streamer over eARC, the projector's mains run through a metering smart plug, and Home Assistant
speaks Zigbee to the remote and the screen, LAN, Wi-Fi to the Chromecast, BLE, four dialects of
infrared, Matter over Thread to the plug and a scene button, and the Spotify cloud API as the
control plane
The blob, drawn to scale of nothing. Solid lines carry signal, wavy lines are wireless and carry only opinions; the subwoofer gets its music over honest copper and its orders over Bluetooth. The matrix in the middle arrived in September and took the eARC job away from the television. The box at the bottom is the only participant that speaks all eight languages, one of them in four accents, talks to the Chromecast over Wi-Fi in two protocols, has the Spotify cloud on speed dial as well, which is how a play button on a Zigbee remote ends up choosing a playlist in another country, and, as of this week, can tell the set-top box to wake up. The one grey line that is not audio or video is the projector's mains cord, which passes through a plug that reports current over Thread; it carries no music, only testimony.

The necromancy of eARC, and its retirement

The television is from 2010. It predates apps, assistants and most of the acronyms in this paragraph, and for a year it had exactly one modern trick: it could hand its audio to the streamer over eARC. The catch took a while to isolate: the audio only routed if the television itself woke the streamer. If the streamer was already awake when the TV came on, the handshake completed, every status light agreed, and no sound arrived. The streamer reports on; only playing means sound.

So the automation did the opposite of what intuition suggests. When the television turned on, we turned the streamer off, and let the TV resurrect it. One power cycle, executed at the only moment it helped, and eighteen years of HDMI politics were settled.

Lesson: model the handshake, not the power state. Two devices being "on" says nothing about whether the negotiation between them succeeded, and the correct automation sometimes looks exactly like sabotage.

Then a second screen arrived, and with it an HDMI matrix: four inputs, two outputs, and an eARC port of its own. The Chromecast and the operator's set-top box go in, the television and the projector come out, and the matrix, not the television, now hands audio to the streamer. The seance is over. The automation does the boring thing at last: switch the streamer on and select the eARC input, then keep a watchdog on playing and reselect if a screen is on and the sound is not.

Lesson: when the topology changes, retire the trick with it. A workaround that outlives its reason is not a workaround any more; it is a bug with a good backstory, and the power cycle that once saved the evening would now sabotage it.

The remote is dead, long live the specification

The projector is an Epson from 2008. Its remote control is wherever remotes go, and buying a replacement for a discontinued model felt like defeat. But an IR remote is not magic, it is a modulated bitstream with a published grammar, and the projector's dialect is plain NEC: a 9 ms leader, then thirty two bits at 562 microseconds a pulse, address first, command after, each followed by its complement.

leader:  9000 us mark, 4500 us space
bit 0:   562 us mark,  562 us space
bit 1:   562 us mark, 1687 us space
frame:   address 0x5583 (every Epson projector since roughly forever),
         then the command byte and its bitwise complement

The command table is public in the crowd-sourced IR databases: power on is 0x90, power off 0x91, and there are twenty five more, direct input selection included, which the buttons on the projector itself cannot do. We generated the Broadlink packets straight from the timing grammar, no learning, no original remote, and the very first synthesized packet woke the projector from across the room. A dashboard tab now carries all twenty seven commands, including a proper navigation pad, so the projector's menus are once again reachable from a seated position.

Lesson: a lost remote is an inconvenience. A lost specification would be a problem. Plastic breaks; protocols are forever, and the databases that catalogue them are one of the quiet treasures of the hobbyist internet.

The television learns the same trick

The matrix cannot switch its outputs by itself; it wants infrared, and it came with a remote, so its codes were learned the honest way: one button at a time, thirty seconds per button, and a learning routine that abandons the whole list at the first missed press. Three buttons per attempt is the rhythm that works. Inputs, outputs and the eARC toggle now live in the house's vocabulary.

The television's remote, it turned out, had gone the way of the projector's. Same cure. Its dialect is Sony's, twelve bits at 600 microsecond ticks behind a 2.4 millisecond leader, the command first and the device address after, sent three times because that is what the original does. The useful discovery in the tables was that the set has discrete power codes, one that means on and one that means off, alongside the toggle on the physical remote. Discrete codes matter more than they sound: a toggle in a dark room is a coin flip, and an automation that flips coins is not an automation. The input buttons need the fifteen bit variant, a second device address for the same television. The television is now a switch in the system: on, wait eight seconds for it to wake, select the input the matrix feeds.

Lesson: prefer discrete codes over toggles wherever a table offers them, and when a device has two address spaces, the button you want is usually in the other one.

Four buttons and an End

With two sources and two screens the couch got four combinations and one way out: each source with each screen, and End. A scene wakes the Chromecast if that is the source (it sleeps readily and does not wake for an HDMI cable), routes the matrix, powers the chosen screen, and tells the streamer to listen. End puts everything back to sleep and lets the room lighting resume its opinions.

The projector's power supply is on a metering plug that is never switched off. It speaks Matter over Thread, the eighth protocol in the room and the only one that carries neither sound nor picture, merely testimony. What the plug is for is the thirty seconds after the on-code: a lamp from 2008 does not always strike on the first attempt, and the plug's current is the only witness. Below a threshold, the code is sent again, up to twice, and the house says so. The screen, incidentally, gained half a second on its way down; a full second, on reflection, was too much.

Two smaller courtesies round it off. The television follows the Chromecast: it wakes when the Chromecast wakes, so the Chromecast's own remote is enough to start an evening, and it switches off a minute after the Chromecast goes to sleep, unless the projector is the screen in use. And a second two-rocker button joined the first, this one on Matter over Thread rather than Zigbee, which quietly made the protocol count eight; the diagram said seven for a while before anyone recounted. One press for the Chromecast on the big screen, a double press for the set-top box on it, the other rocker for End.

The set-top box that will not be told

The operator's set-top box is the one participant that answers to nobody. It lives on the operator's own router, behind the operator's own address translation, and the operator would like it to stay there. A spare VLAN on the room switch and a second leg on the automation host now reach it, which sounds like progress and is not: every port is closed, awake or asleep, no casting, no remote service, and ping answers identically in both states. Reachable and controllable turned out to be different words.

Bluetooth, then. The host's own radio can play a keyboard, and it did: the box paired, encrypted the link, and did so four times in an afternoon. It never once subscribed to a report, dropped the link after twenty seconds, never came back on its own, and after each attempt its scanner went blind until the next reboot, which buys exactly one more attempt. The lesson from the part that did work is exportable: a GATT server that registers itself per session hands the client a different attribute layout each time, and the client, quite reasonably, throws away its cache and gives up. Keep the server resident; toggle only the advertising. A microcontroller that speaks both flavours of Bluetooth is in the post, and this section will be continued.

Lesson: "reachable" is a network property and "controllable" is a policy one, and no amount of the first buys you the second. Also: attribute handles are part of the contract. Move them and you have a new device, whether or not you meant to.

Postscript, one day later. It can be told after all, provided you speak the one language it was not built to hide: infrared. The box's remote is Bluetooth, but pull the box's plug and the remote, having lost its partner, falls back to infrared like any remote from the last century, and the box has a receiver waiting for exactly that. Ten seconds without power, two presses of the power button into the learner, and the house owns a code: Manchester-coded, no leader pulse, two frames a press, identical every time, which makes it a toggle rather than an honest on or off. Replayed from a 38 kHz blaster into a 36 kHz receiver it works from across the room. It now runs at the start of the Neo scenes, guarded by the only state we have, namely which input the matrix was on, and the metering plug that will make it honest is next on the list. The box still answers to nobody on the network. It just turns out to have ears.

A subwoofer with its own page

The subwoofer started as one paragraph here and kept growing until it had more opinions than the rest of the signal path combined. At that point it stopped being a footnote to the living-room signal path and became a story about one Bluetooth link that only ever wants to hear from one caller. It has moved to its own page.

One remote to rule the blob

Holding the blob together is a small Zigbee remote that was designed to control a different manufacturer's speakers. Its community blueprint needed a fork: the upstream volume stepping only applied to grouped players, which is the kind of sentence that costs an afternoon to be able to write. It now moves volume three steps per press, and its play button first checks the streamer's input and reroutes it to Spotify when something else has wandered onto it, because a play button that plays nothing is a lie.

Its two spare gestures went to the house's sense of humour: one dot toggles the streamer's power, and a double dot asks the house spirit to show itself in colour on the nearest lamps. No protocol in the stack strictly required that last feature. It stays.

Count the seams: a cloud service, a LAN protocol, Zigbee, Bluetooth LE, eARC and CEC over HDMI, Google Cast, Matter over Thread, and raw infrared in four dialects, two learned and two written from the specification. Eight ways for machines to disagree, now with a matrix in the middle, wired into one system by the only integrator that speaks all eight. Nobody would design this. It merely works, every evening, from the first press of a play button to the last note the neighbours generously tolerate.

A screen with no bottom

The projector needed a screen, and the screen got a motor on a Zigbee shutter switch: three commands, up, down, stop. Its upper limit is honest mechanics, the screen simply cannot roll any further. Its lower limit switch is broken, so "down" means "down until somebody says stop", which is not a position a system can rely on.

The switch's automatic calibration, the one that runs the motor to both ends and times the trip, was therefore out of the question; it would have unrolled the screen into the floor looking for a switch that no longer exists.

The manual calibration turned that defect into a feature. In manual mode the switch measures the trip up, then drives down and records "fully closed" wherever the human presses the third button. We pressed it at the height that fits the picture, a hand's width above the true end.

From then on "closed" means that height: the switch times the trip itself and stops there, and every position in between is a percentage of a run that ends at the picture, not at the floor. Our first timing run was spoiled by a well-meant stop command sent during the measurement, which taught us that a calibration in progress must be left alone; the second run, done entirely from the phone standing at the screen, took thirty seconds.

The resolution is about a centimetre per percent, so the last few millimetres were settled with one very short pulse and then frozen as a cinema position at three percent. The screen follows the projector: on when the projector comes on, up when it goes off, with the buttons on the audio tab for the times when a human wants it otherwise.