Virtuelles HiH-Thermostat z.Bsp für Fußbodenheizung

Hallo Gemeinde,

wie der ein oder andere schon gelesen hat, halte ich mich mit Kritik nicht zurück, ABER statt nur Text liefere ich auch gerne mal Quelltext… :wink:

Was soll das hier bringen?
Ich und sicher eine Menge anderer User hier hat eine Heizung mit Heizkreisverteiler, wie z.Bsp. eine Fußbodenheizung. Ich persönlich habe eine sog. Hypokaustenheizung, das tut aber nicht viel zur Sache. Heizkreisverteiler werden in den meisten Fällen mit Stellmotoren betrieben die nur 2 Zustände kennen (Ein/Aus). Der Betrieb eines Heizkreisverteilers mit Heizkörperthermostaten ist meiner Meinung nach aus verschiedensten Gründen nicht praktikabel bzw. sinnvoll.
Das darf jeder halten, wie er möchte und bedarf keiner Diskussion.
Gerade für Umsteiger wie mich ist das sicher interessant, da andere Systeme die folgende Funktion bereits nativ on Bord haben und die Hardware für die Heizungssteuerung ggf. bereits vorhanden ist.

Ich habe div. Heizkreise, jeder dieser Heizkreise wird über einen Bimetallstellmotor (NC, also stromlos geschlossen) gesteuert. Je 2 dieser Stellmotoren sind an einen Fibaro-Double-Switch angeschlossen und werden so geöffnet bzw. geschlossen. Weiterhin habe ich je 4 Temperatursensoren an Fibaro Universalsensoren wovon sich je einer in jedem Raum befindet. Die Raumtemperatur könnte aber von anderen Geräten stammen, je nach eurer Infrastruktur.
Der folgende Flow erstellt ein virtuelles Thermostat, welches dann in Heizplänen nutzbar ist.
Der Vorteil, dieses Vorgehens ist, dass man jede Menge HGs spart und bei Bedarf die in homee wirklich gut gemachten Heizpläne mit allen Möglichkeiten nutzen kann. Man kann sich natürlich streiten, ob bei einer trägen Niedertemperaturheizung z.Bsp. eine Fenster-auf-Erkennung sinnvoll ist, aber das soll jeder selbst entscheiden. Eine Absenkung der Temperatur im Urlaubsfall, oder eine evtl. nötige Anpassung der Raumtemperatur von anderen Hausbewohnern ist über die Heizpläne schon deutlich komfortabler.

Hier der Flow zum Thema:
Die notwendigen Anpassungen für euren virtuellen homee, die Ist-Temperatur und die Schaltaktionen müsst ihr natürlich noch vornehmen.

[
    {
        "id": "bedc62a1.657ae",
        "type": "tab",
        "label": "Thermostat",
        "disabled": false,
        "info": ""
    },
    {
        "id": "ce1ab397.9af06",
        "type": "homeeDevice",
        "z": "bedc62a1.657ae",
        "virtual-homee": "",
        "name": "Thermostat",
        "nodeId": "1000",
        "showNodeId": false,
        "profile": "3003",
        "icon": "default",
        "attributes": [
            {
                "state": 1,
                "instance": 0,
                "minimum": 0,
                "maximum": 28,
                "current_value": 0,
                "target_value": 0,
                "last_value": 0,
                "data": "",
                "unit": "°C",
                "step_value": 0.5,
                "editable": 1,
                "last_changed": 1602956037,
                "changed_by": 1,
                "changed_by_id": 0,
                "based_on": 1,
                "options": [],
                "id": 1001,
                "type": 6,
                "node_id": 1000
            },
            {
                "state": 1,
                "instance": 1,
                "minimum": -50,
                "maximum": 125,
                "current_value": 0,
                "target_value": 0,
                "last_value": 0,
                "data": "",
                "unit": "°C",
                "step_value": 0.5,
                "editable": 0,
                "last_changed": 1603010569,
                "changed_by": 1,
                "changed_by_id": 0,
                "based_on": 1,
                "options": [],
                "id": 1002,
                "type": 5,
                "node_id": 1000
            }
        ],
        "statusTemplate": "",
        "x": 190,
        "y": 400,
        "wires": [
            [
                "7cf0a56f.b038a4"
            ]
        ]
    },
    {
        "id": "c595a0ef.b36378",
        "type": "inject",
        "z": "bedc62a1.657ae",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "GET:nodes",
        "payloadType": "str",
        "x": 80,
        "y": 120,
        "wires": [
            [
                "4ac28ec6.0119d"
            ]
        ]
    },
    {
        "id": "f18d6382.75edf",
        "type": "function",
        "z": "bedc62a1.657ae",
        "name": "Isttemp",
        "func": "var attribute = msg.payload.attribute;\nif(attribute && attribute.type === 5 && attribute.instance === 2 && attribute.node_id === 12)\n{\n    return {payload: attribute.current_value}\n}\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 520,
        "y": 120,
        "wires": [
            [
                "89d6ae60.a4968",
                "5c8006a3.ca9a78"
            ]
        ]
    },
    {
        "id": "7cf0a56f.b038a4",
        "type": "switch",
        "z": "bedc62a1.657ae",
        "name": "Solltemp",
        "property": "payload.attributeId",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "1001",
                "vt": "num"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 360,
        "y": 400,
        "wires": [
            [
                "7deabaf.f58b8c4"
            ]
        ]
    },
    {
        "id": "da2960ff.567e1",
        "type": "function",
        "z": "bedc62a1.657ae",
        "name": "Soll Ist Vergleich",
        "func": "var Solltemp = flow.get(\"soll\");\nvar Isttemp = flow.get(\"ist\");\nif (Isttemp > Solltemp) return {payload: false}\nif (Solltemp > Isttemp) return {payload: true}\n//return msg.payload;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 500,
        "y": 320,
        "wires": [
            [
                "bc488a6.5147ef8",
                "563ba82b.ccf3e"
            ]
        ]
    },
    {
        "id": "d11caabf.ac22c8",
        "type": "debug",
        "z": "bedc62a1.657ae",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 990,
        "y": 220,
        "wires": []
    },
    {
        "id": "89d6ae60.a4968",
        "type": "template",
        "z": "bedc62a1.657ae",
        "name": "",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": " {\"attribute\":{\"id\":1002,\"value\":{{payload}}}}",
        "output": "json",
        "x": 120,
        "y": 200,
        "wires": [
            [
                "ce1ab397.9af06"
            ]
        ]
    },
    {
        "id": "4ac28ec6.0119d",
        "type": "homeeApi",
        "z": "bedc62a1.657ae",
        "homee": "",
        "name": "homeeApi",
        "messageTypeFilter": [],
        "nodeFilter": "",
        "attributeFilter": "",
        "x": 280,
        "y": 120,
        "wires": [
            [
                "f18d6382.75edf"
            ]
        ]
    },
    {
        "id": "38997567.ec3362",
        "type": "debug",
        "z": "bedc62a1.657ae",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 990,
        "y": 260,
        "wires": []
    },
    {
        "id": "7deabaf.f58b8c4",
        "type": "function",
        "z": "bedc62a1.657ae",
        "name": "Solltemp",
        "func": "var soll = msg.payload.targetValue;\nmsg.payload = soll;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 520,
        "y": 400,
        "wires": [
            [
                "77703450.e3b9b4"
            ]
        ]
    },
    {
        "id": "bc488a6.5147ef8",
        "type": "debug",
        "z": "bedc62a1.657ae",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 730,
        "y": 320,
        "wires": []
    },
    {
        "id": "5c8006a3.ca9a78",
        "type": "change",
        "z": "bedc62a1.657ae",
        "name": "",
        "rules": [
            {
                "t": "move",
                "p": "payload",
                "pt": "msg",
                "to": "ist",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 220,
        "y": 300,
        "wires": [
            [
                "da2960ff.567e1"
            ]
        ]
    },
    {
        "id": "77703450.e3b9b4",
        "type": "change",
        "z": "bedc62a1.657ae",
        "name": "",
        "rules": [
            {
                "t": "move",
                "p": "payload",
                "pt": "msg",
                "to": "soll",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 220,
        "y": 340,
        "wires": [
            [
                "da2960ff.567e1"
            ]
        ]
    },
    {
        "id": "563ba82b.ccf3e",
        "type": "switch",
        "z": "bedc62a1.657ae",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "true"
            },
            {
                "t": "false"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 610,
        "y": 260,
        "wires": [
            [
                "142ee79.3d09618"
            ],
            [
                "54ee69c9.d39bd8"
            ]
        ]
    },
    {
        "id": "142ee79.3d09618",
        "type": "function",
        "z": "bedc62a1.657ae",
        "name": "Heizung ein",
        "func": "return {payload: \"PUT:/nodes/54/attributes/418?target_value=1\"}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 790,
        "y": 220,
        "wires": [
            [
                "d11caabf.ac22c8",
                "4ac28ec6.0119d"
            ]
        ]
    },
    {
        "id": "54ee69c9.d39bd8",
        "type": "function",
        "z": "bedc62a1.657ae",
        "name": "Heizung aus",
        "func": "return {payload: \"PUT:/nodes/54/attributes/418?target_value=0\"}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 790,
        "y": 260,
        "wires": [
            [
                "38997567.ec3362",
                "4ac28ec6.0119d"
            ]
        ]
    }
]

Einmal mehr vielen Dank an @Micha, bei dem ich wieder kräftig abgeguckt habe.
Vielleicht kann man das ganze deutlich eleganter gestalten? Für dahingehende Tipps hätte ich natürlich ein besonders weit geöffnetes Ohr.

Grüße H.

4 Like

Ich habe mir das mal angeschaut und würde das anders gestalten.
Schreibe dir das mal um und dann schaust mal ob es dir passt. :wink:

1 Like

Das dacht ich mir schon… :smiley:

Ich meine es aber nur gut :relieved:

Das weiß ich, und bin Dir überaus DANKBAR, nur so kann man was lernen.
Ich bin kein Softwareentwickler und mit JS hatte ich noch nie was am Hut, also sind die Skills quasi null. :wink:

DANKE…

Edit: Node Red hab ich auch vor knapp 2 Wochen zum ersten Mal gesehen das geht schon noch alles SEHR zäh von der Hand.

Habe es mal ein wenig angepasst, damit es aufgeräumter ist.
Viele Wege führen ja bekanntlich nach Rom und dein Weg funktioniert natürlich auch und ist deshalb auch nicht falsch.

[
    {
        "id": "ce1ab397.9af06",
        "type": "homeeDevice",
        "z": "bedc62a1.657ae",
        "virtual-homee": "",
        "name": "Thermostat",
        "nodeId": "1000",
        "profile": "3003",
        "icon": "default",
        "attributes": "[{\"state\":1,\"instance\":0,\"minimum\":0,\"maximum\":28,\"current_value\":0,\"target_value\":0,\"last_value\":0,\"data\":\"\",\"unit\":\"°C\",\"step_value\":0.5,\"editable\":1,\"last_changed\":1602956037,\"changed_by\":1,\"changed_by_id\":0,\"based_on\":1,\"options\":[],\"id\":1001,\"type\":6,\"node_id\":1000},{\"state\":1,\"instance\":1,\"minimum\":-50,\"maximum\":125,\"current_value\":0,\"target_value\":0,\"last_value\":0,\"data\":\"\",\"unit\":\"°C\",\"step_value\":0.5,\"editable\":0,\"last_changed\":1603010569,\"changed_by\":1,\"changed_by_id\":0,\"based_on\":1,\"options\":[],\"id\":1002,\"type\":5,\"node_id\":1000}]",
        "x": 390,
        "y": 300,
        "wires": [
            [
                "da2960ff.567e1"
            ]
        ]
    },
    {
        "id": "f18d6382.75edf",
        "type": "function",
        "z": "bedc62a1.657ae",
        "name": "Isttemp",
        "func": "var attribute = msg.payload.attribute;\nif(attribute && attribute.id === 93)\n{flow.set(\"ist\",attribute.current_value);\nreturn{payload:{\"attribute\":{\"id\":1002,\"value\":attribute.current_value}}}\n}\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 240,
        "y": 320,
        "wires": [
            [
                "ce1ab397.9af06",
                "da2960ff.567e1"
            ]
        ]
    },
    {
        "id": "da2960ff.567e1",
        "type": "function",
        "z": "bedc62a1.657ae",
        "name": "Soll Ist Vergleich",
        "func": "if(msg.payload.attributeId=== 1001){flow.set(\"soll\",msg.payload.targetValue)}\nvar Solltemp = flow.get(\"soll\");\nvar Isttemp = flow.get(\"ist\");\nvar State = flow.get(\"state\")||false;\nif (Isttemp > Solltemp && State === true){\n    flow.set(\"state\", false);\n    return {payload: \"PUT:/nodes/54/attributes/418?target_value=0\"}}\nif (Solltemp > Isttemp && State === false){\n    flow.set(\"state\",true);\n    return {payload: \"PUT:/nodes/54/attributes/418?target_value=1\"}}\nreturn",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 560,
        "y": 320,
        "wires": [
            [
                "1c4170ef.1bac9f"
            ]
        ]
    },
    {
        "id": "4ac28ec6.0119d",
        "type": "homeeApi",
        "z": "bedc62a1.657ae",
        "homee": "f5eaadbd.7b3e4",
        "x": 380,
        "y": 240,
        "wires": [
            [
                "ba0596af.c7ee08"
            ]
        ]
    },
    {
        "id": "ba0596af.c7ee08",
        "type": "link out",
        "z": "bedc62a1.657ae",
        "name": "homee out",
        "links": [
            "a0558612.ddb348"
        ],
        "x": 525,
        "y": 240,
        "wires": []
    },
    {
        "id": "fdfcdbca.7d83c8",
        "type": "link in",
        "z": "bedc62a1.657ae",
        "name": "homee in",
        "links": [
            "1c4170ef.1bac9f"
        ],
        "x": 255,
        "y": 240,
        "wires": [
            [
                "4ac28ec6.0119d"
            ]
        ]
    },
    {
        "id": "a0558612.ddb348",
        "type": "link in",
        "z": "bedc62a1.657ae",
        "name": "",
        "links": [
            "ba0596af.c7ee08"
        ],
        "x": 135,
        "y": 320,
        "wires": [
            [
                "f18d6382.75edf"
            ]
        ]
    },
    {
        "id": "1c4170ef.1bac9f",
        "type": "link out",
        "z": "bedc62a1.657ae",
        "name": "",
        "links": [
            "fdfcdbca.7d83c8"
        ],
        "x": 695,
        "y": 320,
        "wires": []
    },
    {
        "id": "f5eaadbd.7b3e4",
        "type": "homee",
        "z": "",
        "name": "",
        "host": ""
    }
]
4 Like

Wie schon per PM gesagt, Du bist absolut unglaublich!
Und damit meine ich nicht nur Dein Know-How, sondern vor allem Dein Engagement - TOP!!! :+1:

3 Like

sieht interessant aus aber wie kann ein nur homee user das jetzt umsetzen???

Du brauchst „irgendwas“ auf dem Node Red oder besser gleich ioBroker läuft.
Das kann z.Bsp. ein PC/Server (Windows/Linux/Mac) oder auch ein NAS sein, da gibt es quasi unzählige Möglichkeiten.
Die gebräuchlichten sind sicher ein Raspberry Pi (ein Einplatienencomputer) oder ein NAS, da die entweder günstig im Verbrauch oder ohnehin immer an sind.
Die vielleicht einfachste Methode ist ioBroker als Dockercontainer auf einem evtl. vorhandenen Synology NAS zu installieren.
Das dauert keine 5 min. -> https://www.youtube.com/watch?v=s471CHl2KHg
Falls kein kompatibles NAS zur Verfügung steht, ist sicher ein Raspberry Pi eine günstige Variante. Die Installation ist u.a. hier Stück für Stück erklärt.
Wenn der ioBroker dann läuft, ist der Node Red Adapter mit 2 Klicks installiert.

Meld Dich, ich geb mir Mühe, Dir zu helfen…

1 Like

Wie hier zu lesen ist,

verfügst Du über ein Synology NAS, die kleinsten auf denen Docker läuft wären DS216+ und DS218+, vielleicht klappt’s ja… :slight_smile:

Docker und ioBroker läuft. was muss ich konfigurieren?

Das ging ja fix! :+1: :grinning:
Jetzt gehst Du zu Adapter, suchst Dir den Adapter namens „node-red“ klickst da auf die drei weißen Punkte im blauen Kreis und dann auf das „+“ unten links.
Das installiert den Node Red Adapter mit wirklich 2 Klicks… :wink:

In Node Red klickst Du auf die 3 Striche oben rechts und dann auf „Palette verwalten“.
Klick auf den Reiter „Installieren“, dort suchst Du nach „homee“ und klickst auf „installieren“.



Wenn das geklappt hat, hat @Micha ein 1a Tutorial für das Anlegen eines virtuellen homee auf Youtube veröffentlicht. Alle weiteren seiner Turorials helfen natürlich sehr, um sich in die Sache weiter zu vertiefen.

So, für heute sind das sicher genug Hausaufgaben… :rofl:

danke ja :slight_smile: das Viedeo kommt die Tage mal dran. Ich melde mich wieder