投稿日:2025年8月27日
前回のPico W に引き続き、今回はRaspberry Pi Zero 2 Wで作る二次元コード受付システムを検証してみたいと思います。

▲購入したQRコードリーダー。モバイルバッテリーからラズパイを起動し、モニターもキーボードも不要な、いわばヘッドレスな環境を構築するのが今回の目標です。
※QRコードは株式会社デンソーウェーブの登録商標です
Zero 2 WはPythonのPyMySQLやmysql-connector-pythonなどのライブラリを使うことができます。
これらを使ってphpMyAdminのフィールド値を更新しようと試してみました。
しかし、契約しているさくらサーバーのビジネスプランでは同一サーバー内からのみ接続が可能で、外部からの接続は許可されていません。
仕方がないので前回同様、フィールド値を更新するPHPをサーバーに設置し、Zero 2 WからそのPHPにアクセスして更新するようにしました。
必要なファイルデータベースを操作するPHP
<?php
// CORSを許可
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");
// サーバー接続(本番サーバーの設定を記述)
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$user = 'root';
$pass = 'root';
try {
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
if (isset($_GET['id']) && isset($_GET['flg'])) {
$id = (int)$_GET['id'];
$flg = (int)$_GET['flg'];
// ▼ QRリーダーで読み取ったidのflgを更新
$stmt = $pdo->prepare("UPDATE customers SET flg = ? WHERE id = ?");
$stmt->execute([$flg, $id]);
echo "更新しました: id={$id}, flg={$flg}";
} else {
echo "パラメータが不足しています。";
}
} catch (PDOException $e) {
die('接続エラー:' . $e->getMessage());
}
<?php
// CORSを許可
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");
// サーバー接続(本番サーバーの設定を記述)
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$user = 'root';
$pass = 'root';
try {
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
if (isset($_GET['id']) && isset($_GET['flg'])) {
$id = (int)$_GET['id'];
$flg = (int)$_GET['flg'];
// ▼ QRリーダーで読み取ったidのflgを更新
$stmt = $pdo->prepare("UPDATE customers SET flg = ? WHERE id = ?");
$stmt->execute([$flg, $id]);
echo "更新しました: id={$id}, flg={$flg}";
} else {
echo "パラメータが不足しています。";
}
} catch (PDOException $e) {
die('接続エラー:' . $e->getMessage());
}
▲データベースを操作するPHPはサーバーに設置し、Zero 2 Wからアクセスしてフィールド値を更新します。
Systemd
Zero 2 Wに電源投入時、自動でプログラムを実行するSystemd という方法を使います。
Systemd はRaspberry Pi OSの旧バージョン、Raspbian Jessie(〜2018年)から推奨されている自動起動の方法です。
Unitファイルと呼ばれるファイルにプログラムを記述し、/etc/systemd/system に .service という拡張子で配置します。
ただし/etc/systemd/system のディレクトリはアクセスが制限されているので新規ファイル作成ができません。
そこで、Zero 2 WでLXTerminalを起動し、下記のコマンドでファイル作成を行います。
sudo nano /etc/systemd/system/qr_update.service
▲ファイル名は任意。
今回はqr_update.serviceという名前でUnitファイルを作成します。
Unitファイルが編集モードになるので下記のようを記述します。

▲コメント入りのソースコードは下記です。
編集後、control + o
で保存。control + x
で終了します。
[Unit]
Description=QRコード受付システム # このUnitの説明
After=network.target # ネットワーク疎通後、このUnit(qr_update.service)を起動する。
[Service]
ExecStart=/usr/bin/python3 /home/onebitious/Desktop/qr_update.py #実行するPythonとファイルを指定。
WorkingDirectory=/home/onebitious # 作業するディレクトリ
StandardOutput=journal # 標準出力をログjournalに保存。
StandardError=journal # エラー出力をログjournalに保存。
Restart=always # エラーが起きても再起動するように設定。
User=onebitious # ラズパイユーザー名
[Install]
WantedBy=multi-user.target # Enable 時に multi-user.target の依存に設定する。
▲コメント入りのソースコードです。
各行、深い意味がありますが、次回以降に触れたいと思います。
自動起動させるPython
from evdev import InputDevice, categorize, ecodes # 下記参照
import requests # PythonのHTTP通信ライブラリ
import time # Pythonの時間に関するライブラリ
SERVER_URL = "https://xxxxxxxxxx/update.php" # サーバーのURL
def update_flag(id_num):
try:
r = requests.get(f"{SERVER_URL}?id={id_num}&flg=2")
print(f"[OK] id={id_num} → flg=2 更新: {r.text}")
except Exception as e:
print(f"[ERROR] {e}")
def main():
# QRリーダーのデバイスを指定
dev = InputDevice('/dev/input/event0') # ラズパイの入力USB
print("=== QRリーダー待機中... ===")
buffer = ""
for event in dev.read_loop():
if event.type == ecodes.EV_KEY:
data = categorize(event)
if data.keystate == 1: # キー押下
key = data.keycode
# Enterキーで確定
if key == 'KEY_ENTER':
id_num = buffer.strip()
buffer = ""
if id_num:
print(f"入力値: {id_num}")
time.sleep(1) # 1秒待ってから更新
update_flag(id_num)
else:
# KEY_1 → "1" のように変換
if key.startswith("KEY_") and len(key) == 5:
buffer += key[-1] # 数字キー
elif key == "KEY_0":
buffer += "0"
elif key == "KEY_MINUS":
buffer += "-"
# ほかに必要なキーがあればここで追加
if __name__ == "__main__":
main()
▲1行目。from evdev import InputDevice, categorize, ecodes
evdevはインプットデバイスを扱うためのPythonライブラリになります。
InputDevice:インプットデバイスを扱うクラス。
categorize:バイナリデータを「わかりやすい形」に変換する関数
ecodes:インプットデバイスが発するイベントの定数を集めた辞書。event codes
の略。
他はコメント参照。
必要なファイルは以上です。
次に必要なライブラリのインストールと自動実行のためのコマンドを入力します。
必要なライブラリのインストール
必要なライブラリのインストール
evdev(インプットデバイスを扱うためのライブラリ)をインストールします。
sudo apt update
▲まずは上記コマンドでアップデートが可能なパッケージのリストを更新します。

▲詳細を表示させるコマンドが表示されますが、今回は省略します。
続けて下記のコマンドを実行しevdevをインストールします。
sudo apt install python3-evdev

▲Runをクリックするとプログラムが実行されます。
続けて下記の自動起動させるコマンドを入力します。
sudo systemctl daemon-reload # systemdに読み込みさせる(再読み込み含む)
sudo systemctl enable qr_update.service # 次回以降も自動起動するように登録
sudo systemctl start qr_update.service # 今すぐ起動
sudo systemctl status qr_update.service # 状態確認
▲コメント付きですが、実際にはコメントは入力しないようにしてください。
各行それぞれ入力し実行します。

▲status
の実行で状態が表示されます。
Active:active (running)と表示されれば実行されていることになります。

▲再起動後、自動起動しました。
QRコードを読み取りデータベースのフィールド値が更新されるか試してみます。

▲自作したデータベースと連動したシステムが更新されました。
読み込み後、リロードするとチェックが入り背景が赤くなります。
難しいことばかりでしたが、何とかやりたいことができました。
ラズパイもそうなのですが、Pythonも勉強し始めたばかりなので、まだまだ習得することがたくさんあります。
以降も、Pico WにUSBや電源モジュールなどを接続し色々と試してみたいと思います。
引き続き精進したます。
最後まで読んでいただき、ありがとうございました。