Arto Bendiken

Building A Home Security System With Elixir And Nerves

Nerves is a framework for crafting bulletproof embedded software written in Elixir and deployed onto the rock-solid, nine-nines Erlang/OTP platform running directly on top of the Linux kernel.
Arto will show how to get started with Nerves with the motivating example of a home security system running on a Raspberry Pi. To disarm the security system, you need to step in front of the camera and give a big smile.
In addition to Nerves and Elixir, we will use deep learning with TensorFlow for face recognition.

Slides here - https://speakerdeck.com/arto/building-a-home-security-system-with-elixir-and-nerves

Pivorak Conf 2.0

00:00:09.500 All right, as I said, Nerves is a framework for crafting bulletproof embedded software. Let me recapitulate some of what I told you guys two years ago and give you updates.
00:00:21.000 Many of you have probably played with Ruby. How many here have used Elixir? That's a good amount, I would say about a third. Has anyone used Nerves? Good! I want to talk to you after.
00:00:35.840 I believe that the killer app for Elixir is not Phoenix, as many often say. Phoenix is just another cool web framework, but I think what really makes Elixir unique is Nerves. Nerves has been around for quite some years, and it finally reached 1.0 last year.
00:01:01.440 The previous time I talked about it, we were still in pre-release, but now it's 1.0 and ready for you to play with. I hope to show today how easy it is to get started and how you can do a lot of cool things.
00:01:14.610 So, what is Nerves? It's a simple concept: when we develop embedded software, we can ditch the whole legacy stack and wipe the slate clean. What would we put in its place? We might start with Linux as the ultimate collection of device drivers.
00:01:27.060 Linux gives us a hardware abstraction layer for almost any hardware. On top of that, we add the Erlang VM and OTP. How many here know Erlang? About six people. Well, Erlang as a language isn't very interesting for most, but as a platform, it's rock solid. It originates from Ericsson in Sweden and has been developed for over 30 years. It runs in systems that cannot tolerate downtime and require live code upgrades.
00:02:05.160 Erlang is a great base to build on, and Elixir runs on top of it. So, Nerves is simply the mechanism for combining all these ingredients to build cool embedded solutions in Elixir, a functional language.
00:02:25.069 It might sound daunting, but the minimal firmware image you can ship on a Raspberry Pi or even a smaller device is only about 12 megabytes. This image includes the Linux kernel, Elixir, the Erlang VM, and your application, along with many supporting libraries. It's incredibly small, which makes sense given that Erlang was developed for telecom switches requiring reliability.
00:03:01.400 The typical choices for playing with Nerves are the Raspberry Pi and various models of BeagleBone. Personally, I prefer the BeagleBone because the Raspberry Pi is a somewhat closed platform. You'll often have to deal with proprietary blobs for Wi-Fi drivers, making it less transparent.
00:03:41.160 On the other hand, BeagleBone has a fully open-source design; you can go to production with modifications. However, we'll use the Raspberry Pi today because it's by far the most popular platform.
00:04:05.199 Although most people primarily know Raspberry Pi for web development, it is actually a good option for embedded development. This wouldn't be the case for Ruby, however; you'd typically avoid using Ruby on a Raspberry Pi or a smaller device.
00:04:59.910 Elixir inherits its capabilities from Erlang and is very suitable for embedded systems. I'm going through this general information quickly, as you can refer to the slides later. Now, Nerves' commercial products have been shipping for a few years, and while I don't have the current stats, I assume it has reached millions.
00:05:43.349 For example, there's a radar product running with Erlang, OTP, and Nerves, and it actually fits on much smaller boards than you'd expect, like the Raspberry Pi Zero, which is about the size of a business card.
00:06:14.910 Now, let's do some live coding. To start, we'll create a simple 'blinky' application, which is the hello world of embedded development. The Raspberry Pi and most of these kinds of boards have a couple of LEDs, and we can blink them from software. Instead of connecting an HDMI screen, we can use the LED to see that our application is alive.
00:06:54.760 Let me clean up a bit and show you the structure of the repo. The biggest directory is the config directory for target-specific settings. For our Pi 3, we’ll put the majority of our code in one Elixir source file. Next, there's the equivalent of a gem file for Elixir and the release configuration for OTP. Lastly, we have a /root filesystem overlay for adding additional files to the firmware image.
00:07:39.000 Now, when developing in embedded systems like Nerves, your laptop is called the 'host' and the target device is called the 'target.' You can run your software on multiple different targets. For instance, we can run this application on a BeagleBone, Raspberry Pi 3, Raspberry Pi Zero, and other devices.
00:08:19.980 The software we assemble and put on the SD card is traditionally called firmware. I’ll now build the firmware for the little application. Because I deleted the build artifacts, we need to get our dependencies again, similar to how you would with bundler. Now that we have our dependencies, we will build the firmware using 'mix firmware'.
00:09:22.270 This application cannot run on the host because it controls hardware, so we must specify our target as Raspberry Pi 3. Now, it knows what target to build for. Let's see... it appears I should have done this earlier since some dependencies are specific to a target. Now we have everything we need. Next, let's build the firmware and burn it to the SD card.
00:10:07.320 I will disconnect the Raspberry Pi for now. We need to take out the SD card that's easy to lose. The firmware we've built is about 28 megabytes.
00:10:51.040 I’ve just created a firmware image that’s less than a thousandth the size of this SD card. If I were to develop on Linux in a typical environment, the install recipe would take up a couple of gigabytes. However, with Nerves, nearly any application will have a firmware size of fewer than 100 megabytes, making it incredibly efficient.
00:11:33.080 Now we are ready to burn the firmware to the SD card. The command for this is straightforward—'mix firmware.burn'. It identifies my attached volumes, confirms that I want to wipe the SD card, and prompts for a password if needed. Once confirmed, the product is burned.
00:12:09.210 In the earlier development setup, you'd have to do this a hundred times a day. It's a tight fit, so let’s find our power cable. The LED should be blinking, indicating that Linux and Erlang are booting up, and finally, control transfers to our application.
00:12:44.260 Now, we should see a blinking LED. While it may not be impressive, it's essentially the 'hello world' of embedded development. With a Raspberry Pi costing around 40 dollars, you can be up and running in about 10 minutes—so there's no reason to feel intimidated.
00:14:07.200 Let's have the LED blink while I show you something more practical. I have a project here that involves a camera, which I want to demonstrate. But first, let me show you the easier way of deploying.
00:14:48.420 This little board is connected via Ethernet to my laptop, creating a private network between us. You can also opt for Wi-Fi, but it tends to be a bit tricky to configure, and Ethernet over USB works well for some boards.
00:15:31.000 We have a dynamic hostname, so I can ping my Linux board. I’ll log into it via SSH. Now let's take a look at the updated process. This is what I usually do nowadays, without fiddling with the SD card.
00:16:43.440 By running an upload script, I can quickly update the firmware on the board. This establishes an SSH connection and updates one of the firmware partitions. Nerves has a clever partition layout allowing you to switch between firmware A and B during upgrades.
00:17:06.460 This mechanism ensures that if an upgrade fails, you can revert back to the previous version. As I mentioned earlier, I’ve been talking longer than expected, so let's move ahead.
00:17:57.650 This project is still a work in progress, so there are rough edges—I was trying to fix a bug just before this presentation. The demo involves burning another firmware to the Raspberry Pi, which will take control of the camera.
00:18:51.490 So, I’ll set the environment variable again, build the project, and burn the firmware wirelessly. Let's see if this works. The build process may take longer than expected, especially if you plan to update frequently.
00:19:43.120 This firmware is larger since I based it off a project dealing with robotics. The uploaded image will be roughly 47 megabytes. Once the board is up, I’ll rely on the heartbeat pattern for feedback, knowing that it usually takes 10-15 seconds to boot.
00:20:51.430 Next, we’ll connect to Nerves locally. This allows us to access an interactive Elixir session on the board where we can monitor the log. The system will be capturing live video and performing face detection and recognition.
00:21:39.790 I'll introduce my lovely wife and baby for demonstration purposes. We're live-streaming JPEGs by grabbing frames from the camera. This may be a small test, but it shows the capabilities of Nerves.
00:22:10.200 Let’s test face recognition. I plan to eventually use this for security, deploying it in various places, including my garage and home. I can quickly run through some highlights of the code we’re working on.
00:22:49.240 We connect the remote console for debugging, and while we don't have much time, I suggest looking into GPRC for seamless interoperability between Elixir and Python. The camera driver is quite simple, controlling a C++ program performing computer vision.
00:23:43.220 I want to model the alarm system as a state diagram. An armed system can transition into an intrusion state upon an unauthorized entry. There’s a lot to cover in terms of implementation, so I might have to save more details for another session.
00:24:36.380 Our API is defined using Protocol Buffers and GPRC, allowing diverse programming languages to interact with the alarm system. While there’s much to discuss about face recognition, I plan to save that for a future talk. If you're interested in these technologies, feel free to reach out.
00:25:14.950 As for integrating digital locks, I'm exploring options for connecting the alarm system to door locks. The Internet of Things is promising, but it's critical to ensure reliability.
00:30:56.520 Thank you all for your attention!