Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Nerves + Phoenix Saves a Father's Sanity!

804c822d96e32515c3ae7eaa52e42490?s=47 Joel Byler
September 06, 2016

Nerves + Phoenix Saves a Father's Sanity!

Recently I've been able to encourage my children to do their chores and not fight about it. Its been made possible with the help of Elixir and an Umbrella project which combines the use of Phoenix and Nerves (and some prototyping hardware) to build a chore system which rewards each kid with their own internet access after they've done their work for the day. It also makes it really easy to revoke access when they misbehave. In this talk I'll take you with me back through the journey, and I'll talk about why it was needed, what I learned, and how the the final outcome has saved my sanity.


Joel Byler

September 06, 2016


  1. Nerves + Phoenix Saves a Father's Sanity! Joel Byler -

    @joelbyler JJ
  2. http://i1.kym-cdn.com/photos/images/facebook/000/234/739/fa5.jpg Full Disclosure • Inspired by Paul Wilson at ElixirConfEU

    • I started this project as an excuse to learn elixir • I’m still learning
  3. I work at CoverMyMeds! • Helping patients get the medications

    they need be healthy • Consistently rated best place to work in central Ohio • Mostly Ruby / Rails but exploring Elixir / Phoenix • Columbus, Cleveland, and Remote
  4. I Have an Amazing Family!

  5. We LOVE Tech!

  6. http://www.indystar.com/story/opinion/cartoons/2015/04/13/cartoonist-gary-varvel-children-playing-mobile-devices/25702733/

  7. http://runitlikeamom.com/wp-content/uploads/2015/02/Messy-playroom.jpg

  8. https://www.thesun.co.uk/wp-content/uploads/2016/08/nintchdbpict000257743056.jpg

  9. But, that means… - The password needs to be changed

    EVERY DAY - There’s only one password, and I have more than one child. - I have lots of other stuff on wifi, like MY phone and laptop - Also, my wife has her stuff, she’s not into this idea at all.
  10. Idea I can build a website! - The website can

    have the kids login and confirm that their chores are done - It will be like Starbucks or McDonalds - After the chores are done, then I can give them access to the internet - Its called a captive portal!
  11. Idea I’ve heard of a Raspberry Pi used as a

    wireless AP • Raspberry Pi 3 has a built in wifi adapter! I just heard about this new Elixir framework, Nerves • Lets you build your own embedded system with elixir • Works on Raspberry Pi and many others • Looks like it makes that really easy! I can build the website in Phoenix!
  12. Warning Captive portals can be used for bad things! https://cdn.meme.am/instances/500x/71390124.jpg

  13. Why is a Web UI Important? - users need a

    way to interact with IoT projects - easy to build an intuitive user interface - better than blinking light codes and buttons - users typically will have a cell phone or laptop nearby anyway
  14. My Desired Approach - I want to learn Elixir! -

    Phoenix: able to perform well on less hardware - Nerves - include additional elixir apps using umbrella - uses buildroot to specify linux dependencies - start phoenix automatically on boot - easily package entire project into a micro SD image
  15. http://meowgifs.com/wp-content/uploads/2014/03/segway-kitten.gif

  16. What’s in the Umbrella? firmware - initializes router user_interface -

    captive portal + admin functions captive_portal_redirector - 302 redirect to captive portal router_controls - wraps system calls chore_repository - data repository Separated Concerns:
  17. What’s in the Umbrella? def application do [ mod: {Firmware,

    []}, applications: [ :captive_portal_login_redirector, :router_controls, :user_interface]] end def deps do [ {:captive_portal_login_redirector, in_umbrella: true}, {:router_controls, in_umbrella: true}, {:user_interface, in_umbrella: true}] end
  18. Custom System The nerves project supports a wide array of

    targets already
  19. Linux Deps - dnsmasq: dns and dhcp - hostapd: wifi

    access point - iptables: firewall - netfilter: filter traffic - arp: identify devices (address resolution) * these dependencies are not included in standard Nerves systems
  20. Custom System - clone repo for system git clone git@github.com:nerves-project/…

    - customize with buildroot make menuconfig - build make system - reference from nerves application NERVES_SYSTEM=/path/to/build/directory
  21. Buildroot `menuconfig` - native libraries and applications dnsmasq, hostapd `linux-menuconfig`

    - linux kernel drivers iptables, netfilter `busybox-menuconfig` - simple command line utilities vim, grep, etc. more details available at:
  22. Buildroot Looks like this HINT: search with forward slash, /

  23. Minimal DNSMAQ Config # /etc/dnsmasq.conf bogus-priv server=/localnet/ local=/localnet/ interface=wlan0 domain=localnet

    dhcp-range=,,2h # 3 - router, 6 - dns-server dhcp-option=3, dhcp-option=6, dhcp-authoritative typically at /etc/dnsmasq.conf
  24. Minimal HOSTAPD Config interface=wlan0 ssid=CHORES_NET hw_mode=g channel=6 auth_algs=1 wmm_enabled=0 typically

    at /etc/hostapd/hostapd.conf
  25. rootfs-additions # firmware/config/config.exs config :nerves, :firmware, rootfs_additions: "config/rootfs-additions" firmware/config !""

    config.exs #"" rootfs-additions #"" etc !"" dnsmasq.conf !"" hostapd $ #"" hostapd.conf #"" erlinit.config
  26. A few iptables commands # new chain called internet iptables

    -t mangle -N internet # attach tcp traffic on wlan0 to internet target iptables -t mangle -A PREROUTING -i wlan0 -p tcp -m tcp -j internet # mark new connections iptables -t mangle -A internet -j MARK --set-mark 99 # forward marked connections iptables -t nat -A PREROUTING -i wlan0 -p tcp -m mark --mark 99 -m tcp \ --dport 80 -j DNAT --to-destination
  27. User Interface --no-ecto - Starts automatically because its a dependency

    of the firmware (nerves) application - Single controller - Only two actions, two templates - Get next (or first) chore, next, next, done. - KEEP IT SIMPLE! A fairly simple Phoenix app
  28. Persistence tried but didn’t feel like a great fit -

    Ecto - Erlang Term Storage (ETS) - Amnesia / Mnesia this worked well - cellulose/persistent_storage I don’t want to hard code those chores Remember one of the apps from earlier? :chore_repository
  29. Persistence alias PersistentStorage def repository_file do, Application.get_env(:chore_repository, :config)[:file] end def

    setup do PersistentStorage.setup path: repository_file end def insert(chore_step, name, description, required) do PersistentStorage.put(chore_step, %{ name: name, description: description, required: required }) end def next_chore(chore_step) do chore_step + 1 |> PersistentStorage.get |> map_to_chore end
  30. Testing! Because of the numerous linux dependencies, this app uses

    lots of OS commands. System.cmd("arp", ["-a", ""]) Not easy to put the OS in a state in which tests will pass for this sort of code. So how do we fix this?
  31. Testing!

  32. Testing! Don’t mock as a verb, mock as a noun

    defmodule Router.OsCommand do @system Application.get_env(:router, :system_client) def os_cmd(command, arguments) do @system.cmd(command, arguments) end end # router/config/test.exs config :router, system_client: Router.Fakes.System # router/config/prod.exs config :router, system_client: System
  33. Testing! defmodule Router.Fakes.System do def cmd("arp", ["-a", ""]) do {“blah

    blah ( at ab:cd:ef:ab:cd:ef yada.yada", 0} end end defmodule Router.AddressResolution do import Router.OsCommand @doc """ Returns arp result or a default one as a fallback ## Examples iex> AddressResolution.fetch_arp "" {blah blah ( at ab:cd:ef:ab:cd:ef yada.yada, 0} """ def fetch_arp(ip) do os_cmd("arp", ["-a", ip]) end end
  34. http://meowgifs.com/wp-content/uploads/2014/03/segway-kitten.gif

  35. Demo! looking for some volunteers

  36. http://hyperboleandahalf.blogspot.com/2010/06/this-is-why-ill-never-be-adult.html

  37. http://www.indystar.com/story/opinion/cartoons/2015/04/13/cartoonist-gary-varvel-children-playing-mobile-devices/25702733/

  38. http://hyperboleandahalf.blogspot.com/2010/06/this-is-why-ill-never-be-adult.html

  39. Change of Plans - Chores are good, keep them -

    Whats missing? - Fun activities! - Get outside and get some fresh air - Exercise, its good for you - Interact with others (games, conversation, high fives!) - Let someone else know you care about them - These are things that I need to do myself!
  40. http://innovplay.com/img/kids_running.jpg

  41. Closing Statements • Hacking on side projects is a fun

    way to learn something new • You should try it! • Share the fun, others love to learn this stuff too! • Include your friends and family • Don’t be upset if the project takes a different turn iex> Elixir |> Nerves |> Phoenix {:success, “wonderful”}
  42. Special Thanks Justin Schneck Frank Hunleth Greg Mefford Garth Hitchens

    Chris Dutton Keyvan Fatehi @pressy4pie @requisite0 Nerves Core Team #nerves on slack @jarel @ssachse My Family CoverMyMeds
  43. THANK YOU! SDG https://github.com/joelbyler/elixir_conf_chores https://github.com/joelbyler/nerves_system_rpi3_ap Joel Byler @joelbyler