Monday, June 14, 2021

Use an Echo Button as a Toggle Switch

 

If you’ve used the Echo Button, you may have been disappointed like I was to find out that it’s a one-way switch. You can only use it to trigger a routine, and last I checked there isn’t a “toggle the light” routine. Well if you have one sitting around, you might be able to make use of it like I did. With Node-RED, you can use a flow to automate toggle switch functionality (and more!) for your Echo button. If you’re doing this you’ll need to make sure you have sudo/admin access to emulate an Echo device on port 80. For example with Docker you could just map an arbitrary container port to host port 80 (just like with iptables). This is the flow that I had working already, but I’ll be walking through step by step building it from scratch. For my setup I have two buttons: one on either end of my living space (bedroom connected to a home office upstairs), controlling both a Domoticz controlled device and an Alexa powered device.

 



1.       The most important thing for this to work are the node modules that both emulate/control echo devices. With Node-RED installed, click the menu icon at the top right, and select Manage palette


2.       Go to the install tab and install both of these modules: node-red-contrib-alexa-home and node-red-contrib-alexa-remote2-v2


3.       Drag and drop the controller node and the home node to the flow, and configure each.


4.       The controller configuration doesn’t need to be modified. If you are running as root/admin, and don’t have port  80 in use, you can set it to port 80 here. Otherwise you will need to forward the firewall port, for example in Linux.
sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 60000
sudo apt install iptables-persistant
sudo apt install iptables-save > /etc/iptables/rules.v4



5.       Name the device, especially if you have multiple buttons. Helps to also write a number on the bottom of the button. The type does not matter as we are not using the light features (but with this node, you could do something else neat like “turn my minecraft lights red”).



6.       You can output to the debug node to see the output at any point of the flow. Connect the node by clicking and dragging the connector icon from one node to another. Configuring the debug node can help when default debugging doesn’t quite cut it. Using complete message object is useful for capturing test payloads for writing JSONata functions (and other useful information). Debugging with msg.payload is usually fine. Using JSONata expressions you can filter the logs and format the output. Click Deploy at the top right to start the flow (and to update any time you’ve made a change). Node connection and deployment moving forward for documentation purposes is implied (you won’t be prompted to).  



7.       Discover the device by saying “Alexa, discover devices” (or using the app like I prefer when I shouldn’t have any reason to). Then in the app, toggle the newly discovered device. Here even though it shows “on” triggered true twice in a row, it seems there was a little bit of a lag for the callback to kick in after starting the flow (it later updated a lot quicker)


8.       To properly manage states a value needs to be stored. Create an inject node, and configure it to run once when the flow is started. Here, I am using payload.nvalue, which Domoticz also uses for control (but this guide does not cover that). One of the devices I am controlling with this flow uses Domoticz, so I can track the state of that device if it’s changed elsewhere. I picked the value of 1 as the default because I’m likely to be working on this stuff during the day when the lights are already on.

9.       Create a change node. Create a rule to set a flow value to the value specified in the inject node. This value is referenced later in the flow.


10.   On the Domoticz side, we have an MQTT node subscribing to the domoticz/out topic, a JSON node to convert the payload into an object, and a switch node, which only passes through the payload if it’s the Domoticz device specified. That completes the “initialization” part of the flow. One could feasibly include some nodes to manage the callback state of the virtual device on the Alexa side, but if you’re going to do that you may as well track the state of that light you’re controlling as well (playing better with voice commands). Otherwise, it’s no more than a couple button presses to sync the lights back to a given state.


11.   Create a change node. This is where *it* happens. You know, the thing. JSONata, what did you think I was talking about? I went into writing JSONata functions in one of my earlier entries. For ease of use an inject button is added to the flow to allow easy development. Also, being that not everyone uses Domoticz, I’ve adapted the flow by disconnecting my MQTT node, and adding a rule to update the flow value. 1) Delete msg.payload. This has to happen a lot of times because errors or other unexpected things can happen. If you need to work with the data from the payload in the same change node, just store it in msg.tmp or something, delete the payload, then do the thing. 2) The IDX is configured but this is for Domoticz only. 3) This JSONata function is used to invert the flow value. 3) The flow value is updated with the inverted value and passed to the next node(s)
$number($not($flowContext("button1"))) 

 

12.   For Domoticz all that is needed is to package up the payload into JSON format, and zap it over to MQTT. The device status gets updated on the Domoticz switch page. To toggle an Alexa controlled device, we are almost ready to call the node for that, but we need another change node (this could be consolidated into the same change node if you’re not using Domoticz). 1) The payload is stored in msg.tmp like previously mentioned, then deleted. 2) The remote control node expects a payload array, so make a rule for msg.payload[0].entity and leave it blank for now. 3) The JSONata conditional function needing to convert the boolean value to the control commands.
tmp.nvalue=1 ? "turnOn" : "turnOff"




13.   Add an Alexa Smarthome node to the flow



14.   Add an account, configuring as such that the authorization cookie can be stored in the text file. You may have to troubleshoot permissions if you don’t see the cookie data being stored in the file.



15.   Select one of the devices from your account and select a command so that we can fetch the ID.





16.   Use an inject node to trigger the remote node, and pipe that to your debug mode (complete message object). You now have your entityID. Paste it into the change node from earlier.



17.   Delete the command you used to fetch the ID, and deploy



18.   Your final product should now be an Alexa device that when triggered by a routine that is triggered by your Echo button, will toggle your Alexa powered light, even though it’s not technically supported.



19.   My Domoticz logs for the device show the activity, and the Alexa powered device I selected seems to reliably trigger when using an Echo button to trigger the routine

 

The takeaway: at a minimum, the Echo button can be used as a toggle button if you want it to. In reality, it could be used for a lot of things. Using a message router node (round robin) you could have a set of lights cycle through RGB colors (I didn’t have the ability to control Alexa powered devices years ago when I set this up). Instead of using the message router node, you could also use an array and a JSONata function to cycle through the values (I did both of these a while back with some AiLight custom firmware powered bulbs but did not save the flows). Also you could feasibly set up a rainbow mode, but if you’re triggering your lights to change with the Amazon API many times per minute, hours on end, I can’t speak towards that (rate limiting of the lambda functions behind the scenes; high usage may draw attention). In that case I would recommend getting some smart bulbs with the “rainbow mode” feature.

Don't forget to backup your flows! Menu -> Export -> All flows -> Download



No comments:

Post a Comment