Synopsis
===============================================================================
McCormick Stir Fry is known for its high quality and wide variety of choices for customization. However, many students complain about waiting more than twenty minutes for their stir fry when they could use the time to work or study. We developed a solution in the form of an online order and pickup system for McCormick dining hall stir fry.
Students will be able to place their orders online in a webform. The chef will be able to use our device to print out the online orders and fill them. When completed,
the chef will type the number into our device and the student will receive an email notification, prompting them to go down to the dining hall and pick it up. Now, overworked students can place orders online and do other productive tasks
while they wait for their stir fry to be completed. We hope that this iteration of Fry on the Fly demonstrates that this concept is viable for future implementation into the McCormick Dining Hall.
Overview
===============================================================================
Develop a webform that students with unique Kerberos IDs can use to order stir fry. The form should include the following categories with checkbox options and comment sections:
- Protein (tofu, chicken, beef, etc.)
- Vegetables (carrots, tomatoes, spinach, etc.)
- Spices (chili flakes, salt, pepper, etc.)
- Starches (rice, rice noodles, penne pasta, etc.)
- Sauces (teriyaki, hoisin, pesto, etc.)
Some additional pages and dialog boxes you may want to include are:
- Home page: include basic instructions and a “View Status” button where users can enter their Kerberos ID to check on the status of their current order
- Confirmation page: displays order after user hits submit button
- Invalid Kerberos box: pops up when someone enters a Kerberos to view the status for without an order associated with it
- Duplicate Order box: will not let user submit an order if they already have one in the queue
Additional Challenges:
- Create a wait time estimator (completed)
- Have an option to enter and save or autofill frequent orders
- Integrate online order system with live queue
- Protect user information via encryption
- Charge for stir fry electronically
Video Demo
===============================================================================
Functional Block Diagram of the System
===============================================================================
![Figure [block_diagram]: Functional System Block Diagram](http://web.mit.edu/varnika/www/fryonthefly/functional_block_diagram.png width="600px" border="1")
The student orders their stir fry via an online form. Once they hit submit, their order details are posted to our database. The chef presses a button on the keypad to send a `GET` request from the database to the ESP32. The thermal printer connected to the ESP32 prints out the order on receipt paper. When the chef is done, they enter the order ID into the keypad, which causes the ESP32 to post to the database. The database then sends a `GET` request to update the status of the order.
Parts List
===============================================================================
From 6.08 Curriculum
- 1.4" TFT LCD Screen
- ESP32 Dev Kit
- Breadboard
Purchased
- Thermal Receipt Printer Guts
- 4x4 Keypad Matrix
- 3A Boost Converter (to supply 1.5A for printer)
- Thermal Paper Roll
- Push button
Discussion
===============================================================================
Assumptions
-------------------------------------------------------------------------------
- There is a one-to-one mapping between the ingredients on the form and the ingredients available to cook.
- Students pick up their orders on time.
- Chef remembers to press buttons and enter order IDs.
- No live queue--everyone uses online form for ordering stir fry.
- For wait time estimator: The chef cooks exactly three orders at a time (starts a new order directly when one finishes--not rounds of three that start and end based on the longest order).
Design Challenges
-------------------------------------------------------------------------------
1. The webform.
*Solution:* Thanks to Material Design by Google's CSS links, we were able to make the form and relevant webpages both aesthetic and functional, complete with a navigation bar. At first the CSS and images didn't link properly, but Joe helped us with that. We started out with just a home page, order form, and contact page. Later, we realized that adding confirmation, "form closed", "duplicate order" and "invalid Kerberos" pages would be helpful too.
*Rationale:* Our goals were to make the website user-friendly and flexible to all orders and adversarial actions. We made the "Submit" and "View Status" buttons active only after a Kerberos between 3 and 8 characters was entered. The "form closed" page would show up (without a navigation bar) outside of dining hours and when the queue is full. We prevent users from submitting multiple orders by linking the "Submit" button on the order form to the "duplicate order" page. Finally, "invalid Kerberos" is for students who try to "View Status" with a Kerberos without a corresponding order in the database.
2. The box enclosure for the keypad, thermal printer, paper, LCD display, printer boost converter, ESP32 voltage regulator, battery, and breadboard wasn't big enough.
*Solution:* We redesigned and reprinted the box twice.
The final box is sized at 20 cm by 9.53 cm by 6 cm. There are two open rectangular slots on the right wall of the box - the one to the left is for charging the battery and the remaining is for reprogramming the ESP32. Looking from the top, the whole front cover is divided into two sections - the receipt's cover and the printer's cover. While the printer's cover is securely fixed, the receipt cover can be easily opened in order for the chef to replace the receipt paper every so often. To prevent the receipt's cover from being misplaced while the receipt paper is being replaced, a hinge is added near the top to keep all the box components attached to the main body at all times.
![Figure [inside_box_1]: Inside of Box](http://web.mit.edu/varnika/www/fryonthefly/isometric_view.png width="600px" border="1")
![Figure [inside_box_2]: Inside of Box](http://web.mit.edu/varnika/www/fryonthefly/top_view.png width="600px" border="1")
![Figure [inside_box_3]: Inside of Box](http://web.mit.edu/varnika/www/fryonthefly/guts.jpg width="600px" border="1")
![Figure [outside_box_1]: Outside of Box](http://web.mit.edu/varnika/www/fryonthefly/box.jpg width="600px" border="1")
![Figure [outside_box_2]: Outside of Box](http://web.mit.edu/varnika/www/fryonthefly/ports.png width="600px" border="1")
Logistical FAQs
===============================================================================
1. How can a user check the status of their stir fry?
*Answer:* Enter Kerberos on Home page and click "View Status".
2. What if someone tries to order again before picking up their current stir fry order?
*Answer:* A dialog box will pop up and say "You already have an order placed in the queue!"
3. What if someone tries to check their status when they haven't ordered anything?
*Answer:* A dialog box will pop up and say "There is no order in the queue associated with that Kerberos."
4. What if someone doesn't pick up their stir fry in time?
*Answer:* Their stir fry will go up for grabs in the dining hall if it isn't picked up within 15 minutes after the chef sends them the notification.
5. What if there are no orders in the queue?
*Answer:* The LCD will display "no new orders" and the chef can take orders from the live queue.
HTML File Descriptions
===============================================================================
- confirmation.html: appears after an order is submitted successfully, displays details of order
- contact.html: if the user has any questions or concerns, they can find our email on this page
- duplicate_order.html: fryorder.html directs here when someone tries to submit an order when there is already an order in the queue associated with the Kerberos
- formclosed.html: appears when dining is closed or queue is full
- fryorder.html: order form with checkboxes and comment sections, the most important webpage
- index.html: home page with "View Status" button
Database
===============================================================================
![Figure [database1]: Database Table Structure](http://web.mit.edu/varnika/www/fryonthefly/database1.png width="600px")
![Figure [database2]: Database Table Structure](http://web.mit.edu/varnika/www/fryonthefly/database2.png width="600px")
*timestamp is a custom type defined by the Python sqlite3 module.
Python File Descriptions
===============================================================================
authstirfryemail.py
-------------------------------------------------------------------------------
This python file uses a token generated from the Gmail API by Google to send an authenticated email to the users when their stir fry is done. This file is used to draft and send emails to users when their stir fry is done, using create_message and send_message. The function build_service establishes a secure connection to the Gmail using our credentials.json file generated from our API. The credentials.json is used instead of a password because if the credentials.json is replicated by someone else, we can generate another credentials.json and invalidate the previous one, unlike a password, where the hacker can potentially lock us out. Also, the credentials.json is set to only have email sending capability unlike a password which offers access to our entire gmail: fryontheflystirfry@gmail.com. It is activated when the chef enters an order number into the keypad by a post request through request_handler.py.
request_handler.py
-------------------------------------------------------------------------------
This script is intended to interface with the embedded system.
In case of a `GET` request, the script will access the oldest entry in the database with a status of 0. It will then parse it and return a string.
The Order ID and Kerberos are separated from the rest of the order by commas to be tokenized on the embedded side. The rest of the string will look something like this:
Protein:
Beef
Veg:
Broccoli
Green Pepper
Spice:
Chili Flakes
Ginger
Starch:
Rice
Sauce:
Pesto
Hoisin
Comments: extra spicy
This is to reduce the amount of string processing which must be done on the embedded side, which is more difficult with C-style strings.
The order that is sent over is then marked with a status of 1 so it is not printed again.
In case of a `POST` request, the script expects `x-www-form-urlencoded` arguments `number` and `status`. The entry in the database with the specified
order number has its status updated to the value of `status`. If `status=2`, the request handler uses `authstirfryemail.py` to send a notification email to the kerberos
associated with that order.
fryorder.py
-------------------------------------------------------------------------------
This script handles the actual submission of an order.
When the user makes a `GET` request, they are simply shown
the form loaded from `fryorder.html`. The user is required to enter their kerberos and fill out the various components of their order:
protein, vegetables, sauces, and so on. The user can select multiple of each component from the provided checkboxes or fill out a custom "other" box.
This file also includes Javascript to prevent the user from submitting forms without
a kerberos or comments that are too long.
Pressing the submit button on the form will trigger the submission of the form's contents as a `POST` request to `fryorder.py`.
The script will check if the request has been made within dining hours, and also determine that there are not too many
orders in the queue.
If all these checks are satisfied, the script will parse the request to extract
all the options selected on the form and then insert the order into the database with a status of 0.
The order number is one greater than that of the previous order, with a limit of three digits, and the time of ordering is determined with the `datetime` module.
The script then returns a formatted version of `confirmation.html`, with the `{}`'s filled in with the contents of the order, so the user can see their order and order number.
status.py
-------------------------------------------------------------------------------
This script allows users to check the status of their order. Pressing the Submit button on the homepage triggers a post request of the inputted kerberos to this file.
The script will check the database and display a message corresponding to the status of the order. If the order is still in progress,
the script will also attempt to estimate a pick-up time based on the orders ahead of it in queue and display that as well.
Arduino File Description and State Machine Diagram
===============================================================================
final.ino
-------------------------------------------------------------------------------
This file contains our state machine for our embedded portion of the project. The states we have include `IDLE`, `POST`, `GET`, and `PRINT`. For `IDLE`, it is waiting for the chef to input key presses in to move to another state. During this state, it will update the LCD with the numbers being pressed, and clearing/deleting them as well. The device will always start and return to state `IDLE`. After all other states are done, the state machine will return to state `IDLE`. When the chef presses the print button, it will go to state `GET`, which will perform a get request from the server to pull the first order in queue to print from the database. Then it will transition into state `PRINT`, which executes the print statements for the thermal printer using the compatible Adafruit library. The LCD will display "Printing..." until the order is done printing. When the chef presses the enter button, it will enter state `POST`. Using the numbers displayed on the LCD, which is supposed to correlate with order IDs associated with users' orders, it will send the number in a post request to the server to mark it as done and trigger a notification email to the user that their order is complete.
State Machine Block Diagram
-------------------------------------------------------------------------------
![Figure [state_machine]: State Machine Block Diagram](http://web.mit.edu/varnika/www/fryonthefly/embedded_state_machine.png width="600px" border="1")
Power
===============================================================================
The thermal printer was the biggest issue for power because it operates by using high temperatures to burn the letters
into the special paper. Thus, it has an especially high power requirement during printing. This necesitated the purchase of another boost converter
capable of sourcing the necessary current, as the one from class could only supply 500 mA. This boost converter also had to be connected in parallel with the
TP4056 regulator, as the TP4056 is limited to 1 A. Even so, getting the thermal printer to operate off of battery power was difficult. While Adafruit, the supplier,
suggested powering the printer from between 5-9 V, we found that the printer worked best in a narrow range of about 3.4-3.6 volts, suggesting the current requirement to be more important than the voltage requirement.
In order to conserve power on our system, we only connect to WiFi when necessary to post order completion or retrieve new orders. In addition,
the thermal printer is put into sleep mode on startup, only woken up before printing, and then immediately put back to sleep. In the `IDLE` state, the system as a whole uses approximately 0.12 A.
To test how long our system could last, we wrote a custom script to automatically make an HTTP request and print a fake order every three minutes, roughly how often the chef
will be printing orders. The request handler was set up to record the timestamp of each request into a database, allowing us to check the lifetime of the system. We saw
that the system lasted for roughly four and a half hours, longer than the three hours necessary for dining. The system contains a mechanical switch and is rechargeable through a hole in the box.
Team Photo
===============================================================================
![Figure [team_photo]: (from left to right) Joe Steinmeyer (Instructor), Julia Wang, Varnika Sinha, Mingfei Duan, Uyen Nguyen ](http://web.mit.edu/varnika/www/fryonthefly/team_photo.jpg width="600px" border="1")