Most home automation is about the present: is the light on, is anyone home. The data you are already collecting can usually answer a more valuable question, what is about to need attention? Your appliances have been politely announcing their own funerals for years, in units nobody graphs.
Batteries: forecast instead of react
The standard approach is a low-battery alert, which arrives as an interruption, usually at a bad moment, usually when you do not have that cell type in the drawer. Every ingredient for something better is probably already in your system: a percentage per device, the chemistry or cell type, and often a "last replaced" date.
Fit a line through each device's recent history and extrapolate to a floor value, not to zero, because devices die well before that. Then aggregate what falls due in the next month into a shopping list by cell type. One order instead of five surprises.
Auditing the sleepers without waking them
Battery devices spend their lives asleep, which makes “is it dead?” a surprisingly rude question: the obvious check, ping it and see, wakes the device, and enough scheduled politeness of that kind will flatten the battery you were trying to protect. It also fails anyway, because a sleeping sensor that ignores you is indistinguishable from a dead one.
So the audit here is passive by rule. Mains-powered devices get probed; battery devices are judged only on what they volunteer: when they last reported, and what their voltage was when they did. A battery sensor that has said nothing for a day is noted. One that has said nothing and whose last reported voltage was sagging goes on the shopping list. Nothing sleepy is ever woken to be asked how it slept.
Heating elements: watch energy per cycle
Scale on a water heater's element does not reduce the power it draws, resistive elements draw what they draw, and, to first order, the same energy still ends up in the water, which is why thin scale is invisible in these numbers. What the trend is really fishing for is the later stages: an element insulated enough to overheat starts tripping its thermal cutout and duty-cycling, cycles stretch, standby losses grow with the stretch, and energy-per-cycle finally creeps.
So this is a lateish early warning, honest only as a trend, and the mechanism above is a hypothesis the logged cycles will confirm or embarrass. A scaled element does eventually burn out, and replacing one on your schedule is still much cheaper than on its own.
Derive cycles from power, not from the switch
The socket can be switched on while the thermostat has already cut the element. Switch state tells you nothing about whether water is being heated. Detect cycles from the power trace with hysteresis (on above one threshold, off below a lower one) and discard anything too short to be a real cycle.
Motors: watch the power factor, not the watts
A washing machine and a dishwasher each contain a motor that will eventually fail. Watching their power consumption tells you almost nothing until the day it does. The classic early signal is the power factor: a drying-out run capacitor makes a plain induction motor pull more reactive power for the same real work, and the ratio sags months ahead.
Two caveats made this humbler after review. A worn bearing moves real power and the power factor the other way (that failure lives in the energy-per-cycle trend, not here). And an inverter-driven machine, which both of these probably are, shows the wall its rectifier rather than its motor, so what is really being tracked is an electrical fingerprint per programme, and drift in it says "something changed" without naming the part. On these appliances it was already being measured and used for nothing at all, so the fingerprint is free.
The trap that makes the naive version useless
Averaging the power factor across a whole cycle produces a number that mostly tracks which programme you chose. Both machines spend most of a cycle running a heating element, and a heating element is purely resistive, power factor essentially 1.0. A hot programme therefore looks healthier than a cold one, and the trend you end up watching is your own laundry habits.
The synthetic test for this is worth writing before the real data exists: feed it a cycle whose motor runs at 85 % and whose heater runs at 99 %, and assert the result is near 85. If the band is wrong, the answer comes back near 95 and looks perfectly reasonable.
Why not just ask the appliance?
Both machines have their own integration, and both report cycle state, phase and programme. It looks like the obvious source of truth, and for cycle boundaries it is a trap:
- The washing machine's cloud service has been observed reporting Off while the drum was turning, it disconnects and the last known state keeps being served as current. Right now it reads Disconnected.
- The dishwasher's local connection can go half-dead mid-cycle, especially in the long drying tail: the entities freeze at their last value, and one cycle spent seven hours officially 75 % done. A watchdog notices the stale feed and reloads it, but a cycle-boundary source that needs its own watchdog is context, not truth.
Current draw cannot lie about whether a machine is running. So power stays the spine, and the integrations are joined on as context, which turns out to matter more than the boundaries would have.
The context is the real prize: compare like with like
Spin speed is a large confounder. A 1200 rpm spin and a 30 °C tumble put the motor at completely different operating points and therefore have genuinely different power factors. Pool them and a change in laundry habits reads as a change in motor health.
With programme and spin speed recorded per cycle, the trend is computed within the largest programme class rather than across everything. If no single class has enough cycles, it falls back to pooling them all, and says so in the output, because a comparison and a pooled comparison are not the same claim.
program_phase to pick the motor-only samples, instead of a wattage band. The phase
is a label, not a measurement of the heating element, the element cycles on and
off within a phase, so "main wash" contains both 2 kW of heating and 300 W of
circulation. The wattage measures the thing directly; the phase name only describes what the
machine believes it is doing. It gets recorded for context and is used for nothing.A string that means "no value" is still a value
The washer's cycle-phase sensor reports the literal text Unavailable. Not the
platform's unavailable state, a string, in a normal available entity, which every
"does this have a value?" check passes happily. Its load-weight sensor reports
65535, which is 0xFFFF, the firmware's way of saying it does not
know. Charted, that is a 65-tonne wash load.
Any join from a vendor integration needs an explicit list of placeholder values to discard, or you end up with a well-populated column recording a programme called "Unavailable".
Two details that decide whether it is trustworthy
- Not every plug reports apparent power. One of these two does; the other reports only volts and amps, so its apparent power is computed as their product. The appliance without the channel had been skipped in the first pass, a good reminder to check what each device exposes instead of assuming a product line is consistent with itself.
Refusing to give a verdict
One cycle means nothing; the load varies enormously. So the detector logs every cycle to a file (duration, energy, peak draw, motor-band power factor, and how many samples supported it) and offers no opinion at all below eight usable cycles. Above that it compares the median of the newest third against the oldest third and reports a relative fall.
The thresholds are frankly uncalibrated: nobody has a failing motor to hand to tune against. So they are set to be quiet, the first verdicts are explicitly a baseline being established rather than a diagnosis, and the log file is the real product. A detector that admits it is still learning is more useful than one that produces a confident number from four data points.
The mundane one that pays off constantly
Washing machines smell because the door and seal are left shut on a damp drum. The data to prevent that is trivial, a finished cycle and a door state, and no appliance does it for you. A gentle reminder a couple of hours after the cycle ends, only when the door is still closed, is one of the highest satisfaction-per-line automations you can write.
Two details make it good rather than annoying: read the "finished" moment from something that works when the vendor cloud is down (the power trace works nicely), and stay silent when nobody is home, a reminder you cannot act on is just noise.
Consumables and the same shape everywhere
Once you notice the pattern, it repeats: filters, water tanks, brush wear, cleaning cycles. The general recipe is always the same three steps.
- Find the quantity that trends, not the one that alarms.
- Project it forward crudely; order-of-magnitude is enough to be actionable.
- Batch the output into a single, actionable list rather than individual interruptions.