#!/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()