Antifurto: home-made security camera

1 Introduction

In February 2014 I had a very unpleasant surprise after coming back home from a
weekend in Berlin. Me and my girlfriend found out our apartment upside down
because of burglars. We suffered the loss not only of many of our belongings,
but worse, of our safety. We didn't feel safe in our home and we didn't feel
safe to leave it - not even for half an hour - for the fear to come back and
find somebody inside. It was with this mood that I started this project: totally
motivated to do something about it.

My goal was to install in the apartment a security alarm that was cheap, safe
and easy to use: something that I could trust. Nowadays there are plenty of
alternatives that satisfy all the requirements, but at that moment I couldn't
find anything like that. As I am a software engineer, I decided to jump into the
project and spend most of my free time on it (my girlfriend was only partially
happy with this resolution).

The end result was a Raspberry Pi with a camera module and a bunch of software,
in part taken from the open-source and in part written by me. As of the time of
writing, it's been running in production (namely my apartment) untouched for
more than three years now. Ironically my security camera lasted way more than my
apartment, because since then I already moved twice. So, quite a success for me.

And, if you're asking yourself if I had any burglars again since then, the
answer is no, luckily. But I had the opportunity to test it multiple times when
my parents have intruded my apartment without permission…

1.1 Why?

At this point you can probably see my motivation behind the project, and also
the target audience: I needed something cheap that I, and my girlfriend could
use. This set of users was important for the design. It meant that the normal
usage should be simple, because my girlfriend (who is not a developer) had to
use it. The configuration and maintenance was however on me, so I didn't focus
on make that simple.

Today I'm open-sourcing the project. You can find it on GitHub under
mbrt/antifurto. The name comes from an Italian word that means "security alarm".
It was a codename at the beginning, waiting to be changed in something better,
but in the end I didn't bother. So antifurto is still the name today.

Why am I open-sourcing that now, and not before? Why not keeping it closed
source? The project started to meet my needs, so I had no reason at the
beginning to open source something that was completely tied to my use case.
Nobody would have gotten any particular benefit from it. After some time however
it grown up into a more featured product. So, since at the time I wasn't happy
with my job, I considered starting a business and commercialize it. Long story
short, getting funds for startups in Italy is quite hard, so I needed money from
myself or my family. I then had to improve many parts of the project because I
needed to scale out for multiple customers. It was not only about my apartment
anymore. In the meantime competitors started to jump out from nowhere before I
even got started. I had an opportunity for a new job, so my motivations kinda
vaporized.

At the end of the day, there is not a commercial product, but a working
prototype, and an interesting experience to share. I decided to open-source it
now, because I needed time to put together this writeup and cleanup some
documentation. All things that I find boring, so it took me a while.

1.2 What?

In this writeup I'm going to present the interesting bits of the project. I will
try to not focus too much on the details, but rather to present clearly the
high-level architecture, some design decisions and some interesting
implementation bits.

1.3 Features

The antifurto project is essentially a security camera that allows to monitor
what happens through the lenses of a single camera. When the camera detects
motion above a certain threshold, it sends notifications through WhatsApp and
emails and starts to record pictures. These are in turn saved to the local disk
and uploaded to a Dropbox folder. There is also a web portal (optimized for
desktop and mobile browsers) from which you can start and stop the monitoring, a
live view from which you can see images in real time and an archive page for the
past recordings. It's not possible to combine multiple cameras together: single
camera, single website.

2 Architecture

The project architecture is simple. Everything lives inside a Raspberry Pi,
period. There isn't a server component communicating with the camera, or
anything else. This is not an ideal architecture from the security point of
view, because all the keys, including SSL, Dropbox API secrets, email passwords,
etc are inside that box. It was the perfect solution for me, because instead of
a device and a server to manage, I had only one device. Moreover, the
development time was reduced because the architecture was simpler.

This unfortunately cannot work out if you want to provide the project to your
mother (assuming she's not a software developer). The Raspberry needs a non-zero
amount of maintenance, to provide a minimum amount of security. This includes
for example installing OS updates and rebooting the device periodically. The
keys need to be safe guarded inside the Raspberry itself, and re-generated in
case of leak. Again, this is not good if you want to do it properly, but I
preferred to do something quick and get it working as fast as I could.

Now for the details. The project is divided into three main parts:

the main antifurto executable (written in C++), which is responsible for the
monitoring and notifications;

a web server (Apache + PHP), that serves the website from which you can see
the live stream, turn the monitoring on and off and view the archive;

a FastCGI component that serves as a bridge between the webserver and the main
executable.

As you can see, the pictures come from the camera module and are processed by
the antifurto main executable. This decides whether to store the pictures on
the local hard drive (an SD card), and upload them on Dropbox or not. It also
decides, when to send notifications via email or WhatsApp messages. Whenever the
user decides to start a live view from the web interface, or start/stop the
monitoring, the backend sends a POSIX signal to the main process. If the desired
action was to start the live view, the main executable will start to send the
pictures over the zmq channel to the antifurto.fcgi component. Its only task
is to forward them to the webserver via an FCGI socket.

In the diagram you can see the architecture of the main executable. Each box
represents a class. I didn't represent all of them, but only the most important.
For example I left out the utility classes like schedulers, queues, observer
lists. The dark boxes represent controller classes, which are responsible for
managing specific parts of the application. Controller classes manage all the
boxes connected via a "tilted square" arrow. This means that they both own those
classes (so they are responsible for their lifetime) and they know how to
operate them. Red boxes don't manage anything, but they provide a functionality
either for other classes or talk to external services.

One important thing to notice is that each class is owned by one and only one
controller. The architecture and the lifetime of the resources are very simple
and clear in this way. A consequence is that classes can be tested individually
much more easily, since there are no cyclical dependencies, and children don't
know anything about their parents.

In the diagram you can also see what are the inputs and outputs of each class.
Red arrows are inputs, and dark arrows are outputs. You can see that I didn't
connect explicitly those arrows. Why? Because they are loose connections.
Outputs are provided in the form of observers1, and classes interested in
pictures don't know anything about the Camera class. So, controllers are
responsible to "wire" those connections, by registering themselves to the inputs
they need and forward them to the classes they manage. For example the
RecordingController class register itself to both alarm notifications (provided
by the MotionDetector) and the picture stream (provided by the Camera). It is
managed by the MonitorController, so whenever the monitoring functionality is
stopped, the recording classes can be safely deleted. The RecordingController
then listens to alarm events and whenever one occurs, it forwards the pictures
stream directly to the PictureArchive and the DropboxUploader.

3 Main executable

In this long section I'm going to talk about the internal details of the main
executable, called antifurto for a very lack of fantasy.

3.1 Main class

The main class is called Antifurto, what a surprise! It is responsible to
start and stop the monitoring and the live view, by orchestrating the resources
involved. It uses a Config structure for the configuration, that comes from
the command line and the configuration file. It can be used as an external
library, as most of the components in this project, since it is self contained.

It contains all the controllers, that are described in the Main controllers
section, and the implementation details are hidden from the header file behind a
Pimpl.

The interface is very simple: it takes a configuration and the user can control
when to start and stop monitoring and live view from four public methods:

So, this class is all about the very high level use cases of configuring,
starting and stopping the main functionalities.2

These functions are a bit less simple than one can at first imagine. For example
the startMonitoring is anynchronous and starts the monitoring only after a
configurable timeout. This is because after the start, the person may need to
get out the way before the monitoring effectively starts. The default I'm using
for myself is one minute. At the same time, the function needs to check if the
user cancels the start request before the timer goes off. I needed to put some
attention in the interaction between start, stop and the destructor. The
CameraController lifetime depends on whether one between the monitoring and the
live view functionalities are on:

This method is called by all the four external methods, to factor out this
common part.

3.2 Main controllers

In this section I'm going to describe the three controllers that manage the
monitoring, live view and the camera sub-components.

3.2.1 MonitorController

This class controls the monitoring functionality life cycle. It delegates to its
sub-components tasks such as motion detection, and notifications. The most
important part of its public interface is the examinePicture function:

voidexaminePicture(constPicture& picture);

The Main class calls this function whenever a new picture comes out of the
camera.

Another interesting bit is the way this class asks for the upper level
controller to change the picture capture interval, or to stop the recording
altogether. To break cyclical dependencies, the upper level class has to
instantiate the MonitorController by passing a couple of callbacks. One of
them is the SetPicturesInterval:

that is used whenever some motion is detected. In that case, the
MonitorController asks for an increase of the capture frequency. It's also
useful whenever nothing is going on, to decrease the capture frequency and so
save energy:

This uses the observer pattern, implemented as an utility in the meta namespace.

Every time a picture is taken, the observer callback is called. If multiple
observers are interested in different capture rates, the maximum rate is used.
This means that an observer specifies the minimum speed, but it could get
pictures at a higher speed, if it's necessary for other observers.

To implement this functionality, in a separate thread a Metronome class sleeps
the required time, and then the Camera class takes a picture. Every time an
observer is registered or de-registered, the sleep time is updated.

3.2.3 LiveViewController

This class starts and stops the live view functionality. It doesn't implement
the functionality itself; it just controls the lifetime of a LiveView object.
From the outside it takes pictures and the start and stop commands.

Whenever a picture comes, it is forwarded to the internal LiveView object. To
detect when the user is not interested in the live view anymore, there is a
primitive control flow, which is basically a fixed queue of pictures sent to the
browser. When the client doesn't request them, the queue fills up. After a
certain timeout with a full queue, the LiveViewController simply stops the
live view:

To do this, the internal LiveView object simply informs whether it has been
able to process the image or not, and if not, the timeout is checked.

The stop function invokes a callback, that asks to be de-registered from the
stream of pictures.

3.3 Picture's capture

3.3.1 MotionDetector

This class uses the OpenCV library to examine the pictures flow and determine if
something is moving. It implements the observer pattern to notify the observers
for the current state. The motion detection code is pretty simple:

The code works with three pictures: the current one and the last two. Two images
are computed out of them by making a difference (i.e. subtracting the gray
values of the pixels one by one) between the first with the second and the
second with the third. Then a "bitwise and" is computed between them. Random
noise will be filtered out, since it's unlikely to stay still for three frames,
and the image will be almost completely black. Whenever something moves however,
certain areas of the pictures will differ among the three frames, and so the
difference will produce white pixels. These pixels are then counted in
motionHappened(), and if they exceed a certain threshold, then motion is
detected.

There is an additional layer of protection against errors, and it's a state
machine that counts how many consecutive moving frames have been detected. These
states are used to better control energy saving, picture capture and alarm
notifications.

Every time a transition occurs in this state machine, all the observers are
notified. It will be up to them to take the right action.

Everything starts from the IDLE state. Whenever some motion is detected, the
state becomes PRE_ALARM. If no more motion frames are detected, the state goes
back to IDLE. If the motion continues however, the state machine transitions
to ALARM. It stays there while the motion continues. When it stops, the state
goes to the STILL state. This means that even though nothing is moving, for
some time, the alert level is still on alarm. Indeed, if some motion happens
again, the state turns immediately to ALARM again. If instead nothing happens
for some time, the state goes back to IDLE.

In this way we have decoupled the abstract states in which the system may be
with the actions the various components have to take to respond.

3.3.2 Camera

The camera type is statically determined in StaticConfig.hpp. In the
Raspberry-Pi case, there is a homegrown version implemented by PiCamera that
uses a slightly modified version of the picam library, that I found here. This
library is a simple interface on top of the Raspberry userland library I forked
just to ease the build. To capture images outside the Raspberry world I instead
opted for the OpenCV library and implemented CvCamera. Now, I have to admit
that the CvCaptureRAII class might look a bit weird, but it was an attempt to
implement the camera resource through RAII. I took inspiration from Martinho
Fernandez rule of zero blog post and the concern about the rule of zero by Scott
Meyers. To discuss this in detail I would need an entire blog post in itself, so
I'll just point you to these valuable resources. To be honest I'm not very
satisfied by its look and feel now.

With the same spirit I implemented the capture resource for PiCamera, which is
just a one liner:

std::unique_ptr<CCamera, void(*)(CCamera*)> capture_;

It uses the non-so-well-known custom deleter feature of std::unique_ptr.
Again, look at the Fernandez's post for an explanation on why I didn't just
implemented a stupid destructor for PiCamera. Everything is handled
automatically, since in the constructor I pass the resource, and the deleter
function to be called in destruction (namely picam_stop_camera):

These two different implementations of the camera resource were not intended to
be used at the same time: one was only for the Raspberry Pi hardware, and the
other for PC's with USB cameras. For this reason I didn't introduce any common
interface, and just used a compile time define and a typedef to switch between
them:

The code will simply refer to the antifurto::config::Camera type to get a
capture resource. I just needed to make sure their public interface (i.e. the
public methods) are the same, so the two classes could be used interchangeably.

This trick is quite handy if you don't need runtime polymorphism, but honestly
it's a bit overkill for this project.

3.4 LiveView

This class is managed by the LiveViewController and is responsible to forward
pictures to a ZeroMQ socket. It has a single producer / single consumer queue
(see the concurrency section) and a worker thread to offload the communication.

The interesting part about this class is the use of a non-blocking lock-free
queue, that allows minimum interruption for the producer. Whenever the queue is
full, the images are discarded, and the caller is notified, in order to make
some control flow, without interrupting the images flow.

3.5 Picture recording

3.5.1 RecordingController

This class is responsible for managing the registration of the pictures while an
alarm is active. It accepts pictures with the void addPicture(Picture p)
method and registers itself to the MotionDetector to know when to start and stop
the recording. This is done by saving Jpeg pictures on the local file system (by
using PictureArchive) and uploading them to Dropbox (by using DropboxUploader).

Whenever the motion detector notifies this class about an alarm, it starts to
save the pictures. When there is no motion involved (even if the alarm is still
active), the recording is stopped.

Saving pictures in real time is important, both on disk and online. If there is
a slow upload for any reason, the queue between the producer (the Camera) and
the consumer (the uploader), grows. This would mean that by looking at the
pictures online, the delay between capture and upload will grow more and more
over time during alarms. To avoid this behavior, the queue size is limited, and
whenever it's full, the coming pictures are queued in a secondary one:

This ensures a fixed maximum delay between capture and upload, just by skipping
pictures now and then, when the queue is full. All the missing pictures are
instead uploaded when the alarm is not active anymore (the case
State::NO_ALARM: above):

3.5.2 PictureArchive

This class saves pictures in Jpeg format to a given folder. It takes a stream of
pictures and two commands: startSaving and stopSaving. When the recording is
started, not only the next picture is saved, but also some of the previous. This
object has indeed a fixed sized circular buffer that allows to retroactively
save the images right before an alarm popped up. It also allows observers to
register for when a picture is saved to disk, getting the file name.

The picture gets a timestamp text overlay on the top left corner and then is
saved on disk.

On the bad side there is the ring buffer, which is actually not a ring buffer at
all. Pictures are pushed to the end of a vector. The beginning is then deleted
by moving all the other elements at the previous index. Not pretty, not fast,
but all in all it works. Moving to a proper circular buffer should not be very
hard.

3.5.3 DropboxUploader

This class is responsible for uploading files to a Dropbox account, by using an
external dropbox_uploader.sh script. It just generates a configure file for
it, starting from the Antifurto's configuration, and uploads a file when
requested, by launching an external process. Nothing fancy here, I just forked
andreafabrizi/Dropbox-Uploader.

3.6 Notifications

Two types of notifications are supported: WhatsApp and emails. WhatsApp have
been historically fighting against bots. For this reason the phone numbers I
used as source for notifications have been banned. I don't recommend using it
for this reason. A much more sane approach would have been to implement a
Telegram bot instead, but at that time they didn't exist. Email notifications
are instead much more safe and reliable to use. For those two functionalities we
have two very similar controllers: WhatsappNotificationController and
MailNotificationController, that register themselves to the MotionDetector and
whenever there is an alarm, they try to use their counterpart
(WhatsappNotifier and MailNotifier) to send the notifications
asynchronously. They also take care of retrials in case of errors, and avoid
sending too many of them in a short period of time, to avoid flooding the
receivers.

3.6.1 WhatsappNotifier

This class manages WhatsApp notifications. Whenever send(std::string const&
dest, std::string const& msg) is called, it sends a message with yowsup-cli by
spawning an external process. This class just generates the configuration file
needed by Yowsup from the main process configuration and takes care of its
execution.

3.6.2 MailNotifier

It calls an external bash script that uses the Unix mail utility, to send the
mail.

3.7 Utility libraries

Here I present some random notes on the utility namespaces that help with design
patterns, concurrency, filesystem and logging. Some of them are a bit
over-engineered but in hobby projects you also need to have some fun, don't you?
:)

3.7.1 meta namespace

This namespace contains some generic patterns and algorithms that do not depend
on the specific details of the project itself. In Observer.hpp you can find a
generic implementation of the observer pattern. A Subject wants to provide
observers the possibility to register for events. The class takes a variadic
number of type parameters, that will be used in the notification. For example:

in this example we want to notify our observer with an integer and a float. To
do that we just need to declare Subject with the right parameters. This will
in turn be able to accept observers that respect the std::function<void(int,
float)> signature.

Interesting:

the registration returns a token that when goes out of scope unregisters the
observer automatically;

it is possible to register and unregister observers within notification
callbacks (re-entrant calls are supported).

Other small utilities are also present, like ErasedUniquePtr, which provides
a unique pointer with an erased deleter. This is an useful workaround to a
subtle problem when you want to forward declare a class and use it in an unique
pointer. For more details see the type erasure post of Andrzej's blog.

3.7.2 fs

This namespace contains simple path manipulation utilities to concatenate
multiple paths with a single call:

std::stringp = fs::concatPaths("/var/log", bar, "file.txt");

This is similar to what boost::filesystem does, but in a more functional way.

3.7.3 log

This namespace contains logging utilities. The focus of this library was to
provide a fast and simple logging without using macro shenanigans.

You can use it with a call to a free function, that will return the proper
logger:

log::debug() << "my log here " << 15;

There is also a reload function. When a log rotation occurs it will simply
close the old file (that has been rotated) and open a new file in the same
place. Ignored log levels are implemented by returning a logger that writes to a
NullSink, which simply does nothing. Interestingly cryptic is the
implementation of an std::outstream that does nothing. You can find it in
log/NullStream.hpp.

3.7.4 concurrency

This namespace contains some classes that deal with concurrency. An interesting
one is SpScQueue, that wraps a worker thread and allows to enqueue work items
for it. The type of the work item is templated, to maximize reusability. The
queue is a lock-free implementation that can be chosen at compile time among a
fixed-size and a dynamically allocated one. The former is preferred in case the
maximum queue size is known at compile time.

As a side note I would like to add here that since the project deals with
real-time data, avoiding dynamic allocations can be critical. We used fixed
bound queues in all places for this reason.

Another interesting class in this namespace is the TaskScheduler. It provides
the possibility to schedule tasks at certain time points, either one-shot or
periodic:

The work items are processed one after the other in a worker thread, so delays
added by one task impact on the next ones. It is for this reason used only for
short tasks.

3.7.5 ipc

This namespace contains classes related to child processes and inter-process
communication. There is a forkAndCall function, that forks the process, calls
a the given function and returns the function result by using the child process
exit code:

/// This function fork the process, calls the function in the child process,/// wait for completion and returns the function return value.ChildProcessforkAndCall(std::function<int()> f);

The child process itself can be killed or waited. In the latter case, the
function return code will be returned.

In this namespace there is also a NamedPipe class that provides Linux named
pipes. The constructor creates a FIFO with the given file name, and the
destructor removes it.

There is also an interesting PosixSignalHandler class, that handles POSIX
signals safely. You need to use it carefully though: initialize it at the
beginning of the main function, before any thread creation, and register all the
signal handlers as soon as possible, by using:

voidsetSignalHandler(intsignal, Handlerh);

where an handler is a callback that takes the signal that just happened:

usingHandler = std::function<void(int)>;

The POSIX standard says that a lot of functions are not safe to be used within
signal handlers. For example it's not possible to allocate heap memory and call
many standard library functions. We need however to support arbitrary code
execution in the handlers, so to workaround this we use a vector of atomic
booleans, one for each possible signal. Whenever a signal is sent to the
process, the handler flips the corresponding boolean to true. A separate thread
polls that vector, and executes the registered handlers, if any were given. This
allows the signal handler to return immediately and in a safe way:

4 Website

I am not so proud of the website code, and I don't recommend looking at it in
detail. I did not have much experience in web development at that time, but I am
still quite happy with the result. Year ago it was not so obvious that a website
was mobile ready:

The website is just a bunch HTML + JavaScript
pages. For the styling and the responsive design I went with the immortals
Bootstrap and JQuery, while for the server side part I used the now infamous
PHP.

Commands like start and stop monitoring and live view are issued by the frontend
by doing GET requests to pages under the controller/ path. The PHP backend
listening that endpoint sends POSIX signals to the main executable. The
communication is not more complicated than that, because this first
implementation worked fine. I didn't bother changing it in something more
complicated.

The funniest part of the frontend is the live view though. Also in this case the
first implementation was good enough :). Basically the frontend uses an infinite
loop of Ajax requests3 to a special live.jpg picture, which is served by a
custom FastCGI backend, written in C++. This is the one described in the
FastCGI backend section.

Yes, that's it. I didn't even have to shorten the code. Something that I
couldn't explain myself here was that in loadImage I couldn't use JQuery,
because it was much slower than the old style setAttribute and image.src =
url. So I decided to live with that.

The archive page shows pictures from previous alarms. Just don't look at the PHP
code behind that, it's really horrible crap. It can give you nightmares for days.

This is the carusel view:

This is the mobile version:

And this is the date selector for the alarm, in the mobile version:

5 FastCGI backend

One of the website backend components is ironically in a folder called
frontend. The name is unfortunate but it was meant to suggest an interface to
the main executable. It communicates with it via a ZeroMQ socket, and with the
web server through FastCGI.

Interestingly enough, the first implementation was in Python, but it was too
slow. I had to re-implement it in C++, and now it's about three orders of
magnitude faster (yes, I really mean 1000X).

The main.cpp file contains all the logic:

A webserver request is directed to the executable through the standard input
(which is ignored);

a picture is requested to the main antifurto executable through a ZeroMQ
request;

as soon as a reply arrives, it is immediately written to the standard output,
that is read by the webserver.

There are a bunch of utility classes that have been used to make the code
cleaner, described in the following sections.

5.1 ZmqLazyPirateClient

This class implements the Lazy pirate pattern in ZeroMQ, which is a
request-reply transition supporting socket reconnections. This allows to start
and stop the main executable and the webserver independently; the connection
between them will catch up automatically. When a request-reply transaction is
needed, this class will send the request and wait until the reply comes, or a
timeout expires. On timeout, the request is sent again, until the maximum number
of retrials is reached. At that point the transaction is considered failed.

5.2 Stream utilities

The StreamRedirector class is responsible for redirecting the standard input
and output to FastCGI stream buffers, while StreamReader allows to buffer
reads from a stream (in this case the standard input). I actually don't remember
because it's a class instead of a simple function. Probably it's a non-sense.

6 Conclusion

In this post we had a look at the pet project I worked on for a while some years
ago. By skimming through this post again I realized that it is mostly a random
collection of impressions, design decisions and code snippets, so I don't know
how effective that is for a reader. However, for me it was important to wrap up,
because after all the time and effort spent, I didn't want to forget it, and I
also wanted to share my insights with the community.4

My takeaways are that with this project I learned some stuff and I did something
useful for myself. I would definitely recommend working on things you really
need, as opposed to experimenting with technologies purposelessly. It really
helps to get them done (to a certain extent at least). Or at least that's the
only way I found preventing me to give up projects too early.5

I hope this post gave you some interesting insights and maybe inspire you some
extensions, related projects or ideas. The code is open source on GitHub, under
mbrt/antifurto, as I wrote earlier. I encourage you to take a look yourself to
some of the classes. You can also build it and use it as is for your own
security alarm. The deployment is kind of a pain right now, because there are
many dependencies and configuring the external services is not exactly easy to
do (Dropbox, mails, WhatsApp, etc). The documentation is also somehow lacking;
apologies for that.