Nerves＋Phoenix 002＋asdfでnodeをインストール

# はじめに
RaspberryPi上で動くNerves＋Phoenix環境の構築です。

前回[Nerves＋Phoenix 00１](https://qiita.com/32hero/items/51098e2995252cd2a8c5)

今回は、詰まりそうな環境構築からNervesで動作する場合の鍵の設定までを記載します。
前回のままでは動かないよって場合にご覧ください。


# 参考
[asdf-vm.com](https://asdf-vm.com/#/core-manage-asdf-vm?id=plugin-dependencies)
[github asdf-node.js](https://github.com/asdf-vm/asdf-nodejs)

[hexdocs.pm/phoenix](https://hexdocs.pm/phoenix/installation.html#content)
[github.com nerves-project #phoenix-web-interfaces]
(https://github.com/nerves-project/nerves/blob/master/docs/User%20Interfaces.md#phoenix-web-interfaces)

# 環境
- macOS
- IEx 1.9.1 (compiled with Erlang/OTP 22)
- nerves_bootstrap-1.7.1
- phoenix 1.4.16

# 目次
- asdfでnodeをインストール
- phoenixを最新化
- 下準備
- プロジェクトの作成
- プロジェクトの依存関係を整理
- ネットワーク（vintage_net）の設定
- 鍵を設定
- ローカルでPhoenix確認
- RaspberryPi3B＋Nerves＋Phoenixを確認
- まとめ

# asdfでnodeをインストール

```Elixir:
#お告げの通りにインストール
$ brew install \
  coreutils automake autoconf openssl \
  libyaml readline libxslt libtool unixodbc \
  unzip curl

$ brew install gpg

$ asdf plugin-add nodejs https://github.com/asdf-vm/asdf-nodejs.git

#ここでエラーになるかも
$ bash ~/.asdf/plugins/nodejs/bin/import-release-team-keyring

Authenticity of checksum file can not be assured! Please be sure to check the README of asdf-nodejs in case you did not yet import the needed PGP keys. If you already did that then that is the point to become SUSPICIOUS! There must be a reason why this is failing. If you are installing an older NodeJS version you might need to import OpenPGP keys of previous release managers. Exiting.

#エラーになったので「import-release-team-keyring」を修正
vi ~/.asdf/plugins/nodejs/bin/import-release-team-keyring

#コメントアウト
#SERVERS="ha.pool.sks-keyservers.net
#         p80.pool.sks-keyservers.net:80 \
#         ipv4.pool.sks-keyservers.net \
#         keyserver.ubuntu.com
#         keyserver.ubuntu.com:80 \
#         pgp.mit.edu
#         pgp.mit.edu:80"

#add
SERVERS="ipv4.pool.sks-keyservers.net \
         pgp.mit.edu"

#node.jsをインストール(ver.推奨版)
$ asdf install nodejs 12.16.1

#bash再実行
asdf global nodejs 12.16.1
```

# 下準備

phoenix、Nervesを最新化

```Elixir:
#phoenixを最新化
$ mix local.phx
phx_new 1.4.16

#phoenixのインストールからの方はこちら
$ mix archive.install hex phx_new 1.4.16

#nervesを最新に（bootstrapのバージョンが古いと怒られるので）
$ mix local.nerves
* creating **/.asdf/installs/elixir/1.9.1-otp-22/.mix/archives/nerves_bootstrap-1.7.1

# bootstrapのinstallが必要な場合は
mix archive.install hex nerves_bootstrap

```

# プロジェクトの作成

ディレクトリ構成は以下とします。
ExiNix
　├deviceio
　└phxif

```Elixir:
#親ディレクトリを作成
mkdir ExiNix
cd ExiNix

#RaspberryPi3をターゲット
set -x MIX_TARGET rpi3

#Nervesプロジェクトを作成
mix nerves.new deviceio  --nerves-pack

#phoenixプロジェクトを作成（--no-webpack オプションは付けない）
mix phx.new phxif --no-ecto

#とりあえずローカルで動くか確認
$ cd phxif
$ mix phx.server
```

ブラウザでlocalhost:4000にアクセス

![nerves.local_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295240/5320ecfd-20d6-1f86-2b14-e5c50948bbae.png)

# プロジェクトの依存関係を整理
今回はUsing a poncho project structureとします。

```Elixir:deviceio/mix.exs

# ...
  defp deps do
    [
      # Add
      {:phxif, path: "../phxif"},
      # ...
    ]
  end
# ・・・
```

```Elixir:deviceio/config/config.exs

# Add　以下を追記
import_config "../../phxif/config/config.exs"
import_config "../../phxif/config/prod.exs"

config :phxif, PhxifWeb.Endpoint,
  # Nerves root filesystem is read-only, so disable the code reloader
  code_reloader: false,
  http: [port: 80],
  # 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,
  url: [host: "nerves.local", port: 80]
```

#　ネットワーク（vintage_net）の設定

```Elixir:deviceio/config/target.exs

config :vintage_net,
　#JPに変更
  regulatory_domain: "JP",
  config: [
    {"usb0", %{type: VintageNetDirect}},
    {"eth0",
     %{
        type: VintageNetEthernet,
        ipv4: %{
          method: :static,
          address: "192.168.***.***",
          prefix_length: 24,
        }
      }
    },
    {"wlan0",
      %{
        type: VintageNetWiFi,
        vintage_net_wifi: %{networks: [%{key_mgmt: :wpa_psk, ssid: "SSIDを記載", psk: "パスワード"}]},
        ipv4: %{method: :dhcp}
      }
    }
  ]

```

#鍵を設定

CSRFトークンをインポート

```Elixir:phxif/lib/phxif_web.ex
#・・・
　# Add 「get_csrf_token: 0,」を追加
　import Phoenix.Controller, only: [get_csrf_token: 0,get_flash: 1, get_flash: 2, view_module: 1]

#・・・
```

鍵の生成と設定

```Elixir:

$ cd phxif
$ mix deps.get

#64byte以上じゃないと実行時にエラーになったので長さを指定しない。
$ mix phx.gen.secret
***秘密鍵***

```

```Elixir:phxif/config/prod.secret.exs
#・・・
#本番環境用の設定
#鍵を設定
secret_key_base = "***秘密鍵***"
  # System.get_env("SECRET_KEY_BASE") ||
  #   raise """
  #   environment variable SECRET_KEY_BASE is missing.
  #   You can generate one by calling: mix phx.gen.secret
  #   """
#・・・
```

```Elixir:phxif/config/config.exs
#・・・
#ローカル実行時の設定
# Configures the endpoint
config :phxif, PhxifWeb.Endpoint,
  url: [host: "localhost"],
　#鍵を設定
  secret_key_base: "***秘密鍵***",
  render_errors: [view: PhxifWeb.ErrorView, accepts: ~w(html json)],
  pubsub: [name: Phxif.PubSub, adapter: Phoenix.PubSub.PG2],
  live_view: [signing_salt: "g5JOni5o"]
#・・・
```
メモ：phxif/config/prod.exs　は　deviceio/config/config.exsでオーバーライドされるので変更不要。


# ローカルでPhoenix確認

```Elixir:
$ cd phxif
$ mix phx.server

```

ブラウザでlocalhost:4000にアクセス

![nerves.local_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295240/5320ecfd-20d6-1f86-2b14-e5c50948bbae.png)

# RaspberryPi3B＋Nerves＋Phoenixを確認
```Elixir:
$ cd deviceio
$ mix.deps.get
$ mix.firmware
$ mix.firmware.burn
```

ブラウザでnerves.local（設定した固定IP）にアクセス

![nerves.local_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295240/5320ecfd-20d6-1f86-2b14-e5c50948bbae.png)

#まとめ
・Nerves上でPhoenixを動かすミニマム構成

・プロジェクトの構成はponchoにしておくと、Phoenixの独立性が高くて開発しやすい。

・postもcsrfを防いだ形で簡単に実装(できるはず)

```html:
<%# <form method="POST" action="/abc/hoge"> %>
```

・開発時にサクッと反映するためにupload.shを作っておく。

```Elixir:
# upload.shを作っておく
$ mix firmware.gen.script

#変更をネットワーク越しに反映
$ ./upload.sh 192.168.***.***
```

・次はデバイス側のIOをPhoenixで表示