Hier ist crumb_byte.md im schlanken Crumbforest-Format – copy-paste-sicher, ohne Sonderzeichen.
(Enthält Definition, Topics, Edge-Code, Node-RED-Snippet, ACL, Tests, CO2, Troubleshooting.)
Crumb Byte (CB) – der zaehlbare Funke
Ziel
Ein CB ist ein sicher geloggter Lern-Funke: Kind handelt -> Ereignis wird mit Zeitstempel, Consent und Bestaetigung gespeichert.
CB macht Lernen messbar, ohne persoenliche Daten.
Status: v1
Scope: ESP-Wald (VLAN50), lokaler Broker, Node-RED/DB optional
Abhaengigkeiten: MQTT 3.1.1+, Uhrzeit (Broker/Node-RED), Netz erreichbar
1. Definition
Ein Crumb Byte (CB) ist 1 abgeschlossener Mikro-Zyklus:
- Ereignis am Rand (Button/Sensor/Frage)
- Payload mit ts (ms), device_id, consent=true
- Broker nimmt an
- Server bestaetigt Persistenz (ACK)
Kein PII. Nur pseudonyme device_id.
2. Broker-Parameter (Beispiel)
- Broker IP:
192.168.50.10 - Port:
1883 - User (ESP):
esp1(nur write auf incr, read auf ack) - User (Dashboard/Node-RED):
dash(read alles, write ack/agg)
3. MQTT Topics
crumb/cb/incr # Edge -> Broker (einzelner Funke)
crumb/cb/ack # Server -> Edge (Persistenz bestaetigt)
crumb/cb/agg/min # Server -> Dashboard (Rollup pro Minute)
crumb/cb/alert # Server -> Dashboard (z.B. Flood-Guard)
Payload incr (JSON):
{"id":"esp-hex-01","scene":"A","consent":true,"ts":1720000000}
Payload ack (JSON):
{"ok":true,"id":"esp-hex-01","ts":1720000050}
4. Edge (ESP / MicroPython) – Minimaler Sender
# file: main.py
import ujson as json, utime
from umqtt.simple import MQTTClient
BROKER = "192.168.50.10"
PORT = 1883
ID = "esp-hex-01"
c = MQTTClient(ID, BROKER, PORT, keepalive=60)
c.connect()
def cb_funke(scene="A"):
msg = {
"id": ID,
"scene": scene,
"consent": True,
"ts": utime.ticks_ms()
}
c.publish(b"crumb/cb/incr", json.dumps(msg))
# Beispiel: einmal senden
# cb_funke("hex")
5. Node-RED Mini-Flow (60s Aggregation, Flood-Guard, ACK)
Knoten
- mqtt-in: topic
crumb/cb/incr - function: Logik (unten)
- mqtt-out:
crumb/cb/agg/min - mqtt-out:
crumb/cb/alert - mqtt-out:
crumb/cb/ack - storage: SQLite/Influx (optional)
Function Node Code (3 Ausgaenge):
// Outputs:
// 1 -> crumb/cb/agg/min
// 2 -> crumb/cb/alert
// 3 -> crumb/cb/ack
const now = Date.now();
const W = 60000; // 1 min window
let start = context.get('windowStart') || now;
let cnt = context.get('cbCount') || 0;
if (now - start >= W) {
node.send([{payload:{t:start, count:cnt}}, null, null]);
start = now; cnt = 0;
}
const p = (typeof msg.payload === "string") ? JSON.parse(msg.payload) : (msg.payload||{});
const id = p.id || "unknown";
// Flood guard: max 10 CB per second per device
const bucket = Math.floor(now/1000);
const key = `flood:${id}:${bucket}`;
let secCnt = context.get(key) || 0;
if (secCnt > 10) {
node.send([null, {payload:{reason:"flood", id, ts:now}}, null]);
return null;
}
context.set(key, secCnt+1);
// Count + ack
cnt += 1;
context.set('windowStart', start);
context.set('cbCount', cnt);
node.send([null, null, {payload:{ok:true, id, ts:now}}]);
return null;
6. Mosquitto Minimal-Config (Ausschnitt)
/etc/mosquitto/mosquitto.conf
persistence true
persistence_location /var/lib/mosquitto/
log_dest file /var/log/mosquitto/mosquitto.log
listener 1883 0.0.0.0
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl
include_dir /etc/mosquitto/conf.d
/etc/mosquitto/acl
user esp1
topic write crumb/cb/incr
topic read crumb/cb/ack
user dash
topic read crumb/cb/#
topic write crumb/cb/ack
topic write crumb/cb/agg/min
topic write crumb/cb/alert
Test lokal
mosquitto_sub -h 127.0.0.1 -t 'crumb/#' -u dash -P '***' -v
mosquitto_pub -h 127.0.0.1 -t 'crumb/cb/incr' -m '{"id":"t1","consent":true,"ts":1}' -u esp1 -P '***'
7. Visualisierung (kindtauglich)
- Sparkline: Balken je Minute (CB/min)
- Funke-Ring (LED): 1 Puls pro CB, sanft Rot bei Alert, dann Reset
- Integrity-Badge: green >=95%, yellow 80-95%, red <80%
8. CO2 pro CB (ehrlich, grob)
Formel je Zeitraum:
CO2_per_CB = (Wh_total * Emissionsfaktor_gCO2_pro_Wh) / CB_gesamt
Wh_total = Summe Leistung (Broker + AP + Edge) * Zeit.
Ziel: CO2/CB runter, Integrity rauf.
9. Governance / Schutz
- Whitelist device_id, keine PII in Payloads
- Flood guard soft (cooldown 10 s)
- Consent Flag muss true sein, sonst verwerfen
- Tgl. Report: CB Summe, Integrity %, Median Latenz, Alerts
10. Testplan (schnell)
- Broker offen:
nc -zvw3 192.168.50.10 1883 - Sub:
mosquitto_sub -h 192.168.50.10 -t 'crumb/#' -u dash -P '***' -v - Edge sendet
cb_funke("hex") - Erwartet:
crumb/cb/incrundcrumb/cb/ackerscheinen innerhalb < 500 ms - Nach 60 s:
crumb/cb/agg/minmit count
11. Troubleshooting (kurz)
OSError 113/116am ESP: Broker-IP/Port/Firewall checken, Ping vom ESP zur Broker-IP, 2.4 GHz RSSI > -70 dBm- Broker startet nicht: doppelte persistence_location entfernen, Logs ansehen
- Keine Acks: Node-RED-Flow aktiv? Topic-Namen exakt? JSON gueltig?
- Fluten:
crumb/cb/alertpruefen, Sensor entprellen
12. Glossar
- CB: Crumb Byte, 1 gezaehlter Funke mit Bestaetigung
- Integrity %: Anteil CB mit ts+consent+persistent OK
- Flood Guard: Schutz gegen ungewollte Event-Stuerme
Warum das wichtig ist
CB zaehlt nicht Klicks, sondern vertrauenswuerdige Lernmomente.
Klein, pruefbar, freundlich – genau das, was ein Wald braucht.