Skip to main content

Unofficial Python client library and CLI for FranklinWH energy storage systems via the Cloud API

Project description

FranklinWH Cloud Client

Tests

A Python client library for interacting with FranklinWH energy storage systems via the cloud API.

๐Ÿ“ฆ Package: franklinwh-cloud-client (install from source or GitHub โ€” not yet on PyPI) | import: from franklinwh_cloud import Client

๐Ÿ“Š Fork of richo/franklinwh-python โ€” see FORK_ANALYSIS.md for a detailed comparison of additions (60+ API methods, 45+ sensor fields, TOU scheduling, power control, and more).

๐Ÿ”’ API Citizenship: See API_CLIENT_GUIDE.md for rate limiting strategies, client identity headers, and how to prepare for authentication changes.

โš ๏ธ Disclaimer: This library is unofficial and not endorsed by FranklinWH. It interfaces with a proprietary Cloud API designed exclusively for the official FranklinWH mobile app and authorised installer portal โ€” not for third-party use. It is provided "AS IS" for educational and informational purposes only, with no warranty of fitness for any purpose. Use at your own risk. See the full disclaimer for details.

โœจ Features

  • Authentication: Automatic token management and refresh, homeowner + installer account types
  • Real-time Data: Battery status, solar production, grid usage, home loads
  • Mode Control: Switch between operating modes (Time-of-Use, Self-Consumption, Emergency Backup)
  • TOU Schedules: Manage Time-of-Use scheduling with multi-season, weekday/weekend support
  • Device Info: Gateway details, network status, device inventory, BMS cell-level data
  • Performance Monitoring: API call metrics, response timing (min/avg/max), error rates, and CloudFront edge tracking
  • CloudFront Edge Tracking: Automatic PoP location monitoring, failover detection, cache hit rates, and distribution ID tracking
  • Client Identity: Honest identification headers for responsible API citizenship
  • Rate Limiting: Opt-in client-side throttling with per-minute/hour/daily budgets
  • Stale Data Cache: Per-endpoint TTL caching for graceful degradation when the cloud is slow or unavailable
  • Modular Architecture: Domain-specific mixins (stats, modes, TOU, storm, power, devices, account)
  • CLI Tool: Subcommand-based CLI with fetch for arbitrary endpoint access, debug tracing, JSON output

๐Ÿ”ง Technical Highlights

Capability Implementation
HTTP/2 All API calls use httpx with http2=True โ€” multiplexed requests, header compression, persistent connections
CloudFront Monitoring Tracks PoP edge location, cache hit rate, distribution IDs, and failover transitions in real-time
Configurable Base URL Client(fetcher, gw, url_base=...) โ€” ready for FranklinWH DNS migration (energy. โ†’ api.)
Dual Account Types LOGIN_TYPE_USER (0) and LOGIN_TYPE_INSTALLER (1) constants for homeowner and installer login
Stale-While-Revalidate Per-endpoint TTL cache returns last-known-good data during API outages
Modbus Mode Constants Bidirectional CLOUD_TO_MODBUS_MODE / MODBUS_TO_CLOUD_MODE mapping for Modbus TCP integration
70+ API Endpoints Comprehensive coverage across TOU scheduling, power control, BMS, storm, smart circuits, compliance

๐Ÿ“ฆ Installation

From wheel (recommended for downstream projects like FEM)

pip install dist/franklinwh_cloud_client-0.3.0-py3-none-any.whl

From source (editable, for development)

git clone https://github.com/david2069/franklinwh-cloud.git
cd franklinwh-cloud
python3 -m venv venv
source venv/bin/activate
pip install -e .

With test dependencies

pip install -e ".[test]"

From GitHub (direct)

# Latest (tracks main branch)
pip install git+https://github.com/david2069/franklinwh-cloud.git@main

# Pinned release (recommended for production / Docker)
pip install git+https://github.com/david2069/franklinwh-cloud.git@v0.3.0

โš™๏ธ Configuration

Create franklinwh.ini with your credentials:

[energy.franklinwh.com]
email = your.email@example.com
password = your_password

[gateways.enabled]
serialno = YOUR_GATEWAY_SERIAL

Security Note: The .ini file is in .gitignore to protect your credentials.

Alternatively, set environment variables:

export FRANKLIN_USERNAME="your.email@example.com"
export FRANKLIN_PASSWORD="your_password"
export FRANKLIN_GATEWAY="YOUR_GATEWAY_SERIAL"

๐Ÿš€ Quick Start

Python API

import asyncio
from franklinwh import Client, TokenFetcher

async def main():
    fetcher = TokenFetcher("email@example.com", "password")
    client = Client(fetcher, "YOUR_GATEWAY_SERIAL")

    # Get real-time stats
    stats = await client.get_stats()
    print(f"Battery: {stats.current.battery_soc}%")
    print(f"Solar: {stats.current.solar_production} kW")
    print(f"Mode: {stats.current.work_mode_desc}")

    # API metrics (automatic)
    metrics = client.get_metrics()
    print(f"API calls: {metrics['total_api_calls']}, avg {metrics['avg_response_time_s']:.3f}s")

asyncio.run(main())

CLI Tool

# System overview โ€” power, SOC, batteries, weather, grid, metrics
franklinwh-cli status

# Device discovery โ€” 3 verbosity tiers
franklinwh-cli discover          # High-level: site, aGate, flags, state
franklinwh-cli discover -v       # Verbose: + firmware, warranty, relays, accessories
franklinwh-cli discover -vv      # Pedantic: + full firmware, NEM, PTO date
franklinwh-cli discover --json   # Full JSON export

# Operating mode
franklinwh-cli mode
franklinwh-cli mode --set tou --soc 20

# TOU schedule inspection
franklinwh-cli tou --dispatch

# Direct API passthrough (33 methods available)
franklinwh-cli raw help
franklinwh-cli raw get_power_info
franklinwh-cli raw get_bms_info AP_SERIAL_NUMBER

# API metrics
franklinwh-cli metrics

# Real-time battery monitor (auto-refresh dashboard)
franklinwh-cli monitor              # full dashboard, 30s refresh, Ctrl+C to exit
franklinwh-cli monitor -i 10        # refresh every 10 seconds
franklinwh-cli monitor -d 5         # run for 5 minutes then stop
franklinwh-cli monitor --compact    # single-line mode (no screen clearing)
franklinwh-cli monitor --json       # JSON stream per interval

Output modes:

franklinwh-cli status --json    # JSON output
franklinwh-cli status --no-color  # disable ANSI colours

Debug & tracing:

franklinwh-cli status -v          # API call summaries
franklinwh-cli status -vv         # + request/response headers
franklinwh-cli status -vvv        # + full raw JSON payloads
franklinwh-cli tou --trace tou    # only TOU mixin debug (46 log points!)
franklinwh-cli status --trace all # everything
franklinwh-cli status --api-trace # per-call timing
franklinwh-cli status -vv --log-file debug.log

๐Ÿ—๏ธ Architecture

graph TB
    CLI["franklinwh-cli"] --> Client
    FEM["FEM / HA Addon"] --> Client
    Scripts["Python Scripts"] --> Client

    subgraph "franklinwh_cloud"
        Client["Client<br/>(composes all mixins)"]
        Client --> API["api.py<br/>HTTP transport, auth"]
        API --> RL["RateLimiter"]
        API --> ET["EdgeTracker<br/>CloudFront PoP"]
        API --> SC["StaleDataCache"]
        
        Client --> Discover["mixins/discover.py"]
        Client --> Stats["mixins/stats.py"]
        Client --> Modes["mixins/modes.py"]
        Client --> TOU["mixins/tou.py"]
        Client --> Power["mixins/power.py"]
        Client --> Devices["mixins/devices.py"]
        Client --> Storm["mixins/storm.py"]
        Client --> Account["mixins/account.py"]
    end

    API --> CF["CloudFront CDN"]
    CF --> FW["FranklinWH Cloud"]
    FW -->|"FranklinWH Official Client<br/>(sendMqtt format)"| aGate[aGate]

    MB["franklinwh_modbus"] -->|"Modbus TCP<br/>(SunSpec/Raw)"| Net["Network<br/>(LAN / WiFi / Remote)"]
    Net -->|port 502| aGate

    aGate --> aPower[aPower Batteries]
    aGate --> PV[Solar PV]
    aGate --> SmC[Smart Circuits]

    style CLI fill:#22c55e,color:#fff
    style Client fill:#3b82f6,color:#fff
    style ET fill:#eab308,color:#000
    style FW fill:#7c3aed,color:#fff
    style MB fill:#d97706,color:#fff
    style Net fill:#6b7280,color:#fff
    style aGate fill:#059669,color:#fff
franklinwh_cloud/
โ”œโ”€โ”€ client.py            # Client class (inherits all mixins)
โ”œโ”€โ”€ models.py            # Stats, Current, Totals, GridStatus dataclasses
โ”œโ”€โ”€ api.py               # HTTP transport, auth, session management
โ”œโ”€โ”€ exceptions.py        # Custom exception hierarchy
โ”œโ”€โ”€ metrics.py           # ClientMetrics โ€” API call instrumentation
โ”œโ”€โ”€ discovery.py         # DeviceSnapshot dataclass
โ”œโ”€โ”€ const/               # Operating modes, TOU, device constants
โ”‚   โ”œโ”€โ”€ modes.py, tou.py, devices.py, device_catalog.json
โ”œโ”€โ”€ mixins/              # Domain-specific API method groups (8 modules)
โ”‚   โ”œโ”€โ”€ discover.py      # client.discover() โ€” 3-tier device survey
โ”‚   โ”œโ”€โ”€ stats.py         # get_stats, get_runtime_data, get_power_by_day
โ”‚   โ”œโ”€โ”€ modes.py         # get_mode, set_mode, get_mode_info
โ”‚   โ”œโ”€โ”€ tou.py           # TOU schedule CRUD + dispatch details
โ”‚   โ”œโ”€โ”€ storm.py         # weather, storm hedge settings
โ”‚   โ”œโ”€โ”€ power.py         # grid status, PCS settings, power control
โ”‚   โ”œโ”€โ”€ devices.py       # device info, BMS, composite info
โ”‚   โ””โ”€โ”€ account.py       # site info, notifications, alarms, warranty
โ”œโ”€โ”€ cli.py               # CLI entry point
โ”œโ”€โ”€ cli_output.py        # Terminal rendering + colour utilities
โ””โ”€โ”€ cli_commands/        # CLI subcommand modules
    โ”œโ”€โ”€ status.py        # Power flow, SOC, mode, weather, grid
    โ”œโ”€โ”€ discover.py      # Device discovery โ€” 3 tiers, system readiness
    โ”œโ”€โ”€ monitor.py       # Real-time dashboard (full/compact/JSON)
    โ”œโ”€โ”€ metrics.py       # API probe + CloudFront edge data
    โ”œโ”€โ”€ bms.py           # Battery Management System inspection
    โ”œโ”€โ”€ diag.py          # System diagnostics report
    โ”œโ”€โ”€ tou.py           # TOU schedule with dispatch details
    โ”œโ”€โ”€ mode.py          # Operating mode get/set
    โ””โ”€โ”€ raw.py           # Direct API method calls

๐Ÿ“– Documentation

Document Description
API_CLIENT_GUIDE.md Rate limiting, CloudFront edge tracking, metrics, monitor usage
FORK_ANALYSIS.md Detailed comparison with upstream richo/franklinwh-python
HISTORY.md Project timeline from fork to independence
UPSTREAM_STRATEGY.md Contributing back to upstream โ€” the trust ladder
CHANGELOG.md Version history and release notes
CONTRIBUTING.md Development setup, code standards, PR process
ISSUES.md How to report bugs and request features

๐Ÿงช Testing

# Unit tests only (no API credentials needed)
pytest -m "not live" -q

# Live API tests (requires franklinwh.ini or env vars)
pytest -m live -v

# All tests
pytest -v

# Record results for traceability (AP-11)
./tests/run_and_record.sh CLI-refactor
cat tests/results/test_history.log

Current coverage: 286 tests across all 8 domains

๐Ÿ“š API Reference

Client Methods

Domain Key Methods
Discovery discover(tier=1) โ†’ DeviceSnapshot โ€” site, aGate, batteries, flags, accessories, warranty
Stats get_stats(), get_runtime_data(), get_power_by_day(date), get_power_details(type, date)
Modes get_mode(), set_mode(mode, soc), get_mode_info()
TOU get_tou_info(type), set_tou(schedule), get_gateway_tou_list(), get_tou_dispatch_detail()
Tariff get_utility_companies(), get_tariff_list(), get_tariff_detail(), apply_tariff_template()
Storm get_weather(), get_storm_settings(), get_storm_list()
Power get_grid_status(), get_power_control_settings(), get_power_info()
Devices get_device_info(), get_bms_info(serial), get_device_composite_info()
Account siteinfo(), get_warranty_info(), get_alarm_codes_list(), get_notification_settings()
Metrics get_metrics() โ†’ {total_api_calls, avg_response_time_s, calls_by_method, errors, ...}

Data Structures

stats.current.battery_soc          # Battery State of Charge (%)
stats.current.solar_production     # Solar production (kW)
stats.current.grid_use             # Grid usage (kW, negative = export)
stats.current.home_load            # Home consumption (kW)
stats.current.work_mode_desc       # Operating mode name
stats.current.grid_status          # GridStatus enum (NORMAL/DOWN/OFF)
stats.totals.solar                 # Daily solar production (kWh)
stats.totals.grid_import           # Daily grid import (kWh)
stats.totals.home_use              # Daily home consumption (kWh)

๐Ÿ—บ๏ธ Roadmap

Installer Account Support (CLI-only, read-only)

The FranklinWH Cloud API supports installer accounts โ€” these are privileged accounts used by solar installers to manage fleets of customer aGate gateways. The login endpoint (appUserOrInstallerLogin) supports both account types via a type parameter: 0 = app user, 1 = installer.

Already implemented:

  • LOGIN_TYPE_USER = 0 and LOGIN_TYPE_INSTALLER = 1 constants
  • login_type parameter on TokenFetcher, login(), and _login()
  • Configurable url_base on Client for future DNS changes

Planned scope:

  • CLI --installer flag to authenticate as an installer
  • discover command to list all customer gateways in the installer's fleet
  • status command with --gateway SN to view any customer's system
  • Read-only only โ€” no write operations (mode changes, TOU updates) via installer CLI
  • Per-gateway selection required (no fleet-wide operations)

Usage:

from franklinwh_cloud.client import TokenFetcher, LOGIN_TYPE_INSTALLER

# Installer login
fetcher = TokenFetcher("installer@company.com", "password", login_type=LOGIN_TYPE_INSTALLER)
client = Client(fetcher, "CUSTOMER_GATEWAY_SN")
info = await client.siteinfo()  # returns installerId, userTypes, roles, etc.

โš ๏ธ Installer accounts can access and modify multiple customer sites. This library intentionally limits installer support to read-only CLI operations as a matter of responsible API citizenship. Developers who fork this library assume their own responsibility for write operations.

๐Ÿค Contributing

See CONTRIBUTING.md for development setup, code standards, API citizenship requirements, and pull request process.

See ISSUES.md for how to report bugs and request features.

๐Ÿ“ License

MIT License with Additional Terms โ€” see LICENSE for details.

The Additional Terms address the specific risks of interacting with undocumented energy equipment APIs. You must read and understand the LICENSE before using this software.

๐Ÿ™ Acknowledgments

  • FranklinWH - For innovative energy storage systems
  • richo - Original library foundation
  • This project was developed with AI assistance (Claude, Gemini)

โš–๏ธ Disclaimer

UNOFFICIAL SOFTWARE โ€” NOT AFFILIATED WITH FRANKLINWH

By using this software, you confirm that you have read and understood the LICENSE and its Additional Terms.

This software is provided AS-IS, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. Use entirely at your own risk.

This library interacts with FranklinWH's undocumented cloud API, which may change, break, or become unavailable without notice. The authors accept no liability for service interruptions, data loss, equipment damage, or any other consequences arising from the use of this software.

MIT License โ€” see LICENSE for details.

This disclaimer is also logged once at startup by the library for audit trail purposes.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

franklinwh_cloud-0.3.0.tar.gz (158.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

franklinwh_cloud-0.3.0-py3-none-any.whl (145.2 kB view details)

Uploaded Python 3

File details

Details for the file franklinwh_cloud-0.3.0.tar.gz.

File metadata

  • Download URL: franklinwh_cloud-0.3.0.tar.gz
  • Upload date:
  • Size: 158.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for franklinwh_cloud-0.3.0.tar.gz
Algorithm Hash digest
SHA256 ca813d48f31f9df7b5e6eb2a95b6099288b26322671dd4f043b12fc9f1b4bb32
MD5 3ee5363d1342b28129aaf3a7002eb609
BLAKE2b-256 1af684b502276ffc87e7a4c37e17bf0fa3e06403125dbe49cf11c9b918dbc741

See more details on using hashes here.

Provenance

The following attestation bundles were made for franklinwh_cloud-0.3.0.tar.gz:

Publisher: publish.yml on david2069/franklinwh-cloud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file franklinwh_cloud-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for franklinwh_cloud-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 346d9d26f11b19d32cf9200902d224e15c17d3347f02c4263cc98ed219b0bef5
MD5 4622a9ea739e9781c7062fd5711fb59f
BLAKE2b-256 8c3e0c207beda81d5fd93b576589c69c5e011bd05e44a38038f51bd0edc8cc77

See more details on using hashes here.

Provenance

The following attestation bundles were made for franklinwh_cloud-0.3.0-py3-none-any.whl:

Publisher: publish.yml on david2069/franklinwh-cloud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page