Android and Linux

Tuesday, January 4, 2011

Heyu home automation toggle for Tasker

(To my regular Android visitors, much of this has been posted here before, but I wanted to put it all together for any X10 users who stumble across it. Although it is related to specific home automation software, it might still be interesting to Tasker users too.)

If you're using X10 home automation devices at home, there are a few apps for controlling them on your Android phone, but if you don't mind using ssh and controlling your X10 from the command line, there are ways to make control your home for free. And, if you want to use an Android app called Tasker, it can be even more powerful that anything on the Market.

This will only concentrate on the simple stuff, how to get Tasker to control Heyu and how to make icons to imitate an X10 app. Tasker can perform so many other functions, like turning on your security system or opening your garage door when you reach certain GPS coordinates, that I don't want to touch on them here.

So, let's do the "simple" stuff. It may look crazily hard but it's not once you're familiar with Tasker/Heyu/X10. It took me 15 minutes to do all of this, another 45 to test workarounds to a Tasker bug, and like two hours of off-and-on writing to actually make the stinking post!

The first goal is to get Heyu running on your computer to control your X10 modules. I'll leave that to the reader because it was dead simple for me so my experience consists of "just install and run it". After that, we need to get ssh keys working and place the ssh key on the phone so you can log into the PC from the phone. There are many how-tos for setting up ssh keys so I won't get into that here either, but you may want to check this post for links that may help.

You should test your ssh logins with a terminal app on the phone. It's probably easiest to test the basic ssh command first:


Once you login (and exit) successfully with that, try something like this to bounce a command off your PC:


That executes what I usually call a 'semi-login'. It uses the keys to log in, run the command and exit. Any output from the command on the PC will be shown in the terminal on your phone. Once that is working, let's make sure an x10 command works:

ssh USER@IP -i /PATH/TO/SSH/KEY "heyu on a1"

Now, you will probably want to put it in a script so you don't have to type it out all the time. I suggest changing the basic command to this first:

ssh USER@IP -i /PATH/TO/SSH/KEY "heyu $*"

That will log into your computer and run heyu with whatever arguments you give it on the command line. If the two arguments are "on a1" it will tell heyu to turn on a1. If they are "dim b2 10", it will tell heyu to dim b2 by level 10.

There are a couple of ways to use this as a script. If you're rooted, you can put the command in a file, add "#! /system/bin/sh" to the top and place the file in /system/bin. It can now be executed by typing the script name. I prefer doing this because it can be executed system-wide by any app.

If you're not rooted, you can put the command in a text file on the sdcard and run "sh /sdcard/filename"

I use the first method, and I'll call the script "ha" so, if you use the second method, anytime you see me executing "ha" just substitute "ha" with "sh /sdcard/filename"

Now that we have a command that works, let's put it to practical use. Using Tasker and it's free plugin named "Locale Execute Plugin", you can set up your commands to run from Tasker. All you have to do is create a new task, select "plugin", "execute" and type in your command.

Now, there are two approaches you can take, or a mixture of both if you wish. You can create widgets or shortcuts to Tasker tasks, so you can set up an "on" task and an "off" task for each X10 module, then put the shortcuts on the home screen. Or, as I prefer to do when using this approach, you can use Folder Organizer to group them all together in their own Heyu folder.

Another approach is to create on/off toggles for each module with icons to reflect the modules state. You first need a script on the PC to interpret the incoming command and dump a list of the on/off/dim state of all your modules to a file so Tasker can grab that file and update it's icons to reflect the state of the module.

Here's the script for the PC. Call it anything, but I'll name it "toggle" for this example. It performs two functions. First, it toggles the module you want to switch on/off. It checks, and if the module is on, it turns it off, and vice versa.

Secondly, it takes the overall state of the housemap from "heyu show h" and maps all the on/offs to a list of modules you want to keep track of. If you notice the last two lines, I am keeping track of j2 and b1. These would correspond to the Tasker icons that you want to update to reflect the on/off state of the modules. This info is stored in a file named "/etc/heyu/toggle.list"

(edited: Jan 9. Oops, I changed the custom "awkc" command to a
non-custom awk print command that will work for everyone)

#! /bin/sh
# don't knock the code! I prefer "compact" to "proper"

cd /etc/heyu
rm toggle.list
state=$(heyu onstate "$1")
if [[ $state == 1 ]]; then heyu off "$1"
elif [[ $state == 0 ]]; then heyu on "$1"

stat ()
house=$(expr substr "$1" 1 1)
unit=$(expr substr "$1" 2 1)
t=$(heyu show h | grep House | awk '{ print $3,$2 }' | tr -d '()')
onoff=$(expr substr $(echo "$t" | grep -i "$house" | awk '{ print $1 }') "$unit" 1)

if [[ $onoff == \* ]]; then echo ${house}${unit} on >> toggle.list
elif [[ $onoff == x ]]; then echo ${house}${unit} dim >> toggle.list
else echo ${house}${unit} off >> toggle.list; fi

# List all modules you want to track here in the form of: "stat Hu"
# j2 and b1 are examples

stat j2
stat b1

# end

Now, we need a script on the phone to interact with the script on the computer. Let's call it "atoggle." This will connect to the PC and toggle the module, then copy the toggle.list file to the phone over scp.
#! /system/bin/sh
ssh USER@IP -i /PATH/TO/SSH/KEY "toggle $1"
scp -i /PATH/TO/SSH/KEY COMPUSER@IP:/etc/heyu/toggle.list /sdcard/Tasker/
Using j2 and b1 as examples, with Tasker, you want to create two new tasks to use the execute plugin to execute to following two commands:

atoggle j2
atoggle b1

Back on the home screen, create new widgets for both those tasks and name them by their house/unit code. I suggest picking icons that will not indicate whether the modules are on or off because the icons will be changed to reflect the state later. Here is an example of the icons I picked.

Now, let's set up a Tasker task to update the icons. This started out as an elegant task that tested well but upon real execution the task outran the scp command and ran before the file was transferred. Tasker is really poor at reading files so the first five lines are there just to pause the task until the file transfer is complete. It's completely illogical, but it works and is necessary and, trust me, you will go crazy trying to find an alternative! Just a quick explanation of what's going on in the first five lines: set the variable to tell it which line to read, overwrite the original file with "WAIT", copy it to a separate file because it messes up later reads if you start reading the original, read it and start over if the file still contains "WAIT."

1- Variable Set %ONE to 1
2- Write File Tasker/toggle.list. Text: WAIT
3- Copy File Tasker/toggle.list to Tasker/toggle.list2
4- Read Line. File: Tasker/toggle.list2 Line: %ONE to Var %WAIT
5- Go To Action 3 if %WAIT matches WAIT

6- Read Line. File: Tasker/toggle.list to Var %VAR
7- Variable Split. %Var
8- Set Widget Icon. Name: %VAR1 if %VAR2 matches on (pick an "on" icon)
9- Set Widget Icon. Name: %VAR1 if %VAR2 matches off (pick an "off" icon)
10- Set Widget Icon. Name: %VAR1 if %VAR2 matches dim (pick a "dim" icon)
11- GoTo Action: Number 1. If %VAR doesn't match EOF

Those last 6 lines are the real meat of the task and are rather elegant if you understand Tasker. Edit: I forgot to mention, you need to name that task and add it to the "atoggle j2" and "atoggle b1" tasks. So step 1 for each module would be execute the atoggle command and step two would be to perform the task I just mentioned to read the file.

Ok, let's walk through everything we've learned. You have two icons, j2 and b1 which are set to "neutral." In reality, both modules are on. When you click the j2 icon, Tasker executes "atoggle j2." This uses ssh to connect to your computer and run "toggle j2".

The toggle script checks if j2 is on or off and sets it to the opposite, then gets the state of all 256 modules and filters out the ones you are interested in (the ones placed near the bottom of the toggle script on the PC), then puts their state in toggle.list. Tasker uses scp to transfer toggle.list to the phone then reads all the lines, checking the module and changing it's icon to reflect it's state.

If j2 and b1 were both on and I toggled j2, the end result is this:

j2 has been toggled off and both icons have been updated to reflect their state.

If you followed all that, you hopefully understand how it all worked. But you may wonder why I update all modules if you're only toggling one? Well, although tapping the icons only blindly toggles the module, looking at it will tell you if it's on or off. I update all icons because some modules may have been turned on/off through other means. It's always possible that the icon you tap is in the wrong state, but by updating all icons every time any icon is clicked, it lessens the chances that an icon will be "out of date."

You may want to create a task just to update the status of all modules. You can create your own, or you can just run "atoggle" on a dummy module that you don't use. Just leave it out of the end of the "toggle" script on the PC so Tasker won't track it's status.

If you want to add modules that may be in a dimmed state, the script does report them so you only need to select an icon for "dim." In this image, j2 is in a dimmed state.

If you use dimming but only want to report off/on states, just select the same icon for dim as you use for "on."

If you want to create an icon that dims a module instead of simply turning it on and off, you can use the information in this post and my previous post to set up a new task for dimming.

Phwew, I hope this is useful for someone!