Saturday, June 28, 2014

So Long, and Thanks For All the Fish

Substitute your favorite parting phrase for the title, but it all comes down to the same thing. Our class has ended and the project will no longer be receiving updates.

Feel free to leave a comment on this post if you have questions about anything that we accomplished, and we'll get in contact with you and can hopefully help out.

Thursday, May 15, 2014

Javascript - the power of ajax

So, one issue we ran into was the fact that changes to the lights had to be submitted with a web form. The action of the form submitted the light values to another view which would handle the input and then redirect us back to the house list page. It worked great for demonstration purposes but then we started noticing (as we got a long list of lights that we had to scroll through) that, after the redirect, you are put back at the top of the page. So, if you've got a few lights at the bottom that you need to modify, you click on a light and are put at the top of the page and you have to scroll down to find your light again. This was also just a bunch of un-necessary page reloading. In the end, we decided to use javascript's ajax to submit the form without going through all this redirection.

The issue to attack was the fact that it doesn't matter what fancy javascript we put in place because once we hit submit, the form's default code will kick in and it will try to redirect us. so first, we have to suppress the default action of the form. I did that with the following javascript. (all this code runs when the document is ready.)

$("form").on("submit", function (e) {
     e.preventDefault();
}

This was okay because we only have one form on this page. I could have also changed "form" to be the exact id or class of my house list form but I figured it was un-necessary.
Now that this is done and the form will now lie here inactive, we need to send the input to the view ourselves but we also want to do this sort-of in the background. We don't really need feedback from this action as all feedback is already handled. To do this, I used ajax.

So, in order to set up this ajax call, we need to collect the information that would have been sent as the form was submitted. It also needs to be in the same format. I searched for a way to do this and quickly found jquery's "serialize" function. It gets all that data and prepares it to be sent. The only other thing I need is the url to send the data to which we have from the action of the original form.

The code looked like this:

$.ajax({
     type: "POST",
     url: "{% url 'management:submitChange' %}",
     data: $("#houseForm").serialize(),
})


And finally, we need to put both of these code sections together so they run immediately when the page loads. Then the ajax call needs to run on the form's attempt to submit. The finished code looked like this:

$(document).ready(function() { $("form").on("submit", function (e) {
   e.preventDefault();
   if (true){
      console.log($("#houseForm").serialize())
      $.ajax({
         type: "POST",
         url: "{% url 'management:submitChange' %}",
         data: $("#houseForm").serialize()
   })
}})})

I threw in that console.log() for debugging purposes and it is not necessary.
And with that, you have a form that does not refresh the page every time you change a light!
Ahh, the power of Ajax!

Tuesday, May 13, 2014

Schemamigration

As progress is made through any project, there comes a time when the creators realize that the models that they had in mind for the final product aren't sufficient to complete the task. At this point, the models must be revised in order to accomplish the goals of the project.

Unfortunately, if the project that is being built involves a database, this adapting of the model can be a difficult process. In our case, we decided to add in a schedule to every light, room, and house. The Django framework is under strict instructions to create tables, but not to update them. Then, when you choose to add something, the Django website will throw an error because it doesn't understand why there is an extra thing added into its design. If the story ends there, that means that every time we adapt our model we will have to re-create all of the test data that we have generated, adding in the schedule information as we build it new.

Fortunately, the story doesn't end there. The good folks at Aeracode have developed South, a data migration tool for Django projects. South takes care of the difficult task of adapting the database for you. All that one needs to do is set up an initial state of the database with the South tool and then when a change has been made, create and apply a data migration. For our purposes, it worked very smoothly and the tutorial was easy to follow. 

After installing South, there were just four simple commands to run:
./manage.py syncdb
./manage.py convert_to_south myapp
./manage.py schemamigration myapp --auto
./manage.py migrate myapp
The only minor hiccup in the migration was that the database did not know what value to fill in for the schedule for each of the lights. Since the lights are allowed to not be on a schedule, a quick null=true fixed this problem and our app was fully functional again.

Friday, May 9, 2014

Standing Meeting 5/6/14

Our standing meeting felt very good this week, mainly because we were able to accomplish many of our goals:

Update the user's light control page

Implement Schedule 

Add button to turn on/off all lights within a room

Well, maybe we didn't accomplish as many goals as we thought. But we made good progress towards each of them. Arik did successfully revise the interface for changing the state of lights, as you can see from his earlier blog post. Karl's work with implementing a schedule led to some revisions to the initial design. With Zach's assistance, the schedule was revised to contain a list of a new class called Rules so that multiple on and off times can be scheduled through the week. Our system can recognize whether or not a schedule should be on at a given time, but we haven't yet put in the functionality to have the houses (Raspberry Pis) recognize this change. We weren't able to put an interface in for turning on or off the lights in a room, but we did some work on the backend to possibly make this task easier in the future.

Moving forward we have several more goals.

Add button to turn on/off all lights within a room. - Arik

Make the stats tab a relevant tab, rather than just displaying dummy data. - Karl

Finish implementing the schedule, and put into effect Lester's success story. - Zach

Lester's user story: Lester is going on vacation to Kathmandu he is in a rush to get through the airport, but he wants to make sure that his house is set to run as he wants it while he is gone. He calls the company and tells a technician to set his house to run on a schedule, turning lights on and off every 5 minutes in order to make it seem like he is still in the house. The technician follows through with this and Lester's neighbors call his house several times because they are confused why the lights are turning on and off so often.

That's all we have for this week's standing meeting.

Thursday, May 8, 2014

Upgrading the user experience - House List Page

So, our original method to control the lights on the webpage was a list of lights with a check box. Users could change lights by modifying check boxes and then clicking save. While this worked, we were getting a little frustrated with it and we figured that our users wouldn't like it either. From here, we started looking into other options.

The best approach we came up with is the standard on/off switch for each light. Each light will have an on and off button that the user can just click. once the button is clicked, the new state of the button will be automatically updated and the user does not need to push save. I figured we could do this through javascript. I ended up making my own on/off buttons from scratch and got the following:

Now, this worked pretty well but what if the user was mobile? It might be easy to accidentally click on when you meant to click off and that may lead to some frustrations. Karl also pointed out that it was a little hard to tell if the light was on or off. It depends on what the user is used to. So we needed a switch that users are used to. From this, I looked online for Bootstrap Switches and eventually came across some code to simulate the iOS switch buttons! I modified the code to implement these new buttons and got the following:

This was much easier to comprehend! Furthermore, this switch is a single button whereas the last design was two buttons. This means, the user can click on any point on this switch and the javascript function will simply toggle the state of the light and submit the changes all with a single click! The look of the button will then change to match the state of the light.

From here, there are still some changes I need to make. For one, we are still going to put in a switch to change all lights in a room. But for now, we have a good switch design to start with.

Monday, May 5, 2014

Let Me Just Write That Into My Schedule ... Not

I knew when I was assigned the task to develop a schedule for our project it wouldn't be easy. I just didn't have any idea how not easy it would be. I'll review a few of the decisions that we made regarding how schedules will be implemented in our project.

1. Lights, Rooms, and Houses will have schedules. This is opposed to a system where a schedule would be in charge of managing all of the parts of a house. If a schedule were to be in charge of managing the house, it would simplify things because all of the schedule information would be located in one place. On the other hand, Lights, Rooms, and Houses each having their own schedule feels like a better reflection of how the world works. I like to think that I have my own personal schedule that I choose to follow in going to classes and appointments, rather than my schedule ruling over me and dictating what I must do.

2. Triggered events are represented by a start time AND an end time. This decision was primarily made based upon how we plan to implement checking whether or not the light should be on a schedule. The plan is to examine the current time and the light's schedule, and if the current time indicates that the light is scheduled to be in a certain state, then the light will be switched to that state. Then if a user changes the state of the light from its scheduled state, a variable will be set indicating that the light is intended to be in the state that it is, rather than its scheduled state. Once the end time has been reached, this "override" switch can be reset to off so that the schedule will work as planned in the future.

In an ideal world, we would like the database to push information regarding whether the lights should be on or off to the client rather than having the client constantly fetch what state the lights are in on the database. For this reason, our decisions on how to implement the schedule may change in the future. 

Thursday, May 1, 2014

Standing Meeting 4/29/14

With the big rush towards Scholar's Day and the much needed respite after the event, we postponed our previous standing meeting almost a week later than it should have been. Then, in an effort to get things back on a regular schedule, we still had our regular standing meeting on Tuesday, even though we just had our previous standing meeting the night before. This resulted in a meeting without much to talk about. We did plan out our meeting times for the week ahead, because we always find that it is easier to work on the project with others around rather than by ourselves. We have already held our meeting on Wednesday night and plan to have another meeting on Sunday evening.

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.

Thursday, March 20, 2014

Django Bootstrap Toolkit

For this project's web interface, we chose to use Twitter Bootstrap. This way, a lot of design things we would have otherwise had to build manually, we can draw upon a pre-existing pack of styles. There were a few unique issues we ran across as we got this to work, however. For starters, Django will not integrate straight-up Twitter Bootstrap because it doesn't know how. We need a way to use Bootstrap THROUGH Django. After a little bit of Google searching, I ran across a Youtube video tutorial that someone was, among other things, doing exactly this: installing Bootstrap through Django.
The link is as follows: http://youtu.be/utR1KtRFvxg
It was actually quite easy in the long run. Assuming you already have pip3 for python3, you can just run this command:

sudo pip3 install django-bootstrap-toolkit

This will install the django-bootstrap-toolkit for your python3. Once this is complete, you will need to modify your settings.py. The section that reads:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
)


or something like that, just add the following to the end of the list:  'bootstrap_toolkit',
so it would look like this or more. Just make sure you have the bootstrap_toolkit.

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bootstrap_toolkit',
)


Django is now using the bootstrap_toolkit.

Then comes the issue of actually using it. As you could imagine, with the Django integration, you can't always just copy a template from http://getbootstrap.com because, again, Django doesn't know what you're doing if you do it wrong. To start, I couldn't just download the .zip from bootstrap's site. I had to load external css pages because Django didn't know where I was actually putting those files so it didn't use them. If I use external style sheets, they will always work regardless of whether Django know's it's there or not. I did the following:

<meta charset=”utf-8”>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">

<!-- Optional theme -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">

This loads the css pages. I put this within the header tag. Then, for the javascript needed for bootstrap, I did the following:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <!-- Latest compiled and minified JavaScript -->
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>

These lines go right before the close of the body tag because I read that this makes the page load a little faster.

You can now start copying and pasting templates from the twitter bootstrap website to see how they work with your project. I added a navbar to every page by putting it in the base.html template. This ended up covering content. Should you choose to take the same route, make sure to add something like this somewhere in your document:

<style type="text/css">
body{padding-top: 60px;}
</style>

this pushes everything down a bit. Finally, to add the Django dynamic content, put the following within your body tag:

<div class="container">
{% block content %}
{% endblock %}
</div>

put this after any header navbar and your content will appear under the navbar. The {% block content %} and {% endblock %} tags tell Django to put the dynamic content here.

At this point, you experiment. Try adding a visual feature and integrate it in the templates. If it breaks, either fix it or try something different.

Arik

Wednesday, March 19, 2014

Standing Meeting 5: Report from the First Split

This week was the first time that our team tried assigning specific tasks to specific people, let's see how we did.
  • Arik:
    • Make the website look pretty. All that we have so far is black text displayed on a white background. Arik plans on looking into how Twitter Bootstrap can be integrated into Django.
  • 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.
  • Karl: 
    • Re-organize code so that authentication files are contained in one location. Implement the Light model to the project.
  • Entire Group:
    • Write tests for the basic model structure that will be implemented for this week.
    • Further solidify the UML diagram for the project.
Arik's success of integrating twitter bootstrap into our project is a huge confidence boost. It makes our website look like it wasn't built by a fourth grader. Check out our new homepage!


Zach made significant progress towards attaining his goal, but difficulties with the svn repository due to power outages prevented him from being able to complete his goal for the week. 

Karl successfully reorganized the authentication files after quite a bit of difficulty regarding URLs and templates. A light model has been successfully added so that an administrator can add lights to a specific user.

Our lack of tests added for the models to be implemented is due in part to our unfamiliarity with the test first coding practice and also in part due to ambiguous UML diagrams. Since we aren't familiar with how to write tests and exactly what tests to write, it is difficult to complete the task.

There really isn't much excuse for the lack of a further solidified UML, this will be our first priority for next week, hopefully allowing other pieces of the project to be more easily understood and implemented.

These are our goals for next week (or whenever, since we will be going on Spring Break next week):
  • 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.
Napoleon is a registered user of the project HAM website. He wants to see how many lights are currently on in his house. He logs into the website and is immediately greeted by a display which indicates how many lights are controlled by the system in his house and whether those lights are off or on.

The Registration Page

Wilbur's success story was implementing a view that would allow a user to create an account on our website. Like a large majority of the things that we do with our website, the way to implement this came from a very helpful post on Stack Overflow.

Unfortunately, while this provided all the details for how to log the user in behind the scenes, it doesn't provide the method of allowing the user to input their data. Thankfully, this webpage provided a template that can be used for logging a user in. Using this template with the code from the previous post should work right?

Wrong! It was at this point that I was introduced to one of Django's security features, csrf tokens. Cross Site Request Forgery Tokens are used to prevent malicious websites from accessing our websites data. Sounds like a good idea to me, as long as I don't have to spend valuable hours of sleep figuring out how to make it work with our software engineering project. The fix was simple enough, I just had to add one line of code:

{% extends "base.html" %}
{% block title %}Create an account{% endblock %} 
{% block content %} 
<h1>Create an account</h1> 
<form action="" method="post"> 
    {% csrf_token %} <--------------This line needs to be added.
    {{ form.as_p }} 
    <input type="submit" value="Create the account"> 
</form> 
{% endblock %}

Now I don't know if my site will be more protected because I added this one line of code, but I do know that it lets me experience success logging in, and that's what's most important to me right now!

Tuesday, March 18, 2014

Logging in Unit Tests

This past week I've been working on implementing Amber's success story into 'unit test format.'  We already had a test making sure that a user is added to the database, but we thought that actually logging in was something different.  I had little to no experience with unit tests, and the environment so my first few attempts were spent figuring out how things worked.

Eventually I came across a hidden section in the django tutorial using Clients.  This is perfect for what I was looking for, as I can use the client to 'post' their username and password to the login page.  I created two tests, one for a successful login (correct username and correct password), and one for an unsuccessful login (correct username, incorrect password).  The way I was checking to make sure it was working (for the successful login) is listed below:

  1. Create test user (Username = Amber, Password = password)
  2. Create client
  3. Client posts <Username = Amber, Password = password> at '/login/'
  4. Save the response code from the post.
  5. Check to make sure that the HTTP response code was equal to 200 (the OK response code).
I did the same process with the incorrect login information, and checked to see if the response code WASN'T equal to 200.  The successful login worked, and the unsuccessful login test failed.

After I spent more time messing around with the tests, I discovered the problem.  After a login attempt, successful or otherwise, the system redirects the user towards the correct page (profile if logged in, and login page if not).  Well the system does a GET request to grab that correct page, and the HTTP request always sends back a 200.  That means no matter what, both tests were always returning a 200.  The HTTP request I was saving was bypassing the POST request and going straight to the GET request.  I am not sure why this is, but it is obviously a problem.  

My next possible solution is to have the client login, then check what view the user is currently on.  For the successful login I will assert that [location] (which is saved along with the HTTP code) is equal to /accounts/profile.  While with the unsuccessful login I will assert that [location] is equal to /login/.

I haven't gotten time to attempt to implement this new strategy, as we were unable to pull our project from our SVN repository on Dijkstra.  I will edit this post once I have implemented it.

Tuesday, March 11, 2014

Standing Meeting 4: Breaking Out

Let's start the review of our standing meeting how we always do, what is our progress from last week?
  • Create a subversion repository for our project.
  • Implement tests to simulate Amber's success story.
  • Develop a mock-up of what we expect the user interface might look like.
  • Implement Wilbur's success story.
  • Make a preliminary structure of the models that we plan to use in our project.
The past week was very successful, as evident from the number of items crossed off our list. I think that we were even more successful than the list indicates however, because we figured out how we can work more effectively as a team. 

Creating a subversion repository for our project turned out to be an easy goal for this week because we were required to do it in class just after we set the goal for ourselves in our standing meeting. After a little confusion about what the project would be named and who would upload it, we managed to have a version stored that everyone was able to download and simulate the success stories that we had already put into place.

Amber's success story made some initial steps toward completion. We have some tests that create a user and check that they are in the database, but we need to do a little bit more research into how to simulate the user navigating to the website and signing in. Zach will be in charge of completing this goal for next week. 

We developed a mock-up of what the user interface might look like, as well as making a rough UML-esque diagram of the classes and method we expect to use in our project. I say UML-esque because I am fairly certain that we didn't follow all of the conventions of the UML. Despite this, I think it was a very useful exercise. In fact, I think that these two activities were probably the most significant achievements of this week. By outlining how we expect the program might be organized, we have a more unified idea of what the project will look like. 

We also implemented Wilbur's success story. You can expect a separate blog post describing that in the near future.

Before our standing meeting this week, we had another group meeting that was very significant. As we have been working on the project, we have just had one major success story that we tried to implement and we had everyone in the group try to work towards that goal independently. We realized that this doesn't work very well because there isn't a lot of motivation to work on the project. Each group member can independently hope that the other group members will accomplish something. From this point forward, we've decided to give each group member a specific task to accomplish so that everyone has an individual goal to work towards. Even though we have these individual goals, we also determined that it will be easier to achieve them if we gather as a project team to work on them. We plan on having regular meeting times scheduled from this point forward.

So with these points in mind, here are our goals for next week:
  • Arik:
    • Make the website look pretty. All that we have so far is black text displayed on a white background. Arik plans on looking into how Twitter Bootstrap can be integrated into Django.
  • 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.
  • Karl: 
    • Re-organize code so that authentication files are contained in one location. Implement the Light model to the project.
  • Entire Group:
    • Write tests for the basic model structure that will be implemented for this week.
    • Further solidify the UML diagram for the project.
Here's a sneak peak at the UML we started to develop.


Saturday, March 8, 2014

Templates

What's a programmer's favorite part of programming? The finished product? The process of learning a new skill to implement some functionality? Building new worlds to explore? Sure these are all reasons why people might enjoy programming, but I'm going to explain the strange reason why I enjoy programming.

I was working on our website, and was trying to change our view from delivering a simple HTTPResponse() text string to delivering a rendered template file. In doing this, I tried to follow the Django tutorial, but I kept on receiving an error that the template file could not be located. Googling for solutions to the problem just returned results about making sure that template files for specific models are stored with the models. This isn't what I was trying to accomplish. I just wanted a general view for the website. The error explained that it searched for templates in: 
.../projectHAM/templates/site/homepage.html
 but couldn't find the resource specified.

"Umm, excuse me?" I said, "I clearly have that template located in the directory. Just look at my directory structure!"

projectHam/templates/site/homepage.html

Clearly there was something wrong with Django, because surely I couldn't have been doing anything wrong. How can I correct an error that the template isn't in the right space when it clearly is located in the right spot. Frustrated and hungry because it was 6:45 pm and I hadn't eaten yet, I left the obstinate computer in a huff.

After coming back from dinner, I sat down to try and make a deal with the computer. Maybe it would be willing to work with me after it had time to cool down a little. It wasn't long until I was able to fix the problem. Can you guess what my error was?

I mentioned earlier that the error said that the template should be located at 
.../projectHAM/templates/site/homepage.html
which is the way I read it when I was trying to solve the problem. What the error actually said was
.../workspace/projectHAM/templates/site/homepage.html
while I had my templates located in
 .../projectHAM/projectHAM/templates/site/homepage.html
I had spent probably 45 minutes trying to figure out what was wrong with Django when I was the one that placed the templates folder in the wrong directory. After this glorious, "Aha!" moment I moved the template directory to the proper place, reloaded the page, and saw the error screen no more.

This enormous struggle that I had that ended in that wonderful moment when you I realized what I had done wrong and exactly what I needed to do to fix it is why programming is so much fun for me. Those small moments when your world is consumed by a problem and then you finally fix it and everything feels right.

With that said, there are two lessons to take away from this:

  1. If you spend more than 30 minutes trying to fix an error and aren't sure what to do just drop it, walk away and come back to the problem later. A fresh perspective is one of the most useful tools for solving a problem.
  2. Read the whole directory structure, of where template files are supposed to be located. It will save you approximately 45 minutes of struggling with what seems to be an impossible problem.
Now that our website uses templates for returning views, we can do some pretty cool features, like identifying our users by name when they log in. Here is our new "congrats, you're logged in" screen.




Thursday, March 6, 2014

Unit Test Exceptions in Python

One of the goals for the next meeting was to develop tests for logging a user in to the system. This is something that is to me personally as a software developer, so I was grateful that the Django tutorial covered how to run tests in Python/Django. I did run into some difficulty though, when it came to trying to retrieve a user that was not in the database. Trying to do this would raise an exception during execution of the program.The Django framework has a method for expected exceptions called assertRaises(), but when I tried to use this, I kept getting an exception during run-time.

I thought to myself, "What's the point of this silly method? It's supposed to detect when an exception is raised, but it doesn't catch the exception before it is thrown." Here is how I was calling the assertRaises() method.
self.assertRaises(User.DoesNotExist, User.objects.get_by_natural_key('fyodor'))
Can you guess why I was still getting an exception? I'll give you a hint, it has something to do with how function argument are passed in the stack frame. Still stumped? I'll show you the solution, and maybe that will give you an idea.
with self.assertRaises(User.DoesNotExist):
    User.objects.get_by_natural_key('fyodor') 
The exception was still being raised because when function had arguments, they are placed on the stack before the function is called. This means that User.objects.get_by_natural_key() was being called before the program called the assertRaises() function was called. The program had no idea that the exception was expected at that point, so the test kept on failing.

At least, that's how I made sense of the scenario.

Standing Meeting 3: Successes and Failures

As always, we begin our standing meeting by reviewing our goals from last week.
  • Create a simple log in page for the website. 
  • Create a subversion repository for our project.
  • Implement tests to simulate Amber's success story.
  • Allow Amber to experience success in her user story.
  • Develop a mock-up of what we expect the user interface might look like.
This week, we for the first time experienced both success and failure in our goals. We were able to make a website for our users to log in to, but failed to build the framework on the back end to build our project. I think that we are still going through the stages of becoming familiar with Python and Django, which is keeping us from being able to look to the future of our project. As we become more aware of our tools and what we can do with them, we will be able to visualize how our project might form so that we can begin building that road. To make a very poor analogy, we are chefs who are cooking a dish from a foreign country. We have cooking (programming) skills already, but we are most familiar with the foods (programming language, backend infrastructure) of our own country (Java, C). Until we've had the chance to experiment with the foods from the foreign country (Python, Django, Web application programming, unit tests, subversion repositories) we won't know how to craft them into an expert dish.

With that said, we have to accept that some of our goals might be unattainable with our present skills, but they might be more accessible later on. We added to our incomplete goals a few new goals for this week.
  • Create a subversion repository for our project.
  • Implement tests to simulate Amber's success story.
  • Develop a mock-up of what we expect the user interface might look like.
  • Implement Wilbur's success story.
  • Make a preliminary structure of the models that we plan to use in our project.
What's that you say? What is Wilbur's success story? Well I'm glad you asked.
Wilbur is interested in this new craze going around his neighborhood, he's heard something about being able to turn lights on in his house without actually touching the light switch. His friend, Amber, says that he can sign up for an account with the HAM website and request that a technician visits his house to set up the system. Wilbur isn't sure about having a stranger coming into his house to fiddle with electronics, but he figures it couldn't hurt to sign up for a website. He navigates to the HAM website and creates a new account. He then logs in to the website.
While we currently aren't sure if this would be something that we would allow at our company (maybe users would have to install the system before they can have an account on the website) we hope that it will be good to experiment a little bit with the food and learn something in the process.

Monday, March 3, 2014

Amber's Success

After a long period of struggling, Amber has finally experienced success with her user story! Amber was able to access the website and log in using her name and a password. Amber is slightly confused by the website though, all that shows up is some small 12pt font in the upper left corner that lets her know that she has accessed the website. She then has to add "/login" to the address bar to bring up the log in screen so that she can enter her credentials. After logging in, a familiar mostly blank screen appears with some different text this time that says "You are now logged in!" Even more confusing, in order to log out, she has to navigate to a "/logout" page. Not the most useful website in the world, but she feels secure knowing that she has an account with this website.

Finding out how to get a standard user to log in with Django's framework proved to be a fairly complex process. After wading through seemingly endless looping links in the Django documentation, I finally stumbled on this page that seemed to be just what I needed. I found that looking at the "login_required" section was particularly helpful. Adding this redirected me to a predefined URL which should host the log in page. Unfortunately, there was an error with displaying this log in page. I was probably missing some obvious piece of code, but it seemed to me that the django directory was missing some template files. By searching in the directories for this log in template, I was able to come across another log in template for the admin half of the site. I pasted this template into the directory that the log in page was looking for the template and I had an instant (though incorrectly labelled) log in page. Using my knowledge from the Django tutorial, I put together the simple text pages that greet the user to the website and notify them that they have logged in.

I hope to come up with a more elegant solution to this log in problem in the future, but for the moment, it feels so good to have completed this first step.

Saturday, March 1, 2014

Django Woes: "You mean I don't have to write code?"

While I was going through the tutorial for Django, I have had some fairly emotional experiences (considering that all I am doing is writing computer code). The first one was when I was accessing the admin portion of the site that I had just effortlessly created. I then recreated the view of the polls so that instead of just listing the text of each of the entries in the database, it also displayed the date that they were published and whether or not they were published recently. I then edited the code so that Django was aware that the was_published_recently() method returned a boolean value. After doing this, little green check marks appeared where True was earlier displayed. This simple aesthetic change was so unexpected and pleasant, I may or may not have raised my fist in the air and screamed a little bit.

The second emotional experience I had was in tutorial 4. We wrote some pretty generic views in tutorial 3, and then we replaced a good chunk of the code in tutorial 4 with generic code that took up a lot less space. I should have been happy that there was a much easier way to do the code that I had just written, but instead I was angry that I had to erase the code that I had so carefully crafted earlier. This is something that I should learn to overcome as an extreme programmer though, because there might often be times when it will be better for me to get rid of code and write new code than stick with older code.

A final note on the Django tutorial. Since it went through the process of logging in with an admin account, I thought it would also go through the process of how you could implement user accounts. Unfortunately it didn't, leaving our project in a precarious place. There seems to already be a useful built in user account system, but I worry that we won't be able to implement it correctly and cause problems later in the development process.

Thursday, February 27, 2014

Standing Meeting 2: Get Set.

Our second standing meeting started with good news! We went over our list of goals from last week:

  • Install Python3 on the server
  • Setup a MySQL database for the Django framework to access
  • Create a website which our potential users could access*
The last item has an asterisk because the "website" that the users can access is nothing more than a page that notifies that a web server is running, but there is no content on the site.

We then proceeded to set goals for next week. This included developing a user story which we plan to implement. This is our first user story:
Amber wants to log in to manage to our web service to manage her home. She navigates to the log in page, inputs her credentials, and is greeted by a welcome page.
Here is what we decided on.
  • Create a simple log in page for the website. 
  • Create a subversion repository for our project.
  • Implement tests to simulate Amber's success story.
  • Allow Amber to experience success in her user story.
  • Develop a mock-up of what we expect the user interface might look like.
In order to reach these goals, we will each independently walk through the Django tutorial so that we are at some level familiar with the framework that we are using. We plan on completing this by the start of the weekend so that we can work on actually building our website over the weekend and implementing our user success story.