実用例
今回は実際にサーバのHPをコントロール画面として利用する為の基本的な説明です。 index.html、 http_server.js、 http_server.css、 http_server.pyの4つの ファイルを用意しそれぞれについて説明していきます。
index.html
index.html
html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" type="text/css" href="./http_server.css" >
<title>http-server 1.0</title>
</head>
<body>
<center>
<div class="b_frame">
<div class="t_font"><u>HTTP-Server 1.0</u></div><br>
<form method='get'>
<button type='submit' name='btn0' value='a' id="led">OFF</button>
<button type='submit' name='btn1' value='b' >時間</button>
</form>
<a href="./time.txt" download="time.txt" style="font-size: 28px; color:white">時間ファイル</a>
<br>
<a href="./test.png" download="test.png" style="font-size: 28px; color:white">画像ファイル</a>
<form method='get'>
<button type='submit' name='m_dir' value='c' >ファイルリスト</button>
</form>
<a href="./file_list.txt" download="file_list.txt" style="font-size: 28px; color:white">ファイルリスト</a>
</div>
</center>
<script src="./http_server.js"></script>
</body>
</html>
http_server.css、http_server.js と合わせて下記の様に表示されます。 コントロール画面でよく使う機能を含めています。
- リンクファイルの読み込み
- 6行:<link rel="stylesheet" type="text/css" href="./http_server.css" >
- 26行:<script src="./http_server.js"></script>
- 14行:<button type='submit' name='btn0' value='a' id="led">OFF</button>
- このボタンでGPIOにつながれたLEDをオンオフします
- 15行:<button type='submit' name='btn1' value='b' >時間</button>
- このボタンでPythonの関数を使って現在の時間を"time.txt"というファイルに書き込みます。
- 17行:"time.txt"をダウンロード
- これはサーバが作製したファイル。
- 19行:"test.png"をダウンロード
- これはサーバに元々有ったファイル。
- 21行:<button type='submit' name='m_dir' value='c' >ファイルリスト</button>
- ホームディレクトリをLinuxのコマンドを使って”file.txt"に保存
- 23行:<a href="./file_list.txt" dwnload="......color:white">ファイルリスト</a>
- "file_list.txt"のダウンロード
http_server.css, http_server.js
http_server.jsは最後にLEDの状態をサーバから受け取っています
http_server.css
css
@charset "UTF-8";
.t_font {
font-size: 32px;
font-weight: bold;
font-style: italic;
color: #ff0000;
}
.b_frame {
width: 400px;
background: #363636;
padding: 15px;
border-radius: 10px;
margin: 0 auto;
margin-top: 10px;
}
button {
display: block;
margin: 10px;
line-height: 30px;
cursor: pointer;
color: #fff;
background: #228b22;
border-radius: 10px;
font-size: 18px;
width: 120px;
}
http_server.js
javascript
document.addEventListener('DOMContentLoaded', function (event) {
let xhr = new XMLHttpRequest();
xhr.open('GET', "http://raspberrypi.local:8080/?80=1");
xhr.send();
xhr.onreadystatechange = function()
{
if(xhr.readyState === 4 && xhr.status === 200)
{
console.log( xhr.responseText );
if(xhr.responseText[0] == "1"){
document.getElementById("led").style.backgroundColor = "red";
document.getElementById("led").innerHTML = "ON";
}
}
}
});
http_server.py
http_server.py
python
from http.server import HTTPServer, SimpleHTTPRequestHandler
from urllib.parse import urlparse,parse_qs
import os
from gpiozero import LED
import datetime
import subprocess
def file_list():
subprocess.run('date +"%Y/%m/%d %H:%M:%S" > file_list.txt', shell=True)
subprocess.run("ls >> file_list.txt", shell=True)
def get_time():
now = datetime.datetime.now()
time_str = now.strftime('%Y-%m-%d %H:%M:%S')
fp = open("time.txt",'w')
fp.write(time_str)
fp.close()
class MyHandler(SimpleHTTPRequestHandler):
def do_GET(self):
global btn_0
allowed_extensions = {'.html', '.css', '.js', '.ico', '.png', '.txt'}
_, ext = os.path.splitext(self.path)
if self.path == "/" or ext.lower() in allowed_extensions:
return super().do_GET()
else :
self.send_response(200)
self.send_header('Content-type', "text/html")
self.end_headers()
parsed = urlparse(self.path)
params = parse_qs(parsed.query)
a = next(iter(params))
flg = 1
#----- LED ON/OFF --------------
if a == "btn0":
btn_0 ^= 1
if btn_0 == 1 :
led.on()
else :
led.off()
print("ボタン0が押されました")
#----- 時間の取得 -----------------
elif a == "btn1":
get_time()
print("ボタン1が押されました")
#----- ファイルリストの作製 -------
elif a == "m_dir":
file_list()
#----- 状態を送る -----------------
elif a == "80":
self.wfile.write(str(btn_0).encode("utf-8"))
flg = 0
if flg == 1:
fp = open("index.html",'rb')
self.wfile.write(fp.read())
fp.close()
#---------------------------------------------------------
btn_0 = 0
led = LED(17)
led.off()
get_time()
file_list()
host = ''
port = 8080
httpd = HTTPServer((host, port), MyHandler)
print('serving at port', port)
httpd.serve_forever()
- 24から28行:リクエストの仕分け
- 24行:予めコード内で使う拡張子を配列に定義
- 25行:self.pathをファイルネームと拡張子に分解
- 26行:self.pathが"/" か拡張子が登録した中に有るかチェック
- 27行:Trueなら、super().do_GET()を実行
- super().do_GET()は以下のファイルを処理
- index.html
- http_server.css
- http_server.py
- time.txt
- test.png
- file_list.txt
- super().do_GET()は以下のファイルを処理
- 29行以下はデータの解読とその処理です。
- 29から31行:クライアントにリクエストを受けた事を送信
- 33から35行:データの取り出し
- 34行:params = parse_qs(parsed.query)
- parse_qs(parsed.query)はクエリを辞書型に変換する関数です。
- HTMLの”name”がキーに”value”が要素になります。
- HTMLで”name”と”value”をセットしないとこの関数は動作しません。
- 38から45行:LEDボタンの処理
- HTMLのname='btn0'が押されるとここが実行されます。
- 操作の内容はGPIOの管理です。
- 47から50行:現在P時間の保存(Pthonの関数を使用)
- HTMLのname='btn1'が押されるとここが実行されます。
- ユーザが宣言した関数get_time()が実行されます
- 現在の時間を取得し"time.txt"に保存します。
- 52から55行:ファイルリストの作製(Linuxのコマンドを使用)
- HTMLのname='m_dir'がクリックされるとここが実行します。
- Linuxのコマンドを使用して現在の時間とホームディレクトリの内容を"file_list.txt"に保存
まとめ
Python Http-Serverの利点は以下の通り。
- GPIOの制御が簡単に出来る
- Pythonの関数またはユーザが定義した関数が使える
- Linuxのコマンドも使用出来る。
次回は
開発途中でHTTPではなくHTTPSのサーバの使用を求められる事が有ります。 次回はHTTPS(SSL)サーバについて説明します。