AutoRecover: bei Recover-Fenster ESP-MOSFET triggern („Stromzufuhr aktivieren")

Erkennt AutoRecover das Plotter-Recover-Fenster, ruft es jetzt zuerst
einen ESP auf (HTTP /trigger) und klickt danach „Recover". Der ESP
schaltet einen MOSFET und aktiviert damit die Stromzufuhr. Konfiguration
über config.json (esp_url/esp_path/esp_key/esp_timeout) bzw. Env-Vars;
ohne esp_url unverändertes Verhalten.

Neu: esp/skrift_mosfet.ino (ESP8266/ESP32-Firmware, WLAN + HTTP-Server,
Endpunkte /trigger /on /off, getimter Puls oder Latch) + esp/README.md
(Verdrahtung/Flashen) + config.example.json.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
s4luorth
2026-09-21 20:20:36 +02:00
parent f75957c15e
commit 16d603b19f
4 changed files with 271 additions and 0 deletions

View File

@@ -47,6 +47,61 @@ def _lade_directus_cfg():
_DX_URL, _DX_TOKEN, _DX_MID = _lade_directus_cfg()
def _lade_esp_cfg():
"""ESP-Zugang (MOSFET-Trigger) aus config.json bzw. Env-Variablen.
Erwartete Schlüssel in der config.json (neben diesem Skript oder beim Agenten):
"esp_url": "http://192.168.2.50" Basis-URL des ESP (Pflicht, sonst aus)
"esp_path": "/trigger" Endpunkt (Default /trigger)
"esp_key": "geheim" optionaler Schutz-Schlüssel (?key=)
"esp_timeout": 5 Sekunden (Default 5)
"""
url = path = key = None
timeout = 5
for pfad in (os.path.join(_HIER, "config.json"),
os.path.join(_HIER, "..", "skrift-agent", "config.json")):
try:
with open(pfad, "r", encoding="utf-8") as f:
c = json.load(f)
if c.get("esp_url"):
url = c.get("esp_url")
path = c.get("esp_path")
key = c.get("esp_key")
timeout = c.get("esp_timeout", 5)
break
except Exception:
pass
url = url or os.environ.get("SKRIFT_ESP_URL")
path = path or os.environ.get("SKRIFT_ESP_PATH") or "/trigger"
key = key or os.environ.get("SKRIFT_ESP_KEY") or ""
try:
timeout = float(timeout)
except Exception:
timeout = 5.0
return (url.rstrip("/") if url else None), path, key, timeout
_ESP_URL, _ESP_PATH, _ESP_KEY, _ESP_TIMEOUT = _lade_esp_cfg()
def esp_trigger():
"""Sagt dem ESP „Stromzufuhr aktivieren" (schaltet den MOSFET). Nie fatal.
Wird bei jedem erkannten Recover-Fenster aufgerufen. Ohne konfigurierte
esp_url passiert nichts (AutoRecover läuft normal weiter).
"""
if not (requests and _ESP_URL):
return
try:
params = {"key": _ESP_KEY} if _ESP_KEY else None
r = requests.get(_ESP_URL + _ESP_PATH, params=params, timeout=_ESP_TIMEOUT)
print(f" → ESP getriggert ({_ESP_URL}{_ESP_PATH}): HTTP {r.status_code}")
dx_log("info", f"ESP-Stromzufuhr aktiviert (HTTP {r.status_code}).")
except Exception as e:
print(f" → ESP-Trigger fehlgeschlagen: {e}")
dx_log("warn", f"ESP-Trigger fehlgeschlagen: {e}")
def dx_log(level, message):
"""Meldet ein Ereignis an Directus (agent_logs). Fehler nie fatal."""
if not (requests and _DX_URL and _DX_TOKEN):
@@ -122,6 +177,9 @@ def main():
print(f"[Versuch {versuche}/{MAX_VERSUCHE}] Fehlerfenster gefunden!")
dx_log("error", f"Plotter-Fehlerfenster erkannt (Versuch {versuche}/{MAX_VERSUCHE}): {meldung}")
# ESP zuerst: MOSFET/„Stromzufuhr aktivieren", dann Recover klicken.
esp_trigger()
time.sleep(0.5)
click_recover_button(hwnd)