DEV Community

loading...

Elixir "poncho" project with Nerves firmware and Phoenix LiveView UI

Masatoshi Nishiguchi
コンニチハニシグチマサトシデスヨロシクオネガイイタシマス
Updated on ・3 min read

Today I learned how to make a poncho project with the Nerves firmware and Phoenix LiveView UI and how it generally works.

My dev environment

MacOS BigSur 11.4
MacBook Pro (13-inch, 2018, Four Thunderbolt 3 Ports)

erlang 23.3.1
elixir 1.12.0-otp-23
node 12.13.0

export MIX_TARGET=rpi0
Enter fullscreen mode Exit fullscreen mode

How-to (A)

The easiest way to do it is just clone the Nerves Project's official example hello_phoenix. The Nerves core team and the community keep the example up-to-date. It should just work.

Clone the example project

cd some/location
git clone git@github.com:nerves-project/nerves_examples.git
cd nerves_examples/hello_phoenix
Enter fullscreen mode Exit fullscreen mode

then follow the instructions in the README.

How-to (B)

I was curious how I could create something similar from scratch so I did. Here is my secret recipe I ended up with.

Create a base project

cd some/location

# Decide on the project name
MY_PROJECT_NAME=hello_poncho

# Create the project directory and move into it
mkdir $MY_PROJECT_NAME && cd $MY_PROJECT_NAME

# Create README.md
echo "Copied from https://github.com/nerves-project/nerves_examples/tree/main/hello_phoenix\n\n$(curl -L https://raw.githubusercontent.com/nerves-project/nerves_examples/main/hello_phoenix/README.md)" > README.md

# Initialize Git
git init && git add . && git commit -m "Initial commit"

# Create Nerves firmware subproject
mix archive.install hex nerves_bootstrap
mix nerves.new "$MY_PROJECT_NAME"_firmware
git add . && git commit -m "Create Nerves firmware subproject"

# Create Phoenix LiveView UI subproject
mix archive.install hex phx_new
mix phx.new "$MY_PROJECT_NAME"_ui --no-ecto --live
git add . && git commit -m "Create Phoenix LiveView UI subproject"
Enter fullscreen mode Exit fullscreen mode

Add to the Firmware subproject the UI subproject as a dependency

# hello_poncho_firmware/mix.exs

{:hello_poncho_ui, path: "../hello_poncho_ui", targets: @all_targets, env: Mix.env()},
Enter fullscreen mode Exit fullscreen mode

Set up WiFi in the Firmware subproject

# hello_poncho_firmware/config/target.exs

{"wlan0",
  %{
    type: VintageNetWiFi,
    vintage_net_wifi: %{
      networks: [
        %{
          key_mgmt: :wpa_psk,
          ssid: System.get_env("WIFI_SSID"),
          psk: System.get_env("WIFI_PSK")
        }
      ]
    },
    ipv4: %{method: :dhcp}
  }}
Enter fullscreen mode Exit fullscreen mode

Configure web server in the Firmware subproject

According to the Nerves official User Interfaces documentation:

If we're using a poncho project structure, we'll need to keep in mind that
the my_app_ui configuration won't be applied automatically, so we should
either import it from there or duplicate the required configuration.

# hello_poncho_firmware/config/target.exs

# Import default UI config based on MIX_ENV
import_config "../../hello_poncho_ui/config/config.exs"

# Override some UI config for firmware
config :hello_poncho_ui, HelloPonchoUiWeb.Endpoint,
  # Nerves root filesystem is read-only, so disable the code reloader
  code_reloader: false,
  # Use compile-time Mix config instead of runtime environment variables
  load_from_system_env: false,
  # Start the server since we're running in a release instead of through `mix`
  server: true,
  # "<firmware's hostname>.local"
  url: [host: "nerves.local"],
  http: [port: 80],
  check_origin: false,
  root: Path.dirname(__DIR__)
Enter fullscreen mode Exit fullscreen mode

Build the firmware and burn (or upload) it

Follow the instructions in Nerves official Hello Phoenix example.

Specify MIX_ENV=prod so that we can build the production UI.

MIX_ENV=prod mix firmware
Enter fullscreen mode Exit fullscreen mode

Verify the UI config is loaded correctly

Application.get_env :hello_poncho_ui, HelloPonchoUiWeb.Endpoint
Enter fullscreen mode Exit fullscreen mode

Visit http://nerves.local or your specified host or IP.

Folder names

The folder names can be verbose if a project name is prepended. I once considered to shorten them somehow, but I decided not to because it is nice to be obvious about what exactly they are.

.
├── README.md
├── hello_poncho_firmware
└── hello_poncho_ui
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

At first, the poncho project looked scary to me, but it is actually pretty simple concept. The Nerves firmware combined with the Phoenix LiveView seems so powerful that I may consider using this pattern for my other Nerves projects. Now that I know how to make a poncho project, it is time to make some UI for my devices.

That's it! Here are some resources I read and found helpful.

Resources

Troubleshooting

  • Sometimes I have an issue resolving dependencies for some reason, then I run mix deps.clean --all.

Discussion (0)