mirror of
https://github.com/IdalecioSch/goodwe-influx-exporter.git
synced 2026-07-27 16:25:45 -03:00
Add files via upload
This commit is contained in:
+140
@@ -0,0 +1,140 @@
|
||||
#!/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)
|
||||
@@ -0,0 +1,4 @@
|
||||
aiohttp
|
||||
goodwe==0.4.8
|
||||
python-dotenv
|
||||
influxdb-client
|
||||
Reference in New Issue
Block a user