Templates with beacon triggers

In the “build your own template” guide, we’ve learned how to build a custom template and fill it with data (context!) from a mobile app.

Yet, Mirror can also detect nearby Bluetooth devices which do not on their own have capabilities to push data to Mirror. Devices such as … Bluetooth beacons!

This allows building templates which sort of … self-feed themselves with data (context!) from the environment around Mirror.

For example, the screen could react to nearby merchandise being picked up, if you tag it with the Estimote Sticker Beacons. Or, beacons embedded in wrist bands or name badges could allow identifying people in front of the screen, without relying on the mobile app.

Let’s dive into the former idea straight away.

What’s ahead (aka Table of Contents)

You will need…

  • 1 x Estimote Mirror
  • 1 x TV or other display with HDMI and USB ports
    • you can twist and bend your Mirror to make it fit into the ports
    • alternatively, you can power it from your computer’s USB port, or use a USB wall charger
    • use a USB extension cable if needed
  • 2 x Estimote Proximity, Location, or Sticker beacons
  • 1 x smartphone with your mobile app inst… just kidding, you won’t be needing that!

Prepare your beacons

We’ll be using the telemetry data broadcast by the beacons to detect when they’re in motion. If you have…

  • … Location Beacons, they already come with Estimote Telemetry packet enabled by default. If you disabled that packet, re-enable it.

  • … Proximity Beacons, use the Estimote iOS/Android app and enable the Estimote Telemetry packet.

  • … Sticker Beacons, they come set to the Nearable packet, which has telemetry data embedded in it, by default. If you switched them to another packet, switch them back to Nearable.

Tip: You might also want to reduce the advertising interval of the Telemetry or Nearable packet. This will improve the responsiveness of the experience.

Create an HTML5 page

Create an index.html file and paste this simple HTML into it:

<!doctype html>
<html>
<head>
    <script><!-- we'll add our JavaScript here in a moment --></script>
</head>
<body>
    <h1>Pick a product to learn more about it</h1>
    <div id="product-info"></div>
</body>
</html>

Once again, notice the product info “blank”. Except this time, we won’t be filling it in from a mobile app, but from the template’s JavaScript itself!

Scanner API

Inside the <script></script> tag, add:

// replace with identifiers of your beacons:
const BEACON_ID_1 = "1a2b...";
const BEACON_ID_2 = "3c4d...";

mirror.init();
mirror.setScanFilter({
    types: ["telemetry", "nearable"],
    ids: [BEACON_ID_1, BEACON_ID_2],
    // you could also set an RSSI filter if you wanted:
    // rssiRange: { hi: -50, low: -60 }
});

This will prepare the scanner. Now, let’s follow that with a handler for the scan results:

mirror.listen(Mirror.Events.SCAN, {
    onscan: function(event) {
        if (alreadyShowingProductInfo()) { return; }

        for (const device of event.devices) {
            if (device.motion == false) {
                // we're trying to find a beacon that's in motion
                continue;
            }

            if (device.id == BEACON_ID_1) {
                showProductInfo("It's a very good product. We promise.");
            } else if (device.id == BEACON_ID_2) {
                showProductInfo("One of our favorites. What an eye you've got.");
            }
        }
    }
});

Finally, the code of the two helper functions we used:

function alreadyShowingProductInfo() {
    let productInfo = document.getElementById("product-info");
    return productInfo.childNodes.length > 0;
}

function showProductInfo(description) {
    let productInfo = document.getElementById("product-info");
    productInfo.innerText = description;

    // automatically remove the description after 5 seconds
    setTimeout(function() {
        productInfo.removeChild(productInfo.firstChild);
    }, 5 * 1000);
}

Load the template onto your Mirror

Unplug the Mirror from your TV, and plug its USB port into your computer for a moment. After a minute or so, it will appear as an external USB drive. (Hey, remember pen-drives? :wink:)

Open it, and navigate to the templates directory. Create a new sub-directory and call it default. Copy your index.html file inside it. Voilà!

Important: Before unplugging Mirror from your computer, make sure to “safely remove it”.

macOS especially has in-memory buffering turned on by default for external drives. This means that files aren’t immediately copied to the drive. If you simply unplug Mirror, your template might end up missing, incomplete, or corrupted.

Plug the Mirror back into your TV. Since we’ve named our template “default”, it will override the factory-default, and show up immediately.

Tip: Instead of unplugging and plugging Mirror back and forth, you can connect Mirror to both your computer and your TV at the same time, and use a feature we call “eject-reload” to reload and test your templates. See “Working with templates” from “Build your own template” to learn more about it.

Give it a try!

Pick one of your beacons up, and in just a moment, the screen should fill up with one of the pre-defined descriptions.

What else could you do? We’ll leave that up to you, but make sure to check up on the reference documentation of Mirror JavaScript API for templates. Browse and learn more about all the available features!