前回は、HPのボタンを押してLEDをオンオフしました。今回は、Java Scriptを使用してLEDのオンオフに合わせてボタンの表示をON/OFFと切り替えてみます。
XMLHttpRequestを使用
現在の設定はサーバからクライアントにHTMLファイルを送ってホームページの画面を製作しています。この設定でボタンの表示文字を変更するには以下の2つが考えられます。
- HTMLファイルをボタンの状態に合わせて書き換えた後、クライアントに送る。
- HTMLファイルの内容を1行づつ送り、該当箇所に来たら書き換えたものを送る。
今回のHTMLファイルは小さいので上記2の方法でも良かったのですが、(ちなみに、2のケースは、ここでやった事が有ります) 今回はJavaScript関数、”XMLHttpRequest” を使う事にしました。XMLHttpRequestは、サーバ、クライアント間でデータの送受信を行う際に利用する関数です。状態に応じてどのタイミングでサーバーと通信するかを指定出来ます。
- readyState=0 : 状況=UNSENT: 初期状態(インスタンス作成)
- readyState=1 : 状況=OPENED: openメソッド実行
- readyState=2 : 状況=HEADERS_RECEIVED: レスポンスヘッダー受信
- readyState=3 : 状況=LOADING: データ受信中
- readyState=4 : 状況=DONE: リクエスト完了
今回は、”4”のリクエスト完了を指定しています。スクリプトファイル、”hello_server_04.js”は、こんな感じです
hello_server_04.js
var url = "http://raspberrypi.local:8080/?80=0";
var xhr = new XMLHttpRequest();
var str;
xhr.open('GET', url);
xhr.send();
xhr.onreadystatechange = function()
{
if(xhr.readyState === 4 && xhr.status === 200)
{
str = "OFF";
if(Number(xhr.responseText[0])) str = "ON";
document.getElementsByName('1')[0].innerHTML = str;
}
}
- 1行目:サーバのURLとリクエストする内容の設定。今回は、サーバーに80=0を送信。
- 2行目:XMLHttpRequest()を宣言
- 5,6行: これでサーバーにGETリクエストを行う。
- 8行目以降: ここからが通信の処理
- 10行目: if文以下が実行される条件
- readyStateが ”4” かつ、通信が正常に行えた(xhr.status === 200)時
- データは、responseText[]に取り込まれる。
- 13行目: ここで送られて来たデータを判断
- 15行目: 状態に合わせて、ボタンの表示を変更する。
- 10行目: if文以下が実行される条件
次は、これに対応するPython ファイル、”hello_04.py” の説明です。
hello_04.py
from http.server import HTTPServer, SimpleHTTPRequestHandler
from urllib.parse import urlparse,parse_qs
import RPi.GPIO as GPIO
btn_stat = 0
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
GPIO.output(17,0)
class MyHandler(SimpleHTTPRequestHandler):
def do_GET(self):
global btn_stat
fl = 1
if self.chk_file() == 0:
parsed = urlparse(self.path)
params = parse_qs(parsed.query)
a=next(iter(params))
#----- LED ON/OFF --------------
if a == "1":
if btn_stat == 0:
GPIO.output(17,1)
print("LED_On\n")
btn_stat = 1
else:
GPIO.output(17,0)
print("LED_Off\n")
btn_stat = 0
#----- Port Clear -----------------
elif a == "2":
GPIO.cleanup()
print("IO_Clear\n")
#----- Data transfer --------------
elif a == "80":
print("Data transfer\n")
self.send_response(200)
self.send_header('Content-type', "text/plain")
self.end_headers()
self.wfile.write(str(btn_stat).encode())
fl = 0
#-------------------------------------
else :
fl = 0
if fl == 1:
f = open("index_04.html",'rb')
self.send_response(200)
self.send_header('Content-type', "text/html")
self.end_headers()
self.wfile.write(f.read())
f.close()
#-------------------------------------------------
def chk_file(self):
a=0
if self.path == "/":
self.path = "/index_04.html"
dataType = "text/html"
a=1
if self.path.endswith(".css"):
dataType = "text/css"
a=1
if self.path.endswith(".js"):
dataType = "application/javascript"
a=1
if a == 1:
self.path = "." + self.path
f = open(self.path,'rb')
self.send_response(200)
self.send_header('Content-type', dataType)
self.end_headers()
self.wfile.write(f.read())
f.close()
return a
#---------------------------------------------------------
host = ''
port = 8080
httpd = HTTPServer((host, port), MyHandler)
print('serving at port', port)
httpd.serve_forever()
- 38行目から:—– Data transfer ————–
- 今回追加したクライアントからのリクエスト 80=0は、ここで処理されます。
- 44行: self.wfile.write(str(btn_stat).encode())
- btn_stat → ボタン状態を保持した変数。 0:オフ 1:オン
- str(btn_stat) → 数字を文字列に変換
- wfile.write(str(btn_stat).encode()) → 文字列をバイト単位に変換しクライアントに送信
- 送られるデータは数字では無く文字で、ボタンオンの場合:”1”。オフの場合:”0”。となる。
- 71,73行目: JavaScriptファイル(拡張子 ”.js”)に対応する為に追加。
最後にHTMLファイル、”index_04.html”です。
index_04.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_03.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='1' value='0' >On</button>
<button type='submit' name='2' value='0' >Clear</button>
</form>
</div>
</center>
<script src="http_server_04.js"></script>
</body>
</html>
19行目の、<script src=”http_server_04.js”></script> を追加しました。CSSファイル、”http_server_03.css”の変更有りません。
http_server_03.css
@charset "UTF-8";
.t_font {
font-size: 40px;
font-weight:bold;
font-style: italic;
color: #0ff;
}
.b_frame {
width: 400px;
background: #363636;
padding: 15px;
border-radius: 10px;
margin-top: -30px;
margin-right: 10px;
}
button {
display: block;
margin: 10px;
line-height: 50px;
cursor: pointer;
color: #fff;
background: #228b22;
border-radius: 10px;
font-size: 24px;
width:120px;
}
今回からファイルは4つです。
- hello_04.py: python本体
- index_04.html: HTMLファイル
- http_server_03.css CSSファイル
- hello_server_04.js: Java Scriptファイル
これら4つを同じフォルダーに入れて、python を実行して下さい。
ブラウザに、”raspberrypi.local:8080”と入力すれば、HPが表示されます。
たった数行のHTTPサーバですが、Java Scriptもしっかり動きます。次回は、温度を測定して値を表示する機能を付けます。