Geovane Fedrecheski


geonnave@


IoT

Nerves

-
IoT ?
-
Quick Demo
-
Nerves
-
Explained Demo


IoT?
The Internet

The Internet of Things

Demo
mix firmware
mix firmware.burndefmodule HelloGpio.Blinky do
use GenServer
require Logger
@ledpin 26
def start_link do
GenServer.start_link __MODULE__, [], name: __MODULE__
end
def toggle, do: GenServer.cast(__MODULE__, :toggle)
def init(_) do
Logger.debug "Initializing.."
{:ok, pin} = Gpio.start_link(@ledpin, :output)
Gpio.write(pin, 1)
{:ok, {pin, 1}}
end
def handle_cast(:toggle, {pin, pin_state}) do
new_pin_state = if pin_state == 0, do: 1, else: 0
Gpio.write(pin, new_pin_state)
{:noreply, {pin, new_pin_state}}
end
endIoT =~
Embedded webservices


O Elixir da IoT



Raspberry Pi
Beaglebone Black

defmodule HelloGpio.Blinky do
use GenServer
require Logger
@ledpin 26
def start_link do
GenServer.start_link __MODULE__, [], name: __MODULE__
end
def toggle, do: GenServer.cast(__MODULE__, :toggle)
def init(_) do
{:ok, pin} = Gpio.start_link(@ledpin, :output)
Gpio.write(pin, 1)
{:ok, {pin, 1}}
end
def handle_cast(:toggle, {pin, pin_state}) do
new_pin_state = if pin_state == 0, do: 1, else: 0
Gpio.write(pin, new_pin_state)
{:noreply, {pin, new_pin_state}}
end
end


wget 'http://director.downloads.raspberrypi.org/
raspbian_lite/images/raspbian_lite-2016-09-28/
2016-09-23-raspbian-jessie-lite.zip'
unzip 2016-09-23-raspbian-jessie-lite.zip


sudo dd \
if=2016-09-23-raspbian-jessie-lite.img \
of=/dev/sdc


sudo vi /etc/apt/sources.list
# deb http://packages.erlang-solutions.com/debian wheezy contrib
wget http://packages.erlang-solutions.com/debian/erlang_solutions.asc
sudo apt-key add erlang_solutions.asc
sudo apt-get update
sudo apt-get install git erlang
git clone https://github.com/elixir-lang/elixir.git
cd elixir
git checkout tags/v1.3.4
make clean test
# waaaaaaaaaaaaaait a LOT (aprox. 1h)
export PATH="$PATH:/path/to/elixir/bin"

SSH
defmodule Broker.AccessControl do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
def authorize(request) do
GenServer.call __MODULE__, {:authorize, request}
end
def handle_call({:authorize, request}, _from, _current) do
ans = Broker.AccessControl.PDP.authorize(request)
{:reply, ans, ans}
end
endCompile on board takes time...
host$ ssh pi@192.168.0.1
pi$ mix nerves.new hello_nerves --target rpi
pi$ cd hello_nerves
pi$ mix deps.get
pi$ mix compile
# takes TIME...
pi$ iex -S mix
But..
-
Repeat the process for each board?
-
Maybe write a script
-
-
Configuration/Compilation Takes time..
-
What if want to use another board? (will need a different setup)






Nerves
Craft and deploy bulletproof embedded software in Elixir



Based on
Buildroot is a simple, efficient and easy-to-use tool to generate embedded Linux systems through cross-compilation.
Code
Package
Run
Prepare


VM
ARM
Toolchain

=
+
+
|>





{
,

}

=
Nerves
(installation)

(have Erlang & Elixir on host)
sudo apt-get install ssh-askpass
sudo apt-get install squashfs-tools
wget 'https://github.com/fhunleth/fwup/releases/
download/v0.9.2/fwup_0.9.2_amd64.deb'
sudo dpkg -i fwup_0.9.2_amd64.deb
mix archive.install 'https://github.com/nerves-project/
archives/raw/master/nerves_bootstrap.ez'
Code
Package
Run
Prepare
mix nerves.new hello_nerves --target rpi3 cd hello_nerves mix deps.get mix compile
(write your project in Elixir)
mix firmware mix firmware.burn
NERVES_TARGET=bbb mix compile



How does it compare?




Image sizes

Nerves

Raspbian
~300MB
~20MB
Boot time

Nerves

Raspbian
~30 sec.
~6 sec.
Multiple Boards

Nerves

Raspbian


All drivers included

Nerves

Raspbian


How about other frameworks?

?

The VM
Concurreny
Fault tolerance
Data structures
Consistent libs
Modern tooling




+
Small images
Multiple boards
Quick iteration

Cases




Demo
(explained)



HTTP
WiFi
GPIO

mix new hello_nerves --umbrella
cd sample/apps
mix nerves.new fw --target rpi3
mix phoenix.new ui --no-ecto --no-brunch
mix new hello_gpio --sup
cd fw
mix deps.get
mix compile├── apps
│ ├── fw
│ ├── hello_gpio
│ └── ui
├── config
│ └── config.exs
├── mix.exs
├── mix.lock
└── README.mdPrepare
Code
apps/hello_gpio
├── config/
├── lib
│ ├── hello_gpio.ex
│ └── blinky.ex
├── mix.exs
├── README.md
└── test/# mix.exs
defp deps do
[{:elixir_ale, "~> 0.5.5"}]
end# lib/blinky.ex
defmodule HelloGpio.Blinky do
use GenServer
require Logger
@ledpin 26
def start_link do
GenServer.start_link __MODULE__, [], name: __MODULE__
end
def toggle, do: GenServer.cast(__MODULE__, :toggle)
def init(_) do
{:ok, pin} = Gpio.start_link(@ledpin, :output)
Gpio.write(pin, 1)
{:ok, {pin, 1}}
end
def handle_cast(:toggle, {pin, pin_state}) do
new_pin_state = if pin_state == 0, do: 1, else: 0
Gpio.write(pin, new_pin_state)
{:noreply, {pin, new_pin_state}}
end
endapps/ui
├── config/
├── lib/
├── mix.exs
├── priv/
├── README.md
├── test/
└── web
├── channels/
├── controllers
│ └── page_controller.ex
├── gettext.ex
├── router.ex
├── templates/
├── views/
└── web.ex# web/controllers/page_controller.ex
defmodule Ui.PageController do
use Ui.Web, :controller
require Logger
def index(conn, _params) do
render conn, "index.html"
end
def update(conn, _params) do
Logger.debug "Will toggle LED!"
HelloGpio.Blinky.toggle
render conn, "index.html"
end
end# web/router.ex
scope "/", Ui do
pipe_through :browser
get "/", PageController, :index
put "/", PageController, :update
endapps/fw
├── config
│ └── config.exs
├── lib
│ └── fw.ex
├── mix.exs
├── README.md
└── test/mix deps.get
mix compile# mix.exs
def deps do
[
{:hello_gpio, in_umbrella: true},
{:ui, in_umbrella: true},
{:nerves_interim_wifi, "~> 0.1.0"},
{:nerves_firmware_http,
github: "nerves-project/nerves_firmware_http"},
{:nerves, "~> 0.3.0"}
]
end# lib/fw.ex
Nerves.InterimWiFi.setup "wlan0",
ssid: "eu sei oqvc fez no verao passado",
key_mgmt: :"WPA-PSK",
psk: "3neeszombees"Package
mix firmware
mix firmware.burnapps/fw
├── config
│ └── config.exs
├── lib
│ └── fw.ex
├── mix.exs
├── README.md
└── test/$ ls -lah _images/rpi3/fw.fw
-rw-rw-r-- 21M _images/rpi3/fw.fwRun




FOTA (Firmware Over the Air) Upgrades!
$ http POST "192.168.0.121:8988/firmware" \
content-type:application/x-firmware \
x-reboot:true < firmware.fw


Run


# mix.exs
def deps do
[
{:hello_gpio, in_umbrella: true},
{:ui, in_umbrella: true},
{:nerves_interim_wifi, "~> 0.1.0"},
{:nerves_firmware_http,
github: "nerves-project/nerves_firmware_http"},
{:nerves, "~> 0.3.0"}
]
endRemote Debugging
├── apps
│ ├── fw
│ │ ├── _build
│ │ ├── config
│ │ ├── deps
│ │ ├── _images
│ │ ├── lib
│ │ ├── mix.exs
│ │ ├── mix.lock
│ │ ├── README.md
│ │ ├── rel
│ │ └── test# rel/vm.args
-name raspi@192.168.0.7
-setcookie secretiex --name host1@192.168.0.6 \
--remsh raspi@192.168.0.7 \
--cookie secretRemote Debugging
remsh
Remote Debugging
iex --name host1@192.168.0.6 \
--cookie secret:observer
iex(host2@192.168.0.6)> :observer.startNodes
-> Connect node
-> input "raspi@192.168.0.7"
For more Information

Obrigado


geonnave@
Elixir of IoT with Nerves
By Geovane Fedrecheski
Elixir of IoT with Nerves
- 1,585