# Spirale, nicht Loop – Low-CO₂ Debug

**Typ:** Playbook • **Version:** v1.1 • **Scope:** ESP\_WALD → BROKER:1883 (nur dieser Pfad)
**Owner:** Eule + Vector • **Tags:** `mikrotik` `esp32` `mqtt` `low-co2` `firewall`
**Prinzip:** *Keine neuen Netze. Ein Pfad. Ein Test. Ein Log. Rollback in 1 Zeile.*

## Ziel

ESP-Clients aus `192.168.50.0/24` dürfen **nur** TCP/1883 zum Broker `192.168.88.227`. Alles andere bleibt isoliert. Entscheidungen **nach Messung**, nicht nach Gefühl.

## Null-Feuer Pledge

* Keine Upgrades / keine neuen Listen während des Debugs.
* Max. 2 Kommandos zwischen Messungen.
* Jeder Schritt liefert **Zähler** oder **Fehlercode**.
* Wenn 2 Zyklen ohne Evidenz → **Stopp & Reframe**.

---

## 0) Preflight (ohne Änderungen)

**Snapshot (RouterOS):**

```routeros
/export file=pre_debug
/ip firewall address-list print where list~"ESP|BROKER"
/ip firewall filter print terse where chain=forward
/ip firewall filter print stats where comment~"ESP|BROKER|1883|MQTT|Isolate|Block"
```

**Soll-Listen (nur sichten):**

* `ESP_WALD` → `192.168.50.0/24`
* `BROKER`   → `192.168.88.227`

> Falls FastTrack aktiv: Zähler können „leer“ bleiben. Merk’ dir die FastTrack-Regel (meist in `forward`).

---

## 1) Broker lebt lokal? (am Broker-Host)

```bash
ss -ltnp | grep :1883
mosquitto_sub -h 127.0.0.1 -t crumb/test -u esp1 -P '***' -v &
mosquitto_pub -h 127.0.0.1 -t crumb/test -m ping -u esp1 -P '***'
```

**Erwartung:** `crumb/test ping` erscheint. ✅

---

## 2) Router → Broker TCP-Probe (RouterOS)

```routeros
/tool telnet 192.168.88.227 1883
# bei "connected" sofort Ctrl-] und 'quit'
```

**Erwartung:** „connected“.
**Wenn nicht:** Routing/ARP zwischen Router und Broker prüfen (dieses Playbook stoppt hier).

---

## 3) ESP reine TCP-Probe (kein MQTT nötig)

Auf dem ESP (REPL):

```python
import usocket as s
a=('192.168.88.227',1883)
s_=s.socket(); s_.settimeout(3)
try:
    s_.connect(a); print("TCP OK")
except Exception as e:
    print("TCP FAIL", e)
finally:
    try: s_.close()
    except: pass
```

**Erwartung:** `TCP OK`.

* `ETIMEDOUT` → Pfad blockiert.
* `ECONNREFUSED` → Broker/Port unerreichbar.

---

## 4) Zähler lesen (RouterOS)

```routeros
/ip firewall filter print stats where comment~"ESP|BROKER|1883"
```

**Fall A – Zähler > 0:** Regel greift. Weiter zu **5)**.
**Fall B – Zähler = 0:** Erlaubnisregel trifft nicht → **nur eine** saubere Allow-Regel setzen.

---

## 4b) (Nur wenn nötig) **eine** Allow-Regel hinzufügen

**Einmalig, ganz nach oben in `forward` — mit Rückweg:**

```routeros
/ip firewall filter add chain=forward action=accept protocol=tcp dst-port=1883 \
    src-address-list=ESP_WALD dst-address-list=BROKER \
    place-before=0 comment="ALLOW-ESP_WALD-TO-BROKER-1883 (FINAL)"
```

**Rollback:**

```routeros
/ip firewall filter remove [find comment="ALLOW-ESP_WALD-TO-BROKER-1883 (FINAL)"]
```

**Hinweis FastTrack:** Wenn eine FastTrack-Regel davor liegt, sieht man evtl. keine Zähler. Für den Test kurz deaktivieren und danach **wieder aktivieren**:

```routeros
/ip firewall filter disable [find where action=fasttrack-connection]
# Test fahren …
/ip firewall filter enable [find where action=fasttrack-connection]
```

---

## 5) End-zu-Ende-Check

**ESP MQTT (MicroPython):**

```python
import network,time
from umqtt.simple import MQTTClient
BROKER="192.168.88.227"; TOPIC=b"crumb/test"
c=MQTTClient("esp-test", BROKER, user="esp1", password="***", keepalive=30)
c.connect(); c.publish(TOPIC, b"wuuuhuuu"); c.disconnect(); print("MQTT OK")
```

**Broker-Host:**

```bash
mosquitto_sub -h 127.0.0.1 -t 'crumb/#' -u esp1 -P '***' -v
# Erwartung: crumb/test wuuuhuuu
```

**Router-Zähler (final):**

```routeros
/ip firewall filter print stats where comment~"ALLOW-ESP_WALD-TO-BROKER-1883"
```

**Done-Kriterium:**

* ESP meldet `MQTT OK` **und**
* Broker zeigt Nachricht **und**
* Allow-Regel hat >0 Pakete/Bytes.

---

## 6) Log-Spitzen (optional, nur kurz aktivieren)

Wenn du sehen willst, *was* geblockt würde:

```routeros
/ip firewall filter set [find comment~"Isolate ESP-Wald"] log=yes log-prefix="DROP ISOLATE "
# ... Sekunden testen ...
/ip firewall filter set [find comment~"Isolate ESP-Wald"] log=no
```

---

## 7) Rollback & Sicherung

**Backup sichern:**

```routeros
/system backup save name=esp_wald_ok
/export file=esp_wald_ok_rsc
```

**Schnell-Rollback der Allow-Regel (falls doch nicht gewollt):**

```routeros
/ip firewall filter remove [find comment="ALLOW-ESP_WALD-TO-BROKER-1883 (FINAL)"]
```

---

## Troubles-Mini (nur lesen)

* **Zähler bleiben 0, aber alles geht?** → FastTrack testweise wie oben kurz aus.
* **ESP TCP OK, MQTT FAIL (Auth):** Nutzer/Passwort im Broker (`/etc/mosquitto/passwd`) checken.
* **`ETIMEDOUT` vom ESP:** Pfad/Firewall. **Nur dann** 4b fahren.
* **Broker lokal ok, remote `REFUSED`:** Listen-IP auf dem Broker (0.0.0.0:1883) prüfen.

---

## CO₂-Budget Notiz

Max. 2 Diagnose-Zyklen (1 Zyklus = messen → eine Änderung → messen). Danach Stopp, Lagebild schreiben, nächste Session planen.
