PCでキー操作して、ラズパイでpythonコードを実行する
STEP1. キー操作画面はWEBサーバー(2)で配信して、同じネットワークにあるPCがキー操作をする。
STEP2. キー操作に対応するpythonアプリ(3)を呼び出してラズパイのpythonコードを実行する。
STEP3. pythonコードの実行結果はアプリサーバー(4)を介して、(2)のWEBサーバーのHTMLファイルでPCに伝達します。
(2)WEBサーバー
ラズパイでWEBサーバーが動いていることを検査します
WEBサーバー(Apache2)のステータスを systemctl コマンドで表示します。
$ sudo systemctl status apache2
Active: の項目が 「active (running)」になっていれば正常。もしapache2がインストールされていなければ「ラズパイでWEBサーバーを立ち上げる」を実行します。
ラズパイと同じネットワークに接続されているPCからWEBブラウザでアクセスして動作確認もできます。
WEBブラウザのURLは、ラズパイのホスト名を指定するか、IPアドレスを指定します。例 http://razpi10.local/
JavaScript が動くことを検査します
ラズパイのディレクトリやファイルは悪意ある改ざんがされないように適切なアクセス制御がされています。通常ユーザー「pi」でHTMLファイルを編集できるように chmod コマンドで設定します。
ディレクトリ「/var/www」に対して、[o]他のユーザーに[w]書き込み権限を[+]追加するという意味です。
$ sudo chmod –R o+w /var/www
ユーザー:[u]ユーザー/所有者, [g]グループ, [o]その他ユーザー, [a]全てのユーザー
演算子:[+]追加, [-]削除, [=]指定する
アクセス権:[r]読み込み, [w]書き込み, [x]実行
指定したパターンに一致するディレクトリとすべてのファイルモードを変更する:[-R]
JavaScript コードをindex.htmlファイルに追加します
ディレクトリを移動して、ファイル[index.html]を編集する
$ cd /var/www/html
$ sudo nano index.html
<body>タグ内に次のコードを追加します。これはWEBページを1秒毎に再表示して、hoge というタグの場所に現在の日付と時刻を表示するコードのサンプルです。hogeは好きな名前に変更できます。
<div id="hoge"></div>
<script>
setInterval( function() {
document.getElementById("hoge").innerHTML = new Date().toLocaleString();
}, 1000);
</script>
エディタ nano で[書き込み]と[終了]をして、PCのWEBブラウザでWEBページ<例 http://razpi10.local/>を検査します。
1秒毎に[YYYY/MM/DD hh:mm:ss]の形式で表示が更新されていれば JavaScript が動作しています。
ここまででWEBサーバー(2)の部分の動作確認ができました
続いてWEBブラウザからラズパイの python アプリを実行できるように準備します
制作する pythonアプリ は、ラズパイのGPIOに接続したLEDを、PCのWEBブラウザでON/OFFするもの。
これができれば、ラズタンクの左右モーターも前進・後進できるはず。
(3)サーバー側 pythonアプリ
LEDの配線
ラズパイのGPIOは空いている端子を選んでください。
下図例はGPIO26を使います。後述する python コードは、GPIO番号を一致させることを忘れずに。
LEDの+側に抵抗を入れるのも忘れずに。GPIO出力は 3.3V 最大電流50mAですが、LED赤のパーツ番号は不明ですが30mA程度の部品があるようなので、この場合、LED赤が壊れます。
LinuxコマンドだけでLEDを点灯する
次の3ステップでLEDをON/OFFします。この仕組みの詳しい説明は「歩行者用信号機をシミュレーション」で紹介しています。
LEDを接続したGPIOを指定する(GPIO26を使う)
$ echo 26 > /sys/class/gpio/export
使うGPIOの入出力を設定する。今回は出力(out)です。
$ echo out > /sys/class/gpio/gpio26/direction
LEDを点灯する
$ echo 1 > /sys/class/gpio/gpio26/value
LEDを消灯する
$ echo 0 > /sys/class/gpio/gpio26/value
Python フレームワーク(Flask)をインストール
PythonアプリをWEBアプリとして、WEBサーバー(Apache2)で動かすには「mod_wsgi」モジュールが必要です
$ sudo apt-get install libapache2-mod-wsgi-py3
Pythonフレームワーク(Flask)をインストールします
$ sudo pip3 install Flask
ラズパイを再起動します
$ sudo reboot
WEBアプリを構築します
3つのファイルを2つのディレクトリに新規作成します。
ラズパイで動かす pythonアプリ 「app.py」を作成
新規ディレクトリ「/var/www/flask」を作って、新規ファイル「app.py」を作ります。
$ cd /var/www
$ sudo mkdir flask
$ cd flask
$ nano app.py
「app.py」のコード
#!/usr/bin/ python3
# -*- coding: utf-8 -*-
import subprocess
# Flaskフレームワークのインポート
from flask import Flask
# テンプレートエンジンのインポート
from flask import render_template
# Flaskインスタンスの作成
app = Flask(__name__)
# ルーティング
@app.route('/')
def index():
# GPIO26を出力に初期設定する
subprocess.run('echo 26 > /sys/class/gpio/export', shell=True)
subprocess.run('echo out > /sys/class/gpio/gpio26/direction', shell=True)
print('GPIOを初期化しました')
return render_template('ledapp.html')
# LEDをONする。URIコマンド「ledOn」を指定するとsubprocessでLinuxコマンドを実行する
@app.route('/ledOn')
def ledON():
subprocess.run('echo 1 > /sys/class/gpio/gpio26/value', shell=True)
return '<p>LED ON</p>'
# LEDをOFFする。URIコマンド「ledOff」を指定するとsubprocessでLinuxコマンドを実行する
@app.route('/ledOff')
def ledOFF():
subprocess.run('echo 0 > /sys/class/gpio/gpio26/value', shell=True)
return '<p>LED OFF</p>'
# アプリ起動時のWEBポートを初期設定
# hostのIPアドレス0.0.0.0は、自分のラズパイ localhost を意味します
# ポート番号が5002。PCからこのポート番号でアクセスします。
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5002)
python アプリの動作確認
ラズパイと同じネットワークにあるPCからWEBブラウザのURIを指定してWEBアプリを実行します。
(参考)
URL:「Uniform Resource Locator」の略で、WEBの場所を示す
URI:「Uniform Resource Identifier」の略で、WEBのファイルを識別する
まずはラズパイ側で pythonアプリ「app.py」を起動する
$ cd /var/www/flask
$ sudo python app.py
次にPCのWEBブラウザでURIを指定する。
最初はGPIOの初期化から。URLはホスト名:ポート番号とURIの組み合わせ。
http://razpi10.local:5002/
LEDをONする
http://razpi10.local:5002/ledOn
LEDをOFFする
http://razpi10.local:5002/ledOff
ここであらためて「app.py」のコードを眺めて 「/」 「/ledOn」 「/ledOff」 を確認してください。改造するときはこのコードを変更すればよいか分かりますか?
PCのWEBブラウザで動かす「ledapp.html」を作成
新規ディレクトリ「/var/www/flask/template」を作り、新規ファイル「ledapp.html」を作ります。
$ cd /var/www/flask
$ sudo mkdir templates
$ cd templates
$ nano ledapp.html
「ledapp.html」のコード
<html>
<body>
<h1>ラズパイ(Razpi10.local) 操作メニュー</h1>
<p>[E]キーでLEDをON/OFFします</p>
<p id="output"></p>
<p id="comment"></p>
<script>
let ledStatus = 0;
document.addEventListener('keypress', keypress_ivent);
document.addEventListener('keyup', keyup_ivent);
// キーが押された時
function keypress_ivent(e) {
// id "output" の場所に e の値を入れます
document.getElementById('output').innerHTML = e.key;
// もし e の値が[e]ならば
if (e.key == 'e') {
// ラズパイの WEB API を呼び出すオブジェクトxhrを作る
var xhr = new XMLHttpRequest();
// LED点灯をON/OFF繰り返すため、LED変数が0ならON(1)にして、1ならOFF(0)にする
if (ledStatus == 0) {
// xhrオブジェクトにメソッド(LED ON 命令)を指定する
xhr.open('GET', '/ledOn');
ledStatus = 1;
} else {
xhr.open('GET', '/ledOff');
ledStatus = 0;
}
// WEB API リクエストの応答があったらここを実行する. とxhrオブジェクトに指定する
xhr.onreadystatechange = function() {
// 応答 readyStat=[1:呼び出し済み 2:ヘッダ情報を読める 3:ダウロード中 4:操作完了]
// 応答 status=[2xx:成功, 3xx:リダイレクト, 4xx:クライアントエラー, 5xx:サーバーエラー]
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById('comment').innerHTML = xhr.responseText;
}
}
// WEB API のリクエストを送信する
xhr.send();
}
return false;
}
// キーが離された時、画面表示をクリアする
function keyup_ivent(e) {
document.getElementById('output').innerHTML = '';
document.getElementById('comment').innerHTML = '';
return false;
}
</script>
</body>
</html>
(4)WEBアプリを構築します
WEBサーバー(Apache2)と Pythonアプリを接続してWEBアプリを構築します。WSGI(Web Server Gateway Interface, 通称ウィスキー)ファイルを新規作成します。
$ cd /var/www/flask
$ sudo nano app.wsgi
「app.wsgi」のコード
#!/usr/bin/ python3
# -*- coding:utf-8 -*-
import sys
# パスの指定
sys.path.insert(0, '/var/www/flask')
from app import app
application = app
ラズパイ側でWEBアプリを起動します。
$ sudo python app.py
* Serving Flask app "app" (lazy loading)
* Environment: production
* Debug mode: off
* Running on http://0.0.0.0:5002/ (Press CTRL+C to quit)
PC側でWEBアプリを呼び出します。
WEBブラウザを立ち上げて、URLを指定します
http://razpi10.local:5002/
表示される画面
Razpi10.local 操作メニュー
[E]キーを押してLEDをON/OFFします
PCの[E]キーを押すと、ラズパイのLEDが点灯・消灯を繰り返します。押し続けるとキーバッファされて点滅します。
まとめ
ラズパイのWEBサーバー・WEBアプリと、PCのWEBブラウザでキー操作できるようになりました。これをクライアント・サーバー型アプリといいます。今回は練習のためLED点灯だけにしましたが、ラズタンクのモーターを制御するWEBアプリに挑戦しましょう。2023年はCUI(テキスト)だけの操作だったのでGUI(グラフィカル)な操作パネルを作ってみたいです。音波センサーで前方までの距離をグラフ表示したり、サーボモーターの角度をグラフィック表示したりできたらいいのになー。