Let there be light

First of all this is a coding post. A post about geeky techy stuff. If you are only here for the games, you can probably go away now. Maybe you are here for the comedy writing, then you can probably go away now.

So for a while now I have had a Raspberry Pi, a small credit card computer (I think there might be a post in the archive).

The RF sockets I use #exciting

At present it’s main duty is as the timer for the lamps in my living room (among other things). It uses a simple Radio Frequency (RF) transmitter (a reader and transmitter cost about £3 off ebay a year or so back) to control the remote control sockets (That I bought ages ago and that have been working with the pi for ages).

It’s simple but it works. The Rasperry Pi has a timer that triggers the lights at a specific time. I go into the timer and every week or so (sometimes more often depending on the changing lights) and update the timings.

I got a bit bored of doing this, and figured somewhere in the age of the Internet of Things, this should be something that could and should be automated.

So, The usual plan of

Get Sunset time > Magic happens > Timer for lights changes

Where do you even start doing this? Well, the plan required a starting point of somewhere I could pull the sunset time. A quick Google later and I had a link to a URL online that didn’t have a huge amount of fancy scripting or anything thing behind the scenes (like many that I looked at).

Right, I’ve got a URL … What do I do next? Talk to my resident techy to find out how I can make the command line pull down the website on a schedule.

After talking to Phil and checking a few things out, it seems that my first thought wasn’t too far off. It seems that it should be possible to schedule a task (in the same timer as the lights at present) to grab a URL and store it on the Pi.

So a simple curl command later and we have the URL. Feed the output into a converter to convert the html from the website into basic text. It doesn’t look pretty and the command doesn’t either, but it does mean I have a simple .txt file with the information I want (somewhere in the body).

curl -s http://www.sunrise-and-sunset.com/en/sun/united-kingdom/hull | html2text -style pretty -o /home/pi/sunset

By using html2text to convert to a usable format I could then grep the section I wanted from the file and output into a second .txt file (In English this means look for a specific bit of text and pull it out and store it somewhere else.)

grep -e 'Sunset.*today' /home/pi/sunset > /home/pi/time.txt

It’s not a pretty series of commands but it did mean that I ended up with a single file with the exact information I needed. A single line of information starting with the phrase “Sunset today”.

Excellent. Now with this scheduled to run every day, I get a simple easy to use file with an updated sunset time. SUCCESS!

Kind of.

Right. Now. Okay. I’ve got a text file with the info I need. What next?

Wait a week. Chill, let the idea grow and develop.

Time passes

How to I get the times out of the text file, into the schedule file (crontab)? It turns out that there is a command built into the system that should be able to do this. You create a variable, and copy a specific part of the file (even more specific than before) – this time I want the time. I want the minute and hour bits… so, a quick script and…

file="/home/pi/time.txt"
time=$(cat "$file")
hour=${time:14:2}
min=${time:17:12}
line="$min $hour"

So, in terms of explanation, we take 2 characters from point 14 and store it in “hour” and then 2 characters from point 17 and store that in “min”. Then put those values into the variable “line”. You’ll notice that they are the wrong way around. This is because the schedule file needs the information in that format (Minute Hour Day Week Month).

Then my code creates a temporary task schedule file and copies this line into it and replaces the main schedule file. It then removes the temporary file (there are two commands being added to “mycron” because I have the lamps on two different sockets).

#copy cronfile template to working file
cp /home/pi/crontemplate /home/pi/mycron
#echo new cron into cron file
echo "$line * * * /usr/lib/cgi-bin/bigon.cgi" >> mycron
echo "$line * * * /usr/lib/cgi-bin/lampson.cgi" >> mycron
#install new cron file
crontab mycron
rm mycron

Brilliant. Leave it alone and see what happens.

So, the next day rolls around and … nothing happens. (Turns out I’d make a rookie mistake and left half of the path for the commands out of the script.)

Quick check of the file locations and away we go again.

Next day rolls around and… still didn’t work.

Thankfully, I have everything dump into a log file to see if things run okay or not. A look at the log shows me two time stamps, but no information on what actually had run. The good news is that the code worked. Sort of. It had actually run at the appropriate time, but something didn’t work.

My guess was that seeing as the time stamps were both one second after the supposed sunset time that the RF transmitter had crapped out when asked to send signals to two sockets at once.

Okay, that’s a simple fix, we just need to set two times up. One command runs at sunset time, and the second command runs at one minute later.

Expect it’s not that easy. How do you do even basic maths with a variable you’ve pulled out of a text file? No, I did’t know either.

Actually it turns out that it’s quite simple. As you can see below,  I now create two “min” variables and two “line” ones. They are then added to the template schedule file and bingo! One command runs at sunset, and one runs at a minute past sunset time.

#!/bin/bash
#pull time from text file and store in variable
file="/home/pi/time.txt"
time=$(cat "$file")
hour=${time:14:2}
min=${time:17:12}
line1="$min $hour"
#Transmitter fails sending both codes at same time - do some maths to add time $
min2=$((min+1))
line2="$min2 $hour"
#copy cronfile template to working file
cp /home/pi/crontemplate /home/pi/mycron
#echo new cron into cron file
echo "$line2 * * * sudo /usr/lib/cgi-bin/bigon.cgi" >> mycron
echo "$line1 * * * sudo /usr/lib/cgi-bin/lampson.cgi" >> mycron
#install new cron file
crontab mycron
rm mycron

and….

It worked!

The schedule file runs, the lights come on, and the file updates with a new sunset time every day.

I think it’s important at this point that I thank a few people who helped to make this happen. Phil Cooper for listening to me rambling about coding and suggesting the best way to lay out the plans (he does proper coding and everything) and Jon Witts (@jonwitts) from the Hull Raspberry Jam who pointed me at a couple of really useful sites and a book on using the command line to do stuff that most people use programming for. With their help along with Claire listening to my rambling about trying to change something that “works, why change it?”.

So what’s next? Who knows… for now I’m happy with what I’ve done and that with some help I’ve actually made something that works and is properly automated.

Get in touch...