You can work in groups of two on this assignment.

Pair Programming

It is strongly recommended that you use formal “pair programming”, where one person (the driver) types/creates and the other (the navigator) observes/assists. Moreover, you should alternate roles so each person takes on each role for a roughly equal amount of time. Remember that a spokesperson will be designated at checkout time, so both group members need to be comfortable presenting the work.


Decide if you will be working in a group or not before configuring a repository . If you will be working in a group, decide who will create the GitHub group and who will join it.

Follow the same basic process used in studios and previous assignments to create/join a group, download the resulting repository (with GitHub Desktop), and import it using the Particle Desktop IDE.

The GitHub Link is:

Files in your repository:

The repository currently contains a few files:

  • contains some questions you need to complete when you’re done with the assignment
  • Garage Hardware files
    • src/GarageController.ino Copy/paste the updated/completed work from the previous assignment.
    • lib/GarageHardware/src/GarageHardwareProxy.cpp Copy/paste the updated/completed work from the previous assignment.
    • You should not add any extra functions in this file, but only edit the contents of the existing functions, leaving the function signature unchanged.
    • lib/GarageHardware/src/GarageHardware.h: This contains the declarations for the Hardware API used by the real hardware. These represent a contract between the hardware team and you. DO NOT MODIFY THEM.
    • lib/GarageHardware/src/GarageHardwareReal.cpp: This contains the definitions for the Hardware API for real hardware. DO NOT MODIFY THEM.
    • lib/GarageHardware/ This contains the directions you need to follow to switch between the hardware checkout with the mini-garage and using your proxy hardware.
  • User Interface Files
    • ui/GarageApp.html is empty, but it should be updated to include the UI from Assignment 2.
    • ui/GarageApp.js is empty, but it should be updated to include the “controller” that will control the UI and interact with the Garage.
    • ui/Garage.js is empty, but it should be updated to include an object that is a reasonably accurate model of the Garage Door Opener.
    • ui/GarageModelTestStub.html is an HTML file that just includes the contents of Garage.js and the Particle API. It can be used to test Particle API calls and the garage model in the JavaScript console.
    • ui/resouces/particle/particle.min.js Particle’s JavaScript API. DO NOT MODIFY
  • documentation/ This contains a description of the files that should be included in the documentation directory when you’re done.

Your (Fourth) Assignment

DBI has decided they’d like you to complete their first internet-enabled garage door opener prototype by combining and extending your prior work. They’d like the prototype to have the following features:

  • All hardware features of the previous assignment need to be implemented and functional
  • The basic open/close features of the UI need to be supported. That is, users should be able to identify the state of the door and open/close the door from the UI
  • The UI needs to show states in a user-friendly way. (This includes information about faults)
  • The “Auto-close” feature should be implemented:
    • The door should behave correctly when auto-close is enabled.
    • Closing the door while an “auto-close” is pending should cancel the pending close.
    • The auto-close feature should be able to be enabled/disabled. Disabling it while the door is open will disable any pending “auto-close” operations.
    • Auto-close should continue to work even if the UI is closed or reloaded. (I.e., auto-close is a hardware feature, not a UI feature)
    • Auto-close will not cause the door to close if there is a fault
    • If the auto-close time is changed or enabled while the door is already open, the auto-close countdown will start as soon as the change is made. For example, if the door is open, auto-close is enabled, and the auto-close time is changed from 90s to 10s, the door will automatically close 10s after the change.
    • The UI should allow users to:
      • Enable/disable the auto-close feature
      • Select auto-close times from 5s-60s (small numbers are chosen to make testing easy, but they should be easy to change)
      • The UI should display auto-close settings consistent with those that are currently set. If the page is reloaded, the settings should be retrieved from the device.
  • (no) User accounts (yet)
    • This prototype doesn’t need to support separate user accounts. (This will be added again for the final product, so don’t completely discard your prior work!)
    • You can leave support for this feature in your HTML.
  • (no) Advanced light control (yet)
    • You don’t yet need to include support for controlling the light’s brightness or the auto-off time yet.
    • You can leave support for these features in your HTML/JavaScript.
  • The API key can be hard coded for now (as it was in Studio 8). It should be implemented with a single global variable so it can easily be updated.

Implementation Requirements

JavaScript/UI Requirements (Variation on Assignment 2 Requirements):
  • You should use the UI to provide a satisfying demonstration that your code works. It should provide a clear understanding of the door’s behavior and the user’s ability to control the door.
  • Single Page Application That means:
    • It shouldn’t be using any <form> elements at all.
    • All HTML should be in a single file using <div>s to contain separate “screens”.
  • Code Organization and use of files:
    • JavaScript, CSS, and HTML should all be in separate files. I.e., there should not be any JavaScript or CSS in the HTML file.
    • As with previous work, you should not use any libraries or frameworks.
    • A garage object that will be used for all access to the hardware.
      • The user should be able to call “setter-like” methods to change state.
      • The Object should follow the “observer pattern” for state updates (support having at least one “listener” function).
      • To ensure that you have proper separation of responsibilities:
        • the garage object should not directly interact with elements of the DOM or UI in any way.
        • The UI should not directly interact with Particle functions/methods in any way.
        • the UI should not directly interact with any properties of the garage. All interaction should take place through methods.
      • The garage object should be in a separate file from the logic that controls the UI (garage in Garage.js and UI logic in GarageApp.js). It should be possible to test it thoroughly independently of the UI.
  • UI Design:
    • The UI should ensure that users have accurate information before acting and limit the ability for errors
      • UI controls should not display until the values have been obtained from the actual garage.
      • If the hardware is off-line when the page is loaded, the controls should be hidden, disabled, or a “loading” page should be displayed.
      • The UI should always be in-sync with the real garage, even if outside forces cause changes in the garage’s state. For example, direct interaction with the garage should be promptly reflected on the UI.
    • User Interfaces should restrict any inputs to appropriate types and ranges.
    • The UI should be responsive and avoid unnecessarily using resources
  • Data Communications Design:
    • The data communication features supported by particle (e.g., variables, function calls, and event streams), should be used in appropriate ways.
    • Unnecessary polling of information from a remote system could use excessive data when this work is converted to a mobile app, so it is not allowed. (I.e., don’t use a JavaScript timer to repeatedly call functions on the Photon). This can usually be avoided by using a publish-subscribe model (Particle’s Event Streams)
  • Miscellaneous:
    • It must use Particle’s JavaScript API (Not Particle’s Cloud API, which uses URLs and HTTP GET/POST/PUT methods).
    • At this point the JavaScript should not need any setInterval or setTimeout for actual functionality (they may be used for visual effects).
Hardware Requirements (Variation on Assignment 3 Requirements):
  • You should use hardware to provide a satisfying demonstration that your code works. It should provide a clear understanding of the door’s behavior.
  • Required Hardware:
    • Four buttons (or use of wires to 3V / GND to simulate button)
      • One to mimic the button to open and close the garage door (described above)
      • One to mimic the Open Switch (described above)
      • One to mimic the Closed Switch (described above)
      • One to mimic a Fault Signal (described above)
    • Three LEDs
      • One to represent the door opening
      • One to represent the door closing
      • One as the garage light (described above)
  • Door Behavior:
    • When the door is down, the open/close button makes the door go up.
    • When the door is up, the open/close button makes the door go down.
    • Pressing the open/close button while the door is in motion should stop the door within 200ms of the button being pressed. The next press should make the door go in the opposite direction.
    • If a fault is detected, all motion to the door should be stopped within 200ms from when the fault occurred (from when the fault button was pressed).
    • When the door starts moving, it should only stop if:
      • there is a fault (the fault button is pressed)
      • it encounters one of the sensors that indicates it has hit the end of its motion (open switch button or closed switch button), or
      • the open/close button has been pressed again
    • If auto-close is enabled, the door should start to close when the designated auto-close time has expired after it was fully openend.
      • Auto-close has no impact on faults
  • Light Behavior:
    • The garage light should come on whenever the door moves and should stay on until the door has fully opened, fully closed, or stopped in the middle due to pressing of the open/close button.
      • Once the door is in one of these three states, the garage light will gently fade out over the course of 5s. You should use the function setLightPWM() to implement this part (not setLight()).
    • When a fault is detected, the light should not only fade out over 5s, but a call should be made to sendDebug(String) with the message “fault”.
  • Initial State:
    • When the door is “powered on” the state could be open, closed, or stopped in-between. The firmware should determine the initial state based on sensors rather than assuming that it is in a specific state.
  • Miscellaneous:
    • The open/close button needs to be held for more than 100ms before the door responds to it (i.e. debounced). The door should start responding by 150ms.
      • i.e. it should not do anything for at least 100ms, but should then start moving within 50ms more. Continuing to hold the button should have no additional impact. So, it isn’t necessary to release the button to impact the door’s action.
    • The door has hard limits on its motion. If either the open or closed switch is activated, the door’s motion should stop within 200ms from when the switch was triggered, otherwise either the motor or mechanical components of the door will be damaged.
    • You should use const int to define constants for any pins used, and all pin references should be grouped together immediately above the setupHardware() function.
    • Nothing from your GarageController.ino should be directly interacting with the hardware, but instead you should be calling functions declared in GarageHardware.h (and defined in GarageHardwareProxy.cpp), which will interact with the hardware.
    • Code on the Photon should avoid the use of anything that blocks execution for long periods of time, like delay() or loops that block execution until complete.

Suggested Work Flow

  1. Review and revise your work from Assignments 1-3.
  2. Review/complete Studio 8 (Cloud 2).
  3. Add support to the firmware (Photon) first.
  4. Be sure your HTML includes the Particle JavaScript API file.
  5. Update the garage object as needed to interact with the Particle cloud.
  6. Update/replace your UI JavaScript from Assignment #2 as needed (only minor changes should be needed).


  1. Review/complete Studio 8 (Cloud 2).
    • Make sure you understand how to use various features of the Particle JavaScript API.
    • The studio has features that may provide insight into an approach that will work for the assignment.
  2. Add support to the firmware (Photon) first.
    • Think carefully about what features/data/interactions will be needed by the UI.
      • What ways will it need to influence the state machine?
      • What information will it need to retrieve?
      • Which of Particle’s idioms (variable, function, or event stream) is best for each?
    • Use iterative development. Add one feature at a time.
    • Test each feature before adding another.
    • Both the online console and Particle Desktop can be used to call functions and “get” the values of variables (The Desktop’s Particle > Show Cloud Variables) and “call” functions (The Desktop’s Particle > Show Cloud Functions).
  3. Experiment with the JavaScript API before focusing too much on garage object. As in previous assignments, you can use GarageModelTestStub and the JavaScript console to interactively try test cases. For example, the following shows the JavaScript console prompts and commands that were entered:
      > var particle = new Particle()
      undefined                      // The return value of the assignment is undefined
                                     // But the variable (particle) refers to an object
                                     // That can be used to access the Particle API
      > particle.callFunction({ deviceId: '2c0...13031',
                                name:     'toggleButton',
                                argument: 'true',
                                auth:     '3842....ea2' }).then(
                                       function() {console.log("good")},
                                       function() {console.log("bad")}   )
      Promise {<pending>}            // The call returned a Promise object
                                     // (And the call hasn't yet completed)
      VM237:1 good                   // The call completed and called the "success" function
  4. Update the garage object as needed to interact with the Particle cloud.
    • Test the garage object independent of the UI.

Artifacts that are Due

  • The documentation directory should contain up-to-date versions of:
    • State Machine Diagram
    • Fritzing circuit diagram
  • A working circuit to demonstrate behavior.
  • A working UI to demonstrate behavior.
  • Completed versions of GarageController.ino, GarageHardwareProxy.cpp, GarageApp.html, GarageApp.js, Garage.js.
  • Completed

Tentative Rubric

UI Behavior (35 points)
  • UI Correctly displays current state at all times (20 points)
    • Includes displaying fault information
  • UI is disabled until current state of the door is loaded (5 points)
  • Auto-close values are handled correctly (10 points)
    • Can be enabled/disabled
    • Delay time can be configured within the specified ranges
Hardware Behavior (45 points)
  • Hardware button should operate as described in previous assignments (10 points)
  • Faults should be handled as in previous assignment (5 points)
  • Lights should behave as in previous assignment (5 points)
  • Initial state is based on sensors, not default value (5 points)
  • Auto-close support (15)
    • Closes door automatically and using the given delay from when it is fully open
    • Time used can be changed, can be enabled-disabled, and updates cause time counting to restart or stop as appropriate
  • Works with mini-garage hardware
Best Practices (20 points)
  • Separate page HTML, CSS, and JavaScript files (5 points)
  • Code is non blocking (5 points)
  • Code is not unnecessarily polling (5 points)
    • See Implementation Requirements section for details
  • Code is easy to read and is properly commented (5 points)

Submission & Checkout

As outlined in the course policies, you must commit work to GitHub and demo it by class time on the due date for full credit.

You need to be prepared to demo and explain your work during your checkout as well as answer the questions in the (The final checklist may help verify that you are ready to demo)

Checkout and review will be done on a first-come-first-serve basis. If you aren’t done before class, you risk not being able to check out during class time. Work demoed after class time is considered late and will either not count as a grade or will consume late day coupons.