Talking to your GRiSP board

Connecting over WiFi

Updated 25 July 2018
will use the project created in Creating Your First GRiSP Application as a base for this tutorial.

Configuration#

Rebar#

First, we need to add the native Erlang implementation of Erlang Port Mapping Daemon (EPMD) as a dependency to our project. This is because the EPMD that ships with Erlang by default is running as a separate process, which is not possible on the GRiSP board since we are running Erlang as the kernel itself.

Update rebar.config and add the Erlang implementation of EPMD as a dependency to you GRiSP project. Change the following line:

{deps, [grisp]}.

To this:

{deps, [
    grisp,
    {epmd, {git, "https://github.com/erlang/epmd", {ref, "4d1a59"}}}
]}.

You also need to include the EPMD application into the release further down in rebar.config. Change the following lines:

{relx, [
    {release, {my_project, "0.1.0"}, [my_project]}
]}.

To this:

{relx, [
    {release, {my_project, "0.1.0"}, [{epmd, none}, my_project]}
]}.

The reason we are using {epmd, none} instead of just epmd is because net_kernel inside the Erlang VM will take care of starting EPMD internally.

Erlang Inet#

Next, we need to add the necessary overlay files to the grisp folder in the project so that they are copied to the SD-card. We need to add an erl_inetrc file to override Erlang's Inet settings. Any file inside $PROJECT/grisp/<platform>/files will get copied onto the SD-card when deploying the project (where <platform> corresponds to the target GRiSP hardware platform, which for this tutorial is grisp_base). Any file in the files folder ending in .mustache will also be used as a template for the file named without that ending (e.g. the custom grisp.ini that we use below).

First create the directory structure in the root of your project:

$ mkdir -p grisp/grisp_base/files

Create a new file at grisp/grisp_base/files/erl_inetrc with the contents:

%--- Erlang Inet Configuration -------------------------------------------------

% Add hosts
{host, {X,X,X,X}, ["Host"]}.

% Do not monitor the hosts file
{hosts_file, ""}.

% Disable caching
{cache_size, 0}.

% Specify lookup method
{lookup, [file, native]}.

where {X,X,X,X} is replaced with the IP-number of your development host that you want to connect from (e.g. {192,168,1,103}) and "Host" is replaced with the hostname of that machine (e.g. "MyLaptop").

GRiSP INI#

We also need to override the default grisp.ini file to start Erlang correctly with the right parameters. Create the file grisp/grisp_base/files/grisp.ini.mustache with the following contents:

[boot]
image_path = /media/mmcsd-0-0/{{release_name}}/erts-{{erts_vsn}}/bin/beam.bin

[erlang]
args = erl.rtems -- -home . -pa . -root {{release_name}} -boot {{release_name}}/releases/{{release_version}}/{{release_name}} -internal_epmd epmd_sup -kernel inetrc "./erl_inetrc" -sname {{release_name}} -setcookie MyCookie

[network]
ip_self = dhcp
wlan = enable
hostname = my_grisp_board

Replace MyCookie with a cookie that you want to use, and set a hostname under [network].

With that configuration the board will try to connect to the first open WiFi network it will find.

WPA#

If you want to connect to an encrypted network add the following line to the [network] section:

wpa = wpa_supplicant.conf

Then add the file grisp/grisp_base/files/wpa_supplicant.conf with the following contents:

network={
    ssid="mynetwork"
    key_mgmt=WPA-PSK
    psk="secret"
}

ssid should contain the exact case sensitive name of the network you want to join and psk is the password. This configuration examples assumes a wireless network with WPA Personal security.

Deploy#

Deploy your release as usual:

$ rebar3 grisp deploy -n my_project -v 0.1.0

This should copy the new files to the SD-card, and include EPMD as a dependency in the release.

Connect#

There are two main ways to connect to the GRiSP node. The first is remote shell, where you get access to the shell running on the board itself. The second is to connect an external node, which is useful to reload code remotely on the GRiSP

Both methods requires a lookup of the GRiSP board hostname. The easiest way to achieve this is to add the GRiSP board to a new line in your /etc/hosts file:

X.X.X.X my_grisp_board

where X.X.X.X is the IP number your GRiSP board has on the wireless network. To be able to connect to it, you need to be able to reach this IP address.

Remote Shell#

To connect a remote shell, run the following command:

$ erl -sname my_remote_shell -remsh my_project@my_grisp_board -setcookie MyCookie

Connect External Node#

Connecting an external node can be done either via pure Erlang, or using Rebar.

Rebar#

Because we don't want to start the GRiSP runtime locally, we have to tell Rebar to not start any applications (by default, all applications included in the release gets started). Add the following to your rebar.config:

{shell, [{apps, []}]}.

To connect, start a shell and give it a node name and use the same cookie as above.

$ rebar3 as test shell --sname my_dev_node --setcookie MyCookie

Once the shell is connected, connect to the GRiSP node. When this is done, you can remotely load modules:

(my_dev_node@Host)1> net_adm:ping(my_project@my_grisp_board).
pong
(my_dev_node@Host)2> nodes().
[my_project@my_grisp_board]

TIP: Use r3:do(compile) in the Rebar shell to recompile and load your module locally, then use nl/1 to load it remotely. Example:

(my_dev_node@Host)3> r3:do(compile).
Verifying dependencies...
Compiling grisp
Compiling my_project
ok
(my_dev_node@Host)4> nl(my_module).
abcast

If you see pong when connecting and abcast when loading the module on the connected nodes, you should have successfully hot code loaded that module over Wi-Fi on the GRiSP board.

Pure Erlang#

If you want to use just Erlang to connect, use the following command:

$ erl -sname my_dev_node -setcookie MyCookie

And then connect to the node as you would in the Rebar shell:

(my_dev_node@Host)1> net_adm:ping(my_project@my_grisp_board).
pong
(my_dev_node@Host)2> nodes().
[my_project@my_grisp_board]