Grafana displaying Solar inverter data

It turns out that the “Sungrow” inverters use a version of modbus standards that can be interrogated via TCP/IP.
Refer to meltaxa at Github for some fine development work which formed the basis of this project.
https://github.com/meltaxa/solariot
In use:
- Meltaxa’s “solariot” python script will scrape the inverter.
While there are many options to use influxdb and other methods, my preference is (always) output to an MQTT host. - Some quick python (see below for example) running as a Raspberry pi systemd service catches the MQTT publications in the topic “inverter/stats” and punches them into a local MySQL database.
- Grafana isn’t really designed for MySQL but with the plugin it works well enough and with a bit of work can create the most stunning displays.
The following code will subscribe to the Solariot mqtt publications and push selected data into a MySQL instance.
#!/usr/bin/python
# Subscribes to MQTT server and waits for Topic: inverter/stats
# On receipt of the JSON data summary in the form {"daily_pv_energy":15330,"total_pv_power":3188,"load_power":1287,"export_power":188, ....etc}
# Extracts the variables and sends to mySQL server on localhost / mySQL host
# Puts it inot the {solar} database and {inverter1} table
import MySQLdb
import json
import paho.mqtt.client as mqtt
import datetime
def on_connect(mqttc, obj, flags, rc):
print("rc: " + str(rc))
def on_message(mqttc, obj, msg):
msg.payload = msg.payload.decode("utf-8") ## Rmmoves b for bytes
# print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))
if (str(msg.topic) == 'inverter/stats'):
now = datetime.datetime.now()
print("mqtt2mysql: inverter/stats message received at ", now.strftime("%H:%M:%S"))
#print(msg.payload)
p = msg.payload
y = json.loads(p)
m1 = y["daily_pv_energy"]
m2 = y["total_pv_power"]
m3 = y["load_power"]
m4 = y["export_power"]
m5 = y["battery_level"]
m6 = y["battery_temp"]
m7 = y["pv1_current"]
m8 = y["pv2_current"]
m9 = y["daily_use_energy"]
m10 = y["battery_power"]
m11 = y["daily_export_energy"]
m12 = y["13036"]/10 # Possibly grid use??
if (m3 > m2):
m10=-m10 # Guess when the battery is being charged or discharged
#print m1
db = MySQLdb.connect(host="localhost", # your host, usually localhost
user="xxxxx", # your username
passwd="xxxxxx", # your password
db="solar") # name of the data base
# you must create a Cursor object. It will let you execute all the queries you need
cur = db.cursor()
cur.execute('INSERT INTO inverter1 (daily_pv_energy,total_pv_power,load_power,export_power,battery_level,battery_temp,pv1_current,pv2_current,daily_use_energy,battery_power,daily_export_energy,grid_use) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)' %(m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12))
db.commit()
# print (row[1]) #for row in cur.fetchall():
print("mqtt2mysql:",str(m1), str(m2) ,str(m3), str(m4), str(m5), str(m6), str(m7), str(m8), str(m9), str(m10), str(m11), str(m12) )
print("mqtt2mysql:", cur.rowcount, "record inserted.")
db.close()
def on_subscribe(mqttc, obj, mid, granted_qos):
print("mqtt2mysql: Subscribed: " + str(mid) + " " + str(granted_qos))
def on_log(mqttc, obj, level, string):
#print(string)
print(str(m1), str(m2) ,str(m3), str(m4), str(m5), str(m6), str(m7), str(m8), str(m9), str(m10), str(m11), str(m12) )
mqttc = mqtt.Client()
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_subscribe = on_subscribe
# mqttc.on_log = on_log # Uncomment to enable debug messages
mqttc.connect("nnn.nnn.nnn.nnn", 1883, 60)
mqttc.subscribe("inverter/stats", 1) #mqttc.subscribe("#", 1)
mqttc.loop_forever()