Cloud Lamp and the Internet of Things

Control my lights at pi.geedo.net. I make no guarantees that the server is on.

EDIT: The server is now down indefinitely. It was a fun experiment unleashing the web page to all my friends and watching as they changed my lights though out the day, but it came time to take it down.

Github

Over the past week I devoted some time towards my LED strip project which I broadly defined as adding networking capabilities with a remote control aspect. At first it seemed like nothing I hadn’t worked on before, create a simple TCP-based interface and control things over the network. However, I then came upon the idea of controlling the lights through a web page instead of a closed protocol on compiled client/server applications. This led me into learning more about internet connectivity and the various interconnections that allow this blog to be delivered to any computer in the world. As simple as the final implementation ended up being, it ended up being quite the learning experience for me.

To start I developed the firmware on the Arduino which was for the most part complete from my earlier experiments with the strip. It just needed a few more stability tweaks because I noticed that the 9600 baud rate on the Arduino was so painfully slow that the bytes get loaded into the buffer much slower than they can be read out. I needed to pass along a buffer length to wait for before reading out the buffer. Later I also discovered the convenience of using printable characters in the protocol over indiscriminate binary. For my purposes, the benefits of increased information density from a dense binary protocol is insignificant compared to the convenience of handling strings in a language such as Javascript. A funny bug I ran into with developing with the Arduino was when I was when I was converting the hex encoded ASCII into a usable number. My test case was RGB#ff0000 and I was scratching my head why the lights would never turn on and why the number always encoded as 0. The earlier conversion for the buffer length succeeds so I assumed that the conversion was good. Turns out the problem was my poor judgement in using the int type. I’ve been working with 32-bit ints for so long I forgot that the crappy AVR on this board was an 8-bit processor with a 16-bit integer. The conversion gets cast into a 16 bits and cut off my test case resulting in a 0. Two lessons learned, use good test cases and stick to the char/short/long convention.

I then started writing up the server side application for the Raspberry Pi to interface with the Arduino. The intent was to open a TCP port and listen for commands which would allow me to write client side applications, but I never did get to writing the TCP portion. To communicate with the Arduino, I used the C WiringPi library which implements an API to use the hardware modules for GPIO and communications. I also found the BCM library for a more bare metal C programming interface. An important note is that any application developed with these libraries and any other that interfaces with GPIO requires root access which becomes a security concern when we start dealing with hostile networks (aka. the internet). A cool thing I noticed though was that Broadcom at some point since I last checked released part of the documentation for this chip’s hardware under pressure from the Raspberry Pi community/foundation.

My reason for dropping the TCP port/socket approach was to learn more about web applications in general by implementing a web interface. This was probably the most time consuming part of the project as there were a large number of ways to meet the same ends and all I could do was try things out and see what I can and can’t do. One of the first things I did was set the Raspberry Pi up as a general purpose web server which consisted of getting Apache2, MySQL, and vsftpd up and running. If I’ve learned one thing from being a generalist in tech it’s that a lot of the time spent learning something new is wrestling with your toolchains. Apt-get took care of the bulk of the grunt work, but I still had a lot setup issues with MySQL due to the latest Raspberry Pi firmware having compatibility issues. Next challenge was making my new server available to the internet. From my router I simply needed to setup a static IP for my Pi and forward all HTTP traffic to my network to that IP. To deal with the pesky problem of Comcast changing my IP I had to subscribe to a free dynamic DNS service (NoIP). This runs a daemon on my Pi which automatically updates my IP on their name server and I simply use their provided hostname for all communications to my network. The final bit of trickery was to mask the free hostname from the user by somehow funneling it through my domain. By registering geedo.net I also have gain the privilege of creating whatever sub domain or sub directory I want. Since the web server is on the Pi separate from my web host and name server I just had to create a new DNS zone CNAME record in CPanel to route pi.geedo.net to geedo.noip.me which in turn routed to my home network which routes to the Raspberry Pi Apache web server. I was pretty ecstatic when I saw the default Apache document root load up in Chrome though my domain name. It really made me appreciate how powerful the internet is in that it reliably connects however many billions of computers there are around the world.

Now I had to actually learn how to make a web application and there seemed to be countless ways to accomplish the same means. My first instinct was to try and do this using C so I can reuse my existing WiringPi code. This introduced me to the Common Gateway Interface (CGI) which is a way for Apache to execute programs by browsing a certain “file” in its document root. These programs can be more or less written in any programming language. The program in turn does all its backend work as well as dynamically print out a web page to be rendered by the browser. What I soon learned was that I had to either give Apache root privileges or give the CGI script root privileges to use GPIO and I wasn’t that confident in my ability to fend off hackers on the internet with source code that I’m also publishing. That was quickly ruled out because of the complexity/security issues.

I then found an elegant solution in a framework written to support the internet of things known as WebIOPi. This packages a server side application that runs as a daemon with root privileges which implements a REST API to interface hardware modules. A REST API I learned is an API that depends on basic HTTP GET/POST requests. The Clipboard01package also provides Javascript and Python libraries to facilitate these GET/POST requests. In the spirit of learning more new and employable skills I decided to implement my web interface in Javascript. As you can tell I am definitely not the best front end web developer so I came up with a rather bare bones interface, but I learned a lot from it. Mostly how JQuery/Javascript obtain data/events from HTML elements and how uncomfortable weakly typed languages make me. It’s all very hackish on the surface, but I like the analogy to biology in web technologies. In a way, they all co-evolved and depend on each other making your modern website an elegant amalgam of independent technologies.

Overall it was an interesting albeit a rather simple project on the surface. I feel that I’ve gained a lot of new and useful skills for future more complicated projects involving the internet of things. Though there’s a lot of room for improvement, I feel the need to table this project to work on something else. Revisiting this project would probably involve implementing individual control of the LED’s via the web interface and making it look prettier than the color picker and button I have now. Some feedback for the user controlling my lights such as a webcam feed would have been a nice touch so people would feel like pressing that button actually did something. I also need to rework the power supply situation as right now the Arduino/LEDs are on a separate supply as the Pi just because I didn’t get around to splicing the USB cable into the Arduino’s supply. All these though are problems for another day.