このページの内容は初代Raspberry piのRaspbian GNU/Linux 9.4で動かしました。

CherrypyをRaspberrypiにインストールしてGPIOを使う

RaspberryPi?のGPIOをpythonから使うのは簡単です。Lチカは簡単にできます。だとすると 次に、これをネットワーク越しに実現したいところです。それもできればhttpでコントロールできたら色々便利。 そこで、ネットワーク越しに別のマシンからGPIOを操る方法を探しました。 Pythonでwebサーバを簡単に作れるフレームワークがあるらしいので、それを使ってみました。

Cherrypyで何ができる?

  • Pythonで書いたwebサーバが簡単に作れる。
  • CGIとしても呼び出せるらしい。

インストール方法

インストール方法がこちらに書いてありました。

RaspberryPi?CherryPy?をインストールします。Rasbianが動いていれば、以下のapt-getで簡単にインストールできます。

$ sudo apt-get install python-cherrypy3

文字を返すだけのwebサーバを作る

まずは、文字を返すだけの簡単なプログラムから試して、動作を確認します。 サーバとして稼働するので、curlコマンドやwebブラウザで文字を取得できます。

簡単なサンプル

Wikipediaに書いてあった簡単な例です。

#!/usr/bin/env python

class HelloWorld(object):
    def index(self):
        return "Hello World!"
    index.exposed = True

cherrypy.quickstart(HelloWorld())

とても簡単。 class名はなんでも良いです。最後にそのクラス名をサーバとして稼働させます。

これを起動するとサーバとして動き出します。アドレスはデフォルトで、ローカルホストの8080。 同じマシンからcurlすると以下のようになります。

$ curl http://127.0.0.1:8080/index
Hello World!

indexは特別な名前で、省略することもできます。index.htmlみたいな位置付けです。

$ curl http://127.0.0.1:8080
Hello World!

他のマシンからも見られるようにするには、RaspberryPi?に割り当てたアドレスを使って公開すればよいです。デフォルトを変更するには、cherrypy.config.updateを使います。以下はアドレスが192.168.0.80の場合。

#!/usr/bin/env python
import cherrypy
cherrypy.config.update({'server.socket_host': '192.168.0.80',
                        'server.socket_port': 8080,
                       })

class HelloWorld(object):
    def index(self):
        return "Hello World!"
    index.exposed = True

cherrypy.quickstart(HelloWorld())

他のマシンからwebブラウザで見ると以下のようになります。

http://siio.jp/gyazo/4abd1abdfd32cca6141898fd51de66cd.png

コマンドを増やす

コマンドというか、webサーバでしたらhtmlファイル類を増やす方法です。例えばLEDという名前に反応するようにプログラムしてみます。

#!/usr/bin/env python
import cherrypy
cherrypy.config.update({'server.socket_host': '192.168.0.80',
                        'server.socket_port': 8080,
                       })
 
class HelloWorld(object):

    def LED(self):
        return "LED!"
    LED.exposed = True

    def index(self):
        return "Hello World!"
    index.exposed = True

cherrypy.quickstart(HelloWorld())

これでいろんなコマンドが使えます。上記の例では、以下のように動きます。

$ curl 192.168.0.80:8080/LED
LED!

引数を増やす

?で引数を増やすには以下のようにします。例えば、LED?turn=onなどに対応させてみます。def宣言の引数にturnを追加すれば良いです。これに=の右側の文字が入っています。

#!/usr/bin/env python
import cherrypy
cherrypy.config.update({'server.socket_host': '192.168.0.80',
                        'server.socket_port': 8080,
                       })
 
class HelloWorld(object):

    def LED(self,turn):
        if turn == "on":
            return "LED ON"
        if turn == "off":
            return "LED OFF"
    LED.exposed = True

    def index(self):
        return "Hello World!"
    index.exposed = True

cherrypy.quickstart(HelloWorld())

結果はこうなります。

$ curl 192.168.0.80:8080/LED?turn=on
LED ON
$ curl 192.168.0.80:8080/LED?turn=off
LED OFF

GPIOを接続する

GPIOの14番にLEDを接続しました。これでLチカをします。

http://siio.jp/gyazo/8c1345157378530d2f8490522dd556fd.png

GPIOを制御する関係のコマンドを追加します。エラーメッセージを出さない設定にしました。

#!/usr/bin/env python
import cherrypy
import RPi.GPIO as GPIO
cherrypy.config.update({'server.socket_host': '192.168.0.80',
                        'server.socket_port': 8080,
                       })

#dont bug me with warnings
GPIO.setwarnings(False)
# to use Raspberry Pi board pin numbers
GPIO.setmode(GPIO.BCM)
# set up GPIO output channels
GPIO.setup(14, GPIO.OUT)

class HelloWorld(object):

    def LED(self,turn):
        if turn == "on":
            GPIO.output(14, GPIO.HIGH)
            return "LED ON"
        if turn == "off":
            GPIO.output(14, GPIO.LOW)
            return "LED OFF"
    LED.exposed = True

    def index(self):
        return "Hello World!"
    index.exposed = True

cherrypy.quickstart(HelloWorld())

これを動かせば、以下のURLアクセスによりLEDがon/offします。

$ curl 192.168.0.80:8080/LED?turn=on
LED ON
$ curl 192.168.0.80:8080/LED?turn=off
LED OFF

一つのメソッドでGETとPOSTの両方に対応している

ところでwebサーバにアクセスするプロトコルにGETとPOSTがあるのをご存知でしょうか? (他にもあるらしいですが、ほとんど使われていないそうです)

上記の例で、

http://192.168.0.80:8080/LED?turn=on

というURLを使い、turn=onという情報をサーバに送りました。これがGETの方式です。 同じようにturn=onという情報をサーバに送るために、POSTプロトコルを使うこともできます。

GETプロトコルは、 元々はWEBサーバから情報を取得するための目的で作らました。なので名前がGETです。 GETで何かの情報をサーバに送付したい場合は、URLの中で、?に引き続き識別子=値という形で情報を送ります。 複数送る場合は&で区切って列挙します。 これで、本来のサーバからGETするという意味からかけ離れて、逆にサーバに情報を送りつける機能を実現しています。

一方で、サーバに情報を送りつける本来のプロトコルは、POSTです。

GETとかPOSTをするために最初に数行の「リクエストヘッダ」を送るのですが、 ヘッダの部分にはURLなどが書かれますので、GETの場合は、送るデータもヘッダに書かれます。 POSTの場合は、ヘッダの後に空行を置いて、その後に「リクエストボディ」を送ります。 例えば、URLの部分は、

http://192.168.0.80:8080/LED

にしておいて、リクエストヘッダの後に、空白行をおいた後の、リクエストボディに

turn=on

と書けば、上のGETの場合と同じデータを送ることができます。

現在では、GETもPOSTも、サーバ向けにデータを送る手法として使われています。

  • POSTの方が送付できるデータ容量が多い
  • POSTはデータが見えにくいので多少は安全
  • GETはテキストのみだけどPOSTはバイナリも送れる
  • GETはブックマークできて使いやすい

などの違いはあるものの、 少量 (2kB程度) のテキストデータを送る分にはどちらも可能です。

Cherrypyのすごいところは、このどちらにも対応しているところです。 なので、GET方式か、POST方式かということを悩む必要がなく、どちらも、上の例の

    def LED(self,turn):

で受け取れます。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-07-24 (火) 11:18:37 (21d)