Lab 02b: Logging Walking

Sharing Our Steps

The questions below are due on Thursday February 14, 2019; 10:00:00 PM.
 

Partners: You have not yet been assigned a partner for this lab.
You are not logged in.

If you are a current student, please Log In for full access to the web site.
Note that this link will take you to an external site (https://oidc.mit.edu) to authenticate, and then you will be redirected back to this page.

POSTing Music

 

Goals:Today we're going to pick up from where we left off in the previous lab. At the end of Lab 02A, we had a device that could count steps. What we're going to do today is merge your working system with one other state machine (if you designed your step counter as a state machine, that means by the end of lab you should have two of them running on your system)

We are working with a shared database today, which all students can see. Any attempt to or successful execution of posting anything offensive, inappropriate, or malevolent will have serious consequences. Please see the Student Responsibilities Page for more information. Do not ruin this for the class.

One common type of IoT device acts by acquiring sensor information from the world, performing some computation on the information (sensor conditioning), and sending information to a server (aka the Cloud). The server is nothing more than a computer sitting in a room somewhere. That server stores the data from the device in a database, along with data from many other connected devices, and performs computation on that data if desired. It may then send that information back to the device or share it with other devices (or the world).

We're going to implement a similar system with our step counter. Our "cloud" is our personal class server, 608dev.net, a server located in New Jersey of all places, which will store all data sent by the embedded systems in the class. In Exercise 03 (not available yet), you'll start to work on the server itself, but as we don't want to go too crazy too quickly we'll leave that alone for today. Instead, we'll focus on developing the mobile, embedded part of the IoT system.

1) HTTP POST

Last week we used the HTTP GET method to receive and partially display fascinating numerical facts from our server1. This week, we'll introduce a new HTTP verb: POST. In web browsing you use the POST method a lot less than the GET method, but one example where a POST method is usually involved is when you fill out some sort of web form. Often these will pack up all the data in the form and send it to the form-processing script as a POST request.

The purpose of an HTTP POST request is to POST data to some sort of persistent storage mechanism (a database). POSTs can support large files. With this in mind, we can now reevaluate a bit of how we understood GET requests from last week. A GET request should generally be an action that "gets" information from a host, whereas a POST request should be a way to contribute or place information on the server/host. There are more complicated and/or official definitions, and, as we'll see later in the class, these rules aren't necessarily always enforced, but it is a good way to start working with (and thinking about) them.

Here is what a typical POST statement looks like (If you remember GET requests from Lab 01B last week you'll see it is very similar). Note internet.com is an actual website, but we're just using that here as a generic server name.:

POST /folder/spot HTTP/1.1
Host: internet.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 22

thing1=value&thing2=89

The POST request has two parts, the header and the body. The general format is: first comes the header, then a blank line, and then finally the body. This should seem familiar from studying the HTTP response format from last week (remember there it was also header, blank line, response body, etc.). The POST header will provide specific information about the POST in general as well as details regarding the POST body which the host/server uses to parse and make sense of the incoming data. Let's analyze it line by line.

First, after establishing a connection with the host of interest, which is generic server internet.com, we send the following, which contains the POST HTTP verb, the URI where we want to POST and the HTTP version number.

POST /folder/spot HTTP/1.1

Following this, the next line specifies the host, which is

Host: internet.com

So far, so similar, to the GET request format. Now new stuff will appear. Next is a new line specifying how the data being POSTed is formatted:

Content-Type: application/x-www-form-urlencoded

The host uses this line to determine how to interpret and parse the incoming data found in the body of the POST (covered below). We will usually use either this formatting, application/x-www-form-urlencoded, or application/json in this class, although there are many more formatting specifications that could be used.

Next we have a line telling the host how long of a POST body to expect. This will of course be determined by the body which you create down below. In our particular case, our POST body is 22 characters long (go ahead count it to convince yourself):

Content-Length: 22

Finally, after our blank line to indicate the end of the request headers (remember the blank line from last week), we'll then add our actual body, consisting of the data we want to post. In this formatting specification, we add the data in key-value pairs here: the value of thing1 is value and the value of thing2 is 89, separating out the pairs with ampersands (&)

thing1=value&thing2=89

And then we're done.

One thing you'll notice is that you can't create your POST line-by-line in order as we described it above since the header line regarding Content-Length obviously requires knowledge about how long the POST body will be. Be aware of this as you're developing your code.

2) Step Logging

We are going to integrate our system with one of the class servers where we're serving an application for tracking everyone's steps located at https://608dev.net/sandbox/stepcounter. We'll use this application in several different ways:

  • If you just go and visit this page in the browser, http://608dev.net/sandbox/stepcounter, which is performaing a HTTP GET request via browser with no query arguments specified, it'll render a table listing the entire class step-count leaderboard.
  • If you perform a POST request to the application using the format discussed below, the application will take the POSTED number of steps, add them to the specified user's steps already recorded, store that in the database, and then return the total user's steps taken so far in its response (just like how a GET request can initiate a response from the server, a POST request can as well!)

An example POST format in this framework would look like the following. Let's say your username is rober_donat and you just took 39 steps. You'd want to generate the following HTTP POST to http://608dev.net/sandbox/stepcounter:

POST /sandbox/stepcounter HTTP/1.1
Host: 608dev.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 26

user=robert_donat&steps=39

Download the example POST code for today, upload it and study what it is doing. For easy-reading and organization we've split the code into two files today (you can switch between them using the tabs of the Arduino editor). There is a function called do_http_request which is nearly identical to the do_http_GET that we used in Lab 01B from last week except that is generalized to allow us to send any form of HTTP request (GET or POST). In particular you should see that the main body of code (loop) is sending a POST request to the stepcounting site which states that the user test_user has taken one step every 6000 milliseconds.

By viewing the Serial monitor one can see that the total number of steps submitted for test_user is returned in the response body to the POST request (compare this by visiting the page in the browser). Also be aware that everyone else in the class is running identical code at first so everyone is reporting that test_user has taken one step. test_user's steps will therefore be increasing at a rather quick rate. Later sections may start to have a hard time finding test_user as the table gets filled up

3) Final Assignment

Your goal in this lab is to develop a system which works like the following (shown in the video below):

In particular your system should:

  1. Re-use your step-counting algorithm that you developed in Lab02A into a single callable function which utilizes global variables,
  2. Utilize a second state machine that will POST your users steps to the database and re-zero the current count
  3. Use a second button to decided to either display the current local tally of steps or the global tally of steps you've taken in a stateless way.

DOWNLOAD THE FINAL CODE SKELETON THAT WE ARE PROVIDING-->HERE<--for you to integrate all this functionality (as well as bring in your code from Lab02a).

The code has the general shape below (for reference):


void setup(){
  //initilzation things including WiFi, IMU, and LCD as well as any variables for your state machine
}

void loop(){
  //GET INPUT INFORMATION:
  imu.readAccelData(imu.accelCount);
  float x,y,z;
  x = imu.accelCount[0]*imu.aRes;
  y = imu.accelCount[1]*imu.aRes;
  z = imu.accelCount[2]*imu.aRes;
  uint8_t button1 = digitalRead(input_pin1);
  uint8_t button2 = digitalRead(input_pin2);
  float acc_mag = sqrt(x*x + y*y + z*z);
  float avg_acc_mag = 1.0/3.0*(acc_mag+old_acc_mag+older_acc_mag);
  older_acc_mag = old_acc_mag;
  old_acc_mag = acc_mag;


  
  step_reporter_fsm(avg_acc_mag); //run step_reporter_fsm
  post_reporter_fsm(button1); //run post_reporter_fsm 
  lcd_display(button2); //update display (minimize pixels you change)
  
  while (millis()-primary_timer<LOOP_PERIOD); //wait for primary timer to increment
  primary_timer =millis();
}

Subdivision of the system's functionality. You've basically done the first one. That means you're 33.3% there!

We've changed the button pins in this lab (don't use pin 19 for your button anymore)

We'd like you to break your functionality into two state machines that run in parallel and one stateless LCD control function.

  • step_reporter_fsm(avg_acc_mag);: This should be a packaged-up version of their step counter from Tuesday.
  • post_reporter_fsm(button1);: State machine controlling POSTing. Uses Button connected to Pin 16 as an input. Should POST on the release of the button
  • lcd_display(button2);: A stateless display selector based off of the second button (connected to Pin 5).

In the serial monitor read what is returned in response to a POST! It should be all that you need to render stuff on the screen! You SHOULD NOT need to do a separate GET request to find the total steps

After studying the code above and the overall structure, meet with a staff member for a bit to discuss your design and how everything will come together:

Checkoff 1:
Discuss HTTP POST requests with a staff member in general and in this specific case. Contrast with an HTTP GET request. Discuss the high-level design of the final deliverable for today and how you will integrate Lab02a's code in with it.

Get your entire system working! There should be minimal to no blocking in your functions. When a staff member sees it, this thing better flow like wine (no weird hang-ups from some while loop waiting on a button or gross calls to the delay function. Make sure your display isn't clogging the flow either by minimizing what is changed on each iteration.

The POSTing event via the do_http_request function as written is inherently blocking, but with good network connection should be able to execute in a 100 milliseconds or so, so for today we don't need to worry about this time delay and we can assume a POST event is sufficiently non-blocking.

When you are ready, demonstrate your working system to a staff member via the checkoff below.

Checkoff 2:
Show your working system to and discuss its implementation with a staff member. What are some potential failure points with the system? How could it be improved?

Happy long weekend! Exercises for Week 2 are due one day later, due to the long weekend (so, Monday at 11:59pm instead of Sunday night). Office hours will shift to Monday as a result.


 
Footnotes

11, for example, is the loneliest number, and 12, it turns out, is the largest number (if your screen truncated properly). (click to return to text)



This page was last updated on Thursday February 14, 2019 at 11:41:42 AM (revision ac1c833).
 
Course Site powered by CAT-SOOP 14.0.4.dev5.
CAT-SOOP is free/libre software, available under the terms
of the GNU Affero General Public License, version 3.
(Download Source Code)
CSS/stryling from the Outboxcraft library Beauter, licensed under MIT
Copyright 2017