 So, first I have to give credit for this picture to the Raspberry Pi Foundation. I actually want to Wikipedia and read about fair use, but I thought it was incredibly appropriate. I already wanted to call this Get Cooking with Nerves and I saw that picture and like, yeah, okay, it works great. So, I'm curious to know how many of you guys have, and gals have ever actually burned firmware for Nerves? Wow, that's a huge number. Okay, so the next question is, how many have done things that went significantly beyond blinking in LED or two? Okay, good, this talk is perfect then. So, I did a training yesterday on Nerves and what I learned from that and what I think I'm learning from the reaction it's got and just for the camera, only a few of you raised your hands on the second question. A lot of people have messed around with Nerves enough to maybe get LEDs blinking on a, excuse me, on a Raspberry Pi, but they haven't taken it much further than that. And I had a presentation that I had all planned to give today, but after yesterday's training, I decided I'm gonna follow in my colleague Dave's footsteps here and do some live coding instead. And the reason, yeah, I'm a little nervous about it, so go easy on me. My impression is a lot of people have been exposed to Nerves and a lot of people have taken the first step of trying to blink an LED or two, but they kind of stopped there because they don't really know where to go with it beyond that. And so I'm hoping to use this time to take a project from brand new scratch to something that is on the network, discoverable and does some interesting things all in the course of the talk. And that's gonna be instead of the slides I was gonna present, which I think maybe I'll save for Elixir Conf or something. So how many people don't know what Nerves is at all? Okay, a few. So it's worth going through a tiny bit. So Nerves is basically a system for merging your Elixir app in with a very tiny embedded Linux and producing firmware that is robust and production capable, meaning you could actually build real world shipping products based on it. And delivering that firmware bundle to a device. And what makes it much more interesting than some of the other platforms out there for building embedded systems is, first of all, it's centered around Elixir, but secondly, it's centered around something called Buildroot which is a really serious production tool chain for building embedded Linuxes and it's used in a lot of embedded products. So I was gonna skip these slides if nobody raised their hands, but I'll go through real quickly. So this slide I presented at a couple other conferences which is embedded systems of today are the supercomputers of yesterday. And it really isn't hard to understand that when Joe and company built Erlang back in the 80s, they were dealing with systems that are put to shame by the small embedded systems of today. And Erlang doesn't seem to appear to be changing at all. So NERVs is basically above what people generally use in these small microcontroller based systems for like watches and RTOSs for cameras, but it's below the really complicated Android or iOS type embedded systems that you may see. And it's trying to fit in a space where it's basically a minimalist embedded Linux. And so other things that use these kinds of minimalist embedded Linux platforms are things like wireless routers. Wireless routers often run a distribution based on build route, just like NERVs. This gives you an idea of how NERVs fits into the ecosystem when you get a, if you get a Raspberry Pi, but you've probably ever had a Raspberry Pi or be good on black. The operating system that comes with that is usually Debian or Debian based like Raspbian. And if you look at, NERVs basically tries to be much, much leaner than those. It takes an opt-in approach as opposed to an opt-out approach. And you can strip Raspbian down to make it faster and smaller, but it's a lot of work. And it comes with a huge overhead like user management and package management and often graphical display. And those things don't make sense for most embedded projects. For most embedded projects you want something that is locked down and works smoothly. And there's one, there's one very important thing that NERVs does, which is it embraces the notion of a read-only root partition. And that means unlike Debian, all of your writing, all of your logs, all of your data goes to somewhere other than where your program is stored. And that's by design and it's enforced by design. And that gives you certain benefits like the ability to be much more stable when somebody yanks the power core in the middle or configure ability because you can always get back to a known state just by resetting the variable storage back. Yeah, I'm not gonna go into that. This is from a prior talk, so some of you have seen this. I would actually go, I'll leave that last slide up for a second, I would actually go, if you're interested in introduction to NERVs, there are a bunch of talks from both this year, last year and also ElixirConf, a number of speakers including Justin Schnek and Frank Hunliffe and myself have given talks on NERVs and they're all available on the NERVs project website. I'm leaving this slide up because one of the things that sold me on NERVs from the beginning is we built production systems on it. So our company ships a product, a couple products actually, that are built using NERVs and we were shocked that when we ran NERVs for weeks on end, it didn't seem to consume resources beyond what it did in the first hour or two. And so this kind of stability was completely unheard of from any other system I've worked with and I was incredibly impressed by it. And I think that the credit both goes to the Beam virtual machine and to the good work that Frank's done in getting the Beam installed on top of Buildroot and the Buildroot guys have done an amazing job too. And my experience has stayed this way. It's not been like, there have been almost no bugs. If I can, I actually can say I cannot think of a single bug in any of our production products that has been caused by the virtual machine or Elixir or the NERVs core, the early knit library that loads NERVs. All those things have been rock solid for us. Almost all of our bugs have been bad hardware design and poor coding on the part of those of us who are writing the software. Just really briefly, this is one of the common prototyping platforms, you guys may have seen this. It's a really nice platform to prototype production products on because it's an open source hardware platform. You can build prototype something on this and then you can do your own board layout and buy the components in small quantities and ship it as a production product. And that's what we've been doing with some of our products. The one that you're probably more familiar with is the Raspberry Pi is another nice hobbyist platform. It's not really a good production prototyping platform because you can't buy the parts and turn them into a real product very easily. But you get a lot for your money and there's a huge support network around the Raspberry Pi including lots of cool sensors and daughter boards and things you can plug in. And I'll talk a little bit about that later if I have time. One of the daughter boards that some of you might want to see and we used in the training yesterday is this thing called a Grove Pi. And I actually have it on the Raspberry Pi here. Hopefully the camera can see that. But it basically takes the Raspberry Pi and adds a whole bunch of IO, analog, digital and I squared C interfaces. And then they sell all these little tiny sensors that you can just plug in and use them to prototype a project. And you don't have to do any soldering which is great. I've done a lot of soldering and I'm glad to not have to do too much to prototype things. So that's a fun platform that we're increasingly supporting. So those are our two products, let's see. That's about it. I'm not gonna ask for questions on NERVs. I'll save those to the end but I'm actually gonna dive into actually building a NERVs app and just get it going and see where we can go with it in the time we have. Okay, so, most of you have built elixir products with MixNew. If you install NERVs, first of all, installing NERVs, I had a slide on this but I'm not quite sure why I missed it. Installing NERVs is, let me actually find that slide because it would be useful. Oh, it was my very next slide, interesting. So installing NERVs, depending on whether you're on Linux or Mac is pretty easy. The instructions to do it are on the NERVsProject.org website. This URL is the exact page for the installation but if you go to NERVsProject.org which is the main website, it's easy to find how to install. You do wanna use Homebrew on a Mac because it gets you everything you need and on Linux, if you're on Debian or Ubuntu, it's pretty easy. There are instructions for other Linux platforms on the NERVs project website as well. The one command that's really a nightmare is this mixarchive.install, HTTPS, blah, blah, blah, blah. Hopefully we'll fix that by making it something like mixlocal.NERVs just like we can with Hex and Rebar at some point but as for right now, you have to go do that and that again is on the installation page on the NERVsProject website. So I'm gonna go ahead and do, I've already installed things so I'm not gonna go through that but I'm gonna do mix, run mix, whoops, help. And can you guys all see that? Looks like it's showing up pretty well. Okay, so you'll see that because I've installed that NERVs archive, I do have mixnervs.new. And so I'm gonna run mixnervs.new and I'm gonna call my project demo. And it immediately gives me an error saying you should pick a default target. This error might go away. So a target is the type of machine that we're building the software for and what NERVs does is it cross compiles your app into the target architecture and platform and bundles firmware for the specific hardware you're going to run. So we have to give it a target. In this case, we're gonna say RPI-3 because I have a Raspberry Pi-3 up here. And it indeed created a little app and I'm gonna cheat. I'm not gonna do everything live coding because I drive you all crazy. So I'm going to copy I'm gonna put a little file there that has my hints about what I need to do so I don't mess it up. That's not what I want to do. I'm still getting used to Adam. Okay, so this is a project structure created. Looks pretty much like any mixed project. There's a couple interesting things about it. The MixStudy.exe file has some extra stuff in it to load the NERVs development environment and it has some aliases it defines to deal with cross compilation. And I'm not gonna go into the technical details of all that because it's just boilerplate at this point. What I am gonna do is start modifying this and the very first thing I'm gonna do is add a couple dependencies. I'm gonna add NERVs interim, let's see, get the right file here. I'm gonna add NERVs interim Wi-Fi which is an unfortunately named library but correctly named. It's not yet ready to call beautiful so there are two network stacks for the NERVs project right now. We're trying to unify that. I'll talk about that later. Sorry? Yep, thanks. Appreciate that. Anyone who wants to do that, that will save me a lot of embarrassment. Okay, and then I'm going to also, let me bring up my sauce. Oh, that's right. This is probably, for those of you that know about the changes in Elixir 1.4, I'm doing this so that dependencies automatically get started. And then I'm going to make some changes to demo.ex which is basically just a boilerplate. This is the thing that was created and it doesn't define any worker children at all. It just starts a supervisor and so I'm gonna put some workers in there. I'm gonna put in one of them that basically starts the Linux kernel module that is needed to do our networking. And then the other one is gonna call a knit Wi-Fi network and that's actually gonna join our Wi-Fi network. And I'm gonna set a module variable to be the name of the interface, the Wi-Fi interface on this board which is WLAN0. And I'm also going to add those two functions. Let's see, let's add those here. Oh, I only got one of them. Thought this would be easier than Vim, but I'm not sure. Okay, so that's all I'm gonna do for now to our main module. And then what I'm gonna do is I'm gonna add a config line in config.exe which defines how we're gonna connect to our wireless network. So hopefully that all made sense. It's not too complicated. And the documentation for a lot of the stuff is in the individual dependency modules. And so let me just double check that I actually did everything I needed to do before I do this, yeah, that looks good. Oh, yeah, good point, thanks. I'll do that now. It isn't really required for this step but I would be confused later if I didn't do it. And I won't actually go into this quite yet, what that does, but we'll do that. Okay, so at this point, I think I have a workable app. Everything's saved. So I do mix depth, step, get. Let me make sure I'm actually online with something useful. I need to get the Casamanica Wi-Fi. Success, but in theory means I have network. See if it really does. Yep, look at that. So it's gonna download all of the NERVS packages it needs to build firmware for this device. Now this would take a long time if I didn't already have them in my cache on my machine from other projects I'd done. Because the hotel Wi-Fi isn't as fast as you might want. But luckily I have them all. So now all I have to do is type mix firmware. Wait, is that right? Yeah, I think so. And a whole bunch of stuff happens. And you'll notice it's compiling some C code. And some of that C code I believe is for, oh, it's got a great error. Okay, so some of that C code is to support the underlying dependencies. So this error actually is one that hopefully will go away but it's actually a pretty nice error because all I have to do is run that. Now that we're using distillery, we need a NERVS.rel config to access file. I'm not gonna review it, I'm just gonna use the default one because I happen to know it works. And then I'm gonna once again mix firmware, it picks up where it left off and builds me some firmware. And what I'm gonna do is actually put that firmware on a device here. So one of the great things about the MacBook Pro with USB-C is you end up with all these little gizmos to do things that you otherwise had different gizmos to do. This one's really cool, it's the world's smallest SD card burner I've ever seen. So to actually burn an SD card, it's a lot easier than it was a year ago or two years ago. You just do mixfirmware.burn. And because I have this really cool, new MacBook, you can see it's once my fingerprint to let me burn to my SD card, which is my favorite use so far of the fingerprint sensor. Okay, so I have an SD card, it's burned, and I'm gonna go ahead and put it in my device. Now there's one in there, let's take that now. Doesn't work to try to put two in at once. Okay. Now unlike previous talks, this talk does not involve linking any LEDs. So the reality is, I don't actually know from the LEDs whether this worked at all. So give me some good karma here. What I'm gonna do is try to access the device on the internet. Unfortunately, I don't really know where it is. We'll get to that in a minute. But I'm gonna guess, because I kinda know where it probably is. I'm gonna say it's at 192, and I'm changing by the way, you'll see I go up here, I'm changing to a wireless router that I have here that this thing joins. So it doesn't have to join the hotel network with a password and all that. I know it's not there. Let's see if it ended up at 101. Yep. Okay. So I'm pretty sure that's 101. I don't really know. It would be nice to know. There you go. There's my demo. Okay, I'll take the next step. Okay, so the next step is, let's see what we can do so we actually can figure out what's going on. There's a great module called logger multicast backend. And for those of you that understand multicast logging, or multicast in general, it lets you find something on a network because the device can basically send to a multicast group and any node in the network can subscribe to that multicast group. And so you can figure out where something is just based on its multicast log spot. So I'm gonna go ahead and add this to config.exe. And basically all this does is configure logger to use the logger multicast backend. And then I'm going to also add the dependency to my mix file. And, okay. So what I didn't talk about in great detail is there's one other little module I added here called nerfs.firmware.http. And so I only just to make sure I got everything here. It's hard to talk and do this at the same time. Yeah, it looks good. Okay. Okay, so because I added mix.firmware.http, the first time I burned firmware, in theory I can do a command called nerfs.push. Oh, I have to get depths, sorry. Oh, this is not gonna be fun. Switch networks. Thank you. I don't think there's any reason for me to stay on wifi after switching networks. But I'm going to switch back. Yeah, okay, so now I've got logger multicast backend. That's interesting. That's what I get for live coding. You did tell me. I grant you that. Oh, it should have that. Oh, I'm just typing the wrong command. Okay, so now I have this thing called firmware.push. And what firmware.push does is kind of cool. I can say firmware.push 192 or, yeah, 192.168.0.10. Was it 101? Is that right? Okay. What did I do? Oh, yeah, yeah. You know what? I did that when I practiced it too. There we go. And so now I'm delivering firmware over the wifi as opposed to burning the card. The other thing that's interesting, great question. No, NERS has two separate read-only partitions by default. And it will always apply a firmware update to the opposite one and then reboot to it. So I got some errors here, which I expected to get because why did I expect to get those errors? Oh, because I'm not actually connected to the hotel wifi. Now interestingly, let me just see something for a second. Okay, so the device is back up, but I didn't get my logs like I expected. Am I on the right network here? Yeah. Let me just, for the fun of it, cycle power again and make sure I didn't miss something at the time that it came up. Not sure I understood it one more time? No. No, multicast addresses are in a separate address range from the local networking addresses. Well, I am definitely in demo mode, so I don't understand what I did there. I'll look and see really quickly. Back end looks good. Let me see my config.dxs, huh. Looks good. Well, I'm gonna keep plowing forward and maybe I just didn't build something because the rest of it all appears to be working. So the next thing I'm gonna do is I'm gonna go ahead and add some more configuration in. When we do it on time, oh, we're getting there. Let's see. Oh, that's not what I want. Oh, yeah, thank you. Okay, so what this is doing is it's actually making my mixed project config available to a module called nerve cell. And that's gonna give us some more data about the environment, the mixed environment available at runtime, so that we can do something interesting with it, and I'll show you what we're gonna do within a minute. So back in my mixie access file here, I'm gonna add a few more module variables at top. I'm going to change some things about my project here to incorporate some, a bit more metadata. And specifically I'm gonna refer to, instead of version the way it was defined, which was just coded as zero, one, zero, I'm gonna use this date stamped version that I created here so that I actually can build firmware and know when I built it. Oh, did I not? There's, that's the reason it didn't work then. Okay. Got any of your notes. Thank you. I only practiced it three times, you know. I didn't need more than that apparently. Well, sorry, we'll jump to the fun part here then. So I'm also gonna add this to my depth. This is a library that isn't really officially part of NERVs yet, but hopefully will be sometime soon. And then I'm gonna go for the gusto here and add a whole bunch of code. And this is a case where I'm gonna try to explain what I'm doing, but it might be partly after it's done. So I'm gonna add one more worker that starts something called a network manager, and I'm gonna add a whole new file called networkmanager.exe, and I'm gonna throw some code in there. And that code is going to basically listen for events from the network stack. And my opinion is this particular functionality that's here should be a standard depth that you can just include in your app, and we may get there. But basically what this is gonna do is start a bunch of things when it hears that the device gets a network address, and specifically it's gonna start relying distribution, which kind of give us some fun things to do. So let's see, did I get that? I get that. Make sure I got everything. This is the last piece of coding. Yeah, I got that. Oh, can't forget this one. So in VM.args, for various reasons, you have to define a cookie before the VM starts, otherwise bad things happen. So I'm gonna give it a cookie if you wanna run distribution. Specifically if you wanna run distribution where you dynamically start it and stop it. So that all looks good. That looks good. Got that, got that, got that. I think I got all that. All right, well wish me luck here. So I will actually talk briefly through this network manager piece. Basically all we're doing here is starting a gen server and we're using registry. And registry is wonderful for NERVs because we've been looking for a general purpose way to distribute and handle events between modules. And so this is looking for events that come from the DHCP client. And the DHCP client will find an address and will catch the fact that it found an address and use it to configure our relaying distribution based on that address. That's what fundamentally is going on here. It's also doing something where it's setting up something called NERV cell, which I'll show in a minute. Okay, so let's try Mix Firmware this time. Actually, mix steps.get. I still have to be on my other network, don't I? Kat Simonica, there we go. And then let's go to the, well actually I'll build firmware or two. I did type it this time. We're good. Thank you. I was wondering why that didn't work. I was like, dang, that worked three times. So when it says updating base firmware with release, it's actually taking a copy of Linux, embedded Linux, in this case a pre-built system for the Raspberry Pi 3 and merging your app with it and building a whole file system and image into this firmware bundle. And now I will connect to my local wifi and I will, it should still be, yeah. That should still work. Let's see, yep. So I'm putting new firmware on my Vox. I might even make it on time, mm-hmm, I believe so. Yeah, let's see what happens when it restarts. I've got my fingers crossed on this one. Okay, it's probably restarting about now. Oh, there it is, whew. Got me a little nervous for a minute. I was just about to say I did something wrong. So you'll notice wifi manager is very noisy, which is one of the reasons it's interim. But you can get the entire startup all the way from starting multicast back in, all the way through starting the network manager and you can see what's going on on this box. I'm gonna do a couple other really quick things here because it's worth pushing the envelope a bit any time you do a live demo. We're gonna try, no, would you say no, it's not? Yeah, don't blame me there. Was I 101, is that right? Let's try remote shell. I am now shelled into my NERVS box and if I do LS, I'm actually looking at the file system of the box and I'm able to poke around and do everything you can do with remote shell, which is kind of cool. And I'll do one more hail merry here because I think there's nothing quite so satisfying as running observer on a embedded node. I don't know why it's more satisfying than any other node, but it is. So, it's connect node 101, I think. And if you give it a second, yep. Okay, so you just noticed the architecture changed. Confiled for ARM build route and I actually can look at load charts and memory and so forth is coming across. Memory allocations, applications running, processes, so forth. So this is pretty cool. Finally, you have visibility into this beyond LEDs. I'm gonna show one more quick command and then we'll call it good. This is an experimental tool. When I've been watching this log, I've actually been running a command called cell watch, which watches a multicast log. But one of the other things you wanna be able to do is discover devices on a network. And one of the reasons I didn't demo this first is it's somewhat unreliable on some Wi-Fi networks, including mine for some reason. So I've got some work to do there. But you'll notice I can go query the metadata from the device and I have the version number and it's IP address. I can also refer to it by its board ID, which is this first number, EC314F. Every device will have a unique board ID. Thank you. So it gives me information from my project, including pretty much any metadata I wanna put there I can return. And so there are libraries to basically query devices on a network and discover and return what's there. So that's pretty much it. I think I'm out of time. I don't think I had anything more particularly in the slide deck. If I could get the slide deck back up. Yeah, okay. So there's some things we're working on right now. These are the kind of the major focuses of the NERVS team. Getting things better, getting things easier. It's been clear from the training that getting to the point I'm just at is not documented well enough or nor is it something that a lot of people feel comfortable doing yet. And getting the cell to a little more robust, especially in wireless setups is important. There's a bunch of security work going on. And Justin demoed NERVS Reactor, which is a way of doing live code reloading for development. And I wanna give a big thanks to Frank Heinlitz who happens to be in the room who started NERVS project and is responsible for all the really hard parts of it. And Justin Schnek who's been doing a lot to improve the tool chain and give speeches. And Greg Mefford who's been involved. And I'm not gonna be able to thank everyone who's been involved, but there's a lot of people who are starting to contribute to this project and it's really cool to see it go. And thank you guys all. This is what I demoed. And I guess if you wanna get further resources NERVS project.org is the best place to go because you can get everywhere else from there. And join us on Elixir Slack. So I'll be around later if there are questions. All right.