solaredge_exporter/solaredge_modbus.py

88 lines
3.9 KiB
Python

#!/usr/bin/env python3
import argparse
import datetime
import prom
import sunspec
metric_data = {
"dc_voltage_volts": ["gauge", "Input bus voltage"],
"dc_current_amps": ["gauge", "Input bus current"],
"dc_power_watts": ["gauge", "Input bus power"],
"energy_watthours_total": ["counter", "Power meter total"],
"temperature_celsius": ["gauge", "Temperature"],
"inverter_status": ["gauge", "Inverter state (0=off, 3=producing, 5=fault)"],
"inverter_status_vendor": ["gauge", "Inverter vendor-specific fault code"],
"ac_current_amps": ["gauge", "Output bus current"],
"ac_voltage_volts": ["gauge", "Output bus voltage"],
'ac_frequency_hertz': ["gauge", "Output bus frequency"],
'ac_power_watts': ["gauge", "Active/Reactive/Apparent AC power"],
'ac_power_factor': ["gauge", "AC Phase factor"]
}
def export(d, m):
yield ('dc_voltage_volts', {}, d.dc_voltage)
yield ('dc_current_amps', {}, d.dc_current)
yield ('dc_power_watts', {}, d.dc_power)
yield ('ac_current_amps', {'phase': 'a', 'meter': 'production'}, d.ac_current_a)
yield ('ac_current_amps', {'phase': 'b', 'meter': 'production'}, d.ac_current_b)
yield ('ac_current_amps', {'phase': 'c', 'meter': 'production'}, d.ac_current_c)
yield ('ac_power_watts', {'power': 'active', 'meter': 'production'}, d.ac_power)
yield ('ac_power_watts', {'power': 'reactive', 'meter': 'production'}, d.ac_apparent_power)
yield ('ac_power_watts', {'power': 'apparent', 'meter': 'production'}, d.ac_reactive_power)
yield ('energy_watthours_total', {'meter': 'production'}, d.ac_energy)
yield ('ac_voltage_volts', {'phase': 'ab', 'meter': 'production'}, d.ac_voltage_ab)
yield ('ac_voltage_volts', {'phase': 'bc', 'meter': 'production'}, d.ac_voltage_bc)
yield ('ac_voltage_volts', {'phase': 'ca', 'meter': 'production'}, d.ac_voltage_ca)
yield ('ac_frequency_hertz', {'meter': 'production'}, d.frequency)
yield ('inverter_status', {}, d.status_code)
yield ('inverter_status_vendor', {}, d.status_vendor)
for phase in ('a','b','c','total'):
yield ('ac_current_amps', {'phase': phase, 'meter': 'mains'}, m.ac_current[phase])
yield ('ac_power_watts', {'phase': phase, 'meter': 'mains', 'power': 'active'}, m.ac_real_power[phase])
yield ('ac_power_watts', {'phase': phase, 'meter': 'mains', 'power': 'reactive'}, m.ac_reactive_power[phase])
yield ('ac_power_watts', {'phase': phase, 'meter': 'mains', 'power': 'apparent'}, m.ac_apparent_power[phase])
for phase in ('a', 'b', 'c', 'average'):
yield ('ac_power_factor', {'phase': phase, 'meter': 'mains'}, m.power_factor[phase])
yield ('ac_voltage_volts', {'phase': phase, 'meter': 'mains'}, m.ac_voltage[phase])
for meter in ('import', 'export'):
yield ('energy_watthours_total', {'meter': meter}, m.energy_real[meter])
yield ('ac_frequency_hertz', {'meter': 'mains'}, m.frequency)
def main():
parser = argparse.ArgumentParser(prog='solaredge_modbus.py', description='SolarEdge Modbus Exporter')
parser.add_argument('-d', '--debug', action='store_true')
parser.add_argument('-b', '--bind', default='localhost')
parser.add_argument('-p', '--bind-port', default='9150')
parser.add_argument('host')
parser.add_argument('port', nargs='?', default=1502)
args = parser.parse_args()
inverter = sunspec.Inverter(host=args.host, port=args.port)
def collect():
date = datetime.datetime.now()
common = inverter.common_block()
inv = inverter.data()
meters = inverter.meter(0)
yield (date, 'firmware_version', {'version': common.version}, 1)
for (m,a,v) in export(inv, meters):
yield (date,m,a,v)
prom.run(collect, metric_data, 'SolarEdge Modbus/TCP Exporter\n',
host=args.bind, port=args.bind_port, debug=args.debug)
if __name__ == '__main__':
main()