Android and Linux

Sunday, January 16, 2011

61 minute cron

It seems like everyone who uses cron to schedule jobs in Linux eventually runs into a problem where they need to schedule a command at odd intervals, like 61 minutes. Cron can easily run every hour, but 61 minutes is harder to achieve.

The normal methods include using a sleep command or various rather elaborate methods in the script itself to fire off every 61 minutes.

A much simpler method is using cron's cousin, the at command. The at command will run through a file and run all the commands inside, so you just need to place the commands in a file, one per line, then add this line to the bottom of the file:
at now + 61 minutes < file
The commands can be any type of one-liner you want to use.

Here is an example. Call this file foo and to kick off the execution the first time, you can simply run: sh foo
date >> ~/foo_out
cd ~/tmp && rm *
at now + 61 minutes < ~/foo
That will output the date and time to ~/foo_out then move to a tmp directory and clean out files, then tell the at command to run itself again in 61 minutes which will again run the at command after executing the rest.

Tasker command runner

The Locale Execute Plugin is great for running shell commands or scripts with Tasker, but it can be tedious when you're testing the commands. It takes several steps to edit tasks themselves, and even if you don't need to edit the task, you still have to get to the editing error to change the command in the plugin.

There is a way to make it easier.

Profile/Context : Variable Set. Variable %COMMAND

Task:
1- Write File /sdcard/command %COMMAND
2- Execute: sh /sdcard/command

Or if you'd like to get the output of the command:

Task:
1- Write File /sdcard/output WAIT
2- Write File /sdcard/command %COMMAND
3- Execute: sh /sdcard/command
4- Read Paragraph: /sdcard/output to %OUTPUT
5- Go To 4 if %OUTPUT matches WAIT
6- Flash %OUTPUT if %OUTPUT doesn't match EOF
7- Variable Clear %COMMAND

Just make sure your command sends it's output to that file.

Now you only need to set the variable %COMMAND with the actual command you want to use. When the variable is set, Tasker will write the command into the file and the plugin will execute it.

You could even set the command by popping up a list to choose from, or by using the Variable Query which allows you to type a variable's contents into a box.

Security:

I wouldn't consider it very safe to have a file in which commands can be entered by anyone and ran, possibly with root permissions. But the first step of the task is to overwrite the file, so I suppose a person would have to be able to control Tasker in order to get their code executed, and if they can do that, they already have free reign anyway, so it's probably fairly safe.

Sunday, January 9, 2011

Example Tasker Home Automation profile

I'm still pretty new to home automation, but have been coming home late the past few days to a dark house, so let's turn on some lights with Tasker. This assumes you're using Heyu/Linux and ssh, as in my previous post.

This may need some tweeks, I just came up with it tonight and haven't tested it. It would probably be more useful with a Tasker location profile, but I don't actually use any location profiles. When I drive into the garage, as long as my phone's screen is on and unlocked, it automatically connects to my home wifi. When I remove it from the car dock, the screen comes on and it connects to wifi, so I'm using wifi as my trigger instead of a location. If you use a location profile, adjust accordingly.

First, there's no reason to turn on a lot of lights at noon, so we need to know if it's dark when you get home.

Set up a new time based profile called Night. Set "From" and "To" to the times when it is dark where you live. Then make the entry task for the Night profile: Set Variable %NIGHT to "yes", and as an exit task: Set Variable %NIGHT to "no".

The variable should change at dusk and dawn every day, although you may need to adjust it every few weeks.

Now it's as simple as having your trigger check the variable and turning on the lights if it is dark. In my case "wifi connected" is the trigger, but maybe location or "cell near" is better for others. Since I used j2 and b1 in my last post as example X10 modules, I'll stick to them here. Under the wifi connected profile, I'd add:

Perform Task: j2 if %NIGHT matches: yes
Perform Task: b1 if %NIGHT matches: yes

And hopefully the lights will come on when I get home... if it's night.

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:

ssh USER@IP -i /PATH/TO/SSH/KEY

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

ssh USER@IP -i /PATH/TO/SSH/KEY "COMMAND"

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"
fi

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!

Monday, January 3, 2011

Tasker variable select function

I had a task where I wanted to be able to enter a custom number into a variable. Tasker has a "variable Query" action that pops up a box and allows you to type in the variable, but I didn't like it because you have to tap on the box to bring up the keyboard, type out the entry, then save it. But a workaround is simple, as long as you know certain values the variable could be.

Task: VarMenu1
1 Variable Set %VAR to EOF (you could use 'variable clear' but I prefer using EOF since errors will sometimes manifest as EOF)
2 Perform Task VarMenu2
3 Wait Until %VAR doesn't match EOF

Task: VarMenu2
Task Type: Menu
1 Set Variable %VAR to 0
2 Set Variable %VAR to 1
3 Set Variable %VAR to 2
4 Set Variable %VAR to 3
...etc (change numbers to suit your needs)

Used alone, VarMenu1 acts like a function or library, a piece of code that you can leave by itself and call any time you need to perform a certain task, in this case custom setting a variable. Any time you're writing a task that requires you to input a custom value for a variable, just put "Perform Task: VarMenu1" and your task will pause to allow you to select a value from a list.

You can also use variables for task names when using the "Perform Task" action. This would be useful if you want to prepare more than one menu of variables. Instead of 0,1,2,3, maybe you also want to have a menu for 0,5,10,20. Just make a new menu task containing those numbers, let's call it VarMenu3, change the "Perform Task" in VarMenu1 to a variable and set the variable before that step.

1 Variable Set %VAR to EOF
2 Variable Set %VARMENU to VarMenu3
3 Perform Task %VARMENU
4 Wait Until %VAR doesn't match EOF

Voila, flexibility!

Tuesday, December 28, 2010

X10 coolness

I've been slowly getting into X10 home automation lately. It works like this, you get an X10 control module that plugs into the wall near the computer and a cable comes from it and plugs into your computer. Then you get software to control the control module. The control module controls whatever other modules you want to use throughout the house.

The most basic module is the lamp module, which is a small box that plugs into a wall outlet, then your lamp plugs into the module. From the computer, you tell that module to turn on or off.

What happens is that the control module sends a special signal through the wires in your house. The signal is picked up by all the X10 modules you have. The modules themselves have dials where you can select identification letters and numbers on them. You take a module and select, let's say, B4, so that module is now identified as B4. When you send the signal "B4 on," it turns itself on, which turns the lamp on.

There are numerous different modules to do different things. There are wall switches, modules for plug-in electronics like the lamp module and a similar appliance module, security modules, camera modules, dimmers, timers, weather sensors. Anything you can think of, the possibilities are endless.

You can also use them with remote controls and there are a few apps in the Android Market to run them from your phone, but I like setting them up to control from my phone over ssh. There is a Linux program called Heyu for use with the CM11A control module. Heyu can perform nearly two hundred different commands and uses simple command line syntax like heyu on B4. This makes it extremely simple to script, which in turn makes it extremely simple to control through the phone using the basic ssh command I've posted many times:

ssh USER@IP -i /PATH/TO/SSH/KEY 'heyu on B4'

This can be set up as a script to be ran from a terminal, through a GScript shortcut, or with Tasker. Of course, Tasker and X10 make an extremely useful pair.

I really haven't set much up yet except to manually turn a couple of lights on. I plan on getting a module to control the garage door next. This is done by using a "universal module" that acts like a single state button instead of an on/off switch. When the module is activated, it just does it's thing once and there is no way to reverse it. Every time it is activated, it is the same as pushing the garage door opening button so there is no way to know if it is up or down.

I plan to set it up with Tasker to activate it when I am close to home so the door will be open by the time I pull into the driveway. I'm not sure how reliable that will be, so I'll probably add a statusbar reminder that the door is open in case it is activated accidentally.

I've also considered getting a camera for the front door and a doorbell sensor. When someone rings the doorbell, the computer could tell the camera to take a photo then send it to me via MMS. If it looks like someone trying to sell something, I can ignore them. If it's a family member with a birthday present and I'm at work, I can open the garage door so they can come in.

I have no plans to do this, but this would be a cool setup...

Send a notification to the phone when the door is open

Have Tasker silence/ignore the notification if I'm at home and end the task.

If I'm not at home have Tasker say "Sir, I've detected that your garage door is open but you don't appear to be near your house. Would you like me to close it?"

Pop up the voice command window.

Using yes/no, open/closed, up/down as the keyword, I could answer in a natural voice and say "yes please close it for me" or "sure, close that sucker, I must have forgotten" or "nah, leave it up" or "it's ok, I want it open"

It could then say "Ok, closing it now," run the command to close the door and once the sensor detects that the door is closed say "It's closed, sir"

Like I said, I'm not going to do that, but it illustrates how well Tasker and X10 gear could work together to both perform really cool actions like opening doors for you and also make your phone behave somewhat like an intelligent assistant.

Wednesday, December 22, 2010

Happy Holidays!

I haven't been around much lately but I wanted to drop in and wish everyone Happy Holidays. I also wanted to let everyone know that the current economic climate has not affected my Christmas budget and all of the readers of this little blog can expect to receive the same thing I got you last year!

Followers