Example Stateless Programmable Switch - NRCHKB/node-red-contrib-homekit-bridged GitHub Wiki

Properties

Available Properties

The stateless programmable switch is meant to replicate the function of a button similar to Logitech Pop or Phillips Hue Remote. It can be used to set scenes in the Home app. In a setup with mixed Node-RED HomeKit devices and authentic HomeKit devices, this setup can be used to control the official HomeKit devices from within Node-RED. The following characteristic properties are available:

Single Button:

Characteristic Optional/Required Characteristic Properties (to enable property)
ProgrammableSwitchEvent Required {"ProgrammableSwitchEvent": 0}

Multi Button (Parent Service)

Characteristic Optional/Required Characteristic Properties (to enable property)
ServiceLabelNamespace Required {"ServiceLabelNamespace": {"MinValue":1,"MaxValue":1}} (sets namespace to numbers 1,2,3...)
ServiceLabelIndex Required {"ServiceLabelIndex": {"MinValue":2,"MaxValue":2}} (sets to "button 2")
ProgrammableSwitchEvent Required {"ProgrammableSwitchEvent": 0}

Details

Characteristic Format Accepted Values Notes
ProgrammableSwitchEvent uint8 0, 1, 2 0 means single press, 1 means double press, 2 means long press
ServiceLabelNamespace uint8 0, 1 0 means "Dot names", 1 means "numeral names 1, 2, 3"
ServiceLabelIndex uint8 1, 2, 3, etc Numbers the buttons in a multi button service

Examples

These examples are meant to be copied into your Node-RED system and adapted to your setup.

Single Button

This example is a single button with 3 press options: "Single Press", "Double Press", or "Long Press". Each of these can be set in the Home.app to set a scene. Note the scene settings for these buttons is done from within the button settings in the Home app rather than the automation screen.

In the Home.app, this example appears as a single button with 3 press actions:

In Node-RED it will look like:

Copyable Node-RED Flow:

[{"id":"7d1c7028.435a78","type":"homekit-service","z":"821a2c87.afa08","isParent":true,"bridge":"fc1c5b0d.cd50f8","parentService":"","name":"State Less","serviceName":"StatelessProgrammableSwitch","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{}","x":490,"y":480,"wires":[](/NRCHKB/node-red-contrib-homekit-bridged/wiki/)},{"id":"f24f73b8.99fcd8","type":"inject","z":"821a2c87.afa08","name":"0","topic":"","payload":"{\"ProgrammableSwitchEvent\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":460,"wires":["7d1c7028.435a78"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"7d1c7028.435a78")},{"id":"f120536.bb629b","type":"inject","z":"821a2c87.afa08","name":"1","topic":"","payload":"{\"ProgrammableSwitchEvent\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":500,"wires":["7d1c7028.435a78"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"7d1c7028.435a78")},{"id":"cc75a2e8.032db","type":"inject","z":"821a2c87.afa08","name":"2","topic":"","payload":"{\"ProgrammableSwitchEvent\":2}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":540,"wires":["7d1c7028.435a78"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"7d1c7028.435a78")},{"id":"fc1c5b0d.cd50f8","type":"homekit-bridge","z":"","bridgeName":"Irrigation","pinCode":"123-45-321","port":"","allowInsecureRequest":false,"manufacturer":"Garage","model":"Pi HAT","serialNo":"3Aplus","customMdnsConfig":false,"mdnsMulticast":true,"mdnsInterface":"","mdnsPort":"","mdnsIp":"","mdnsTtl":"","mdnsLoopback":true,"mdnsReuseAddr":true}]

Single Button Example applied for dimming a light bulb

The following example is using a Stateless Programme Switch to control a light bulb. Even it is connected to a Philips Hue node to control the particular light bulb, it can be used also for sending payload for brightness also to a NRCHKB Light Bulb generated accessory.

The following flow was designed to have the following features available by pressing the a button:

  • Single press - Toggle light switching on with recent brightness and off
  • Double press - Switch Light on with full brightness, but with different color temperature depending on evening time
  • Long press - dim light bulb stepwise up to 100% brightness and down to 0% as long as the button remains pressed

The example relies on a hardware setup using an Aqara button connected via a Zigbee gateway to Node-red. The Stateless Programmeable Switch accessory is bridged with NRCHKB to have it available in the Home.App (e. g. for further processing using actions, but the logic for the features above is applied within node-red). This has the advantage the capabilities are still available, even the HomeKit Hub (e. g. aTV is offline/out of order which happens some time if it gets disconnected from the WIFI at night).

Node-RED flow looks like:

There are some specials in this flow. First prerequisite is to persist the recent state of the light bulb: flow.set('BedroomLightBulbLeftsideBed', msg.payload) wicht persists the following values:

{
   "on":false,
   "brightness":27,
   "brightnessLevel":68,
   "reachable":true,
   "colorTemp":447,
   "updated":"2020-11-04T14:08:59+01:00"
}

The Author of this example leave it to your own choice, whether to persist this value in Node-red globally or locally within the flow. For the dimming feature there is also a need persist a factor whether the bulb shall dimming brighter or darker, which is represented by a stepValue. The function node for A btnLongPress event controls the brightness. Here is an excerpt of the code to illustrate the coding concept for dimming:

var stepValue  = flow.get('BedroomLightBulbLeftsideBedStepValue') || 10;
var bulbStatus = flow.get('BedroomLightBulbLeftsideBed')
...
if (stepValue > 0) {
    // raise brightness of the bulb

    if (brightness + stepValue <= 100) {
        myMsg.payload = {
            "on": true,
            "brightness": brightness + stepValue
            
        }
    } else {
        myMsg.payload = {
            "on": true,
            "brightness": brightness
        }
        // reverse direction of dimming light
        stepValue = -stepValue;
        flow.set('BedroomLightBulbLeftsideBedStepValue', stepValue);
    }

}
...

Some more tricky is the required generation of messages needed for increment/decrement the brightness based on the state of a long pressed button. In this application it is required because the deCONZ connected AQARA button doesn't provide a "pulsed" BTN_LONG_PRESS-event. The following diagram gives an overview what's happens in the related part of the flow:

The trigger node sends each second a msg.payload = 1 to the Set dimmable function node, triggered by the btnPress event from the deCONZ node. The sequence is delayed for two seconds. The entire dimming process happens until the deCONZ node captures the a btnRelease from the physical button. You can deal with the set timing different from the given example to change the speed your bulbs are going brighter or darker. An initial reset of the sequence is implemented as well es a reset if other button interaction by the user happens.

Copyable Node-Red flow:

[{"id":"4280ad0c.d166ac","type":"homekit-service","z":"123b4880.955e18","isParent":true,"bridge":"60729d35.03880c","parentService":"","name":"Bedroom Left Bedside Table","serviceName":"StatelessProgrammableSwitch","topic":"","filter":false,"manufacturer":"Xiaomi","model":"Aqara Switch Button","serialNo":"Default Serial Number","firmwareRev":"","hardwareRev":"","softwareRev":"","cameraConfigVideoProcessor":"","cameraConfigSource":"","cameraConfigStillImageSource":"","cameraConfigMaxStreams":"","cameraConfigMaxWidth":"","cameraConfigMaxHeight":"","cameraConfigMaxFPS":"","cameraConfigMaxBitrate":"","cameraConfigVideoCodec":"","cameraConfigAudioCodec":"","cameraConfigAudio":false,"cameraConfigPacketSize":"","cameraConfigVerticalFlip":false,"cameraConfigHorizontalFlip":false,"cameraConfigMapVideo":"","cameraConfigMapAudio":"","cameraConfigVideoFilter":"","cameraConfigAdditionalCommandLine":"","cameraConfigDebug":false,"cameraConfigSnapshotOutput":"disabled","cameraConfigInterfaceName":"","characteristicProperties":"{\"Name\":\"Bedroom Left Bedside Table\"}","waitForSetupMsg":false,"outputs":2,"x":460,"y":280,"wires":[],["4166bbd4.f50474"]]},{"id":"ad569bd2.bde578","type":"inject","z":"123b4880.955e18","name":"Single Press","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"ProgrammableSwitchEvent\":0}","payloadType":"json","x":170,"y":120,"wires":[["4280ad0c.d166ac"]]},{"id":"aed80a58.cdb98","type":"inject","z":"123b4880.955e18","name":"Double Press","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"ProgrammableSwitchEvent\":1}","payloadType":"json","x":170,"y":160,"wires":[["4280ad0c.d166ac"]]},{"id":"f8c297d8.b982f8","type":"inject","z":"123b4880.955e18","name":"Long Press","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"ProgrammableSwitchEvent\":2}","payloadType":"json","x":170,"y":200,"wires":[["4280ad0c.d166ac"]]},{"id":"60653b4d.5f11dc","type":"hue-light","z":"123b4880.955e18","name":"Leftside Bed","bridge":"b461e4d7.4e0da","lightid":"13","colornamer":true,"skipevents":false,"universalevents":false,"x":1250,"y":280,"wires":[["56a5e547.7a98e4","4c1eb839.04a478"]]},{"id":"4166bbd4.f50474","type":"switch","z":"123b4880.955e18","name":"","property":"payload.ProgrammableSwitchEvent","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"str"},{"t":"eq","v":"2","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":670,"y":280,"wires":[["fb47cb89.46bdf","8da7d4.94de203"],["8da7d4.94de203","6158161e.02f428"],[]]},{"id":"fb47cb89.46bdf","type":"change","z":"123b4880.955e18","name":"Toggle Light Last State","rules":[{"t":"set","p":"payload.toggle","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":990,"y":220,"wires":[["60653b4d.5f11dc"]]},{"id":"4c1eb839.04a478","type":"mqtt out","z":"123b4880.955e18","name":"","topic":"hu/status/Bedroom/LightBulb/BedsideTableLeft","qos":"1","retain":"false","broker":"107097e2.fc9c48","x":1580,"y":280,"wires":[]},{"id":"56a5e547.7a98e4","type":"function","z":"123b4880.955e18","name":"Persist Brightness","func":"flow.set('BedroomLightBulbLeftsideBed', msg.payload)\n\nreturn msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1490,"y":340,"wires":[[]]},{"id":"77ffbcca.bbae7c","type":"deconz-input","z":"123b4880.955e18","name":"Btn Leftside Bed","server":"d6144ff9.fba308","device":"00:15:8d:00:04:27:1a:f3-01-0012","device_name":"Smart Switch - Leftside Bedroom : ZHASwitch","topic":"","state":"0","output":"always","outputAtStartup":true,"x":180,"y":280,"wires":[[],["4280ad0c.d166ac"]]},{"id":"fdc47374.e3e4b8","type":"deconz-event","z":"123b4880.955e18","name":"deCONZ Events","server":"d6144ff9.fba308","device_name":null,"x":180,"y":460,"wires":[["36d669e.4d0f916"]]},{"id":"36d669e.4d0f916","type":"function","z":"123b4880.955e18","name":"Catch Longpress Btn Evt","func":"var myMsg = {}\n\nif (msg.payload.uniqueid == \"00:15:8d:00:04:27:1a:f3-01-0012\") {\n    // only for specific btn\n    myMsg.payload = {\n        \"BtnLeftsideBedLongEvent\": msg.payload.state.buttonevent,\n        \"lastupdated\": msg.payload.state.lastupdated\n    }\n}\n\nreturn myMsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":450,"y":460,"wires":[["684224a0.9e09d4"]]},{"id":"addf16d6.54f9f","type":"function","z":"123b4880.955e18","name":"Set dimmable brightness","func":"var myMsg = {};\nvar brightness = 0\nvar stepValue  = flow.get('BedroomLightBulbLeftsideBedStepValue') ](/NRCHKB/node-red-contrib-homekit-bridged/wiki/|-10;\nvar-bulbStatus-=-flow.get('BedroomLightBulbLeftsideBed')\n\nif-(typeof-bulbStatus-!=-\"undefined\")-{\n----//-Rounds-to-whole-tens-otherwise-startign-with-0\n----brightness-=-Math.ceil((bulbStatus.brightness)/10)*10\n}\n\nif-(stepValue->-0)-{\n----//-raise-brightness-of-the-bulb\n----\n----//-correct-brightness-if-the-bulb-was-off-before\n----if-(bulbStatus.on-===-false-&&-brightness-==-10)-{\n--------brightness-=-0\n----}\n\n----if-(brightness-+-stepValue-<=-100)-{\n--------myMsg.payload-=-{\n------------\"on\":-true,\n------------\"brightness\":-brightness-+-stepValue\n------------\n--------}\n----}-else-{\n--------myMsg.payload-=-{\n------------\"on\":-true,\n------------\"brightness\":-brightness\n--------}\n--------\n--------stepValue-=--stepValue;\n--------flow.set('BedroomLightBulbLeftsideBedStepValue',-stepValue);\n----}\n\n----node.status({fill:\"yellow\",shape:\"dot\",text:\"Increase-to-\"-+-myMsg.payload.brightness-});\n\n}-else-{\n----//-decrease-brightness-of-the-bulb\n----\n----if-(brightness-+-stepValue->-0)-{\n--------myMsg.payload-=-{\n------------\"on\":-true,\n------------\"brightness\":-brightness-+-stepValue\n--------}\n----}-else-{\n--------myMsg.payload-=-{\n------------\"on\":-false,\n------------\"brightness\":-0\n--------}\n\n--------stepValue-=--stepValue;\n--------flow.set('BedroomLightBulbLeftsideBedStepValue',-stepValue);\n----}\n----\n----node.status({fill:\"grey\",shape:\"dot\",text:\"Decrease-to-\"-+-myMsg.payload.brightness-});\n}\n\nreturn-myMsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":990,"y":340,"wires":[["60653b4d.5f11dc")},{"id":"684224a0.9e09d4","type":"switch","z":"123b4880.955e18","name":"","property":"payload.BtnLeftsideBedLongEvent","propertyType":"msg","rules":[{"t":"eq","v":"1001","vt":"num"},{"t":"eq","v":"1003","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":670,"y":460,"wires":["8015bcf2.957588"],["8da7d4.94de203"],[]]},{"id":"8015bcf2.957588","type":"trigger","z":"123b4880.955e18","name":"Trigger Dimm Msg","op1":"1","op2":"1","op1type":"num","op2type":"num","duration":"1","extend":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":970,"y":400,"wires":[["b0f95f60.fb6d3","addf16d6.54f9f"]]},{"id":"b0f95f60.fb6d3","type":"delay","z":"123b4880.955e18","name":"Delay next Dimm Msg","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":980,"y":460,"wires":[["8015bcf2.957588"]]},{"id":"8da7d4.94de203","type":"change","z":"123b4880.955e18","name":"Stop Dimm Msg","rules":[{"t":"set","p":"reset","pt":"msg","to":"reset","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":400,"wires":[["b0f95f60.fb6d3","8015bcf2.957588"]]},{"id":"a2fef5a2.f13ad","type":"inject","z":"123b4880.955e18","name":"Initial Reset","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":490,"y":520,"wires":[["8da7d4.94de203"]]},{"id":"6158161e.02f428","type":"function","z":"123b4880.955e18","name":"Set On with full brightness","func":"var date = new Date();\nvar myMsg = {};\n\nif (date.getHours() > 19 ](/NRCHKB/node-red-contrib-homekit-bridged/wiki/|-date.getHours()-<-8)-{\n----myMsg.payload-=-{\n----\"on\":-true,\n----\"brightness\":-100,\n----\"colorTemp\":-366\n----}\n}\nelse-{\n----myMsg.payload-=-{\n----\"on\":-true,\n----\"brightness\":-100,\n----\"colorTemp\":-153\n----}\n}\n\nreturn-myMsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1000,"y":280,"wires":[["60653b4d.5f11dc")},{"id":"5060339b.5edd4c","type":"ui_button","z":"123b4880.955e18","name":"Btn Leftside Bed","group":"e156b6ec.f27cc8","order":1,"width":0,"height":0,"passthru":false,"label":"Linkes Bett","tooltip":"Nachttischlampe links ein/ausschalten","color":"","bgcolor":"","icon":"lightbulb_outline","payload":"{\"ProgrammableSwitchEvent\":0}","payloadType":"json","topic":"","x":190,"y":240,"wires":["4280ad0c.d166ac"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"4280ad0c.d166ac")},{"id":"60729d35.03880c","type":"homekit-bridge","z":"","bridgeName":"NRCHKB-02-PROD","pinCode":"002-02-002","port":"","allowInsecureRequest":false,"manufacturer":"eQ-3","model":"CCU3","serialNo":"000000008c02b30a","firmwareRev":"","hardwareRev":"BCM2835","softwareRev":"a02082","customMdnsConfig":false,"mdnsMulticast":true,"mdnsInterface":"","mdnsPort":"","mdnsIp":"","mdnsTtl":"","mdnsLoopback":true,"mdnsReuseAddr":true,"allowMessagePassthrough":true},{"id":"b461e4d7.4e0da","type":"hue-bridge","z":"","name":"Philips hue II","bridge":"192.168.178.24","key":"ifG37dulMEgYcAMuA5J2pbBI0BU6PjC5YxAsgi6i","interval":"3000","disableupdates":false},{"id":"107097e2.fc9c48","type":"mqtt-broker","z":"","name":"Mosquitto-raspi-smarthome","broker":"raspi-smarthome","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","willTopic":"","willQos":"0","willRetain":"false","willPayload":""},{"id":"d6144ff9.fba308","type":"deconz-server","z":"","name":"deCONZ raspi-smarthome","ip":"192.168.178.60","port":"8080","apikey":"30DD716E3F","ws_port":"443","secure":false,"polling":"15"},{"id":"e156b6ec.f27cc8","type":"ui_group","z":"","name":"Nachtlicht","tab":"761bf68b.431248","order":2,"disp":true,"width":"6","collapse":false},{"id":"761bf68b.431248","type":"ui_tab","z":"","name":"Schlafen","icon":"mi-single_bed","order":4,"disabled":false,"hidden":false}]

Multi-button Example

For a multi-button example, each button gets up to 3 actions. My example will show 3 buttons each with 3 actions. The buttons are set up very similar to the above example - but with ServiceLabel as the Parent node and StatelessProgrammableSwitch as the linked node.

The required configurations will go in Characteristic Properties inside of the node configuration.

For the ServiceLabel node, the ServiceLabelIndex must be defined. 0 is "dot numbers" so the buttons will be called "one dot", "two dots", "three dots", etc. 1 is normal numbers so they will be called "Button 1", "Button 2", "Button 3", etc. This example will explain using numbered buttons.

Characteristic properties for ServiceLabel service:

{
    "ServiceLabelNamespace":
    {
        "minValue":1,
        "maxValue":1
    }
}

The buttons are configured the same as the previous example with some added information in the Characteristic Properties (example for button 2):

{
    "ServiceLabelIndex":
    {
        "minValue":2,
        "maxValue":2
    }
}

The ServiceLabelIndex is required so all buttons don't appear as "Button 1".

In the Home.app, my example looks like this:

Node-RED flow looks like:

Copyable Node-RED flow:

[{"id":"cb200db5.a6b7d","type":"homekit-service","z":"821a2c87.afa08","isParent":true,"bridge":"fc1c5b0d.cd50f8","parentService":"","name":"Multi Button","serviceName":"ServiceLabel","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{\n    \"ServiceLabelNamespace\":\n    {\n        \"minValue\":1,\n        \"maxValue\":1\n    }\n}","x":490,"y":660,"wires":[](/NRCHKB/node-red-contrib-homekit-bridged/wiki/)},{"id":"7613def3.7d80d","type":"homekit-service","z":"821a2c87.afa08","isParent":false,"bridge":"","parentService":"cb200db5.a6b7d","name":"Button 1","serviceName":"StatelessProgrammableSwitch","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{\n    \"ServiceLabelIndex\":\n    {\n        \"minValue\":1,\n        \"maxValue\":1\n    }\n}","x":480,"y":800,"wires":[](/NRCHKB/node-red-contrib-homekit-bridged/wiki/)},{"id":"2b9112bc.f268ae","type":"homekit-service","z":"821a2c87.afa08","isParent":false,"bridge":"","parentService":"cb200db5.a6b7d","name":"Button 2","serviceName":"StatelessProgrammableSwitch","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{\n    \"ServiceLabelIndex\":\n    {\n        \"minValue\":2,\n        \"maxValue\":2\n    }\n}","x":480,"y":860,"wires":[](/NRCHKB/node-red-contrib-homekit-bridged/wiki/)},{"id":"e471bc3c.1151e","type":"homekit-service","z":"821a2c87.afa08","isParent":false,"bridge":"","parentService":"cb200db5.a6b7d","name":"Button 3","serviceName":"StatelessProgrammableSwitch","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{\n    \"ServiceLabelIndex\":\n    {\n        \"minValue\":3,\n        \"maxValue\":3\n    }\n}","x":480,"y":920,"wires":[](/NRCHKB/node-red-contrib-homekit-bridged/wiki/)},{"id":"64408457.fc1604","type":"inject","z":"821a2c87.afa08","name":"0","topic":"","payload":"{\"ProgrammableSwitchEvent\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":700,"wires":["7613def3.7d80d"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"7613def3.7d80d")},{"id":"2eee0f62.a2f88","type":"inject","z":"821a2c87.afa08","name":"1","topic":"","payload":"{\"ProgrammableSwitchEvent\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":740,"wires":["7613def3.7d80d"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"7613def3.7d80d")},{"id":"22d5965.1f5156a","type":"inject","z":"821a2c87.afa08","name":"2","topic":"","payload":"{\"ProgrammableSwitchEvent\":2}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":780,"wires":["7613def3.7d80d"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"7613def3.7d80d")},{"id":"2348cbc0.32e3c4","type":"inject","z":"821a2c87.afa08","name":"0","topic":"","payload":"{\"ProgrammableSwitchEvent\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":820,"wires":["2b9112bc.f268ae"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"2b9112bc.f268ae")},{"id":"adde99d3.2a0838","type":"inject","z":"821a2c87.afa08","name":"1","topic":"","payload":"{\"ProgrammableSwitchEvent\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":860,"wires":["2b9112bc.f268ae"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"2b9112bc.f268ae")},{"id":"ea7db176.764068","type":"inject","z":"821a2c87.afa08","name":"2","topic":"","payload":"{\"ProgrammableSwitchEvent\":2}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":900,"wires":["2b9112bc.f268ae"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"2b9112bc.f268ae")},{"id":"2cc3fa36.2adf8e","type":"inject","z":"821a2c87.afa08","name":"0","topic":"","payload":"{\"ProgrammableSwitchEvent\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":940,"wires":["e471bc3c.1151e"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"e471bc3c.1151e")},{"id":"feb803d2.f1e728","type":"inject","z":"821a2c87.afa08","name":"1","topic":"","payload":"{\"ProgrammableSwitchEvent\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":980,"wires":["e471bc3c.1151e"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"e471bc3c.1151e")},{"id":"ecad23a6.12434","type":"inject","z":"821a2c87.afa08","name":"2","topic":"","payload":"{\"ProgrammableSwitchEvent\":2}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1020,"wires":["e471bc3c.1151e"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"e471bc3c.1151e")},{"id":"fc1c5b0d.cd50f8","type":"homekit-bridge","z":"","bridgeName":"Irrigation","pinCode":"123-45-321","port":"","allowInsecureRequest":false,"manufacturer":"Garage","model":"Pi HAT","serialNo":"3Aplus","customMdnsConfig":false,"mdnsMulticast":true,"mdnsInterface":"","mdnsPort":"","mdnsIp":"","mdnsTtl":"","mdnsLoopback":true,"mdnsReuseAddr":true}]

Note: The number of press actions for each button can be limited by adding to the Characteristic Properties for "ProgrammableSwitchEvent": {"validValues": [0,1,2]}} - taking away 0, 1, or 2 to disable single, double, or long press respectively.

This example would only have double press and long press actions:

"ProgrammableSwitchEvent":
{
    "validValues": [1,2]
}