I want to enable my Nerves devices to talk to each other using Distributed Erlang. Here is my memo.
If you are not familiar with Nerves, this conference talk by a Nerves co-author Frank Hunleth will introduce it to you.
Find hostname or IP address for each device
Normally when shelling into a Nerves device, we will see IP address and host name printed by nerves_motd.
DNS Bridge configuration
According to mdns_lite - DNS Bridge configuration documentation, we need to let Erlang/OTP's built-in DNS resolver know about mDNS. Underjord's YouTube video explaining DNS Bridge configuration was helpful.
Start Erlang nodes
- nerves_pack - Erlang distribution documentation explains about how to form an Erlang cluster.
- Let's say we have a device with host name
nerves-mn00.localand anoter with host name
- Alternatively IP addresses can be used instead of host names
- Make sure that the same Erlang magic cookie is used
❯ ssh nerves-mn00.local # make sure the epmd OS process is running by calling epmd -daemon iex> System.cmd("epmd", ["-daemon"]) # start a node. iex> Node.start(:"firstname.lastname@example.org") # check current node. `node/0` does the same. iex(email@example.com)> Node.self() # configure the magic cookie to form this cluster. iex(firstname.lastname@example.org)> Node.set_cookie(:securecookie)
❯ ssh nerves-mn02.local iex> System.cmd("epmd", ["-daemon"]) iex> Node.start(:"email@example.com") iex(firstname.lastname@example.org)> Node.set_cookie(:securecookie)
Connect a node to another
- Let's connect
iex(email@example.com)> Node.connect(:"firstname.lastname@example.org") true iex(email@example.com)> Node.list() [:"firstname.lastname@example.org"]
Invoke a function in another node
nerves-mn02.localinvoke a function that is defined in
Node.spawn/2or something similar
- Let's access to the other device and peek into its firmware infomation by invoking
Toolshed.Nerves.uname/0that is normally available in our Nerves IEx shell.
Node.spawn( # the node name we want to invoke a function in :"email@example.com", # the function we want to invoke fn -> Toolshed.Nerves.uname() end )
iex(firstname.lastname@example.org)> Node.spawn(:"email@example.com", fn -> Toolshed.Nerves.uname() end) Nerves nerves-mn00 hello_nerves 0.1.0 (240d82e1-1e6c-5800-0ef9-63cba9efc212) arm #PID<51667.6840.0>
Yay, we were able to at least do something in another device through the Distributed Erlang. Isn't it cool?
I put together what I learned as
kantan_cluster Elixir package. It allows us to form an Erlang cluster automatically. Please take a look if you like.
Top comments (0)