UMEHOSHI ITA TOP PAGE

[Raspberry Pi 3 Model A+]と[UMEHOSHI ITA]を乗せたモータ付き台車の利用例

このページで示した[Raspberry Pi]のインストールと[UMEHOSHI ITA]を制御できた後のページです。
Raspberry Pi 3 Model A+]に接続した[UMEHOSHI ITA]基板を乗せるモータ付き台車の制作

起動Unitで実行するDIPスイッチでネット設定を切り替えるスクリプト

DIPスイッチの設定で、次のように使うと決めた。
4ビットDIPスイッチの設定(2進表現で ?のビットは任意)起動状態の目標
0b??00 自宅のWifiに接続する。ステーションモード (STA接続)
0b??01 Raspberry Pi自身をWifiの親機。アクセスポイントモード (APモード)
0b??10職場AのWifiに接続する。ステーションモード (STA接続)
0b??11職場BのWifiに接続する。ステーションモード (STA接続)

さて、RaspberryPi3のOSは「imager_1.7.4.exe」でインストールしたシステムを使っています。
このシステムのデフォルトでは、APモードで動作させるために、hostapd、dnsmasq のモジュールが足りません。
よってこれらモジュールが存在しない場合は、次のコマンド操作で追加します。
sudo apt update
sudo apt install hostapd
sudo apt install dnsmasq
(2025年8月で、hostapdのVersion: 2:2.9.0-21+deb11u3、dnsmasqのVersion: 2.85-1+deb11u1がインストールされました)


対して、アクセスポイントモード (APモード)で使うファイルは次の通りです。
以上の切り替え用のコード(/usr/local/bin/network-select.py)を以下の内容で作成しました。
#!/usr/bin/python3

# 『/usr/local/bin/network-select.py』の内容
import shutil
import RPi.GPIO as GPIO
import subprocess

#import time

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.cleanup()

GPIO.setup(21, GPIO.OUT)  # GPIO21を出力に設定
GPIO.output(21, GPIO.HIGH)  # ON(3.3V)
GPIO.setwarnings(True)

for no in [6, 16, 17, 22, 23, 24, 25]:
    GPIO.setup(no, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # プルアップ付き入力

dip =  0b0001 if GPIO.input(22) == GPIO.LOW else 0
dip += 0b0010 if GPIO.input(23) == GPIO.LOW else 0

def set_station_mode(src_conf):
    print("Switching to station mode...")
    subprocess.run(["systemctl", "stop",     "dhcpcd"], check=False)
    dst_conf = "/etc/wpa_supplicant/wpa_supplicant.conf"
    subprocess.run(["cp", src_conf ,                    dst_conf])
    print(f"Copied {src_conf} → {dst_conf}")
    subprocess.run(["cp", "/etc/dhcpcd.d/dhcp.conf",    "/etc/dhcpcd.conf"])
    subprocess.run(["systemctl", "stop",     "hostapd"], check=False)
    subprocess.run(["systemctl", "stop",     "dnsmasq"], check=False)
    subprocess.run(["systemctl", "start",     "dhcpcd"], check=False)
    # デフォルトで、check=False があり、コマンドが失敗してもエラーを出さずに CompletedProcess オブジェクトを返します。

def set_ap_mode(src_conf):
    print("Switching to AP mode...")
    subprocess.run(["systemctl", "stop", "wpa_supplicant"], check=False)
    #subprocess.run(["pkill", "wpa_supplicant"], check=False)
    subprocess.run(["systemctl", "stop",     "dhcpcd"], check=False)
    subprocess.run(["cp", "/etc/dhcpcd.d/ap.conf",    "/etc/dhcpcd.conf"])
    dst_conf = "/etc/hostapd/hostapd.conf"
    subprocess.run(["cp", src_conf ,                 dst_conf])
    print(f"Copied {src_conf} → {dst_conf}")
    subprocess.run(["systemctl", "start",  "dhcpcd"], check=False)
    subprocess.run(["systemctl", "start", "dnsmasq"], check=False)
    subprocess.run(["systemctl", "start", "hostapd"], check=False)


if dip == 0:
    set_station_mode("/etc/wpa_supplicant/home.conf")
elif dip == 1:
    set_ap_mode("/etc/hostapd/hostapd_default.conf")
elif dip == 2:
    set_station_mode("/etc/wpa_supplicant/officeA.conf")
elif dip == 3:
    set_station_mode("/etc/wpa_supplicant/officeB.conf")

GPIO.output(21, GPIO.LOW)  # OFF

ネットワークをDIP SWで切り替えるスクリプト起動サービスのUnit

切り替え用のサービスコード(/etc/systemd/system/network-select.service)を以下の内容で作成しました。
[Unit]
Description=Network mode selector based on DIP switch
After=local-fs.target
# Before=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /usr/local/bin/network-select.py
TimeoutStartSec=100
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

上記のサービスの起動確認と停止は、『systemctl start network-select.service』と『systemctl stop network-select.service』です。
サービス自動起動有効の設定は、『systemctl enable network-select.service』です。
(上記において、コメントにしたBeforeの行を有効にすると、タイムアウトの起動失敗が起きます。 その時、TimeoutStartSec=100の1.5分の指定が無いと起動できなくなりました。)

上記のサービスで起動しているnetwork-select.pyでは、ステーションモード (STA接続)とアクセスポイントモード (APモード)の切り替えが要になっています。
この処理内容は、まとめる次のようになります。
/etc/dhcpcd.confは、ステーションモードもアクセスポイントモードで内容を変える必要があり、その変更をコピー操作で行っています
/etc/wpa_supplicant/wpa_supplicant.confは、自宅と職場で違う内容になるように、その変更をコピー操作で行っています
4bit スイッチの
設定と目標
( ?のビットは任意)
network-select.pyの
処理内容
0b??00
自宅のWifiに接続する
Wifi接続用の /etc/wpa_supplicant/wpa_supplicant.confに、/etc/wpa_supplicant/home.confをコピー
IPアドレスを取得設定用の /etc/dhcpcd.confに、/etc/dhcpcd.d/dhcp.confをコピー
アクセスポイント用のサービス(hostapd,dnsmasq)を止めて、dhcpcdを実行
0b??01
Raspberry Piを
WiFiアクセスポイント
の親機にする
Wifiアクセスポイント設定用の /etc/hostapd/hostapd.confに、/etc/hostapd/hostapd_default.confをコピー
固定アドレス設定用の /etc/dhcpcd.confに、/etc/dhcpcd.d/ap.confをコピー
上記設定ファイルを利用するhostapdサービスの実行 ステーションモード用のサービス(wpa_supplicant,dhcpcd)を止めて、dhcpcd,dnsmasq,hostapdサービスを起動
(dnsmasq用の設定ファイルとして /etc/dnsmasq.conf を配置して置く)
0b??10
職場AのWifiに接続する
0b??00に対して、下記の接続先のコピー元だけが異なる
/etc/wpa_supplicant/officeA.confを/etc/wpa_supplicant/wpa_supplicant.confにコピー
0b??11
職場BのWifiに接続する
0b??00に対して、下記の接続先のコピー元だけが異なる
/etc/wpa_supplicant/officeB.confを/etc/wpa_supplicant/wpa_supplicant.confにコピー

/etc/dhcpcd.dのディレクトリを作成し、ここに/etc/dhcpcd.confに設定するコピーとなるファイル群を配置しておいて、 起動時にDIP SW設定によって対応するコピー元を、/etc/dhcpcd.confへ上書きコピーさせます。
職場Aや職場BのWifiに接続する場合と、自宅のWifiに接続場合との違いは、wpa_supplicant.confの内容が違うだけなので、接続先の設定を別アフィルで配置しておいて、 起動時にDIP SW設定によって対応するコピー元を、/etc/wpa_supplicant/wpa_supplicant.confへ上書きコピーさせています。

[Raspberry Pi 3 Model A+]の起動プログラムをDIP SWで切り替える。

DIPスイッチの設定で、次のように使うと決めた。
4ビットDIPスイッチの設定起動状態の目標
0b00?? 制御コマンドを受信して実行するTCPサーバープログラム(raspiAPumeTcp.py)を起動する
0b01?? Webサーバープログラム(raspiAPumeWeb.py)を起動する
0b10??実験用プログラム(raspiAPumeTest.py)を起動する
0b11??スキャンのプログラム(raspiAPume.py)を起動する

以上の切り替え用のコード(/usr/local/bin/start-app-select.py)を以下の内容で作成しました。
#!/usr/bin/python3

# 『/usr/local/bin/start-app-select.py』の内容
import sys
import shutil
import RPi.GPIO as GPIO
import subprocess
module_path='/usr/local/apps'
if module_path not in sys.path:
    sys.path.append(module_path)

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(21, GPIO.OUT)  # GPIO21を出力に設定
GPIO.output(21, GPIO.HIGH)  # ON(3.3V)

for no in [6, 16, 17, 22, 23, 24, 25]:
    GPIO.setup(no, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # プルアップ付き入力

dip =  0b0001 if GPIO.input(24) == GPIO.LOW else 0
dip += 0b0010 if GPIO.input(25) == GPIO.LOW else 0


if dip == 0:
    import raspiAPumeTcp  # raspiAPumeTcp.py
elif dip == 1:
    import raspiAPumeWeb
elif dip == 2:
    import raspiAPumeTest
elif dip == 3:
    import raspiAPume

GPIO.output(21, GPIO.LOW)  # OFF

上記では、DIPスイッチの状態で、/usr/local/appsの中各種モジュールを起動するプログラムです。
よって、次のようにモジュールを置くディレクトリを作って、そこに起動のPythonファイルを置いておきます。
sudo mkdir -p /usr/local/apps
sudo vi /usr/local/apps/raspiAPumeTcp.py
上記では、0b00??のスイッチで動かすTCPサーバープログラムを作成・編集する時のコマンド例です。

ネットワーク設定後に起動するアプリをDIP SWで切り替えるスクリプト起動サービスのUnit

切り替え用のサービスコード(/etc/systemd/system/start-select.service)を以下の内容で作成しました。
[Unit]
Description=Start Application selector based on DIP switch
After=network-select.service
Requires=network-select.service

[Service]
Type=simple
ExecStart=/usr/bin/python3 /usr/local/bin/start-app-select.py
TimeoutStartSec=100
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

上記のサービスの起動確認と停止は、『systemctl start start-select.service』と 『systemctl stop start-select.service』です。
サービス自動起動有効の設定は、『systemctl enable start-select.service』です。
上記実行状態の検証方法示します。
サービスの実行エラーメッセージを確認:systemctl status start-select.service
サービスのログを分析・確認:journalctl -u start-select.service