ブラウザから変数の値を書き換えると便利だけど。。。
IoT機器を使った開発では、センサーの値だけでなく、設定値やメッセージなどを「Webから書き換えられる仕組み」があると便利です。
この記事では、UIFlow2を使って簡単なWebサーバーを構築し、ブラウザ経由で変数を更新する方法を解説していきます。
Webサーバー(変数書き換え)のフロー

プログラムの流れは次の通りです。
Setupブロック
- 変数を定義(関数:SetVariables)
- WiFiに接続(関数:ConnectWiFi)
- config.jsonの読み込み(関数:ReadConfig)
- config.jsonの内容を変数をセット(関数:SetConfig)
- htmlファイルの読み込み(関数:ReadHtml)
- Tcpサーバーの設定(TCP server start)
- ブロッキングモードの設定
Loopブロック
- Webサイトの表示(関数:WebServer)
- ディスプレイに変数の内容を表示
- 100msecで繰り返し
画面表示

WebServer(変数表示)の実行結果
M5StackのIPアドレスにアクセスすると、設定画面が表示されます。
値を入力して変更をクリックすると、変更が反映されます。

ブラウザで値を変更すると、ディスプレイの表示に変更が反映されます。

Webサーバー(変数を表示)フローの詳細
Setupブロックの詳細

関数:SetVariables

ネットワーク関連の変数 に初期値を設定します。
ネットワーク関連の変数には、それぞれの環境に応じたパラメータを設定してください。
関数:ConnectWiFi
WiFiに接続する処理を行います。

このフローの詳細についてはこちらの記事を参考にしてください。
関数:ReadConfig

ファイルconfig.jsonを開いて、json文字列を変数 config_jsonに保存します。
config_jsonをmapに変換して、config_mapに保存します。
config.jsonの内容は次の通り。
{
"last_name": "Yamada",
"first_name": "Taro",
"age": "45"
}config.jsonをVisual Studio Codeなどのエディターで編集した後、M5Stackのフラッシュメモリに転送します。
詳しい方法はこちらの記事を参考にしてください。
関連記事
UIFlow2:WebServerの作り方 その1(基本編)
関数:SetConfig

Map変数 config_mapから、変数 last_name、first_name、age に値を代入します。
関数:ReadHtml

ファイル index.htmlを読み込んで、変数 htmlに保存します。
index.htmlの内容は次の通り
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Config M5</h1>
<form method="GET" action="/submit">
<p>Last Name:<input type="text" name="last_name" value="{{last_name}}" /></p>
<p>First Name:<input type="text" name="first_name" value="{{first_name}}" /></p>
<p>age:<input type="text" name="age" value="{{age}}" /></p>
<input type="submit" value="変更" />
</form>
</body>
</html>index.html をVisual Studio Codeなどのエディターで編集した後、M5Stackのフラッシュメモリに転送します。
TCP server start
TCP server start ブロックに値を設定して、TCP server をスタートさせます。

- IP address : TCPサーバーのIPアドレス(M5StackのIPアドレス)
- port : 通常は80番を使用
- listen : 接続できるクライアントの数
TCP serverのブロッキングモードは False にします。(デフォルトは true )
Loopブロックの詳細

関数:WebServerで、Web Serverの処理を行います。
ブロッキングモードはFalse(ノンブロッキングモード)としたため、Tryの中で関数 Web Serverを実行します。
ノンブロッキングモードなので、Web表示と、ディスプレイの表示は平行して実行することが可能です。
ブロッキングモードの詳細についてはこちらの記事を参考にしてください。
関連記事
UIFlow2:WebServerの作り方 その2|変数の値を表示
画面表示
ディスプレイに、変数の値を表示します。

- lbl_last_name: Last Name 表示用ラベル
- lbl_first_name: First Name 表示用ラベル
- lbl_age: age(年齢)表示用ラベル
関数:WebServer

関数 WebServerは少し複雑なので、がんばって理解しましょう。
関数前半の部分では、TCPサーバーを立てて、クライアントから接続されるのを待ち、接続されたらメッセージを受信します。

メッセージを受信すると、conn_info には、新しいソケットとクライアントアドレス情報のペア(client_socket , client_address)が入ります。
client_socket は接続されたクライアントとの通信に使うソケットオブジェクトです。
このソケットを使ってデータの送受信を行います。

このブロックでクライアントからデータを受信します。(バイナリ形式)
はバイナリデータを文字列に変換します。
変数 request には、クライアントが送ってきたテキストが文字列として格納されます。

これは、request の文字列の中に "/submit" が含まれる場合の処理です。
今回の記事のキモになる部分ですので、後で詳しく解説します。

関数 RenderHtml で、クライアントに送信するHTMLを生成して変数 rendered_html に保存します。
その後、rendered_html をクライアントに送信してソケットをCloseして終了します。
関数:RenderHtml

元になるHTMLの中の、{{last_name}}、{{first_name}}、{{age}} を、変数の値で置き換えます。
変数の値に置き換えた結果を 変数rendered_html に保存します。
HTTPリクエストから設定情報を抽出する
関数 ExecuteQuery

関数 ExecuteQuery では、HTTPリクエストからクエリパラメータを解析して、設定情報として保存し、変数に保存する処理を行っています。
Pythonコードで記述したほうがスッキリしますが、ここでは、UIFlowのブロックを使ってクエリの解析処理を行ってみましょう。
まず、クライアントからWeb画面の変更ボタンをクリックすると次のようなリクエストがサーバーに届きます。

GET /submit?last_name=Yamada&first_name=Taro&age=45 HTTP/1.1
request文字列から、" " (半角スペース)区切りに分けて、2番目の要素 /submit?last_name=Yamada&first_name=Taro&age=45 を path に格納します。

文字列 path から"?"で区切って、2番目の要素 last_name=Yamada&first_name=Taro&age=45 を queryに格納します。

query から "&" で区切って、リストに分解したものを params に格納します。
['last_name=Yamada' , 'first_name=Taro' , 'age=45']

config_map(Map型)を初期化します。
クエリで渡された設定値をここに格納していきます。

ここで、パラメータを1つずつ処理していきます。
['last_name=Yamada' , 'first_name=Taro' , 'age=45']
パラメータを key と value に分けて、マップに加えていきます。
config_map には 次の値が格納されます。
{'last_name': 'Yamada', 'age': '45', 'first_name': 'Taro'}

jsonファイルに保存するための前処理として、mapをjson文字列に変換します。
{"last_name": "Yamada", "age": "45", "first_name": "Taro"}
関数 WriteConfig

config_json の内容を フラッシュメモリのconfig.json に保存します。
関数 SetConfig

Setupブロックでも実行した関数です。
config_map から、それぞれの変数に値を格納します。
変数の値を変更するWebServer 実行結果
M5StackでWebサーバーを構築して、変数の値をブラウザから変更する方法を解説しました。
ただし、記事内のHTMLは必要最低限の内容なので、デザインがあまりよくありませんでした。
index.htmlの内容に、CSSを加えることで下記のような見栄えのよい設定画面も作ることが可能です。

CSS装飾を加えたHTMLの例
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Config M5</title>
<style>
body {
font-family: sans-serif;
padding: 20px;
background: #f5f5f5;
}
form {
background: #fff;
padding: 15px;
border-radius: 8px;
max-width: 400px;
margin: auto;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
input[type="text"],
input[type="password"],
input[type="number"] {
width: 100%;
padding: 10px;
margin: 8px 0;
border: 1px solid #ccc;
border-radius: 6px;
box-sizing: border-box;
font-size: 16px;
}
input[type="submit"],
button[type="submit"] {
width: 100%;
background-color: #007bff;
color: white;
padding: 10px;
margin-top: 12px;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
}
input[type="submit"]:hover,
button[type="submit"]:hover {
background-color: #0056b3;
}
p {
margin-bottom: 12px;
}
h1 {
text-align: center;
}
</style>
</head>
<body>
<h1>Config M5</h1>
<form method="GET" action="/submit">
<p>Last Name:<input type="text" name="last_name" value="{{last_name}}" /></p>
<p>First Name:<input type="text" name="first_name" value="{{first_name}}" /></p>
<p>Age:<input type="text" name="age" value="{{age}}" /></p>
<input type="submit" value="変更" />
</form>
</body>
</html>
WebServerの作り方 その3|Webから変数を書き換える まとめ
今回は、WebからM5Stack内部の変数を書き換える方法をご紹介しました。
この方法は、M5StackをIoTデバイスとして活用する際に、様々な設定値をWebから変更できるようになるため、実際にとても役に立つテクニックです。
UIFlowとM5Stackの組み合わせで、本格的なIoT機器を作ることも夢ではありません。
この記事がお役に立てれば幸いです。