#author("2018-07-24T02:18:37+00:00","ocha","ocha")
#author("2018-11-11T11:05:48+00:00","ocha","ocha")
このページの内容は初代Raspberry piのRaspbian GNU/Linux 9.4で動かしました。

*CherrypyをRaspberrypiにインストールしてGPIOを使う [#jf437582]

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

**Cherrypyで何ができる? [#rb2aa220]

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

**インストール方法 [#d6b28289]

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

- http://kzky.hatenablog.com/entry/2014/11/08/CherryPyまとめ

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

 $ sudo apt-get install python-cherrypy3

*文字を返すだけのwebサーバを作る [#k890ec59]

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

**簡単なサンプル [#yd36e53b]

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

- https://ja.wikipedia.org/wiki/CherryPy

 #!/usr/bin/env python
 
 import cherrypy
 
 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


**コマンドを増やす [#kbfe9936]

コマンドというか、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!

**引数を増やす [#h8138de4]

?で引数を増やすには以下のようにします。例えば、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を接続する [#a69582ed]

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の両方に対応している [#yd3b0cd3]

ところで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