Controlling the color of button indicators on a Zooz ZEN32 using Node-RED

I would like to use Node-RED to set the colors of the button LED indicators on a ZOOZ Zen32. I can see how to do this using the Z-Wave JS GUI, and I can set one parameter at a time… but I’d like to set multiple parameters at once if possible (LED on, LED color, LED brightness, etc.) is there a good way to do this… or do I need a LOT of individual call service nodes?

I’ve followed the “How to program your ZEN32 on Home Assistant” guide… but it only shows changing a single parameter at a time.

I think you will still need to send multiple calls but you can use a function delay to send the calls to one call service node.

I don’t have this particular service call, so I am unsure how to structure the message. I set it from what i saw in that link, You’ll need to change the entity id and the parameter/value. It’s set to fire every 300ms (300, 600, 900) you may need to extended that.

image

[{"id":"0756074d8498a081","type":"function","z":"f80b6c338afd5483","name":"delay func","func":"setTimeout(function () {\n    node.status({ fill: \"red\", shape: \"ring\", text: \" \" });\n    msg['payload'] = {\n        domain: \"zwave_js\",\n        service: \"bulk_set_config_parameters\",\n        data: {\n            \"entity_id\": \"switch.your_switch\",\n            \"parameter\": 2,\n            \"value\": 3,\n        }\n    };\n    node.send(msg);\n}, 300);\n\nsetTimeout(function () {\n    node.status({ fill: \"red\", shape: \"ring\", text: \" \" });\n    msg['payload'] = {\n        domain: \"zwave_js\",\n        service: \"bulk_set_config_parameters\",\n        data: {\n            \"entity_id\": \"switch.your_switch\",\n            \"parameter\": 2,\n            \"value\": 3,\n        }\n    };\n    node.send(msg);\n}, 600);\n\nsetTimeout(function () {\n    node.status({ fill: \"red\", shape: \"ring\", text: \" \" });\n    msg['payload'] = {\n        domain: \"zwave_js\",\n        service: \"bulk_set_config_parameters\",\n        data: {\n            \"entity_id\": \"switch.your_switch\",\n            \"parameter\": 2,\n            \"value\": 3,\n        }\n    };\n    node.send(msg);\n}, 900);\nnode.status({ fill: \"blue\", shape: \"ring\", text: ' ' });","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1170,"y":2820,"wires":[["598bd26b79556c6b","095a8d052af1f65e"]]},{"id":"ef36acc61689034f","type":"inject","z":"f80b6c338afd5483","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":900,"y":2820,"wires":[["0756074d8498a081"]]},{"id":"095a8d052af1f65e","type":"api-call-service","z":"f80b6c338afd5483","name":"","server":"6b1110b5.183a4","version":5,"debugenabled":true,"domain":"","service":"","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1470,"y":2820,"wires":[[]]},{"id":"6b1110b5.183a4","type":"server","name":"Home Assistant","version":4,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m"}]

Here’s the function node I use to set the led status lights. The default I use is all lights off and the main button on only when the light is on.

[{"id":"6c0c3dd0d976bfd1","type":"server-state-changed","z":"1a9590f5.2d236f","name":"doors/windows/alarm","server":"","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":["alarm_control_panel.alarm","binary_sensor.back_door","cover.garage_door"],"entityidfiltertype":"list","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[],"x":484,"y":3376,"wires":[["b4391a5b2f70b141"]]},{"id":"b4391a5b2f70b141","type":"trigger","z":"1a9590f5.2d236f","name":"","op1":"","op2":"","op1type":"nul","op2type":"pay","duration":"1","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":625,"y":3376,"wires":[["b96cbf9b30236f3e"]],"l":false},{"id":"b96cbf9b30236f3e","type":"function","z":"1a9590f5.2d236f","name":"build","func":"const entities = global.get(\"homeassistant\").homeAssistant.states\nconst isAlarmArmed = [\"armed_home\", \"armed_night\", \"armed_away\"].includes(entities['alarm_control_panel.alarm'].state);\nconst isSleeping = entities['input_boolean.sleep_mode'].state === \"on\";\nconst isGarageOpen = entities['cover.garage_door'].state !== \"closed\";\nconst isBackDoorOpen = entities['binary_sensor.back_door'].state !== \"off\";\n\nconst state = {\n    on: 3,\n    off: 2,\n    loadOn: 1,\n    loadOff: 0,\n};\nconst color = {\n    white: 0,\n    blue: 1,\n    green: 2,\n    red: 3,\n};\nconst brightness = {\n    bright: 0, // 100%\n    medium: 1, // 60%\n    low: 2, // 30%\n};\nconst properties = {\n    indicator: \"LED Indicator\",\n    color: \"LED Indicator Color\",\n    brightness: \"LED Indicator Brightness\"\n};\nconst values = {\n    indicator: [1,2,2,2,2],\n    color: [0,0,0,0,0],\n    brightness: [1,1,1,1,1],\n};\n\nif(!isSleeping) { \n    // Show alarm armed\n    if(isAlarmArmed) {\n        values.indicator[1] = state.on;\n        values.color[1] = color.red;\n    }\n}\nif(isGarageOpen || isBackDoorOpen) {\n    const both = isGarageOpen && isBackDoorOpen;\n    values.indicator[2] = state.on;\n    values.color[2] = both ? color.blue : color.green;\n}\n// node.warn(values);\nupdateLeds();\n\nfunction getParameterName(property, index) {\n    const buttonName = `(${index === 0 ? 'Relay' : `Button ${index}`})`;\n    return `${properties[property]} ${buttonName}`\n}\n\nfunction send(property, index, value) {\n    node.send({\n        payload: {\n            data: {\n                parameter: getParameterName(property, index),\n                value\n            }\n        }\n    });\n}\n\nfunction updateLeds() {\n    Object.keys(properties).forEach((property) => {\n        values[property].forEach((value, index) => {\n            send(property, index, value)\n        });\n    });\n\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":738,"y":3376,"wires":[["5d91bd48f4645dbf"]]},{"id":"5d91bd48f4645dbf","type":"api-call-service","z":"1a9590f5.2d236f","name":"","server":"","version":5,"debugenabled":false,"domain":"zwave_js","service":"set_config_parameter","areaId":[],"deviceId":[],"entityId":["switch.bedroom_light"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":958,"y":3376,"wires":[[]]}]
const entities = global.get("homeassistant").homeAssistant.states
const isAlarmArmed = ["armed_home", "armed_night", "armed_away"].includes(entities['alarm_control_panel.alarm'].state);
const isSleeping = entities['input_boolean.sleep_mode'].state === "on";
const isGarageOpen = entities['cover.garage_door'].state !== "closed";
const isBackDoorOpen = entities['binary_sensor.back_door'].state !== "off";

const state = {
    on: 3,
    off: 2,
    loadOn: 1,
    loadOff: 0,
};
const color = {
    white: 0,
    blue: 1,
    green: 2,
    red: 3,
};
const brightness = {
    bright: 0, // 100%
    medium: 1, // 60%
    low: 2, // 30%
};
const properties = {
    indicator: "LED Indicator",
    color: "LED Indicator Color",
    brightness: "LED Indicator Brightness"
};
const values = {
    indicator: [1,2,2,2,2],
    color: [0,0,0,0,0],
    brightness: [1,1,1,1,1],
};

if(!isSleeping) { 
    // Show alarm armed
    if(isAlarmArmed) {
        values.indicator[1] = state.on;
        values.color[1] = color.red;
    }
}
if(isGarageOpen || isBackDoorOpen) {
    const both = isGarageOpen && isBackDoorOpen;
    values.indicator[2] = state.on;
    values.color[2] = both ? color.blue : color.green;
}
// node.warn(values);
updateLeds();

function getParameterName(property, index) {
    const buttonName = `(${index === 0 ? 'Relay' : `Button ${index}`})`;
    return `${properties[property]} ${buttonName}`
}

function send(property, index, value) {
    node.send({
        payload: {
            data: {
                parameter: getParameterName(property, index),
                value
            }
        }
    });
}

function updateLeds() {
    Object.keys(properties).forEach((property) => {
        values[property].forEach((value, index) => {
            send(property, index, value)
        });
    });

}