Problems With Power Pet Dog Door
The Original Problem
In the first few days of dog ownership it was clear to me that letting the dog in and out every time she had to pee was going to be something I would need to do tens of thousands of times over her life… Some quick research lead me to power pet doors which sell a wifi dog door. https://www.hitecpet.com/petdoors.html#petdoors-wifi
This simple door has local controls on the door for open/close/in/out/etc that all work perfect. The dog wears a transmitter on her collar the transmits an ultrasonic tone that the door listens for using 2 sensors, one on the outside and one on the inside. Using these sensors the door can be configured for in-only or out-only operation.
But the coolest feature is that this door has bluetooth and wifi and can be controlled from millions of miles away using an app for IOS and Android. This is where the problems with this product lie. The Wifi control often doesn't work, and takes to long to connect when it does work. It infact takes so long that hitting the door open button in the app usually results in my dog giving up on waiting and just peeing on the floor.
I tried many things with the same horrible results, i tried the IOS app, the Android app, the web interface. All interfaces would only respond to open commands about half the time and often when it shows a connection to the door it is not actually connected. Logging out of the app and logging in again would fix the problem every 3rd attempt or so.
I have now owned the door for 1 year, the problem has been consistant over that entire 1 year span.
The Hardware
It was obvious that something was wrong with the door… With this problem being so obvious and annoying I have to assume that the problem was on my side. I take the door apart and find that the dog door houses an ESP32 WROOM chip, and some simple circuits to detect the ultrasonic tones, door switches and a simple motor controller circuit for the motor that raises the door. There is even a nice programming header for reprograming the ESP processor. So if all else fails i could write my own firmware to fix this issue if it turns out to be a problem with the vendor.
I find the IP using my routers DHCP table and get a constant ping going to see if maybe Wi-Fi is dropping, causing the door to go unresponsive. After hours of testing I find that the Wi-Fi signal is rock solid, without any dropouts.
Figuring out how this thing works
Its obvious at this point that the problem is likely in the products firmware or server configuration/code, I will now need to know how the protocols works before we can drill in a little deeper. The TCP Protocol is a good place to start, one option would be to man in the middle the door using a wireless network in my control, but that would take some time to setup and would require some hardware, so instead I try my hand at reverse engineering the web interface at https://app.hightechpet.com/web/. Using Chrome I open the inspect tools, head over to the "network" tab and start logging in.
The login process is pretty straight forward,
- HTTP Post to https://app.hightechpet.com/api/login with Email/Password and an empty BearerToken results in a JSON Response with a RefreshToken
- HTTP GET to https://app.hightechpet.com/api/refreshToken with our RefreshToken gives us a BearerToken
- HTTP GET to https://app.hightechpet.com/api/petdoors/ with our BearerToken gets us our door details in JSON
There are 2 pieces of information in there that we care about, our ID and the ChannelKey. These are used to connect to an MQTT server that is wrapped beind a Secure Web Sockets (WSS). The MQTT username is "Support" and the MQTT server is "iot.hightechpet.com"
Creating my own Python app
With all of this new information I was able to create a python script that uses the API to grab the ID and ChannelKey and connect to the WSS server. I could then open up the Android app and get a list of all of the commands
Download HERE
- {"config":"POWER_ON","msgId":4201,"dir":"p2d"}
- {"config":"POWER_OFF","msgId":4202,"dir":"p2d"}
- {"config":"DISABLE_TIMERS","msgId":4203,"dir":"p2d"}
- {"config":"ENABLE_TIMERS","msgId":4204,"dir":"p2d"}
- {"config":"DISABLE_INSIDE","msgId":4205,"dir":"p2d"}
- {"config":"ENABLE_INSIDE","msgId":4206,"dir":"p2d"}
- {"config":"DISABLE_OUTSIDE","msgId":4207,"dir":"p2d"}
- {"config":"ENABLE_OUTSID","msgId":4208,"dir":"p2d"}
- {"config":"GET_DOOR_STATUS","msgId":4209,"dir":"p2d"}
- {"config":"GET_HW_INFO","msgId":4210,"dir":"p2d"}
- {"config":"GET_POWER","msgId":4211,"dir":"p2d"}
- {"config":"GET_SENSORS","msgId":4211,"dir":"p2d"}
- {"config":"GET_DOOR_BATTERY","msgId":4212,"dir":"p2d"}
- {"config":"CHECK_RESET_REASON","msgId":4213,"dir":"p2d"}
- {"config":"GET_SCHEDULE_LIST","msgId":4214,"dir":"p2d"}
- {"config":"GET_SETTINGS","msgId":4214,"dir":"p2d"}
- {"config":"HAS_REMOTE_ID","msgId":4215,"dir":"p2d"}
- {"config":"HAS_REMOTE_KEY","msgId":4215,"dir":"p2d"}
- {"config":"GET_DOOR_BATTERY","msgId":4216,"dir":"p2d"}
- {"cmd":"OPEN_AND_HOLD","msgId":4217,"dir":"p2d"}
- {"cmd":"CLOSE","msgId":4217,"dir":"p2d"}
- {"cmd":"OPEN","msgId":4218,"dir":"p2d"}
- {"PING":"9082340589","dir":"p2d"}
Door Events (Door transmits these)
- {"success":"true","dir":"d2p","CMD":"OPEN"}
- {"dir":"d2p","CMD":"DOOR_STATUS","success":"true","delta":0,"door_status":"DOOR_RISING"}
- {"dir":"d2p","CMD":"DOOR_STATUS","success":"true","delta":960,"door_status":"DOOR_SLOWING"}
- {"dir":"d2p","CMD":"DOOR_STATUS","success":"true","delta":1630,"door_status":"DOOR_HOLDING"}
- {"dir":"d2p","CMD":"DOOR_STATUS","success":"true","delta":1630,"door_status":"DOOR_CLOSING"}
- {"dir":"d2p","CMD":"DOOR_STATUS","success":"true","delta":1870,"door_status":"DOOR_CLOSING_TOP_OPEN"}
- {"dir":"d2p","CMD":"DOOR_STATUS","success":"true","delta":3380,"door_status":"DOOR_CLOSING_MID_OPEN"}
- {"dir":"d2p","CMD":"DOOR_STATUS","success":"true","delta":4440,"door_status":"DOOR_CLOSED"}
- {"dir":"d2p","CMD":"DOOR_STATUS","success":"true","delta":4440,"door_status":"DOOR_IDLE"}
Protocol is pretty easy to to figure out, "dir" is "p2d" for commands sent to the door and "d2p" for commands coming from the door.
It was at this point that I learned a few more details
- The server disconnects automatically after exactly 10 minutes, doesn't matter if you send pings or not
- The Door often disappears from the server for a period of exactly 10 minutes at a time
- Events from the app sometimes appear and sometimes do not appear, this problem comes and goes in 10 minute shots
- disconnecting and reconnecting my app multiple times (<3 usually) will eventually result in responses from the door.
So the problems i was seeing with the IOS and Android app are impacting my app as well. But why are all the weird results in 10 minute durations, this has to be a clue.
Getting to the bottom of the problem.
It's at this point that I had a theory, I think there are multiple MQTT servers behind a load balancer and 1 or more of those servers are not relaying information back to the other servers. I do a quick DNS resolution on the WSS servers but this is a dead end, the servers are not using DNS based load balancing.
I open up 10 instances of my python app, each one connects to the same DNS entry, each command issued shows up in about half of the other windows, if I move to the other half of the windows and issue a command, that command gets repeated in those windows but not the other half. BINGO!!!!
So there are 2 MQTT servers or clusters that the load balancer is handing out but they do not transmit messages between them. If I open the Android app or connect to the web interface I can see that randomly they connect to one of the two servers and issue a series of commands, the app always shows as connected even when connected to an MQTT server that does not have the door connected. Pressing on any buttons in those interfaces results in no action.
So now we know the problem, how do we fix it
- Let the company know, maybe they will fix their backend
- Rewrite my app to constantly (every second) query one option on the door, when no response, disconnect and reconnect, issue the command again, repeat until the door responds, stay connected until the door goes unresponsive again. This will work but may leave sections of time where the door is unresponsive for 10 seconds or more and it will hammer their server.
- Create my own WSS server, sign it with my own internal certificate and spoof the DNS for the real server on my internal network. This assumes the ESP does not validate that the cert is valid. (this is likely to work) This also has the added benefit of removing the cloud from my cloud hosted door.
- Write my own firmware for the ESP to connect to my MQTT server and ditch the cloud service.
Why me, why are not all customers complaining about this?
This is a server problem, how are more users not having this problem.
If I ping the server and then do a reverse lookup on its IP i get the real server name of 116.251.186.35.bc.googleusercontent.com. This server could very well be specific to my region of Canada. Its also now clear that Google is hosting the infrastructure for this service via Google Cloud Provider, my bet is that its using this offering https://cloud.google.com/iot-core.
C:\Users\user>ping iot.hightechpet.com
Pinging iot.hightechpet.com [35.186.251.116] with 32 bytes of data:C:\Users\user>ping -a 35.186.251.116
Pinging 116.251.186.35.bc.googleusercontent.com [35.186.251.116] with 32 bytes of data:
In Conclusion
I will send an email off to the manufacturer linking back to this article and see what traction I can get on that side. At least I know what's wrong now.
Leave a comment