Android and Linux

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.

Saturday, August 20, 2011

Finding the current song playing in Android, sorta.

I've seen people wanting to use Tasker to get the title of the currently playing song before, but it's not really possible because Android doesn't have an API for it. There is a semi-workable solution using the Locale Execute Plugin. We can find which files the media server has open with the lsof command. Assuming the only files you're interested in are mp3s, we can just grep the mp3s from the list and print the filename:
lsof -p $(pidof mediaserver) | grep -m 1 mp3 | awk '{print substr($0, index($0,$9))}'
As luck would have it, the current song seems to always be at the top of the list, so using grep -m 1 we can just get the first line of output.

Output: /mnt/sdcard/download/AloeBlacc-YouMakeMeSmile.mp3

It can be cleaned up a little with the basename command:
basename "$(lsof -p $(pidof mediaserver) | grep -m 1 mp3 | awk '{print substr($0, index($0,$9))}')" .mp3
Output: AloeBlacc-YouMakeMeSmile

If you're interested in files other than mp3, you can add them to the grep command:
grep -E -m 1 'mp3|wav|other1|other2'
The downside is that this just gets the file name and doesn't display any metadata or anything like that. If your file is Track10.mp3, it may show information about the artist and song in the media player, but with this trick it will only show Track10.

This trick also works to display the file being played in BeyondPod, the podcatcher app, but podcasts often don't follow naming schemes meant for humans so the output for the Jordan Jesse Go! podcast ends up being jjgo110814_ep187. If your goal was to display the file in Tasker or Zoom, you could set up replacement titles for your podcasts, like if the title matches jjgo*, display "Jordan Jesse Go!"

Aug 23: I edited the awk command to handle filenames with spaces, then I realized the awk command isn't needed. There's no need to pick out the field with the filename with awk. You can use the entire line, the basename command will only output whatever is to the right of the last "/" anyway. I'll leave the original up since it's been there for a couple of days and people have already seen it, but this simpler command would be better to use:
basename "$(lsof -p $(pidof mediaserver) | grep -m 1 mp3)" .mp3
Use that one instead, and I'll try to notice the obvious sooner next time.

Wednesday, August 3, 2011

Free Nexus S

If you go to google.com, there is a line of text that reads "Nexus S, a pure Google experience. Get it FREE today only"

It requires a 2 year contract or an extension of your existing contract. I wasn't impressed with the Nexus S when it came out but my Nexus One is seriously aging and I'm contemplating getting a Nexus S. I can't make up my mind because I want to wait for something better too. Oh well, in case you missed it, go to google.com and click the link.

Wednesday, July 20, 2011

New Tasker plugin

If you read this blog, you're probably interested in the new Secure Settings Tasker plugin. It has a lot of features which seem good. Unfortunately, I don't have a use for any of them except the shell command runner and I'm happy enough with my own methods that I probably won't change. But the plugin does allow you to store stdout and stderr in a Tasker variable and I'm sure will be a hit.

The downside is that you have to set up a "variable changed" profile to get the output (see the second post in that thread and the later reply). It's more or less the same as my command runner profile except it can display multiple lines of output and my profile can't because Tasker still can't read entire files. (I got it on the todo list, but it's been sitting there for nearly a year).

Plus, it has other features. If you're interested in those, it's probably a win-win.

Thursday, July 14, 2011

Notify My Android down

Wouldn't you know it, as soon as I start using and posting about Notify My Android, it stops working. According to an NMA Twitter post:
Google C2DM SSL Server certificate expired and they didn't update. It should be normalized later this morning. Sorry for that.
That was 16 hours ago. Hopefully they get it running soon.

Monday, July 11, 2011

Pulling data from Notify My Android notifications

Notify My Android (NMA) doesn't have Tasker integration, but we can bridge the gap... sorta.

Data for the app is stored in a database so we can pull out the ever handy sqlite3 and grab it.

sqlite3 /data/data/com.usk.app.notifymyandroid/databases/nma "SELECT * from notifications;"

The data is stored in pipe delimited fields with the newest record on top. Here is what it looks like when I send the output of the date command as both the event and description field.

44|141395|Home|Mon Jul 11 20:18:43 EDT 2011|Mon Jul 11 20:18:43 EDT 2011|1310430099|0|1

Assuming we want the 5th field, just tell Tasker to read the line, split the variable then flash %VAR5.

But here's the catch, Tasker can perform an action when the notification comes in but the data doesn't go into the file until a few seconds after the app is opened, after it syncs with it's home server.

The most elegant solution doesn't work. That would be a Tasker context watching for the file to be modified, then running the command to get the new notification. Unfortunately, watching for file modification doesn't seem to work in /data/data.

You could write a script to watch the file for new contents then put something in a file on the sdcard that Tasker could see, but it would be necessary to keep the script looping and if you lost the network connection or something, it could loop indefinitely. You could kill it once the app exits, but this is getting too complicated.

The easy answer is to just add a wait. You'll need a profile watching for the app to open, but disable that profile. Then have a profile watching for the notification. Once the notification comes in, have it enable the "App Open" profile. The App Open profile can carry out a task to

1 wait 5 seconds (adjust if your network connection takes longer)
2 execute: @! sqlite3 /data/data/com.usk.app.notifymyandroid/databases/nma "SELECT * from notifications;" > /mnt/sdcard/Tasker/notified
3 read line 1 of Tasker/notified to var %NOTIFIED
4 Variable Split %NOTIFIED splitter: |
5 flash %NOTIFIED5
6 Profile Status set Notified off

Remember, the NMA app must be opened for Tasker to grab the notification data, but with these profiles, when there isn't a notification, it can be opened without triggering the task.

%NOTIFIED5 will contain the main body of the notification. You can select from 3, 4 or 5. They are the application, event and description. All three are necessary to send a notification through NMA and can contain 256, 1000 and 10000 characters respectively. Only the application and as much of the event as possible show in the Android Notification area. The entire event and the description are shown in the app.

Pent has put the ability to read any file system-wide on Tasker's todo list. Until then, I hope someone gets some use out of this.

Followers