Heizungssteuerung mit Homematic Thermostat und Shelly Switch

Hallo Zusammen,
ich habe es nach langem hin und her endlich geschafft, in RED NODE einen Flow zur Steuerung meiner FUßbodenheizung aufzubauen. Der Flow funktioniert bzw. wird - basierend auf den ausgelesenen Werten (current_temperature und temperature) - ausgeführt. Aber nur 1x beim Deployen.
Ändert sich danach eine der beiden oben genannten Werte, passiert leider nichts.
Wer kann mir da weiterhelfen?

Grüße
ETHVH

Du hast nur ein Bild eingefügt. Damit wissen wir nicht was deine Funktion macht, was in payload mitgegeben wird oder auf was du in state_changed abfrägst.

Ok- ich dachte es reicht, um zu zeigen, dass der Flow an sich funktioniert. Mein Problem ist das Node Events.state, das offensichtlich keine Änderung der Temperatur mitbekommt und dann den Flow ausführt.

Soll ich den kompletten JSON Code posten- oder was hilft?

Wie mostie schon schrieb fehlen da einige Infos. Aber ich denke es liegt daran das du bei state_changed den Status (auto, manuell, aus) des Thermostat anfragst, du solltest besser das Argument current_temperature abfragen.

mach das. Kann man dann importieren. Zum Beginn auch mal einen Screenshot wie du die “state_change” Node gefüllt hast. Und was du in deiner Funktion drin hast.

Zur Analyse würde ich zusätzlich eine Debug node direkt hinter die status-change hängen und die ganzen Inforationen ausgeben lassen, nicht nur msg.payload.

{
“id”: “f1g2h3i4j5k6l7m8”,
“type”: “function”,
“z”: “a07947fbd326497e”,
“name”: “IST vs SOLL anzeigen”,
“func”: “// Zugriff auf die neuen Werte\\nlet newState = msg.data?.new_state;\\n\\nif (!newState) {\\n    node.warn("Kein new_state gefunden!");\\n    return null;\\n}\\n\\nlet ist = newState.attributes.current_temperature;\\nlet soll = newState.attributes.temperature;\\n\\n// Status im Node anzeigen\\nnode.status({fill:"blue", shape:"dot", text:`IST: ${ist}°C | SOLL: ${soll}°C`});\\n\\nif (ist < soll) {\\n    return {payload: "unterSoll"};\\n} else {\\n    return {payload: "ueberSoll"};\\n}\\n// Werte im Payload zurückgeben\\nmsg.payload = { ist, soll };\\nreturn msg;”,
“outputs”: 1,
“timeout”: “”,
“noerr”: 0,
“initialize”: “”,
“finalize”: “”,
“libs”: [ ],
“x”: 460,
“y”: 180,
“wires”: \[
\[
“9z8y7x6w5v4u3t2s”,
“546acc724d0288e0”
\]
\]
},
{
“id”: “9z8y7x6w5v4u3t2s”,
“type”: “debug”,
“z”: “a07947fbd326497e”,
“name”: “Debug IST + SOLL”,
“active”: true,
“tosidebar”: true,
“console”: false,
“tostatus”: false,
“complete”: “payload”,
“targetType”: “msg”,
“statusVal”: “”,
“statusType”: “auto”,
“x”: 610,
“y”: 280,
“wires”: [ ]
},
{
“id”: “27966741702c68d1”,
“type”: “server-state-changed”,
“z”: “a07947fbd326497e”,
“name”: “”,
“server”: “5a437bb6.e336e4”,
“version”: 6,
“outputs”: 1,
“exposeAsEntityConfig”: “”,
“entities”: {
“entity”: \[
“climate.thermostat_og_kueche”
\],
“substring”: [ ],
“regex”: [ ]
},
“outputInitially”: true,
“stateType”: “num”,
“ifState”: “”,
“ifStateType”: “str”,
“ifStateOperator”: “is”,
“outputOnlyOnStateChange”: true,
“for”: “0”,
“forType”: “num”,
“forUnits”: “minutes”,
“ignorePrevStateNull”: false,
“ignorePrevStateUnknown”: false,
“ignorePrevStateUnavailable”: false,
“ignoreCurrentStateUnknown”: false,
“ignoreCurrentStateUnavailable”: false,
“outputProperties”: \[
{
“property”: “payload”,
“propertyType”: “msg”,
“value”: “”,
“valueType”: “entityState”
},
{
“property”: “data”,
“propertyType”: “msg”,
“value”: “”,
“valueType”: “eventData”
},
{
“property”: “topic”,
“propertyType”: “msg”,
“value”: “”,
“valueType”: “triggerId”
}
\],
“x”: 250,
“y”: 100,
“wires”: \[
\[
“f1g2h3i4j5k6l7m8”,
“bba6ac218d2d1470”,
“1060445e0938c527”,
“4d75933f8c92162b”
\]
\]
},
{
“id”: “546acc724d0288e0”,
“type”: “switch”,
“z”: “a07947fbd326497e”,
“name”: “”,
“property”: “payload”,
“propertyType”: “msg”,
“rules”: \[
{
“t”: “eq”,
“v”: “ueberSoll”,
“vt”: “str”
},
{
“t”: “eq”,
“v”: “unterSoll”,
“vt”: “str”
}
\],
“checkall”: “true”,
“repair”: false,
“outputs”: 2,
“x”: 730,
“y”: 180,
“wires”: \[
\[
“f4608f61d69b49e7”
\],
\[
“2f3609f5db28b178”
\]
\]
},
{
“id”: “f4608f61d69b49e7”,
“type”: “api-call-service”,
“z”: “a07947fbd326497e”,
“name”: “VENTIL ZU/AUS”,
“server”: “5a437bb6.e336e4”,
“version”: 7,
“debugenabled”: false,
“action”: “switch.turn_off”,
“floorId”: [ ],
“areaId”: [ ],
“deviceId”: [ ],
“entityId”: \[
“switch.shellypro4pm_2cbcbbb1d658_switch_1”
\],
“labelId”: [ ],
“data”: “”,
“dataType”: “jsonata”,
“mergeContext”: “”,
“mustacheAltTags”: false,
“outputProperties”: [ ],
“queue”: “none”,
“blockInputOverrides”: true,
“domain”: “switch”,
“service”: “turn_off”,
“x”: 970,
“y”: 160,
“wires”: \[
[ ]
\]
},
{
“id”: “2f3609f5db28b178”,
“type”: “api-call-service”,
“z”: “a07947fbd326497e”,
“name”: “VENTIL AUF/AN”,
“server”: “5a437bb6.e336e4”,
“version”: 7,
“debugenabled”: false,
“action”: “switch.turn_on”,
“floorId”: [ ],
“areaId”: [ ],
“deviceId”: [ ],
“entityId”: \[
“switch.shellypro4pm_2cbcbbb1d658_switch_1”
\],
“labelId”: [ ],
“data”: “”,
“dataType”: “jsonata”,
“mergeContext”: “”,
“mustacheAltTags”: false,
“outputProperties”: [ ],
“queue”: “none”,
“blockInputOverrides”: true,
“domain”: “switch”,
“service”: “turn_on”,
“x”: 960,
“y”: 220,
“wires”: \[
[ ]
\]
},
{
“id”: “bba6ac218d2d1470”,
“type”: “debug”,
“z”: “a07947fbd326497e”,
“name”: “debug 5”,
“active”: true,
“tosidebar”: true,
“console”: false,
“tostatus”: false,
“complete”: “false”,
“statusVal”: “”,
“statusType”: “auto”,
“x”: 580,
“y”: 340,
“wires”: [ ]
},
{
“id”: “1060445e0938c527”,
“type”: “debug”,
“z”: “a07947fbd326497e”,
“name”: “debug 6”,
“active”: true,
“tosidebar”: true,
“console”: false,
“tostatus”: false,
“complete”: “data”,
“targetType”: “msg”,
“statusVal”: “”,
“statusType”: “auto”,
“x”: 580,
“y”: 400,
“wires”: [ ]
},
{
“id”: “4d75933f8c92162b”,
“type”: “debug”,
“z”: “a07947fbd326497e”,
“name”: “debug 7”,
“active”: true,
“tosidebar”: true,
“console”: false,
“tostatus”: false,
“complete”: “topic”,
“targetType”: “msg”,
“statusVal”: “”,
“statusType”: “auto”,
“x”: 600,
“y”: 460,
“wires”: [ ]
},
{
“id”: “5a437bb6.e336e4”,
“type”: “server”,
“name”: “Home Assistant”,
“addon”: true,
“rejectUnauthorizedCerts”: true,
“ha_boolean”: “”,
“connectionDelay”: false,
“cacheJson”: true,
“heartbeat”: false,
“heartbeatInterval”: “”,
“areaSelector”: “friendlyName”,
“deviceSelector”: “friendlyName”,
“entitySelector”: “friendlyName”,
“statusSeparator”: “am:”,
“statusYear”: “hidden”,
“statusMonth”: “short”,
“statusDay”: “numeric”,
“statusHourCycle”: “h23”,
“statusTimeFormat”: “h:m:s”,
“enableGlobalContextStore”: true
}

:crayon:by HarryP: Code-/Logzeilen formatiert (bitte immer in </> einbinden)
s.a.: (Neues Update & Features - Hier in der Community 🫶)

Dein Code lässt sich nicht importieren. Bitte Code-Tags verwenden.

Prüfe ob in Homeassistant überhaupt ein Event “state_change” ausgelöst wird. Entwicklungswerkzeuge - Events. Wenn da nichts ausgelöst wird kann node-red auch nicht reagieren. Dann hast du schlichtwegs die falsche Entität als Auslöser


Dein Code lässt sich nicht importieren. Bitte Code-Tags verwenden.”Dein Code lässt sich nicht importieren. Bitte Code-Tags verwenden.” - Wie mache ich das beim Export?

tippe oder füge den Code hier ein

climate-Device sendet nur Updates wenn du von Manuell auf Auto oder Aus schaltest. Temperaturen haben eigene Sensoren. Du willst aber sicher mit über/unter Soll die Temperaturen abfragen.

Ich habe die Umschaltmöglickeit nicht :frowning:

Schau mal ob du “hinter” dem Plus was hast. Ansonsten testweise mit dem Gravis Zeichen (Apostroph nach vorne gekippt) " ``` " 3 mal vor und nach dem Codeblock.

Wenn das nicht geht kann ggf. ein Mod oder Admin die Frage beantworten.

[
    {
        "id": "f1g2h3i4j5k6l7m8",
        "type": "function",
        "z": "a07947fbd326497e",
        "name": "IST vs SOLL anzeigen",
        "func": "// Zugriff auf die neuen Werte\nlet newState = msg.data?.new_state;\n\nif (!newState) {\n    node.warn(\"Kein new_state gefunden!\");\n    return null;\n}\n\nlet ist = newState.attributes.current_temperature;\nlet soll = newState.attributes.temperature;\n\n// Status im Node anzeigen\nnode.status({fill:\"blue\", shape:\"dot\", text:`IST: ${ist}°C | SOLL: ${soll}°C`});\n\nif (ist < soll) {\n    return {payload: \"unterSoll\"};\n} else {\n    return {payload: \"ueberSoll\"};\n}\n// Werte im Payload zurückgeben\nmsg.payload = { ist, soll };\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 480,
        "y": 180,
        "wires": [
            [
                "9z8y7x6w5v4u3t2s",
                "546acc724d0288e0"
            ]
        ]
    },
    {
        "id": "9z8y7x6w5v4u3t2s",
        "type": "debug",
        "z": "a07947fbd326497e",
        "name": "Debug IST + SOLL",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 710,
        "y": 280,
        "wires": []
    },
    {
        "id": "27966741702c68d1",
        "type": "server-state-changed",
        "z": "a07947fbd326497e",
        "name": "",
        "server": "5a437bb6.e336e4",
        "version": 6,
        "outputs": 1,
        "exposeAsEntityConfig": "",
        "entities": {
            "entity": [
                "climate.thermostat_og_kueche"
            ],
            "substring": [],
            "regex": []
        },
        "outputInitially": true,
        "stateType": "str",
        "ifState": "",
        "ifStateType": "str",
        "ifStateOperator": "is",
        "outputOnlyOnStateChange": true,
        "for": "0",
        "forType": "num",
        "forUnits": "minutes",
        "ignorePrevStateNull": false,
        "ignorePrevStateUnknown": false,
        "ignorePrevStateUnavailable": false,
        "ignoreCurrentStateUnknown": false,
        "ignoreCurrentStateUnavailable": false,
        "outputProperties": [
            {
                "property": "payload",
                "propertyType": "msg",
                "value": "",
                "valueType": "entityState"
            },
            {
                "property": "data",
                "propertyType": "msg",
                "value": "",
                "valueType": "eventData"
            },
            {
                "property": "topic",
                "propertyType": "msg",
                "value": "",
                "valueType": "triggerId"
            }
        ],
        "x": 270,
        "y": 100,
        "wires": [
            [
                "f1g2h3i4j5k6l7m8",
                "bba6ac218d2d1470"
            ]
        ]
    },
    {
        "id": "546acc724d0288e0",
        "type": "switch",
        "z": "a07947fbd326497e",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "ueberSoll",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "unterSoll",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 750,
        "y": 180,
        "wires": [
            [
                "f4608f61d69b49e7"
            ],
            [
                "2f3609f5db28b178"
            ]
        ]
    },
    {
        "id": "f4608f61d69b49e7",
        "type": "api-call-service",
        "z": "a07947fbd326497e",
        "name": "VENTIL ZU/AUS",
        "server": "5a437bb6.e336e4",
        "version": 7,
        "debugenabled": false,
        "action": "switch.turn_off",
        "floorId": [],
        "areaId": [],
        "deviceId": [],
        "entityId": [
            "switch.shellypro4pm_2cbcbbb1d658_switch_1"
        ],
        "labelId": [],
        "data": "",
        "dataType": "jsonata",
        "mergeContext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "blockInputOverrides": true,
        "domain": "switch",
        "service": "turn_off",
        "x": 990,
        "y": 160,
        "wires": [
            []
        ]
    },
    {
        "id": "2f3609f5db28b178",
        "type": "api-call-service",
        "z": "a07947fbd326497e",
        "name": "VENTIL AUF/AN",
        "server": "5a437bb6.e336e4",
        "version": 7,
        "debugenabled": false,
        "action": "switch.turn_on",
        "floorId": [],
        "areaId": [],
        "deviceId": [],
        "entityId": [
            "switch.shellypro4pm_2cbcbbb1d658_switch_1"
        ],
        "labelId": [],
        "data": "",
        "dataType": "jsonata",
        "mergeContext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "blockInputOverrides": true,
        "domain": "switch",
        "service": "turn_on",
        "x": 980,
        "y": 220,
        "wires": [
            []
        ]
    },
    {
        "id": "bba6ac218d2d1470",
        "type": "debug",
        "z": "a07947fbd326497e",
        "name": "debug 5",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 600,
        "y": 340,
        "wires": []
    },
    {
        "id": "5a437bb6.e336e4",
        "type": "server",
        "name": "Home Assistant",
        "addon": true,
        "rejectUnauthorizedCerts": true,
        "ha_boolean": "",
        "connectionDelay": false,
        "cacheJson": true,
        "heartbeat": false,
        "heartbeatInterval": "",
        "areaSelector": "friendlyName",
        "deviceSelector": "friendlyName",
        "entitySelector": "friendlyName",
        "statusSeparator": "am:",
        "statusYear": "hidden",
        "statusMonth": "short",
        "statusDay": "numeric",
        "statusHourCycle": "h23",
        "statusTimeFormat": "h:m:s",
        "enableGlobalContextStore": true
    }
]

Stimmt - und es gibt einen Sensor, der heißt “sensor.thermostat_OG_kueche temperatur”, aber der liefert nur IST-Temperatur und keine SOLL.

:crayon:by HarryP: Zusammenführung Doppelpost (bei Änderungen oder hinzufügen von Inhalten bitte die „Bearbeitungsfunktion“ anstatt „Antworten“ zu nutzen)

Dann leg dir am besten einen Template Sensor an. Du schreibst im Titel von Homematic, da geh ich davon aus, dass du die Solltemperatur als Attribut im climate-Device hast. Musst halt die Attribute prüfen.


Ich habe es anscheinend tatsächlich hinbekommen. Evtl. etwas kompliziert - aber es scheint zu funktionieren. DANKE!! für Eure Hilfe. Ich habe eine Sensor-Template für die SOLL Temperatur erstellt und dieses dann mit einem current-state node zusätzlich abgefragt. Das events:state node liefert mir die IST-Temperatur in payload1 - das current:state node die SOLL-Temperatur in payload2.

Die werden verglichen und über den switch node wird dann das Ventil geöffnet oder geschlossen.

DANKE!!! @mostie @rstuck

In deiner Logik reagierst du nur auf die Änderung der Ist-Temperatur. Wenn du die Soll-Temperatur in HA änderst kommt die Prüfung erst wieder wenn sich die Ist-Temperatur ändert. Ich denke du musst die Soll auch als Eventlistener reinhängen.

Stimmt - danke für den Hinweis. Ich habe jetzt noch einen Eventlistener für die SOLL-Temperatur eingehängt und über Kreuz verknüpft. Sollte jetzt passen :slight_smile: .

Nein, tut es nicht. Die Linien von “IST Sensor Küche OG” zu “IST anzeigen”, und die Linie “SOLL Sensor Küche OG” zu “SOLL anzeigen” muss weg. Damit duplizierst du das Event, bei oberem (IST Sensor) Zweig kommt es einmal mit und einmal ohne aktuellem SOLL Wert an. Das siehst du an der Funktion “Soll anzeigen”, der Wert ist 17, in der Funktion “IST vs Soll Entscheindung” siehst du aber den Wert “SOLL 18,5”.

Die IST/SOLL anzeigen Funktion brauchst du eigentlich nicht. Bei “current status node” wird der Wert sowieso angezeigt.

Wenn du Werte anzeigen willst kannst du das auch mit Node display-property erledigen ohne dass du dafür eine function brauchst.

Ich würde es so lösen …

[
    {
        "id": "1e2da5215dcb76db",
        "type": "server-state-changed",
        "z": "cb4c2d91f85165e6",
        "name": "eventhm",
        "server": "b99a7cfd90266689",
        "version": 6,
        "outputs": 1,
        "exposeAsEntityConfig": "",
        "entities": {
            "entity": [
                "sensor.hmwohnzimmer_temperatur",
                "sensor.hmwohnzimmer_desired_temperature"
            ],
            "substring": [],
            "regex": []
        },
        "outputInitially": false,
        "stateType": "str",
        "ifState": "",
        "ifStateType": "str",
        "ifStateOperator": "is",
        "outputOnlyOnStateChange": true,
        "for": "0",
        "forType": "num",
        "forUnits": "minutes",
        "ignorePrevStateNull": false,
        "ignorePrevStateUnknown": false,
        "ignorePrevStateUnavailable": false,
        "ignoreCurrentStateUnknown": false,
        "ignoreCurrentStateUnavailable": false,
        "outputProperties": [],
        "x": 80,
        "y": 1300,
        "wires": [
            [
                "de48c23869222e93"
            ]
        ]
    },
    {
        "id": "de48c23869222e93",
        "type": "api-current-state",
        "z": "cb4c2d91f85165e6",
        "name": "soll",
        "server": "b99a7cfd90266689",
        "version": 3,
        "outputs": 1,
        "halt_if": "",
        "halt_if_type": "str",
        "halt_if_compare": "is",
        "entity_id": "sensor.hmwohnzimmer_desired_temperature",
        "state_type": "str",
        "blockInputOverrides": true,
        "outputProperties": [
            {
                "property": "soll",
                "propertyType": "msg",
                "value": "",
                "valueType": "entityState"
            }
        ],
        "for": "0",
        "forType": "num",
        "forUnits": "minutes",
        "override_topic": false,
        "state_location": "payload",
        "override_payload": "msg",
        "entity_location": "data",
        "override_data": "msg",
        "x": 270,
        "y": 1300,
        "wires": [
            [
                "c025941325502c1e"
            ]
        ]
    },
    {
        "id": "ead0a3d9dc61f98c",
        "type": "switch",
        "z": "cb4c2d91f85165e6",
        "name": "",
        "property": "soll",
        "propertyType": "msg",
        "rules": [
            {
                "t": "lt",
                "v": "ist",
                "vt": "msg"
            },
            {
                "t": "gt",
                "v": "ist",
                "vt": "msg"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 610,
        "y": 1300,
        "wires": [
            [
                "2edae7b5770c34c1"
            ],
            [
                "f2fac9e868356a17"
            ]
        ]
    },
    {
        "id": "c025941325502c1e",
        "type": "api-current-state",
        "z": "cb4c2d91f85165e6",
        "name": "ist",
        "server": "b99a7cfd90266689",
        "version": 3,
        "outputs": 1,
        "halt_if": "",
        "halt_if_type": "str",
        "halt_if_compare": "is",
        "entity_id": "sensor.hmwohnzimmer_temperatur",
        "state_type": "str",
        "blockInputOverrides": true,
        "outputProperties": [
            {
                "property": "ist",
                "propertyType": "msg",
                "value": "",
                "valueType": "entityState"
            }
        ],
        "for": "0",
        "forType": "num",
        "forUnits": "minutes",
        "override_topic": false,
        "state_location": "payload",
        "override_payload": "msg",
        "entity_location": "data",
        "override_data": "msg",
        "x": 430,
        "y": 1300,
        "wires": [
            [
                "ead0a3d9dc61f98c",
                "8a54269aec66e712"
            ]
        ]
    },
    {
        "id": "2edae7b5770c34c1",
        "type": "debug",
        "z": "cb4c2d91f85165e6",
        "name": "debug 26",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 760,
        "y": 1260,
        "wires": []
    },
    {
        "id": "f2fac9e868356a17",
        "type": "debug",
        "z": "cb4c2d91f85165e6",
        "name": "debug 27",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 760,
        "y": 1340,
        "wires": []
    },
    {
        "id": "8a54269aec66e712",
        "type": "display property",
        "z": "cb4c2d91f85165e6",
        "name": "",
        "property": "msg.ist",
        "showDate": true,
        "showTime": true,
        "x": 720,
        "y": 1500,
        "wires": [
            []
        ]
    },
    {
        "id": "b99a7cfd90266689",
        "type": "server",
        "name": "Home Assistant",
        "version": 5,
        "addon": false,
        "rejectUnauthorizedCerts": true,
        "ha_boolean": "y|yes|true|on|home|open",
        "connectionDelay": true,
        "cacheJson": true,
        "heartbeat": true,
        "heartbeatInterval": "30",
        "areaSelector": "friendlyName",
        "deviceSelector": "friendlyName",
        "entitySelector": "friendlyName",
        "statusSeparator": ": ",
        "statusYear": "numeric",
        "statusMonth": "2-digit",
        "statusDay": "numeric",
        "statusHourCycle": "h23",
        "statusTimeFormat": "h:m",
        "enableGlobalContextStore": false
    },
    {
        "id": "1f342d03a73c76ea",
        "type": "global-config",
        "env": [],
        "modules": {
            "node-red-contrib-home-assistant-websocket": "0.77.2",
            "node-red-contrib-display-property": "1.0.0"
        }
    }
]

Guten Morgen @mostie ,

vielen Dank noch mal für den Hinweis. Ich habe dein Beispiel umgesetzt :+1:- viel einfacher und funktioniert. Bin noch in der Lernphase :wink:.