You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hey all, I spent the evening digging into whether it's possible to add automatic device share acceptance to the HA integration (with toggle to enable/disable accepting new devices). Right now the workaround is pretty clunky: you have to log out of the integration, open the phone app, accept the share, then log back in. I wanted to see if we could just handle it silently in the background.
Turns out the rabbit hole goes pretty deep. Sharing what I found in case anyone else wants to pick it up, or has already solved a piece of it. I may resume project at a later date, but after over 5 hours of playing around (I'm not an expert at this and getting assistance from Claude code) I'm moving on, but figured I would share what I found out so far, as well as if anyone else has any input on this.
Background
The HA integration currently requires a manual workaround to accept device shares: log out of the integration, log into the phone app, accept the share, then log back in. This is because shares are delivered and accepted via MQTT, not HTTP. This post documents what I found while investigating whether this could be automated.
How Device Sharing Works
The share flow is entirely MQTT — no HTTP calls are made during either the invitation or the acceptance:
Share invitation: PetLibro server → MQTT → recipient's phone app
Share acceptance: phone app → MQTT → PetLibro server
Note: The HTTP endpoint /device/deviceShare/rec exists in the API but appears to be unused by current app versions. Testing it returns either SYSTEM_ERROR (1001) or "Share record does not exist" regardless of parameters.
MQTT Broker Details
Property
Value
Host
mqtt.us.petlibro.com
Port
8883 (TLS 1.3, mTLS)
Port 1883
Open but returns CONNACK rc=5 for all connection attempts
Authentication
Client certificate mandatory — no username/password fallback
Share topic
dl/member/{memberId}/sub
Client ID format
APP_{memberId}
The Blocker: Client Certificates
To connect to the MQTT broker, a client certificate is required. The API endpoint for generating one is POST /member/certificate/generate.
From binary analysis of libapp.so (the Flutter AOT binary), the app generates an EC P-256 (secp256r1) CSR and submits it. Despite replicating this exactly, all programmatic attempts return error 5995 ("Certificate generate failed").
Likely cause: the server requires an EJBCA end-entity pre-registration that only happens through the official app's first-login flow when a real device is registered to the account. Fresh accounts or programmatic requests are rejected.
What Was Tried
Approach
Result
Programmatic /member/certificate/generate (EC P-256 CSR, various params)
All return error 5995
mitmproxy HTTP interception (patched APK, user cert trust)
Confirmed: share acceptance makes zero HTTP calls
PCAPdroid full packet capture on port 8883
TLS 1.3 throughout — client cert encrypted in handshake
Direct MQTT connection attempts (all auth combos, ports 1883 and 8883)
All return CONNACK rc=5
The certificate is the single blocker. Without it, neither MQTT connection nor message interception is possible.
Potential Next Steps
Option A: Extract cert from app storage
Patch APK manifest: add android:debuggable="true", rebuild with apktool
Log into the official app to trigger cert generation and storage
adb shell run-as com.designlibro.petlibro
Look in /data/data/com.designlibro.petlibro/files/mmkv/ and SharedPreferences
Risk: the private key may be stored in Android Keystore (hardware-backed, unextractable even with ADB access)
Option B: Frida
Hook the app's MQTT connect() call at runtime to extract the cert bytes and log all published/received messages. Works regardless of TLS version since it reads data before encryption. More complex to set up but the most reliable path.
Option C: Pragmatic UX (no MQTT needed)
The HTTP endpoint /device/deviceShare/sharePopList works fine and returns pending share invitations. The integration could poll this on each refresh cycle and fire a HA persistent notification prompting the user to open the app and accept. Not fully automated but removes the "log out and back in" confusion.
Questions for the Community
Has anyone successfully called /member/certificate/generate programmatically? If so, what request format worked?
Does anyone know if PetLibro uses a standard EJBCA or similar PKI that has a known enrollment flow?
Is the MQTT acceptance message format documented anywhere, or has anyone captured it?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Hey all, I spent the evening digging into whether it's possible to add automatic device share acceptance to the HA integration (with toggle to enable/disable accepting new devices). Right now the workaround is pretty clunky: you have to log out of the integration, open the phone app, accept the share, then log back in. I wanted to see if we could just handle it silently in the background.
Turns out the rabbit hole goes pretty deep. Sharing what I found in case anyone else wants to pick it up, or has already solved a piece of it. I may resume project at a later date, but after over 5 hours of playing around (I'm not an expert at this and getting assistance from Claude code) I'm moving on, but figured I would share what I found out so far, as well as if anyone else has any input on this.
Background
The HA integration currently requires a manual workaround to accept device shares: log out of the integration, log into the phone app, accept the share, then log back in. This is because shares are delivered and accepted via MQTT, not HTTP. This post documents what I found while investigating whether this could be automated.
How Device Sharing Works
The share flow is entirely MQTT — no HTTP calls are made during either the invitation or the acceptance:
MQTT Broker Details
mqtt.us.petlibro.com8883(TLS 1.3, mTLS)CONNACK rc=5for all connection attemptsdl/member/{memberId}/subAPP_{memberId}The Blocker: Client Certificates
To connect to the MQTT broker, a client certificate is required. The API endpoint for generating one is
POST /member/certificate/generate.From binary analysis of
libapp.so(the Flutter AOT binary), the app generates an EC P-256 (secp256r1) CSR and submits it. Despite replicating this exactly, all programmatic attempts return error5995("Certificate generate failed").Likely cause: the server requires an EJBCA end-entity pre-registration that only happens through the official app's first-login flow when a real device is registered to the account. Fresh accounts or programmatic requests are rejected.
What Was Tried
/member/certificate/generate(EC P-256 CSR, various params)5995CONNACK rc=5The certificate is the single blocker. Without it, neither MQTT connection nor message interception is possible.
Potential Next Steps
Option A: Extract cert from app storage
android:debuggable="true", rebuild with apktooladb shell run-as com.designlibro.petlibro/data/data/com.designlibro.petlibro/files/mmkv/and SharedPreferencesOption B: Frida
Hook the app's MQTT
connect()call at runtime to extract the cert bytes and log all published/received messages. Works regardless of TLS version since it reads data before encryption. More complex to set up but the most reliable path.Option C: Pragmatic UX (no MQTT needed)
The HTTP endpoint
/device/deviceShare/sharePopListworks fine and returns pending share invitations. The integration could poll this on each refresh cycle and fire a HA persistent notification prompting the user to open the app and accept. Not fully automated but removes the "log out and back in" confusion.Questions for the Community
/member/certificate/generateprogrammatically? If so, what request format worked?All reactions