DIY Video Surveillance

So I recently started messing around with NodeJS just for the fun of it. Since I have done my share of JavaScript in my career, it was quite easy to go at. I already had video cameras setup in our house, with my Synology NAS capturing the video and storing it, however everything was stored on premise in my NAS. I wanted to try to do something useful with NodeJS (and more) and thus decided to extend my home video surveillance solution with the ability to backup video files in the cloud (i.e. Dropbox) when motion was captured and “an alarm” was enabled. The video setup I had initially was simply a rolling window of video footage covering the past X days stored on premise.

Alarm

So I wanted to introduce the an option for enabling/disabling the “alarm” in the sense that when the alarm is enabled, it uploads the current video footage to my Dropbox account when motion is detected by any of my cameras. Such a toggle functionality was implemented in a matter of minutes using the Express package for NodeJS. A very simple REST API and the toggle functionality was in place. Less than 20 lines of code looking somewhat like this:

var express = require("express");
var apiHost = new express();
apiHost.put("/alarm/:action", function(req, res) {
    if ("on" === req.params.action.toLowerCase()) {
        ALARM_ENABLED = true;
        res.send(true);
    } else if ("off" === req.params.action.toLowerCase()) {
        ALARM_ENABLED = false;
        res.send(true);
    } else {
        res.send(false);
    }
});

Notifications

So I wanted my e-mail notifications (i.e. “motion detected” events) to be sent to my e-mail only in case the above alarm was enabled. So I figured the easiest way to do this was to place an SMTP relay in between my Synology NAS and my actual outgoing e-mail server. A search around the NPM (Node Packaged Manager) for NodeJS revealed that MailDev was a good option. So I extended my NodeJS program with less than 25 lines of code looking somewhat like this:

var maildev = new MailDev({
    smtp: 25,
    outgoingHost: "smtp.gmail.com",
    outogingPort: 465,
    outgoingSecure: true,
    outgoingUser: "<my username>",
    outgoingPass: "<my password>"
});

maildev.on("new", function(email) {
    if (email.subject.toLowerCase().indexOf("has detected motion") > -1) {
        if (ALARM_ENABLED) {
            maildev.relayMail(email, function(err) {
                if (err) return console.log(err);
            });
        }
    } else {
        maildev.relayMail(email, function(err) {
            if (err) return console.log(err);
        });
    }
});

Online Backup

I also wanted the solution to upload video footage to the cloud (i.e. my Dropbox account) when motion was detected while the alarm was enabled. So another quick search in the NPM lead me to the official dropbox package. With another approximately 10 lines of code I now had video footage stored in my dropbox when motion was detected. The code looking something like this:

var fs = require("fs");
var p = require("path");
var Dropbox = require('dropbox');
var dbx = new Dropbox({ accessToken: '<my access token>' });

function uploadFile(file) {
    var filename = p.basename(file);
    var contents = fs.readFileSync(file);
    dbx.filesUpload({
        path: "/" + filename,
        contents: contents,
        mode: 'overwrite'
    });
}

I have since then tweaked the solution to cleanup the cloud so that I don’t use up all my space but only have an appropriate amount of video footage stored (the oldest being deleted when new arrives).

User Interface

With this in place, I now needed a user interface which would allow me to enable/disable my alarm remotely. For this, Pimatic seemed a perfect fit. A few very simple shell scripts (i.e. curl to my own REST API and the Synology Surveillance Station REST API) and I had that up and running with a toggle button to enable/disable my alarm. Another 10 minutes of work and now had it set up to only accept HTTPS requests and using a self-signed certificate. With a port-forward setup in my router, I am now able to toggle my alarm on/off remotely from nearly any browser.

Overview

Just for the fun of it, I drew up this overview which shows how the things are connected. For the simple proof-of-concept I think I spent around 1-2 hours and have since then used a few more hours tweaking the solution to fit my needs. I must say I was really surprised at how easy it was to get something working with NodeJS. I will definitely be doing other fun stuff with it in the future!

By the way, the whole solution consists of my Synology NAS with Surveillance Station enabled, and all of the NodeJS parts (including Pimatic) on a 64-bit Ubuntu Server (headless) running on a virtual machine with 1GB of RAM. I have also had it running on a Raspberry Pi, but found things to be running a bit faster and more stable on a VM.

homevideosurveillance

MEF2 Composition Helper

MEF2, or Microsoft.Composition, is the portable version of Managed Extensibility Framework which allows you to use dependency injection to create your instances.

When going from standard MEF (i.e. System.ComponentModel.Composition) to MEF2, I was a bit surprised to find that some relatively simple, but very useful, functionality was not readily available to me anymore. I am talking about the ability to compose my own type into my composition container and thus overwriting a potential implementation already present (via the Export attribute in an assembly added to the container).

With MEF2, this is not to be possible, due to the nature of the static composition computing the composition graph up front. However, there are ways to solve the issue, and this is what I have tried to encapsulate in a helper utility.

The utility lets you compose exports, provided that they have not already been added to the composition, using a syntax which is very close to the standard MEF syntax in order to ease the transition. The AddAssemblies() method can take in a list of types which should NOT be added from the assembly you wish to add. This allows you to “overwrite” it in the composition since it is not already there.

// Create stub of Interface2
var stubInterface2 = Substitute.For<Interface2>();
// ... Setup stub properties/methods if required ...

// Create helper (without Implementation2 included)
var helper = new CompositionHelper()
    .AddAssemblies(new[] { implementationAssembly },
        typeof(Implementation2));

// Compose stub in composition
helper.ComposeExport(stubInterface2);

The utility is available as a NuGet package which can be installed from the Package Manager Console using the following command:

PM> Install-Package Nicolai.Utils.Composition.CompositionHelper

More details on the utility can be found in the github repo.

Ambient Resource

Quite a few times in my career I have encountered code that requires access to a resource, e.g. an SqlConnection, where the resource instance is created in the entry method and then passed along to all other methods called from within that method. This is of course much better than firing up a new instance of the resource in every method, however, it really pollutes the method signatures with parameters that, in essence, are irrelevant to the purpose of the method.

There are many ways to solve this issue, (dependency) injection and ambience are examples of such, however I quite like the ambient way of accessing a resource, and thus I decided to roll my own utility to simplify writing this type of code. The main concern with the ambient approach is, in my opinion, that it hides the specifics of how and when the resource is created/disposed.

The scenarios I most often encounter are request-scoped where one instance of the resource is required (i.e. instantiated) for each request. All subprocessing going on within that one request will all utilize the same resource. This is the basis for my VERY simple implementation of an ambient resource.

The concept is fairly simple: A thread-safe (singleton) property, AmbientResource.Current ,represents the ambient resource and encapsulates instantiation of the “actual resource” by requiring the caller/user to specify a factory which will return an instance of the “actual resource”. This factory is used internally by the ambient resource to create a single instance of the “actual resource” which is used internally until the ambient resource is disposed.

Consider the example below which is a perfect example of a signature being polluted with a parameter which in essence is irrelevant:

void Method1()
{
    using (var conn = new SqlConnection(/* connection string omitted */))
    {
        // ... Do some stuff
        Method2(conn);
    }
}

void Method2(SqlConnection conn)
{
    // ... Do some more stuff
}

Method1() is the entry method which fires up an SqlConnection instance. This instance is then passed along to Method2() which uses the connection to do some more work. The method signature for Method2() includes the connection only because we want to reuse the connection, not because it has any relevance to the task which the method performs. This is just a very simple case, and there might as well have been multiple nested method calls with most of the method signatures being polluted with “unnessecary” parameters. One can easily imagine that more than one resource is required and thus 2 (or more) resource parameters will be passed along to all nested method calls; Ugh! Another horrible side-effect of this approach is that once you along the way find out that you actually need to access Method2() as the entry method, you find yourself writing a “dummy” method which simply instantiates the connection and passes it to the existing Method2(); or other equally undesirable work arounds.

This is why I decided to roll my own ambient resource to make my code more readable. The above example can be transformed into the following using my ambient resource utility:

// Create the factory somewhere appropriate (contructor, initialization code, etc.)
AmbientResource.ResourceFactory =
    () => new SqlConnection(/* connection string omitted */);

void Method1()
{
    using (var conn = AmbientResource.Current)
    {
        // ... Do some stuff
        Method2();
    }
}

void Method2()
{
    using (var conn = AmbientResource.Current)
    {
        // ... Do some more stuff
    }
}

This keeps the method signatures clean, and the ambient resource handles instantiating the resource and disposing it again when no longer used (i.e. exit from the “outer” using block).

Ok, but how do I use a REAL resource?

Yeah ok, so the above example was mostly to provide a really short example which actually compiles and works. The problem is that AmbientResource class is very simple and simply encapsulates an instance of reference type IDisposable; thus not providing anything useful to the user. In effect the AmbientResource is mainly used as a proof-of-concept and should not be used for anything other than that.

Therefore the utility also includes a generic ambient resource, GenericAmbientResource, which is not intended to be used directly (therefore abstract), but rather to be extended.

So let’s continue with the above example. For this scenario I would create my own ambient resource class representing the type of resource I want to expose to my application (i.e. an SqlConnection):

class DbConnectionAmbientResource :
    GenericAmbientResource<DbConnectionAmbientResource, SqlConnection>
{
    public SqlCommand CreateCommand(string sql = null)
    {
        var cmd = Resource.CreateCommand();
        if (!string.IsNullOrEmpty(sql))
        {
            cmd.CommandText = sql;
        }
        return cmd;
    }
}

In such a class you have a choice of implementing “wrapper”/”delegation” methods (like I have done) to expose only the relevant methods of the “actual resource” (possibly with some additional around it), or to expose the “actual resource” itself via a property/method to provide the caller access to the real resource. I find the “wrapper methods” option to be most useful when refactoring existing code since you can then leave the existing code in place; it now just accesses the wrapper method on the ambient resource, rather than the actual method on the “actual resource” itself.

Using the class above, the example code can now be modified to:

// Create the factory somewhere appropriate (contructor, initialization code, etc.)
DbConnectionAmbientResource.ResourceFactory =
    () => new SqlConnection(/* connection string omitted */);

void Method1()
{
    using (var conn = DbConnectionAmbientResource.Current)
    {
        // ... Do some stuff
        var cmd = conn.CreateCommand();
        Method2();
    }
}

void Method2()
{
    using (var conn = DbConnectionAmbientResource.Current)
    {
        // ... Do some more stuff
        var cmd = conn.CreateCommand("SELECT * FROM MyTable");
    }
}

Now you are actually able to use the ambient resource for something useful (i.e. connect to a database).

Where can I get it?

The utility is available as a NuGet package which can be installed from the Package Manager Console using the following command:

PM> Install-Package Nicolai.Resources.AmbientResource

You can also find the package on nuget.org.

Important things to know

  • It is recommended to only use the ambient resource with a using block.
    • AmbientResource.Current can be used outside of a using block, but it requires that it is stored in a reference variable and that it is explicitly disposed (i.e. refVar.Dispose()) when no longer needed.
  • The generic ambient resource includes a timer mechanism which will Dispose() the resource if a timeout expires. The timer is reset every time a call to AmbientResource.Current is executed.
    • The default timeout is 30 seconds (i.e. 30.000 milliseconds) but can be adjusted to your liking by setting the AmbientResource.ResourceTimeoutMillis.

Feedback

If you have any questions, comments or requests regarding this simple utility, please feel free to comment on this post. I will get back to you as soon as possible.

More information can be found on the github repo.