#!/usr/bin/env python3 import os import sys import time import asyncio from datetime import datetime, date, timedelta from decimal import Decimal import xml.etree.ElementTree as ET import aiohttp import goodwe from dotenv import load_dotenv from influxdb_client import InfluxDBClient, Point from influxdb_client.client.write_api import SYNCHRONOUS load_dotenv() print("=" * 60) print("GoodWe Influx Exporter") print("=" * 60) INVERTER_IP = os.getenv('INVERTER_IP') POLLING_INTERVAL = int(os.getenv('POLLING_INTERVAL', '30')) PV_POWER = float(os.getenv('PV_POWER', '5670')) SCRAPE_SPOT_PRICE = os.getenv('SCRAPE_SPOT_PRICE', 'False').lower() == 'true' INFLUXDB_URL = os.getenv('INFLUXDB_URL') INFLUXDB_TOKEN = os.getenv('INFLUXDB_TOKEN') INFLUXDB_ORG = os.getenv('INFLUXDB_ORG') INFLUXDB_BUCKET = os.getenv('INFLUXDB_BUCKET') if not INVERTER_IP: print("ERRO: INVERTER_IP não configurado no .env") sys.exit(1) if not all([INFLUXDB_URL, INFLUXDB_TOKEN, INFLUXDB_ORG, INFLUXDB_BUCKET]): print("ERRO: Configurações do InfluxDB faltando no .env") sys.exit(1) print(f"Inversor: {INVERTER_IP}") print(f"Intervalo: {POLLING_INTERVAL}s") print(f"InfluxDB: {INFLUXDB_URL}") print("=" * 60) influx_client = InfluxDBClient(url=INFLUXDB_URL, token=INFLUXDB_TOKEN, org=INFLUXDB_ORG) write_api = influx_client.write_api(write_options=SYNCHRONOUS) current_port = 8899 def write_to_influx(measurement, fields, tags=None): try: point = Point(measurement) if tags: for key, value in tags.items(): point = point.tag(key, value) for key, value in fields.items(): if isinstance(value, (int, float)): point = point.field(key, float(value)) write_api.write(bucket=INFLUXDB_BUCKET, record=point) except Exception as e: print(f"Erro ao escrever no InfluxDB: {e}") async def connect_inverter(): #conecta ao inversor alternando entre portas 8899 e 48899 global current_port ports = [8899, 48899] for attempt in range(len(ports)): try: print(f"Tentando conectar na porta {current_port}...") inverter = await goodwe.connect(INVERTER_IP, timeout=5, retries=1,port=current_port, family="DT") print(f"✓ Conectado na porta {current_port}") return inverter except Exception as e: print(f"✗ Falha na porta {current_port}: {e}") current_port = 48899 if current_port == 8899 else 8899 print(f"Tentando novamente na porta {current_port}...") return await goodwe.connect(INVERTER_IP, timeout=5, retries=1, family="DT") async def collect_and_send(): inverter = await connect_inverter() runtime_data = await inverter.read_runtime_data() # prepara dados fields = {} for sensor in inverter.sensors(): if sensor.id_ in runtime_data: value = runtime_data[sensor.id_] if isinstance(value, (int, float)): fields[sensor.id_] = float(value) fields['pv_total_power'] = PV_POWER write_to_influx( "inverter_data", fields, { "inverter_ip": INVERTER_IP, "model": runtime_data.get("model_name", "unknown") } ) print(f"[{datetime.now().strftime('%H:%M:%S')}] Enviado {len(fields)} métricas | " f"Potência: {fields.get('ppv', 0):.0f}W | " f"Energia hoje: {fields.get('e_day', 0):.2f}kWh ") async def main_loop(): print("\nIniciando coleta de dados...\n") while True: try: await collect_and_send() except Exception as e: print(f"✗ Erro: {e}") await asyncio.sleep(POLLING_INTERVAL) if __name__ == "__main__": try: asyncio.run(main_loop()) except KeyboardInterrupt: print("\n\nInterrompido pelo usuário") influx_client.close() sys.exit(0) except Exception as e: print(f"\n\nErro fatal: {e}") influx_client.close() sys.exit(1)