I want to enable my Nerves devices to talk to each other using Distributed Erlang. Here is my memo.
Preparation
About Nerves
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.local
and anoter with host namenerves-mn02.local
. - 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(:"nerves@nerves-mn00.local")
# check current node. `node/0` does the same.
iex(nerves@nerves-mn00.local)> Node.self()
# configure the magic cookie to form this cluster.
iex(nerves@nerves-mn00.local)> Node.set_cookie(:securecookie)
❯ ssh nerves-mn02.local
iex> System.cmd("epmd", ["-daemon"])
iex> Node.start(:"nerves@nerves-mn02.local")
iex(nerves@nerves-mn02.local)> Node.set_cookie(:securecookie)
Connect a node to another
- Let's connect
nerves-mn02.local
tonerves-mn00.local
iex(nerves@nerves-mn02.local)> Node.connect(:"nerves@nerves-mn00.local")
true
iex(nerves@nerves-mn02.local)> Node.list()
[:"nerves@nerves-mn00.local"]
Invoke a function in another node
- From
nerves-mn02.local
invoke a function that is defined innerves-mn00.local
usingNode.spawn/2
or something similar - Let's access to the other device and peek into its firmware infomation by invoking
Toolshed.Nerves.uname/0
that is normally available in our Nerves IEx shell.
Node.spawn(
# the node name we want to invoke a function in
:"nerves@nerves-mn00.local",
# the function we want to invoke
fn -> Toolshed.Nerves.uname() end
)
iex(nerves@nerves-mn02.local)> Node.spawn(:"nerves@nerves-mn00.local", 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)