Flow Details
Zeigt die deutschen Feiertage an. Unterstützt Dashboard 2.0 im Node-Red. Hier kann man das Bundesland einstellen für das die Feiertage angezeigt werden sollen. Ansonsten werden nur bundeseinheitliche Feiertage angezeigt.
[
{
"id": "72175f931b3e29ac",
"type": "group",
"z": "d9d4383b2014cb99",
"name": "Feiertage",
"style": {
"stroke": "#6f2fa0",
"fill": "#dbcbe7",
"label": true
},
"nodes": [
"5127bf18830d4ad3",
"fb298cb6c8ec9590",
"8a2930e407402daf",
"13d51937bd72c388",
"fdf27e5ec4e49676",
"ef0f8c8001460cd1",
"c6e493c70e7beb4d",
"6770cec013307649",
"b92c198634443888",
"ceaf8e559ff49b55",
"399d5d84e767d0e3",
"44f26464b2a65cc7",
"826e9166dab33416"
],
"x": 14,
"y": 4339,
"w": 1152,
"h": 222
},
{
"id": "5127bf18830d4ad3",
"type": "function",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"name": "Definition Feiertage",
"func": "\nvar today = new Date();\nvar year = today.getYear();\n// year = \"2027\"\nif (year < 1900) {\n year += 1900\n};\n\nvar Feiertage = [\n {\n Name: \"Neujahr\",\n Datum: \"01.01.\" + year,\n Bundesland: \"all\",\n icon: 26001,\n },\n {\n Name: \"Heilige drei Könige\",\n Datum: \"06.01.\" + year,\n Bundesland:\"BY,BW,AUG,ST\",\n icon: 16528,\n },\n {\n Name: \"Rosenmontag\",\n Datum: \"00.00.\",\n Bundesland:\"all\",\n icon: 4163,\n },\n {\n Name: \"Karfreitag\",\n Datum: \"00.00.\",\n Bundesland:\"all\",\n icon: 1967,\n },\n {\n Name: \"Ostersonntag\",\n Datum: \"00.00.\",\n Bundesland: \"all\",\n icon: 19550,\n },\n {\n Name: \"Ostermontag\",\n Datum: \"00.00.\",\n Bundesland: \"all\",\n icon: 19550,\n },\n {\n Name: \"Himmelfahrt\",\n Datum: \"00.00.\",\n Bundesland: \"all\",\n icon: 1967,\n },\n {\n Name: \"Pfingstsonntag\",\n Datum: \"00.00.\",\n Bundesland: \"all\",\n icon: 41394,\n },\n {\n Name: \"Pfingstmontag\",\n Datum: \"00.00.\",\n Bundesland: \"all\",\n icon: 41394,\n },\n {\n Name: \"Fronleichnam\",\n Datum: \"00.00.\",\n Bundesland: \"BW,BY,AUG,HE,NW,RP,SL,SN,TH\",\n icon: 74987,\n },\n {\n Name: \"Augsburger Friedensfest\",\n Datum: \"08.08.\" + year,\n Bundesland:\"AUG\",\n icon: 41394,\n },\n {\n Name: \"Maria Himmelfahrt\",\n Datum: \"15.08.\" + year,\n Bundesland:\"BY,AUG,SL\",\n icon: 1967,\n },\n {\n Name: \"Tag der deutschen Einheit\",\n Datum: \"03.10.\" + year,\n Bundesland:\"all\",\n icon: 35315,\n },\n {\n Name: \"Reformationstag\",\n Datum: \"31.10.\" + year,\n Bundesland:\"BB,HB,HH,MV,NI,SN,ST,SH,TH\",\n icon: 1967,\n },\n {\n Name: \"Allerheiligen\",\n Datum: \"01.11.\" + year,\n Bundesland:\"BW,BY,AUG,NW,RP,SL\",\n icon: 1967,\n },\n {\n Name: \"Buß- und Bettag\",\n Datum: \"00.00.\",\n Bundesland:\"SN\",\n icon: 26170,\n },\n {\n Name: \"Heiligabend\",\n Datum: \"24.12.\" + year,\n Bundesland:\"all\",\n icon: 9526,\n },\n {\n Name: \"1. Weihnachstag\",\n Datum: \"25.12.\" + year,\n Bundesland:\"all\",\n icon: 1817,\n },\n {\n Name: \"2. Weihnachstag\",\n Datum: \"26.12.\" + year,\n Bundesland:\"all\",\n icon: 1817,\n },\n {\n Name: \"Silvester\",\n Datum: \"31.12.\" + year,\n Bundesland:\"all\",\n icon: 25144,\n },\n {\n Name: \"Tag der Arbeit\",\n Datum: \"01.05.\" + year,\n Bundesland: \"all\",\n icon: 49923,\n },\n {\n Name: \"Frauentag\",\n Datum: \"08.03.\" + year,\n Bundesland:\"BE,MV\",\n icon: 70204, \n },\n {\n Name: \"Weltkindertag\",\n Datum: \"20.09.\" + year,\n Bundesland:\"TH\",\n icon: 6870, \n },\n {\n Name: \"Gründonnerstag\",\n Datum: \"00.00.\" + year,\n Bundesland:\"BW\",\n icon: 110, \n },\n {\n Name: \"Testfeiertag\",\n Datum: \"08.06.\" + year,\n Bundesland:\"TE\",\n icon: 4163, \n }\n];\n\n\n//const ost = new Date(year,0,1);\n//ost.setDate(ost.getDate() + Number(ostern(year)));\n//var easter=ost;\nvar diff = Number(ostern(year));\nmsg.payload = Feiertage;\n// Rosenmontag\nFeiertage[2][\"Datum\"] = osterdate(diff-48);\n//Karfreitag\nFeiertage[3][\"Datum\"] = osterdate(diff-2);\n// Ostern\nFeiertage[4][\"Datum\"] = osterdate(diff);\n//Ostermontag\nFeiertage[5][\"Datum\"] = osterdate(diff+1);\n// Himmelfahrt\nFeiertage[6][\"Datum\"] = osterdate(diff+39);\n// Fronleichnam\nFeiertage[9][\"Datum\"] = osterdate(diff+60);\n// Pfingsten\nFeiertage[7][\"Datum\"] = osterdate(diff+49);\n// Pfingstmontag\nFeiertage[8][\"Datum\"] = osterdate(diff+50);\n// Gründonnerstag\nFeiertage[23][\"Datum\"] = osterdate(diff-3);\n\n// Buß-und Bettag Berechnung\nvar btag = new Date(year, 11, 25);\nvar offset = btag.getDay();\nbtag.setDate(btag.getDate() - (btag.getDay()+32) );\nFeiertage[15][\"Datum\"] = btag.toLocaleDateString('de-DE');\nFeiertage.sort((a, b) => String(a.Datum).split(\".\")[0].localeCompare(String(b.Datum).split(\".\")[0]));\nFeiertage.sort((a, b) => String(a.Datum).split(\".\")[1].localeCompare(String(b.Datum).split(\".\")[1]));\n\nmsg.payload = Feiertage;\nreturn msg;\n\n\nfunction ostern(j) {\n //Schaltjahresberechnung\n let sch = 0;\n if ((j % 4 == 0 && j % 100 != 0) || j % 400 == 0) {\n sch = 1;\n }\n else {\n sch = 0;\n }\n // Osterberechnung\n let dd =0;\n let ja = Math.trunc(j / 100);\n let jb = Math.trunc(j / 400);\n let a = j % 19;\n let u_B = j % 4;\n let C = j % 7;\n let ma = Math.trunc((8 * ja + 13) / 25)\n let m = ma - 2;\n let s = ja - jb - 2;\n let mm = (15 + s - m) % 30;\n let nn = (6 + s) % 7;\n let d = (mm + (19 * a)) % 30;\n if (d == 29) {\n dd = 28;\n }\n else if (d == 28 && a >= 11) {\n dd = 27;\n }\n else {\n dd = d;\n }\n \n let E = ((2 * u_B) + (4 * C) + (6 * dd) + nn) % 7;\n let z = (dd + E + 1);\n let ta = 80 + z + sch;\n var ost = ta - 1;\nreturn ost;\n}\n\nfunction osterdate(diff){\n const options = { \n day: \"2-digit\",\n month: \"2-digit\",\n year: \"numeric\",\n };\n var ost1 = new Date(year,0,1);\n ost1.setDate(ost1.getDate() + diff);\n return ost1.toLocaleDateString(\"de-DE\", {day: \"2-digit\",month: \"2-digit\",year: \"numeric\",});\n}\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 420,
"y": 4460,
"wires": [
[
"13d51937bd72c388",
"399d5d84e767d0e3"
]
]
},
{
"id": "fb298cb6c8ec9590",
"type": "debug",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"name": "debug 13",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1060,
"y": 4380,
"wires": []
},
{
"id": "8a2930e407402daf",
"type": "inject",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"name": "Jeden Tag",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "01 00 * * *",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 140,
"y": 4460,
"wires": [
[
"5127bf18830d4ad3"
]
]
},
{
"id": "13d51937bd72c388",
"type": "function",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"name": "Ist Feiertag?",
"func": "const Feiertage = msg.payload;\nconst Land = flow.get(\"Bundesland\",\"file\");\n// Annahme: birthdayStorage ist ein Objekt zum Verfolgen bereits angezeigter Geburtstage\n// birthdayStorage sollte initialisiert werden, wenn das Skript zum ersten Mal ausgeführt wird.\nconst FeiertageStorage = {};\n\nconst today = new Date();\nconst currentYear = today.getFullYear();\nvar msg1 = {\"payload\": \"\",}\nvar duration = 10;\n\n// Filtern Sie die Feiertage, um nur diejenigen anzuzeigen, die heute Geburtstag haben und noch nicht in birthdayStorage verzeichnet sind\nconst newFeiertag = Feiertage\n .filter( Tag=> {\n let day, month;\n if (Tag.Datum && Tag.Datum.length >= 5) {\n day = parseInt(Tag.Datum.substring(0, 2));\n month = parseInt(Tag.Datum.substring(3, 5));\n }\n return day === today.getDate() && month === today.getMonth() + 1 && !FeiertageStorage[Tag.Name];\n })\n .map(Tag => {\n return {\n Name: Tag.Name,\n Bundesland: Tag.Bundesland,\n icon: Tag.icon,\n };\n });\n\nlet bday = newFeiertag.length;\nif (bday == 0) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"Kein Feiertag heute.\" });\n\n msg.topic = \"Kein Feiertag\";\n msg.payload ={};\n \n return msg;\n}\n\n//Anzeigen der neuen Feiertage und Aktualisieren von FeiertageStorage\nconst FeiertagMessage = newFeiertag\n .map(Tag => {\n FeiertageStorage[Tag.Name] = true; // Feiertag als angezeigt markieren\n return Tag.Name;\n });\nconst FeiertagFuer = newFeiertag\n .map(Tag => {\n FeiertageStorage[Tag.Bundesland] = true; // Feiertag als angezeigt markieren\n return Tag.Bundesland;\n });\nconst FeiertagIcon = newFeiertag\n .map(Tag => {\n FeiertageStorage[Tag.icon] = true; // Feiertag als angezeigt markieren\n return Tag.icon;\n });\n\n\nif (FeiertagFuer.join().includes(Land) == true || FeiertagFuer.join().includes(\"all\")) {\n duration = calculateDuration(msg.payload, 90);\n msg.topic = `${FeiertagMessage}`;\n node.status({ fill: \"green\", shape: \"dot\", text: \"Es gibt einen Feiertag heute.\" + FeiertagMessage + \" \" + duration + \"sec\" + \" \"+ bday });\n\n msg.payload = {\n \"text\": msg.topic,\n \"icon\":`${FeiertagIcon}`,\n \"textCase\": 2,\n \"pushIcon\": 2,\n \"duration\": duration, \n }\nreturn msg;\n}\nelse {\n msg.topic = \"Kein Feiertag\";\n msg.payload ={};\n \nreturn msg;\n\n return msg; \n}\n\n\n\nfunction calculateDuration(msgPayload, scrollTextDelay = 90) {\n const durationSec = (msgPayload.length + 8) * scrollTextDelay / 250;\n return durationSec;\n}\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 710,
"y": 4460,
"wires": [
[
"fdf27e5ec4e49676",
"ef0f8c8001460cd1",
"6770cec013307649"
]
]
},
{
"id": "fdf27e5ec4e49676",
"type": "mqtt out",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"name": "",
"topic": "awtrix_test/custom/Feiertag",
"qos": "",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "858457535e7dc82b",
"x": 960,
"y": 4460,
"wires": []
},
{
"id": "ef0f8c8001460cd1",
"type": "ui-text",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"group": "f8d5e98fd03fa4d9",
"order": 1,
"width": 0,
"height": 0,
"name": "",
"label": "Heute ist:",
"format": "{{msg.payload}}",
"layout": "row-spread",
"style": false,
"font": "",
"fontSize": 16,
"color": "#717171",
"wrapText": false,
"className": "",
"value": "topic",
"valueType": "msg",
"x": 900,
"y": 4420,
"wires": []
},
{
"id": "c6e493c70e7beb4d",
"type": "ui-dropdown",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"group": "f8d5e98fd03fa4d9",
"name": "Bundesland",
"label": "Bundesland auswählen:",
"tooltip": "",
"order": 3,
"width": 0,
"height": 0,
"passthru": true,
"multiple": false,
"chips": false,
"clearable": false,
"options": [
{
"label": "Baden-Württemberg",
"value": "BW",
"type": "str"
},
{
"label": "Bayern",
"value": "BY",
"type": "str"
},
{
"label": "Berlin",
"value": "BE",
"type": "str"
},
{
"label": "Brandenburg",
"value": "BB",
"type": "str"
},
{
"label": "Bremen",
"value": "HB",
"type": "str"
},
{
"label": "Hamburg",
"value": "HH",
"type": "str"
},
{
"label": "Hessen",
"value": "HE",
"type": "str"
},
{
"label": "Mecklenburg-Vorpommern",
"value": "MV",
"type": "str"
},
{
"label": "Niedersachsen",
"value": "NI",
"type": "str"
},
{
"label": "Nordrhein-Westfalen",
"value": "NW",
"type": "str"
},
{
"label": "Rheinland-Pfalz",
"value": "RP",
"type": "str"
},
{
"label": "Saarland",
"value": "SL",
"type": "str"
},
{
"label": "Sachsen",
"value": "SN",
"type": "str"
},
{
"label": "Sachsen-Anhalt",
"value": "ST",
"type": "str"
},
{
"label": "Schleswig-Holstein",
"value": "SH",
"type": "str"
},
{
"label": "Thüringen",
"value": "TH",
"type": "str"
},
{
"label": "Augsburg",
"value": "AUG",
"type": "str"
},
{
"label": "Test",
"value": "TE",
"type": "str"
}
],
"payload": "",
"topic": "payload",
"topicType": "msg",
"className": "",
"typeIsComboBox": true,
"msgTrigger": "onChange",
"x": 290,
"y": 4380,
"wires": [
[
"b92c198634443888"
]
]
},
{
"id": "6770cec013307649",
"type": "debug",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"name": "debug 15",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 900,
"y": 4520,
"wires": []
},
{
"id": "b92c198634443888",
"type": "function",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"name": "Bundesland speichern",
"func": "flow.set(\"Bundesland\",msg.payload,\"file\");\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 500,
"y": 4380,
"wires": [
[
"5127bf18830d4ad3"
]
]
},
{
"id": "ceaf8e559ff49b55",
"type": "ui-table",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"group": "f8d5e98fd03fa4d9",
"name": "",
"label": "",
"order": 4,
"width": 0,
"height": 0,
"maxrows": 0,
"passthru": false,
"autocols": false,
"showSearch": false,
"deselect": false,
"selectionType": "none",
"columns": [
{
"title": "Feiertag",
"key": "Name",
"keyType": "key",
"type": "text",
"width": "",
"align": "start"
},
{
"title": "Datum",
"key": "Datum",
"keyType": "key",
"type": "text",
"width": "",
"align": "start"
}
],
"mobileBreakpoint": "",
"mobileBreakpointType": "none",
"action": "replace",
"className": "",
"x": 890,
"y": 4380,
"wires": [
[]
]
},
{
"id": "399d5d84e767d0e3",
"type": "function",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"name": "Feiertagstabelle",
"func": "const Feiertage = msg.payload;\nconst Land = flow.get(\"Bundesland\",\"file\");\n\nconst FTage = Feiertage.filter(({Bundesland}) => Bundesland.includes(Land) ); //.map(({Name}) => Name,({Datum}) => Datum,(({Bundesland}) => Bundesland));\nconst FTage1 = Feiertage.filter(({Bundesland}) => Bundesland.includes(\"all\") );\n\nconst Feiertag = FTage1.concat(FTage);\nFeiertag.sort((a, b) => String(a.Datum).split(\".\")[0].localeCompare(String(b.Datum).split(\".\")[0]));\nFeiertag.sort((a, b) => String(a.Datum).split(\".\")[1].localeCompare(String(b.Datum).split(\".\")[1]));\n\nmsg.payload = Feiertag\nreturn msg",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 720,
"y": 4380,
"wires": [
[
"ceaf8e559ff49b55",
"fb298cb6c8ec9590"
]
]
},
{
"id": "44f26464b2a65cc7",
"type": "inject",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"name": "Bundesland ",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "#:(file)::Bundesland",
"payloadType": "flow",
"x": 130,
"y": 4380,
"wires": [
[
"c6e493c70e7beb4d"
]
]
},
{
"id": "826e9166dab33416",
"type": "ui-template",
"z": "d9d4383b2014cb99",
"g": "72175f931b3e29ac",
"group": "f8d5e98fd03fa4d9",
"page": "",
"ui": "",
"name": "",
"order": 2,
"width": 0,
"height": 0,
"head": "",
"format": "<template>\n <Teleport v-if=\"mounted\" :to=\"target\">\n <div :class=\"[positionClass, 'collapse-control']\" @click=\"toggle\" style=\"cursor: pointer;\">\n <v-icon class=\"toggle-icon\" aria-hidden=\"false\" style=\"color: inherit; opacity: 0.8;\">\n {{icon}}\n </v-icon>\n </div>\n </Teleport>\n</template>\n\n<script>\n export default {\n data() { \n return {\n mounted: false,\n target: \"\",\n position: \"right\",\n opened: true\n }\n },\n computed: { \n positionClass: function () {\n return this.position == \"left\" ? \"v-card-item__prepend\" : \"v-card-item__append\"\n },\n icon: function() {\n return this.opened ? \"mdi-menu-up\" : \"mdi-menu-down\"\n },\n storageKey: function() {\n return `widget-state-${this.id}`\n }\n },\n mounted() { \n // On cible l'élément par l'ID du groupe passé par les props de Node-RED\n this.target = '#nrdb-ui-group-' + this.props.group + ' .v-card-item'\n \n // 1. Restauration de l'état sauvegardé\n const savedState = localStorage.getItem(this.storageKey)\n if (savedState !== null) {\n this.opened = savedState === 'true'\n }\n\n this.$nextTick(() => {\n const container = document.querySelector(`#nrdb-ui-group-${this.props.group}`)\n if (container) {\n this.updateState(container)\n }\n this.mounted = true\n \n // 2. Envoi de l'état initial à Node-RED\n this.send({ open: this.opened })\n })\n },\n methods: {\n toggle() {\n this.opened = !this.opened\n localStorage.setItem(this.storageKey, this.opened)\n \n const container = document.querySelector(`#nrdb-ui-group-${this.props.group}`)\n this.updateState(container)\n\n // 3. Envoi du nouvel état lors du clic\n this.send({ open: this.opened })\n },\n updateState(el) {\n if (!el) return\n if (!this.opened) {\n el.classList.add('is-collapsed')\n } else {\n el.classList.remove('is-collapsed')\n }\n }\n },\n\n // Cette fonction se déclenche juste avant que le widget ne soit supprimé de l'écran\nunmounted() {\n// On force l'arrêt du flux Node-RED quand on quitte la page\n// Mais on ne touche pas au localStorage pour que ça se rouvre au retour\nthis.send({ open: false });\n}\n}\n</script>\n\n<style>\n /* 1. Cache le conteneur du widget qui porte la classe saisie dans l'UI */\n /* Cela évite qu'un espace vide n'apparaisse dans le groupe */\n .hidden-template {\n display: none !important;\n }\n\n /* Masquage des éléments quand la classe 'is-collapsed' est présente */\n [id^=\"nrdb-ui-group-\"].is-collapsed .v-card-text,\n [id^=\"nrdb-ui-group-\"].is-collapsed .v-divider {\n display: none !important;\n }\n</style>",
"storeOutMessages": true,
"passthru": true,
"resendOnRefresh": true,
"templateScope": "local",
"className": "",
"x": 560,
"y": 4520,
"wires": [
[]
]
},
{
"id": "858457535e7dc82b",
"type": "mqtt-broker",
"name": "FHEM-Nachricht",
"broker": "raspberry-4.fritz.box",
"port": "1884",
"tls": "",
"clientid": "storage-3",
"autoConnect": true,
"usetls": false,
"protocolVersion": "4",
"keepalive": "60",
"cleansession": true,
"autoUnsubscribe": true,
"birthTopic": "LWT",
"birthQos": "0",
"birthRetain": "true",
"birthPayload": "online",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"closeMsg": {},
"willTopic": "LWT",
"willQos": "0",
"willRetain": "true",
"willPayload": "offline",
"willMsg": {},
"userProps": "",
"sessionExpiry": ""
},
{
"id": "f8d5e98fd03fa4d9",
"type": "ui-group",
"name": "Feiertage",
"page": "1e38b760668321ec",
"width": "4",
"height": 1,
"order": 10,
"showTitle": true,
"className": "",
"visible": "true",
"disabled": "false",
"groupType": "default"
},
{
"id": "1e38b760668321ec",
"type": "ui-page",
"name": "Awtrix 3.0",
"ui": "7013987c94f55176",
"path": "/awtrix",
"icon": "home",
"layout": "grid",
"theme": "75ddda7292ca61b7",
"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": 2,
"className": "",
"visible": "true",
"disabled": "false"
},
{
"id": "7013987c94f55176",
"type": "ui-base",
"name": "AWTRIX",
"path": "/dashboard",
"appIcon": "http://storage-3:1880/logo/awtrix.png",
"includeClientData": true,
"acceptsClientConfig": [
"ui-notification",
"ui-control"
],
"showPathInSidebar": false,
"headerContent": "none",
"navigationStyle": "default",
"titleBarStyle": "default",
"showReconnectNotification": true,
"notificationDisplayTime": 1,
"showDisconnectNotification": true,
"allowInstall": true
},
{
"id": "75ddda7292ca61b7",
"type": "ui-theme",
"name": "Standardthema",
"colors": {
"surface": "#517070",
"primary": "#0094ce",
"bgPage": "#8b8b8b",
"groupBg": "#ffffff",
"groupOutline": "#000000"
},
"sizes": {
"density": "compact",
"pagePadding": "12px",
"groupGap": "6px",
"groupBorderRadius": "0px",
"widgetGap": "6px"
}
},
{
"id": "0717e4e3b5f5fc06",
"type": "global-config",
"env": [],
"modules": {
"@flowfuse/node-red-dashboard": "1.30.2"
}
}
]
-- Flow first published on June 8, 2026, last updated on June 9, 2026 at 10:20.