Android and Linux

Sunday, October 30, 2011

Run Tasker task from command line

I have been looking for an alternative to Notify My Android in order to send myself notifications to my phone when I'm at home. NMA notifications work fine, but you have to open the app to clear them and I just wanted a vibration or sound that didn't leave anything else on the phone for when a job finished at the computer or something.

I first looked at playing a media file with the following command:

am start -n com.android.music/com.android.music.MediaPlaybackActivity -d /sdcard/foo.mp3

That sorta works. It opens the media app and plays the file then immediately goes to the next song. Adding && sleep 1 && pkill com.android.music makes it work more like I wanted, but that's too ugly.

I ran across this post in the Tasker forum about invoking a task from the command line, but the consensus was that it wouldn't work unless the command line app has the right permissions.

But then I discovered that this works:

am broadcast -a net.dinglisch.android.tasker.ACTION_TASK -e task_name YOUR_TASK_NAME

The only difference being the "-e" option instead of "-es."

So I made a simple script called "task" for the phone.
#! /system/bin/sh
am broadcast -a net.dinglisch.android.tasker.ACTION_TASK -e task_name "$*"
Now I can bounce the command off the phone via ssh and run any Tasker task I want.

Wednesday, October 19, 2011

The Pogoplug is taking over my life

The $50 Pogoplug that I bought to goof around with is now my main server.



The Pogoplug is about the size of a small, thick book. To the right is an Edge DiskGo network attached storage drive. That's where I keep all my media to be played on the TV via the Roku and the MyMedia Server Roku app. The Pogoplug is running a small python server that acts as the companion to the Mymedia app and I simply mounted the drive over the network because I didn't have any USB cables to plug it in directly, so it acts as if it is serving the files from it's own drive.

Debian is installed on the USB stick in the front of it. The white cable in the back is the power cord, and there's a cat5 plugged into the back which you can't see, and the two black cords are USB cords running to my CM11A and W800RF32A, which are an X10 controller and wireless receiver respectively.

It's not only serving media and running the automation, but other scripts to check weather, watch my IP address, back up files from my phone when I connect to my home wifi, etc. Everything installed and runs just as easily as it would on any desktop Linux. The only hard part was getting accustomed to Debian, but it's not so different from Slackware and at least it's not Ubuntu.

That's the beauty of Linux, very small programs requiring very little resources can do as much, if not more, than some $100 program you'd have to buy for a Windows computer, and they can do it in the background without you having to be there to point and click, and they can do it on very minimal hardware.

Thursday, October 13, 2011

remote ssh to multiple hosts on same network in Android

I have four devices running ssh at home. Since they're all attached to my router, they all have the same IP address to the outside world, but ssh runs on different ports on each device. In theory, you can ssh into each one by specifying the correct port. In practice, however, it's not always that simple, especially with Android.

In order to prevent a man-in-the-middle attack, when ssh makes a connection, it saves the computer's IP and host key in the ~/.ssh/known_hosts file and the next time you try to connect, it checks the IP in that file to make sure the host key is the same.

Let me illustrate. Let's say my home IP address is 123.45.54.321. I have 2 devices, comp1 and comp2 running ssh on port 111 and 222, respectively. And let's just say their host keys are AAA and BBB (the keys are actually much, much longer). If I ssh into 123.45.54.321 port 111, then this gets entered into the known_hosts file: 123.45.54.321 AAA.

Now, if I try to ssh into comp2 at 123.45.54.321 port 222, it gets the host key BBB from the computer and looks in the known_hosts file and says, "whoa, I expected AAA from the computer at 123.45.54.321, something is wrong" then the connection fails.

There are normally a couple of solutions for this. First, you can sometimes connect to comp1, copy the key from known_hosts then remove it from the file and connect to comp2. Now put the comp1 key back in known hosts. I've never done this and heard that it doesn't always work, but sometimes ssh will keep trying entries in known_hosts until it gets one right.

The better solution is to set up ssh config file like so:

Host comp1
Hostname comp1.somedomain.com
Port 111
HostKeyAlias = comp1
CheckHostIP = no

Host comp2
Hostname comp2.somedomain.com
Port 222
HostKeyAlias = comp2
CheckHostIP = no


Then you can connect with the command ssh comp1 or ssh comp2.

Unfortunately, that doesn't work with Android because it doesn't have an ssh config file. I'm not entirely sure you can do anything about it with the normal Android ssh program. I deleted it long ago and use the ssh binary from Better Terminal Emulator Pro (see this post) and there is a workaround with it.

The first trick doesn't work with the BTEP ssh binary, and neither does the second trick because it doesn't seem to use a config file. As often is the case with Android, the ugliest solution is the only solution.

BTEP looks for the known_hosts file in /data/data/com.magicandroidapps.bettertermpro/home/.ssh (sorry, I originally posted the wrong directory. Fixed now!). You can use the first trick to get a copy of the host keys, then write a script to overwrite known_hosts depending on which computer you want to connect to.
#! /system/bin/sh

case "$1" in

comp1)
echo "$(hip) ssh-rsa AAA==" > /data/data/com.magicandroidapps.bettertermpro/home/.ssh/known_hosts
ssh USER@$(hip) -i PATH/TO/KEYFILE -p PORT;;

comp2)
echo "$(hip) ssh-rsa BBB==" > /data/data/com.magicandroidapps.bettertermpro/home/.ssh/known_hosts
ssh USER@$(hip) -i PATH/TO/KEYFILE -p PORT;;

esac
You would fill in your user, path to the ssh key and port number. You can also fill in the IP address, but that's what the $(hip) part does. hip is a script that tells me my home computer's IP address which I've blogged about here and here. Essentially, I keep my home IP address in a file and the hip command just displays that file. That way, I don't need to hard code my IP in any scripts. If my IP changes, I can just update it in that file and not worry about changing the scripts.

I named the script above simply "s". So, if I run s comp2, it will write 123.45.54.321 ssh-rsa BBB== to known_hosts then connect to comp2.

Incidentally, this also takes care of another problem- IP changes. The first time you connect to a host, ssh asks if you really want to connect and you have to type yes or no.

If you normally have 123.45.54.321 ssh-rsa BBB== in your known_hosts file and your home IP changes for some reason, the new IP won't be in the file and your scripts will break until you manually log in and tell ssh yes or no. But now that no longer matters because we are controlling known_hosts and filling it with the correct up-to-date IP and associated key.

The other solutions are better for computers that are running the real OpenSSH, but this is the only solution I could figure out for Android and it's funky programs.

Tuesday, October 11, 2011

Pogoplug

I was in Best Buy today and noticed that they sell Pogoplugs for $50 so I picked one up. I believe it is the first generation without wifi, but I don't care about that, I prefer using network cable when available over wifi anyway. The downside to Pogoplugs is that they have very little space available on them, but you can install Linux on an external hard drive plugged into them via USB. I didn't have an external drive, per se. I have a NAS network drive, and that may work, but I didn't have a USB cord to attach it, so I installed Linux on a USB stick for the time being.

Using this guide, it only took a few minutes to have a very minimalistic version of Debian running on it, and after installing the gcc compiler and other tools, I was able to install Heyu. Then I plugged my CM11A X10 controller into the Pogoplug and was a little surprised that the darn thing actually worked. Awesome!

The NAS drive is what I use to store videos for streaming to the Roku. I tried to install the server program on the Pogoplug using the USB stick just to see if it would work, but python threw socket errors for some reason. I'm going to investigate whether I can use the NAS with the Pogoplug. If not, I'll probably get an external drive and use it to serve videos, control the home automation, and various other things I have a computer doing now. I'm not entirely certain I want to turn over everything to a little box like this, but I want to do it to see for myself that it can be done, then change back to the computer if I prefer it.

I think it's pretty amazing that, for $50, you can get a computer the size of a book that can do all this. Then again, the Raspberry Pi.org/ is only going to be $25, so maybe I got ripped off!

Friday, October 7, 2011

Yay, new computer.

I bought a new computer and, boy, why didn't someone tell me computers had gotten so darn good these days? My main desktop was a 2.2 GHz box with 2 gigs of ram. That's pretty outdated but was enough for everything I needed, but I wanted to turn it into a server and get a new one for general use. Now I have an i7 quad core with eight 3.3Ghz processors. What a difference!

Since I got the Roku, I found myself wanting to encode videos to play on it. With the old computer, encoding a 175mb 30 minute TV show took about 45-50 minutes and the fans on the computer sounded like a jet trying to take off. And movies? They weren't worth spending hours to encode.

The new computer? It can encode a TV show in 1-2 minutes and a 3 Gig HD movie in 15-30 minutes and it doesn't make a sound the entire time.

I've had it for a couple weeks, but soon after getting it, half of my home automation stopped working. I finally figured out that the computer was to blame. The instant the power cord is plugged into the computer, it causes interference that drowns out the X10 signals. I ordered a noise filter that finally arrived so now I can leave it plugged in as long as I want and still have my automation working.

Anyway, I've been slowly setting up the old computer to act as a server. It isn't a lot of work, it was really a desktop/server before, but I need to get everything set up so I can stick it in a closet somewhere and forget about, administering it from the new computer when needed.

I should have a lot to post about soon. I have a transceiver for my home automation on the way in order to pick up RF signals. With it, I will be able to set up motion detectors and things that can send a signal to the computer instead of only the other direction. Automation is only half useful without that.

I'm also planning to start toying around with plug computing. A plug computer is a full fledged linux computer that fits in a box the size of an electric plug. With the right setup, I could do away with my computer that acts as a server and use a plug computer to run the automation, and mount a cheap hackable display like the Chumby in the house to control it all graphically, and of course Android to control it all remotely.

Anyway, sorry for not having much to post about but hopefully that will change soon.

Monday, September 19, 2011

Camera weather display

I'm sorry I haven't posted much in a while. To tell the truth, I haven't done much worth sharing. My daughter started kindergarten and I think her school is harder for the parents than the kids, and being a single dad makes it all the more tough. The only time I have for myself is a couple hours after she goes to bed and the housework ain't doin' itself during that time.

Oh well, I did come up with something pretty cool that will probably be of no use to anyone unless they have the same gadgets as me. It may inspire someone to do something similar with other gadgets though.

Taking my Foscam and Roku scripts and a Roku app, I made a little automated camera/weather display for my TV.

The Roku app is MyMedia which allows you to play files from your computer on your TV. It's two parts, a simple server for your computer and an app on the Roku. The server shares Music, Photo and Video folders to your local network where the MyMedia app on the Roku can pick them up. There are other Roku apps which do the same thing, but this one fit my needs.

Once that is set up, the ID for that channel is 2542, so using my Roku script, you can use the command roku go 2542 to load that channel. Once it loads, you can use the script again to navigate to different folders using left/right and select commands. You can, of course, do this with the Roku remote control, but it's a lot cooler to automate it.

Let me back up and first post the script then walk through everything that is happening in 4 steps.
#! /bin/sh

cam snap

WX=$(links -dump 'URL' | grep -A 6 'Weather:' | sed -e 's/^[ \t]*//')

convert /sdcard/cam.jpg -fill white -gravity South -pointsize 25 -stroke '#000C' -strokewidth 2 -annotate 0 "$WX" -stroke none -fill white -annotate 0 "$WX" /sdcard/cam.jpg

roku right
roku go 2542; sleep 7
roku str right right select; sleep 1
roku select


Step 1: cam snap
Using the Foscam script, just run cam snap and a jpg will be saved wherever you have the script set up to save it. On my computer, I actually made a /sdcard directory so I could more easily write scripts that would work on both the computer and Android phone, so /sdcard/cam.jpg in this post is on the computer, not the phone.

Step 2: WX=$(links -dump...
Links is a command line Linux browser which can dump the text of a webpage. Lynx is another which is often interchangeable with Links, and both have the same -dump option so either could be used here. This sets the WX variable to the output of the links command. I used the weather conditions from the weather.gov mobile site. Click that, put in your zip code, click go, then click current conditions. Copy the URL of the current conditions page and use it to replace URL in this command in order to grab everything from Weather to Visibility then align the text properly. This is just an example, you could get the weather from anywhere.

Step 3: convert...
"convert" is part of Imagemagick, a powerful command line image manipulation program which is installed on most Linux distributions. In this case, I'm using it to write the weather from the WX variable on the image.

Step 4: roku...
All the Roku commands use my Roku script to navigate to the MyMedia channel and select the image. The first command is used to wake the Roku up in case the screen saver is on, the second selects the channel and waits for it to load, which usually only takes 3-4 seconds, and the rest navigate and select the image. I don't have any other images to display so when I navigate to the Photos folder and click "select", it automatically opens the image I want since it's the only one. If you have other photos, you may want to use a subdirectory and a couple extra commands to navigate to it.

Here is the end result:



I pointed the camera at a wall because the normal view would show part of my neighbor's house, and I would feel awkward about that. It's also dark, it looks much better pointed over my yard with the daytime sky in view. The image itself is mediocre on a computer, but looks great stretched out on a wide screen TV.

So, what use was all this? Well, I have a cron job scheduled to run at the same time my alarm goes off in the morning. It turns on a couple lights that are controlled with X10 automation, sends the weather forecast to my phone, and a couple other odd jobs. I added this to the schedule, so I can roll over, look at the TV and see what it looks like outside as well as the current weather conditions.

I also set up a Tasker task to ssh in to my home computer and run the first three steps, copy the resulting file to my phone, then display it, in case I'm interested in seeing this image and info while I'm away.

While this trick is pretty specific to my setup, maybe it will inspire someone with other gadgets to do something cool with whatever they have.

Sunday, August 28, 2011

Part 2: Finding the current song playing in Android, still sorta.

I made a post about getting the filename from the mediaserver at the Tasker discussion group and others found that the lsof utility only comes on Cyanogen so many people don't have it. I found an alternative in "ls -l /proc/$(pidof mediaserver)/fd" and I'll show some ways to use it below.

Another poster, Matthieu, also figured out a way to get the mp3 tags from the files. The ID3v1 tags are pretty simple, but ID3v2 is a pain. Here is a post I made to that thread incorporating the lsof alternative, Matthieu's method of extracting ID3v1 from that thread, and the start of an ugly method to get ID3v2 tags. More on that in a moment.

Here's an lsof alternative. I think it could do without the grep command but it's safer with it in:
ls -l /proc/$(pidof mediaserver)/fd | sort -g -k 9 | grep mp3 | tail -n1
This will give you the long filename like /sdcard/foo.mp3:
ls -l /proc/$(pidof mediaserver)/fd | sort -g -k 9 | grep mp3 | tail -n1 | awk '{print substr($0, index($0,$11))}'
This gives the short filename like foo.mp3:
basename "$(ls -l /proc/$(pidof mediaserver)/fd | sort -g -k 9 | grep mp3 | tail -n1 | awk '{print substr($0, index($0,$11))}')" .mp3
This gives the id3v1 tag:
tail -c 125 $(ls -l /proc/$(pidof mediaserver)/fd  | sort -g -k 9 | grep mp3 | tail -n1 | awk '{print substr($0, index($0,$11))}') | head - c30
This gives the id3v2 tag but needs tweaking:
grep -A 20 TIT2 "$(ls -l /proc/$(pidof mediaserver)/fd  | sort -g -k 9 | grep mp3 | tail -n1 | awk '{print substr($0, index($0,$11))}')" | grep -m 1 [a-z]
That last one is ugly and unfinished. ID3v2 tags are variable length and the length of the tag is supposed to be encoded in the file itself but, for the life of me, I can't find a file on my system that follows that guideline. I'm obviously missing something because they display correctly when played, but most of them also have ID3v1 tags on the end as well, so maybe that's why they display properly.

I would spend time trying to find a better solution but Pent said he is going to add mp3 tag support to Tasker soon and that should work better than anything I could come up with. Plus, I'm really not interested in the tags. When something interests me, I usually get about an hour late at night to work on it, and I only want the file name.

As ugly as it is, the last one still kinda works. All the tags on my system start with TIT2, but are followed by a lot of hex gibberish before the plain text tag begins. This greps TIT2 then greps the first line below it that contains a lower case letter. On my files, it has a high success rate. One big problem it has is that the tag is often followed by another field such as TALB, so the output can be "Song TitleTALB." Someone could figure out all the possible fields in an ID3v2 tag then just use sed to chomp them off. Or someone cou otu a more reliable method, or we can just wait for Tasker to do it for us.

Followers