#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): で受け取れます。