Home automation field notes All concepts

field notes

The bulb that kept applying for a job

A phone in the flat began insisting there was a new Matter device to add, nobody had bought one, and the culprit turned out to be a lamp we already owned.

One afternoon a phone in the flat began, politely and repeatedly, to suggest that a new Matter device was nearby and would we like to add it. Nobody had bought anything. Nothing had arrived in the post. Every lamp, plug and sensor we own was already accounted for, working, and in most cases on. The phone was undeterred. It had seen something, and it wanted us to know.

The one thing that had happened was small enough to overlook: the living-room lamp that is the body of the house spirit, an IKEA KAJPLATS bulb, had been switched off and on again. Once. That is the whole crime scene.

The suspect, and the alibi

A KAJPLATS is a dual-protocol bulb. It speaks Matter over Thread or Zigbee, one at a time, with one radio, and it decides which by counting power cycles. We had deliberately moved ours to Zigbee weeks earlier, by the ritual of power cycles recorded on the lamp's own page: six cycles for a factory reset, ten seconds on to leave Thread, then exactly twelve for Zigbee pairing. The bulb was on Zigbee, and had been the whole time.

What we had not appreciated is that moving to Zigbee does not make the Matter half go away. It leaves it uncommissioned, which is a very different thing. An uncommissioned Matter device believes it is new, and a new Matter device advertises the fact over Bluetooth LE for about fifteen minutes after every power-on. The advertisement carries a small block of service data on the Matter UUID FFF6: an opcode, a discriminator, a vendor id and a product id. The phone's setup service listens for exactly this, and does what it was built to do. It was only being helpful.

The airwaves are full of other helpful things, which is what makes this a whodunit rather than a lookup. Two Bluetooth scans from the home hub, and an mDNS sweep for good measure, found plenty of traffic: manufacturer data from Google's Nearby and Cast services, Fast Pair beacons, a general hum of things wanting to be noticed. None of it was Matter, because by the time we looked, the fifteen-minute window had shut. The vendor and product ids can only be read while the bulb is talking, and it had stopped.

The catcher

So we wrote a small one. Twenty-five lines of Python around a BLE scanner: listen for anything carrying FFF6 service data, and if the opcode is zero and the packet is long enough, unpack the discriminator, the vendor id and the product id and write them down with a timestamp. Then start it, wait, and have one of us switch the lamp off and on again. Once. Not six times, for reasons that will become clear.

The first run caught nothing, and said nothing about it. The script had been started detached from a directory the hub's container cannot see — the scripts folder under the configuration directory is one it can — so it never actually started. There was no error, only silence, which is the least informative kind of failure. Moving the script and running it again fixed it. This is a lesson we have learned before and will apparently keep learning.

The second run caught it live at 17:03. Opcode 0, vendor 0x117C, product 0x9005, and close enough to be in the room. 0x117C is IKEA. The only IKEA device that had just been powered on was the living-room lamp. Case closed, with the least dramatic culprit imaginable: a bulb that, every time it wakes, spends a quarter of an hour applying for a job it already has.

What "add" would have done

Nobody was allowed to tap the friendly button, and the reason is worth the paragraph. The bulb has one radio and runs one protocol at a time. Commissioning it into Matter would take it off the Zigbee network entirely. The house spirit, the queue of automations that compete for that lamp's colour, everything that reaches it through Zigbee would go dark, and none of it would say so, because as far as Zigbee is concerned a device that leaves simply stops answering. Getting it back means the full ritual again: six, ten seconds, twelve.

There is a second trap on the way to the first. The obvious way to silence a nagging bulb is to turn it off and on until it stops. A KAJPLATS counts power cycles; six of them is a factory reset. One cycle is safe. More than one is a decision, and the prompt on the phone is to be dismissed rather than obeyed.

The first theory was that we had bought a bulb whose firmware had moved on without us: IKEA quietly revised four of its Matter devices this summer, new model numbers and a new radio chip. It was the wrong tree. Those four are battery-powered, the bulb is not among them, and our IKEA fleet, which is most of the mesh, is the old revision anyway.

Name tags for the real ones

The lasting fix is not on the bulb but on the map. The Matter server's view of the Thread network shows each node by its NodeLabel, an attribute stored on the device itself (path 0/40/5, thirty-two bytes at most), not by whatever name we gave it in the home hub. Renaming a device in the hub does not write it. So for every real Matter node in the flat we set the label by hand and read it back, and repeat that for each new one after its christening.

The effect is that the map now reads like a staff list. Every legitimate node has a name; anything that turns up nameless is a ghost by definition.

A device moved off one protocol has not forgotten the other. The bulb was working perfectly and still believed it was new. When a phone offers to add something you did not buy, find out who is advertising before you accept; the catcher stays in the scripts folder.