One of the frequent questions on forums for Node-RED and Home Assistant is how to make use of the images and videos that MotionEye saves when it detects motion from a security camera. Users don’t want the images and videos to be trapped in the MotionEye server they want to send them to themselves or another server for viewing. We’ll show you how to take advantage of all the part to make this work for you using some automation from Node-RED and it’s ability to send data to nodes that will deliver the media to you.

Webhooks and Node-RED

One of the easiest ways to take advantage of the automation that MotionEye gives you is to call a webhook when MotionEye senses motion on one of the cameras. You can do this in the settings panel for the camera in question by hitting the wrench icon on the image shown below.

The MotionEye camera action icons showing fullscreen option, saved images and video library and settings panel (wrench icon).
The MotionEye Camera action icons

Basically a webhook is a call to a URL using one of the standard methods to send or receive data from a web server. It’s much like browsing the web in your browser or submitting a web site form, data is exchanged between you and the server and typically there is an action on one end due to the exchange. The webhook take the idea a step further and by definition it means an action gets executed on the server (or it’s implied in the definition of webhook).

MotionEye’s Motion Notification Section focused on an example webhook call.

What we are going to do is define what the actions are on the server side by using Node-RED’s automation capabilities.

Building our Webhook

Before we can tell MotionEye to call a webhoook in the settings UI we need to define the webhook – it’s basically a prerequisite. Once we have it defined we can use a Node-RED debugging node to see what MotionEye sends over when it calls the webhook.

To start, we’ll need an HTTP in node from the Node-RED pallet – let’s grab it and drag it into our layout;

The HTTP in node which will let us define an API like end-point in Node-RED
The HTTP in node which will let us define an API like end-point in Node-RED

Then we need to define the URL endpoint for our webhook. In the example below we are using /apiv2/webhookURL. This will translate into a full webhook URL like the one below (assuming Node-RED is not exposed to the internet and only accepting connections on the local network):

http://192.168.1.112:1880/apiv2/webhookURL

And here is how we configured the Node-RED HTTP in Node for our webhook;

Notice in the HTTP in settings we set the HTTP Method to POST (from GET the default)

Testing the Webhook Endpoint

Besides going in front of your cameras and jumping up and down we can test the endpoint and see what happens, that it’s up and running in a few ways. First, let’s add debugging to our flow so we can see what happens on the automation server when we call the webhook. We do this by dragging in a debug node and attaching it to our HTTP in node as shown below;

An HTTP node for our webhook connected to the debugging node.

And we’re going to make a change now to make debugging easier and on our debug node we’re going to set it to show the full data payload and not just the msg.payload information;

Debug node with the output set to "complete msg object" in Node-RED
Debug node with the output set to “complete msg object” in Node-RED

Now we’re set to test and debug the output of our webhook which will guide us along the way later as you’ll see. Let’s deploy our changes in Node-RED to make them live on the top right using the Deploy button.

We can first test that the webhook is reachable by just visiting the URL we created above, http://192.168.1.112:1880/apiv2/webhookURL, in our browser. If you get an error on the page like the below, you know it’s reachable;



Cannot GET /apiv2/webhookURL

Now that we get a response, even a bad one, we can see what happens in Node-RED. If you visit debugging in Node-RED at this point you’ll see there is no output because we caused an error. We can now start using CURL to test what happens when we send an HTTP call with the proper method. This is entirely optional at this point and we could just move into using MotionEye to send the response.

Using CURL to test a webhook (optional)

Most Linux distributions already have CURL installed and if you’re like me and running Debian you might have to install it if you went with the slimmer install option;

sudo apt install curl

Now you have CURL installed and can call the webhook endpoint from the CLI to test. We do this by crafting a CURL call that is a POST call to our new favorite URL;

curl -X POST http://192.168.1.112:1880/apiv2/webhookURL

Go ahead and run the above command in the command line of your Linux install. It will appear to not complete, go ahead and hit CTRL+C to close it and go back to Node-RED’s admin UI.

In the debugging panel you’ll now see output from out debugging node showing what the endpoint saw from your CURL command;

Node-RED debugging node output from a webhook call to our home automation server
Node-RED debugging node output from a webhook call to our home automation server

And if we expanded that data we’d see the below;

{"_msgid":"8788e030.6eabe","req":{"_readableState":{"objectMode":false,"highWaterMark":16384,"buffer":{"head":null,"tail":null,"length":0},"length":0,"pipes":null,"pipesCount":0,"flowing":null,"ended":true,"endEmitted":false,"reading":false,"sync":true,"needReadable":false,"emittedReadable":false,"readableListening":false,"resumeScheduled":false,"paused":true,"emitClose":true,"autoDestroy":false,"destroyed":false,"defaultEncoding":"utf8","awaitDrain":0,"readingMore":true,"decoder":null,"encoding":null},"readable":true,"_events":{},"_eventsCount":1,"socket":"[internal]","connection":"[internal]","httpVersionMajor":1,"httpVersionMinor":1,"httpVersion":"1.1","complete":true,"headers":{"host":"192.168.1.112:1880","user-agent":"curl/7.64.0","accept":"*/*"},"rawHeaders":["Host","192.168.1.112:1880","User-Agent","curl/7.64.0","Accept","*/*"],"trailers":{},"rawTrailers":[],"aborted":false,"upgrade":false,"url":"/apiv2/webhookURL","method":"POST","statusCode":null,"statusMessage":null,"client":"[internal]","_consuming":false,"_dumped":false,"baseUrl":"","originalUrl":"/apiv2/webhookURL","_parsedUrl":{"protocol":null,"slashes":null,"auth":null,"host":null,"port":null,"hostname":null,"hash":null,"search":null,"query":null,"pathname":"/apiv2/webhookURL","path":"/apiv2/webhookURL","href":"/apiv2/webhookURL","_raw":"/apiv2/webhookURL"},"params":{},"query":{},"res":"[internal]","route":{"path":"/apiv2/webhookURL","stack":[{"name":"cookieParser","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"},{"name":"httpMiddleware","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"},{"name":"corsMiddleware","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"},{"name":"metricsHandler","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"},{"name":"jsonParser","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"},{"name":"urlencodedParser","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"},{"name":"multipartParser","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"},{"name":"rawBodyParser","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"},{"name":"<anonymous>","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"},{"name":"<anonymous>","keys":[],"regexp":{"fast_star":false,"fast_slash":false},"method":"post"}],"methods":{"post":true}},"cookies":{},"signedCookies":{},"body":{},"_body":true},"res":{},"payload":{}}

Wow, that’s a lot of data! Luckly we only need a few parts of this. Let’s do this all again but instead of using CURL we’ll start using MotionEye to make the webhook call instead. This will give us valuable debugging information that we can start using in our flow.

Setting MotionEye to Send Webhooks

Just as easy it was to setup the webhook in Node-RED it’s just as easy to call the webhook in MotionEye when it detects motion from a camera. Really all we need to do is copy and paste the URL into the settings panel for the security camera in question, the same one we used in the CURL example above.

http://192.168.1.112:1880/apiv2/webhookURL

We’re going to throw a curve ball here and add a URL argument to the webhook to be interpreted by Node-RED upon receiving the call.

http://192.168.1.112:1880/apiv2/webhookURL?%f

Notice what we did – we added ?%f to the end of the URL. Though this isn’t well documented and isn’t in the MotionEye UI what this will do is append the name of the file to the end of the URL, so it looks more like this when the call gets made;

http://192.168.1.112:1880/apiv2/webhookURL?/mnt/xstore/motion-porch/2020-11-30/08-09-07.mp4

Now what we’ve done is basically constructed a URL that does two things – it will let MotionEye tell Node-RED when something happened so Node-RED can kick off a series of events – but we can also tell the endpoint more information about the event (in our case, the file generated from it).

Let’s have MotionEye detect motion and send the webhook so we can see the debug output. We’ll want to know where the name of the file goes and grab it to use in our flow. What we’ll need to do is setup MotionEye to call the webhook and then watch the debugging. To do this we paste the URL into the section we showed up top;

MotionEye webUI showing the Motion Notification settings
MotionEye webUI showing the Motion Notification settings

Now what you’ll get in the debug node is the query string information we added earlier, the filename will come through instead of “%f“. If you are lucky each time you save the changes in MotionEye the camera will reinitialize and it will think there was motion – if so you’ll see the output in your Node-RED debug node.

Just to skip ahead we won’t analyze each part of the debugging data. It’s all there for you to explore. You can do more stuff like send the date and time as a URL argument but we’ll keep it simple for now.

Parsing the Output in Node-RED

Now that we have MotionEye making a webhook call when there is motion and we have Node-RED accepting that call we can start picking apart the information we receive and start using it in our flow.

What we need to do is start setting values and picking apart the data. In our example we’re going to post the information to Mastodon so we’ll need two part of information – the text of our toot and the image or video we want to post.

Let’s add two change nodes to our flow after the HTTP in node and connect them to the node we started with;

Example HTTP in node with two change nodes attached
Example HTTP in node with two change nodes attached

Our Mastodon node, that posts the toots, will need two message payloads combined; msg.payload.text and msg.payload.image. Let’s look at the part of our flow to set msg.payload.text first.

On the first node attached to the HTTP in, we’ll start setting up our text going to our toot (or your Telegram message!). Basically we’re just going to change msg.payload to a text string by using the change node’s “Set” function.

Change node - setting msg.payload to a text string we define.
Change node – setting msg.payload to a text string we define.

Now that we have changed, in this portion of our flow, msg.payload and have basically overridden what is coming from the input (our webhook) we just use the next node to move it to msg.payload.text required for the Mastodon API node later.

Our second change node that moves the msg.payload to another JSON location.
Our second change node that moves the msg.payload to another JSON location.

Now we’ll look at the other half of our flow – pulling the image location from the webhook’s URL and changing this information so it’s usable in our flow.

If you remember we mentioned there are two change nodes from the HTTP in node (and we showed the above). In the second of the two, what we’re going to do is pull out an element of the giant debugging information we looked at earlier – we are after the req.__parsedURL.search information. This is where in the JSON our file name is.

Here with a change node we set the msg.payload equal to what the webhook received as the URL parameters - our filename coming from MotionEye
Here with a change node we set the msg.payload equal to what the webhook received as the URL parameters – our filename coming from MotionEye

There is just one small problem, a single character problem. There is an extra question mark at the front of our filename. If you added a debugging node after the one we built above you might see it. We can easily strip off the first character of the string by using a Node-RED function node and some JavaScript. Drag the function node to your flow and place it behind the one above and attach it.

In our function node we’ll use the JavaScript function slice to trim off the first character of the msg.payload and return the rest to the next node in our running flow;

msg.payload = msg.payload.slice(1);
return msg;

Your flow should start looking like this;

Just like we did before, we need to start shifting our msg.payload information around and our Mastodon API node will need the image to be in a specific part of the JSON message (msg.payload.image) and the text of the toot to be in a different node of the JSON (msg.payload.text). To do this will just use another change node and move msg.payload to msg.payload.image;

Now we are basically setup – we have two portions of the flow that creates a string message “Motion detected” or something similar applied to msg.payload.text and we have our image location (file name including full path) in msg.payload.image – we are ready to put the messages together with a join node.

Our join node combining our msg.payloads in manual mode to create a merged object.
Our join node combining our msg.payloads in manual mode to create a merged object.

This trick I discovered after trying to do this all in one leg of the flow – unsuccessfully. By bifurcating our flow into two parts we can set both messages independently and then put them back together later. Remember we are working on two parts of the same message so the join node here comes in handy. Were just going to use the manual mode and select the option to create a merged object in this section. For extra issue handling with MotionEye let’s set this node to send on it’s data when 2 messages are received or 100 seconds goes by.

If you were to debug here you should see a JSON message that has two parts of course. We’re ready to now post to Mastodon!

Posting to Mastodon with Node-RED

Posting to Mastodon couldn’t be easier with Node-RED since Mastodon is API friendly and there is already a Node-RED pallet node to use. All you’ll need is to create an access token for your Mastodon account and then paste it into Node-RED. You can do this by visiting Settings and then Development and creating a new application (https://yourmastodoninsance.social/settings/applications).

But before we do that let’s setup some rate limiting on what we’re going to post. We can do this in Node-RED with a delay node – by setting the action to rate limit. We want to be sure we’re not posting messages every few seconds and angering our followers and this might happen depending on your motion settings.

Before posting to Mastodon with Node-RED we're going to rate limit those requests and stop them in Node-RED
Before posting to Mastodon with Node-RED we’re going to rate limit those requests and stop them in Node-RED

Now we’re ready to drop in our Mastodon sendMessage node into Node-RED and start sending our first message! You should have a flow similar to the one below once you do (before setting up the sendMessage node);

Our flow - accept a webhook, send out a Mastodon toot!
Our flow – accept a webhook, send out a Mastodon toot!

Configuring sendMessage just needs the API endpoint of your Mastodon server and the Access Token you generated when creating a new app tied to your Mastodon login.

sendMessage node of Node-RED, this will send toots to Mastodon

Deploy your flow and sit back, it’s all working. Here’s an example toot to show you what you should see in Mastodon!


Expanding Your Motion Eye Security System: Unlocking Limitless Possibilities

Now that you’ve successfully configured Motion Eye to send webhooks to Node Red, and subsequently share images on Mastodon, you’ve laid a solid foundation for an intelligent and dynamic security camera system. However, the journey doesn’t end here—instead, it’s an invitation to explore the vast realm of AI image detection systems and APIs.

Embrace the Power of AI Image Analysis

With Node Red as your orchestrator, you have the flexibility to integrate various AI-driven image analysis tools into your security pipeline. Imagine the possibilities:

1. Package Detection:

Utilize AI algorithms to detect packages or objects in the camera feed. Receive instant notifications when a package is detected, enhancing your awareness of any unusual activity.

2. Person Detection:

Enhance security by incorporating AI models that can identify and notify you about the presence of individuals in the camera frame. This could be a valuable feature for monitoring restricted areas or securing your property.

3. Facial Recognition with Azure:

Leverage Azure’s powerful facial recognition services to add an extra layer of identity verification. Receive alerts when specific individuals are detected, providing a more personalized and tailored security experience.

Building Your Customized AI Security Solution

The beauty of Node Red is its versatility and extensibility. Here’s a simplified guide to expanding your system with AI capabilities:

  1. Research AI Services: Explore AI image detection services and APIs available in the market. Popular platforms include Google Cloud Vision API, AWS Rekognition, and Microsoft Azure Cognitive Services.
  2. Obtain API Keys: Sign up for the chosen AI service, obtain API keys, and configure them within Node Red for seamless integration.
  3. Node Red Integration: Use Node Red’s intuitive interface to create flows that connect your Motion Eye camera feed with the AI image detection service. This might involve adding nodes for HTTP requests, parsing responses, and making decisions based on the analysis.
  4. Customize Notifications: Tailor notifications based on AI detections. Whether it’s sending an alert when a person is detected or triggering actions for specific objects, Node Red allows you to create a personalized and responsive security system.

The Sky’s the Limit

By integrating AI image detection into your Motion Eye setup, you’re not just monitoring; you’re creating an intelligent and proactive security solution. The options are limitless, and the power is in your hands. Experiment, explore, and discover how AI can elevate your security camera system to new heights.

Remember, technology is ever-evolving, so stay curious and stay secure!