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.