Using the Raspberry Pi to Send Push Notifications
One reason I wanted to have a Raspberry Pi was to be able to cheaply run periodic scripts and monitoring apps. I could have easily left on a full PC and hid it in my closet, or I could have rented out another Amazon EC2 server, but in both cases, it’s quite expensive. With the dedicated PC, there is a significant up front cost, and depending on the power efficiency of the computer, it could cost me monthly as well in the form of an electricity bill. Amazon EC2, on the other hand, costs anywhere from $20 up to hundreds of dollars a month, which is fine if you need the full power of a server to run a website, but not ok for hacking together some stuff.
With the Raspberry Pi, I have a low cost ($35) and low power device that I can always leave on, without worrying about heat building up in a case or a large power bill— after all, the entire thing runs on a Micro USB port.
I’ve been a big fan of Node.js since fall of last year. The first project I really used Node in was a ticketing website for a business competition. There were, however, a few downfalls to using an experimental platform:
- New versions often broke my application, which happened to use Express.js
- Express.js was upgraded from 2.0 to 3.0 in the time I was working on the app— which broke more stuff
- Keeping the app running properly. Unlike PHP and Apache, I had to worry about keeping the script running at all times
To get Node.js running on the Pi, I had to compile it— it’s only available officially in x86 binaries, as far as I know. These instructions are what got me started. Of course, since I wasn’t using ARM Arch, so I couldn’t simply cheat and use the pre-built version:
$ pacman -S nodejs
After modifying the files in the V8 engine and setting it to build for Arm,
make took over an hour— I left it overnight so I wouldn’t have to watch it build. And because it’s a fan-less machine, it didn’t even disturb my sleep.
Until recently, to do any parsing of web pages, I’ve used JQuery or regular expressions.
The benefit of using JQuery and the Sizzle CSS selector engine built into JQuery is that I can do the following to get the title of the page:
var doc = $([some html]);
var title = $(doc).find('title').text();
Regular expressions are a little tougher to write and require a bit of testing, but they also let you extract a small part of an HTML element without an issue, and they don’t require the use of a DOM, since all you ever deal with is plain text.
Zombie.js is generally used for virtual browser automation and testing— you can tell it to go to a link, click buttons, and fill out forms. You can also extract values from elements using the same Sizzle engine JQuery uses, making Zombie a great choice for extracting values from HTML as well. And of course, all of this is done from Node.js in a virtual web browser.
To test Zombie and Node.js out on the Raspberry, I created a simple script that fetches the forecast for the day at 6 AM on weekdays and 9 AM on weekends, as well as the next day’s weather at 8 PM every night. This data is pushed to my phone using Boxcar, so by the time I wake up, I have the forecast and chance of rain sitting right there. Yes, my iPhone is jailbroken and I could have a weather widget or Intelliscreen X on my lock screen, but this solution will work throughout iOS 6 as well, and it’s a great introduction to using Boxcar’s API.
Rather than starting from scratch, I tried to use an existing Node.js module, but for whatever reason, I could not get it to work. Sending a notification from the API just didn’t seem to get through.
Boxcar’s API is simple enough, so I coded the notification myself. Instead of dealing with Node’s HTTP API, I instead use a module called Restler. With a simple POST request to Boxcar, a push notification is sent to my phone.
However, it is important to remember, if you get a
401 error from the API, you need to subscribe a user to your Boxcar service.
Because I am running into a bug with Zombie.js, I can’t actually parse Weather.com or AccuWeather with it. My local news station works fine, however, and the weather is more accurate anyways. I simply fetch an element that holds the temperature or forecast on the page, and put it in a message to be sent using Boxcar.
All of this is deployed to the Raspberry using Git.
With college coming up in the fall, I’ve been registering for classes and housing. The college dashboard has a ton of information on it, including tuition balances, meal card information, and more, but who wants to log in and look? The next step is to create a script using Zombie.js on the Raspberry to monitor the account balances, and send me a push notification when anything is running low or if there are any significant changes in the notices section. This was actually the idea that allowed me to find Zombie— there is no API, and I have to log into the dashboard somehow.