Raspberry PIに軽量webサーバーを入れる

ロボット

ラズパイにwebからアクセスして、GPIOの状況を見たり設定したいとする。

多くの人がwebiopiに走るようだ。
しかし、このパッケージは使わないことにした。
理由はwebiopiは便利にできていて、webサーバーを兼ねてくれている。
自分でページを作ったり、そこにjavascriptを動かそうとすると、結構、調べなければならない。
しかも開発は7年前に止まっている。

いろいろ考えたが、webサーバーを動かしてCGIをpythonで書くということにする。CGIは別にPearlやPHPだけがつながるわけじゃない。Common Gateway Interfaceで様々な言語環境でプログラムを書いてかまわない。

軽量ウェブサーバーの導入

sudo apt install lighttpd

軽量なだけに、不要なモジュールは最初は動いていない。
状況は

sudo lighttpd-enable-mod

で調べられる。

動かしたいモジュールを

sudo lighttpd-enable-mod cgi

とする。

設定を反映し、スタートする。

sudo sytemctl restart lighttpd

起動したらlighthttpdを動かしたいので、

systemctl enable lighttopd.service

(やめたい時は、systemctl disable lighttpd.service)

設定ファイルは/etc/lighttpd/lighttpd.conf

なかにserver.document-rootがあるので適当に自分がドキュメントルートを起きたいフォルダーを指定。

cgiでpythonを起動させるには/etc/lighttpd/conf-availabe/10-cgi.confを設定する。

中を読めばわかるけど、

$HTTP["url"]=~ "^/cgi-bin/"{ cgi.assign = ( ".py" => "/usr/bin/python" )  alias.url += ("/cgi-bin" => "usr/...../cgi-bin/") }

とか設定する。
ここでpythonの実行ファイル、/cgi-bin/とブラウザーから要求された時の真のフォルダー名を設定する。つまりhtml内に/cgi-bin/と書くが、その本当の場所はここで決まる。

普通、CGIはドキュメントルート下のサブフォルダーCGI-binとする。

ドキュメントルートに以下のhtmlをindex.htmlとして置いてみた。

<!DOCTYPE html><html><head>
<meta charset="utf-8">
<title>index</title></head><body>  
<form action="/cgi-bin/formtest1.py" method="post">  
<input type="text" name="value1"><BR />  
<input type="text" name="value2"><BR />  
<input type="submit" name="submit">  
</form>
</body>
</html>

cgiプログラムはformtest1.py

#!/usr/bin/python3

import cgi
import cgitb # for debug

cgitb.enable() # for debug

form = cgi.FieldStorage() # get data from form
value1 = form.getvalue('value1','') 
value2 = form.getvalue('value2','') 

print('Content-Type: text/html; charset=UTF-8\n')
html_body = '''
<!DOCTYPE html>
<html>
<body>
<h1>python cgi test</h1>
<p>value1 is %s</p>
<p>value2 is = %s</p>
</body>
</html>
''' 
print(html_body % (value1, value2))

pythonからGPIOを動かすためには、ROS2を使ってみる(1)で書いたpigpioの設定をする。

LEDを繋いだ。

CGIでGPIOをオンオフするサンプルHTML。チェックボックスをビジュアルにしているので長い。
Javascriptを入れてみたかったのだ。あしからず。


<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewpoint" content="width=device-width, initial-scale=1.0" />
<title>switch</title>
<style type="text/css">
<!--
.switch_label {
display: flex;
align-items: center;
}

input[type="checkbox"]{
position:absolute;
width: 0;
height: 0;
}
.base {
width: 56px;
border-radius: 16px;
height: 32px;
background-color: #ddd;
}
input:checked ~ .base{
background-color: rgb(219,234,254);
transition: 0.5s;
}

.title {
margin-left: 4px;
}
.circle {
position: absolute;
top: 4px;
left: 4px;
width: 24px;
height: 24px;
border-radius: 12px;
background-color: gray;
}

input:checked ~ .circle {
transform: translateX(100%);
backgound-color: blue;
}

.switch {
position: relative;
}

-->
</style>
<script>
const checkbox = document.getElementById('switch');
checkbox.addEventListener('click', () => {
const title = document.querySelector('.title');
title.textContent = checkbox.checked ? 'ON' : 'OFF' ;});
</script>
</head>
<body>
<h1>switch button</h1>
<form action="/cgi-bin/formcgi3.py" method="POST">
<label for="switch" class="switch_label">
<div class="switch">
<input type="checkbox" id="switch" name="onoff" />
<div class="circle"></div>
<div class="base"></div>
</div>
<span class="title">Off</span>
</label>
<input type="submit" vaalue="GO">
</form>
</body>
</html>

CGI(formcgi3.py)は以下のとおり

 
#!usr/bin/python3

import cgi
import cgitb
import pigpio

cgitb.enable()

pi = pigpio.pi()
pi.set_mode(21, pigpio.OUTPUT)

form = cgi.FieldStorage()

if (form.getvalue('onoff') ):
    pi.write(21, 1)
else:
    pi.write(21, 0)

  
print("Content-Type: text/html")
print()
htmlTxt = '''
<h1 > Done < /h1 >

'''
print(htmlTxt)

 

一応、動作は確認できた。