LoginSignup
10
1

NervesとPhoenixでPonchoしたい

Last updated at Posted at 2021-12-23

NervesのファームウエアにPoncho projectsと呼ばれる手法を用いてPhoenixのUIを搭載したいと思います。

Poncho projectsとは

Ponchoプロジェクトのファイル構成は以下のようになります。

hello_poncho
├── README.md
├── hello_poncho_firmware
└── hello_poncho_ui

Elixir界隈ではPoncho projectsに似たようなものでUmbrella projectsがありますが、NervesではPoncho projectsが一般的には好まれるようです。理由は、Nervesではファームウエアが特別な存在だからと理解してます。
Umbrella projectsではすべての下位プロジェクトを同等に扱われます。
しかしながら、ファームウエアは他のElixirプロジェクトと異なり、ビルドツールであるため、ファームウエアをメインとして特別視した方が分かりやすいということだと思います。

ディレクトリー名は短くしてもよいのですが、個人的には後々の保全性を考えてあえて冗長なディレクトリー名を使うのが好みです。

MacOS BigSur 11.6

elixir          1.12.3-otp-24
erlang          24.1

nerves          1.7.11
phoenix         1.6.2

やりかた (A): hello_phoenix exampleをクローン

一番手軽なやり方は、Nerves公式のhello_phoenix exampleをクローンすることです。Nervesコアチームとコミュニティーにより定期的にアップデートされています。
万一なにか問題がみつかった場合は、プルリクエストで貢献する良い機会となると思います。

nerves_examplesをクローンして、hello_phoenix READMEの指示に従います。

git clone git@github.com:nerves-project/nerves_examples.git
cd nerves_examples/hello_phoenix

やりかた (B): From scratch

いちからhello_phoenix同様のものを作るのはそんなにむずかしいことではありません。

Nervesプロジェクトを作る

# プロジェクト名を決める
MY_PROJECT_NAME=hello_poncho

# プロジェクトのディレクトリーを作成して、その中に移動
mkdir $MY_PROJECT_NAME && cd $MY_PROJECT_NAME

# Nervesファームウエアのプロジェクトを新規作成
mix archive.install hex nerves_bootstrap
mix nerves.new "$MY_PROJECT_NAME"_firmware

# Phoenix UIのプロジェクトを新規作成
mix archive.install hex phx_new
mix phx.new "$MY_PROJECT_NAME"_ui --no-ecto --no-mailer

UIプロジェクトの設定

ひとつ大事なことは、Nervesでは開発環境でファームウエアをビルド・デプロイすることも多いと思いますので、(Phoenix 1.6から導入された)esbuildの設定に工夫が必要です。
ホストマシン(開発マシン)以外ではesbuildのランタイムが不要です。

hello_poncho/hello_poncho_ui/mix.exs
  defp deps do
    [
      {:phoenix, "~> 1.6.0"},
      # ...
      {:esbuild, "~> 0.2", runtime: Mix.env() == :dev && Mix.target() == :host},
      # ...
    ]
  end

参考までに、ターゲットマシン(ラズパイ等)でesbuildのランタイムが走るとこんな感じにファームウエアがクラッシュします。

UIプロジェクトをファームウエアプロジェクトの依存関係リストに追加

hello_poncho/hello_poncho_firmware/mix.exs
  defp deps do
    [
      {:nerves, "~> 1.7", runtime: false},
      # ...
      {:hello_poncho_ui, path: "../hello_poncho_ui", targets: @all_targets, env: Mix.env()},
      # ...
    ]
  end

ファームウエアプロジェクトにてウエブサーバー関連の設定

一つ注意点は、UIプロジェクトに設定を記述してもそれはファームウエアのビルド時には読み込まれないことです。
ですので、UIの設定もファームウエア側に記述する必要があります。UIプロジェクトからimportする手もありますが、個人的には必要な設定はすべてファームウエア側に記述する手法が気に入ってます。

hello_poncho/hello_poncho_firmware/config/target.exs
# as of phoenix 1.6.2
config :hello_poncho_ui, MyAppUiWeb.Endpoint,
  url: [host: "nerves.local"],
  http: [port: 80],
  cache_static_manifest: "priv/static/cache_manifest.json",
  secret_key_base: "HEY05EB1dFVSu6KykKHuS4rQPQzSHv4F7mGVB/gnDLrIu75wE/ytBXy2TaL3A6RA",
  live_view: [signing_salt: "AAAABjEyERMkxgDh"],
  check_origin: false,
  render_errors: [view: MyAppUiWeb.ErrorView, accepts: ~w(html json), layout: false],
  pubsub_server: Ui.PubSub,
  # Start the server since we're running in a release instead of through `mix`
  server: true,
  # Nerves root filesystem is read-only, so disable the code reloader
  code_reloader: false

# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason

WiFiの設定 (任意)

USBガジェットモードを利用して、USB経由で通信する場合は不要です。

hello_poncho/hello_poncho_firmware/config/target.exs
config :vintage_net,
  regulatory_domain: "US",
  config: [
    {"usb0", %{type: VintageNetDirect}},
    {"eth0",
     %{
       type: VintageNetEthernet,
       ipv4: %{method: :dhcp}
     }},
    {"wlan0",
     %{
       type: VintageNetWiFi,
       vintage_net_wifi: %{
         networks: [
           %{
             key_mgmt: :wpa_psk,
             # 環境変数経由で渡すか、直書きするかご自由に
             ssid: System.get_env("NERVES_WIFI_SSID"),
             psk: System.get_env("NERVES_WIFI_PSK")
           }
         ]
       },
       ipv4: %{method: :dhcp}
     }}
  ]

UIの開発

UIの開発に取り組むときは、hello_poncho/hello_poncho_uiディレクトリーに移動して、Phoenixのサーバーを起動します。

cd hello_poncho/hello_poncho_ui

iex -S mix phx.server

ファームウエアのビルド

まずはhello_poncho/hello_poncho_uiディレクトリーにてUIのアセットをビルドします。

cd hello_poncho/hello_poncho_ui

export MIX_TARGET=host
export MIX_ENV=dev

mix deps.get

# アセットをビルド
mix assets.deploy

そして hello_poncho/hello_poncho_firmwareディレクトリーにてファームウエアをビルドします。

cd hello_poncho/hello_poncho_firmware

export MIX_TARGET=rpi0
export MIX_ENV=dev

mix deps.get

# ファームウエアをビルド
mix firmware

# ファームウエアをMicroSDカードに焼き上げる
mix firmware.burn

焼き上がったMicroSDカードをターゲットマシンに挿入し、電源オン。

以下のURLでPhoenixアプリにアクセスできるはずです。
http://nerves.local

以降、ファームウエアはネットワーク経由でもアップデート可能です。

mix firmware

mix upload nerves.local

:tada::tada::tada:

資料

10
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
1