Tuesday, April 29, 2014

Standing Meeting 4/28/14

With our goals for Scholar's Day out of the way and some new goals in mind, we met about where to proceed from our current state. We met and discussed some changes that we would like to make to the user interface and the framework. The main tasks are as follows:

Update the user's light control page - It got the job done but in the long run, we didn't like having the user select check-boxes and then click save to make any changes to the lights. Our goal is to change the interface so each light has an on and an off button. There will also be a way to identify whether the light is on or off based on which button (on or off) is highlighted or depressed. Users can simply click "On" and their update will automatically be sent to the database without them having to click and then save repeatedly. We figure this can be done through JavaScript.

Implement Schedule - We didn't worry about this leading up to Scholar's Day because our presentation time was limited anyway and it gave us time to work on other things but now, we would like to implement at least a basic schedule framework. Users will be able to schedule lights to turn on or off and the lights will carry out this action at the specified time.

Our last thing which will be a combination of front-end and back-end is:
Add button to turn on/off all lights within a room - This is not mandatory to the functionality of the project but we could see that clients would likely want this feature especially if they have a lot of lights in every room. This way, they can click one button rather than having to click all of them to turn off all lights. The On/Off button for the room will work just like the individual lights but it will be in a different place an will likely look different.

With this planned out, our meeting adjourned ready to improve the world! One satisfied customer at a time!

Pi-Side Script

As of right now, we are hosting our database on a central server.  Each PI needs to be able to connect to that database to check if it needs to turn on or off any of its lights.  We ran into some troubles writing the Python script that would accomplish this.

The script was not very long, and was laid out in the following manner.
  1. Establish a connection with the database.
  2. Query the database to check what state of the lights should be.
  3. Check the current state of the lights.
  4. Make any changes to the state of the lights if necessary.
  5. Repeat.
We had no problems except for steps number 3 and 4.  We were using a subprocess call to run a bash command that read in the current state of all our lights.  All we needed was a 1 or 0 to know if the lights was on of off, respectively.  After some time spent troubleshooting, we discovered that all the lights were always being read as off.

As it turns out, the subprocess call() function only returns if the call was successful or not.  Basically in layman's terms our Python script was telling bash to do something, then turning around and giving us a thumbs up that bash successfully did it.  We wanted to know the result of the command, not just that it was being done.

Well, the information we wanted from the command was being sent to stdout.  So how do we get that information into a variable in our script so we can make use of it?  File redirection.

What felt maybe a little dirty, and still looks a little strange perhaps, turned out to work pretty well.  We redirected stdout to a file in our current directory.  Then we had python jump into the file and read what was written there.  Finally, we had the information we needed!  That took care of most of our problems.

There was still a minor problem afterwords with step number 5.  In our script we are essentially running a while( true ) loop, and constantly checking the database/current-state and making changes if necessary with a few if statements.  The problem we ran into was because in Python you don't create your own data types.  You just say var = <whatever>.  Well, the information we were reading from our file was either a 0 or a 1.  A simple int.  Because it was coming from a file however, Python made it into a string.  In our if statements when we compared our string information to an int, we would get the wrong response.  It was a simple fix, simply casting the string to an int, but a problem that took a little bit of time to locate and really showed our inexperience with Python.

Monday, April 28, 2014

Twitter Bootstrap

To keep our website looking professional, we needed to change the list of lights in a given house to look more modern. We were sure that we wanted to use Twitter Bootstrap for this, but we weren't sure the best component to use. I perused the documentation for a while, and attempted to use stacked nav tabs to accomplish the effect. Alas, my attempt was in vain. The day seemed bleak and the sky dark. I handed in my resignation and Zach decided to take up the cause. It wasn't long before Zach found the "list-group" and "list-group-item" class. This seemed to work perfectly for our project, and made our website look much more professional. Here is the example of what our light view looks like now and the code that produced it.

{% if house_list %}
  <form action="{% url 'management:submitChange' %}" method="post" >
  {% csrf_token %}
  {% for house in house_list %}
    <!-- <h3> {{ house.description }} </h3> -->
    <ul class ="list-group">
    {% for room in house.get_rooms %}
          <li class="list-group-item"><h3 style="margin-top: 0px">{{ room.description }}:
                    {{ room.getNumberOfLights }} lights</h3></li>
      <ul class="list-group">
            {% for light in room.get_lights %}

          <li class="list-group-item">&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" 
name="light" value="{{light.id}}"
                        {% if light.is_on %} checked {% endif %}>
                        {{ light.description }}</li>

        {% endfor %}
      </ul>
    {% endfor %}
    </ul>
  {% endfor %}
  <div class="form-actions">
    <button type="submit" class="btn btn-primary"> Save</button>
    <button class="btn" type="button" value="Cancel">Cancel</a>
    <!-- <input type="submit" value="Save"/><input type="button" value="Cancel"/> -->
  </div>
    </form> 
{% else %}
  <p>No lights are installed.</p>
{% endif %}

In the future, we hope to get rid of the check boxes in favor of buttons, which will require altering the method currently in place for communicating changes to the database. 

Tuesday, April 22, 2014

Project Schedule from now until the End

With this post I will outline our project schedule that we have until the end of the year.  We only have 4 weeks remaining to meet our deadline.


  • April 22 - April 28:  Build Popsicle Stick Houses.  Get Bootstrap Working for the rest of the website.
  • April 29 - May 5: Improved Interface /controls for toggling lights on or off.
  • May 6 - May 12: Company Side Support.
  • May 13 - May 19: Investigate additional features such as a video feed or support for other appliances.
We wish to build small model houses out of Popsicle Sticks to easily show how our service can be implemented and used.  We want to finish this before our presentation this upcoming Friday (Scholar's Day).  Another goal we want to have completed for that is a nicer looking website interface for the users to turn on and off their lights.

We also wish to investigate additional controls, such as the ability to turn off all lights in a specific room, or perhaps even the house.  We feel that a checkbox for every light in the house that the user has to go through and click one by one is not the best interface possible.

Right now, we have been focusing mostly, if not entirely, on the user without much consideration for the Company providing this service.  We want to provide a way for the company to monitor all of their clients.  This would require having a copy of every database on each PI in the clients' houses on the Company's server.

Lastly, we would like to see if we can easily add additional features.  It would be nice if users could not only control lights, but also video feeds (for monitoring or security) and other appliances in their home.  This goal is secondary to our other goals, and may not be accomplished if the previous goals take longer to complete than anticipated.

Writing Values to the GPIO Pins

We now know how to set up GPIO for the Raspberry PI and set the pins to output mode and check the current set value of the pins but how do you change the values and what should you keep in mind?

The command to write a value to a pin in output mode is:

gpio write <pin> <value>

for example:
gpio write 0 1

Now, as stated at the end of the last Raspberry PI post, you need to be VERY careful with your PI because your pins are not buffered. You can fry your whole board by overloading a pin! You do not want this!

I found a pin diagram at
http://www.raspberrypi-spy.co.uk/2012/09/raspberry-pi-p5-header/raspberry-pi-gpio-layout-revision-2/
which can help you to see which pins are designed for 5 volts, which are designed for 3.3 volts. We will mostly be using 5 volts as that is easiest to use with microprocessors and is the digital standard.

To test your writing capabilities (and just to have a little fun!) try setting up a simple LED circuit and writing a Python script. Hook up your LED with the anode (long lead) to pin 0 and the cathode (the short lead) to the ground pin. Turn on your PI and write the program. Here in team PorkPI, we use the Linux text editor for real men: VIM. Do the following command:

vim ledTest.py


In this file, we need to make a simple script to flash the light on and off. You can use my code as a template or if you're lazy, feel free to copy and paste for a simple test. The code is as follows:

#strobe_lights
import subprocess
import time

subprocess.call(["clear"])
print('waiting')
#time.sleep(5)
for x in range(0,10):
    subprocess.call(["gpio", "write", "0", "0"])
    time.sleep(.5)
    subprocess.call(["gpio", "write", "0", "1"])
    time.sleep(.5)
    print(x)

subprocess.call(["gpio", "write", "0", "1"])


So, a quick explanation of what's happening here:
We import subprocess which allows us to call bash commands from a python script. If there's a returned value, you can store it in a variable. However, we don't look for return values so we won't worry about it. We also import time so we can slow down the script enough so we can actually see the light flashing. (if you don't know what i mean, remove all the time.sleep(.5) lines and watch how fast it flashes. It will likely look like it's just solid and on.)

So now we are able to control a light that's attached to the GPIO pins! From here, to go on a larger scale, we would need to use a relay instead of an LED and we could control much larger things. But for now, this will be enough for demonstration and learning purposes.

Accessing Databases via Python

In order for our Raspberry Pis to be able to turn off and on their lights according to the state on the website, some sort of interfacing with the database outside of the Django framework will be required. This can easily be accomplished using the same PyMySQL module that allowed the Django framework on Python3 to be compatible with MySQL. What follows is a basic script which we used to access our database and get information about the states of the lights. By modifying this basic script to include code that Arik has been posting about GPIO reading and writing, our application should be nearing a usable state where modifying the database equates to a change "in the real world."

import sys
import time
import pymysql

lights = {'bathroom light 1':0,'bathroom light 2':1,
        'kitchen light':2, 'bedroom light':3}
conn = pymysql.connect(
db='database',
user='user',
passwd='password',
host='123.45.67.890',
)
cur = conn.cursor()
cur.execute("SELECT * FROM lightDB WHERE user_Id = <user_id>") 
for line in cur:
    for key,val in lights.items():
        if key==line[1] and line[3]==1:
            print("turning",key,"on")
        elif key==line[1] and line[3]==0:
            print("turning",key,"off")
Each line in cur is a tuple that has various information about the lights, the 1st (line[1]) item in the tuple is the description of the light, and the 3rd (line[3]) item is the state of whether the light is off or on.

There are some obvious security concerns at this point if this database were a database maintained by the company which contained all of its users lights. For this and other reasons, we are considering restructuring our design regarding where the server for the lights is run and how the information is accessed/backed up. Look for more on this in a later post.

Wednesday, April 16, 2014

Standing Meeting 7: Back in the Flow

Let's look at our progress from last week:
  • Arik:
    • Develop the way that we will implement having the database of lights control the Pi.
  • Karl:
    • Develop the method that will allow users to change the states of lights through the website. These changes must also then be reflected in the database. 
  • Zach:
    • Assist both Arik and Karl in accomplishing their goals
  • Whole Group:
    • Implement Snowball's success story.
Karl succeeded in plugging in functionality on the website so that users can alter the database of lights by selecting which ones they want to be on and then saving their selection. Arik suffered a more terrible fate, as his goal was less clearly defined than Karl's. Figuring out how we will integrate the Raspberry Pis into our databases is proving to be slightly more difficult than we had anticipated. We are fairly certain that we want the application to be run on the client side. This way if the internet service provider experiences an outage, the user would still be able to alter the state of lights in their house. Unfortunately, this probably means that we will have to look into some sort of mirroring system to keep the Company and the client side databases identical. We will describe the details of that problem as we ourselves become more familiar with them.

Karl found great benefits to having Zach as a "roamer" in the group. Being able to voice ideas out loud helped him to more quickly identify the problem and find a solution. 

Going forward, we of course have set more goals:
  • Arik:
    • Clean up the parts of the website that do not yet implement Twitter bootstrap code. 
  • Karl:
    • Help both Arik and Zach work towards their goals. Develop unit tests to keep our code maintainable.
  • Zach:
    • Explore a possibility regarding how we might be able to connect the Raspberry Pis to the database.
  • Whole Group:
    • Connect the entire system so that a user can alter a light through the website and see the result on the Raspberry Pi.
That's all for now, happy coding!

Thursday, April 10, 2014

I Speak the Language of URLs

While I was trying to accomplish my goal of allowing users to turn on a light, I ran into a problem. I wanted to direct users to a new page when I clicked on a link. I put in the URL that I wanted them to be directed to and created a page to correspond to that URL. Still being confused with the "reverse lookup" patterns that Django offers, I wasn't surprised that I received an error when I tried to click on the link. I probably worked on this problem for an hour straight before I was able to discover the problem.

Django offers regular expression matching for URLs so that a new URL doesn't need to be written for every page on a site. One of these special characters in a regular expression is a '$'. I had seen this dollar sign before, and knew that I could put it on the end of URLs. In fact, most of the URLs I wrote in the Django tutorial had this character hanging on the end. I naturally included this in my URLs that were being used to navigate to the new page.

The key that I was missing out on was that the '$' character represents the end of the line. This means that the '$' character should only exist in a URL regular expression if there is no possibility for more URL to come after. I had foolishly put one of these dollar signs at the end of one of my URLs which could still have more content come after it. When Django tried to search for the URL I was expecting, it would reach the '$' and fail to find the page I was trying to access. After removing the dollar sign, everything worked great.

So the lesson to be learned is: "Pay careful attention to all of the components of an error statement and make sure that you know what all of them mean." The dollar sign was staring me in the face the entire time that I was working on the problem, and I assumed because I didn't know what it was, it wasn't important. Bad decision. On a related note, the '^' symbol represents the start of a string, so watch out for that guy too.

Standing Meeting 6: Return from Break

Let's see what we accomplished since our last meeting.
  • Arik:
    • Continue to update new pages which we develop to be wrapped in the beautiful environment that is twitter bootstrap.
    • Develop the House model for the management app.
    • Implement tests for the house model.
      • Adding a house to the database.
      • Adding a room to the house.
      • Removing a room from the house.
      • Accessing a house by the user.
  • Zach
    • Complete tests to simulate Amber's success story. This will be accomplished by checking to make sure the views that are returned are the correct views for a logged in user.
    • Develop the Room model for the management app.
    • Implement tests for the room model.
      • Adding a room to the database.
      • Adding a light to a room.
      • Removing a light from the room.
  • Karl
    • Solidify the UML diagrams for the project. Make these in the Violet UML editor.
    • Provide users with a view to see what lights are in their house, not necessarily organized by house or room.
    • Allow users to change the state of a light.
  • Whole group
    • Start programming on the Pis, install all necessary software on the devices so that they can function as our "houses".
    • Implement Napoleon's success story.
    Arik has the unfortunate task of always updating the website's common look-and-feel, which is never really completely done, so he will never be able to completely check that item off of his list. Arik did not implement tests for the House model, but some of those tests are contained within other tests because houses are required to add rooms and lights. 
    Zach completed all his objectives except for the test to simulate Amber's success story. Since this is proving to be much too difficult to be worth pursuing, he will be abandoning this task. Karl may try implementing using a different method, but for now it is incomplete. 
    Karl failed yet again to make official looking UML documents for our project. The temptation to continue using our whiteboard picture has proven too strong. Karl also failed to implement the user being able to change the state of the light.
    The whole group was successful in installing software on our Pis that we will need in the future. The end goal is to have the Pis run a Django server, which we have not verified is possible yet, but we believe we have all of the required software.
     We were also able to implement Napoleon's success story. When a user logs in, they are now immediately directed to a page which shows all of the lights that they have in their house, arranged by room. We have yet to add a common look and feel, but it is encouraging to see the application really begin to take shape.
    
We held our standing meeting and determined what our goals for the next couple of weeks should be. 
  • Arik:
    • Develop the way that we will implement having the database of lights control the Pi.
  • Karl:
    • Develop the method that will allow users to change the states of lights through the website. These changes must also then be reflected in the database. 
  • Zach:
    • Assist both Arik and Karl in accomplishing their goals
  • Whole Group:
    • Implement Snowball's success story.
Snowball wants to log in to the system at his house and turn off a light. He logs in to the website, and turns off the bathroom light. The website shows him that he has accomplished this change.
This week we are trying something new by really focusing on using the Team Programming approach. You probably noticed that Zach does not have a specific goal for this week. He will instead be sitting beside Arik or Karl while they program and providing a second pair of eyes to look at the code. If there is some discreet task that Arik or Karl find, they could also pass this task to Zach to complete for them.

We will now leave you with a screenshot of Napolean's success story, all of the lights in his house, organized by room:


    

Tuesday, April 8, 2014

GPIO and the Raspberry PI

As we approach the day of full Raspberry PI integration, we have a few things to consider beyond a typical Linux machine like we have on our Ubuntu partitions of our laptops. The Raspberry PI has GPIO pins (General Purpose Input/Output) that are going to be the key to turning these lights on and off. But aside from that, all the rest of our software should work just fine on the PI.

So how do we use these legendary GPIO pins? Well, in my experience from past projects, you can use the complicated way with no software and echoing values directly to the pins, or you can use the easy way where someone has automated the whole process for you and you can control every pin with ease. The software package we are using to make our lives easier is called Wiring PI which can be found at... That's right! you guessed it: http://wiringpi.com . The download and install instructions are on that webpage under "download and install" and they are very clear.

This software package was developed by Gordon Henderson (Twitter: @drogon) and he's made it a lot easier to interact with the Raspberry PI's GPIO interface. Using WiringPI, I am able to run the command:

gpio readall

I will see a chart of all the pins on my PI and their I/O modes and current states:


Now, right now, this probably just looks like gibberish but don't worry, it's actually quite easy. If you look at the "wiringPi" column, you will see the numbers 0 through 20. These are the pins we will be using will probably not go any higher than 7. And in the example above, under "Mode" you can see that each of these pins are on input mode. Now, for us, this is kind of a problem. We don't want to simply wait and observe. We want to MAKE something happen! So the way we make this happen is by putting the pins in question into OUTPUT mode. Let's start with pin 0 because the process is the same for all pins. You can use the command:

gpio mode 0 out

The pin is now in output mode. To check, re-run:

gpio readall

Or, since you are only dealing with one pin, I will introduce you to the command to only read the state of a single pin. It is:


gpio read 0

In our case, we say "read 0" because we are working with pin 0. This will change with your target pin.

A WORD OF CAUTION!
The pins on the Raspberry PI are not buffered. This means that if you have a short circuit or a voltage overload, you can fry not only the pins, but the entire Raspberry PI board! Check, double check, and triple check your wiring before switching it on and NEVER wire things up with the board powered on! This is simply good practice for any type of electronic prototyping because it will most likely eliminate some CRIPPLING mistakes.