7. ウェブサーバーのセットアップ¶
この記事では、Pico Wをブラウザから回路を操作したり、センサーからの読み取りを取得できるウェブサーバーにする方法を学びます。
1. 必要なコンポーネント
このプロジェクトには、以下のコンポーネントが必要です。
一式を購入すると便利です。こちらがリンクです:
名前 |
このキットに含まれるアイテム |
リンク |
---|---|---|
ケプラーキット |
450+ |
以下のリンクから個別に購入することもできます。
SN |
コンポーネント |
数量 |
リンク |
---|---|---|---|
1 |
1 |
||
2 |
マイクロUSBケーブル |
1 |
|
3 |
1 |
||
4 |
数本 |
||
5 |
4(1-330Ω, 2-220Ω, 1-10KΩ) |
||
6 |
1 |
||
7 |
1 |
||
8 |
1 |
||
9 |
18650バッテリー |
1 |
|
10 |
バッテリーホルダー |
1 |
2. 回路を組み立てる
警告
図に示されている通り、Li-poチャージャーモジュールが接続されていることを確認してください。そうでないと、ショート回路が起きてバッテリーや回路が損傷する可能性があります。
3. コードを実行する
kepler-kit-main/iot
のパスの下にある7_web_page.py
ファイルを開きます。Run current script ボタンをクリックするか、F5キーを押して実行します。接続が成功すると、Pico WのIPが表示されます。
注釈
コードを実行する前に、Pico Wに
do_connect.py
とsecrets.py
スクリプトがあることを確認してください。もしなければ、 1. ネットワークへのアクセス を参照して作成してください。Pico WのIPアドレスをブラウザに入力して、このプロジェクトのために構築されたウェブページにアクセスします。任意のボタンをクリックして、RGB LEDの色を変更し、温度と湿度を更新します。
このスクリプトを起動できるようにしたい場合は、Raspberry Pi Pico Wに
main.py
として保存できます。
動作原理は?
アクセスしているウェブページは実際には何らかのサーバーでホストされており、そのサーバーのソケットが訪問時にウェブページを送信します。 ソケットとは、サーバーが接続を希望するクライアントを待ち受ける方法です。
このプロジェクトでは、Pico Wがサーバーであり、ブラウザを介してPico Wでホストされているウェブページにアクセスしています。
最初にソケットを作成します。これにはIPアドレスと port が必要です。 ネットワーク接続とIPの取得方法は、 1. ネットワークへのアクセス で説明されています。ポートには80を使用します。 ソケットの設定が完了したら、それを返して次のステップで使用します。
import socket
def open_socket(ip):
# ソケットを開く
address = (ip, 80)
connection = socket.socket()
connection.bind(address)
connection.listen(1)
print(connection)
return(connection)
次に、以前に設定したソケットを使用してウェブサービスを設定します。 以下のコードにより、Pico Wはブラウザからのアクセス要求を受け取ることができます。
def serve(connection):
while True:
client = connection.accept()[0]
request = client.recv(1024)
client.close()
次に、訪問者に送信するhtmlページが必要です。この例では、変数 html
に文字形式で単純なhtmlページを格納しています。
注釈
自分でhtmlを書きたい場合は、 HTML.COM でヘルプを得ることができます。
def webpage(value):
html = f"""
<!DOCTYPE html>
<html>
<body>
<form action="./red">
<input type="submit" value="red " />
</form>
<form action="./green">
<input type="submit" value="green" />
</form>
<form action="./blue">
<input type="submit" value="blue" />
</form>
<form action="./off">
<input type="submit" value="off" />
</form>
<p>温度は{value}度です</p>
</body>
</html>
"""
return html
訪問者にHTMLページを送信する。
def serve(connection):
while True:
client = connection.accept()[0]
request = client.recv(1024)
html = webpage(0)
client.send(html)
client.close()
上記の部分を組み合わせると、ブラウザでページにアクセスできます。効果を確認したい場合は、以下のコードをThonnyで実行してください。
import machine
import socket
from secrets import *
from do_connect import *
def webpage(value):
html = f"""
<!DOCTYPE html>
<html>
<body>
<form action="./red">
<input type="submit" value="赤" />
</form>
<form action="./green">
<input type="submit" value="緑" />
</form>
<form action="./blue">
<input type="submit" value="青" />
</form>
<form action="./off">
<input type="submit" value="オフ" />
</form>
<p>温度は{value}度です</p>
</body>
</html>
"""
return html
def open_socket(ip):
# ソケットを開く
address = (ip, 80)
connection = socket.socket()
connection.bind(address)
connection.listen(1)
print(connection)
return(connection)
def serve(connection):
while True:
client = connection.accept()[0]
request = client.recv(1024)
html = webpage(0)
client.send(html)
client.close()
try:
ip = do_connect()
if ip is not None:
connection = open_socket(ip)
serve(connection)
except KeyboardInterrupt:
machine.reset()
上記のコードを実行すると、ウェブページのみが表示され、RGB LEDの制御やセンサーの読み取りは許可されていないことがわかります。 このウェブサービスはさらに洗練される必要があります。
最初に知るべきことは、ブラウザがウェブページにアクセスしたときにサーバーが受け取る情報です。それゆえに、 serve()
をわずかに変更して request
を出力します。
def serve(connection):
while True:
client = connection.accept()[0]
request = client.recv(1024)
request = str(request)
print(request)
html = webpage(0)
client.send(html)
client.close()
スクリプトを再実行すると、シェルはウェブページでキーを押すときに以下のメッセージを出力します。
b'GET /red? HTTP/1.1\r\nHost: 192.168.18.162\r\nConnection: keep-alive.......q=0.5\r\n\r\n'
b'GET /favicon.ico HTTP/1.1\r\nHost: 192.168.18.162\r\nConnection: keep-alive.......q=0.5\r\n\r\n'
b'GET /blue? HTTP/1.1\r\nHost: 192.168.18.162\r\nConnection: keep-alive.......q=0.5\r\n\r\n'
b'GET /favicon.ico HTTP/1.1\r\nHost: 192.168.18.162\r\nConnection: keep-alive.......q=0.5\r\n\r\n'
読むには長すぎます!
しかし、実際に必要なのは /red?
や /blue?
の前にある小さな情報だけです。
これはどのボタンが押されたのかを教えてくれます。それで、キーストロークの情報を抽出するために serve()
を少し改良しました。
def serve(connection):
while True:
client = connection.accept()[0]
request = client.recv(1024)
request = str(request)
try:
request = request.split()[1]
except IndexError:
pass
print(request)
html = webpage(0)
client.send(html)
client.close()
プログラムを再実行すると、ウェブページでキーを押すと、シェルは以下のようなメッセージを出力します。
/red?
/favicon.ico
/blue?
/favicon.ico
/off?
/favicon.ico
次に、 request
の値に応じてRGB LEDの色を変更するだけです。
def serve(connection):
while True:
client = connection.accept()[0]
request = client.recv(1024)
request = str(request)
try:
request = request.split()[1]
except IndexError:
pass
print(request)
if request == '/off?':
red.low()
green.low()
blue.low()
elif request == '/red?':
red.high()
green.low()
blue.low()
elif request == '/green?':
red.low()
green.high()
blue.low()
elif request == '/blue?':
red.low()
green.low()
blue.high()
html = webpage(0)
client.send(html)
client.close()
最後に、ウェブページにサーミスターの値を表示する必要があります(サーミスターの使用方法の詳細については、 2.13 温度計 を参照してください)。
この部分は実際にはHTMLのテキストを修正することで実現されます。
webpage(value)
関数でパラメータを設定し、入力パラメータを変更するだけでウェブページに表示される数字を変更します。
def serve(connection):
while True:
client = connection.accept()[0]
request = client.recv(1024)
request = str(request)
try:
request = request.split()[1]
except IndexError:
pass
#print(request)
if request == '/off?':
red.low()
green.low()
blue.low()
elif request == '/red?':
red.high()
green.low()
blue.low()
elif request == '/green?':
red.low()
green.high()
blue.low()
elif request == '/blue?':
red.low()
green.low()
blue.high()
value = '%.2f' % temperature()
html = webpage(value)
client.send(html)
client.close()