I have a Ginlong PV inverter being driven by two strings of solar panels. The inverter has a wifi dongle [“Wifi Stick Datalogger version 3.5”] that reports data back to Solis every 5 minutes.
The dongle has a basic web interface with a few parameters on it.
Polling the web interface does not poll the inverter. The dongle polls the inverter on a 5 minute cycle regardless of how often you attempt to fetch the data. Puzzlingly, the web interface has Javascript loop that fetches /inverter.cgi every 10s showing a countdown, to fool you into thinking you’re looking at recent data. Monitoring the output for a few hours soon proves that it’s only 5-minute resolution. /inverter.cgi is one line of semicolon-separated values, which is helpful for acquiring the data, no screen-scraping required.
The web interface uses basic auth. When first set up the dongle has a password of 123456789. After being adopted on the Solis cloud, the admin password will be changed to the wifi PSK; this doesn’t seem to be documented anywhere.
This sounds ideal for integrating with Zabbix but it was trickier than expected. I couldn’t get any of the three web data fetching types to work. I think the problem was the presence of 50 or so NULs in the output. I ended up using wget from a cronjob to pull the data, written to a log file on the server
*/5 * * * * bash -c "/usr/bin/wget http://inverter/inverter.cgi --http-user=admin --http-passwd=wifipsk -O - --quiet | head -n1 |ts >> /tmp/inverter.log"
and read in to Zabbix with a log[] item. My cron job pipes the output through ts to timestamp the data. I still had to use preprocessing steps to convert the CSV to JSON, to use the JSONPath support to pick out items. Puzzlingly, I had to remove extraneous [ and ] created by the CSV to JSON step before I could get the JSONPath items to work.
But every 5 minutes is way too long!
Yep, agreed. To break the “5 minute barrier” we need to talk directly to the inverter with an RS-485 adaptor and Modbus. An FT232-based USB adaptor with screw terminals was acquired, as was the obscure Exceedconn EC04681-2014-BF plug. The plug cost twice as much as the RS-485 adaptor. I wired the dongle in parallel with RS-485 adaptor so both can work. The dongle is powered by the inverter so if the dongle can’t be pinged then the panels aren’t generating.
I modified the python script from here:
and feed the output into zabbix_sender.
This is my version of the Python script. This is the associated Zabbix template.
For now, all I have is a simple bash while loop that pipes it into zabbix_sender:
$ while sleep 30 ; do ./solis-rs485.py | zabbix_sender -i - -r -s solisinverter -z localhost ; done
I only really need 1-minute updates on this, but randomly it will fail with a checksum error, so every 30s will ensure I get at least 1-minute data.
OpenEnergyMonitor forums were a helpful source of information here.
Modbus register numbers are confusing: Many of the examples use a 5-digit register number starting with 3, and many of them are 4 digits starting with 3. Also, you subtract 1 from the register number you want. This is covered by the Solis documentation, but not commented on in many of the code examples:
“the register address needs to offset one bit. Example: register address: 3000, the send address is 2999.”
Why not just be the actual register number? Also, many examples assume you only have a single string.
TODO: systemd unit to run this automatically.
Update 2024/03/03: the Paho MQTT library was updated recently, so
client = mqtt.Client(client_id)
is now
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id)