I’m a parent to three kids, and they, like most kids and adult-sized kids, love the holidays. The lights, the decorations, the sweets that their parents try really hard not to let them have the other 11 months of the year. And, of course, the presents from family, friends, and those delivered by Santa Claus and his faithful flying reindeer.
Speaking of reindeer, my kids and I had some fun this year making up a story called “Reindeer Recon.” The idea is that in the weeks leading up to Christmas, Santa sends out his Reindeer individually to do reconnaissance of all the neighborhoods around the world. You know, to make sure all of the streets are where they should be, chimneys are accessible, map out the rest stops, and what not. So, as children are filling out their wish lists, and shaking packages under the tree, Santa’s reindeer are gliding through the sky and surveying the land as they prepare for December 25th.
The kids and I have had such fun with this story that I decided to turn it into a hardware and software project and create a real Reindeer Recon tracker that captures location data, sends it to the cloud, and appears on a handy web dashboard that Santa can use to keep tabs on his magical agents!
In this article, I’ll walk through:
- How I configured the Reindeer Recon hardware using the Notecard and Notecarrier.
- The tools and services I used for storing GPS data (Notehub.io, Azure Functions, and Azure CosmosDB).
- How I built the web-based dashboard using Svelte and Mapbox.
If you want a 3 minute overview of the project, check out the video below.
What is the Notecard?The hardware I chose for this project is the blues wireless Notecard. The Notecard is a cellular and GPS-enabled device-to-cloud data-pump that comes with 500 MB of data and 10 years of cellular service for $49. No activation charges, and no monthly fees.
The Notecard is a small 30 by 34 mm SoM that’s ready to embed in a custom project via its m.2 connector. But blues also provides a series of expansion boards, called Notecarriers, that include an m.2 socket for the Notecard and a number of other features for prototyping. For the Reindeer Recon project, I used the Notecarrier-AL, which has onboard cellular and GPS antennas, and a LiPo battery port, making it perfect for this project.
On the cloud side, the Notecard is preconfigured to securely talk to Notehub.io, the blues wireless service that enables secure device-to-cloud data flow. Notecards are assigned to a project in Notehub.io, which then sync data into those projects for routing to your cloud application.
Configuring the Notecard as an Asset TrackerOne of the most powerful features of the Notecard for developers is its mode of communication. You connect to it over Serial, I2C, or USB and it speaks JSON. It takes JSON requests and returns JSON responses. You don’t have to learn or use any AT commands to work with this device. If you’re interested in learning more, there’s a quickstart on the developer portal that introduces the basic concepts and commands.
The Notecard can be used with a host microcontroller or Single-board Computer to add cellular to your project, but it can also be configured as a standalone asset tracker that captures GPS readings and uploads those to the Blues Wireless cloud service, Notehub.io, on a periodic basis.
To configure my Notecard as a standalone tracker, I connected it to a Notecarrier-AL, and plugged it into my laptop via the USB port on the Notecarrier. You can send configuration requests either via the installable Notecard CLI or the in-browser Notecard Playground at dev.blues.io. I opted to use the playground for this project.
First, I used a hub.set
request to assign my Notecard to a product in Notehub.io, and set an optional serial number (sn
). In my case, I used the serial number to assign each Notecard to a reindeer.
{"req":"hub.set","product":"com.blues.bsatrom:reindeer_tracker","sn":"dancer"}
Then, I sent another hub.set request to configure how the Notecard synchronizes data with Notehub.io (I don’t have to send these requests separately, but I did so here for the sake of readability). The mode
indicates that the Notecard does not maintain an active connection to Notehub.io, but reconnects periodically to send data and download data from Notehub.io. inbound
means that the Notecard checks for incoming data every 720 minutes, a long time since I wasn't planning to send data from Notehub to these trackers. outbound
means that the Notecard will upload its data to Notehub.io no less often than every fifteen minutes.
{"req":"hub.set","mode":"periodic","align":true,"inbound":720,"outbound":15}
Next, I enabled location tracking with a card.location.mode request. Since I expect ed Santa’s reindeer to move a lot, I told the Notecard to capture data every 5 seconds.
{"req":"card.location.mode","mode":"periodic","seconds":5}
The Notecard has a built-in accelerometer. Among other things, it pays attention to device movement and does not capture new GPS data if the Notecard hasn’t moved. You can adjust the sensitivity of the accelerometer using a card.motion.mode
request, and I did so to ensure that reindeer movement would trigger GPS activation.
{"req":"card.motion.mode","sensitivity":2}
Next, I enabled location tracking and added a daily heartbeat, to make sure that each tracker checks in once per day, even if it hasn’t moved.
{"req":"card.location.track","start":true,"heartbeat":true,"hours":24}
Each of these requests can be sent one after another, or placed into a .json
file and sent via the Notecard CLI’s setup
command. As each request is sent, the Notecard responds with JSON.
For detailed information on Notecard API requests, check out the complete API reference.
With my reindeer recon trackers configured, it’s time to deploy them. I don’t actually have access to any reindeer at the moment, so I just took each tracker for a couple of rides, one at a time. And while I drove around listening to festive tunes, each Notecard faithfully recorded the device location and used its cellular connection to send that data to the cloud.
After I deployed my trackers and they started syncing, location data appeared in the Notehub.io events view for my project.
Each individual event includes the full payload with the tracker data I needed like its location (where_*
), bearing, distance, and more.
Once I had tracking data in Notehub, I was ready for the next step: getting that data into Azure.
Routing Tracker Data to Microsoft Azure and Cosmos DBNotehub.io is designed to allow you to easily direct data to your own cloud apps. This is accomplished with Routes. Notehub.io provides a number of pre-built routes for popular cloud services, as well as support for any HTTPS or MQTT endpoint. For the Reindeer Recon project, I created a simple Microsoft Azure Function App and CosmosDB database for storing location data. The saveReindeerLocation
function below receives data from Notehub.io in the form of a JSON payload, and saves that data to CosmosDB (signified by locationStorage
) so I can retrieve it later for my web dashboard.
module.exports = async function (context, req) {
context.bindings.locationStorage = req.body;
const name = (req.query.name || (req.body && req.body.reindeer));
const responseMessage = name
? "Location for " + name + " received."
: "Location received.";
context.res = {
body: responseMessage
};
}
For additional information on using Azure Function Apps and CosmosDB, checkout the Microsoft docs.
Once I’ve created and deployed my Function app, I can create a Route in Notehub.io. Under the Routes view of my project, I clicked “Add Route” and chose the “Azure Function” with secret Key Route Type.
Notecard data is sent to Notehub.io as Notes (JSON objects) in Notefiles, and each default Notefile serves a specific purpose. In the case of location tracking, the Notecard stores Notes in a Notefile called _track.qo
. When creating Routes, its possible to select a Notefile so that your Route only covers data you want to publish to your cloud app. In my case, this is just location data.
Rather than sending the entire JSON payload to my Azure Function app, I can use JSONata to transform the payload into just the data that I want to save into my CosmosDB database. JSONata is a powerful and simple JSON transformation library that supported out-of-the-box with Notehub routes. With the JSONata transformation below, I can create a simple JSON object for storing in CosmosDB.
{
"device": device,
"reindeer": sn,
"capture_time": when,
"olc": where_olc,
"lat": where_lat,
"lon": where_lon,
"motion": body.motion ? body.motion : 0,
"seconds": body.seconds ? body.seconds : 0,
"temp": body.temperature,
"voltage": body.voltage,
"bearing": body.bearing ? body.bearing : 0,
"distance": body.distance ? body.distance : 0,
"velocity": body.velocity ? body.velocity : 0,
"journey": body.journey
}
Once my Route is created, I can verify that it works by viewing the Route Log for any _track.qo
event.
At this point, I was nearly ready to create my web dashboard. First, I needed to create another function in my Azure Function App to fetch reindeer data from CosmosDB. Since I want all of the data, I just grab everything from my CosmosDB locationStorage binding. Then, before returning, I’ll sort the results and group them by reindeer, making them easier to work with on the client side.
module.exports = async function (context, req) {
data = context.bindings.locationStorage;
// Sort all reindeer location by reindeer
const reindeerPoints = data
.sort((first, second) => first.capture_time - second.capture_time)
.reduce((previous, next) => {
previous[next.reindeer] = previous[next.reindeer] || [];
if (next.lon !== undefined && next.lat !== undefined) {
previous[next.reindeer].push([next.lon, next.lat]);
}
return previous;
}, Object.create(null));
context.res = {
body: reindeerPoints
};
}
Creating a Web Dashboard with SvelteJS and MapboxWith the new function deployed, I was ready for the final piece, a web dashboard to view Santa’s Reindeer as they perform their recon. My simple app uses Svelte and Mapbox on the front-end, and Proi-UI for a few UI components.
The full source is available on GitHub, but the basic flow of the app is as-follows:
- Create Icons for each reindeer I have tracking data for. This recon run only included 5 of the 8 (or 9, if you count Rudolph) reindeer.
- Load a Mapbox map centered around where the trackers were deployed.
- Add Route details to each map.
- Animate each reindeer as it moves from one location to the next.
This last piece was the most complex, but I was able to get it to work reasonably well with requestAnimationFrame
and an array of state objects that I used to track and move each reindeer each frame. The complete source for the Map.svelte component is available in the Code tab below, or you can view it here.
I also added a button to toggle the route lines on and off, and a legend so Santa knows who’s who. Once the site was in a halfway-decent place, I deployed it to Vercel. You can check it out for yourself at https://reindeer-recon.vercel.app/.
This was a fun project to work on, and hopefully demonstrates of how easy it is to use the blues wireless Notecard and Notehub.io, along with cloud services and front-end tools, to create simple, yet powerful, asset tracking applications. To learn more about the Notecard, visit blues.io and I can't wait to see what you'll build with developer-friendly cellular IoT.
Comments