91 lines
4.0 KiB
Python
91 lines
4.0 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"],
|
|
'meter_event': ["gauge", 'Power meter event']
|
|
}
|
|
|
|
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)
|
|
for event in m.events:
|
|
yield ('meter_event', {'event': event}, float(m.events[event]))
|
|
|
|
|
|
|
|
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()
|