The fountain runs. It is not in Home Assistant.
Bruno needs water — does his bowl need Wi-Fi? Half an afternoon, a device that quietly swaps its key, and a verdict that comes in two halves.
Contents
- What the bowl does with nothing attached
- Why I wanted it connected anyway
- The easy path was shut
- The local path, and why it does not work on this model
- The finding, and it is measured
- The error message that says the opposite of what it seems to say
- And why the before-and-after test was needed
- What remains: a second account
- The verdict
- The one question before buying
- What I would advise
- So what?
Bruno has a drinking fountain. It runs, the water moves, Bruno drinks from it. That is what the reel shows and it needs no further explanation.
The question of this series is a different one: does his bowl need Wi-Fi?
After half an afternoon the answer is clear, and it comes in two halves that have to be kept apart.
What the bowl does with nothing attached
A pump, a filter, a basin. Moving water, because dogs and cats prefer it to still water.
That works from a wall socket and needs no network. If that is all you want, you are done here and can stop reading.
Why I wanted it connected anyway
Two things, and neither is a gimmick:
| why a system knows this better than a person | |
|---|---|
| Water level | A fountain that runs dry is worse than none — the pump keeps going and the bowl is empty. |
| Filter life | Nobody remembers when the filter was last changed. A counter does. |
Both are values the device already knows. This is not about measuring something new, it is about reaching something that is already there.
As things stand today, so that nothing false sits here: there is no water-level warning in my system. The bowl is not in Home Assistant. This article explains why.
The easy path was shut
Home Assistant ships with a Xiaomi integration. It covers certain device categories — a pet fountain is not one of them.
So the usual second step: a general community integration from HACS that can address anything speaking Xiaomi’s protocol. It fetches the device token once from the manufacturer account and talks locally afterwards. A fair deal, and exactly how it should be.
That is where it failed, for a reason that has nothing to do with technology: my Xiaomi account is an old Chinese one with a phone number that no longer exists. The two-factor confirmation arrives neither by SMS nor by email.
Xiaomi serviceLoginAuth2: … → need_verify
An account you cannot get into is not an account.
The local path, and why it does not work on this model
Without an account a second path remains, and it is the interesting one: the token can be read straight off the device. In pairing mode such a device reveals it in the handshake — in the place otherwise occupied by filler bytes.
I rebuilt the protocol by hand for that. It was not wasted, because it worked:
pairing mode, token read
→ full device data: model, firmware, network …
set Wi-Fi
→ {"result": ["ok"]}
home network, same token
→ no answer, five attempts
handshake on the home network
→ ffffffff…ffffffff
└─ token withheld ─┘
The finding, and it is measured
The device issues a new token when it leaves pairing mode.
That is not a guess. Two independent observations prove it:
- Before and after within the same session. The query works in pairing mode and, with exactly the same token, no longer works on the home network.
- Two consecutive runs produced different tokens for the same device.
And a detail that completes the picture: it withholds the token even when it is bound to no account. So account binding is not the condition. The change happens on leaving pairing mode, full stop.
That closes the cloud-free path for this model. Not because of a fault, but by design.
The error message that says the opposite of what it seems to say
Here is the part where I took a wrong turn, and it is more instructive than the rest.
If the device does not answer a command, the integration internally returns an empty dictionary instead of an error. Its setup dialog does not catch that and crashes on the next access:
AttributeError: 'dict' object has no attribute 'model'
From outside this shows up as HTTP 500, “Server got itself in trouble”.
Anyone seeing that thinks of a fault in the integration. In fact the message only says: the device did not answer. Which, as a rule, means: wrong token.
I concluded the opposite. From the crash on that particular line I read that the integration had received data and the token was therefore fine. Wrong — the empty dictionary means nothing came back.
An error deep inside somebody else’s code rarely says what its top line suggests.
And why the before-and-after test was needed
Two independent implementations failed the same way here: my hand-built one and the integration’s.
A failure alone proves nothing about the token. It can just as well mean that your own tool is broken — and with two tools implementing the same protocol, the same error in reasoning can sit in both.
Only the attempt in pairing mode separated “tool broken” from “token changed”. Without that step I would have kept searching my own code, for something that is not in there.
What remains: a second account
The way out is unspectacular and it works. After a reset the device sits on Wi-Fi and is bound to no account — and precisely that state solves the problem:
- A new account with a reachable email address, region Europe.
- Sign in to the manufacturer app with it and add the bowl.
- Only then sign in from Home Assistant.
The order is the whole trick. Sign in to Home Assistant first and you find an empty account and look for the fault in the wrong place.
After that it is the normal case: the token comes from the cloud once, everything runs locally afterwards, and the app stays usable.
I have not done it — and I am not going to.
Creating a second account, maintaining it and keeping an eye on it, so that a dog bowl hands over a key once: the effort is out of proportion to what comes out at the end. It is two numbers, water level and filter life, and for both there is an alternative that has always worked — looking.
The bowl stays out. That is not a failure, it is a decision, and it deserves documenting just as much as a success. A system does not grow by taking everything in, but by taking in the right things.
The verdict
The series is called “smart or pointless”, and the answer has two halves:
| verdict | |
|---|---|
| As a fountain | Worth it. Bruno drinks from it, the water moves, the filter does its job. That needs no network and no app. |
| As a smart device | Pointless — not because it is bad, but because the only cloud-free path is closed by design and the detour was not worth the effort. |
Would I buy it again? For the dog yes. For the system no — at least not without first asking a question I did not ask back then.
The one question before buying
Not “is it compatible”. Every box answers that with yes.
But: how does the key get out of the device, and what do I need for that?
For this class of device the answer is: through a manufacturer account you have to be able to get into. Anyone with a working account has no problem. Anyone with an old one has an afternoon.
That is on no box, and it is the single point that decided this.
What I would advise
- Separate the device from its connectivity. A good fountain stays a good fountain even if it never appears in your system.
- Check the path to the key before buying, not the compatibility list. With Xiaomi that is the account question; other manufacturers call it something else.
- Tidy up your manufacturer account before you need it. A dead phone number in the second factor is noticed exactly once — when you are in a hurry.
- Read error messages from somebody else’s code with suspicion. A crash on a particular line tells you where it blew up, not why.
- Separate “my tool is broken” from “the device is doing something else”. That needs an experiment that forces the difference — for me it was the before-and-after test in pairing mode.
- Write down what does not work. The tools from that afternoon demonstrably function. On the next device from the same manufacturer, the same path may well work.
So what?
The most honest sentence about this device is the most boring one: it does what it was bought for. Bruno drinks, and that was the purpose.
What it does not do is something I added in my head — and the failure is not the device’s but a manufacturer decision you cannot see before buying: the key only leaves the device through an account.
That is the real lesson from that afternoon, and it reaches far beyond a dog bowl. For many devices “locally controllable” means: locally controllable once the cloud has agreed. The difference goes unnoticed as long as the account works.
Bruno could not care less. For him the fountain was smart enough from day one.
If you want to follow this: use RSS
No newsletter. You give me no address, I keep no list, and nobody has to agree to anything to learn that an article is finished. RSS is the older and, for both sides, the more honest solution.
How it works, and why no newsletter
- 1Get a feed reader. No account needed with an app on your phone or a browser extension; use a hosted service if you prefer.
- 2Add the address above to it.
- 3Done. New articles turn up in your reader by themselves — unread stays unread, and nothing lands between invoices and ads in your inbox.
Why that is better: your reader fetches the file. I get no address and cannot see who reads or whether anyone opened it. Unsubscribing means deleting the entry — no link, no confirmation mail, no me.
