v1.8.18: MQTT rc=5 Fehlerhandling, Port-Absicherung, Flash-Wizard + NuttX OTA
MQTT: - rc=5 (Not Authorized) stoppt Reconnect-Loop via _auth_failed Flag - Fehlermeldung im MQTT-Einstellungen-Banner sichtbar Sicherheit: - /api/* nur über HAOS-Ingress (X-Ingress-Path) oder Loopback erreichbar Flash-Wizard (Baustelle B): - Neuer Tab "Flash" mit IP-Eingabe und OTA-Modus-Erkennung - OTA: integrierte oder eigene Firmware via POST /api/flash/update auf Stick - Fortschrittsbalken + Polling bis Stick nach Reset wieder online - ST-Link-Erstflash-Anleitung (Pinout, st-flash Kommando) - Firmware-Binaries im Docker-Image unter /firmware/ NuttX OTA (Baustelle A, shinelanx-modbus): - ota_http.c: Zwei-Phasen OTA für STM32F103 Single-Bank Flash Stage 1: Firmware in Staging-Bereich (obere Flashhälfte) schreiben Stage 2: .ramfuncs aus SRAM heraus — Staging → App-Bereich kopieren, Reset - ota_http.h, Makefile und main.c entsprechend erweitert - ld.script.dfu: .ramfuncs in .data Section → Ausführung aus SRAM Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
bbfb11fb9c
commit
15c0ede72e
@@ -12,12 +12,23 @@ AGG_DEVICE_ID = "shinebridge_aggregate"
|
||||
AGG_TOPIC = "shinebridge/aggregate"
|
||||
|
||||
|
||||
_RC_MESSAGES = {
|
||||
1: "Falsche Protokollversion",
|
||||
2: "Client-ID abgelehnt",
|
||||
3: "Broker nicht verfügbar",
|
||||
4: "Falscher Benutzername oder Passwort",
|
||||
5: "Nicht autorisiert — Credentials prüfen",
|
||||
}
|
||||
|
||||
|
||||
class MqttPublisher:
|
||||
def __init__(self, broker: str, port: int, user: str, password: str,
|
||||
agg_meta: Optional[Dict] = None):
|
||||
self._broker = broker
|
||||
self._port = port
|
||||
self._connected = False
|
||||
self._last_error: Optional[str] = None
|
||||
self._auth_failed = False
|
||||
self._registered: List[Tuple] = []
|
||||
self._agg_meta: Dict = agg_meta or {}
|
||||
|
||||
@@ -32,6 +43,8 @@ class MqttPublisher:
|
||||
def _on_connect(self, client, userdata, flags, rc):
|
||||
if rc == 0:
|
||||
self._connected = True
|
||||
self._last_error = None
|
||||
self._auth_failed = False
|
||||
log.info("MQTT verbunden: %s:%d", self._broker, self._port)
|
||||
for entry in self._registered:
|
||||
self._publish_discovery(*entry)
|
||||
@@ -40,11 +53,17 @@ class MqttPublisher:
|
||||
for topic, _ in self._subscriptions:
|
||||
client.subscribe(topic)
|
||||
else:
|
||||
log.error("MQTT Verbindungsfehler rc=%d", rc)
|
||||
msg = _RC_MESSAGES.get(rc, f"Unbekannter Fehler")
|
||||
self._last_error = f"rc={rc}: {msg}"
|
||||
log.error("MQTT Verbindungsfehler %s", self._last_error)
|
||||
if rc == 5:
|
||||
self._auth_failed = True
|
||||
client.loop_stop()
|
||||
|
||||
def _on_disconnect(self, client, userdata, rc):
|
||||
self._connected = False
|
||||
log.warning("MQTT getrennt rc=%d", rc)
|
||||
if rc != 0:
|
||||
log.warning("MQTT getrennt rc=%d", rc)
|
||||
|
||||
def _on_message(self, client, userdata, msg):
|
||||
for topic, callback in self._subscriptions:
|
||||
@@ -60,6 +79,9 @@ class MqttPublisher:
|
||||
self._client.subscribe(topic)
|
||||
|
||||
def connect(self):
|
||||
if self._auth_failed:
|
||||
log.warning("MQTT connect übersprungen — Authentifizierung fehlgeschlagen")
|
||||
return
|
||||
try:
|
||||
self._client.connect_async(self._broker, self._port, keepalive=60)
|
||||
self._client.loop_start()
|
||||
@@ -74,6 +96,10 @@ class MqttPublisher:
|
||||
def connected(self) -> bool:
|
||||
return self._connected
|
||||
|
||||
@property
|
||||
def last_error(self) -> Optional[str]:
|
||||
return self._last_error
|
||||
|
||||
# ── Gerät-Discovery ──────────────────────────────────────
|
||||
|
||||
def register_inverter(self, inverter: Inverter, device_id: str,
|
||||
|
||||
Reference in New Issue
Block a user