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.
Files changed (65) hide show
  1. franklinwh_cloud-0.3.0/LICENSE +50 -0
  2. franklinwh_cloud-0.3.0/PKG-INFO +471 -0
  3. franklinwh_cloud-0.3.0/README.md +384 -0
  4. franklinwh_cloud-0.3.0/franklinwh_cloud/__init__.py +49 -0
  5. franklinwh_cloud-0.3.0/franklinwh_cloud/api.py +5 -0
  6. franklinwh_cloud-0.3.0/franklinwh_cloud/cli.py +423 -0
  7. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/__init__.py +1 -0
  8. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/accessories.py +478 -0
  9. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/bms.py +233 -0
  10. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/diag.py +535 -0
  11. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/discover.py +473 -0
  12. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/fetch.py +218 -0
  13. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/metrics.py +143 -0
  14. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/mode.py +138 -0
  15. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/monitor.py +297 -0
  16. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/raw.py +202 -0
  17. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/status.py +160 -0
  18. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/support.py +1465 -0
  19. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_commands/tou.py +897 -0
  20. franklinwh_cloud-0.3.0/franklinwh_cloud/cli_output.py +197 -0
  21. franklinwh_cloud-0.3.0/franklinwh_cloud/client.py +633 -0
  22. franklinwh_cloud-0.3.0/franklinwh_cloud/const/__init__.py +91 -0
  23. franklinwh_cloud-0.3.0/franklinwh_cloud/const/devices.py +75 -0
  24. franklinwh_cloud-0.3.0/franklinwh_cloud/const/modes.py +122 -0
  25. franklinwh_cloud-0.3.0/franklinwh_cloud/const/test_fixtures.py +202 -0
  26. franklinwh_cloud-0.3.0/franklinwh_cloud/const/tou.py +165 -0
  27. franklinwh_cloud-0.3.0/franklinwh_cloud/discovery.py +267 -0
  28. franklinwh_cloud-0.3.0/franklinwh_cloud/endpoints.py +135 -0
  29. franklinwh_cloud-0.3.0/franklinwh_cloud/exceptions.py +41 -0
  30. franklinwh_cloud-0.3.0/franklinwh_cloud/metrics.py +576 -0
  31. franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/__init__.py +5 -0
  32. franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/account.py +390 -0
  33. franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/devices.py +679 -0
  34. franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/discover.py +578 -0
  35. franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/modes.py +462 -0
  36. franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/power.py +132 -0
  37. franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/stats.py +267 -0
  38. franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/storm.py +133 -0
  39. franklinwh_cloud-0.3.0/franklinwh_cloud/mixins/tou.py +1246 -0
  40. franklinwh_cloud-0.3.0/franklinwh_cloud/models.py +162 -0
  41. franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/PKG-INFO +471 -0
  42. franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/SOURCES.txt +63 -0
  43. franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/dependency_links.txt +1 -0
  44. franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/entry_points.txt +2 -0
  45. franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/requires.txt +8 -0
  46. franklinwh_cloud-0.3.0/franklinwh_cloud.egg-info/top_level.txt +1 -0
  47. franklinwh_cloud-0.3.0/pyproject.toml +65 -0
  48. franklinwh_cloud-0.3.0/setup.cfg +4 -0
  49. franklinwh_cloud-0.3.0/tests/test_build_payload.py +93 -0
  50. franklinwh_cloud-0.3.0/tests/test_cli_core.py +185 -0
  51. franklinwh_cloud-0.3.0/tests/test_cli_tou.py +222 -0
  52. franklinwh_cloud-0.3.0/tests/test_const.py +95 -0
  53. franklinwh_cloud-0.3.0/tests/test_discover.py +271 -0
  54. franklinwh_cloud-0.3.0/tests/test_get_stats.py +244 -0
  55. franklinwh_cloud-0.3.0/tests/test_grid_status.py +63 -0
  56. franklinwh_cloud-0.3.0/tests/test_live.py +320 -0
  57. franklinwh_cloud-0.3.0/tests/test_metrics.py +188 -0
  58. franklinwh_cloud-0.3.0/tests/test_mode_soc.py +171 -0
  59. franklinwh_cloud-0.3.0/tests/test_modes.py +89 -0
  60. franklinwh_cloud-0.3.0/tests/test_network.py +402 -0
  61. franklinwh_cloud-0.3.0/tests/test_retry.py +69 -0
  62. franklinwh_cloud-0.3.0/tests/test_set_mode.py +54 -0
  63. franklinwh_cloud-0.3.0/tests/test_support.py +337 -0
  64. franklinwh_cloud-0.3.0/tests/test_token_fetcher.py +121 -0
  65. 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
+ ![Tests](https://github.com/david2069/franklinwh-cloud/actions/workflows/test.yml/badge.svg)
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.