This is (currently) a prototype AppDaemon-based application to integrate Petlibro's Automatic Feeder model PLAF203S into home assistant using MQTT. This enables users to control and monitor their device locally without Petlibro's proprietary App and Cloud platform.
I am releasing my research and code to the public so interested hackers and home enthusiasts can pick it up and take it to the next level. It would make me glad to see this research serves as a foundation for creating a proper home assistant integration for these devices.
The goal of this project is (currently) NOT to provide a fully working and battle tested integration for the device and it's different models and versions.
I am appreciating any comments/suggestions or contributions to this in the form of issues or pull requests with bugfixes or improvements and I eventually look into these. However, I have no intentions nor capacity to become a maintainer of this.
Source code license is the Unlicense; you are permitted to do with this as thou wilt. For details, please refer to the LICENSE file included with the source code.
All of my research and implementation is based on a PLAF203S
device with:
1.0.7
3.0.14
Even the feeders look identical from the outside, the hardware and software stack are very different.
More information can be found on the home assistant forums already.
The key difference relevant to kicking off the reverse engineering efforts here were:
Luckily, the device has three pins on the PCB exposed and easily accessible which are RXD
, TXD
and GND
to hook up a serial console via a serial adapter USB adapter with the baudrate set to
115200
. The device outputs all terminal output, from initial bootloaders, the kernel and userspace
to the serial console.
For example, using minicom:
minicom --capturefile capture.dump --baudrate 115200 --device /dev/tty.usbserial-130
Which also writes all output to a file called capture.dump
which was very useful to come back to
package dumps that I created while playing around with the official app.
Furthermore, the main application is also very verbose with a lot of useful debug output to understand and debug application and device behavior including full MQTT sent and received message dumps.
Remark: I haven't been able to send keyboard inputs to the device which would have allowed me to interrupt the boot process and probably use the shell that is spawned during the boot process.
In order to get the device on-boarded and accessible on my local network, I used the official petlibro app once to pair the device to my local wifi. Once that was finished, I blocked all access to the outside for the device as that's not needed anymore for running it fully local (without using the official app).
mqtt.us.petlibro.com
us-mqtt-0.aiotlibro.com
us-mqtt-0.dl-aiot.com
mqtt.us.petlibro.com
to my own local MQTT server instance1883
which is somewhat questionable from
a security perspective under intended usage, but useful in this case to get it connected easily on
my local networkMQTTConnect retry,DL_PRODUCT_KEY:<KEY>, DL_PRODUCT_SECRET:<SECRET>, DL_MQTT_ADDR:mqtt.us.petlibro.com, DL_DEVICE_ID:<ID>
DL_PRODUCT_KEY
= usernameDL_PRODUCT_SECRET
= passwordDL_DEVICE_ID
will be the name of the device in mqttThe current project structure is kept as a simple "mono-file" which makes it fairly straight forward to deploy it to AppDaemon:
plaf203.py
file to your appdaemon/apps
folderapps.yaml
to your AppDaemon installation's apps.yaml
serial_number
with your device's serial number which is the DL_DEVICE_ID
you
need to acquire somehowmqtt_host
with either the hostname or IP of your MQTT brokerINFO plaf203: Initializing plaf203, serial number 00000000000000000
dl/plaf203/...
are created on your brokerPet libro cat feeder
All configuration options of the feeder are exposed as writable configuration entities on the MQTT device such as switches, text, sliders, number boxes or drop-down lists.
Most of these should be self-explanatory, except for the food plans. Currently, up to 10 food plans can be configured. The food plan defines when the feeder is outputting a specific amount of food automatically.
This is currently implemented by providing a json formatted data structure on the available configuration entities. Contributions to make this more user-friendly but also avoiding complexity are very welcome.
Here is an example of one food plan that runs daily at 19:00 with the feeding sound disabled and
outputs 3 portions. Just copy-paste into one or multiple food plan slots and make sure the id
field differs (just increment it, that's sufficient).
{"id": 1, "execution_time": {"hour": 19, "minute": 0}, "scheduled_days": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"], "enable_audio": false, "play_audio_times": 1, "grain_num": 3}
Scheduled days is a set of days when to run the plan.
Capture the network traffic and also looking into the firmware, I discovered the following hostnames and IP addresses that are either used or potentially used:
mqtt.us.petlibro.com
us-mqtt-0.aiotlibro.com
us-mqtt-0.dl-aiot.com
54.156.99.57
-> Petlibro MQTT on AWS in US44.211.92.174
-> tutk ip?139.162.174.232
-> Akamai? Maybe for the feeding audio asset(s) mqtt.us.petlibro.com
:1883sit-svc.dl-aiot.com
:1883demo-svc.dl-aiot.com
:1883mqtt.dl-aiot.com
:1883test.svc.dl-aiot.com
:1883kalay.net.cn
kalayservice.com
iotcplatform.com
sub
dl/plaf203/00000000000000000/device/service/sub
post
dl/plaf203/00000000000000000/device/service/post
post
dl/plaf203/00000000000000000/device/event/post
sub
dl/plaf203/00000000000000000/device/event/sub
heart
: Heartbeat messages from deviceota
: Over the air firmware updatesntp
: NTP time synchronization for devicebroadcast
: Some currently unknown broadcast channel?config
: Device/system configuration related, direction: server -> deviceevent
: Main channel for feeder product features communication, direction: device -> serverservice
: Main channel for feeder product features communication, direction: server -> devicesystem
: System related commands: direction: server -> devicecmd
: The command/message type identifier (see plaf203.py
at the top for all commands and
documentation)message_id
: Unique identifier for messages, IDs of responses have to match requeststimestamp
: Unix-epoch timestamp in milliseconds (UTC)tutk
in the firmware which is the Kalay SDK of ThroughTek
No actual work has been done on this. It seems to require a re-implementation of the server to talk to the client portion of the device correctly in order to implement local video streaming.
Maybe there is an easier solution to modify the system once it is possible to access it.