Files
franklinwh-agate-client/README.md
T
kfj001 a87dbe200e Add recovered protocol stack, Wi-Fi hotspot join, and RE findings
Reconstruct the app's Dart-layer behaviour (blutter over libapp.so,
jadx over base.apk — see docs/RE_DART_FINDINGS.md) as working Python,
replacing the library stubs with a real local-connect stack.

protocol/ (new package, hardware-independent):
- commands: CommunicationMode / CommunicationOperate / CommunicationCmd
  enums with the raw values recovered from the Dart object pool
- envelope: CommunicationObject with the app's exact JSON key order
- crypto: SN-derived secret key and the position-dependent additive
  cipher (encrypt/decrypt; radix 16 default, 32 documented alternate)
- crc: CRC-16/MODBUS with the app's hi/lo swap + 4-hex string form,
  CRC32 envelope check, little-endian int16 helpers
- framing: BLE frame build/parse (0x5AA5 data / 0x4AA4 ACK magics,
  CRC slots, MTU chunking) and local-socket int16LE length framing
  plus a streaming SocketFrameDecoder

wifi.py (rewritten):
- derive_hotspot_credentials(): the AP_<sn> SSID/password rules
  (20-char SN branch, full-SN fallback with the app's warning log)
- WifiBackend abstraction: NmcliWifiBackend for Linux hosts via
  nmcli, NoOpWifiBackend for radio-less containers
- WifiManager keeps the original stub method names for API compat
  and adds join_device_hotspot(sn) / leave_device_hotspot() / local_ip()

device_local.py (new): LocalDeviceClient for the mode==local path —
the /terminal/* HTTP endpoint family (hotspot info, aGate info,
overall info, MQTT relay, ...) and direct-connect socket RPC
(envelope -> cipher -> length frame -> decrypt -> JSON) with
convenience query_* RPCs.

docs/RE_DART_FINDINGS.md (new): the full findings — transport
selector, wire envelope, crypto, CRCs, MQTT (AWS IoT + Cognito),
socket, BLE + ESP provisioning, hotspot credential derivation,
local/cloud HTTP layers, and the Java glue — plus the open items;
README now links to it.

Unconfirmed candidates (local port 18000, cipher key radix, BLE
field order, X-Device-* header values) are flagged in the docs and
kept configurable in code.
2026-10-13 00:18:23 +00:00

1.9 KiB

FranklinWH AGATE Client

Python client library for interacting with FranklinWH AGATE energy storage device.

Repository

Gitea: http://192.168.1.74:30008/WesternTechnologies/franklinwh-agate-client

Documentation

Reverse Engineering Summary

This library was reverse engineered from the official FranklinWH Family Energy Android app (com.Franklinwh.FamilyEnergy).

Network I/O Stack

The device communicates via:

  • Bluetooth LE: Direct connection to AGATE device
  • Onboard Wi-Fi: Local network connection via device hotspot
  • Cloud APIs: https://e-api.franklinwh.com, https://energy.franklinwh.com

Key Operations Discovered

  • queryAgateInfo - Get device information
  • queryDeviceInfoHttp - HTTP device info query
  • queryModesByHttp - Query operating modes
  • queryConnectWifi - Wi-Fi connection management
  • connectViaBluetooth - Bluetooth connection
  • startBluetoothHeartbeat - Keepalive
  • BluetoothManager - Bluetooth service management
  • WifiOnboarding - Wi-Fi setup flows

Endpoints Found

  • https://e-api.franklinwh.com/api/appapi
  • https://energy.franklinwh.com/api-energy/deviceGroup/electric
  • https://energy.franklinwh.com/hes-gateway
  • https://dev.franklinwh.com/hes-gateway
  • https://uat.franklinwh.com/api-vpp-portal

Usage

from franklinwh_agate_client import AgateClient

client = AgateClient()
device_info = client.query_agate_info(device_id)

Development

This library is a work in progress. Additional operations will be added as reverse engineering continues.

License

Internal use only. Reverse engineering findings for research purposes.