Arduino Uno Qの利用 ⑦ 入門編 従来のArduinoと互換性を保ち新しい機能を追加されたArduino Uno Q<Blink LED with UIの処理の手順を確認>

 前回、サンプル・プログラム「Blink LED with UI」では、CPU側(QRB2210、Pythonなど側)とMPU側(STm32U585、スケッチ側)の分担、連携を説明しました。

 今回は「Blink LED with UI」の処理の手順を具体的に確認していきます。

 index.htmlとstyle.cssで指定されたWeb画面が表示され、表示画面の動きを分担するapp.js、全体の処理とArduinoのスケッチとの連携を分担するmain.py、スケッチのプログラムが展開されたのち初期化が行われ、開始画面が表示されます。

 「Blink LED with UI」では、マウスのクリックでLEDの状態が反転します。併せてWebブラウザの表示も反転します。これらの処理がどのように行われているのかを具体的に確認していきます。

起動した最初にmain.pyが読み込まれる

 最初にmain.pyのpythonのプログラムが読み込まれ、メモリに展開されます。  
  WebUI-HTMLのBrickの初期化を行います。Brickを仲介してWeb上のイベントを受け取り、必要に応じて表示の変更などを行う処理ができるようにします。

 ui.on_messageは、app.js側から呼び出された関数の文字列名と実際のmain.pyプログラム内の関数名とで関連付けます。これによりmain.pyとHTML/js側との間のプログラムが連携できるようになります。


#  WebUIの初期化(コメント行)
ui = WebUI() //
# マウスのクリックに対する対応、最初の状態の設定の連携を記述 
ui.on_message('toggle_led', toggle_led_state)
ui.on_message('get_initial_state', on_get_initial_state)
# Start the application
App.run()


 処理の終わりにはApp.run()でWebサーバを立ち上げます。サーバが起動するとWebUIウインドウが開きます。このウィンドウの表示はindex.htmlの記述に従います。


index.htmlが表示画面の構成を決めている

 Webブラウザに表示される画面は、index.htmlで基本的な構成が決められています。HTMLファイルの構成は次のようになります。

<!DOCTYPE html> HTML文書であることの宣言文
 <html lang="en">   HTML文書のはじめに<html>、終わりには</html>のタグ
   となる。
         lang="en”は英語で表記されていること示し、日本語の場合lang="ja”となる。
<head>     この<head>~</head>がヘッダ部で、文書についての記述となる。
         文字セット、画面の大きさ、タイトル、アイコンなど、この画面の修飾
        の情報を記述している文書などが指定されている。
</head>
<body>   この<body>~</body>に、画面に表示される内容が記述される。
       Linux Blinkの画面のタイトルとArduinoのアイコンの表示、
       LEDのON/OFFの表示およびON/OFFの指示を受けるボタンと、「Click to
    Controlboard's LED」の文とアイコンの表示を指定。
       body部の終わりには、この表示の動きなどを制御するjavascriptの
      ファイルの読み込みも指定されている。
</body>
</html>


 以上に示すように、上から順番に指示に従って必要な項目が表示されます。アイコン、タイトル、LEDのON/OFFのボタンなどが表示されます。
  </body>の前に記述されている<script ~ >のメッセージの段階になるとスクリプトが読み込まれ、app.jsの処理が開始します。


app.jsの役割

 最初にイベントが発生した時に対応するためのメソッドaddEventlistenerで、イベントが発生したときに処理される命令、または関数を指定します。以後、イベントの発生するごとに対応する処理が実行されます。

(1)イベント対応の処理を設定
 最初の処理は、Webページがロードされたことを検出したときに{ }で囲まれた範囲の命令が実行されます。最初のものはエラーが生じたときのための処理です。
  initSocketIO();で必要な初期化処理が実行されます。次のledButton.以下の命令で、マウスがクリックされたときにhandleledClick()関数が起動されます。

      // Start the application
      document.addEventListener('DOMContentLoaded', () => {
         errorContainer = document.getElementById('error-container');
         initSocketIO();
         ledButton.addEventListener('click', handleLedClick);
      });


 initSocketIO();でWebUI-HTMLとmain.pyとの接続を確立し、ソケットの接続を行います。
 次に、updateLedStatus()関数でLEDの点灯状態をmessageに取り出します。


(2)以後イベントの発生を待つ
 以後、LEDの点滅を制御するためのWebのLEDボタンがクリックされるのを待ちます。クリックされるとapp.jsのjavascriptのledButton.addEventListenerで設定されたapp.jsのhandleLEDLedClick()関数が起動されます。

 この関数はpythonのmain.pyのtoggle_led_state()関数を起動し、LEDの表示を指示するled_is_onの値を反転します。その後ブリッジ・ライブラリによりArduinoのボード上のLED状態を変えます。

 その後、get_led_status()でWeb上の表示をled_is_onの内容と一致させます。


実行の様子をコンソールにprintして確認する

 実行時の(1)、(2)動作を確認するためにmain.pyのプログラムの中に関数の実行場所が分かるようにprint命令を追加します。

 main.pyの最初の6行目の後にプログラムのスタートを示す「print("1","start")」命令を追加します。

① プログラムの開始時には次の追加された命令で、コンソールには 1 start が表示される。

from arduino.app_bricks.web_ui import WebUI
print("1","start")
# Global state

⓶ プログラム開始後、Webの画面がロードされた時にjavascriptで初期化処理の  on_get_initial_state()関数が起動されるので、この関数内に設定した  
 print("on_get_initial_state")の結果としてon_get_initial_stateが表示される。

"""Handle client request for initial LED state."""
    print("on_get_initial_state")
    ui.send_message('led_status_update', get_led_status(), client)


 続いてget_led_status()関数が呼び出され、コンソールにget_led_status、まだLEDは点灯していないのでFalseと表示される。

def get_led_status():
    print("get_led_status")
    print(led_is_on)


③  LED IS OFFと表示された画像をクリックすると、javascriptの設定でマウスのクリック動作が検出されhandleledClick()関数が呼びだされ、ここからmain.pyのtoggle_led経由でtoggle_led_status()関数が起動され、この関数がLEDのstatusを反転します。statusに応じて画面とLEDの状態が変更されます。


def toggle_led_state(client, data):
    """Toggle the LED state when receiving socket message."""
    global led_is_on
    led_is_on = not led_is_on


 ここまででstatusを反転、


 Bridge.call("set_led_state", led_is_on) ボードのLEDに反映
    print("toggle_led_state")


 この後、get_led_status()関数が呼び出され、画面の表示が変更されます。コンソールにはget_led_statusとTrueまたはFalseが表示されます。
  

①   1 start 
 初期化処理が行われる
②  on_get_initial_state
③  get_led_status
   False


 ここまでが初期化処理のon_get_initial_stateとget_led_statusの実行結果、まだマウスはクリックされていないのでLEDは消灯のままです。そのため led_is_on の値はFalseとなります。

 次はマウスをクリックした結果、
④   get_led_status
   True
 LEDは点灯する。再度マウスをクリックする
⑤  get_led_status
   False
 LEDは消灯する。再度マウスをクリックする
⑥  get_led_status
   True
 LEDは点灯する。


app.jsの実行状況をモニタする

 index.htmlで構成される画面の制御を、javascriptで記述されたapp.jsのプログラムが分担しています。その処理の実行の様子をconsole.log()関数で確認します。


イベントが生じたときに処理を実行する

 定数などの設定の後 // Start the applicationに続く命令の{  }の中には画面がロードされたイベント発生時に実行される命令がセットされています。app.jsのプログラムの中で最初に実行される部分です。
  この命令の中に、コンソールに「app.js start」を表示する console.log('app.js start');を追加しました。


 document.addEventListener('DOMContentLoaded', () => {
     errorContainer = document.getElementById('error-container');
     initSocketIO();
     ledButton.addEventListener('click', handleLedClick);
     console.log('app.js start');
 });


 この命令の中の ledButton.addEventListener('click', handleLedClick);が実行されると、以後マウスがクリックされたときにhandleledClick()関数が起動するようにセットされます。

マウスがクリックされたときに起動する関数

 Webのボタンがマウスでクリックされた時に起動する関数の起動時の ledTextの値を、コンソールに表示します。


function handleLedClick() {
    // Send toggle message to server via socket
    console.log("handleLedClick",ledText);


LEDの状態を反映する

 マウスがクリックされるとhandleLedClick() 関数が起動し、main.pyの toggle_led_state()関数でLEDの状態を示すled_is_onの値が反転します。その内容を次の関数でWebに反映します。


function updateLedStatus(status) {
    console.log("status",status);


 これらの関数に、コンソールに状況を示す console.log()関数を追加し実行した結果を次に示します。
  WebブラウザのChromeにLEDの点滅のアイコンを表示し合わせてコンソールにconsole.log()関数の出力も表示できるようにします。Chromeの右上の三つの点のメニューをクリックしリストから、

    その他のツール>デベロッパーツール

を選択すると、次に示すようになります。

 app.jsが起動しプログラムがメモリに展開しサーバにWebデータがロードされると、次の命令の矢印以降の{ }の中の命令が実行されます。

  document.addEventListener('DOMContentLoaded', () => { }

 その実行結果が上の図の中間部分の app.js start の表示です。
 マウスをクリックするごとに handleledClickとStatusの行が追加されます。開始時はfalseで最初のマウスのクリックでtrueに変わり、以後繰り返します。

神崎 康宏

前へ

Arduino Uno Qの利用 ⑥ 入門編 従来のArduinoと互換性を保ち新しい機能を追加されたArduino Uno Q<Blink LED with UIの各要素の関係 >