Stream Deck and Node Red

Hey Everyone-

I started using a Stream Deck for various key short-cuts for use around my house. My particular Stream Deck (SD+) has 4 dials that I"d love to use one of them for Denon AVR Volume control. In Node-Red for Stream Deck, there’s a Websocket plug-in - I’ve installed this and have gotten it to work, but where I’m stuck is in DialRotate.

DialRotate when the payload outputs in Node-Red just shows up as “DialRotate” with no indication of clockwise turn or counter-clockwise turn. In the Stream Deck documentation, it mentions that this is determined by the value set (positve or negative) for DialRotate that determines this.

I guess that’s my problem, if I’m to utilize “media_player.set_volume” how do I set it to go louder on a clockwise turn and quiter on a counter-clockwise turn?

I’m clearly missing something obvious, but any help would be greatly appreciated.

Sometimes when you keep digging, you figure it out! Here’s the solution for those interested:

  1. Download and Install the StreamDeckWS plugin for Stream Deck
  2. In Stream Deck, you’ll see under “Custom” Plugins anitem called “WSProxy”
  3. Drag and drop “WSProxy” to your Dial of choice in the Stream Deck

Configuring the Dial in Stream Deck:

  1. Leave “Title” Blank
  2. Under Websocket, put in your IP address (and port) of your Node-Red Instance in this manner:

ws://NODE-RED-IP-ADDRESS:PORT/PUT-IN-A-NAME-HERE-NO-SPACES (remember this part)

If your Node-red instance is in a secure http, then use wss:// instead

  1. id: Button/Dial Name (no spaces)

Node Red Side:

[{"id":"00cc2c946dcebb57","type":"tab","label":"Stream Deck","disabled":false,"info":""},{"id":"c5d6c874a8a41abb","type":"server-state-changed","z":"00cc2c946dcebb57","name":"What time is it?","server":"6c17af13d9cffd63","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"sensor.time","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":200,"y":1020,"wires":[["dad58c38a0512165"]]},{"id":"dad58c38a0512165","type":"debug","z":"00cc2c946dcebb57","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":430,"y":1020,"wires":[]},{"id":"25b029c396551ae0","type":"sd-input","z":"00cc2c946dcebb57","name":"Stream Deck In","x":340,"y":220,"wires":[["d35430b5769a85c6"]]},{"id":"08c478a655877662","type":"debug","z":"00cc2c946dcebb57","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":140,"y":500,"wires":[]},{"id":"83d99d744371a03f","type":"websocket in","z":"00cc2c946dcebb57","name":"","server":"d4e3635399790eeb","client":"","x":90,"y":80,"wires":[["90e730e93445d502","25b029c396551ae0"]]},{"id":"90e730e93445d502","type":"json","z":"00cc2c946dcebb57","name":"","property":"payload","action":"","pretty":false,"x":310,"y":80,"wires":[["56059ed21088ba8b"]]},{"id":"56059ed21088ba8b","type":"change","z":"00cc2c946dcebb57","name":"","rules":[{"t":"set","p":"payload.ticks","pt":"msg","to":"payload.ticks","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":80,"wires":[["1e3dd75680478213"]]},{"id":"1e3dd75680478213","type":"switch","z":"00cc2c946dcebb57","name":"","property":"payload.payload.ticks","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"num"},{"t":"eq","v":"-1","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":910,"y":220,"wires":[["4624ba1268769dc1"],["bbfda7943f73696e"]]},{"id":"48f56eb4a8b37681","type":"api-call-service","z":"00cc2c946dcebb57","name":"Mute","server":"6c17af13d9cffd63","version":5,"debugenabled":false,"domain":"media_player","service":"volume_mute","areaId":[],"deviceId":[],"entityId":["media_player.denon_3"],"data":"{ \"is_volume_muted\": \"True\" }","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1070,"y":380,"wires":[[]]},{"id":"d35430b5769a85c6","type":"change","z":"00cc2c946dcebb57","name":"","rules":[{"t":"set","p":"context","pt":"msg","to":"payload.context","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":300,"wires":[["3491f68bd7d26883"]]},{"id":"3491f68bd7d26883","type":"switch","z":"00cc2c946dcebb57","name":"","property":"payload.event","propertyType":"msg","rules":[{"t":"eq","v":"dialRotate","vt":"str"},{"t":"eq","v":"dialDown","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":710,"y":300,"wires":[[],["0c5f632aa6daa96b"]]},{"id":"0c5f632aa6daa96b","type":"api-current-state","z":"00cc2c946dcebb57","name":"State of Mute","server":"6c17af13d9cffd63","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.denon_source_3","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":650,"y":420,"wires":[["a74bf2f12b1ce589"]]},{"id":"a74bf2f12b1ce589","type":"switch","z":"00cc2c946dcebb57","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"False","vt":"str"},{"t":"eq","v":"True","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":850,"y":420,"wires":[["48f56eb4a8b37681"],["8d9587a4b0def1c1"]]},{"id":"8d9587a4b0def1c1","type":"api-call-service","z":"00cc2c946dcebb57","name":"Un-Mute","server":"6c17af13d9cffd63","version":5,"debugenabled":false,"domain":"media_player","service":"volume_mute","areaId":[],"deviceId":[],"entityId":["media_player.denon_3"],"data":"{ \"is_volume_muted\": \"False\" }","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1080,"y":440,"wires":[[]]},{"id":"4624ba1268769dc1","type":"api-call-service","z":"00cc2c946dcebb57","name":"Volume Up","server":"6c17af13d9cffd63","version":5,"debugenabled":false,"domain":"media_player","service":"volume_up","areaId":[],"deviceId":[],"entityId":["media_player.denon_3"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1130,"y":200,"wires":[[]]},{"id":"bbfda7943f73696e","type":"api-call-service","z":"00cc2c946dcebb57","name":"Volume Down","server":"6c17af13d9cffd63","version":5,"debugenabled":false,"domain":"media_player","service":"volume_down","areaId":[],"deviceId":[],"entityId":["media_player.denon_3"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1140,"y":260,"wires":[[]]},{"id":"6c17af13d9cffd63","type":"server","name":"Home Assistant","version":5,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"d4e3635399790eeb","type":"websocket-listener","path":"/sd-demo","wholemsg":"false"}]
  • When you set up your first node, the node will ask for a “path” - the path is the item (Bolded and underlined):

ws://NODE-RED-IP-ADDRESS:PORT/PUT-IN-A-NAME-HERE-NO-SPACES (remember this part)

  • The item in bold is your “Path” - be sure to put in a forward slash in the begining (aka: /NameofNode)

I am certain my Node red “coding” is HIGHLY inefficient, and I"m sure (actually hoping) someone will make a better and more efficient version, but it works!

The Node-Red flow that I shared does both volume control and mute/un-mute (when you press on the dial as a button).

1 Like