ShineBridge v1.9.0 — Fokus auf Energiemanagement: Flash/OTA + Setup-Wizard ausgelagert
Repositionierung: ShineBridge macht ab jetzt eine Sache gut (Energiemanagement), statt alles zu versuchen. Flash/OTA-Firmware-Update fürs ShineLAN-X und der Ersteinrichtungs-Wizard sind kein Energiemanagement-Feature und wandern ins neue, eigenständige Projekt 'growatt-diagnose-tool'. - 4 Flash/OTA-Endpunkte aus main.py entfernt (probe/firmware/update/reboot) - Flash-Tab, Flash-Panel und zugehöriges CSS/JS aus index.html entfernt - Setup-Wizard-Overlay entfernt — Geräte werden über '+ Gerät hinzufügen' im Geräte-Tab angelegt (Button existierte bereits unabhängig vom Wizard) - firmware/-Ordner (ShineLAN-X .bin-Dateien) entfernt, liegt jetzt im neuen Repo - Dockerfile: COPY firmware/ entfernt - Bugfix dabei gefunden: switchTab() referenzierte noch den entfernten 'flash'-Tab per Index — hätte die Tab-Reihenfolge durcheinandergebracht Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+2
-62
@@ -1,7 +1,6 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
import uuid
|
||||
@@ -900,67 +899,8 @@ def api_spot_price():
|
||||
log.warning("Spot-Price API Fehler: %s", e)
|
||||
return jsonify({"ok": False, "data": _spot_cache.get("data", [])})
|
||||
|
||||
_IP_RE = re.compile(r'^(\d{1,3}\.){3}\d{1,3}$')
|
||||
|
||||
@app.get("/api/flash/probe")
|
||||
def api_flash_probe():
|
||||
import urllib.request as _ur
|
||||
ip = request.args.get("ip", "").strip()
|
||||
if not ip or not _IP_RE.match(ip):
|
||||
return jsonify({"ota": False, "error": "invalid ip"}), 400
|
||||
try:
|
||||
with _ur.urlopen(f"http://{ip}/", timeout=5) as r:
|
||||
data = json.loads(r.read().decode())
|
||||
return jsonify({"ota": bool(data.get("ota")), "info": data})
|
||||
except Exception:
|
||||
return jsonify({"ota": False})
|
||||
|
||||
@app.get("/api/flash/firmware")
|
||||
def api_flash_firmware():
|
||||
fw_dir = "/firmware"
|
||||
try:
|
||||
files = sorted(f for f in os.listdir(fw_dir) if f.endswith(".bin"))
|
||||
return jsonify({"files": files})
|
||||
except Exception:
|
||||
return jsonify({"files": []})
|
||||
|
||||
@app.post("/api/flash/update")
|
||||
def api_flash_update():
|
||||
import urllib.request as _ur
|
||||
ip = request.args.get("ip", "").strip()
|
||||
fw_name = request.args.get("fw", "").strip()
|
||||
if not ip or not _IP_RE.match(ip):
|
||||
return jsonify({"ok": False, "error": "invalid ip"}), 400
|
||||
try:
|
||||
if fw_name:
|
||||
fw_path = os.path.join("/firmware", os.path.basename(fw_name))
|
||||
with open(fw_path, "rb") as f:
|
||||
data = f.read()
|
||||
else:
|
||||
data = request.get_data()
|
||||
if len(data) < 256:
|
||||
return jsonify({"ok": False, "error": "firmware too small"}), 400
|
||||
req = _ur.Request(
|
||||
f"http://{ip}/update", data=data, method="POST",
|
||||
headers={"Content-Type": "application/octet-stream",
|
||||
"Content-Length": str(len(data))})
|
||||
with _ur.urlopen(req, timeout=90) as r:
|
||||
return jsonify({"ok": True, "response": r.read().decode(errors="replace")})
|
||||
except Exception as e:
|
||||
return jsonify({"ok": False, "error": str(e)}), 502
|
||||
|
||||
@app.post("/api/flash/reboot")
|
||||
def api_flash_reboot():
|
||||
import urllib.request as _ur
|
||||
ip = request.args.get("ip", "").strip()
|
||||
if not ip or not _IP_RE.match(ip):
|
||||
return jsonify({"ok": False, "error": "invalid ip"}), 400
|
||||
try:
|
||||
req = _ur.Request(f"http://{ip}/reboot", data=b"", method="POST")
|
||||
with _ur.urlopen(req, timeout=10) as r:
|
||||
return jsonify({"ok": True})
|
||||
except Exception as e:
|
||||
return jsonify({"ok": False, "error": str(e)}), 502
|
||||
# Flash/OTA-Endpunkte ausgelagert nach growatt-diagnose-tool (v1.9.0) —
|
||||
# ShineBridge fokussiert sich auf Energiemanagement, kein Firmware-Flashing mehr.
|
||||
|
||||
@app.get("/")
|
||||
def index():
|
||||
|
||||
Reference in New Issue
Block a user