1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MicroPythonでWi-Fiの設定画面(CaptivePortal)を実装する

Posted at

はじめに

皆さんはMiroPythonをインストールしたRaspberryPi Pico WやESP32等のマイクロコントローラをWi-Fiに接続して使用するようなシーンにおいて接続したいWi-FiのSSIDやパスワードをソースコードに直書きせず、なんらかの手法で後から自由に変更できるような形で設定したいと思ったことはないでしょうか?私はあります。

アクセスポイントモードで起動したデバイスにスマホ等を接続し表示されたWEBページからSSIDやパスワードを設定する、さらにWEBページのURL等を覚えていなくてもCaptivePortalとして勝手に設定ページが立ち上がる...そんな機能を実装したので紹介します。

この記事で触れないこと

RaspberryPi PicoやESP32等へのMicroPythonのインストール、Thonny等の開発環境構築・操作等に関しては触れません。

wifi-setupライブラリ

概要

前述のとおりMicroPythonにてCaptivePortalを実装し、表示されるページ上でMicroPythonデバイスが接続してほしいWi-FiのSSIDやパスワードを設定できるものです。
※MicroPythonでのCaptivePortal実装にはmicropython-captiveportalを大いに参考にしました
※RaspberryPi Pico W & MicroPython v1.23.0で動作確認しています

リポジトリはこちら:

ライブラリのインストール

リポジトリ上のwifi_setupフォルダ一式をMicroPythonデバイスのlibフォルダ内にコピーします。

ディレクトリツリー
root
└─lib
    └─wifi_setup
        ├─wifi_setup.py
        ├─__init__.py
        │
        └─web
            ├─error.html
            ├─index.html
            ├─style.css
            └─success.html

サンプルコードのコピー

起動時に処理されるboot.pyとその処理完了後に実行されるmain.pyのサンプルをリポジトリ上のsampleフォルダ内からコピーします。
※RaspberryPi Pico Wでの利用を想定したサンプルコードとしています

boot.pyではボタン(RaspberryPiのBOOTSELボタン)が押下されている場合にWi-Fiの設定を削除するサンプルとなっています。

boot.py サンプルコード
boot.py
import time

from wifi_setup import WifiConfig

# Sample of deleting settings when some button is pressed at boot.
# For RaspberryPi Pico W
if WifiConfig().check():
    time.sleep_ms(3000)
if rp2.bootsel_button() == 1:
    WifiConfig().delete()

main.pyではWi-Fiが未設定の場合はWi-Fi設定用のポータルを起動、設定済みの場合は設定情報に基づいてWi-Fiへの接続とメインルーチンを実行するサンプルとしています。

main.py サンプルコード
main.py
import time
from network import (
    WLAN,
    STA_IF,
    STAT_GOT_IP,
    STAT_NO_AP_FOUND,
    STAT_CONNECT_FAIL,
    STAT_WRONG_PASSWORD,
)
from machine import reset

from wifi_setup import WifiConfig, WifiSetupPortal

class IoTDevice:
    def execute(self) -> None:
        try:
            if not WifiConfig().check():
                print("start wifi setup portal")
                WifiSetupPortal().execute()
            else:
                print("start iot device")
                if not self._connect_wifi():
                    raise Exception("cannot connect wifi")
                self._main_routine()
        except Exception as e:
            print(f"{e=}")
            time.sleep(1)
            reset()

    def _connect_wifi(self) -> bool:
        ssid: str
        key: str
        ssid, key = WifiConfig().get()
        wlan: WLAN = WLAN(STA_IF)
        wlan.active(True)
        wlan.connect(ssid, key)

        while True:
            time.sleep(1)
            status: int = wlan.status()
            if status == STAT_NO_AP_FOUND or status == STAT_CONNECT_FAIL:
                break
            elif status == STAT_WRONG_PASSWORD:
                print("cannot connect wifi because incorrect password so wifi_config reset")
                WifiConfig().delete()
                reset()
                break
            elif status == STAT_GOT_IP:
                return True
        return False

    def _main_routine(self) -> None:
        # Your main routine here
        print("main routine")

if __name__ == "__main__":
    IoTDevice().execute()

スマホからのWi-Fi設定

  1. サンプルを実行するとMicroPythonデバイスが無線アクセスポイントモード(デフォルトではSSID:IoTDeviceSetUpのセキュリティ無し)で起動します
  2. スマホ等を使用し無線アクセスポイントモードで起動してきたMicroPythonデバイスのSSIDに接続します
  3. CaptivePortalとして実装しているので(Androidでは)「Wi-Fiネットワークにログイン」の通知及びWi-Fi設定画面へ自動遷移します
  4. 表示されたWi-Fi設定画面にてMicroPythonデバイスが接続してほしいWi-FiのSSID及びPasswordを入力し、Submitします
  5. リクエストに成功するとMicroPythonデバイスが再起動しboot.pymain.pyが再度実行され、サンプルコードではWi-Fi設定済み時の処理(無線APへの接続やメインルーチンの実行)が行われます

一連のスクショ

補足

無線アクセスポイントモード時のSSIDやパスワードのカスタマイズ

MicroPythonデバイスにWi-Fi設定を行う時の無線アクセスポイントのSSIDパスワード、設定ページのドメインWifiSetupPortalクラスのインスタンス生成時に指定できます。

カスタマイズ
WifiSetupPortal(
    ssid="SetUpSSID",
    key="SetUpPassword",
    domain="setup.local"
)
Wi-Fi設定情報へのアクセス

Wi-Fiの設定情報はMicroPythonデバイスのroot直下にwifi_config.jsonとして保存され直接のアクセスも可能ですが、WifiConfigクラスから操作できます。

  • WifiConfig().get():設定されたSSIDパスワードをタプルで返します
  • WifiConfig().check():設定ファイルの存在確認と設定情報を正しく読み込み可能か確認し結果をboolで返します
  • WifiConfig().save():与えられたSSIDパスワードを設定ファイルに保存します
  • WifiConfig().delete():設定ファイルを削除します

最後に

CaptivePortalをWi-Fiを使用しようとする者の認証以外の用途で使用してもいいものか?は悩みましたが、スマホ等で設定画面に自動で遷移するという利便性・魅力の前に考えることをやめて実装しました。

個人の趣味としての電子工作等の用途であればWi-Fi設定のためにアプリ等を必要とせず、自動で画面遷移するためMicroPythonデバイスのIPアドレスやURL等を覚えておく必要がないため便利なんじゃないかなと思います。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?