HOME  >>  LED電子工作集 > R-7 WebIOPiを用いたPCやスマホとの連携

R-7 WebIOPiを用いたPCやスマホとの連携

■ はじめに

 今、RaspberryPiに挑戦している。 今回は、いよいよスマホやPCから制御する方法を勉強する。 鉄道模型でのリモート・コントロールやデータ収集などの夢を描きながら勉強することにしよう。

 

■ 演習12: ブラウザのボタンによるLEDの点灯

 教則本の9章ではWebIOPiを用いたPCやスマホとの連携について説明されています。 これはラズパイを WEB サーバーに仕立て、クライアントであるPCやスマホから、HTTPプロトコルを使ってアクセスし、ラズパイと連携を取ろうとするシステムと解釈している。 そこで教則本の説明に従って、 WEB サーバーを立ち上げる作業を実施した。 作業はやや面倒であったが、問題無く設定することが出来た。

 最初のデモアプリケーションも無事クリアー出来たので、9.3章のブラウザのボタンによるLED点灯の演習を実施した。 この演習も指示通りに実施出来、さらにプログラムの解説を読んだが、いまいち理解できないでいた。

 そこで、関係するファイル関係を探し、その関係を自分なりに解釈してみた。 今までの知識や関係するファイルから考察して、下の図に示すような関係があると解釈した。 これは自分なりに解釈したものなので間違っていかも知れないが、ご容赦ください。

 

********** 以下の部分について、お詫びして訂正させていただきます。 *******************************

 やはり間違えていましたね。    ( 間違えていた模式図 )

 その理由は、表示されているページを保存してみると、下のように JavaScript ファイルも保存されていたからです。 PCにダウンロードされていたと解釈します。

 でも、ga.js.や jquery.js と言ったファイルも一緒にダウンロードされていますし、 Python ファイルである script.py とどうやって連携するのかが、理解できていません。 従って下記の記述も間違っているはずですので、信用しないでください。

 理解出来た時点で訂正いたしますので、ご容赦ください。

 ********************************************************************************************************

修正後の模式図

 メインになっているHTMLファイルとスタイルシートは、何時も記述しているこのホームページでも活用しているので理解できる。 また、Pythonファイルは、今勉強しているラズパイの制御のためのプログラムファイルである。 そして、このHTMLファイルとPythonファイルを結び付けているのが、JavaScript ファイルなのだ。 この何種類かあるJavaScript ファイルはパソコンにダウンロードされ、パソコン上で実行される。

 このJavaScript はホームページの勉強を始めた時にもお目にかかった言語であるが、ホームページにダイナミックな動きを付与する手段に使用していた。 例えば、マウスを当てると色が変わるとか、クリックすると何かが動き出しなどの細工を学んだ事がある。 しかし、習ったのはHTMLファイル内に記述する簡単なものであった。

 普通、HTMLファイルはWEBサーバーからPCにダウンロードしてPC 内で実行されると考えているのだが、LED の点灯・消灯はサーバー側で実行されるので、その間のやり取りはどうやっているのか不思議である。

 そこで、まず、このWeb サーバーのファイル構成をさばくってみた。 その結果を左に示す。

 最初のデモアプリケーションで示された WebIOPi のトップ画面 (教則本のP231) を表示するHTMLファイルの位置より、 htdocs のフォルダーがホームディレクトリーと解釈できた。 http://raspberrypi.local:8000/ によってここに飛んでくるのである。

 なお、自分のパソコンには、iTunes がインストールされているので、このアドレス表記が使用できるのだ!

 さて、9.3章のブラウザのボタンによるLED点灯の演習では、ここの /bb/01/ フォルダに飛んでくるので、ここの index.html ファイルを表示することになる。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no"
<title>1 - LEDの点灯制御</title>
<script src="js/require.js"></script>
<script>
require(["/webiopi.js", "javascript.js"], function(){
webiopi().ready( initialize_webiopi );
});
</script>

</head>
<body>

<p>下のボタンを押すごとに、LEDの点灯状態が変化します。</p>

<div align="center">
<button id="gpio25" onClick="toggleLED(25)">LED</button>
</div>

</body>
</html>

 その時のパソコン画面を上に示す。 そして、このファイルの内容を右に示す。 注目する部分を赤字で示すが、 ボタンとそのアクションについては、 onClick によって toggleLED(25) を実行せよとの命令と解釈する。

 しかし、toggleLED(25) の命令をどうやって実行するのか、このファイルやスタイルシートには一切記載されていない。 それは、<script>の部分で指定されているはずである。 そこで、ここに記されている複数の js ファイルを探してみることにした。

 require.jswebiopi.js については、ゴチャゴチャと呪文がいっぱい記されていてさっぱり理解できなかった。

 javascript.js には、教則本でも解説されているが、 toggleLED(25) を起動せよとの内容が記されであり、その命令内容は Python ファイルである script.py に指定されている。 要するに、GPIO 命令を実行する script.py とPC画面を記述している index.html との間を、この js ファイルが取り持っているようである。 さらに require.js と webiopi.js については、アンタッチャブル・ゾーンのようなので、各例題ごとにフォルダに収められている javascript.js がテーマに応じた記述がなされているものと判断される。

 なお、他の例題での記述内容より、 require.js と webiopi.js のファイルは、 WebIOPi に関係するものと解釈できるので、専門家が記述したモジュールであるので、ここは「おまじない」として理解しておこう。

 このコマンドの流れを整理しておく。 これも自分が勝手に解釈したものであるので、間違いがある場合はご容赦ください。

  1. PC画面上でボタンをクリックする。
  2. onClick のイベントによって、 toggleLED(25) を実行せよとの scriput 命令が発せられる。
  3. javascript.js の記述によって toggleLED(25) を実行するが、まず Python ファイルにて記述している toggleLED と言うマクロを呼び出して、それを実行させた後、返信されたデータをもとに、後処理として、changeButtonColor を実行するようにセットする。
  4. マクロ実行の指示を受けた script.py は、GPIO25の HIGH と LOW を反転させた後、その状態を javascript.js に返信してくる。
  5. javascript.js は後処理として、PC画面の表示を変更する。

 PC上の index.html と、ラズパイ上の script.py は直接的には連携出来ないので、JavaScriput の仕掛けを活用するものと理解しておこう。

 なお、この連携方法の解析には、Webブラウザで Raspberry Pi からの情報を受け取る(WebIOPi利用)を参考にさせて頂きました。

 

■ 演習13: ブラウザへの温度センサの値の表示

***** (1) index.html *******************
<div align="center">
温度: <input type="text" id="temp_text">
</div> ***** (2) javascript.js *************** function initialize_webiopi(){
getTempPeriodic(2000); } function getTempPeriodic(millis){
var drawTemp = function(macro, args, response){
var temp = response;
$("#temp_text").val(temp);
} webiopi().callMacro("getTemp", [], drawTemp); setTimeout(function(){getTempPeriodic(millis);}, millis); } ***** (3) script.py ******************* import threading
------------ def getTempLoop():
while True:
global temp
try:
temp = read_adt7410()
except IOError:
pass
webiopi.sleep(1)
t = threading.Thread(target=getTempLoop)
t.start()
@webiopi.macro
def getTemp():
return temp

 教則本の9.4章では、ブラウザへ温度センサの値を表示する場合の演習が説明されてます。 これも説明に従って実行したが、温度表示は空欄のままであった。 パソコン画面には表示欄が表示されているので設定は間違いないと戸惑っていたが、I2Cセンサのアドレスを変更していることに気が付いた。 「R- 4 I2C通信の演習」参照。

 そこで、script.py の中の記述を

 0x48 ⇒ 0x49

に変更して走らせた。 その結果を下に示す。

 我が iPhone には、送信されてきた右のセンサからの温度データを1秒毎に送信してきました。

 今回もコマンドの流れを追ってみます。 このための手順を簡単に紹介いたします。 まず、関係するファイルをテキストエディタで開き、それをファイル共有フォルダの中にテキストファイルとして保存します。 この時、改行記号の設定を CR+LF に変更します。

 このファイルをパソコン側からメモ帳で開き、プリントアウトした印刷物を眺めながら、関数宣言や初期設定などをサインペンで印をつけて、関係するコマンドを探して行きました。 その結果、特にメインルートとして関係する部分を取り出したものを右に記述します。

 1) HTMLファイルの仕事: index.html 画面の表示、
ラズパイから送られてくる温度データ temp の値を表示するだけですから、簡単なテキストボックスの記述しかありません。 ではどうやってそのデータは送られてくるのでしょうか。
 2)JavaScriput の仕事: javascript.js データの受け渡し
どうやら drawTemp の関数の中の、$("#temp_text").val(temp); コマンドによって、temp データをPCに指示しているものと解釈します。そしてこの関数は、webiopi().callMacro("getTemp", [], drawTemp); によって、マクロ getTemp の実施後に実行される。 さらに、これらを実行する関数 getTempPeriodic() は2000ミリ秒ごとに実行するようにセットされています。
 3) Python の仕事: script.py 温度測定の実施
JavaScriput から呼び出された、マクロ getTemp は、保管していた temp データを単に返事しているだけです。 return temp 。 しかしこの temp データは、getTempLoop() によって1秒ごとに温度センサの値をI2C 通信によって取得し、最新データを保管しています。

 このようにして、作動していることが理解できたのですが、threading.Thread と言う不思議なコマンドに出会いました。 なんだろう このコマンドは? 一定時間毎に処理されるとのことらしいが・・・・・・・・。

 そこで、ネットで検索すると、なんでも ”並列処理” 命令とか! 並列処理という言葉に敏感に反応してしまいました。 先回苦労した踏切モデルでのレーバーの上げ下げと警報機の点滅の二つの動作が、簡単に並列処理できるのでは・・・・? と思ったのです。 そこで解説文を勇んで読んでみたのですが、難しくてさっぱりわかりませんでした。 簡単な実施例があればと探してみることにしましょう。

 もう一つ、@webiopi.macro と記述されている部分について、@の意味が分かりませんでした。 これはデコレータと言われもので、関数を実行する前後に特殊な処理を実行したい場合に支持される関数を指定するそうです。 その内容は、 Python入門 - 関数 を参考にさせて頂きました。  即ち、 getTemp() を実行する前後に、webiopi.macro と言う関数を実行せよとの意味の様です。 この関数は webiopi が マクロ処置を実行するための手順や処理内容を記述しているものと解釈しますが、そこまで追及する意欲がありませんでした。 またまた、おまじないとしておきます。

  ****************  続く  **************************