Ask the box, don't guess from the label
Reports what every HDHomeRun tuner is receiving and who is watching it — then goes considerably further, into capability probing, proper programme listings, and publishing a guide the rest of the house can read.
Available now in the HomeSeer plugin store.
An HDHomeRun is a set of television tuners on the network with no opinion whatsoever about who uses them. That makes it excellent hardware and mildly frustrating automation: the house has no idea whether anything is being watched, recorded, or quietly holding a tuner hostage.
The protocol is the simplest thing in the building. No authentication, no pairing, no cloud — three endpoints over plain HTTP tell you what the box is, what each tuner is doing right now, and which channels it can receive. That is genuinely all it takes to turn "is anyone watching television" into something automation can act on.
One detail worth mentioning because it is not used: the discovery response also carries a per-device secret for SiliconDust's own cloud and DVR services. The plugin has no use for it, so it is never read, never stored and never logged. Credentials you do not handle are credentials you cannot leak.
Asking rather than guessing
Here is where it stops being simple, and it is my favourite part of this one.
The JSON tells you a model number and a tuner count. It does not tell you what the
hardware can actually do. Two of the boxes here transcode and two do not, and from the
HTTP API the only way to tell is to look for HDTC in the model string — which is a
guess about a naming convention, and is guaranteed to be wrong about a box that has not
shipped yet.
So the plugin opens SiliconDust's own control protocol on TCP 65001 and asks:
/sys/features channelmap: us-bcast us-cable us-hrc us-irc kr-bcast kr-cable
modulation: 8vsb qam256 qam64
transcode: heavy mobile internet540 internet480 internet360 internet240
The EXTEND lists that last line. The QUATRO has no such line at all. And nothing in the plugin needs to know what an EXTEND is — which is the entire point. A box released next year describes itself in the same words, and the code that reads it was written before that box existed.
There is a general principle hiding in there that applies well beyond tuners: ask the device what it can do, rather than inferring it from what it is called. Model-string matching is a maintenance burden disguised as a shortcut.
The guide, and why the free one was not enough
HDHomeRun's own listings service is free and needs no account, which makes it the obvious choice right up until you have a house full of sub-channels. The minor channels carrying old films and regional news often have no listings at all, and what does come through has no episode numbers, no original air dates and no series links.
So there is a Schedules Direct integration — the data the commercial guides actually use. It is four requests rather than one, which is the reason the free service is a single URL and this is three hundred lines: a token, the account's lineups, the station map, the schedules by station, and then the programme titles by ID. The last two are deliberately separate, because a schedule is a list of programme identifiers and the same programme appears on many of them.
The part that is not for us
The plugin publishes the guide it has already fetched as XMLTV and as JSON, into a folder on disk.
That is not a convenience feature. Schedules Direct limits how many times an account may log in per day. A house where HomeSeer, Jellyfin, Emby and a DVR each hold the same account and each sign in on their own schedule will hit that limit — and the failure mode is a lockout for everything at once, including the thing that was working perfectly well five minutes ago.
Publishing what has already been fetched means one consumer does the fetching and the rest read the file. The traffic it saves is not ours; it is everyone else's.
The licensing is worth stating plainly, since the code does: Schedules Direct listings are for personal use. Feeding your own media server from your own subscription on your own network is squarely inside that. A HomeSeer instance exposed to the internet is not, and those files sit in a folder HomeSeer serves without asking for a login — which was verified rather than assumed.
A correction, and the reason it is here
The original version of this post repeated a warning from the plugin's own documentation:
that HomeSeer compares plugin versions as strings, so 1.0.10.0 sorts as older than
1.0.9.0 and the update is silently never offered. It was written down confidently, dated,
marked proven the hard way, and copied into a second repository for good measure.
It is not true.
The shipped releases disprove it without any need for a test. Jellyfin went 0.1.1.9 to
0.1.1.10 and carried on through 0.1.1.13. Voice Announce shipped 0.4.0.10 and
0.4.0.11. And this plugin — the one whose documentation carried the warning — shipped
1.0.10.0 itself, the exact version named as the failure case, and then went on to
1.3.9.4 without incident.
Something genuinely did go wrong that day. An update genuinely was not offered. But the diagnosis was wrong, and being wrong is not the interesting part — surviving is. It became a rule, the rule shaped version numbers across a whole suite, and it propagated to another repository, all without anyone re-testing the claim, because it was written in the confident register we reserve for things we have learned the hard way.
The tone that makes a note memorable is the same tone that stops anyone questioning it later. Which is worth remembering the next time I write proven the hard way above something.