Node Red - Action Validation Error

Hi all,

Will start off that I am a complete Node Red newbie and limited knowledge on JSON etc. and also a self confessed tinkerer salvaging various New Red knowledge from various posts and websites to clutter up my own automations!

Hoping there is somebody that can assist me how the “Validation Error” can be fixed for the Action node from a Function Node (credit to Mark Nygaard!) to automate a Philip Hue light using the Dimmer switch, in which utilises the previous Call Service node before it was replaced by the latest Action node. I have attempted to fixed the Function node to call the latest Action node however get the “Validation Error” even though the automation in theory still “works!”.

P.S., this is my first post and any feedback appreciated :slight_smile:

[{"id":"a07b0840d4a3932f","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"ca85d28b8b242cf7","type":"mqtt in","z":"a07b0840d4a3932f","name":"Ollie's Light Switch","topic":"zigbee2mqtt/Ollie Light Switch","qos":"0","datatype":"json","broker":"a5bea32f15404669","nl":false,"rap":false,"inputs":0,"x":230,"y":200,"wires":[["a34f0fe64e36aa96"]]},{"id":"cf0cbbb70e09c809","type":"switch","z":"a07b0840d4a3932f","name":"Control","property":"press","propertyType":"flow","rules":[{"t":"eq","v":"true","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":800,"y":280,"wires":[["88cab56c5f3a7fb0"]]},{"id":"df7c587aa7ce1783","type":"delay","z":"a07b0840d4a3932f","name":"Delay","pauseType":"delay","timeout":"500","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"outputs":1,"x":650,"y":280,"wires":[["cf0cbbb70e09c809"]]},{"id":"c4348bef6822940c","type":"api-call-service","z":"a07b0840d4a3932f","name":"Light","server":"30f2dc85.ab1bf4","version":7,"debugenabled":false,"action":"","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"light","service":"toggle","output_location":"","output_location_type":"none","x":930,"y":200,"wires":[[]]},{"id":"a34f0fe64e36aa96","type":"change","z":"a07b0840d4a3932f","name":"","rules":[{"t":"move","p":"payload.action","pt":"msg","to":"payload.button_action","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":200,"wires":[["88cab56c5f3a7fb0"]]},{"id":"88cab56c5f3a7fb0","type":"function","z":"a07b0840d4a3932f","name":"switch","func":"var entity = 'light.ollie_light';\nvar interval = 30;\n/*\nfunction name(parameter1, parameter2, parameter3) {\n  // code to be executed\n}\n*/\nconst globalHomeAssistant = global.get('homeassistant');\nvar brightness = globalHomeAssistant.homeAssistant.states[entity].attributes.brightness || 0;\nvar state = globalHomeAssistant.homeAssistant.states[entity].state;\nvar delay = 500;\nflow.set('press', false);\n\nif (!msg.payload.hasOwnProperty('action')) msg.payload.button = \"\";\nvar newMsg = { payload: {} };\n\nlet ollieswitch = msg.payload.button_action;\n\nif (ollieswitch == \"on_press\")\n    if (state == \"on\" && brightness > 1) {\n        newMsg.payload =\n        {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": 255,\n                \"transition\": 2\n            }\n        };\n    }\n    else {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"transition\": 2\n            }\n        };\n    }\n\nif (ollieswitch == \"up_press\") {\n    if (brightness < 255) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": brightness + interval,\n                \"transition\": 1\n            }\n        };\n\n    } else { return null; }\n}\n\nif (ollieswitch == \"down_press\") {\n    if (brightness > 0) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": brightness - interval,\n                \"transition\": 1\n            }\n        };\n\n    } else { return null; }\n}\n\nif (ollieswitch == \"up_hold\") {\n    flow.set('press', true);\n    if (brightness < 255) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": brightness + interval,\n                \"transition\": 1\n            }\n        };\n\n    } else {\n        flow.set('press', false);\n        return null\n    }\n}\n\nif (ollieswitch == \"down_hold\") {\n    flow.set('press', true);\n    if (brightness > 0) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": brightness - interval,\n                \"transition\": 1\n            }\n        };\n\n    } else {\n        flow.set('press', false);\n        return null\n    }\n}\n\nif (ollieswitch == \"up_hold_release\") {\n    flow.set('press', false)\n    return null;\n}\n\nif (ollieswitch == \"down_hold_release\") {\n    flow.set('press', false)\n    if (brightness <= 0) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_off\",\n            target: {\n                entity_id: [entity],\n            }\n        }\n    } else {\n        return null;\n    }\n}\n\nif (ollieswitch == \"off_press\")\n    newMsg.payload =\n    {\n        \"action\": \"homeassistant.turn_off\",\n        target: {\n            entity_id: [entity],\n        },\n        data: {\n            \"transition\": 2\n        }\n    }\n\nif (msg.payload.action === \"\") {\n    return null;\n}\n\nreturn [newMsg, msg]\n","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":200,"wires":[["c4348bef6822940c"],["df7c587aa7ce1783"]]},{"id":"c6e7c0b36a6a0785","type":"function","z":"a07b0840d4a3932f","name":"switch","func":"var entity = 'light.ollie_light';\nvar interval = 30;\n/*\nfunction name(parameter1, parameter2, parameter3) {\n  // code to be executed\n}\n*/\nconst globalHomeAssistant = global.get('homeassistant');\nvar brightness = globalHomeAssistant.homeAssistant.states[entity].attributes.brightness || 0;\nvar state = globalHomeAssistant.homeAssistant.states[entity].state;\nvar delay = 500;\nflow.set('press', false);\n\nif (!msg.payload.hasOwnProperty('action')) msg.payload.button = \"\";\nvar newMsg = { payload: {} };\n\nlet myswitch = msg.payload.button_action;\n\nif (myswitch == \"on_press\")\n    if (state == \"on\" && brightness > 1) {\n        newMsg.payload =\n        {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": 255,\n                \"transition\": 2\n            }\n        };\n    }\n    else {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"transition\": 2\n            }\n        };\n    }\n\nif (myswitch == \"up_press\") {\n    if (brightness < 255) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": brightness + interval,\n                \"transition\": 1\n            }\n        };\n\n    } else { return null; }\n}\n\nif (myswitch == \"down_press\") {\n    if (brightness > 0) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": brightness - interval,\n                \"transition\": 1\n            }\n        };\n\n    } else { return null; }\n}\n\nif (myswitch == \"up_hold\") {\n    flow.set('press', true);\n    if (brightness < 255) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": brightness + interval,\n                \"transition\": 1\n            }\n        };\n\n    } else {\n        flow.set('press', false);\n        return null\n    }\n}\n\nif (myswitch == \"down_hold\") {\n    flow.set('press', true);\n    if (brightness > 0) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_on\",\n            target: {\n                entity_id: [entity],\n            },\n            data: {\n                \"brightness\": brightness - interval,\n                \"transition\": 1\n            }\n        };\n\n    } else {\n        flow.set('press', false);\n        return null\n    }\n}\n\nif (myswitch == \"up_hold_release\") {\n    flow.set('press', false)\n    return null;\n}\n\nif (myswitch == \"down_hold_release\") {\n    flow.set('press', false)\n    if (brightness <= 0) {\n        newMsg.payload = {\n            \"action\": \"homeassistant.turn_off\",\n            target: {\n                entity_id: [entity],\n            }\n        }\n    } else {\n        return null;\n    }\n}\n\nif (myswitch == \"off_press\")\n    newMsg.payload =\n    {\n        \"action\": \"homeassistant.turn_off\",\n        target: {\n            entity_id: [entity],\n        },\n        data: {\n            \"transition\": 2\n        }\n    }\n\nif (msg.payload.action === \"\") {\n    return null;\n}\n\nreturn [newMsg, msg]\n","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":140,"wires":[[],[]]},{"id":"d426e7b039fdce5c","type":"comment","z":"a07b0840d4a3932f","name":"Ollie's Room","info":"","x":210,"y":140,"wires":[]},{"id":"a5bea32f15404669","type":"mqtt-broker","name":"","broker":"localhost","port":1883,"clientid":"","autoConnect":true,"usetls":false,"protocolVersion":4,"keepalive":60,"cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"30f2dc85.ab1bf4","type":"server","name":"Home Assistant","addon":true}]
var entity = 'light.ollie_light';
var interval = 30;
/*
function name(parameter1, parameter2, parameter3) {
  // code to be executed
}
*/
const globalHomeAssistant = global.get('homeassistant');
var brightness = globalHomeAssistant.homeAssistant.states[entity].attributes.brightness || 0;
var state = globalHomeAssistant.homeAssistant.states[entity].state;
var delay = 500;
flow.set('press', false);

if (!msg.payload.hasOwnProperty('action')) msg.payload.button = "";
var newMsg = { payload: {} };

let ollieswitch = msg.payload.button_action;

if (ollieswitch == "on_press")
    if (state == "on" && brightness > 1) {
        newMsg.payload =
        {
            "action": "homeassistant.turn_on",
            target: {
                entity_id: [entity],
            },
            data: {
                "brightness": 255,
                "transition": 2
            }
        };
    }
    else {
        newMsg.payload = {
            "action": "homeassistant.turn_on",
            target: {
                entity_id: [entity],
            },
            data: {
                "transition": 2
            }
        };
    }

if (ollieswitch == "up_press") {
    if (brightness < 255) {
        newMsg.payload = {
            "action": "homeassistant.turn_on",
            target: {
                entity_id: [entity],
            },
            data: {
                "brightness": brightness + interval,
                "transition": 1
            }
        };

    } else { return null; }
}

if (ollieswitch == "down_press") {
    if (brightness > 0) {
        newMsg.payload = {
            "action": "homeassistant.turn_on",
            target: {
                entity_id: [entity],
            },
            data: {
                "brightness": brightness - interval,
                "transition": 1
            }
        };

    } else { return null; }
}

if (ollieswitch == "up_hold") {
    flow.set('press', true);
    if (brightness < 255) {
        newMsg.payload = {
            "action": "homeassistant.turn_on",
            target: {
                entity_id: [entity],
            },
            data: {
                "brightness": brightness + interval,
                "transition": 1
            }
        };

    } else {
        flow.set('press', false);
        return null
    }
}

if (ollieswitch == "down_hold") {
    flow.set('press', true);
    if (brightness > 0) {
        newMsg.payload = {
            "action": "homeassistant.turn_on",
            target: {
                entity_id: [entity],
            },
            data: {
                "brightness": brightness - interval,
                "transition": 1
            }
        };

    } else {
        flow.set('press', false);
        return null
    }
}

if (ollieswitch == "up_hold_release") {
    flow.set('press', false)
    return null;
}

if (ollieswitch == "down_hold_release") {
    flow.set('press', false)
    if (brightness <= 0) {
        newMsg.payload = {
            "action": "homeassistant.turn_off",
            target: {
                entity_id: [entity],
            }
        }
    } else {
        return null;
    }
}

if (ollieswitch == "off_press")
    newMsg.payload =
    {
        "action": "homeassistant.turn_off",
        target: {
            entity_id: [entity],
        },
        data: {
            "transition": 2
        }
    }

if (msg.payload.action === "") {
    return null;
}

return [newMsg, msg]

This is a generic turn on command. I don’t think it supports attributes officially. Try light.turn_on instead.

This is just a guess, but if you hold up you’re increasing the brightness by 30 every 500ms, and decreasing when you hold down. But nothing stops your code going above 255 or below 0.

Thank you both for your response, I believe that I have managed to resolve this!

Using the Debug node noted that the Move “payload.action” node was passing all the payload from the Dimmer Switch through the Function node which included payload from the Dimmer Switch that were not called in the Function node (i.e. on_hold_release, off_press_release, etc.) therefore the Action node was assumed to be complaining that it has nothing to action.

Resolved this by including a “Sort” node to only pass the payload from the Dimmer Switch to the Function node.

1 Like