After my webinar, lots of people have been asking about how I did the motion detection demo wherein I used a Raspberry Pi based motion detector that used the Azure IoT Hub and more broadly other Azure resources. The demo was a little cheeky because I used a princess castle, toy bear, and toy police officer as models to demo the app. In reality, the triviality of this means that the device itself could probably send the messages, but where’s the fun in that? Azure is awesome, and the Azure IoT is designed for scale…image thousands of devices doing this!
The Raspberry Pi setup was pretty simple, as it required no soldering, breadboards, capacitors, resistors or anything of that nature – just an old USB webcam that I had lying around. The Pi itself was connected to an Ethernet hub and powered by a USB phone charger. The principle purpose of this demo was not to have a complex IoT device, rather it was more intended to highlight the capabilities of Azure IoT and how to integrate it with other Azure resources.
The Raspberry Pi has a NodeJS script that acts as a wrapper around a little Linux utility called Motion, which can use all kinds of device and streams for motion detection. It does this by looking for differences in frames taken from a video steam. The script looks for the output from motion, which in this case are JPG images that are saved should motion be detected. Below are some sample images.
When images are found, these are uploaded via IoT Hub to an Azure Storage Account. Once a fair number of images are sent, the script then sends a message to IoT Hub. IoT Hub is wired up to an Azure Service Bus Message Queue which receives the message publications. An Azure Function subscribes to the queue to handle the messages. The function simply creates an email with references to the images embedded, and then sends that email message out by way of SendGrid. All in all, this simple demo shows end-to-end what an Azure IoT app might look like.
A few disclaimers: this is a demo and is by no means intended to be run as a production grade app. This code and setup are actually part of a larger project that I am working on that will involved AI and image recognition, but borrowed pieces from it to do an IoT demo. Also, This is not not a trivial setup, so it can take a while to do. Many of the details are glossed over in favor of brevity. If you have questions, please post in the comments or contact me. So with no further adieu, here’s how to set this up.
To create resources, follow the links below to Azure which have detailed instructions for how to create the necessary resources in the Azure Portal. Along with these links are some notes about what needs to be done on each of these to ensure that you get the right settings. Before creating all these resources it’s important to remember to get all of these resources on the same subscription, in the same resource group, and in the same region for best performance.
Once all of the resources are deployed…
Now that the resources are configured, create a function in your function app to bring some of the resources together.
container
to be the same as the container you created when you configured the File upload on the IoT Hub, then Save the code.
var azure = require('azure-storage');
module.exports = function(context, mySbMsg) {
var blobService = azure.createBlobService(process.env.APPSETTING_AzureWebJobsStorage);
var deviceId = mySbMsg.deviceId;
var htmlstr = "<h1>" + deviceId + "</h1>"
htmlstr += "<h3>" + mySbMsg.timestamp + "</h3>"
var container = "motion-files"
for(var i = 0; i < mySbMsg.files.length; i++){
var dateNow = new Date(new Date().toUTCString());
var file = deviceId + "/" + mySbMsg.files[i];
var numberOfDaysToAdd = 365;
var operation = azure.BlobUtilities.SharedAccessPermissions.READ
var sharedAccessPolicy = {
AccessPolicy: {
Protocols : "https",
Permissions: operation,
Start: dateNow.setDate(dateNow.getDate()),
Expiry: dateNow.setDate(dateNow.getDate() + numberOfDaysToAdd)
},
};
var sasToken = blobService.generateSharedAccessSignature(container, file, sharedAccessPolicy)
var sasUrl = blobService.getUrl(container, file, sasToken);
htmlstr += "
” } context.log(htmlstr) context.done(null, { message: { content: [{ type: ‘text/html’, value: htmlstr }] } }); };
npm install azure-storage
That’s all for configuring the Azure Function, now you can proceed to setting up the Raspberry Pi
This project used a Raspberry Pi 2 running Ubuntu Core. Installing Ubuntu Core on a Raspberry Pi is pretty straight forward. Once Ubuntu Core is installed, connect to the Pi with an SSH client and run the following commands.
sudo -i
apt-get update && apt-get upgrade
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
apt-get install -y nodejs motion
motion.conf
file.
nano etc/motion/motion.conf
Then, search (Ctrl + W
) for target_dir
and set the value to /home/ubuntu/iot/motion/
. Save the file (Ctrl + O
).
mkdir /home/ubuntu/iot /home/ubuntu/iot/motion
cd /home/ubuntu/iot
iot.js
nano iot.js
<YOUR DEVICE CONNECTION STRING>
to the connection string you copied when you configured the IoT Device and <YOUR DEVICE ID>
to the Device ID. Then, save the File (Ctrl + O
).
var fs = require('fs');
var { exec } = require('child_process');
var clientFromConnectionString = require('azure-iot-device-mqtt').clientFromConnectionString;
var Message = require('azure-iot-device').Message;
var moment = require("moment");
var connectionString = '<YOUR DEVICE CONNECTION STRING>';
var deviceId = '<YOUR DEVICE ID>'
var folder = '/home/ubuntu/iot/motion/'
var client = clientFromConnectionString(connectionString);
var pollFreq = 1000
var connectCallback = function (err) {
if (err) {
console.error('Could not connect: ' + err);
} else {
console.log('Client connected');
checkImages();
client.on('message', function (msg) {
var toggle = msg.data.toString('utf-8');
if(toggle == "ON"){
console.log("Motion Detection is ON");
exec("motion")
}else if(toggle == "OFF"){
console.log("Motion Detection is OFF");
exec("pkill motion")
}
client.complete(msg, function () {
});
});
}
};
client.open(connectCallback);
console.log('Starting daemon...');
function checkImages(){
fs.readdir(folder, (err, files) => {
var fileIdx = 0;
if (files.length > 0){
var sendImage = function(){
var filename = files[fileIdx];
fs.stat(folder + filename, function (err, stats) {
var rr = fs.createReadStream(folder + filename);
client.uploadToBlob(filename, rr, stats.size, function (err) {
if (err) {
console.error('Error uploading file: ' + err.toString());
} else {
fs.unlinkSync(folder + filename);
console.error('Uploaded file: ' + filename);
}
fileIdx++;
if (fileIdx == files.length){
var now = moment()
data = JSON.stringify({ deviceId: deviceId, timestamp: now, files: files });
message = new Message(data);
message.contentEncoding = "utf-8";
message.contentType = "application/json"
console.log("Sending message: " + message.getData());
client.sendEvent(message);
setTimeout(function(){checkImages();}, pollFreq);
}else{
sendImage();
}
});
});
}
sendImage();
}else{
}
})
}
npm install azure-iot-device moment
The Raspberry Pi is configured to run at this point.
node iot.js
ON
in the Message Body, then click Send Message. (Conversely, you can turn off motion detection by sending an OFF
message.) Motion Detection is ON
Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…
Cloud management is difficult to do manually, especially if you work with multiple cloud…
Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…
https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…
FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…
Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…