Die letzten sechs Beiträge:

Über mich

Wie viele ....

Random Post Random Post Random Post Random Post Random Post Random Post
Search
Search

Ausgewählte Beiträge

Zusammenstellung von ausgewählten Beiträgen aus dem Blog

    Die neue Eisenbahn Brücke bei Fridingen Richtung Mühlheim

    21. Juni 2026 Simplon Tour Zepfenhahn, Lochen, Fridingen, Tuttlingen, Spaichingen

    An diesen Wettermäßig sehr warmen Sonntag habe ich mir meine Donaual Runde vorgenommen, allerdings wollte ich im Uhrzeigernsinn fahren und noch ein Stück dazu hängen. Der Plan war von Göllsdorf nach Feckenhausen weiter nach Zepfenhahn und Schömberg, dann Hausenam Tann und Tieringen. In Schömberg habe ich dann beschlossen über den Lochen zu fahren. Das war etwa so gegen 14:00 Uhr, da war es richtig warm.  Dafür gab es eine schöne Abfahrt nach Tieringen runter, wo es sonst auf der anderen Strecke hoch geht.

    Weiter ging es dann nach Oberdigisheim, Unterdigisheim, Nusplingen wo es ein Gewitter hatte das zum Glück vor mir abgeldaen hat, die Strecke war nass und es hat immer weider leicht geregnet. Weiter nach Fridingen, an der neune Brücke hab ich kurz angehalten und einige Bilder gamcht. Aus der Wntfernung habe ich das Wummern vom Southside Festival gehört.

    Ab Mühlheim war es dann wieder abgetrocknet und wurde wieder warm. Weiter bin ich dann wie üblich über Tuttlingen, Spaichingen Michelfeld zurück gefahren. Am Ende  knapp 105 km.

    War ganz schön dehydriert und hab auf dem Sofa dann Krämpfe im Oberschenkel bekommen, sehr unangenehm.

    Trotz den Beschwerden hinter her ne schöne Tour und dreistellige km .. das ist ganz ok.

    Gruß

    Edi

    Die zurückgelegte Strecke als Open Street Map Karte mit Höhenprofil und Zusatzinfos

    Simplon Tour Zepfenhahn, Lochen, Fridingen, Tuttlingen, Spaichingen – 21.06.2026

    Gesamtstrecke: 102747 m
    Maximale Höhe: 825 m
    Minimale Höhe: 512 m
    Gesamtanstieg: 1196 m
    Gesamtabstieg: -1185 m
    Gesamtzeit: 03:57:30
    Download file: 2026-06-21-edi-teppert-com-SimplonTourZepfenhahnLochenFridingenTuttlingenSpaichingen.gpx

  • Schleuse im Neckar in Horb

    07. Juni 2026 Simplon Tour Villingendorf, Herrenzimmern, Talhausen, Altoberndorf, Sulz, Horb zurück Sigmarswangen, Bochingen, AO

    Heute mal eine Tour am Neckar entlang bis nach Horb. Die Technik hat heute richtig gezickt, Garmin Uhr und Edge haben nicht sauber aufgezeichnet und nur einen Teil der Tour im Speicher gehabt. Mein zuverlässiger “analoger” Tacho hat normal funktioniert und am Ende die erwarteten 120 km angezeigt.

    Tourverlauf:
    Rottweil durch die Stadt, Villingendorf, Herrenzimmern, runter nach Talhausen, auf dem Neckartalradweg über Epfendorf nach Altoberndorf, in Oberdorf dann auf der Strasse bis Sulz, Horb zurück hoch nach Sigmarswangen, Bochingen, wieder runter nach Altoberndorf und die Strasse hoch nach Villingendorf. Am Cafe eine kurze Pause mit Kaffee und einer Cola. Der Rest dann wieder über Rottweil heim.

    Gruß

    Edi

    Die zurückgelegte Strecke als Open Street Map Karte mit Höhenprofil und Zusatzinfos

    Simplon Tour Villingendorf, Herrenzimmern, Talhausen, Altoberndorf, Sulz, Horb zurück Sigmarswangen, Bochingen, AO – 07.06.2026

    Gesamtstrecke: 72259 m
    Maximale Höhe: 643 m
    Minimale Höhe: 388 m
    Gesamtanstieg: 828 m
    Gesamtabstieg: -657 m
    Gesamtzeit: 03:18:36
    Download file: 2026-06-07-edi-teppert-com-SimplonTourHerrenzimmernTalhausenSulzHorbSigmarswangenBochingenAltoberndorf.gpx

  • Bodmann Hafenpromenade - der See hat hostorisch wenig Wasser

    31. Mai 2026 Simplon Tour – Bodmann über Ludwigshafen zurück Wasserburger Tal, Witthoh mit Gewitter

    Am Sonntag den 31. Mai 2026 habe ich mir überlegt, mal wieder eine Tour an den Bodensee zu machen. Die Wettervorhersage war nicht wirklich gut aber Regen war erst für 17:00 Uhr angesagt. Die Tour, die ich schon so oft gefahren bin hab ich dann einfach mal in Angriff genommen.

    Von Daheim über Spaichingen, Tuttlingen, Emmingen, Windegg, Stokach, Ludwigshafen nach Bodmann. Am Strandbad wollte ich ne Pause machen und Kaffee und Kuchen verspeisen, leider war da so voll, dass ich es bleiben liess.

    Vor der Abfahrt habe ich mir zwei Flschen mit Getränekn vorbereitet zum Mitnehmen. Bin dann losgefahren und habe nach 10 km bemerkt, dass ich die Flaschen stehen lassen habe … dumm gllaufen, aber umdrehen wollte ich auch nicht. Also weitergefahren, dachte bis Bodmann gehts ja eher runter, das schaffe ich ohne Wasser. Da das Strandcafe voll war bin ich dann Richtung Marienschlucht gefahren in der Hoffnung eine Möglichkeit zum Essen / Trinken zu finden. Erst als ich umgedreht habe konnte ich an einem Kebap Getränke kaufen und eine 500 ml Flasche mitnehmen.

    Auf dem Rückweg hat es dann kurz vor dem Schlss Langenstein / Eigeltingen angefangen zu Gewittern, so dass ich eine Pause machen musste. Nch etwa 10 – 15 min. konnte ich weiterfahren, bin aber immer wieder nass geworden weil es stellenweise leicht geregnet hat.

    Die Herausforderung war das Wasserburger Tal bis zum Witthoh, da geht es nur hoch, da konnte ich erleben wie gut es mit meiner Kondition stand. Ich dache mir: ich komm jede Steigung hoch, muss halt langsamer fahren und das hat geklappt. Am ende ca. 140 km, kmnapp 1200 hm.

    Um kurz vor 17:00 Uhr war ich daheim und um 18:00 Uhr hat es dann richtig angefangen zu schütten. Glück gehabt!

    Ich hab´s noch drauf 🙂

    Gruß

    Edi

    Die zurückgelegte Strecke als Open Street Map Karte mit Höhenprofil und Zusatzinfos

    Simplon Tour Bodmann über Ludwigshafen zurück Wasserburger Tal, Witthoh mit Gewitter – 31.05.2026

    Gesamtstrecke: 131806 m
    Maximale Höhe: 843 m
    Minimale Höhe: 406 m
    Gesamtanstieg: 1490 m
    Gesamtabstieg: -1628 m
    Gesamtzeit: 05:46:03
    Download file: 2026-05-31-edi-teppert-com-SimplonTourBodmannLudwigshafenWasserburgerTalWitthoh.gpx

  • Blick auf die Burg Wildenstein im Donautal

    17. Mai 2026 Wanderung Donautal – von Fridingen ans Jägerhaus und zurück

    Heute zum Abschluss der Urlaubswoche noch eine Wanderung, da das Wetter so halbwegs gut ausgesehen hat. Tatsächlich sind wir nicht nass geworden und konnten Hin- und Rückweg trocken aber recht kühl absolvieren.

    Die Natur ist in voller Blüte und alles ist grün … das Donautal ist zu dieser Zeit wirklich sehr schön und immer wieder entdeckt man Neues, wie z. B. das Schloss Bronnen. Das ist mir nie so richtig aufgefallen wenn ich mit dem Rad auf dem Donauradweg unterwergs war. Wäre sicher mal eine Besichtigung wert, leider ist die burg für die Öeentlichkeit gesperrt.

    Die Burg WIldenstein ist ebenfalls auf dem Verlauf der Wanderung aus der Enfernung zu sehen: Burg Wildenstein

    Ein kurzer Auszug aus Wikipedia vom Schloss Bronnen:
    Die für die Öffentlichkeit nicht zugängliche Burganlage befindet sich auf einem steil abfallenden Felsen im Oberen Donautal. Unter ihr fließt die Donau. Die Anlage liegt im Landkreis Tuttlingen, nahe an der Kreisgrenze zum Landkreis Sigmaringen.

    Die Wanderung war kpl. flach und ohne Herausforderungen, aber doch einige km, leider hat sich in meiner GPX Aufzeichnung eine fataler Höhenmessfehler eingeschlichen, der diese im Prinzip unbrauchbar macht.

    Gruß

    Edi

    Die zurückgelegte Strecke als Open Street Map Karte mit Höhenprofil und Zusatzinfos

    Donautal Wanderung – Fridingen, Jägerhaus – 17.05.2026

    Gesamtstrecke: 23809 m
    Maximale Höhe: 5841 m
    Minimale Höhe: 582 m
    Gesamtanstieg: 5589 m
    Gesamtabstieg: -5589 m
    Gesamtzeit: 02:53:24
    Download file: 2026-05-17-edi-teppert-com-DonautalWanderung.gpx

    Bereinigte Version: Donautal Wanderung – Fridingen, Jägerhaus – 17.05.2026

    Gesamtstrecke: 13697 m
    Maximale Höhe: 656 m
    Minimale Höhe: 582 m
    Gesamtanstieg: 334 m
    Gesamtabstieg: -334 m
    Gesamtzeit: 02:46:30
    Download file: 2026-05-17-edi-teppert-com-DonautalWanderung-bereinigt.gpx

  • Das Eingangstor zum Kloster Kirchberg

    03. Mai 2026 Simplon Tour – RW, Villingendorf, Marschalkenzimmern, Hopfau, Glatt, Kloster Kirchberg, Geislingen, BL, Schömberg, Schörzingen, Wellendingen

    Heute mal wieder seit längerer Zeit eine Tour mit dreistelligen km, die Höhenmeter hatten es auch in sich.

    Der Tourverlauf:
    nach Rottweil durch die Stadt über den Hegneberg dann nach Villingendorf, Herrenzimmern, Bösingen, Beffendorf, Hochmössingen. Immer auf der Höhe bleiben weiter nach Marschalkenzimmern, Brachfeld, dann ging es runter nach Hopfau, zurück nach Glatt, Neckarhausen, Fischingen, Mühlheim, Renfritzhausen. Zum Kloster Kirchberg waren einige Höhenmeter zu absolvieren, dort habe ich dann Kaffee, Kuchen und ein Cola zu mir genommen. Danach ging es weiter nach Heiligenzimmern. Nach Binsdorf ging es wieder einige Höhenmeter rauf. Dann weiter nach Geislingen, durch Balingen, an Frommern vorbei ürsprünglichwar der Lochen noch eingeplant, das war mir dann doch zu anstrengend also alternativ nach Rosswangen, Dotternhausen, Schömberg, Schörzingen, Wilflingen, Wellendingen, zurück nach Neufra.

    Das Wettter war ganz ok, später als ich schon zwei Stunden daheim war hat es noch geregnet und wurde kühl.

    Ja die Form lässt noch zu wünschen übrig, da fehlt das Training.

    Trotzdem ne schöne Tour und ganz gut duchgekommen obwohl ich am Freitag zwei Tage davor auch 90 km gefahren bin.

    Gruß

    Edi

    Die zurückgelegte Strecke als Open Street Map Karte mit Höhenprofil und Zusatzinfos

    Simplon Tour RW, Villingendorf, Marschalkenzimmern, Hopfau, Glatt, Kloster Kirchberg, Geislingen, BL, Schömberg, Schörzingen, Wellendingen – 03.05.2026

    Gesamtstrecke: 106731 m
    Maximale Höhe: 732 m
    Minimale Höhe: 404 m
    Gesamtanstieg: 1530 m
    Gesamtabstieg: -1526 m
    Gesamtzeit: 04:39:00
    Download file: 2026-05-03-edi-teppert-com-SimplonTourGlattKlosterKirchbergBL.gpx

  • Heimann Rauchmelder Titelbild

    Heiman HS1SA-E Rauchmelder mit ZigBee2MQTT in Node-Red

    Meine bisheringen Rauchmelder arbeiten alle Standalone, die sind zwar recht laut wenn ein Alarm gemeldet wird, aber nicht vernetzbar, so dass immer nur der Melder in dem Raum einen Alarm ausgibt wo Rauch erkannt wird.

    Da ich ein IoT Smarthome System einsetze lag es nahe vernetzbare Rauchmelder einzusetzen. Nach einer ausfürlichen Suche bin ich auf die “Heimann HS1SA-E Rauchmelder mit ZigBee2MQTT” aufmerksam geworden und habe mir einige davon beschafft. Es gibt da verschiedene Typen, die einen haben ZigBee, andere nicht wichtig: HS1SA-E der kann ZigBee. Nach meiner Recherche ist wohl gerade ein Nachfolgemodell in Entwicklung, das auch einen Testalarm per ZigBee unterstützt, was das Modell HS1SA-E nicht kann!

    Meine Intergartion basiert auf Node-Red mit ZigBee2MQTT (die Voraussetzungen siehe weiter unten), ich habe mir dazu Schritt für Schritt einen Flow erstellt, der den Zustand der Rauchmelder erfasst und Berichte per Mail, ntfy und Pushover verschickt. Falls es einen Alarm gibt habe ich eine ZigBee Kerzenbirne in zentraler Lage eingebunden, die dann blinkt. Mit einer aktustische Meldung muss ich mir noch überlegen wie das inntegriert werden könnte.

    Die Rauchmelder sind etwas zickig bei der Integration in ZB2M, wenn man ein Interview startet muss man am Besten alle zwei drei Sekunden den Reset Knopf kurz drücken, damit sie nicht sofort wieder in den Schlafmodus gehen. Musste das mehrmals machen, damit die Daten sauber ausgelesen werden konnten, seit dem ist es ok.

    Das Ganze ist natürlich noch V 0.8, also da gibt es noch Potential für Verbesserungen, wer will kann sich ja mal mit dem Status Quo versuchen und mir Rückmeldung geben für Verbesserungen, Korrekturen oder was auch immer. Schon mal viel Sapß damit.

    Gruß

    Edi

    Eine Beschreibung des Heimann Rauchmelders:
    HEIMAN Zigbee Rauchmelder

    Der HEIMAN Zigbee Rauchmelder besitzt eine genaue Raucherkennung und Sie werden akustisch und visuell alarmiert. In einer ernsten Situation alarmiert der Rauchsensor mit einer roten LED, die schnell und mit einem lauten Alarm blinkt. Darüber hinaus besteht die Möglichkeit, eine Warnung auf Ihrem Smartphone zu erhalten, wenn Sie nicht zu Hause sind. So wird verhindert, dass ein Brand durch Rauch entsteht und teure Folgeschäden verursacht werden.
    Durch den Einsatz der Funktechnologie Zigbee 3.0 kann der Sensor an jedes Zigbee-Gateway angeschlossen werden. Dank des neuesten Zigbee 3.0 Standards gewährleistet der Rauchsensor eine Batterielebensdauer von 3 Jahren.
    Eigenschaften:

    Erkennt Rauch und sichtbare Partikel, welche durch einen Schwelbrand entstehen
    Benachrichtigung über Feueralarm, auch unterwegs
    Lautstärke des Alarms: 85 dB/3m
    Anzeige des Batteriestandes
    Batterie notwendig: Ja (1x Batterie CR123A)
    Lebensdauer der Batterie: 3 Jahre
    Funktechnologie: Zigbee 3.0
    Rauchmelder entspricht DIN EN14604 Norm

    Voraussetzung für den gesamten Ablauf:
    • Raspberrypi
    • MQTT Broker
    • ZigBee2mQTT mit Sonoff Dongle oder Ähnlichem
      • Heimann Rauchmelder
        • ZigBee Kerzenbirne oder was sonst zum Alarmieren verwendet wird
    • Node-Red mit Dashboard 2.0 und diversen anderen Paletten
    • ntfy Account
    • Pushover Account
    •  Mailaccount
      • für die Zustellung der Meldungen werden ntfy, Pushover und Mail verwendet
    Der komplette Node-Red Flow für die Rauchmelder Integration:
    [
    {
    “id”: “f19c1232b5818c2a”,
    “type”: “group”,
    “z”: “a906f7d4665bf705”,
    “style”: {
    “stroke”: “#999999”,
    “stroke-opacity”: “1”,
    “fill”: “none”,
    “fill-opacity”: “1”,
    “label”: true,
    “label-position”: “nw”,
    “color”: “#a4a4a4”
    },
    “nodes”: [
    “a6ea58dab388b29c”,
    “765bf0769705a2ff”,
    “g7h8i9j0k1l2m3n4”,
    “i9j0k1l2m3n4o5p6”,
    “fac5633b6eba8601”,
    “7a1904f924795633”,
    “1fc2a6b8f60b088d”,
    “f8b1b27956f09b3e”,
    “147944ef03bfde4c”,
    “4ab2f6e25855efce”,
    “9d6eebcf795ee86e”,
    “ac1607f8f0db6b5d”,
    “24495c060d2a8756”,
    “2bb5b7ad91154a04”,
    “06fda76032ceaefb”,
    “296a847a7c85c981”,
    “3deb8b862d1238e4”,
    “acbb6ccfa4615f05”,
    “2cf42ba58b153108”,
    “0f916dab840c7276”,
    “fd8f8ffdf77a106c”,
    “0469b6708a6631f2”,
    “e45e871a10a710b2”,
    “95efe3c5faf4ab5b”,
    “6f243fcb4da873d4”,
    “b69dfaa826fb2d91”,
    “685b6cb6ac3300e8”,
    “efd4d502334fbc36”,
    “6247c2a58286fc73”,
    “ab3764d33b337c6f”,
    “0f3d4c079b703181”,
    “cb8dcc5798bb85a4”,
    “551b4d13bc9b505f”,
    “191ef45fc6c07a97”,
    “d4e9451a20607f2f”
    ],
    “x”: 34,
    “y”: 19,
    “w”: 1312,
    “h”: 522
    },
    {
    “id”: “a6ea58dab388b29c”,
    “type”: “zigbee2mqtt-get”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “”,
    “server”: “1bfcccb11dd30d19”,
    “friendly_name”: “KellerWerkstatt (HS1SA-E)”,
    “device_id”: “0xf84477fffe123ed0”,
    “state”: “0”,
    “enableMultiple”: false,
    “x”: 400,
    “y”: 100,
    “wires”: [
    [
    “06fda76032ceaefb”
    ]
    ]
    },
    {
    “id”: “765bf0769705a2ff”,
    “type”: “inject”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “8:00 Tag”,
    “props”: [
    {
    “p”: “topic”,
    “vt”: “str”
    }
    ],
    “repeat”: “”,
    “crontab”: “00 08 * * *”,
    “once”: false,
    “onceDelay”: 0.1,
    “topic”: “”,
    “x”: 140,
    “y”: 140,
    “wires”: [
    [
    “a6ea58dab388b29c”
    ]
    ]
    },
    {
    “id”: “g7h8i9j0k1l2m3n4”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “E-Mail Formatierung”,
    “func”: “let data = msg.payload;\n\n// E-Mail Inhalt erstellen\nlet emailContent = `\n<h2>🏠 🚨 Rauchmelder Statusbericht</h2>\n<p><strong>Gerät:</strong> ${data.friendly_name}</p>\n<p><strong>Datum/Uhrzeit:</strong> ${new Date(data.timestamp).toLocaleString(‘de-DE’)}</p>\n<hr>\n<h3>Status:</h3>\n<table border=\”1\” cellpadding=\”5\” cellspacing=\”0\” style=\”border-collapse: collapse;\”>\n <tr>\n <td><strong>Batteriestatus:</strong></td>\n <td>${data.battery}%</td>\n </tr>\n <tr>\n <td><strong>Batterie OK:</strong></td>\n <td>${data.battery_ok ? ‘✅ Ja’ : ‘❌ Nein – Bitte wechseln!’}</td>\n </tr>\n <tr>\n <td><strong>Test-Modus:</strong></td>\n <td>${data.test_mode ? ‘🔴 Aktiv’ : ‘⚪ Inaktiv’}</td>\n </tr>\n <tr>\n <td><strong>Rauchmelder:</strong></td>\n <td>${data.smoke ? ‘🚨 ALARM’ : ‘✅ Normal’}</td>\n </tr>\n <tr>\n <td><strong>Signalstärke:</strong></td>\n <td>${data.linkquality} LQI</td>\n </tr>\n</table>\n\n<p><em>Automatisierte Statusmeldung ZigBee Rauchmelder ${data.friendly_name}.</em></p>\n`;\n\n// Warnung bei niedrigem Batteriestand\nif (!data.battery_ok) {\n emailContent = emailContent.replace(‘<h2>’, ‘<h2 style=\”color: red;\”>⚠️ WARNUNG – ‘);\n emailContent += ‘<p style=\”color: red; font-weight: bold;\”>⚠️ Der Batteriestand ist niedrig! Bitte tauschen Sie die Batterie aus.</p>’;\n}\n\nmsg.payload = emailContent;\nmsg.topic = `Rauchmelder ${data.friendly_name} Statusbericht`;\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: “”,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 820,
    “y”: 240,
    “wires”: [
    [
    “fac5633b6eba8601”
    ]
    ]
    },
    {
    “id”: “i9j0k1l2m3n4o5p6”,
    “type”: “inject”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Manueller Test”,
    “props”: [
    {
    “p”: “payload”
    },
    {
    “p”: “topic”,
    “vt”: “str”
    }
    ],
    “repeat”: “”,
    “crontab”: “”,
    “once”: false,
    “onceDelay”: 0.1,
    “topic”: “”,
    “payload”: “”,
    “payloadType”: “date”,
    “x”: 160,
    “y”: 100,
    “wires”: [
    [
    “a6ea58dab388b29c”
    ]
    ]
    },
    {
    “id”: “fac5633b6eba8601”,
    “type”: “e-mail”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “server”: “smtp.mail.de”,
    “port”: “465”,
    “secure”: true,
    “tls”: true,
    “name”: “rauchmelder@domain.com”,
    “dname”: “Rauchmelder Mail Bericht”,
    “output”: false,
    “outputs”: 0,
    “x”: 890,
    “y”: 300,
    “wires”: []
    },
    {
    “id”: “7a1904f924795633”,
    “type”: “debug”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Daten aufbereitet”,
    “active”: true,
    “tosidebar”: true,
    “console”: false,
    “tostatus”: false,
    “complete”: “payload”,
    “targetType”: “msg”,
    “statusVal”: “”,
    “statusType”: “auto”,
    “x”: 850,
    “y”: 60,
    “wires”: []
    },
    {
    “id”: “1fc2a6b8f60b088d”,
    “type”: “ui-gauge”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Rauchmelder Batterie”,
    “group”: “5673b51cc6b259c0”,
    “order”: 1,
    “value”: “payload.battery”,
    “valueType”: “msg”,
    “width”: 3,
    “height”: 3,
    “gtype”: “gauge-half”,
    “gstyle”: “needle”,
    “title”: “Batterie”,
    “alwaysShowTitle”: false,
    “units”: “%”,
    “icon”: “”,
    “prefix”: “”,
    “suffix”: “”,
    “segments”: [
    {
    “from”: “0”,
    “color”: “#ff2600”,
    “text”: “”,
    “textType”: “label”
    },
    {
    “from”: “40”,
    “color”: “#ffc800”,
    “text”: “”,
    “textType”: “label”
    },
    {
    “from”: “100”,
    “color”: “#4e8f00”,
    “text”: “”,
    “textType”: “label”
    }
    ],
    “min”: 0,
    “max”: 100,
    “sizeThickness”: 16,
    “sizeGap”: 4,
    “sizeKeyThickness”: 8,
    “styleRounded”: true,
    “styleGlow”: false,
    “className”: “”,
    “x”: 1220,
    “y”: 60,
    “wires”: [
    []
    ]
    },
    {
    “id”: “f8b1b27956f09b3e”,
    “type”: “ui-text”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “group”: “5673b51cc6b259c0”,
    “order”: 7,
    “width”: “3”,
    “height”: 1,
    “name”: “Batterie Anzeige”,
    “label”: “Batteriestatus”,
    “format”: “{{msg.payload.battery}}%”,
    “layout”: “row-spread”,
    “style”: false,
    “font”: “”,
    “fontSize”: “”,
    “color”: “#000000”,
    “wrapText”: false,
    “className”: “”,
    “value”: “payload.battery”,
    “valueType”: “msg”,
    “x”: 1200,
    “y”: 100,
    “wires”: []
    },
    {
    “id”: “147944ef03bfde4c”,
    “type”: “ui-text”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “group”: “5673b51cc6b259c0”,
    “order”: 6,
    “width”: “3”,
    “height”: 1,
    “name”: “Batterie OK Status”,
    “label”: “Batterie OK”,
    “format”: “{{msg.payload.battery_ok ? ‘✅ Ja’ : ‘❌ Nein’}}”,
    “layout”: “row-spread”,
    “style”: false,
    “font”: “”,
    “fontSize”: “”,
    “color”: “#000000”,
    “wrapText”: false,
    “className”: “”,
    “value”: “payload.battery_ok”,
    “valueType”: “msg”,
    “x”: 1210,
    “y”: 140,
    “wires”: []
    },
    {
    “id”: “4ab2f6e25855efce”,
    “type”: “ui-text”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “group”: “5673b51cc6b259c0”,
    “order”: 5,
    “width”: “3”,
    “height”: 1,
    “name”: “Test Modus”,
    “label”: “Test-Modus”,
    “format”: “{{msg.payload.test_mode ? ‘🔴 Aktiv’ : ‘⚪ Inaktiv’}}”,
    “layout”: “row-spread”,
    “style”: false,
    “font”: “”,
    “fontSize”: “”,
    “color”: “#000000”,
    “wrapText”: false,
    “className”: “”,
    “value”: “payload.test_mode”,
    “valueType”: “msg”,
    “x”: 1190,
    “y”: 180,
    “wires”: []
    },
    {
    “id”: “9d6eebcf795ee86e”,
    “type”: “ui-text”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “group”: “5673b51cc6b259c0”,
    “order”: 4,
    “width”: “3”,
    “height”: 1,
    “name”: “Rauch Status”,
    “label”: “Rauchmelder”,
    “format”: “{{msg.payload.smoke ? ‘🚨 ALARM’ : ‘✅ Normal’}}”,
    “layout”: “row-spread”,
    “style”: false,
    “font”: “”,
    “fontSize”: “”,
    “color”: “#000000”,
    “wrapText”: false,
    “className”: “”,
    “value”: “payload.smoke”,
    “valueType”: “msg”,
    “x”: 1200,
    “y”: 220,
    “wires”: []
    },
    {
    “id”: “ac1607f8f0db6b5d”,
    “type”: “ui-text”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “group”: “5673b51cc6b259c0”,
    “order”: 3,
    “width”: “3”,
    “height”: 1,
    “name”: “Signalstärke”,
    “label”: “Signalstärke”,
    “format”: “{{msg.payload.linkquality}} LQI”,
    “layout”: “row-spread”,
    “style”: false,
    “font”: “”,
    “fontSize”: “”,
    “color”: “#000000”,
    “wrapText”: false,
    “className”: “”,
    “value”: “payload.linkquality”,
    “valueType”: “msg”,
    “x”: 1190,
    “y”: 260,
    “wires”: []
    },
    {
    “id”: “24495c060d2a8756”,
    “type”: “ui-text”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “group”: “5673b51cc6b259c0”,
    “order”: 2,
    “width”: “3”,
    “height”: 1,
    “name”: “Letztes Update”,
    “label”: “Letztes Update”,
    “format”: “{{msg.payload.timestamp | date:’DD.MM.YYYY HH:mm:ss’}}”,
    “layout”: “row-spread”,
    “style”: false,
    “font”: “”,
    “fontSize”: “”,
    “color”: “#000000”,
    “wrapText”: false,
    “className”: “”,
    “value”: “payload.timestamp_formatted”,
    “valueType”: “msg”,
    “x”: 1200,
    “y”: 300,
    “wires”: []
    },
    {
    “id”: “2bb5b7ad91154a04”,
    “type”: “comment”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Rauchmelder Keller Werkstatt – ntfy, Pushover und Mail Meldungen und Statusbericht”,
    “info”: “”,
    “x”: 360,
    “y”: 60,
    “wires”: []
    },
    {
    “id”: “06fda76032ceaefb”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Rauchmelder Daten aufbereiten”,
    “func”: “// ZigBee2MQTT Daten parsen\nlet data = msg.payload;\nlet deviceInfo = {};\n\n// Prüfen ob Daten vorhanden sind\nif (typeof data === ‘object’) {\n // Batteriestatus (in % oder Spannung)\n deviceInfo.battery = data.battery || data.battery_percentage || 0;\n deviceInfo.battery_low = data.battery_low || false;\n \n // Test-Modus (falls vorhanden)\n deviceInfo.test_mode = data.test_mode || false;\n \n // Rauchmelder Status (Alarm, Normal, etc.)\n deviceInfo.smoke = data.smoke || false;\n deviceInfo.smoke_detected = data.smoke_detected || false;\n \n // Zusätzliche Status-Felder für HS1SA-E\n deviceInfo.trouble = data.trouble || false;\n deviceInfo.tamper = data.tamper || false;\n \n // Link Quality\n deviceInfo.linkquality = data.linkquality || 0;\n \n // Last seen aus ZigBee2MQTT\n deviceInfo.last_seen = data.last_seen || new Date().toISOString();\n \n // Batterie OK Status berechnen\n deviceInfo.battery_ok = true;\n if (deviceInfo.battery_low === true || \n (typeof deviceInfo.battery === ‘number’ && deviceInfo.battery < 20)) {\n deviceInfo.battery_ok = false;\n }\n \n // Timestamp für die aktuelle Abfrage\n deviceInfo.timestamp = new Date().toISOString();\n deviceInfo.timestamp_formatted = new Date().toLocaleString(‘de-DE’);\n \n deviceInfo.friendly_name = \”KellerWerkstatt\”;\n \n msg.payload = deviceInfo;\n \n return msg;\n}\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: 0,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 650,
    “y”: 140,
    “wires”: [
    [
    “3deb8b862d1238e4”,
    “1fc2a6b8f60b088d”,
    “f8b1b27956f09b3e”,
    “147944ef03bfde4c”,
    “4ab2f6e25855efce”,
    “9d6eebcf795ee86e”,
    “ac1607f8f0db6b5d”,
    “24495c060d2a8756”,
    “7a1904f924795633”,
    “g7h8i9j0k1l2m3n4”
    ]
    ]
    },
    {
    “id”: “296a847a7c85c981”,
    “type”: “pushover api”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “keys”: “13d7f9e6fd4a0fe1”,
    “title”: “Rauchmelder Keller Werkstatt”,
    “name”: “Rauchmelder Keller Werkstatt”,
    “x”: 570,
    “y”: 300,
    “wires”: []
    },
    {
    “id”: “3deb8b862d1238e4”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Statusbericht formatieren”,
    “func”: “// Statusbericht formatieren\nconst data = msg.payload;\nconst friendlyName = data.friendly_name || \”Rauchmelder Keller Werkstatt\”;\nconst timestamp = new Date().toLocaleString(‘de-DE’, {\n weekday: ‘long’,\n year: ‘numeric’,\n month: ‘2-digit’,\n day: ‘2-digit’,\n hour: ‘2-digit’,\n minute: ‘2-digit’,\n second: ‘2-digit’\n});\n\n// Batteriestatus\nlet batteryEmoji = \”🔋\”;\nlet batteryStatus = \”\”;\nif (data.battery <= 20) {\n batteryEmoji = \”⚠️🔴\”;\n batteryStatus = \”KRITISCH – SOFORT WECHSELN!\”;\n} else if (data.battery <= 50) {\n batteryEmoji = \”⚠️🟡\”;\n batteryStatus = \”Bald wechseln\”;\n} else if (data.battery <= 80) {\n batteryEmoji = \”🟢\”;\n batteryStatus = \”Gut\”;\n} else {\n batteryEmoji = \”💚\”;\n batteryStatus = \”Sehr gut\”;\n}\n\n// Geräte-Status\nlet deviceStatus = \”✅ OK\”;\nif (data.battery_low) deviceStatus = \”⚠️ Batterie schwach\”;\nif (data.trouble) deviceStatus = \”🔴 Störung\”;\nif (data.tamper) deviceStatus = \”🔧 Manipulation\”;\nif (data.smoke) deviceStatus = \”🚨 RAUCHALARM!\”;\n\n// Linkqualität (LQI: 0-255)\nlet linkQualityText = \”🔴 Schlecht\”;\nif (data.linkquality >= 200) linkQualityText = \”🟢 Sehr gut\”;\nelse if (data.linkquality >= 150) linkQualityText = \”🟢 Gut\”;\nelse if (data.linkquality >= 100) linkQualityText = \”🟡 Mittel\”;\nelse if (data.linkquality >= 50) linkQualityText = \”🟠 Schwach\”;\n\n// Last seen formatieren\nlet lastSeenStr = \”Unbekannt\”;\nif (data.last_seen) {\n try {\n lastSeenStr = new Date(data.last_seen).toLocaleString(‘de-DE’);\n } catch (e) {\n lastSeenStr = data.last_seen;\n }\n}\n\n// Statusbericht\nconst reportTitle = `Statusbericht – Rauchmelder`; // Ohne Emoji für Header\nconst reportMessage = \n `📋 ${reportTitle}\\n` +\n `Gerät: ${friendlyName}\\n` +\n `${batteryEmoji} Batterie: ${data.battery}% – ${batteryStatus}\\n` +\n `📶 Signal: ${linkQualityText} (${data.linkquality} LQI)\\n` +\n `🔄 Gerätestatus: ${deviceStatus}\\n` +\n `🕒 Letzter Kontakt: ${lastSeenStr}\\n` +\n `📊 Bericht erstellt: ${timestamp}\\n\\n` +\n `Letzte Werte:\\n` +\n `• Rauch gemeldet: ${data.smoke ? ‘Ja 🚨’ : ‘Nein ✅’}\\n` +\n `• Batterie schwach: ${data.battery_low ? ‘Ja ⚠️’ : ‘Nein ✅’}\\n` +\n `• Manipulation: ${data.tamper ? ‘Ja 🔧’ : ‘Nein ✅’}\\n` +\n `• Störung: ${data.trouble ? ‘Ja 🔴’ : ‘Nein ✅’}\\n` +\n `• Test-Modus: ${data.test_mode ? ‘Ja 🔧’ : ‘Nein ✅’}\\n\\n`;\n\n// Für Pushover\nmsg.pushover = {\n // url: \”https://ntfy.sh/secret-theme-Rauchmelder\”,\n // method: \”POST\”,\n headers: {\n \”Title\”: reportTitle.replace(/[^a-zA-Z0-9\\s-]/g, ”), // Entfernt alle Sonderzeichen\n \”Tags\”: data.battery <= 20 ? \”warning,rotating_light,battery\” : \”battery,rotating_light\”,\n \”Priority\”: data.battery <= 20 ? \”high\” : \”default\”\n },\n payload: reportMessage\n};\n\n// Für ntfy – Header müssen ASCII-konform sein (keine Umlaute oder Emojis)\nmsg.ntfy = {\n url: \”https://ntfy.sh/secret-theme-Rauchmelder\”,\n method: \”POST\”,\n headers: {\n \”Title\”: reportTitle.replace(/[^a-zA-Z0-9\\s-]/g, ”), // Entfernt alle Sonderzeichen\n \”Tags\”: data.battery <= 20 ? \”warning,rotating_light,battery\” : \”battery,rotating_light\”,\n \”Priority\”: data.battery <= 20 ? \”high\” : \”default\”\n },\n payload: reportMessage\n};\n\n// Kennzeichnung für Debug\nmsg.is_battery_report = true;\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: 0,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 230,
    “y”: 200,
    “wires”: [
    [
    “acbb6ccfa4615f05”,
    “0f916dab840c7276”
    ]
    ]
    },
    {
    “id”: “acbb6ccfa4615f05”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “ntfy vorbereiten”,
    “func”: “// ntfy Request vorbereiten\nconst ntfyConfig = msg.ntfy;\n\n// HTTP Request für ntfy erstellen\nmsg.url = ntfyConfig.url;\nmsg.method = ntfyConfig.method;\nmsg.headers = ntfyConfig.headers;\nmsg.payload = ntfyConfig.payload;\n\n// Debug-Ausgabe (optional, kann später entfernt werden)\nnode.warn(\”ntfy Header: \” + JSON.stringify(msg.headers));\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: 0,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 500,
    “y”: 200,
    “wires”: [
    [
    “2cf42ba58b153108”
    ]
    ]
    },
    {
    “id”: “2cf42ba58b153108”,
    “type”: “http request”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Keller Werkstatt ntfy senden”,
    “method”: “use”,
    “ret”: “txt”,
    “paytoqs”: “ignore”,
    “url”: “”,
    “tls”: “”,
    “persist”: false,
    “proxy”: “”,
    “insecureHTTPParser”: false,
    “authType”: “”,
    “senderr”: false,
    “headers”: [],
    “x”: 560,
    “y”: 260,
    “wires”: [
    []
    ]
    },
    {
    “id”: “0f916dab840c7276”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Pushover vorbereiten”,
    “func”: “// Pushover Request vorbereiten\nconst pushoverConfig = msg.pushover;\n\n// HTTP Request für Pushover erstellen\nmsg.headers = pushoverConfig.headers;\nmsg.payload = pushoverConfig.payload;\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: 0,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 300,
    “y”: 300,
    “wires”: [
    [
    “296a847a7c85c981”
    ]
    ]
    },
    {
    “id”: “fd8f8ffdf77a106c”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Rauchmelder Daten aufbereiten”,
    “func”: “// ZigBee2MQTT Daten parsen\nlet data = msg.payload;\nlet deviceInfo = {};\nlet alarmStatus = false;\n\n// Prüfen ob Daten vorhanden sind\nif (typeof data === ‘object’) {\n // Batteriestatus (in % oder Spannung)\n deviceInfo.battery = data.battery || data.battery_percentage || 0;\n deviceInfo.battery_low = data.battery_low || false;\n \n // Test-Modus (falls vorhanden)\n deviceInfo.test_mode = data.test || false; // Wichtig: heißt ‘test’ im HS1SA-E\n \n // Rauchmelder Status (Alarm!)\n deviceInfo.smoke = data.smoke || false;\n alarmStatus = deviceInfo.smoke; // Für Alarmerkennung\n \n // Link Quality\n deviceInfo.linkquality = data.linkquality || 0;\n \n // Last seen aus ZigBee2MQTT\n deviceInfo.last_seen = data.last_seen || new Date().toISOString();\n \n // Batterie OK Status berechnen\n deviceInfo.battery_ok = true;\n if (deviceInfo.battery_low === true || \n (typeof deviceInfo.battery === ‘number’ && deviceInfo.battery < 20)) {\n deviceInfo.battery_ok = false;\n }\n \n // Timestamp für die aktuelle Abfrage\n deviceInfo.timestamp = new Date().toISOString();\n deviceInfo.timestamp_formatted = new Date().toLocaleString(‘de-DE’);\n deviceInfo.friendly_name = \”Keller Werkstatt\”;\n \n // Alarm-Status für nachfolgende Nodes\n msg.payload = deviceInfo;\n msg.alarm_active = alarmStatus; // Explizites Flag für Alarm\n msg.alarm_triggered = alarmStatus; // Alternative Bezeichnung\n \n return msg;\n}\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: 0,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 570,
    “y”: 400,
    “wires”: [
    [
    “0469b6708a6631f2”
    ]
    ]
    },
    {
    “id”: “0469b6708a6631f2”,
    “type”: “switch”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Alarm-Status prüfen”,
    “property”: “alarm_active”,
    “propertyType”: “msg”,
    “rules”: [
    {
    “t”: “true”
    }
    ],
    “checkall”: “true”,
    “repair”: false,
    “outputs”: 1,
    “x”: 240,
    “y”: 460,
    “wires”: [
    [
    “e45e871a10a710b2”,
    “685b6cb6ac3300e8”
    ]
    ]
    },
    {
    “id”: “e45e871a10a710b2”,
    “type”: “trigger”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “30s Blinksteuerung”,
    “op1”: “start”,
    “op2”: “stop”,
    “op1type”: “str”,
    “op2type”: “str”,
    “duration”: “30”,
    “extend”: false,
    “overrideDelay”: false,
    “units”: “s”,
    “reset”: “”,
    “bytopic”: “all”,
    “topic”: “topic”,
    “outputs”: 2,
    “x”: 910,
    “y”: 460,
    “wires”: [
    [
    “95efe3c5faf4ab5b”
    ],
    [
    “b69dfaa826fb2d91”
    ]
    ]
    },
    {
    “id”: “95efe3c5faf4ab5b”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Blink-Modus vorbereiten”,
    “func”: “// Blink-Modus für die Kerzenbirne\n// Sekundentakt: 1s an, 1s aus\n\n// Aktuellen Zustand der Birne abfragen und speichern\n// Dazu müssten Sie den aktuellen Status kennen – hier als Platzhalter\nflow.set(\”light_previous_state\”, {\n state: \”ON\”, // Hier müsste der echte Status ermittelt werden\n brightness: 254\n});\n\n// Blinken aktivieren\nflow.set(\”blink_active\”, true);\nflow.set(\”blink_counter\”, 0);\nflow.set(\”blink_state\”, \”OFF\”); // Startet mit OFF, dann wechselt zu ON\n\n// Ersten Befehl senden (Licht an in Rot)\nmsg.topic = \”zigbee2mqtt/KerzenbirneBuero/set\”;\nmsg.payload = {\n \”state\”: \”ON\”,\n \”brightness\”: 254,\n \”color\”: { \”hex\”: \”#FF0000\” }\n};\n\nnode.warn(\”Alarm-Blinken gestartet\”);\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: 0,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 930,
    “y”: 400,
    “wires”: [
    [
    “6f243fcb4da873d4”
    ]
    ]
    },
    {
    “id”: “6f243fcb4da873d4”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Toggle-Blinken”,
    “func”: “// Diese Funktion erzeugt den Sekundentakt\n// Sie wird von einem Inject-Node im Sekundentakt aufgerufen\n\n// Aktuellen Zustand aus Flow-Kontext holen\nlet currentState = flow.get(\”blink_state\”) || \”OFF\”;\nlet counter = flow.get(\”blink_counter\”) || 0;\nlet blinkActive = flow.get(\”blink_active\”) || false;\n\n// Prüfen ob Blinken aktiv ist (vom Trigger gesetzt)\nif (!blinkActive) {\n // Wenn nicht aktiv, nichts tun\n return null;\n}\n\n// Zustand umschalten\nlet newState = (currentState === \”ON\”) ? \”OFF\” : \”ON\”;\nflow.set(\”blink_state\”, newState);\n\n// Zähler erhöhen\ncounter++;\nflow.set(\”blink_counter\”, counter);\n\n// Nach 30 Sekunden automatisch beenden (30 Toggles = 30 Sekunden bei 1s Intervall)\nif (counter >= 30) {\n // Blinken beenden\n flow.set(\”blink_counter\”, 0);\n flow.set(\”blink_state\”, \”OFF\”);\n flow.set(\”blink_active\”, false);\n\n // Vorherigen Zustand wiederherstellen\n let previousState = flow.get(\”light_previous_state\”) || { state: \”OFF\” };\n\n msg.topic = \”zigbee2mqtt/KerzenbirneBuero/set\”;\n msg.payload = {\n \”state\”: previousState.state || \”OFF\”\n };\n\n node.warn(\”Alarm-Blinken nach 30s beendet\”);\n return msg;\n}\n\n// Befehl für die Kerzenbirne\nmsg.topic = \”zigbee2mqtt/KerzenbirneBuero/set\”;\nif (newState === \”ON\”) {\n msg.payload = {\n \”state\”: \”ON\”,\n \”brightness\”: 254,\n \”color\”: { \”hex\”: \”#FF0000\” } // Rot\n };\n} else {\n msg.payload = {\n \”state\”: \”OFF\”\n };\n}\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: 0,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 1200,
    “y”: 440,
    “wires”: [
    [
    “191ef45fc6c07a97”
    ]
    ]
    },
    {
    “id”: “b69dfaa826fb2d91”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Blinken beenden”,
    “func”: “// Blinken stoppen\nflow.set(\”blink_active\”, false);\nflow.set(\”blink_counter\”, 0);\nflow.set(\”blink_state\”, \”OFF\”);\n\n// Vorherigen Zustand wiederherstellen\nlet previousState = flow.get(\”light_previous_state\”) || { state: \”OFF\” };\n\nmsg.topic = \”zigbee2mqtt/KerzenbirneBuero/set\”;\nmsg.payload = {\n \”state\”: previousState.state || \”OFF\”\n};\n\nnode.warn(\”Alarm-Blinken gestoppt\”);\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: 0,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 1210,
    “y”: 400,
    “wires”: [
    [
    “191ef45fc6c07a97”
    ]
    ]
    },
    {
    “id”: “685b6cb6ac3300e8”,
    “type”: “function”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Alarm-Pushover”,
    “func”: “// Alarm-Benachrichtigung für Pushover\nconst data = msg.payload;\nconst timestamp = new Date().toLocaleString(‘de-DE’, {\n weekday: ‘long’,\n year: ‘numeric’,\n month: ‘2-digit’,\n day: ‘2-digit’,\n hour: ‘2-digit’,\n minute: ‘2-digit’,\n second: ‘2-digit’\n});\n\n// Gerätename ermitteln (mit Fallback)\nconst deviceName = data.friendly_name || ‘Rauchmelder Werkstatt’;\n\n// Alarm-Nachricht formatieren\nlet alarmMessage =\n `🚨 RAUCHALARM! 🚨\n\nGerät: ${deviceName}\nZeit: ${timestamp}\n\n📍 Bereich: ${deviceName}\n⚠️ Es wurde RAUCH detektiert!\n\nBitte überprüfen Sie den Bereich SOFORT!`;\n\n// Pushover-spezifische Felder\nmsg.title = `🚨 RAUCHALARM – ${deviceName}`;\nmsg.payload = alarmMessage;\nmsg.priority = 1; // High Priority\nmsg.sound = \”persistent\”; // Alarmton\nmsg.timestamp = Math.floor(Date.now() / 1000);\n\nreturn msg;”,
    “outputs”: 1,
    “timeout”: 0,
    “noerr”: 0,
    “initialize”: “”,
    “finalize”: “”,
    “libs”: [],
    “x”: 460,
    “y”: 500,
    “wires”: [
    [
    “6247c2a58286fc73”
    ]
    ]
    },
    {
    “id”: “efd4d502334fbc36”,
    “type”: “inject”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Sekundentakt für Blinken”,
    “props”: [
    {
    “p”: “payload”
    }
    ],
    “repeat”: “1”,
    “crontab”: “”,
    “once”: false,
    “onceDelay”: 0.1,
    “topic”: “”,
    “payload”: “”,
    “payloadType”: “date”,
    “x”: 930,
    “y”: 500,
    “wires”: [
    [
    “6f243fcb4da873d4”
    ]
    ]
    },
    {
    “id”: “6247c2a58286fc73”,
    “type”: “pushover api”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “keys”: “13d7f9e6fd4a0fe1”,
    “title”: “Rauchmelder Werkstatt Alarm”,
    “name”: “Pushover Werkstatt”,
    “x”: 670,
    “y”: 500,
    “wires”: []
    },
    {
    “id”: “ab3764d33b337c6f”,
    “type”: “comment”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “=== ALARM-BENACHRICHTIGUNG & BLINKEN ===”,
    “info”: “”,
    “x”: 280,
    “y”: 360,
    “wires”: []
    },
    {
    “id”: “0f3d4c079b703181”,
    “type”: “zigbee2mqtt-in”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “”,
    “server”: “1bfcccb11dd30d19”,
    “friendly_name”: “KellerWerkstatt (HS1SA-E)”,
    “device_id”: “0xf84477fffe123ed0”,
    “state”: “0”,
    “outputAtStartup”: true,
    “filterChanges”: true,
    “enableMultiple”: false,
    “x”: 190,
    “y”: 400,
    “wires”: [
    [
    “fd8f8ffdf77a106c”,
    “d4e9451a20607f2f”
    ]
    ]
    },
    {
    “id”: “cb8dcc5798bb85a4”,
    “type”: “inject”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Manueller Test”,
    “props”: [
    {
    “p”: “payload”
    },
    {
    “p”: “topic”,
    “vt”: “str”
    }
    ],
    “repeat”: “”,
    “crontab”: “”,
    “once”: false,
    “onceDelay”: 0.1,
    “topic”: “”,
    “payload”: “”,
    “payloadType”: “date”,
    “x”: 260,
    “y”: 500,
    “wires”: [
    [
    “685b6cb6ac3300e8”,
    “e45e871a10a710b2”
    ]
    ]
    },
    {
    “id”: “551b4d13bc9b505f”,
    “type”: “inject”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “”,
    “props”: [
    {
    “p”: “payload”
    },
    {
    “p”: “topic”,
    “vt”: “str”
    }
    ],
    “repeat”: “”,
    “crontab”: “”,
    “once”: false,
    “onceDelay”: 0.1,
    “topic”: “”,
    “payload”: “”,
    “payloadType”: “date”,
    “x”: 1070,
    “y”: 360,
    “wires”: [
    [
    “b69dfaa826fb2d91”
    ]
    ]
    },
    {
    “id”: “191ef45fc6c07a97”,
    “type”: “zigbee2mqtt-out”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Kerzenbirne”,
    “server”: “1bfcccb11dd30d19”,
    “friendly_name”: “KerzenbirneBuero (HG07834B/HG09155B/HG08131B)”,
    “device_id”: “0x8cf681fffeaf1b37”,
    “command”: “state”,
    “commandType”: “z2m_cmd”,
    “payload”: “payload”,
    “payloadType”: “msg”,
    “optionsValue”: “”,
    “optionsType”: “nothing”,
    “x”: 1210,
    “y”: 500,
    “wires”: []
    },
    {
    “id”: “d4e9451a20607f2f”,
    “type”: “debug”,
    “z”: “a906f7d4665bf705”,
    “g”: “f19c1232b5818c2a”,
    “name”: “Werkstatt”,
    “active”: true,
    “tosidebar”: true,
    “console”: false,
    “tostatus”: true,
    “complete”: “payload”,
    “targetType”: “msg”,
    “statusVal”: “payload”,
    “statusType”: “auto”,
    “x”: 600,
    “y”: 360,
    “wires”: []
    },
    {
    “id”: “1bfcccb11dd30d19”,
    “type”: “zigbee2mqtt-server”,
    “name”: “Sonoff ZigBee Raspi”,
    “host”: “Raspi”,
    “mqtt_port”: “1883”,
    “mqtt_username”: “raspi”,
    “mqtt_password”: “password”,
    “mqtt_qos”: “2”,
    “tls”: “”,
    “usetls”: false,
    “base_topic”: “zigbee2mqtt”
    },
    {
    “id”: “5673b51cc6b259c0”,
    “type”: “ui-group”,
    “name”: “Keller Werkstatt”,
    “page”: “5515adb8b2455e2c”,
    “width”: “3”,
    “height”: 1,
    “order”: 2,
    “showTitle”: true,
    “className”: “”,
    “visible”: “true”,
    “disabled”: “false”,
    “groupType”: “default”
    },
    {
    “id”: “13d7f9e6fd4a0fe1”,
    “type”: “pushover-keys”,
    “name”: “Rauchmelder Berichte, Warnungen”
    },
    {
    “id”: “5515adb8b2455e2c”,
    “type”: “ui-page”,
    “name”: “Rauchmelder”,
    “ui”: “2e2c9c04099535bf”,
    “path”: “/page3”,
    “icon”: “smoke”,
    “layout”: “grid”,
    “theme”: “12f619e2761c4ce7”,
    “breakpoints”: [
    {
    “name”: “Default”,
    “px”: “0”,
    “cols”: “3”
    },
    {
    “name”: “Tablet”,
    “px”: “576”,
    “cols”: “6”
    },
    {
    “name”: “Small Desktop”,
    “px”: “768”,
    “cols”: “9”
    },
    {
    “name”: “Desktop”,
    “px”: “1024”,
    “cols”: “12”
    }
    ],
    “order”: 1,
    “className”: “”,
    “visible”: “true”,
    “disabled”: “false”
    },
    {
    “id”: “2e2c9c04099535bf”,
    “type”: “ui-base”,
    “name”: “Dashboard @flowuse”,
    “path”: “/dashboard”,
    “appIcon”: “”,
    “includeClientData”: true,
    “acceptsClientConfig”: [
    “ui-notification”,
    “ui-control”
    ],
    “showPathInSidebar”: false,
    “headerContent”: “dashboard”,
    “navigationStyle”: “default”,
    “titleBarStyle”: “default”,
    “showReconnectNotification”: true,
    “notificationDisplayTime”: 1,
    “showDisconnectNotification”: true,
    “allowInstall”: false
    },
    {
    “id”: “12f619e2761c4ce7”,
    “type”: “ui-theme”,
    “name”: “Standardthema”,
    “colors”: {
    “surface”: “#5734fc”,
    “primary”: “#e3b450”,
    “bgPage”: “#eeeeee”,
    “groupBg”: “#ffffff”,
    “groupOutline”: “#cccccc”
    },
    “sizes”: {
    “density”: “default”,
    “pagePadding”: “12px”,
    “groupGap”: “12px”,
    “groupBorderRadius”: “4px”,
    “widgetGap”: “12px”
    }
    },
    {
    “id”: “c812ee4757f928dd”,
    “type”: “global-config”,
    “env”: [],
    “modules”: {
    “node-red-contrib-zigbee2mqtt”: “2.7.5”,
    “node-red-node-email-variable”: “1.1.7”,
    “@flowfuse/node-red-dashboard”: “1.30.2”,
    “node-red-contrib-pushover”: “0.2.0”
    }
    }
    ]