Who's Home? Sniffing the Static

Hero image for Who's Home? Sniffing the Static

I can ask my phone if I'm home. It'll tell me. I can ask my watch. It'll tell me. Apple and Google both have opinions and will happily volunteer them to any app that pays enough to ask.

My house, though. My house has no idea.

The house has power meters, thermostats, cameras, sensors, and compute in almost every room. I plan remodels around a dedicated server room. Multiple bare-metal virtualization hosts. Too many network cabling tools. And yet if you asked the house right now, "is JB home," the honest answer would be a shrug.

I started poking at this because I wanted a decent morning routine. Coffee on, lights up to warm, weather forecast on the kitchen speaker. Standard smart-home stuff. Everyone builds a version of this. The version everyone builds is: my phone crosses a geofence, therefore me. That works fine until it doesn't, and once you notice the ways it doesn't, you can't unsee it. The problem is that sometimes nobody is home. Sometimes somebody else is home. Sometimes that matters, and sometimes it matters a lot.

JB: Orion and I broke a lot of things together during troubleshooting. Somewhere in the middle of a ReAct loop, it decided: "I have reasoned, as the AI, that I need to reboot this physical machine. JB, go do that." I was two timezones away.

The stack of questions gets weird fast

Once you take the question seriously, it does not stay one question for very long.

Am I home? Fine, say we can figure that out. Is somebody else who I trust home? Different phone, structurally similar problem. Is anyone home? Now we're doing set union over the humans that count. Is someone else home who I don't trust? Now it's an intrusion problem, not a coffee-pot problem, and those are entirely different questions.

Then it keeps going. Are the neighbors' devices bleeding into my measurements? (At the townhouse: constantly. There are more phones on the other side of the shared wall than in my living room.) Do I want the coffee pot to fire when the house is empty but a delivery driver walked past the porch? (No.) Do I want it to fire when a friend is over and I'm not? (Also no, but sometimes absolutely yes.) Do I want it to fire at 3 AM because a neighbor got home from the pub? (Again, no. Maybe in three more hours.)

Then, there is a whole other dimension to the question that the coffee pot doesn't have to care about but my AI agent does. Half the tasks Orion (the agent that runs my fleet) tries to plan hinge on where I physically am. Can it reboot the thing itself, or does it have to ask me? Can it wait until I'm at the mountain, or is that in three weeks? If the house knew where I was, half of those planning steps could resolve without a message ever landing in my DMs.

JB: I'm pretty sure I accidentally pick the 'wrong location' projects. Plan a drone-survey mapping system while I'm in the city? Sure! Design new kitchen-layout while I'm in the wrong kitchen? Why not! I have a knack for picking the best times to do the wrong thing.

The questions get weirder the further you push. And every honest attempt to answer any of them runs into the same problem: the framing is wrong.

The reframe

Here is the smack. You cannot ask "is someone home." You are not equipped to ask it. Your house is not equipped to answer it. There is no sensor that returns a boolean.

What you can ask: what does the RF environment around this house look like right now, and how much does it differ from what it usually looks like at this time on this day of the week?

That's a completely different problem. And it changes what "empty" means, which turns out to be the important reframe.

My house, when I am not in it, is not empty. It is full of Sonos speakers announcing themselves, a Synology yelling for backups, a fridge that has opinions about WiFi, three Apple TVs, a HomePod that never stops thinking, smart bulbs, thermostats, some ESP32 sensors I built and forgot to label, and whatever appliances with cloud connectivity I have not yet had the courage to "trust" and configure. Neighbors have theirs. Delivery drivers walk past with theirs. A UPS truck rolls by at 10:37 every weekday and its telematics unit says hello to the sky.

The house is never empty. The RF signature of "empty" is not silence. It is a particular shape of noise.

So the actual question is not "is a phone present." The actual question is: how does the current RF shape compare to the baseline for this hour, this day, this weather, this season? A single MAC flipping into range means almost nothing. A cluster of devices arriving together at 6 PM on a Tuesday, matching a shape we've seen before, means a lot.

The naive geofence-and-whitelist crowd wants to ask "did JB's iPhone MAC appear on the WiFi?" That's wrong in two directions. Modern phones aggressively randomize their MACs precisely so the answer to that question is unreliable. And even if the MAC were stable, one MAC is not a person. The shape is the identity.

One iPhone + one Apple Watch + a set of AirPods + a MacBook Bluetooth beacon, all showing up together, moving through the house in the same direction, dwelling in the same rooms for the same durations: that is one human wearing Apple. Two Androids + a Fitbit + a cheap BLE keychain: that is a couple visiting. A single randomized MAC that shows up every Thursday between 3 and 4 PM and never at any other time: that is a routine, and the routine has an owner, and I don't need to know their name to know they belong to a pattern.

The identity emerges from the cluster and the behavior, not from any single signal. That is the interesting engineering problem. It is also the actual problem, and there is no clean library that solves it for you.

Two ways to listen

Every device in and around a house broadcasts in one of two dialects, mostly. LoRa is out there. Zigbee is out there. Cellular is a whole thing. But for "who's near this house," ninety-something percent of the interesting traffic is one of:

Bluetooth Low Energy beacons. Short range (a room, maybe two), very high broadcast rate (many times a second), and a whole ecosystem of manufacturer-specific patterns layered on top. Apple's Continuity protocol is the biggest: every Apple device leaks a small pile of BLE advertisements identifying itself as an Apple thing, sometimes leaking useful things like AirPods pairing state or Apple Watch presence. BLE is good for "which room" and "is a known Apple device close." The weakness: BLE MACs randomize less aggressively on the identifiable stuff most people already own. An Apple Watch, an AirTag, a set of AirPods: much more legible than a modern iPhone, which is doing everything it can to be evasive.

802.11 probe requests. This is what your phone does when it's looking for known WiFi networks. At fairly regular intervals it shouts, "hey, is 'MyHouseWifi' around? What about 'Starbucks-Free-WiFi'? What about the guest network at the office I haven't been to in six months?" Every phone does this. It's how devices find networks they've joined before without a full active scan every time. That magic where you show up to a physical location, and your Phone/Laptop/Tablet hops back on the WiFi? This is how it does it. The range is longer than BLE (a house and its driveway, sometimes the neighbor's driveway, sometimes across the street). The broadcast rate is lower. And here's the important part: modern phones aggressively randomize the MAC address they broadcast in these probes. The MAC itself is nearly useless as an identity signal.

But the pattern of networks a device probes for is not randomized. That's a fingerprint, and a startlingly good one. A phone that probes for a specific combination of three or four semi-unusual SSIDs is very likely the same phone every time, even if its MAC changes every hour. The identity emerges from behavior, not from the MAC. A randomized MAC that shows up daily at 6 PM, probing for the same odd list of networks, is still a pattern.

Two dialects. Two range profiles. Two weaknesses. Both worth listening to, because they answer different questions. BLE answers "which room, right now, is an Apple thing close." WiFi probes answer "is a device in the house, driveway, or across the street, and has this behavior been seen before." Both feed the baseline. Both feed the diff.

A whisper in a bar, a whisper in a forest

Here is where the setup gets interesting. I run this rig at two houses, and they could not be more different as RF environments.

One is a townhouse in a dense neighborhood. The neighbors' devices bleed through the walls at full volume. Foot traffic goes by all day. Delivery drivers arrive with phones cached against the last seven addresses on their route, each one probing for a residue of SSIDs I've never heard of. Ubers idle at the curb for two minutes. The FedEx guy comes twice on Tuesdays. The neighbor across the street runs a Roomba on a schedule and it announces itself to the world every time it docks. The baseline at the townhouse is loud and churning. Detecting a new arrival there is like listening for a whisper at a bar.

The other is a mountain property, genuinely in the woods. Zero neighbors. When nobody's there, the only RF up there is the house's own device fleet: Synology, Sonos, HomePods, thermostats, lights, a weather station, some ESP32 sensors reporting their own presence. That's it. Orion has access to know everything that exists there, so anomalies are intrusions in the physical space. The baseline at the mountain is nearly silent. Anything new is immediately visible against black. Listening for a whisper in a forest.

Those two footprints answer the same question, but the methodology in each place is completely different.

At the mountain, I can detect a single visitor's phone the moment it turns into the driveway. The delta from "empty" to "one unfamiliar phone within 200 feet of the house" is huge, unambiguous, and instantly visible in logs. Detection is almost trivial once the pipeline is running. The hard problem is coverage: the property is large enough that a single sensor doesn't see all of it, and I've had to think about where each sensor sits and what corners are dark to it.

At the townhouse, that same visitor's phone would vanish into the noise. Detecting them requires first characterizing the churn: who normally walks past on a Tuesday at 3 PM, which SSIDs the neighborhood's phones probe for, what the delivery windows look like, when the neighbor's Roomba docks, when the guy on the third floor's Apple Watch comes home from work. Only once that background pattern is subtracted can a real anomaly land. The hard problem at the townhouse is not coverage. It is baseline. You cannot see a signal against noise until you have modeled the noise.

This is why I run the same in both. The mountain gives me the clean-room floor: what does detection look like when the environment is quiet and the answer is unambiguous? The townhouse gives me the real-world ceiling: does the same technique still work when the background is fifty phones per hour? Any method that only works at the mountain is a lab-only method. Any method that only works at the townhouse is missing a control. I set up a 2×2 experimental matrix (zero-neighbor × neighbor-dense × empty × populated) because these two environments are so far apart that they function as each other's sanity check.

Both sites feed a Loki telemetry pipeline that's been building a baseline since early June. Every observation is hashed on ingest, so what lands in Loki is id_h=b8e7… plus a timestamp, an RSSI, and a manufacturer OUI. No raw MAC. The mapping from hash back to raw MAC lives in a sealed sqlite file that only I can open, from one specific machine. Dashboard viewers see the hashed shape. I see the hashed shape too, most of the time. The reverse map exists for the specific case of "I want to confirm this is my wife's phone by physical correlation," and never as a default view.

JB: My work life is detection & monitoring. This concept isn't new; it's old, just utilized for telemetry around whether a security event happened that requires humans to intervene. Same concepts, new application.

The shape of an arrival

When I arrive at the mountain, a specific delta happens. An iPhone appears in the WiFi probe stream. An Apple Watch shows up in the BLE stream a few seconds later. AirPods, if I have them in. The iPhone's probe list matches a fingerprint that stays stable across MAC randomizations because the SSID list doesn't change. The BLE cluster arrives from a direction (the driveway sensor picks it up before the kitchen sensor). The delta from "empty shape" to "JB just arrived shape" is distinctive. It took me about three hours of staring at Grafana to read it visually. A real model will take longer.

But the shape is there. It is real. It is not the same shape as "Somebody else just arrived," which involves different clusters. It is not the same shape as "delivery driver walked up to the porch," which is a brief flare in one sensor with no dwell time. It is not the same shape as "a neighbor's phone briefly hit the property boundary from the road," which shows up as a single sensor observation with a specific RSSI ceiling.

JB: I can count on one hand the number of visitors we've had, un-announced, in a given year to the house. Known entities, like our favorite contractor, gets tagged with timestamps so a new pattern can emerge, be measured, and applied as an insight in the noise.

What comes next

For the BLE half of the story, I built a small fleet of ESP32 sensors. That is the next post: the sensor build, the firmware saga (the compile toolchain broke; I spun up a Linux build host in a Proxmox LXC just to get around a Python ABI break on macOS), the shipper daemon that sits between the sensors and the fabric and hashes on the way through. It is the "duct-tape competence made visible" part of this project. There is a lot of duct tape.

For the "how do you tell one shape from another" half, that is the third post: baseline deviation, anomaly detection, and the specific reason that a delta against a moving baseline is a much better identity signal than any static allow-list. The claim I'll make in that post is the shape is the identity. This post is the setup for that claim. The next one is the sensor rig that produces the data. The third is the detection theory.

Coming back to the coffee pot

Circle back. The dumb question at the top is still the point. The whole rig exists so the coffee pot fires when the RF signature matches "JB is here, moving around, in his normal morning routine (by house location)" and does not fire for any other reason. Not "a phone is present." Not "a geofence tripped." Not "a MAC address matches a whitelist." A specific compound shape, matching a pattern in the baseline diff, at a plausible time of day for a plausible number of humans.

Which is a different problem than the one I thought I was solving when I put a Shelly relay on the coffee pot circuit. It is only solvable by first sitting quietly and listening to what an empty house sounds like.

Which turns out to be: not empty at all.


This is Part 1 of "Who's Home?", a three-part series about presence detection, passive RF listening, and the epistemic problem of knowing who is (and isn't) in your own house. Part 2 is the sensor build. Part 3 is the anomaly detection.

honeypots.fail covers home automation, infrastructure projects, and what happens when you wire things together yourself. New pieces go up weekly.

JB

JB

Security engineer. RF, wireless, threat detection, and countermeasures. Now adding GenAI to the toolkit. Hiding in the Washington mountains where the only signals are mine. Part researcher, part tinkerer, all questionable decisions.
Mountains