mqtt and Homekit for Shelly Dimmer

This flow can control the Shelly Dimmer and sets the user interface accordingly.

The flow does multiple things:

  1. It sets the values using Homekit or Node-RED UI and send the mqtt commands.
  2. It listens to the mqtt commands and set the switches and dimmer values in the Home app & Node-RED UI accordingly.
  3. It prevents an infinite loop which seems to be a feature of homekit-service.
  4. You can use the software slider / dimmer.
  5. You can use your light switch (hardware or in the user interface) to change the dimmer level to 4 presets values by doing a on/off/on sequence within 2 seconds.

This flow has some custom javascript because that is my preferred way to handle the message (msg) flow. As you will see, I prefer to set the msg.topic within my function node.

The device in this example is called hanglamp (which is Dutch for ceiling light or hanging lamp). Personally I use a text editor to rename the device in the JSON file to give it a new name. I guess using an inject node could also work.

Let me know if you have improvements.

Have fun,

Bas Nelissen

[{"id":"7a868da3.b1a744","type":"ui_slider","z":"4d2d578e.6cea28","name":"hanglamp slider","label":"","tooltip":"","group":"efa9c015.d79758","order":2,"width":4,"height":1,"passthru":false,"outs":"end","topic":"shellies/hanglamp/light/0/set","min":"0","max":"100","step":"5","x":1060,"y":920,"wires":[["83e1023e.62b47"]]},{"id":"83e1023e.62b47","type":"function","z":"4d2d578e.6cea28","name":"brightness2mqtt","func":"brightness = msg.payload;\nmsg.payloadold = msg.payload;\n// set the brightness, turn the light on\nmsg.payload = {\n    \"turn\": \"on\",\n    \"brightness\": + brightness\n};\nreturn msg;","outputs":1,"noerr":0,"x":1280,"y":920,"wires":[["ffafc6ee.6ee4d8"]]},{"id":"ef232119.ab0b48","type":"mqtt in","z":"4d2d578e.6cea28","name":"hanglamp","topic":"shellies/hanglamp/light/0/status","qos":"0","datatype":"auto","broker":"707b233c.d0ad2c","x":170,"y":860,"wires":[["a8896a13.25a638"]]},{"id":"d79687d2.b1629","type":"function","z":"4d2d578e.6cea28","name":"prep switch","func":"lightOn = msg.payload.ison;\nif (lightOn){\n    msg.payload = 'on';\n}else{\n    msg.payload = 'off';\n}\nreturn msg;","outputs":1,"noerr":0,"x":850,"y":860,"wires":[["e754c3c8.e50cf"]]},{"id":"a8896a13.25a638","type":"json","z":"4d2d578e.6cea28","name":"","property":"payload","action":"","pretty":false,"x":310,"y":860,"wires":[["46614d53.ed2fb4"]]},{"id":"b50a4b62.45e34","type":"mqtt out","z":"4d2d578e.6cea28","name":"","topic":"","qos":"","retain":"","broker":"707b233c.d0ad2c","x":1450,"y":860,"wires":[]},{"id":"ffafc6ee.6ee4d8","type":"mqtt out","z":"4d2d578e.6cea28","name":"","topic":"","qos":"","retain":"","broker":"707b233c.d0ad2c","x":1450,"y":920,"wires":[]},{"id":"cb558f65.bcf9b","type":"homekit-service","z":"4d2d578e.6cea28","isParent":true,"bridge":"93e1fd.7adf2e","parentService":"","name":"hanglamp","serviceName":"Lightbulb","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","cameraConfigVideoProcessor":"ffmpeg","cameraConfigSource":"","cameraConfigStillImageSource":"","cameraConfigMaxStreams":2,"cameraConfigMaxWidth":1280,"cameraConfigMaxHeight":720,"cameraConfigMaxFPS":10,"cameraConfigMaxBitrate":300,"cameraConfigVideoCodec":"libx264","cameraConfigAudioCodec":"libfdk_aac","cameraConfigAudio":false,"cameraConfigPacketSize":1316,"cameraConfigVerticalFlip":false,"cameraConfigHorizontalFlip":false,"cameraConfigMapVideo":"0:0","cameraConfigMapAudio":"0:1","cameraConfigVideoFilter":"scale=1280:720","cameraConfigAdditionalCommandLine":"-tune zerolatency","cameraConfigDebug":false,"cameraConfigSnapshotOutput":"disabled","cameraConfigInterfaceName":"","characteristicProperties":"{ \"Brightness\":true }","x":1040,"y":980,"wires":[["385ad340.901afc"],[]]},{"id":"e20da7d6.c777e8","type":"function","z":"4d2d578e.6cea28","name":"prep homekit","func":"// set variables known by Homekit\nmsg.prev = msg.payload;\n\nif(msg.prev.ison){\n    msg.prev.on = 1;\n}else{\n    msg.prev.on = 0;\n}\n\nmsg.payload = {\n    \"On\": + msg.prev.on,\n    \"Brightness\": + msg.prev.brightness\n}\nreturn msg;","outputs":1,"noerr":0,"x":850,"y":980,"wires":[["cb558f65.bcf9b"]]},{"id":"e754c3c8.e50cf","type":"ui_switch","z":"4d2d578e.6cea28","name":"","label":"hanglamp","tooltip":"","group":"efa9c015.d79758","order":1,"width":2,"height":1,"passthru":false,"decouple":"true","topic":"shellies/hanglamp/light/0/command","style":"","onvalue":"on","onvalueType":"str","onicon":"","oncolor":"","offvalue":"off","offvalueType":"str","officon":"","offcolor":"","x":1040,"y":860,"wires":[["b50a4b62.45e34"]]},{"id":"48cb8aa0.e6cfbc","type":"mqtt out","z":"4d2d578e.6cea28","name":"","topic":"","qos":"","retain":"","broker":"707b233c.d0ad2c","x":1450,"y":980,"wires":[]},{"id":"385ad340.901afc","type":"function","z":"4d2d578e.6cea28","name":"home2mqtt","func":"// the message from homekit is either the brightness, or if it is on.\n// when the brightness changes also put the light on\n// when on/off changes, do not change the brightness\n// for anything else just turn it off as a default exit case (which should never happen)\n\nmsg.payloadold = msg.payload;\nmsg.topic = 'shellies/hanglamp/light/0/set';\n\n// set the brightness if it exists\nbrightness = msg.payload.Brightness||false;\n\n\nstatus = msg.payload.On\n\nif(brightness){\n    msg.payload = {\n        \"turn\": \"on\",\n        \"brightness\": + brightness\n    }\n}else if(status){\n    msg.payload = {\n        \"turn\": \"on\"\n    }\n}else{\n    msg.payload = {\n        \"turn\": \"off\"\n    }\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":1290,"y":980,"wires":[["48cb8aa0.e6cfbc"]]},{"id":"46614d53.ed2fb4","type":"function","z":"4d2d578e.6cea28","name":"loop detection and auto dimmer","func":"// B. Nelissen\n// Loop detection and dimmer preperation\n\n// timeouts\nlet msLoopDetection = 100;\nlet msWithinDimming = 2000;\nlet currentTime=Math.round(Date.now());\n\n// setting variables\nlet previousTime=context.get('time') || 0;\nlet previousIson=context.get('ison') || false;\nlet timeDifference=currentTime-previousTime;\n\n// catch loop and exit\nif (msLoopDetection > timeDifference) return;\n\n// dimmer function\nfunction changeBrightness(brightness) {\n    var step0 = 5;\n    var step1 = 30;\n    var step2 = 55;\n    var step3 = 100;\n    if (!(brightness >= 0 && brightness <= 100)) {\n        node.warn('Invalid brightness, set to 42')\n        brightness=step1;\n    }\n    switch (true) {\n        case (brightness < step0):\n            brightness=step0;\n            break;\n        case (brightness < step1):\n            brightness=step1;\n            break;\n        case (brightness < step2):\n            brightness=step2;\n            break;\n        case (brightness < step3):\n            brightness=step3;\n            break;\n        default: // when 100\n            brightness=step0;\n    }\n    return brightness;\n}\n\n// dimmer when state goes from OFF to ON\nif(msg.payload.ison && (msg.payload.ison !== previousIson)){\n    switch (true) {\n        case (msLoopDetection > timeDifference): // loops should be catched already\n            msg = null;\n            break;\n        case (msWithinDimming > timeDifference): // dimmer\n            msg.payload.brightness = changeBrightness(msg.payload.brightness)\n            break; \n      default: //do nothing\n            break;\n    }\n}\n\ncontext.set('time',currentTime);\ncontext.set('ison',msg.payload.ison);\nreturn msg;","outputs":1,"noerr":0,"x":530,"y":860,"wires":[["d79687d2.b1629","e20da7d6.c777e8","fb1435fa.0a159"]]},{"id":"fb1435fa.0a159","type":"change","z":"4d2d578e.6cea28","name":"prep brightness","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.brightness","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":860,"y":920,"wires":[["7a868da3.b1a744"]]},{"id":"c7c574bf.0c3698","type":"inject","z":"4d2d578e.6cea28","name":"","topic":"shellies/hanglamp/light/0/command","payload":"on","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":980,"wires":[["6406408e.e87808"]]},{"id":"61f2fe69.492a88","type":"inject","z":"4d2d578e.6cea28","name":"","topic":"shellies/hanglamp/light/0/command","payload":"off","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"1","x":170,"y":920,"wires":[["7455ea6e.a48244"]]},{"id":"7455ea6e.a48244","type":"mqtt out","z":"4d2d578e.6cea28","name":"","topic":"","qos":"","retain":"","broker":"707b233c.d0ad2c","x":470,"y":920,"wires":[]},{"id":"6406408e.e87808","type":"mqtt out","z":"4d2d578e.6cea28","name":"","topic":"","qos":"","retain":"","broker":"707b233c.d0ad2c","x":470,"y":980,"wires":[]},{"id":"efa9c015.d79758","type":"ui_group","z":"","name":"Woonkamer","tab":"f529ddcc.a47f8","order":1,"disp":true,"width":"6","collapse":false},{"id":"707b233c.d0ad2c","type":"mqtt-broker","z":"","name":"serverPi","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","willTopic":"","willQos":"0","willRetain":"false","willPayload":""},{"id":"93e1fd.7adf2e","type":"homekit-bridge","z":"","bridgeName":"server Home","pinCode":"111-11-111","port":"","allowInsecureRequest":false,"manufacturer":"server","model":"Model","serialNo":"Serial Number","customMdnsConfig":false,"mdnsMulticast":true,"mdnsInterface":"","mdnsPort":"","mdnsIp":"","mdnsTtl":"","mdnsLoopback":true,"mdnsReuseAddr":true,"allowMessagePassthrough":true},{"id":"f529ddcc.a47f8","type":"ui_tab","z":"","name":"Lichten","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

Flow Info

Created 4 years, 11 months ago
Updated 4 years, 7 months ago
Rating: not yet rated

Owner

Actions

Rate:

Node Types

Core
  • change (x1)
  • function (x5)
  • inject (x2)
  • json (x1)
  • mqtt in (x1)
  • mqtt out (x5)
  • mqtt-broker (x1)
Other
  • homekit-bridge (x1)
  • homekit-service (x1)
  • ui_group (x1)
  • ui_slider (x1)
  • ui_switch (x1)
  • ui_tab (x1)

Tags

  • shelly
  • dimmer
  • ui
  • homekit
  • homekit-service
  • mqtt
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option