Make the Philips Hue Tap dial control anything in your home, using Node-RED

The Philips Hue Tap dial is an extremely versatile ZigBee remote control, ordinarily used to govern lights using the Hue system.

The device has four buttons, labeled (in what appears to be Braille but isn’t) 1 through 4, which ordinarily are used to recall scenes in the Hue system. In addition to the buttons, the Hue Tap dial also has — very apropos — a dial. This dial has very fine-grained déténtes; it clicks as you spin it, and they offer a minimal, if comfortable and reassuring resistance.

In the Home Assistant universe, the Hue Tap dial is compatible with both ZigBee4MQTT and ZigBee Home Automation. In Home Assistant’s ZHA, when you actuate the device’s buttons, the Hue Tap dial produces zha_event events . Rotation of the dial also produces up / down events, with a rotation “angle” associated to them (rotations do not produce start and end rotation events like, for example, the SYMFONISK knob from IKEA — this device’s events are discrete, more on that below in the Caveats section).

These events are directly usable in automations, but there is no support for double-tap or triple-tap of the buttons, and these types of ZHA events are cumbersome to use in automations, generally speaking. For that reason, I’ve devised a Node-RED subflow which converts raw events from the Hue Tap dial into usable messages — and it also adds double- and triple-tap functionality to the scene buttons, multiplying the amount of things you can make the dial do for you.

With this thing you can do things like use the dial to simultaneously control volume, seek your song or TV show back and forth, and also skip chapters or jump to the next song in your playlist.

Check out the full article, code for your Node-RED instance, and documentation on the node, right here:

This grew out of a need similar to what is expressed in this project:


Nice work!


Hi there,

I’ve try to implement the control but I’ve some issues:

I keep getting errors:
Deprecated API warning: Calls to RED.util.evaluateJSONataExpression must include a callback. This will not be optional in Node-RED 4.0. Please identify the node from the following stack and check for an update on npm. If none is available, please notify the node author."


at Object.evaluateJSONataExpression (/opt/node_modules/@node-red/util/lib/util.js:775:18)
at JSONataService.evaluate (/opt/node_modules/node-red-contrib-home-assistant-websocket/dist/common/services/JSONataService.js:58:39)
at TypedInputService.getValue (/opt/node_modules/node-red-contrib-home-assistant-websocket/dist/common/services/TypedInputService.js:58:85)
at EventsAll.getTypedInputValue (/opt/node_modules/node-red-contrib-home-assistant-websocket/dist/nodes/BaseNode.js:134:39)
at /opt/node_modules/node-red-contrib-home-assistant-websocket/dist/nodes/BaseNode.js:138:32
at Array.forEach ()
at EventsAll.setCustomOutputs (/opt/node_modules/node-red-contrib-home-assistant-websocket/dist/nodes/BaseNode.js:137:20)
at EventsAll.onHaEventsAll (/opt/node_modules/node-red-contrib-home-assistant-websocket/dist/nodes/events-all/controller.js:57:18)
at EventEmitter. (/opt/node_modules/node-red-contrib-home-assistant-websocket/di…

My goal is to select zone’s e.g. kitchen, hall, dining and be able to adjust the brightness of the selected zone.

Hope someone can give me a direction to look.

Thanks in advance.

Cheers, Thomas.

You sure you are feeding events to the input node? How does the event data look like?

Thanks for your reply, I had made a mistake with the events being fed in to the node. It’s all working now.

You are an absolute life saver for this. Thank you.

I’m, embarrassingly, having trouble understanding Node Red. I just want to have a Service call decrease brightness. ie brightness_step_pct:5*step_size"{{msg.payload.step_size}}". AKA - I want to change my, set by last clicked button, brightness of a light group to the step_size * x.

Not using the above Data value, just an example of what I am trying to do.

What is the best approach for this?

I got it working by feeding the button switch into a function that sets the data payload - but my lights are not smooth. I think this may be because I’m not using Local Tuya though - they will dim or brighten, then quickly adjust back and forward.

Thank you so much for your work on this. If you have any advice on making a better light dimmer please share your thoughts!

Thanks a lot for this quick-start using the device in node-red. :slightly_smiling_face:

Currently printed a kind of a „cover“ with custom button icons.

Together with my LaMetric as display, I plan to build a menu controller for lights, scenes, media and more in the living room.


I am new to the entire HA world, but this sounds exactly like what I am looking for. I just can’t figure out how to implement this.(I have no idea where to start with node-red).

Can someone make a basic tutorial of how to start using this? I tried some ZHA blueprints but they all lack functionality I am looking for. (or aren’t working as intended)

Help would be appreciated :slight_smile:

Can someone make a basic tutorial of how to start using this?

That’s what the link in the first post is.

1 Like

Wow pretty ! I may steal your idea!

Is there anyway to do this directly in Home Assistant without installing Node Red?

I suppose you could create an automation (and therefore a blueprint) that intercepts the events and implements the logic that my Node-RED flow implements for you, but it would require a bunch of helpers to remember the click timeout and state machine state.

I only did it in Node Red because I contemplated doing it in Home Assistant directly, and I failed.

Best of luck to you.

1 Like

@Rudd-O very nice and detail work, I just implanted for two bedside Tap dials, now I am trying to adjust brightness and RGB controls, just like how you had volume media control, do you have a subflow for that you can share?

1 Like

What to look for instead of ZHA events if I am using ZB2MQTT? Thanks.

You should be able to see the device inside the dropdown of a device(pink) node. Either that or the mqtt in and listen to it’s topic. Connect to a debug with it set to complete message object. Then use a switch node to break up the individual commands.

I don’t because I’m not using the Tap dial for lights, but it should be easy to have a function node that remembers the last level from 0 to 255 using context.get() and context.set(), adds or subtracts from that level based on the amount rotated (this is provided by my node), and sends that to a service call light.turn_on Home Assistant Node Red Websocket node.

Not sure how Z2M event packets look like. But I bet it’s a 1:1 transformation to what the subflow I made wants.