#!/usr/bin/env python3 """Simuliert eine go-e-Wallbox-Ladung über MQTT, um den Collector zu testen. Sendet nacheinander: car=2 (Start) -> wh -> cdi -> car=4 (Ende) Broker/User/Topic werden – wie beim Collector – aus der .env gelesen. Beispiele: .venv/bin/python collector/sim_charge.py # 5230 Wh, 3600 s .venv/bin/python collector/sim_charge.py --wh 8000 --duration 5400 .venv/bin/python collector/sim_charge.py --end idle # mit car=1 beenden .venv/bin/python collector/sim_charge.py --no-finish # Session offen lassen """ import argparse import json import os import sys import time import paho.mqtt.client as mqtt from dotenv import load_dotenv load_dotenv() MQTT_HOST = os.environ.get("MQTT_HOST", "localhost") MQTT_PORT = int(os.environ.get("MQTT_PORT", "1883")) MQTT_USER = os.environ.get("MQTT_USER") or None MQTT_PASS = os.environ.get("MQTT_PASS") or None TOPIC_BASE = os.environ.get("MQTT_TOPIC_BASE", "go-eCharger/310014").rstrip("/") def parse_args() -> argparse.Namespace: p = argparse.ArgumentParser(description="Test-Ladung über MQTT simulieren") p.add_argument("--wh", type=float, default=5230.5, help="geladene Energie in Wh") p.add_argument("--duration", type=int, default=3600, help="Ladedauer in Sekunden") p.add_argument("--end", choices=["complete", "idle"], default="complete", help="Abschluss über car=4 (complete) oder car=1 (idle)") p.add_argument("--no-finish", action="store_true", help="Session nicht abschließen (kein car=1/4 senden)") p.add_argument("--delay", type=float, default=0.7, help="Pause zwischen den Nachrichten in Sekunden") return p.parse_args() def main() -> int: args = parse_args() client = mqtt.Client( callback_api_version=mqtt.CallbackAPIVersion.VERSION2, client_id="auto-charger-sim", ) if MQTT_USER: client.username_pw_set(MQTT_USER, MQTT_PASS) print(f"Verbinde zu {MQTT_HOST}:{MQTT_PORT} (Topic-Basis {TOPIC_BASE}) ...") try: client.connect(MQTT_HOST, MQTT_PORT, keepalive=60) except OSError as exc: print(f"FEHLER: Verbindung zum Broker fehlgeschlagen: {exc}") return 1 client.loop_start() end_car = 4 if args.end == "complete" else 1 steps: list[tuple[str, str]] = [ ("car", "2"), ("wh", f"{args.wh}"), ("cdi", json.dumps({"type": 1, "value": args.duration * 1000})), ] if not args.no_finish: steps.append(("car", str(end_car))) for key, payload in steps: topic = f"{TOPIC_BASE}/{key}" info = client.publish(topic, payload, qos=1) info.wait_for_publish(timeout=5) print(f" -> {topic} = {payload}") time.sleep(args.delay) client.loop_stop() client.disconnect() print("Fertig. Erwartete Collector-Ausgabe: 'Ladung gestartet ...' " "und 'Ladung gespeichert: %.0f Wh, %d s'." % (args.wh, args.duration)) return 0 if __name__ == "__main__": try: sys.exit(main()) except KeyboardInterrupt: sys.exit(0)