franklinwh-cloud 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- franklinwh_cloud-0.3.0/LICENSE +50 -0
- franklinwh_cloud-0.3.0/PKG-INFO +471 -0
- franklinwh_cloud-0.3.0/README.md +384 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/__init__.py +49 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/api.py +5 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli.py +423 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/__init__.py +1 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/accessories.py +478 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/bms.py +233 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/diag.py +535 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/discover.py +473 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/fetch.py +218 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/metrics.py +143 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/mode.py +138 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/monitor.py +297 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/raw.py +202 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/status.py +160 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/support.py +1465 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/tou.py +897 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/cli_output.py +197 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/client.py +633 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/const/__init__.py +91 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/const/devices.py +75 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/const/modes.py +122 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/const/test_fixtures.py +202 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/const/tou.py +165 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/discovery.py +267 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/endpoints.py +135 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/exceptions.py +41 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/metrics.py +576 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/__init__.py +5 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/account.py +390 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/devices.py +679 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/discover.py +578 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/modes.py +462 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/power.py +132 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/stats.py +267 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/storm.py +133 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/tou.py +1246 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud/models.py +162 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/PKG-INFO +471 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/SOURCES.txt +63 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/dependency_links.txt +1 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/entry_points.txt +2 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/requires.txt +8 -0
- franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/top_level.txt +1 -0
- franklinwh_cloud-0.3.0/pyproject.toml +65 -0
- franklinwh_cloud-0.3.0/setup.cfg +4 -0
- franklinwh_cloud-0.3.0/tests/test_build_payload.py +93 -0
- franklinwh_cloud-0.3.0/tests/test_cli_core.py +185 -0
- franklinwh_cloud-0.3.0/tests/test_cli_tou.py +222 -0
- franklinwh_cloud-0.3.0/tests/test_const.py +95 -0
- franklinwh_cloud-0.3.0/tests/test_discover.py +271 -0
- franklinwh_cloud-0.3.0/tests/test_get_stats.py +244 -0
- franklinwh_cloud-0.3.0/tests/test_grid_status.py +63 -0
- franklinwh_cloud-0.3.0/tests/test_live.py +320 -0
- franklinwh_cloud-0.3.0/tests/test_metrics.py +188 -0
- franklinwh_cloud-0.3.0/tests/test_mode_soc.py +171 -0
- franklinwh_cloud-0.3.0/tests/test_modes.py +89 -0
- franklinwh_cloud-0.3.0/tests/test_network.py +402 -0
- franklinwh_cloud-0.3.0/tests/test_retry.py +69 -0
- franklinwh_cloud-0.3.0/tests/test_set_mode.py +54 -0
- franklinwh_cloud-0.3.0/tests/test_support.py +337 -0
- franklinwh_cloud-0.3.0/tests/test_token_fetcher.py +121 -0
- franklinwh_cloud-0.3.0/tests/test_tou_set.py +324 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 david2069
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
ADDITIONAL TERMS
|
|
26
|
+
|
|
27
|
+
This software interacts with FranklinWH's undocumented cloud API. By using
|
|
28
|
+
this software, you acknowledge and agree that:
|
|
29
|
+
|
|
30
|
+
1. This is UNOFFICIAL software, NOT affiliated with, endorsed by, or
|
|
31
|
+
supported by FranklinWH Inc. or any of its subsidiaries.
|
|
32
|
+
|
|
33
|
+
2. The FranklinWH cloud API is undocumented and may change, break, or become
|
|
34
|
+
unavailable without notice. The authors accept no responsibility for
|
|
35
|
+
service interruptions, API changes, or authentication modifications by
|
|
36
|
+
FranklinWH.
|
|
37
|
+
|
|
38
|
+
3. You assume ALL RISK associated with using this software, including but
|
|
39
|
+
not limited to: equipment damage, data loss, service disruption, warranty
|
|
40
|
+
implications, and any financial consequences.
|
|
41
|
+
|
|
42
|
+
4. You are solely responsible for compliance with FranklinWH's terms of
|
|
43
|
+
service and any applicable laws or regulations in your jurisdiction.
|
|
44
|
+
|
|
45
|
+
5. The authors provide no guarantee of continued maintenance, updates, or
|
|
46
|
+
compatibility with future FranklinWH API versions.
|
|
47
|
+
|
|
48
|
+
6. This software controls energy storage equipment. Improper use may affect
|
|
49
|
+
electrical systems, battery health, grid interconnection, or building
|
|
50
|
+
safety. You should understand what each API call does before using it.
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: franklinwh-cloud
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Unofficial Python client library and CLI for FranklinWH energy storage systems via the Cloud API
|
|
5
|
+
Author: david2069
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 david2069
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
ADDITIONAL TERMS
|
|
31
|
+
|
|
32
|
+
This software interacts with FranklinWH's undocumented cloud API. By using
|
|
33
|
+
this software, you acknowledge and agree that:
|
|
34
|
+
|
|
35
|
+
1. This is UNOFFICIAL software, NOT affiliated with, endorsed by, or
|
|
36
|
+
supported by FranklinWH Inc. or any of its subsidiaries.
|
|
37
|
+
|
|
38
|
+
2. The FranklinWH cloud API is undocumented and may change, break, or become
|
|
39
|
+
unavailable without notice. The authors accept no responsibility for
|
|
40
|
+
service interruptions, API changes, or authentication modifications by
|
|
41
|
+
FranklinWH.
|
|
42
|
+
|
|
43
|
+
3. You assume ALL RISK associated with using this software, including but
|
|
44
|
+
not limited to: equipment damage, data loss, service disruption, warranty
|
|
45
|
+
implications, and any financial consequences.
|
|
46
|
+
|
|
47
|
+
4. You are solely responsible for compliance with FranklinWH's terms of
|
|
48
|
+
service and any applicable laws or regulations in your jurisdiction.
|
|
49
|
+
|
|
50
|
+
5. The authors provide no guarantee of continued maintenance, updates, or
|
|
51
|
+
compatibility with future FranklinWH API versions.
|
|
52
|
+
|
|
53
|
+
6. This software controls energy storage equipment. Improper use may affect
|
|
54
|
+
electrical systems, battery health, grid interconnection, or building
|
|
55
|
+
safety. You should understand what each API call does before using it.
|
|
56
|
+
|
|
57
|
+
Project-URL: Homepage, https://david2069.github.io/franklinwh-cloud/
|
|
58
|
+
Project-URL: Documentation, https://david2069.github.io/franklinwh-cloud/
|
|
59
|
+
Project-URL: Source, https://github.com/david2069/franklinwh-cloud
|
|
60
|
+
Project-URL: Bug Tracker, https://github.com/david2069/franklinwh-cloud/issues
|
|
61
|
+
Project-URL: Changelog, https://github.com/david2069/franklinwh-cloud/blob/main/CHANGELOG.md
|
|
62
|
+
Keywords: franklinwh,battery,solar,energy-storage,home-energy-management,agate,apower,tou
|
|
63
|
+
Classifier: Development Status :: 4 - Beta
|
|
64
|
+
Classifier: Intended Audience :: Developers
|
|
65
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
66
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
67
|
+
Classifier: Operating System :: OS Independent
|
|
68
|
+
Classifier: Programming Language :: Python :: 3
|
|
69
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
70
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
71
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
72
|
+
Classifier: Topic :: Home Automation
|
|
73
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
74
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
75
|
+
Classifier: Typing :: Typed
|
|
76
|
+
Requires-Python: >=3.10
|
|
77
|
+
Description-Content-Type: text/markdown
|
|
78
|
+
License-File: LICENSE
|
|
79
|
+
Requires-Dist: httpx[http2]
|
|
80
|
+
Requires-Dist: jsonschema
|
|
81
|
+
Provides-Extra: test
|
|
82
|
+
Requires-Dist: pytest>=8.0; extra == "test"
|
|
83
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "test"
|
|
84
|
+
Requires-Dist: pytest-cov>=5.0; extra == "test"
|
|
85
|
+
Requires-Dist: respx>=0.21; extra == "test"
|
|
86
|
+
Dynamic: license-file
|
|
87
|
+
|
|
88
|
+
# FranklinWH Cloud Client
|
|
89
|
+
|
|
90
|
+

|
|
91
|
+
|
|
92
|
+
A Python client library for interacting with FranklinWH energy storage systems via the cloud API.
|
|
93
|
+
|
|
94
|
+
> 📦 **Package**: `franklinwh-cloud-client` (install from source or GitHub — not yet on PyPI) | **import**: `from franklinwh_cloud import Client`
|
|
95
|
+
|
|
96
|
+
> 📊 **Fork of [richo/franklinwh-python](https://github.com/richo/franklinwh-python)** — see [FORK_ANALYSIS.md](FORK_ANALYSIS.md) for a detailed comparison of additions (60+ API methods, 45+ sensor fields, TOU scheduling, power control, and more).
|
|
97
|
+
|
|
98
|
+
> 🔒 **API Citizenship**: See [API_CLIENT_GUIDE.md](API_CLIENT_GUIDE.md) for rate limiting strategies, client identity headers, and how to prepare for authentication changes.
|
|
99
|
+
|
|
100
|
+
> ⚠️ **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](https://david2069.github.io/franklinwh-cloud/#about-this-library) for details.
|
|
101
|
+
|
|
102
|
+
## ✨ Features
|
|
103
|
+
|
|
104
|
+
- **Authentication**: Automatic token management and refresh, homeowner + installer account types
|
|
105
|
+
- **Real-time Data**: Battery status, solar production, grid usage, home loads
|
|
106
|
+
- **Mode Control**: Switch between operating modes (Time-of-Use, Self-Consumption, Emergency Backup)
|
|
107
|
+
- **TOU Schedules**: Manage Time-of-Use scheduling with multi-season, weekday/weekend support
|
|
108
|
+
- **Device Info**: Gateway details, network status, device inventory, BMS cell-level data
|
|
109
|
+
- **Performance Monitoring**: API call metrics, response timing (min/avg/max), error rates, and CloudFront edge tracking
|
|
110
|
+
- **CloudFront Edge Tracking**: Automatic PoP location monitoring, failover detection, cache hit rates, and distribution ID tracking
|
|
111
|
+
- **Client Identity**: Honest identification headers for responsible API citizenship
|
|
112
|
+
- **Rate Limiting**: Opt-in client-side throttling with per-minute/hour/daily budgets
|
|
113
|
+
- **Stale Data Cache**: Per-endpoint TTL caching for graceful degradation when the cloud is slow or unavailable
|
|
114
|
+
- **Modular Architecture**: Domain-specific mixins (stats, modes, TOU, storm, power, devices, account)
|
|
115
|
+
- **CLI Tool**: Subcommand-based CLI with `fetch` for arbitrary endpoint access, debug tracing, JSON output
|
|
116
|
+
|
|
117
|
+
## 🔧 Technical Highlights
|
|
118
|
+
|
|
119
|
+
| Capability | Implementation |
|
|
120
|
+
|------------|----------------|
|
|
121
|
+
| **HTTP/2** | All API calls use `httpx` with `http2=True` — multiplexed requests, header compression, persistent connections |
|
|
122
|
+
| **CloudFront Monitoring** | Tracks PoP edge location, cache hit rate, distribution IDs, and failover transitions in real-time |
|
|
123
|
+
| **Configurable Base URL** | `Client(fetcher, gw, url_base=...)` — ready for FranklinWH DNS migration (`energy.` → `api.`) |
|
|
124
|
+
| **Dual Account Types** | `LOGIN_TYPE_USER` (0) and `LOGIN_TYPE_INSTALLER` (1) constants for homeowner and installer login |
|
|
125
|
+
| **Stale-While-Revalidate** | Per-endpoint TTL cache returns last-known-good data during API outages |
|
|
126
|
+
| **Modbus Mode Constants** | Bidirectional `CLOUD_TO_MODBUS_MODE` / `MODBUS_TO_CLOUD_MODE` mapping for Modbus TCP integration |
|
|
127
|
+
| **70+ API Endpoints** | Comprehensive coverage across TOU scheduling, power control, BMS, storm, smart circuits, compliance |
|
|
128
|
+
|
|
129
|
+
## 📦 Installation
|
|
130
|
+
|
|
131
|
+
### From wheel (recommended for downstream projects like FEM)
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
pip install dist/franklinwh_cloud_client-0.3.0-py3-none-any.whl
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### From source (editable, for development)
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
git clone https://github.com/david2069/franklinwh-cloud.git
|
|
141
|
+
cd franklinwh-cloud
|
|
142
|
+
python3 -m venv venv
|
|
143
|
+
source venv/bin/activate
|
|
144
|
+
pip install -e .
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### With test dependencies
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pip install -e ".[test]"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### From GitHub (direct)
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Latest (tracks main branch)
|
|
157
|
+
pip install git+https://github.com/david2069/franklinwh-cloud.git@main
|
|
158
|
+
|
|
159
|
+
# Pinned release (recommended for production / Docker)
|
|
160
|
+
pip install git+https://github.com/david2069/franklinwh-cloud.git@v0.3.0
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## ⚙️ Configuration
|
|
164
|
+
|
|
165
|
+
Create `franklinwh.ini` with your credentials:
|
|
166
|
+
|
|
167
|
+
```ini
|
|
168
|
+
[energy.franklinwh.com]
|
|
169
|
+
email = your.email@example.com
|
|
170
|
+
password = your_password
|
|
171
|
+
|
|
172
|
+
[gateways.enabled]
|
|
173
|
+
serialno = YOUR_GATEWAY_SERIAL
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Security Note**: The `.ini` file is in `.gitignore` to protect your credentials.
|
|
177
|
+
|
|
178
|
+
Alternatively, set environment variables:
|
|
179
|
+
```bash
|
|
180
|
+
export FRANKLIN_USERNAME="your.email@example.com"
|
|
181
|
+
export FRANKLIN_PASSWORD="your_password"
|
|
182
|
+
export FRANKLIN_GATEWAY="YOUR_GATEWAY_SERIAL"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 🚀 Quick Start
|
|
186
|
+
|
|
187
|
+
### Python API
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
import asyncio
|
|
191
|
+
from franklinwh import Client, TokenFetcher
|
|
192
|
+
|
|
193
|
+
async def main():
|
|
194
|
+
fetcher = TokenFetcher("email@example.com", "password")
|
|
195
|
+
client = Client(fetcher, "YOUR_GATEWAY_SERIAL")
|
|
196
|
+
|
|
197
|
+
# Get real-time stats
|
|
198
|
+
stats = await client.get_stats()
|
|
199
|
+
print(f"Battery: {stats.current.battery_soc}%")
|
|
200
|
+
print(f"Solar: {stats.current.solar_production} kW")
|
|
201
|
+
print(f"Mode: {stats.current.work_mode_desc}")
|
|
202
|
+
|
|
203
|
+
# API metrics (automatic)
|
|
204
|
+
metrics = client.get_metrics()
|
|
205
|
+
print(f"API calls: {metrics['total_api_calls']}, avg {metrics['avg_response_time_s']:.3f}s")
|
|
206
|
+
|
|
207
|
+
asyncio.run(main())
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### CLI Tool
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# System overview — power, SOC, batteries, weather, grid, metrics
|
|
214
|
+
franklinwh-cli status
|
|
215
|
+
|
|
216
|
+
# Device discovery — 3 verbosity tiers
|
|
217
|
+
franklinwh-cli discover # High-level: site, aGate, flags, state
|
|
218
|
+
franklinwh-cli discover -v # Verbose: + firmware, warranty, relays, accessories
|
|
219
|
+
franklinwh-cli discover -vv # Pedantic: + full firmware, NEM, PTO date
|
|
220
|
+
franklinwh-cli discover --json # Full JSON export
|
|
221
|
+
|
|
222
|
+
# Operating mode
|
|
223
|
+
franklinwh-cli mode
|
|
224
|
+
franklinwh-cli mode --set tou --soc 20
|
|
225
|
+
|
|
226
|
+
# TOU schedule inspection
|
|
227
|
+
franklinwh-cli tou --dispatch
|
|
228
|
+
|
|
229
|
+
# Direct API passthrough (33 methods available)
|
|
230
|
+
franklinwh-cli raw help
|
|
231
|
+
franklinwh-cli raw get_power_info
|
|
232
|
+
franklinwh-cli raw get_bms_info AP_SERIAL_NUMBER
|
|
233
|
+
|
|
234
|
+
# API metrics
|
|
235
|
+
franklinwh-cli metrics
|
|
236
|
+
|
|
237
|
+
# Real-time battery monitor (auto-refresh dashboard)
|
|
238
|
+
franklinwh-cli monitor # full dashboard, 30s refresh, Ctrl+C to exit
|
|
239
|
+
franklinwh-cli monitor -i 10 # refresh every 10 seconds
|
|
240
|
+
franklinwh-cli monitor -d 5 # run for 5 minutes then stop
|
|
241
|
+
franklinwh-cli monitor --compact # single-line mode (no screen clearing)
|
|
242
|
+
franklinwh-cli monitor --json # JSON stream per interval
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Output modes:**
|
|
246
|
+
```bash
|
|
247
|
+
franklinwh-cli status --json # JSON output
|
|
248
|
+
franklinwh-cli status --no-color # disable ANSI colours
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Debug & tracing:**
|
|
252
|
+
```bash
|
|
253
|
+
franklinwh-cli status -v # API call summaries
|
|
254
|
+
franklinwh-cli status -vv # + request/response headers
|
|
255
|
+
franklinwh-cli status -vvv # + full raw JSON payloads
|
|
256
|
+
franklinwh-cli tou --trace tou # only TOU mixin debug (46 log points!)
|
|
257
|
+
franklinwh-cli status --trace all # everything
|
|
258
|
+
franklinwh-cli status --api-trace # per-call timing
|
|
259
|
+
franklinwh-cli status -vv --log-file debug.log
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## 🏗️ Architecture
|
|
263
|
+
|
|
264
|
+
```mermaid
|
|
265
|
+
graph TB
|
|
266
|
+
CLI["franklinwh-cli"] --> Client
|
|
267
|
+
FEM["FEM / HA Addon"] --> Client
|
|
268
|
+
Scripts["Python Scripts"] --> Client
|
|
269
|
+
|
|
270
|
+
subgraph "franklinwh_cloud"
|
|
271
|
+
Client["Client<br/>(composes all mixins)"]
|
|
272
|
+
Client --> API["api.py<br/>HTTP transport, auth"]
|
|
273
|
+
API --> RL["RateLimiter"]
|
|
274
|
+
API --> ET["EdgeTracker<br/>CloudFront PoP"]
|
|
275
|
+
API --> SC["StaleDataCache"]
|
|
276
|
+
|
|
277
|
+
Client --> Discover["mixins/discover.py"]
|
|
278
|
+
Client --> Stats["mixins/stats.py"]
|
|
279
|
+
Client --> Modes["mixins/modes.py"]
|
|
280
|
+
Client --> TOU["mixins/tou.py"]
|
|
281
|
+
Client --> Power["mixins/power.py"]
|
|
282
|
+
Client --> Devices["mixins/devices.py"]
|
|
283
|
+
Client --> Storm["mixins/storm.py"]
|
|
284
|
+
Client --> Account["mixins/account.py"]
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
API --> CF["CloudFront CDN"]
|
|
288
|
+
CF --> FW["FranklinWH Cloud"]
|
|
289
|
+
FW -->|"FranklinWH Official Client<br/>(sendMqtt format)"| aGate[aGate]
|
|
290
|
+
|
|
291
|
+
MB["franklinwh_modbus"] -->|"Modbus TCP<br/>(SunSpec/Raw)"| Net["Network<br/>(LAN / WiFi / Remote)"]
|
|
292
|
+
Net -->|port 502| aGate
|
|
293
|
+
|
|
294
|
+
aGate --> aPower[aPower Batteries]
|
|
295
|
+
aGate --> PV[Solar PV]
|
|
296
|
+
aGate --> SmC[Smart Circuits]
|
|
297
|
+
|
|
298
|
+
style CLI fill:#22c55e,color:#fff
|
|
299
|
+
style Client fill:#3b82f6,color:#fff
|
|
300
|
+
style ET fill:#eab308,color:#000
|
|
301
|
+
style FW fill:#7c3aed,color:#fff
|
|
302
|
+
style MB fill:#d97706,color:#fff
|
|
303
|
+
style Net fill:#6b7280,color:#fff
|
|
304
|
+
style aGate fill:#059669,color:#fff
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
```
|
|
308
|
+
franklinwh_cloud/
|
|
309
|
+
├── client.py # Client class (inherits all mixins)
|
|
310
|
+
├── models.py # Stats, Current, Totals, GridStatus dataclasses
|
|
311
|
+
├── api.py # HTTP transport, auth, session management
|
|
312
|
+
├── exceptions.py # Custom exception hierarchy
|
|
313
|
+
├── metrics.py # ClientMetrics — API call instrumentation
|
|
314
|
+
├── discovery.py # DeviceSnapshot dataclass
|
|
315
|
+
├── const/ # Operating modes, TOU, device constants
|
|
316
|
+
│ ├── modes.py, tou.py, devices.py, device_catalog.json
|
|
317
|
+
├── mixins/ # Domain-specific API method groups (8 modules)
|
|
318
|
+
│ ├── discover.py # client.discover() — 3-tier device survey
|
|
319
|
+
│ ├── stats.py # get_stats, get_runtime_data, get_power_by_day
|
|
320
|
+
│ ├── modes.py # get_mode, set_mode, get_mode_info
|
|
321
|
+
│ ├── tou.py # TOU schedule CRUD + dispatch details
|
|
322
|
+
│ ├── storm.py # weather, storm hedge settings
|
|
323
|
+
│ ├── power.py # grid status, PCS settings, power control
|
|
324
|
+
│ ├── devices.py # device info, BMS, composite info
|
|
325
|
+
│ └── account.py # site info, notifications, alarms, warranty
|
|
326
|
+
├── cli.py # CLI entry point
|
|
327
|
+
├── cli_output.py # Terminal rendering + colour utilities
|
|
328
|
+
└── cli_commands/ # CLI subcommand modules
|
|
329
|
+
├── status.py # Power flow, SOC, mode, weather, grid
|
|
330
|
+
├── discover.py # Device discovery — 3 tiers, system readiness
|
|
331
|
+
├── monitor.py # Real-time dashboard (full/compact/JSON)
|
|
332
|
+
├── metrics.py # API probe + CloudFront edge data
|
|
333
|
+
├── bms.py # Battery Management System inspection
|
|
334
|
+
├── diag.py # System diagnostics report
|
|
335
|
+
├── tou.py # TOU schedule with dispatch details
|
|
336
|
+
├── mode.py # Operating mode get/set
|
|
337
|
+
└── raw.py # Direct API method calls
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## 📖 Documentation
|
|
341
|
+
|
|
342
|
+
| Document | Description |
|
|
343
|
+
|----------|-------------|
|
|
344
|
+
| [API_CLIENT_GUIDE.md](API_CLIENT_GUIDE.md) | Rate limiting, CloudFront edge tracking, metrics, monitor usage |
|
|
345
|
+
| [FORK_ANALYSIS.md](FORK_ANALYSIS.md) | Detailed comparison with upstream `richo/franklinwh-python` |
|
|
346
|
+
| [HISTORY.md](HISTORY.md) | Project timeline from fork to independence |
|
|
347
|
+
| [UPSTREAM_STRATEGY.md](UPSTREAM_STRATEGY.md) | Contributing back to upstream — the trust ladder |
|
|
348
|
+
| [CHANGELOG.md](CHANGELOG.md) | Version history and release notes |
|
|
349
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Development setup, code standards, PR process |
|
|
350
|
+
| [ISSUES.md](ISSUES.md) | How to report bugs and request features |
|
|
351
|
+
|
|
352
|
+
## 🧪 Testing
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
# Unit tests only (no API credentials needed)
|
|
356
|
+
pytest -m "not live" -q
|
|
357
|
+
|
|
358
|
+
# Live API tests (requires franklinwh.ini or env vars)
|
|
359
|
+
pytest -m live -v
|
|
360
|
+
|
|
361
|
+
# All tests
|
|
362
|
+
pytest -v
|
|
363
|
+
|
|
364
|
+
# Record results for traceability (AP-11)
|
|
365
|
+
./tests/run_and_record.sh CLI-refactor
|
|
366
|
+
cat tests/results/test_history.log
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**Current coverage**: 286 tests across all 8 domains
|
|
370
|
+
|
|
371
|
+
## 📚 API Reference
|
|
372
|
+
|
|
373
|
+
### Client Methods
|
|
374
|
+
|
|
375
|
+
| Domain | Key Methods |
|
|
376
|
+
|--------|-------------|
|
|
377
|
+
| **Discovery** | `discover(tier=1)` → `DeviceSnapshot` — site, aGate, batteries, flags, accessories, warranty |
|
|
378
|
+
| **Stats** | `get_stats()`, `get_runtime_data()`, `get_power_by_day(date)`, `get_power_details(type, date)` |
|
|
379
|
+
| **Modes** | `get_mode()`, `set_mode(mode, soc)`, `get_mode_info()` |
|
|
380
|
+
| **TOU** | `get_tou_info(type)`, `set_tou(schedule)`, `get_gateway_tou_list()`, `get_tou_dispatch_detail()` |
|
|
381
|
+
| **Tariff** | `get_utility_companies()`, `get_tariff_list()`, `get_tariff_detail()`, `apply_tariff_template()` |
|
|
382
|
+
| **Storm** | `get_weather()`, `get_storm_settings()`, `get_storm_list()` |
|
|
383
|
+
| **Power** | `get_grid_status()`, `get_power_control_settings()`, `get_power_info()` |
|
|
384
|
+
| **Devices** | `get_device_info()`, `get_bms_info(serial)`, `get_device_composite_info()` |
|
|
385
|
+
| **Account** | `siteinfo()`, `get_warranty_info()`, `get_alarm_codes_list()`, `get_notification_settings()` |
|
|
386
|
+
| **Metrics** | `get_metrics()` → `{total_api_calls, avg_response_time_s, calls_by_method, errors, ...}` |
|
|
387
|
+
|
|
388
|
+
### Data Structures
|
|
389
|
+
|
|
390
|
+
```python
|
|
391
|
+
stats.current.battery_soc # Battery State of Charge (%)
|
|
392
|
+
stats.current.solar_production # Solar production (kW)
|
|
393
|
+
stats.current.grid_use # Grid usage (kW, negative = export)
|
|
394
|
+
stats.current.home_load # Home consumption (kW)
|
|
395
|
+
stats.current.work_mode_desc # Operating mode name
|
|
396
|
+
stats.current.grid_status # GridStatus enum (NORMAL/DOWN/OFF)
|
|
397
|
+
stats.totals.solar # Daily solar production (kWh)
|
|
398
|
+
stats.totals.grid_import # Daily grid import (kWh)
|
|
399
|
+
stats.totals.home_use # Daily home consumption (kWh)
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
## 🗺️ Roadmap
|
|
403
|
+
|
|
404
|
+
### Installer Account Support (CLI-only, read-only)
|
|
405
|
+
|
|
406
|
+
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.
|
|
407
|
+
|
|
408
|
+
**Already implemented:**
|
|
409
|
+
- `LOGIN_TYPE_USER = 0` and `LOGIN_TYPE_INSTALLER = 1` constants
|
|
410
|
+
- `login_type` parameter on `TokenFetcher`, `login()`, and `_login()`
|
|
411
|
+
- Configurable `url_base` on `Client` for future DNS changes
|
|
412
|
+
|
|
413
|
+
**Planned scope:**
|
|
414
|
+
- CLI `--installer` flag to authenticate as an installer
|
|
415
|
+
- `discover` command to list all customer gateways in the installer's fleet
|
|
416
|
+
- `status` command with `--gateway SN` to view any customer's system
|
|
417
|
+
- **Read-only only** — no write operations (mode changes, TOU updates) via installer CLI
|
|
418
|
+
- Per-gateway selection required (no fleet-wide operations)
|
|
419
|
+
|
|
420
|
+
**Usage:**
|
|
421
|
+
```python
|
|
422
|
+
from franklinwh_cloud.client import TokenFetcher, LOGIN_TYPE_INSTALLER
|
|
423
|
+
|
|
424
|
+
# Installer login
|
|
425
|
+
fetcher = TokenFetcher("installer@company.com", "password", login_type=LOGIN_TYPE_INSTALLER)
|
|
426
|
+
client = Client(fetcher, "CUSTOMER_GATEWAY_SN")
|
|
427
|
+
info = await client.siteinfo() # returns installerId, userTypes, roles, etc.
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
> ⚠️ 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.
|
|
431
|
+
|
|
432
|
+
## 🤝 Contributing
|
|
433
|
+
|
|
434
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, code standards,
|
|
435
|
+
API citizenship requirements, and pull request process.
|
|
436
|
+
|
|
437
|
+
See [ISSUES.md](ISSUES.md) for how to report bugs and request features.
|
|
438
|
+
|
|
439
|
+
## 📝 License
|
|
440
|
+
|
|
441
|
+
MIT License with Additional Terms — see [LICENSE](LICENSE) for details.
|
|
442
|
+
|
|
443
|
+
The Additional Terms address the specific risks of interacting with
|
|
444
|
+
undocumented energy equipment APIs. **You must read and understand the
|
|
445
|
+
LICENSE before using this software.**
|
|
446
|
+
|
|
447
|
+
## 🙏 Acknowledgments
|
|
448
|
+
|
|
449
|
+
- **[FranklinWH](https://www.franklinwh.com)** - For innovative energy storage systems
|
|
450
|
+
- **[richo](https://github.com/richo/franklinwh-python)** - Original library foundation
|
|
451
|
+
- This project was developed with AI assistance (Claude, Gemini)
|
|
452
|
+
|
|
453
|
+
## ⚖️ Disclaimer
|
|
454
|
+
|
|
455
|
+
> **UNOFFICIAL SOFTWARE — NOT AFFILIATED WITH FRANKLINWH**
|
|
456
|
+
>
|
|
457
|
+
> By using this software, you confirm that you have read and understood the
|
|
458
|
+
> [LICENSE](LICENSE) and its Additional Terms.
|
|
459
|
+
>
|
|
460
|
+
> This software is provided **AS-IS**, without warranty of any kind, express or implied,
|
|
461
|
+
> including but not limited to the warranties of merchantability, fitness for a particular
|
|
462
|
+
> purpose, and non-infringement. Use entirely at your own risk.
|
|
463
|
+
>
|
|
464
|
+
> This library interacts with FranklinWH's undocumented cloud API, which may change,
|
|
465
|
+
> break, or become unavailable without notice. The authors accept no liability for
|
|
466
|
+
> service interruptions, data loss, equipment damage, or any other consequences
|
|
467
|
+
> arising from the use of this software.
|
|
468
|
+
>
|
|
469
|
+
> **MIT License** — see [LICENSE](LICENSE) for details.
|
|
470
|
+
|
|
471
|
+
This disclaimer is also logged once at startup by the library for audit trail purposes.
|