Growatt Solar (Cloud)
Read-only monitoring of Growatt residential and light-commercial inverters (SPH, MIN, MOD, MAX, TL, SPA series) and paired ARK / BATT-XL battery storage via the ShineServer cloud API — the same backend the ShinePhone mobile app talks to. Surfaces real-time PV power, daily / monthly / lifetime energy, battery state of charge, and plant status. There is no public write endpoint on the ShineServer mobile API for most inverter classes, so this driver is monitoring-only.
For local Modbus TCP control (curtailment, setpoint writes) use the modbus driver against the inverter's Modbus TCP port — not this driver.
Prerequisites
- A ShinePhone / ShineServer account with the inverter already added to it. Confirm by logging into https://server-us.growatt.com/ (or your regional shard) in a browser and seeing current PV power on the plant page.
- The inverter's datalogger is online and reporting. A datalogger that has fallen off Wi-Fi will show a stale reading in ShineServer — the driver will happily poll it, but the numbers will not move.
- Pick the correct regional endpoint before wiring up the device:
- server-us.growatt.com — North America (default).
- server.growatt.com — China / APAC.
- server-au.growatt.com — Australia.
Setup
- Add the device. In the admin, create a new device with driver
growatt_cloud. Fill in:username— the email address or username you use to sign into ShinePhone.password— the ShinePhone password. The value is stored encrypted; a Growatt-flavored MD5 hash is sent on the wire, never the plaintext.api_base— leave onserver-us.growatt.comunless you are outside North America.
- Verify the login. After saving, watch the device row — connection state should flip to Connected within a few seconds. If it stays disconnected, jump to Troubleshooting below.
- Enumerate plants. From the device detail page, run the
get_plantscommand. The response is an array like:Copy the[{"plantId": "12345", "name": "Home", "status": 1}]plantId— it is what you will use as the zone address. - Create one zone per plant you want telemetry for. Set
zone.address = plantId. The zone can live under any subsystem;energyormonitoringis a good fit. - Adjust
status_interval(optional). Defaults to 60000 ms. The datalogger only uploads new readings on a ~5 minute cadence, so anything under 30 s just wastes calls without giving fresher data.
Attributes
Device attributes
| Name | Required | Type | Default | Description |
|---|---|---|---|---|
username | yes | string | — | ShineServer account email / username. |
password | yes | string | — | ShineServer password. Stored encrypted; MD5-hashed on the wire. |
api_base | no | string | server-us.growatt.com | Regional ShineServer host, hostname only. |
status_interval | no | int | 60000 | Poll cadence in milliseconds. Minimum 30000. |
request_timeout | no | int | 15000 | HTTP request timeout. |
Zone attributes (read-only, populated by the polling loop)
| Name | Type | Description |
|---|---|---|
current_power_w | float | Live PV output in watts. Zero at night. |
daily_energy_kwh | float | Today's cumulative production. Rolls over at local midnight on the datalogger. |
monthly_energy_kwh | float | Month-to-date production. |
total_energy_kwh | float | Lifetime production since inverter commissioning. |
battery_soc | integer | Paired battery state of charge, 0–100. Omitted on plants without storage. |
plant_status | string | Normalized status: producing, idle, waiting, fault, or offline. |
plant_name | string | Plant label as shown in ShinePhone. Populated on first poll. |
state | string | Zone rollup — producing (>5 W), idle, waiting, fault, or offline. Written to zone.state for macros and widgets. |
Zone address format
Zone address is a plantId — a numeric string like 12345. Run get_plants on the device to enumerate. If you have more than one plant on the account (multi-site), create one zone per plant with distinct addresses.
Commands
| Command | Args | What it does |
|---|---|---|
get_plants | — | Enumerates plants on the account. Use this once during setup. |
get_plant_detail | address | Static plant info (name, timezone, install date, module count). |
get_plant_data | address | Current top-of-plant reading — the same numbers the ShinePhone home screen shows. |
get_devices | address | Enumerates the inverters and dataloggers behind one plant. |
poll_now | — | Force a status poll of every wired-up zone right now. Cadence is unchanged. |
Known limitations
- Read-only. ShineServer's public mobile API does not expose a write endpoint for on/off, curtailment, or export limits on most inverter classes. Growatt gates those behind their OSS OpenAPI (v6 token, vendor-issued) or local Modbus TCP.
- Update rate is capped at the datalogger. The inverter reports on a ~5 minute cadence to ShineServer. Polling GEM faster than that just re-reads the same numbers.
- No per-inverter zones on multi-inverter plants. This driver rolls telemetry up to plant granularity. If you need per-inverter numbers on a multi-string commercial install, either split the plant in ShinePhone or run the
modbusdriver locally. - Cloud dependency. If ShineServer is down (rare but happens), the driver flags the connection as unhealthy and re-polls on the normal cadence. There is no local fallback on this driver.
Troubleshooting
Every request returns login failed or errCode 501.
Wrong regional endpoint. Switch api_base to server.growatt.com (APAC) or server-au.growatt.com (Australia). If the account was recently migrated between shards, try each one — the login endpoint returns 501 without a helpful message when the account lives on a different shard.
get_plants returns an empty list.
The datalogger is registered under a different account, or the account has never been linked to a plant. Log into the web portal at https://server-us.growatt.com/ to confirm which plants are visible.
Zone attributes stop updating after a period of correct operation. The datalogger has probably dropped Wi-Fi. Check the plant page in ShinePhone — if it shows "offline" there too, this is a device-side problem, not a driver issue. Power-cycle the datalogger (WiFi-X / WiFi-F).
Power reads 0 W for hours with plant_status = waiting.
Normal after sunset. Nothing to fix.
Timeouts to server-us.growatt.com.
Growatt rotates their edge occasionally. Lower request_timeout to see failures faster; if the outage persists, check https://downdetector.com/ for a broader ShineServer incident.
Under the hood — the password hash quirk
Growatt's mobile API uses a non-standard MD5 variant on the password: it hashes password with plain MD5, then walks the hex digest and rewrites any '0' character sitting on an even index to 'c'. Every community client for ShineServer applies the same substitution — including grott, growattServer on PyPI, and the Home Assistant growatt_server integration. The GEM driver does the same. You do not need to compute this by hand; just paste the plaintext password into the password attribute and the driver handles the transformation.