> For the complete documentation index, see [llms.txt](https://docs.idew.org/code-internet-of-things/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.idew.org/code-internet-of-things/tutorials/create-security-system/4.9-web-app-js.md).

# D-9 Web App JS

Next, you'll add JavaScript code to allow your web app to interact with your Photon device through Particle Cloud. Remember that the web app will perform these tasks:

1. The web app will display whether the security device is currently armed or disarmed. The web app will do this by getting the value of the `deviceMode` variable in your Photon device app.
2. The web app will display a toggle switch that can be clicked to remotely toggle the security device between armed and disarmed mode. The web app will do this by calling the `toggleMode()` function in your Photon device app.
3. The web app will display a notification if the security device detects motion while the device is armed. The web app will do this by receiving event notifications sent from your Photon device app.

## Add Starter JS <a href="#add-starter-html" id="add-starter-html"></a>

[​Copy this starter JS for your web app](https://docs.idew.org/code-internet-of-things/references/web-app#js), and paste it into a **blank** JS file named `script.js`.

{% hint style="danger" %}
**IMPORTANT:** You **must** modify this JS code to [insert your actual Photon device ID and access token](https://docs.idew.org/code-internet-of-things/references/particle-cloud/web-app-prep-steps#device-id-and-access-token). Otherwise, your web app will **not** work properly.
{% endhint %}

## Add Custom JS <a href="#add-custom-html" id="add-custom-html"></a>

Copy this JS, and paste it **after** your modified starter JS:

```javascript
var alertSound = new Audio("notification.wav");

window.setInterval(checkMode, 500);

function checkMode() {
    particle.getVariable({ deviceId: myDevice, name: "deviceMode", auth: myToken }).then(function(data) {
        // add code to do something with value returned as: data.body.result
        if (data.body.result == "armed") {
            $("#system-mode").html("ARMED");
            $("input[name=toggle]").prop("checked", true);
        }
        else if (data.body.result == "disarmed") {
            $("#system-mode").html("DISARMED");
            $("input[name=toggle]").prop("checked", false);
        }
    }, function(err) {
            console.log("An error occurred: ", err);
    });
}

function toggleMode() {
    particle.callFunction({ deviceId: myDevice, name: "toggleMode", argument: "data", auth: myToken });
}

particle.getEventStream({ deviceId: myDevice, name: "motion", auth: myToken }).then(function(stream) {
  stream.on('event', function(feed) {
    // add code to do something when event notification received
    // any text data received is stored as: feed.data
    alertSound.play();
    var dateTime = new Date();
    dateTime = dateTime.toLocaleString();
    $("#event-time").html(dateTime);
    $("#motion-alert").show().delay(1500).fadeOut();
  });
});
```

This custom JS does 5 main things:

1. Stores an audio file in a JS global variable named `alertSound`
2. Sets a time interval to call a JS function named `checkMode()`
3. Adds a JS function named `checkMode()` that will get the value of a Photon variable
4. Adds a JS function named `toggleMode()` that will call a Photon function
5. Starts listening for `"motion"` event notifications sent by your Photon device

### Variable for Audio File

A variable named `alertSound` is declared that stores an audio file named `"notification.wav"`. [Download a copy of this audio file](https://drive.google.com/open?id=1MYgo-SFuQLOSA2Z0tW8eVqg_5P6EYtc1), and place it in the **same folder** as your web app files.

### Set Interval to Call Function

The `window.setInterval()` method will automatically call the function named `checkMode()` every `500` ms (0.5 seconds).

### Get Photon Variable

The function named `checkMode()` contains a call to the `particle.getVariable()` method that will get the current value of the `"deviceMode"` variable in your Photon app.

Inside the `particle.getVariable()` method are JS and jQuery code statements (lines 8-15 above) that were added to perform actions based on the value returned for the Photon variable.

An if-else statement is used to determine whether `data.body.result` has a value equivalent to `"armed"` or `"disarmed"`. Then jQuery statements (which start with `$`) are used to dynamically change the information displayed in the first "card" by targeting specific [id selectors](https://www.w3schools.com/jquery/jquery_selectors.asp):

* `$("#system-mode")` targets the HTML element with `id="system-mode"`. The jQuery statements change this element's HTML to display either `ARMED` or `DISARMED`.
* `$("input [name=toggle])` targets the `<input>` element with `name="toggle"`. The jQuery statements change its `"checked"` property to either `true` (checked) or `false` (unchecked), which changes the toggle switch slider position.

Since the `window.setInterval()` method will keep calling this function every 0.5 seconds, your web app will continuously monitor the current mode of your Smart Security device.

### Call Photon Function

The function named `toggleMode()` contains a call to the `particle.callFunction()` method that will call the `"toggleMode"` function in your Photon app to remotely switch your device's mode between "armed" and "disarmed".

The `<input type="checkbox">` in your web app HTML contains an [onclick event attribute](https://www.w3schools.com/tags/ev_onclick.asp) that will call this `toggleMode()` function whenever the toggle switch in the web app is clicked.

### Listen for Event Notifications

The `particle.getEventStream()` method is used to start listening for event notifications sent from your Photon app.

The `particle.getEventStream()` method requires your Photon device ID, the name of your cloud event, and your Photon access token:

1. `myDevice` is the global variable that stores your Photon device ID
2. `"motion"` is the name of the cloud event that you want to receive notifications from
3. `myToken` is the global variable that stores your Photon access token

If an event notification includes any data, this text string data gets temporarily stored in a local variable called: `feed.data`

Code statements added within the `particle.getVariable()` method will be performed whenever an event notification is received.

In this case, JS and jQuery code statements (lines 29-33 above) were added that will perform these actions each time a new event notification is received:

* Play the `alertSound`
* Get the current date and time and store it in a variable named `dateTime`
* Display the value of `dateTime` in the HTML element with `id="event-time"`
* Show the HTML element with `id="motion-alert"`, wait for `1500` ms (1.5 seconds), and then fade out the element until it is hidden. This creates a visible "pop-up" notification in your web app.

**NOTE:**  Since your Photon app is sending the `"motion"` event notification **without** data, there aren't any JS or jQuery code statements using `feed.data` (because no text string is being received).

## Test Web App

Be sure your Photon device is connected to Wi-Fi and Particle Cloud.

Refresh your web app, and test it with your Photon device to make sure they interact correctly:

* Verify that your web app displays the current mode ("armed" or "disarmed") of your Smart Security device. Use the push button connected to your Photon device to change the device mode.  When the LED is turned on, the device is in "armed" mode. When the LED is turned off, the device is "disarmed." Verify that your web app updates automatically to show the correct device mode.
* Verify that your web app can remotely change the device mode. Click the toggle switch in your web app, and verify that your Photon device automatically toggles modes (by checking the LED). It may take up to 2 seconds for the mode to switch due to the `delay(2000)` in the Photon app.
* While your Smart Security device is in "armed" mode, wave your hand over the motion sensor to trigger a motion event. Verify that your web app displays a motion notification pop-up (which will fade out after 1.5 seconds). Verify the web app displays the correct date and time for the last motion event notification.

![](/files/-LKNwJV-C0XobtFFpfdB)

## Going Further

If you have time and want to experiment with the other inputs and outputs in your Photon kit, you could explore the [SparkFun Photon Experiment Guide](https://learn.sparkfun.com/tutorials/sparkfun-inventors-kit-for-photon-experiment-guide).  (You can skip ahead to Experiment 3 or later.)

There are also references in this guidebook that show and explain how to connect and code each of the [physical inputs](/code-internet-of-things/references/physical-inputs.md) and [physical outputs](/code-internet-of-things/references/physical-outputs.md) included in your Photon kit.

Your team should now be ready to start thinking of possible ideas for [your IoT project challenge](https://docs.idew.org/project-internet-of-things/project-instructions/project-challenge).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.idew.org/code-internet-of-things/tutorials/create-security-system/4.9-web-app-js.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
