The Alert Tube

The Alert Tube is an open source information appliance that connects wirelessly to the Internet of Things in the cloud. The user interface is dead simple, it communicates data via customized colored light sequences, sounds and text to speech. (Check out the video above.)

The idea for the Alert Tube came from something simple, a clock. You don’t have to turn it on, or boot it up and request information, it simply tells you the time, all the time, without you having to ask. That’s the idea behind the Alert Tube. You tell it what you want and then it continuously displays and/or emits audible information, without you having to ask. Simply walk by and take a glance at it or listen for any important alerts. Set it and forget it!

In the subsequent sections I provide detailed instructions on how to build your own Alert Tube information appliance…

Part 1: Getting Started
Part 2: Install the OS, Setup WiFi, and Run Headless with Tight VNC Server
Part 3: Update the OS, Enable SPI & GPIO, and install modules
Part 4: Add some power, create the user interface and autostart at boot
Part 5: Build the enclosure
Part 6: Setup and usage
Part 7: Python code overview (Optional)
Part 8: Next Steps and Future Enhancements

Part 1: Getting Started

Design Decisions:

My goal for this project was to have a real word physical object that connected to the internet and displayed information. I liked the idea of the blink(1), but since it required a host computer and cost $30.00 a pop it seemed kind of expensive based on the cost of the components. Instead I oped for a Raspberry Pi and an RGB LED strip, which I could reuse for other projects.

I liked the Raspberry Pi model A, since it was a full fledged computer and only cost $25.00 USD. ** NOTE ** Since the Raspberry Pi model A only has 256MB RAM, I noticed that it would crash when I loaded a GUI text editor, like Geany. I would recommend using command line based editors when doing development on the Raspberry Pi model A. Being new to the Raspberry Pi I wanted to learn Python, and there seemed to be a large community of Python developers, so this seemed like a logical choice. I started out developing with Python 2, but soon realized that if I wanted to use interrupt driven GPIOs, to reduce CPU polling overhead, then I would need to use Python 3. There may be interrupt based Python 2 GPIO examples out there, but I didn’t see any. Using Python 3 caused some problems for me initially, since my WS2801 chip based LED module(pigredients) wasn’t written using Python2. So I forged ahead and modified it to use Python 3. Along the way I needed to use another SPI implementation(spidev) since it was developed using Python2. I eventually settled on quick2wire’s SPI implementation written in Python3. The good news is that all of the functionality I wanted requires only about 1% CPU and 3% of the memory of a Raspberry Pi model B rev 2.

Materials Needed
  • Electronics
  • - Raspberry Pi model A $25.00 USD + S&H (Model B is OK too, it just costs more)
    - 4 GB or larger SD Card for the OS $6.00 USD or more
    - Edimax WiFi EW-7811Un $9.99 USD
    - Raspberry Pi case $6.50 USD (optional, but useful for insulating the Raspberry Pi from the steel outer casing)
    - Panel Mount USB extension Cable $3.95 USD
    - WS2801 IC based RGB LED Strip $24.99 USD + 5.00 S&H or daisy chain a couple of WS2801 Breakouts $4.95 ea + S&H

    click here to daisy chain a couple of these together.
    - Inline Fuse Holder $1.97 USD ensures that if a short occurs the fuse will blow
    - Inline AC switch to remove power when needed
    - Old IDE Hard Drive cable
    - Old Computer speakers (Amplifier, Speaker)
    - 1 foot long 1/8″ male to male stereo jack. My amplifier requires a male adaptor, in addition to the Raspberry Pi
    - Cable strain relief for AC power cord $5.00 USD I recommend black, since it’s less obtrusive
    - solderable PCB Breadboard $3.00 or less
    - push button tact switches $6.00 USD or less
    - misc 1/4 watt resistors
    - 3mm LED $8.00 USD or less
    - soldering iron, solder, wire, wire cutters/strippers, electrical tape or heat shrink tubing

  • Enclosure
  • - Stainless Steel Wine Cooler $19.99 USD
    - Silver Round Tin with Window $2.99 USD
    - Miscellaneous screws and nuts for USB extension cable and pushbutton/LED PCB
    - Plexiglass and sandpaper, a halved ping pong ball, or a section of a plastic milk jug to act as LED diffusers
    - Dremel to cut out USB port hole in Stainless steel wine cooler
    - 5/32” drill bit for push buttons and small LED
    - Large drill bits to make hole for power supply cable.

    Part 2: Install the OS, Setup WiFi, and Run Headless with Tight VNC Server


    Install Raspbian wheezy OS to SD Card:

    1. Download Raspberry Pi Raspbian “wheezy” OS image at: http://www.raspberrypi.org/downloads. You can also download the copy I used here.
    2. OS X: Install Raspbian “wheezy” image to SD card – run RPi-sd card builder v1.2 or click here to use my copy -> select .img file -> select SD card to install to -> provide password to proceed -> watch gear rotate in taskbar at top and wait for dialog box to open when done -> stick the card in the Raspberry Pi and boot up

      Windows: Install Raspbian “wheezy” image to SD card – run(may need to run as Administrator) Win32 Disk Imager or click here to use my copy -> select .img file -> select SD card to install to -> wait until finished -> stick the card in the Raspberry Pi and boot up.

    3. Raspberry Pi “wheezy” OS image configuration

      Raspberry Pi “wheezy” OS image configuration

    4. Upon first boot the following is how I configured my OS(FYI, I live on the east coast of the US): expand_rootfs; configure_keyboard => generic 101 PC => Other => English(US) => English(US) => default layout => no compose key => no; change_password => set your own password; set_locale => en_US.UTF-8; change_timezone => US => eastern; ssh => enable; boot_behavior => boot straight to desktop; finish.

    Setup Wired and Wireless interfaces with a static IP address:

    1. I typed sudo nano /etc/network/interfaces and made it look like the below text, which sets the wired(eth0) IP address, as well as the wireless IP addresses.  You will need to determine what you want your static IP address, netmask and gateway addresses to be. Instead of typing the below text you can also download, if you already have connectivity, and modify the file by typing: cd /etc/network/ then sudo wget https://dl.dropbox.com/u/8170542/interfaces then sudo chmod 644 interfaces to set the correct permissions
    2. auto lo
      
      iface lo inet loopback
      iface eth0 inet static
      address 192.168.0.14
      netmask 255.255.255.0
      gateway 192.168.0.1
      
      allow-hotplug wlan0
      iface wlan0 inet manual
      wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
      
      iface default inet static
      address 192.168.0.14
      netmask 255.255.255.0
      gateway 192.168.0.1
      
    3. Next, I typed sudo nano /etc/wpa_supplicant/wpa_supplicant.conf to make it look like the below text, which sets your WiFi network's SSID name and PSK password. You can also download, if you already have connectivity, and modify the file by typing cd /etc/wpa_supplicant/ then sudo wget https://dl.dropbox.com/u/8170542/wpa_supplicant.conf then sudo chmod 600 wpa_supplicant.conf to set the correct permissions. If all else fails use the GUI WiFi Config utility, click Manage Networks Tab => Enabled => Scan for your network.
    4. ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
      update_config=1
      
      network={
              ssid="YOUR SSID"
              psk="YOUR PSK PASSWORD"
              proto=RSN
              key_mgmt=WPA-PSK
              pairwise=CCMP
              auth_alg=OPEN
              id_str="default"
      }
      
    5. Once you have made the changes reboot the Raspberry Pi by typing sudo reboot and check that the settings have stuck. In my case I'm using the Edimax 7811U USB WiFi, so there is no need to install any drivers. Everything just works out of the box after a restart.

    Setup Raspberry Pi VNC server for headless operation:

    1. Login to your Raspberry Pi and install the Tight VNC package by typing sudo apt-get install tightvncserver
    2. Next Run TightVNC Server by typing vncserver. This will prompt you to enter a Password and an optional View Only Password(respond with No). When you do this you will see something like "New 'X' desktop is raspberrypi:1" The 1 corresponds to the number of the desktop session created
    3. Screenshot

      VNC Viewer Headless Display

    4. Once that is done you can start a VNC server from the shell prompt by typing vncserver :0 -geometry 1920x1080 -depth 24 This example starts a session on VNC display zero (:0) with full HD resolution.
    5. You can test the server by using a VNC client, on your desktop or notebook, like VNC Viewer or use my copy here. On the desktop/notebook side you will need to enter the ip address of your Raspberry Pi and the VNC desktop session number. For example, for the VNC Server your would type something like, 192.168.1.5:1 and then you will be prompted for the VNC Password you typed earlier.
    6. To make the server startup automatically on boot type sudo nano /etc/init.d/vncboot and make it look like the below text, or you can download and modify the file by typing cd /etc/init.d/ then sudo wget https://dl.dropbox.com/u/8170542/vncboot then sudo chmod 755 vncboot to set the correct permissions
    7. ### BEGIN INIT INFO
      # Provides: vncboot
      # Required-Start: $remote_fs $syslog
      # Required-Stop: $remote_fs $syslog
      # Default-Start: 2 3 4 5
      # Default-Stop: 0 1 6
      # Short-Description: Start VNC Server at boot time
      # Description: Start VNC Server at boot time.
      ### END INIT INFO
      
      #! /bin/sh
      # /etc/init.d/vncboot
      # First configure the user you want to run this under - this will generally be pi, unless you've created your own users
      export USER='pi'
      
      eval cd ~$USER
      
      # Check the state of the command - this'll either be start or stop 
      case "$1" in
        start)
          # if it's start, then start vncserver using the details below
          su $USER -c '/usr/bin/vncserver :1 -geometry 1280x960 -depth 16 -pixelformat rgb565'
          echo "Starting vncserver for $USER "
          ;;
        stop)
          # if it's stop, then just kill the process
          pkill Xtightvnc
          echo "vncserver stopped"
          ;;
        *)
          echo "Usage: /etc/init.d/vncserver {start|stop}"
          exit 1
          ;;
      esac
      exit 0
      
    8. We can now start or stop the service manually by typing: sudo /etc/init.d/vncboot start or sudo /etc/init.d/vncboot stop to make sure everything is working.
    9. To make the Tight VNC Server start every time the Raspberry Pi boots up type: cd /etc/init.d/ then sudo update-rc.d vncboot defaults
    10. Reboot your Raspberry Pi and startup your VNC client on your Desktop/Notebook and enter the Raspberry Pi's IP address:1 ,or whatever desktop number you want, and your password. **NOTE** Wait for the the Raspberry Pi to finish booting before trying the Tight VNC Server, otherwise you'll get connection errors. For me the trickiest part of this project was getting the WiFi setup and the VNC server. I seemed to have a spotty success rate, which were caused by typos most of the time. Don't give up and keep trying until it works.
    11. References and more information:

    Enable Tight VNC copy and paste to/from your desktop or notebook

    1. It's much easier to copy and paste text to and from the Raspberry Pi by installing autocutsel. To do this type sudo apt-get install autocutsel
    2. To enable copy and paste type sudo nano /home/pi/.vnc/xstartup and make it look like the below text, or you can download and modify the file by typing cd /home/pi/.vnc/ then sudo rm xstartup then sudo wget https://dl.dropbox.com/u/8170542/xstartup then sudo chmod 755 xstartup to set the correct permissions then sudo reboot to reboot and try out the Raspberry Pi as a headless server
    3. #!/bin/sh
      
      xrdb $HOME/.Xresources
      xsetroot -solid grey
      autocutsel -fork
      #x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
      #x-window-manager &
      # Fix to make GNOME work
      export XKL_XMODMAP_DISABLE=1
      /etc/X11/Xsession
      

    Part 3: Update the OS, Enable SPI & GPIO, and install modules


    Make sure your Linux distribution is up to date and has the right Python modules installed:

      1. Update your Linux distribution by typing in the following commands(**NOTE** This can take up to 45 minutes or more to complete):
        sudo apt-get update then
        sudo apt-get upgrade then
        sudo apt-get dist-upgrade (this part takes a long time) then
        sudo apt-get install python3-pip to update python 3 packages, then
        sudo apt-get install git-core to install github 3rd party software and modules.
      2. Get SPI working on the Raspberry Pi by typing:
        sudo nano /etc/modprobe.d/raspi-blacklist.conf then edit raspi-blacklist.conf to look like the below text(comment out the blacklist spi line with a # mark):

        # blacklist spi and i2c by default (many users don't need them)
        
        #blacklist spi-bcm2708
        blacklist i2c-bcm2708
        

        sudo reboot to reboot your Raspberry Pi. After rebooting type:
        ls /dev/ now you should see spidev0.0 and spidev0.1 listed as devices (see below image).

        SPI devices

        SPI devices shown when typing 'ls /dev/'

      3. Download and install the SPI and GPIO Python module for the Raspberry Pi by typing:
        git clone git://github.com/quick2wire/quick2wire-python-api.git to download the quick2wire module then
        cd quick2wire-python-api then
        sudo python3 setup.py install to install the quick2wire module then
        cd .. then
        sudo rm –r quick2wire-python-api to remove the directory after installation
      4. Download and install the forked version(maintains flicker code, which I need) of pigredients, with ws2801 driver IC, by typing:
        git clone git://github.com/mikegwatson/pigredients.git to download the pigredients module then
        cd pigredients then
        sudo python3 setup.py install to install the pigredients module then
        cd .. then
        sudo rm –r pigredients to remove the directory after installation
      5. Download and install the weatheralerts module by typing:
        sudo pip-3.2 install weatheralerts wait a while for this to install...
      6. Download the WS2801 RGB test script by typing:
        sudo wget https://dl.dropbox.com/u/8170542/RGB_test.py to download the RGB test script
        sudo chmod 755 RGB_test.py to make the script executable
      7. Download the General Purpose Input/Output test script by typing:
        sudo wget https://dl.dropbox.com/u/8170542/GPIO_test.py to download the GPIO test script
        sudo chmod 755 GPIO_test.py to make the script executable
      8. Download the Alerts Tube Python script by typing:
        git clone git://github.com/mikegwatson/AlertsTube.git to download the AlertsTube.py script then
        cd AlertsTube then
        sudo chmod 755 GPIO_test.py to make the script executable
    1. Personalize the Alerts Tube script by typing: sudo nano AlertsTube.py and edit line 16 which says:
      KEY = 'YOUR_KEY_GOES_HERE' and set KEY equal to your own free Weather Underground Developer key. You can get a free Weather Underground key at: http://www.wunderground.com/weather/api/d/pricing.html then modify your location to whatever State and City you are in, e.g. LOCATION = 'MA/Wellesley'.
    2. Personalize

      Personalize the AlertsTube.py script

    3. Get your area's weather alert SAME code at http://www.nws.noaa.gov/nwr/indexnw.htm#sametable and modify it accordingly to your area's SAME code, e.g. MY_SAME_CODE = '025021' then set ALERT_SEVERITY to "severe" or "major" or "moderate" or "minor". The "minor" option yields the most alerts, while "severe" option yields the least, but only the most severe. Next set PRECIP_THRESHOLD to a number between 0 and 100, where 0 is 0% chance of precipitation and 100 is 100% chance of precipitation. e.g. PRECIP_THRESHOLD = 40. Next set CHECK_DELAY to the number of seconds that you would like to wait before checking for alerts. For example, CHECK_DELAY = 600, means check for alerts every 600 seconds, which is 10 minutes. Next enable or disable ALERT_SOUND, which plays a sound when a new alert is generated. e.g. ALERT_SOUND = True, means play a sound when a new alert is detected. Additionally, enable or disable CHECK_EMAILS, which when enabled will check an email account like gmail for emails containing alert information. e.g. CHECK_EMAILS = True, enables email account checking. When CHECK_EMAILS is set to True you must also include email account login credentials, such as your EMAIL_ADDRESS and EMAIL_PASSWD. These are stored as clear text, since the account created, on gmail, is for the AlertTube only, so it doesn't really matter if it gets hacked. I'll just create another account if there's a problem.

    Part 4: Add some power, create the user interface and autostart at boot


    Wire up the power, an LED, some buttons and a couple of RGB LEDs from an LED strip:

    1. Connect the speaker amplifier and AC-DC power converter according to the diagram shown below. Additionally, connect the Raspberry Pi and the WS2801 based LED strip to the +5VDC power supply as shown.
    2. Wiring Diagram

    3. Do not connect power to the micro USB connector, instead use a separate power supply. In my case I wasn’t able to boot up unless I used a 3A power supply. A 3A power supply may not be necessary, since I was running a full LED strip with 32 LEDs and a Raspberry Pi Model B. By using only two LED’s of a strip and a Raspberry Pi Model A you can probably use a smaller power supply with no problems. I used only 2 of the 32 available RGB LEDs. For my particular LED strip I cut off a section of the strip that’s 2 LEDs long. See the dotted cut lines on the LED strip shown in the Fritzing User Interface Schematic below. Additionally, you could use WS2801 Breakout boards(mentioned in the materials section) by connecting to SCLK/CKI and MOSI/SDI then daisy chaining CKO to the next WS2801 Breakout boards CKI and SDO to the next WS2801 Breakout boards SDI.
    4. Connect the Raspberry Pi as shown below in the Fritzing User Interface Schematic. (Click the image for a larger view.) The Raspberry Pi A and B rev 2.0 pinout is shown further below. Pin 1 is closest to the silk screened portion of the Raspberry Pi board that says ”Made in the UK”. Additionally, you will see a silkscreen P1 next to a notch that sticks out closest to pin 1. Lastly, the User Interface Schematic is shown for additional clarity with the various resistor values and pin labels that connect to the Raspberry Pi. **Note** Be sure to keep the 5V supply separate from the 3.3V supply. The 5V supply powers the board and the LEDs, while the 3.3V supply is provided by the Raspberry Pi and is used for all the pushbuttons and LEDs associated with the Raspberry Pi GPIOs.
    5. Fritzing User Interface Schematic

      Fritzing User Interface Schematic

      Button / LED PCB

      Button / LED PCB

      Raspberry Pi Pinout

      Raspberry Pi A and B rev 2.0 pinout (NOTE: this pinout is shown 180 deg off from the above schematic)

      AlertsTube-Schematic

      User Interface Schematic

    6. Once you are done, check you’re wiring to make sure you didn’t make any silly mistakes, or short anything out. Use plenty of electrical tape or heat shrink tubing as needed. Power up your Raspberry Pi, check for sparks or smoke, and make sure that all the electronic components are cool enough to touch without getting burned.
    7. Once everything seems to be working as expected, test out the GPIO functionality by typing:
      sudo ./RGB_test.py
      Take a look at the RGB LED strip. If it’s working properly then you should see a sequence of blinking LEDs. If it’s not working then go back and check your wiring.
    8. From there you can test out the GPIO functionality by typing:
      sudo ./GPIO_test.py
      You should be able to press buttons and see the state change on the screen, as well as the LED should toggle. If it’s not working then go back and check your wiring.
    9. If everything seems to be working then Connect one end of the 1/8 inch male stereo jack to the Raspberry Pi and the other end to your amplifier. Turn up the volume and type the following:
      cd AlertsTube then
      sudo ./AlertsTube.py
      If everything is working as desired then you should hear a beep whenever a button is pressed. One button is responsible for toggling visual alerts on and off, another is responsible for fetching todays weather and telling you if any weather alerts are currently in progress, and the last button plays tomorrows weather forecast.

    Download the alertsboot script and run it at startup:

    1. Autostart the AlertsTube.py script by typing the following:
      cd /etc/init.d
      Then download the alertsboot script by typing:
      sudo wget https://dl.dropbox.com/u/8170542/alertsboot then
      sudo chmod 755 alertsboot
      You can test the script by typing:
      ./alertsboot start
      If you didn’t see any errors then you can proceed by typing:
      sudo update-rc.d alertsboot defaults to have the startup script run at boot time.

    Part 5: Build the enclosure


    When drilling holes I found a template made of wood helps to ensure button alignment is correct and ensures that the drill bit doesn’t skip around when starting to drill holes in the stainless steel. From the image below you can see I created a lip on the end that would stick out over the edge of the stainless steel wine cooler to ensure there was no vertical movement.

    IMG_0569

    Additionally, I used two zip ties around the wood and the stainless steel wine cooler tube to ensure that the template didn’t move around from side to side.

    IMG_0580

    In my case, I used a cheap drill press from harbor freight tools, but I’m not sure it’s necessary. I also placed a 2×4 inside the stainless steel wine cooler tube, when I was drilling, to prevent the tube from becoming out of round. I drilled the first hole and placed a nail in it to prevent the wood from moving around and did the same for the last hole I drilled. This kept everything in alignment so all my drill holes were straight.

    IMG_0582

    Lastly to remove any small scratches from the stainless steel wine cooler tube, I buffed them out with an abrasive scotch pad.

    For an internal DC power brick drill holes in or around the stainless steel wine cooler top to allow excess heat to escape(not shown). If you keep the DC power supply brick external then the extra holes to allow heat to escape may not be necessary.

    If I had this to do over again, I would place the power cord and USB WiFi on the other side of the stainless steel wine cooler tube. Initially, my intent was to hide everything in the back of the Alert Tube, but since the buttons are handy to use and I don’t mind the look of them I would keep them in the front next time. For the record, I think I’m going to redo the enclosure with those modifications in mind.

    For the top of the Alert Tube, I used the top of the Silver Round Tin with Window. I drilled a couple of holes in the top to allow heat to escape and to enable me to remove the top of the unit for servicing by sticking in a hook and pulling. I lightly sanded the top of the Silver Round Tin plastic window to make it diffuse the light from the RGB LEDs. From there I wrapped some electrical tape along the outside edge of the top to make it a bit bigger and provide a snug fit inside the stainless steel wine cooler tube.

    Once you have all the electronics working gently stuff it in the stainless steel wine cooler tube. I started with the speaker first, screwed it to the bottom, then I screwed in the USB extension cable followed by the push buttons/LED and screwed them in too. Afterwards I placed the amplifier inside, followed by the AC-DC power adaptor then the Raspberry Pi. By this point things are started getting pretty tight inside, so I didn’t need to screw anything else in. Friction fitting seemed to be fine in this case. now at the top, I placed a diffuser over the RGBs inside the enclosure(sanded plexiglass, halved ping pong ball or milk jug plastic). I found that it’s best to keep the RGB LEDs with diffuser an inch away, or more, from the top of the Silver Round Tin with Window to help diffract the light properly. If all goes well then you should have a functioning Alert Tube on your hands that’s ready for action.

    Part 6: Setup and usage

    Setup a gmail account:
    - Setup a new gmail account to receive Alert Tube email notifications and to get calendaring functionality. Once your gmail email account is setup, login -> click on the settings gear in the upper right corner -> settings -> set ‘Conversation view’ to off -> Save changes. I would recommend starting off with a clean inbox for testing, but this may not be necessary.
    Setup a IFTTT account:
    1. Setup a new IFTTT account
    2. Subscribe to Email(not gmail), Google Calendar, and Stocks channels on IFTTT.
      **NOTE** IFTTT alerts work using personal recipes.  When setting up an IFTTT recipe, have the alert sent to the EMAIL CHANNEL, DO NOT HAVE IT SENT TO THE GMAIL CHANNEL!!!  Setting the alert up this way will cause the Alert Tube to not function correctly.
    3. Create your own Calendar Alert and Stock recipe by using mine:
    Functionality and Usage:
    - Every 10 minutes a weather check, a weather alert check and a mail box check are performed to check for alerts.  By default the color sequence for tomorrow’s weather is shown (See “Alert Color Coding” below). When a personal recipe is matched, like a calendar alert via email, an alert is triggered and the corresponding email is deleted.  The calendar alert(blinking blue RGB LEDs) remains active until the next time the mail is checked in 10 minutes.
    *** NOTE *** The weather forecast and weather alerts utilize weather services from the United States of America.  If you live in a different country then you will need to modify the weather forecast and weather alert sources for your own country.

    Button Functionality:
    - Button 1: Toggles on/off RGB LED visual alerts
    - Button 2: Announce today’s weather or current weather alerts in progress, if any
    - Button 3: Announce tomorrow’s weather

    Alert Color Coding:
    Tomorrow’s Weather Forecast
    - Rain: Solid light blue
    - Snow: Flicker white
    - Cloudy: Solid gray
    - Sunny: Solid Yellow

    Weather Alert
    - Alert in Progress: Blinking Red, alert.wav sound played on new alerts

    Calendar Alert
    - Active Appointment Alert: Blinking Blue

    Stock Alert
    - Text to speech audio alert provided with current stock price