I have a Growatt solar inverter, which has a ShineWiFi-X datalogger attached to send metrics to Growatt’s servers, which can be viewed in their app.
However, Growatt are not very friendly, they block the official Growatt Home Assistant plugin, which logins into the Growatt portal and grabs the solar datalogger metrics. By block, I mean they heavily rate limit logins and eventually lock accounts for 24 hours:
{'msg': '507', 'lockDuration': '24', 'success': False, 'error': 'Current account has been locked for 24 hours'}
Or, they block the user-agent the plugin uses. Either way, very unreliable.
Instead, the community have made a proxy named “Grott” that forwards the data being sent from the datalogger, to MQTT (and therefore Home Assistant), and then to Growatt, so the app still works. It also means you can continue to configure the datalogger via their portal.
(Shamelessly stolen from the Grott repo)
I run Home Assistant in Docker, which means I need to manually set up an MQTT (Mosquito) instance (container). If you’re running Home Assistant as a system service (e.g. on a dedicated Raspberry Pi), or running HA OS, you can use the Mosquitto Add-on and remove the mosquitto
service from the docker-compose.yml file below.
Configuration files Link to heading
docker-compose.yml Link to heading
---
version: "3.5"
services:
home-assistant:
image: homeassistant/home-assistant:latest
container_name: home-assistant
volumes:
- /docker/home-assistant/config/:/config
- /etc/localtime:/etc/localtime:ro
ports:
- 8123:8123
restart: unless-stopped
networks:
- traefik
mosquitto:
image: eclipse-mosquitto:latest
container_name: mosquitto
volumes:
- ./mosquitto/config/mosquitto.conf:/mosquitto/config/mosquitto.conf
ports:
- 1883:1883
restart: unless-stopped
networks:
- traefik
grott:
image: ledidobe/grott:latest
container_name: grott
environment:
- gmqttip=10.2.0.1
- gmqttport=1883
- TZ=Australia/Brisbane
- gblockcmd=True
- ggrowattip=server.growatt.com
ports:
- 5279:5279
mosquitto.conf Link to heading
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
bind_address 0.0.0.0
port 1883
protocol mqtt
allow_anonymous true
All traffic is local, so I’m not worrying about authentication.
Grott seems to only support IP addresses for the MQTT host (gmqttip
) unfortunately, so I’m just exposing the MQTT port and pointing Grott at my server’s IP address.
Home Assistant integration Link to heading
In Home Assistant, add the MQTT integration:
Select the first MQTT option:
The Broker is the hostname of the Mosquitto docker container (mosquitto
) and the port is 1883
Updating the Datalogger to send data to Grott Link to heading
-
Log into the Growatt portal and go to All Devices
-
Go to Datalogger settings
-
Select the “Set IP” option, and enter the (internal) IP of the server running Grott
The password is the current date in YYYYMMDD format (e.g. 20250106)
Click “Yes” to save (lol)
Bonus: Increase the metric frequency from the default of 5 minutes Link to heading
In the same settings window, click Advanced Setting, then select the first Register and enter “4” (the register of the update frequency) and set the value to 1 - 10 (1 minute to 10 minutes).
Adding the sensors to Home Assistant Link to heading
In your Home Assistant configuration.yaml, add the following mqtt
section:
mqtt:
sensor:
- name: Solar - State
state_topic: energy/growatt
value_template: >
{% if (value_json['values']['pvstatus'] | int == 0) %}
Waiting
{% elif (value_json['values']['pvstatus'] | int == 1) %}
Normal
{% elif (value_json['values']['pvstatus'] | int == 2) %}
Fault
{% else %}
Unknown
{% endif %}
icon: mdi:power-settings
- name: Solar - Energy Today
state_topic: energy/growatt
value_template: "{{ value_json['values']['pvenergytoday'] | float / 10 }}"
unit_of_measurement: "kWh"
icon: mdi:solar-power
- name: Solar - Energy Total
state_topic: energy/growatt
value_template: "{{ value_json['values']['pvenergytotal'] | float / 10 }}"
unit_of_measurement: "kWh"
icon: mdi:solar-power
- name: Solar - Power In
state_topic: energy/growatt
value_template: "{{ value_json['values']['pvpowerin'] | float / 10000 }}"
unit_of_measurement: "kW"
icon: mdi:solar-power
- name: Solar - Power Out
state_topic: energy/growatt
value_template: "{{ value_json['values']['pvpowerout'] | float / 10000 }}"
unit_of_measurement: "kW"
icon: mdi:solar-power
- name: Solar - Temperature (Array)
state_topic: energy/growatt
value_template: "{{ value_json['values']['pvtemperature'] | float / 10 }}"
unit_of_measurement: "°C"
icon: mdi:thermometer
- name: Solar - Temperature (IPM)
state_topic: energy/growatt
value_template: "{{ value_json['values']['pvipmtemperature'] | float / 10 }}"
unit_of_measurement: "°C"
icon: mdi:thermometer
- name: Solar - Grid Voltage
state_topic: energy/growatt
value_template: "{{ value_json['values']['pvgridvoltage'] | float / 10 }}"
unit_of_measurement: "V"
icon: mdi:flash
- name: Solar - Frequency
state_topic: energy/growatt
value_template: "{{ value_json['values']['pvfrequentie'] | float / 100 }}"
unit_of_measurement: "Hz"
icon: mdi:flash
The payload sent from the datalogger is as follows (in case you’re wanting to add more sensors):
{
"device": "device-id",
"time": "2025-01-06",
"buffered": "no",
"values": {
"datalogserial": "dl-serial",
"pvserial": "pv-serial",
"pvstatus": 1,
"pvpowerin": 22739,
"pv1voltage": 3259,
"pv1current": 38,
"pv1watt": 12710,
"pv2voltage": 2645,
"pv2current": 36,
"pv2watt": 10029,
"pvpowerout": 22281,
"pvfrequentie": 5002,
"pvgridvoltage": 2402,
"pvgridcurrent": 91,
"pvgridpower": 22294,
"pvgridvoltage2": 0,
"pvgridcurrent2": 0,
"pvgridpower2": 0,
"pvgridvoltage3": 0,
"pvgridcurrent3": 0,
"pvgridpower3": 0,
"totworktime": 113047997,
"pvenergytoday": 36,
"pvenergytotal": 313514,
"epvtotal": 319001,
"epv1today": 20,
"epv1total": 176043,
"epv2today": 16,
"epv2total": 142958,
"pvtemperature": 374,
"pvipmtemperature": 408
}
}