IoT何をいまさら(23) PythonとBottleで通信相手を作る

前回はマイコン(ノード側)の通信テストの相手にするために、Raspberry Piを使おうと思い立ち、Raspberry Piを「数年ぶりの再稼働」いたしました。数年ぶりともなると溜まるものが溜まっています。ファイルの更新作業だけで夜中までかかってしまいました。ようやく今回から、Raspberry Pi上に「テスト用のサーバーもどき」を作り始めたいと思います。お手軽重視なので、簡単に作れるものが良いな~と探したところ

Python上で動作するBottleというフレームワークが良さげ

ではないかなと考えました。Pythonでしたら普段から使っているので(Python使いの人のPythonらしいPythonコードには未だに慣れず、ごくごく普通な書き方をしておりますが)何かとお手軽。

まずは、Bottleのご本家へのリンクを貼り付けておきます。

Bottle: Python Web Framework

このフレームワークのまず良いところは、

  1. Pythonの標準ライブラリだけで動く(Python2.7でも3xでもOK)
  2. 必須のファイルが少ない。bottle.pyという1ファイルで動くみたい

インストールは、pythonの標準的なインストール管理ツールだと思うpipを使えば最新の「安定版」がインストールされる、wgetで1ファイルを作業ディレクトリにダウンロードする場合は、(unstable)な最新版になるとのこと。前回、この辺でちとポリシーと異なる作業をしてしまったので、今回はちゃんとインストールの指示を守ります。

$ sudo pip install bottle

当然ですが、特に問題もなく直ぐにbottle使えるようになりました。なお、上記のホームページのTutorialとかUSER’S GUIDEはなかなか充実していて、virtualenv使って個人ごとにインストールする場合にはこうしろ、とかまで書いてくれています。raspberry pi ではvenvとか使っていないので、スルーですが。

インストールすると即座に Tutorialに書かれている”HELLO WORLD”以下のサンプルを試してみることができます。書き込むスクリプトファイルの名前はなんでも良いようです。例えば xxx.py ならば

$ python xxx.py

でサーバーが立ち上がります。ただし、Tutorialのサンプルは、皆localhost上で動作するように書かれているので、私の場合のように別マシンの仮想端末からアクセスしているときは自分の手元のマシン上のブラウザで操作できず不便です。localhostのところを、サーバー機のIPアドレス(複数のNICがある時はどれかを指定)で置き換えるか、

0.0.0.0

として、全てのNICを指定することになります。この0.0.0.0はちょっと過激ですが、どのマシンに持って行っても同じソースで動くので便利かもしれません。また、デバッグモードで動かすと、エラーが発生したときにいろいろ詳細情報をブラウザ側に表示してくれるので便利です。ただし、公開するときはデバッグモードで動かすなよ、と当然ですが警告書いてあります。そんなこんなで、サーバーを起動するrunのところをmain関数の末尾に置き、以下のようにしました。

なお、コマンドライン引数の処理には標準モジュールの argparse を使っています。htmlサーバーのデフォルトポート番号は別に使っているものがいるのでここでは避けています。この場合、ブラウザからこれにアクセスするときはポート番号指定しないとなりません。

Bottle自体は、特に初期化的なことをせずとも、ルーティングを指定して関数をずらずらと書いておくだけで、ルーティング指定のパスにアクセスすればその関数が勝手に走ってくれます。そこでデータベースなどの初期化などBottleの外の初期化にmain関数を使い、その末尾でrunするようにしてみました。チュートリアルを見ながら書いたスクリプトをraspberry  pi上で走らせると、こんな感じ。Bottle v0.12.16とある行以前は、こちらで書き込んだコードの出力で、下の3行はBottleから出力されている出力です。

ともかく、これでサーバーが待ち受け状態になったので、手元のブラウザから動かしてみます。

まずトップページへアクセス。ブラウザでソースコード表示にしてみました。

これ以上シンプルになりようもないソースコードが送られてきています。このトップページを生成しているコード部分はこちら。

上のrouteというデコレータで、ルートであるパスを示し、後はPython関数で表示する文字列を返しているだけ。極めてシンプル。同様な方法でページ階層を増やせますし、ソース内に文字列で書かずとも外部のファイルを送り出す関数もあります。

パスについては動的なものをサポートしていて、以下のようなコードを書けば、

/test/123

などというパスでアクセスすると最後の123が数値であれば、上の関数の引数であるidに、その値を入れてくれるということも可能。便利、便利。

データのPOSTであれば、Tutorialの真似をして以下のように書いてみます。

 

 

 

 

 

まず、/post_testにアクセスすれば、上の関数が動作して普通にhtmlフォームをブラウザに送り出すので、ブラウザに入力フィールドが現れます。submitボタンを押してフィールド内のデータが送信されると、こんどは下の方の関数が反応して、POSTされたデータを取得して変数に代入してくれます。変数に代入されてしまえば、後はPythonのコードでなんとでもなると。一応、最初の関数が動いたところのブラウザ画面。

 

 

 

次に、入力フィールドに文字列testSTRと打ち込んでGoボタンを押した後の画面。ちゃんと動作しています。

 

 

勿論、Pythonなのでデータベースへの接続も簡単です。テストに使うにはsqliteがお手軽でよいです。/dump_dbというパスにアクセスすると、データベースの中を全て表示する(といってもテスト用のレコード一つ入っているだけ)コードがこちら。

 

 

 

 

実行すると実に、味気ないPythonが機械的に文字列に変換している結果ですが、データベース内部のデータが表示されました。

 

 

ま、こんだけできれば、マイコンの通信テスト相手のサーバーにするには十分ですかね。後は、実際に作るだけ(といって、マイコン側から作らないとダメですがね。)

本格運用のサーバーを構築するとなると、Bottleのデフォルトであるシングルスレッドのテスト用サーバーでは間に合わないでしょうが、Bottle自体はバックエンドのサーバも複数選択可能な作りになっているようです。小規模、クローズドなアプリならこれ使っても結構なことができるようにも思われます。

IoT何をいまさら(22)Raspberry Pi再稼働で大慌て へ戻る

IoT何をいまさら(24)ST, VL53L0X  TOFセンサ へ進む