WiringPi(2) CGI編

PythonのGPIOモジュールはルート権限でしか扱えず、Pythonの内蔵CGIサーバ機能はルート権限でスクリプトを実行できないので困ってしまい、ユーザ権限でもGPIOにアクセスできるWiringPiを試してみた。

事前にポートをexportしておく必要はあるが、これならCGIでも使えそうなことが分かった。と言うことで次は実際にRaspberry PiのGPIOに接続したLEDをOn/OffするCGIを作ってみる。

LED一個ではあまり面白くないので、今回はLEDを三個に増やしてGPIOの23~25に接続。ピンヘッダの番号で言うと16、18、22番になる。ピン番号の対応はこのページにある表が分かりやすい。コピーして保存しておくと良いだろう。

ブレッドボード上の配線はこんな感じ。スイッチは今回使わない。

ledbread

LEDのマイナス極(カソード)を電流制限抵抗(470Ω)経由でRaspberry Piのポートに接続してあるので、ポートに0を出力すると点灯、1を出力すると消灯する。一般的なOn/Offのイメージとは逆になるが、ピンに出力できる電流には制限があるので吸い込み電流で点灯させたほうが安全。

LED三個ぐらいなら吐き出し電流でも問題にならないが、負荷が大きくなると出力電圧が下がってしまう場合があるからだ。

WiringPiを使ったCGIプログラムは以下の通り

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Prepare:
#   gpio export 23 out
#   gpio export 24 out
#   gpio export 25 out

import cgi
import wiringpi

def imgbtn(no, onoff):
    img = ['../swon.jpg', '../swoff.jpg']
    name = ['L1', 'L2', 'L3']
    sw = ['ON', 'OFF']
    print '<input type="image" src="'+img[onoff]+'"',
    print 'style="border:none; background-color: #ffffff"', 
    print 'name="'+name[no]+sw[onoff]+'"',
    print 'value="submit" />'

if __name__ == '__main__':
    io = wiringpi.GPIO(wiringpi.GPIO.WPI_MODE_SYS)
    pins = [23, 24, 25]
    name = ['L1OFF', 'L2OFF', 'L3OFF', 'L1ON', 'L2ON', 'L3ON']
    hilo = [io.LOW, io.HIGH]    # HIGH:off,LOW:on
    [io.pinMode(pin,io.OUTPUT) for pin in pins]
    form = cgi.FieldStorage()
    for i in range(6):
        if form.getfirst(name[i]):
            no = i % 3
            onoff = i / 3
            io.digitalWrite(pins[no], hilo[onoff])
            break
    # html
    print \
'''Content-type: text/html; charset=UTF-8\n
<html>
<head>
<title>CGI Test</title>
</head>
<body bgcolor=#ffffff>
<div style="text-align:center">
<h1>LED Remote On/Off</h1>
<form action="wiringcgi.py" method="post">
''',
    for i in range(3):
        imgbtn(i, io.digitalRead(pins[i]))
    print \
'''</form>
</div>
</body>
</html>
'''

せっかくなのでフリー素材で適当なボタン画像を探してきて使った。
swon swoff

この画像ファイルとスクリプトを、以下のように配置する

.
├── cgi-bin
│   └── wiringcgi.py
├── swoff.jpg
└── swon.jpg

画像ファイルもスクリプトと同じ場所に置きたかったのだが、Pythonの内蔵CGIサーバはcgi-binフォルダにPythonスクリプト以外は置くことができないので、上の階層に置いた。

スクリプトファイル wiringcgi.py には、chmodコマンドで実行属性を付けておく。

$ chmod 755 wiringcgi.py

画像ファイルを置いたフォルダで、以下のようにポートのexportとCGIサーバの起動を行う

$ gpio export 23 out
$ gpio export 24 out
$ gpio export 25 out
$ python -m CGIHTTPServer

これで準備完了。ブラウザからRaspberry PiのIPアドレスと、スクリプトファイル名を http://192.168.1.9:8000/cgi-bin/wiringcgi.py と直接指定してアクセスすれば、以下のように表示されるはず。

ledremote

ボタンをクリックするとLEDがOn/Offされて、同時にボタン画像が切り替わればOK。

CGIスクリプトはプログラムがHTMLファイルを動的に生成する形になるので少しややこしいが、最終的にクライアントへ送信されるHTMLファイルは以下のような形になる。

<html>
<head>
<title>CGI Test</title>
</head>
<body bgcolor=#ffffff>
<div style="text-align:center">
<h1>LED Remote On/Off</h1>
<form action="wiringcgi.py" method="post">
<input type="image" src="../swoff.jpg" style="border:none; background-color: #ffffff" name="L1OFF" value="submit" />
<input type="image" src="../swoff.jpg" style="border:none; background-color: #ffffff" name="L2OFF" value="submit" />
<input type="image" src="../swoff.jpg" style="border:none; background-color: #ffffff" name="L3OFF" value="submit" />
</form>
</div>
</body>
</html>

スクリプトは出力ポートの現在値を読み取って、対応するボタンを持つHTMLファイルを生成。ブラウザで画面上のボタンがクリックされると、その情報をパラメータとして同じスクリプトが再度実行される。スクリプトはパラメータに従ってLEDのOn/Offを行い、またHTMLファイルを生成。
という手順で処理が続いていく事になる。

LEDが制御できれば、これを赤外線リモコンに替えてエアコンのリモート制御等も、理論的には可能になるはずだ。実際にやるとしたら他にも色々と考慮する必要があるが、何もない所から始めるよりもとりあえず動かせる状態にして、そこから考えるほうが近道。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中