9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

#NervesJPAdvent Calendar 2023

Day 12

Elixir Nerves で 無線LAN (Wi-Fi)を設定する

Last updated at Posted at 2023-11-06

はじめに

Nerves 対象デバイスRaspberry PiBeaglebone等)で DHCP を設定して無線LAN (Wi-Fi) でインターネット接続する方法をまとめます。

やりかた

やり方はいくつかあります。

  • コンパイル時
    • ネットワーク設定をファームウエアと一緒に microSD カードに焼く
  • 実行時
    • 対象 Nervesマシンが実行中に有線 (Ethernet、シリアルコンソール等) で接続してネットワーク設定をする
  • NervesLivebook
    • NervesLivebook 限定の裏技

基本的なネットワーク設定は VintageNet Cookbook で解説されています。

環境

  • Elixir: 1.15.4-otp-26
  • Nerves: 1.10.3

nerves_pack

Nerves の公式サンプルプロジェクトNerves Getting Started ドキュメントに沿って新規作成された Nerves プロジェクトには、mix.exs の依存パッケージリストに nerves_pack が含まれていると思います。

nerves_pack は最小限の作業で Nerves プロジェクトを立ち上げて実行するための依存関係とデフォルト設定をまとめたものです。ネットワーク関連のパッケージ(vintage_net 等)もそこに含まれています。

inets

インターネット接続するには inetsssl をあらかじめ mix.exs:extra_applications に追加しておく必要があります。

インターネットに接続しない場合は無視してください。

mix.exs
   def application do
     [
       mod: {HelloNerves.Application, []},
-      extra_applications: [:logger, :runtime_tools]
+      extra_applications: [:logger, :runtime_tools, :inets, :ssl]
     ]
   end

以下のエラーを見たらこのことを思い出してください。

対象デバイスのIEx
iex(1)> weather
** (RuntimeError) :ssl can't be started.
This probably means that it isn't in the OTP release.
To fix, edit your mix.exs and add :ssl to the :extra_applications list.

    (toolshed 0.3.1) lib/toolshed.ex:100: Toolshed.check_app/1
    (toolshed 0.3.1) lib/toolshed.ex:12: Toolshed.weather/0
    iex:1: (file)
対象デバイスのIEx
iex(1)> weather
** (RuntimeError) :inets can't be started.
This probably means that it isn't in the OTP release.
To fix, edit your mix.exs and add :inets to the :extra_applications list.

    (toolshed 0.3.1) lib/toolshed.ex:100: Toolshed.check_app/1
    (toolshed 0.3.1) lib/toolshed.ex:11: Toolshed.weather/0
    iex:1: (file)

コンパイル時に設定

お手元の Nerves プロジェクトの config/target.exs を開き、以下の設定を追加します。

target.exs
ssid = System.get_env("NERVES_WIFI_SSID") ||
  raise("environment variable WIFI_SSID is missing")

psk = System.get_env("NERVES_WIFI_PASSPHRASE") ||
  raise("environment variable NERVES_WIFI_PASSPHRASE is missing")

config :vintage_net,
  regulatory_domain: "JP", # Japan: JP, US: US, Global: 00, etc
  config: [
    {"usb0", %{type: VintageNetDirect}},
    {"eth0",
     %{
       type: VintageNetEthernet,
       ipv4: %{method: :dhcp}
     }},
    # Wi-Fi の 設定
    {"wlan0",
     %{
       type: VintageNetWiFi,
       vintage_net_wifi: %{
         networks: [
           %{
             key_mgmt: :wpa_psk,
             ssid: ssid, # Wi-Fi の ID ー 直書き、もしくは環境変数で渡す
             psk: psk # Wi-Fi の パスワード ー 直書き、もしくは環境変数で渡す
           }
         ]
       },
       ipv4: %{method: :dhcp} # DHCP(IP アドレス等を自動的に割り当て)
     }}
  ]

regulatory_domain は使用される国に応じて設定する必要があるようです。よくわかりません。

もちろん DHCP の代わりに、固定 IP アドレスの設定をすることも可能です。

実行時に設定

VintageNet.configure/3、もしくは VintageNetWiFi.quick_configure/2 を使うと、対象デバイスが動作中に Wi-Fi の設定を行うことができます。特に VintageNetWiFi.quick_configure/2 が便利です。

対象デバイスのIEx
VintageNetWiFi.quick_configure("access_point", "passphrase")

このときに設定された内容は永続化されますので、デバイスを再起動しても設定された内容は保持されます。

エンタープライズネットワーク上にある場合、固定 IP アドレスを使用している場合、またはその他の特殊な処理が必要な場合は、VintageNet.configure/3 を呼び出す必要があります。詳しくは VintageNet Cookbook をご覧ください。

ネットワーク設定を消去したい場合は、VintageNet.deconfigure/2 を使います。

対象デバイスのIEx
VintageNet.deconfigure("wlan0")

対象デバイスにまだ Wi-Fi の設定がされていない場合は当然 Wi-Fi がまだ使えませんので、Ethernet やシリアルコンソールで接続する必要があります。

NervesLivebook から設定

Nerves Livebook ファームウェアを使用すると、何も構築せずに実際のハードウェアで Nerves プロジェクトを試すことができます。 数分以内に、Raspberry Pi や Beaglebone で Nerves を実行できるようになります。 Livebook でコードを実行し、ブラウザーで快適に Nerves チュートリアルを進めることができます。

有志の方々が Nerves Livebook のセットアップ方法ついてのビデオを制作してくださっています。ありがとうございます。

Nerves Livebook の中に ネットワーク関連のノートブックが含まれており、ブラウザ上で Wi-Fi の設定ができてしまいます。

また、Nerves Livebook ファームウェア を microSD に焼く時点で Wi-Fi の設定を環境変数として渡す方法もあります。

README の firmware-provisioning-options セクションをご参照ください。

ホストマシンのターミナルで microSD に焼くコマンド
sudo NERVES_WIFI_SSID='access_point' \
     NERVES_WIFI_PASSPHRASE='passphrase' \
     fwup nerves_livebook_rpi0.fw

ネットワーク設定を確認

VintageNet.info

VintageNet.info/1 で現在のネットワーク設定を確認できます。

対象デバイスのIEx
VintageNet.info
VintageNet 0.13.5

All interfaces:       ["lo", "usb0", "wlan0"]
Available interfaces: ["wlan0"]

Interface eth0
  Type: VintageNetEthernet
  Present: false
  Configuration:
    %{type: VintageNetEthernet, ipv4: %{method: :dhcp}}

Interface usb0
  Type: VintageNetDirect
  Present: true
  State: :configured (12 days, 18:46:34)
  Connection: :disconnected (12 days, 18:46:36)
  Addresses: 172.31.36.97/30
  MAC Address: "12:3d:01:01:19:79"
  Configuration:
    %{type: VintageNetDirect, vintage_net_direct: %{}}

Interface wlan0
  Type: VintageNetWiFi
  Present: true
  State: :configured (12 days, 18:46:34)
  Connection: :internet (12 days, 18:46:27)
  Addresses: 192.168.1.2/24, fe80::ba27:ebff:asdf:222a/64
  MAC Address: "b8:27:eb:cb:12:34"
  Configuration:
    %{
      type: VintageNetWiFi,
      vintage_net_wifi: %{
        networks: [
          %{
            mode: :infrastructure,
            psk: "....",
            ssid: "PiyoPiyo",
            key_mgmt: :wpa_psk
          }
        ]
      },
      ipv4: %{method: :dhcp}
    }

:ok

ifconfig

ターミナルで使う UNIX コマンドのような感覚で Toolshed.ifconfig/0 を使うこともできます。

対象デバイスのIEx
ifconfig
lo: flags=[:up, :loopback, :running]
    inet 127.0.0.1  netmask 255.0.0.0
    inet ::1  netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
    hwaddr 00:00:00:00:00:00

wlan0: flags=[:up, :broadcast, :running, :multicast]
    inet 192.168.1.2  netmask 255.255.255.0  broadcast 192.168.1.255
    inet fe80::ba27:ebff:asdf:222a  netmask ffff:ffff:ffff:ffff::
    hwaddr b8:27:eb:cb:12:34

usb0: flags=[:up, :broadcast, :running, :multicast]
    inet 172.31.36.97  netmask 255.255.255.252  broadcast 172.31.36.99
    hwaddr 12:3d:01:01:19:79

インターネット接続の確認

Toolshed.weather/0 を実行してエラーが出なければ OK です。

対象デバイスのIEx
iex(1)> weather
┌┤  Weather report for: Washington, District of Columbia, United States  ├┐
                                                                        
                                                                        
       Sun 05 Nov              Mon 06 Nov              Tue 07 Nov       
                                                                      
                                                                        
                                                                        
+71          ⡔⠉⠉⠉⠑⡄                                                     
                 ⠘⡄                                         ⢀⠔⠉⠉⠉⠢⣀    
           ⢠⠃      ⠱⡀                                       ⢠⠃      ⠑⢄  
                                                         ⢠⠃         ⠉⠁│
          ⢀⠇        ⠈⣆                                    ⡠⠃            
│⢀⢄⡀                 ⠈⡂              ⡠⠒⠉⠉⠉⠑⠒⠤⣀    ⢀⣀⣀⣀⣀⣀⠤⠔⠁             
│⡇ ⠢⡀                 ⠈⠢⡀           ⡰⠁        ⠉⠉⠉⠉⠁                     
│⡇  ⠱⡀                  ⠈⠢⢄        ⡰⠂                                   
│⡇   ⠱⡀  ⢀⠇                 ⠉⠢⢄    ⢠⠃                                    
+44  ⠑⢄⢁⠎                     ⠑⠢⠤⡠⠃                                     
                                                                        
│─────┴─────┼─────┴─────╂─────┴─────┼─────┴─────╂─────┴─────┼─────┴─────╂│
     6    12    18           6    12    18           6    12    18      
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
 ⛅️ ⛅️ ⛅️ ☁️  ☀️  ☀️  ☀️  ☀️  ☀️  ☀️  ☀️  ⛅️ ⛅️ ☁️  ☁️  ☀️  ☀️  ⛅️ ⛅️ ⛅️ ⛅️ ☁️  ⛅️ ☀️ 
                                                
 2  2  3  2  7  9  5  5  5  3  3  3  4  7  6  7  9  8  8  8  9  6  7  9 
                                                                        
│🌗                     🌗                      🌘                     🌘│
       ━━━━━━━━━━━             ━━━━━━━━━━━             ━━━━━━━━━━━      
                                                                        
                                                                        
└────────────────────────────────────────────────────────────────────────┘
Weather: ⛅️  Partly cloudy, +61°F, 44%, ↓9mph, 1018hPa
Timezone: America/New_York
  Now:    21:24:24-0500 | Dawn:    06:12:21  | Sunrise: 06:40:49
  Zenith: 11:51:41      | Sunset:  17:02:10  | Dusk:    17:30:37

Toolshed.ping/1 も使えます。

対象デバイスのIEx
iex(1)> ping "8.8.8.8"
Response from 8.8.8.8 (8.8.8.8): icmp_seq=0 time=33.517ms
Response from 8.8.8.8 (8.8.8.8): icmp_seq=1 time=100.672ms
Response from 8.8.8.8 (8.8.8.8): icmp_seq=2 time=39.159ms

Toolshed.speedtest/1 も面白いです。

対象デバイスのIEx
iex(1)> speed_test
2345425 bytes received in 5.18 s
Download speed: 3.62 Mbps

ファームウエアのメタデータ

Nerves.Runtime.KV の関数でファームウエアのメタデータにアクセスできます。

対象デバイスのIEx
Nerves.Runtime.KV.get_all
Nerves.Runtime.KV.get("wifi_ssid")
Nerves.Runtime.KV.get("wifi_passphrase")

さいごに

Nerves で 無線LAN (Wi-Fi) でインターネット接続する方法をまとめました。

他にも vintage_net_wizard などまだ試せていないものがたくさんあります。

本記事は autoracex #253 の成果です。ありがとうございます。

toukon-qiita-macbook_20230912_091808.jpg

9
3
1

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
9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?