flic / node-red-contrib-hal2

A set of nodes to help with basic home automation logic
2 stars 1 forks source link

Ingress vs Egress function #12

Closed alexsahka closed 2 years ago

alexsahka commented 2 years ago

Used Ingress function for while and it works great, here is an example for Z2M door/window sensor:

msg.payload = (msg.payload.contact == true) ? 'closed' : 'opened'; return msg.payload;

While started using the Egress function nothing came out of output no matter what I have tryed. image

msg.payload = (msg.payload.contact == true) ? '1' : '0'; return msg.payload;

Question if the Egress function works at all? I have tried an example with the Egress function and it is not working as well.

image

image

flic commented 2 years ago

This is the built-in example for an ingress function:

// msg & attribute objects are
// passed to function

return msg.payload;

...and this is the example for an egress function:

// msg & attribute objects are
// passed to function

return msg;

Spot the difference? ;)

I should add a line or two to the example code to better highlight the difference. The ingress is supposed to return a single value, "return msg.payload;" but the egress returns a complete msg object "return msg;". The reasoning behind this is that it might be necessary for the egress to manipulate other parts of the msg object, like msg.topic or msg.url or anything else, so the egress needs to return the whole object.

Looks like you only return msg.payload which is probably the reason it doesn't work for you.

alexsahka commented 2 years ago

Is this is correct for Egress? This returns nothing.

msg.payload = (msg.payload.contact == true) ? '1' : '0'; return msg;

Also tried Pass-through

return msg;

returns nothing.

flic commented 2 years ago

Seems to be working. Maybe a bit strange to user payload.contact as an input to the action? Try the example below: Skärmavbild 2022-03-19 kl  16 42 58

[
    {
        "id": "453f525291d30f5c",
        "type": "hal2Thing",
        "z": "d9b62b0.9ebbfd8",
        "eventHandler": "e228014191d14be6",
        "thingType": "3bbd5e2d12efd9a0",
        "name": "Test thing",
        "attributes": [],
        "topicFilter": "",
        "topicFilterType": "mqtt",
        "topicPrefix": "",
        "notes": "",
        "outputs": "1",
        "x": 420,
        "y": 3520,
        "wires": [
            [
                "3f29d3d9a955dcb6"
            ]
        ]
    },
    {
        "id": "3f29d3d9a955dcb6",
        "type": "debug",
        "z": "d9b62b0.9ebbfd8",
        "name": "Output",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 570,
        "y": 3520,
        "wires": []
    },
    {
        "id": "3e9c82d75accf248",
        "type": "inject",
        "z": "d9b62b0.9ebbfd8",
        "name": "contact = true",
        "props": [
            {
                "p": "payload.contact",
                "v": "true",
                "vt": "bool"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 230,
        "y": 3580,
        "wires": [
            [
                "017dad059d5fdf2d"
            ]
        ]
    },
    {
        "id": "017dad059d5fdf2d",
        "type": "hal2Action",
        "z": "d9b62b0.9ebbfd8",
        "eventHandler": "e228014191d14be6",
        "name": "Test action",
        "commandset": [
            {
                "category": "hal2Thing",
                "thing": "453f525291d30f5c",
                "item": "db49b125.6ae54",
                "value": "payload",
                "type": "msg"
            }
        ],
        "ratelimit": 0,
        "x": 430,
        "y": 3580,
        "wires": []
    },
    {
        "id": "12cba9878bba6772",
        "type": "inject",
        "z": "d9b62b0.9ebbfd8",
        "name": "contact = false",
        "props": [
            {
                "p": "payload.contact",
                "v": "false",
                "vt": "bool"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 240,
        "y": 3620,
        "wires": [
            [
                "017dad059d5fdf2d"
            ]
        ]
    },
    {
        "id": "e228014191d14be6",
        "type": "hal2EventHandler",
        "name": "Event handler",
        "maxlisteners": "50",
        "heartbeat": "60"
    },
    {
        "id": "3bbd5e2d12efd9a0",
        "type": "hal2ThingType",
        "name": "Test",
        "contextStore": "memory",
        "nodestatus": "",
        "items": [
            {
                "name": "Test egress",
                "id": "db49b125.6ae54",
                "topicFilterType": "str",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "command",
                "ingress": "748151a2.840f9",
                "egress": "293406ea.fc48da",
                "notes": "",
                "output": "1"
            }
        ],
        "attributes": [],
        "ingress": [
            {
                "name": "Pass-through",
                "id": "748151a2.840f9",
                "fn": "// msg & attribute objects are\n// passed to function\n\nreturn msg.payload;"
            },
            {
                "name": "Convert to Number",
                "id": "9243d3c4.f5753",
                "fn": "// msg & attribute objects are\n// passed to function\n\nmsg.payload = Number(msg.payload);\nreturn msg.payload;"
            },
            {
                "name": "Convert to Boolean",
                "id": "21bf578f.d98df8",
                "fn": "// msg & attribute objects are\n// passed to function\n\nmsg.payload = (msg.payload === 'true');\nreturn msg.payload;"
            }
        ],
        "egress": [
            {
                "name": "Pass-through",
                "id": "8fd76278.c7a82",
                "fn": "// msg & attribute objects are\n// passed to function\n\nreturn msg;"
            },
            {
                "name": "Test",
                "id": "293406ea.fc48da",
                "fn": "msg.payload = (msg.payload.contact == true) ? '1' : '0';\nreturn msg;"
            }
        ],
        "thingStatus": false,
        "thingCommand": true,
        "thingOutput": true,
        "hbCheck": false,
        "hbType": "lwt",
        "hbTTL": "",
        "hbFilterVal": "",
        "hbFilterType": "str",
        "filterFunction": "0",
        "outputs": "1"
    }
]
alexsahka commented 2 years ago

Thanks, your example works. But when I tried this: nothing returns to output, same time ingress work.

image image image

flic commented 2 years ago

Can you export and post an example?

flic commented 2 years ago

Okay, got it.

The input on the Thing node is for ingress only. To get anything out of the output (egress) side you need to use an Action or Group node. Take a look at my example, I send msg.payload.contact true/false to an Action node, not to the Thing input.

alexsahka commented 2 years ago

I was under the impression that what I got on Ingress I can output try Egress function same time.

What I want to achieve is:

Z2M sensor contact: False/True

Ingress function converts it to Opened/Closed (easy to read for humans)

Egress function converts it to 0/1 for database use.

flic commented 2 years ago

Well, I can see a couple of different ways to do that. I would probably not use an egress function, although that will work. Take a look at the example below. I would recommend example 2, that's what I would use.

Skärmavbild 2022-03-19 kl  17 43 24

[
    {
        "id": "2097573d5a616c9d",
        "type": "inject",
        "z": "e33735cb57f4c372",
        "name": "Door true",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "{\"battery\":100,\"contact\":true,\"linkquality\":68,\"voltage\":3.04}",
        "payloadType": "json",
        "x": 240,
        "y": 120,
        "wires": [
            [
                "ca1d645f1bcf7440"
            ]
        ]
    },
    {
        "id": "ca1d645f1bcf7440",
        "type": "mqtt out",
        "z": "e33735cb57f4c372",
        "name": "",
        "topic": "zigbee2mqtt/tttttttttt",
        "qos": "1",
        "retain": "false",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "5aeb1c10233e4cc2",
        "x": 520,
        "y": 140,
        "wires": []
    },
    {
        "id": "ca4226481ef8bce7",
        "type": "inject",
        "z": "e33735cb57f4c372",
        "name": "Door false",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "{\"battery\":100,\"contact\":false,\"linkquality\":68,\"voltage\":3.04}",
        "payloadType": "json",
        "x": 240,
        "y": 160,
        "wires": [
            [
                "ca1d645f1bcf7440"
            ]
        ]
    },
    {
        "id": "e6efe10ab218e082",
        "type": "hal2Thing",
        "z": "e33735cb57f4c372",
        "eventHandler": "488bfca26161ef73",
        "thingType": "1067281e08cac1b6",
        "name": "Z2M test",
        "attributes": [],
        "topicFilter": "zigbee2mqtt/tttttttttt",
        "topicFilterType": "mqtt",
        "topicPrefix": "",
        "notes": "",
        "outputs": "1",
        "x": 320,
        "y": 220,
        "wires": [
            [
                "e9a696d6b6cb6e58"
            ]
        ]
    },
    {
        "id": "e9a696d6b6cb6e58",
        "type": "debug",
        "z": "e33735cb57f4c372",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 510,
        "y": 220,
        "wires": []
    },
    {
        "id": "bc26aa1879b223d2",
        "type": "mqtt in",
        "z": "e33735cb57f4c372",
        "name": "zigbee2mqtt",
        "topic": "zigbee2mqtt/#",
        "qos": "1",
        "datatype": "json",
        "broker": "5aeb1c10233e4cc2",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 150,
        "y": 220,
        "wires": [
            [
                "0142f143f41938e0",
                "e6efe10ab218e082"
            ]
        ]
    },
    {
        "id": "0142f143f41938e0",
        "type": "hal2Action",
        "z": "e33735cb57f4c372",
        "eventHandler": "e228014191d14be6",
        "name": "Contact out action",
        "commandset": [
            {
                "category": "hal2Thing",
                "thing": "e6efe10ab218e082",
                "item": "2be75f55.195c4",
                "value": "payload",
                "type": "msg"
            }
        ],
        "ratelimit": 0,
        "x": 350,
        "y": 340,
        "wires": []
    },
    {
        "id": "9a46b6321f6613a3",
        "type": "hal2Event",
        "z": "e33735cb57f4c372",
        "eventHandler": "e228014191d14be6",
        "name": "Event on contact change",
        "topic": "",
        "thing": "e6efe10ab218e082",
        "typeSel": "hal2Thing",
        "item": "af0460be.09d73",
        "operator": "always",
        "change": "1",
        "compareValue": "",
        "compareType": "num",
        "outputValue": "payload",
        "outputType": "state",
        "x": 370,
        "y": 440,
        "wires": [
            [
                "d0a62cd05b8c3b65"
            ]
        ]
    },
    {
        "id": "30ed894a10f24da0",
        "type": "comment",
        "z": "e33735cb57f4c372",
        "name": "Example 1",
        "info": "",
        "x": 320,
        "y": 300,
        "wires": []
    },
    {
        "id": "e83393bb875ae5b0",
        "type": "comment",
        "z": "e33735cb57f4c372",
        "name": "Example 2",
        "info": "",
        "x": 320,
        "y": 400,
        "wires": []
    },
    {
        "id": "d0a62cd05b8c3b65",
        "type": "function",
        "z": "e33735cb57f4c372",
        "name": "Convert to 1/0",
        "func": "msg.payload = (msg.payload == 'closed') ? '1' : '0';\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 600,
        "y": 440,
        "wires": [
            [
                "87ea1a07174f5321"
            ]
        ]
    },
    {
        "id": "87ea1a07174f5321",
        "type": "debug",
        "z": "e33735cb57f4c372",
        "name": "To DB",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 770,
        "y": 440,
        "wires": []
    },
    {
        "id": "5aeb1c10233e4cc2",
        "type": "mqtt-broker",
        "name": "MQTT 100",
        "broker": "10.90.0.100",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "willMsg": {},
        "sessionExpiry": ""
    },
    {
        "id": "488bfca26161ef73",
        "type": "hal2EventHandler",
        "name": "Windows Doors",
        "maxlisteners": "50",
        "heartbeat": "3600"
    },
    {
        "id": "1067281e08cac1b6",
        "type": "hal2ThingType",
        "name": "Z2M Xiaomi MCCGQ11LM door / window sensor",
        "contextStore": "file",
        "nodestatus": " 🚪%Contact%⏳%Contact Open Delay%⏳%Contact Delay%🌡️%Temperature%°F📶%Linkquality%🔋%Battery%%⚡%Voltage%V🕢%LastSeen%",
        "items": [
            {
                "name": "Battery",
                "id": "38773bb6.1923d4",
                "topicFilterType": "StrEnd",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "status",
                "ingress": "488ff997.1fae98",
                "egress": "5a6ab0b3.43636",
                "notes": "",
                "output": "1"
            },
            {
                "name": "Voltage",
                "id": "a308050c.ec17f8",
                "topicFilterType": "StrEnd",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "status",
                "ingress": "b891197f.d119c8",
                "egress": "5a6ab0b3.43636",
                "notes": "",
                "output": "1"
            },
            {
                "name": "Linkquality",
                "id": "977167c1.ae6448",
                "topicFilterType": "StrEnd",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "status",
                "ingress": "7838e8e7.d95508",
                "egress": "5a6ab0b3.43636",
                "notes": "",
                "output": "1"
            },
            {
                "name": "Temperature",
                "id": "df60e448.dfe898",
                "topicFilterType": "StrEnd",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "status",
                "ingress": "5306119b.55bd2",
                "egress": "5a6ab0b3.43636",
                "notes": "",
                "output": "1"
            },
            {
                "name": "Contact",
                "id": "af0460be.09d73",
                "topicFilterType": "StrEnd",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "both",
                "ingress": "d2515770.de6b18",
                "egress": "acd4d5b2.e46cf8",
                "notes": "",
                "output": "1"
            },
            {
                "name": "LastSeen",
                "id": "800ca8b7.4b7328",
                "topicFilterType": "str",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "status",
                "ingress": "9f7dd133.3df26",
                "egress": "5a6ab0b3.43636",
                "notes": "",
                "output": "1"
            },
            {
                "name": "Contact Delay",
                "id": "cd3d788f.2a4dd8",
                "topicFilterType": "str",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "status",
                "ingress": "43e4e408.dfb08c",
                "egress": "5a6ab0b3.43636",
                "notes": "",
                "output": "1"
            },
            {
                "name": "Contact Open Delay",
                "id": "5a23656.d93b79c",
                "topicFilterType": "str",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "status",
                "ingress": "6e073250.e8a16c",
                "egress": "5a6ab0b3.43636",
                "notes": "",
                "output": "1"
            },
            {
                "name": "contact out",
                "id": "2be75f55.195c4",
                "topicFilterType": "str",
                "topicFilterValue": "",
                "topicSuffix": "",
                "type": "command",
                "ingress": "c7ccebbd.016228",
                "egress": "acd4d5b2.e46cf8",
                "notes": "",
                "output": "1"
            },
            {
                "name": "Alive",
                "id": "1",
                "topicFilterType": "StrEnd",
                "topicFilterValue": "",
                "topicSuffix": "",
                "readOnly": true,
                "ingress": "c7ccebbd.016228",
                "egress": ""
            }
        ],
        "attributes": [],
        "ingress": [
            {
                "name": "Pass-through",
                "id": "c7ccebbd.016228",
                "fn": "// msg object is passed to function\n\nreturn msg.payload;"
            },
            {
                "name": "Battery",
                "id": "488ff997.1fae98",
                "fn": "// msg object is passed to function\nif (msg.payload.battery) {\n msg.payload = Number(msg.payload.battery);\n return msg.payload;\n}\n"
            },
            {
                "name": "Voltage",
                "id": "b891197f.d119c8",
                "fn": "// msg object is passed to function\nif (msg.payload.voltage) {\n msg.payload = Number(msg.payload.voltage);\n return msg.payload * 0.01;\n}"
            },
            {
                "name": "Linkquality",
                "id": "7838e8e7.d95508",
                "fn": "// msg object is passed to function\nif (msg.payload.linkquality) {\n msg.payload = Number(msg.payload.linkquality);\n return msg.payload;\n}"
            },
            {
                "name": "Temperature",
                "id": "5306119b.55bd2",
                "fn": "// msg object is passed to function\nif (msg.payload.temperature) {\n tempc = Number(msg.payload.temperature);\n tempf = tempc * 9/5 + 32;\n msg.payload = Math.round(tempf* 10) / 10;\n return msg.payload\n}"
            },
            {
                "name": "Contact",
                "id": "d2515770.de6b18",
                "fn": "// msg object is passed to function\n//msg.payload = (msg.payload.contact == 1);\n//return msg.payload;\n\n// msg object is passed to function\nmsg.payload = (msg.payload.contact == true) ? 'closed' : 'opened';\nreturn msg.payload;"
            },
            {
                "name": "LastSeen",
                "id": "9f7dd133.3df26",
                "fn": "// msg object is passed to function\nif (msg.payload.last_seen) {\n msg.payload = String(msg.payload.last_seen);\n return msg.payload;\n}"
            },
            {
                "name": "Contact_Delay",
                "id": "43e4e408.dfb08c",
                "fn": "// msg object is passed to function\nif (msg.payload.delay) {\n msg.payload = String(msg.payload.delay);\n return msg.payload;\n}"
            },
            {
                "name": "Open_Delay",
                "id": "6e073250.e8a16c",
                "fn": "// msg object is passed to function\nif (msg.payload.open) {\n msg.payload = String(msg.payload.open);\n return msg.payload;\n}"
            }
        ],
        "egress": [
            {
                "name": "Pass-through",
                "id": "5a6ab0b3.43636",
                "fn": "// msg object is passed to function\n\nreturn msg;"
            },
            {
                "name": "Contact 2 DB",
                "id": "acd4d5b2.e46cf8",
                "fn": "msg.payload = (msg.payload.contact == true) ? '1' : '0';\nreturn msg;"
            }
        ],
        "thingStatus": true,
        "thingCommand": true,
        "thingOutput": true,
        "hbCheck": true,
        "hbType": "ttl",
        "hbTTL": "3600",
        "hbLWT": "c7ccebbd.016228",
        "hbFilterVal": "",
        "hbFilterType": "StrEnd",
        "filterFunction": "0",
        "outputs": "1"
    },
    {
        "id": "e228014191d14be6",
        "type": "hal2EventHandler",
        "name": "Event handler",
        "maxlisteners": "50",
        "heartbeat": "10"
    }
]
alexsahka commented 2 years ago

I thought about this, even have this in my flows, but I thought to have a simple out from the hal2Thing with internal conversion would be a nice feature. Thank you! image

flic commented 2 years ago

Yeah that might be worth considering, maybe add a separate output option. Thanks.