Ⅰ. ESP32によるWi-Fi通信とHTTPのおさらい

 今回の実験では、すでに作成済みの「計測用」と「監視用」の2つのデバイスを使用します。まだ準備できてなければ、『ESP32による近距離無線通信の実験① 準備作業編』にしたがって事前に作成して、開発環境の設定と必要なライブラリーのインストールを行ってください。
 これらの2つのデバイスは、いずれもWebサーバーとして動作させます。パソコンやスマートフォンのWebブラウザーからWi-Fi接続して、計測結果の表示やデバイスの制御を行います。


1.LANとWi-Fi通信

 このシリーズで取り上げているネットワークは、家庭やオフィス、工場などでの情報機器のネットワーク、つまり限られた範囲内のLAN(Local Area Network)を対象にしています。
 LANを構成する方法としてもっとも一般的なのは、モデムとパソコンなどをLANケーブルで接続した有線LAN(Wired LAN)です。イーサネット(Ethernet)とTCP/IPプロトコルを組み合わせたもので、IEEE802.3規格として策定されています。ケーブル接続のため設定が簡単、また電波のような干渉がないので安定した通信が可能であり、セキュリティ面でも比較的安全なネットワークといえます。
 その後、無線通信で接続する無線LAN(Wireless LAN)が登場して、IEEE802.11規格が定まり、業界団体のWi-Fi Allianceが製品間の相互接続性を認定することにより一気に普及が進みました。
 Wi-Fi通信をするためには、パソコンなどをWi-Fiルーターと無線接続します。ルーターには多くの通信規格のバリエーションがあり、使用する周波数と通信速度が異なっています。次の表はI-O DATAの「無線LAN規格の違い」から転載させていただきました。

 これからわかるように、2.4GHz帯の他に5GHz帯と60GHz帯を使用しています。2.4GHz帯は電子レンジやBluetoothなどの電波干渉を受けやすいが障害物に強い、5GHz帯は電波干渉が少なくて安定しているが障害物には弱い、60GHz帯は障害物にきわめて弱いが狭い範囲での高速通信向き、というような特徴があります。使用環境によって最適なものを選択する必要があります。
 最近では、最大通信速度が9.6Gbpsと超高速なIEEE 802.11ax規格の製品が出始めているようです。


2.ESP32のサーバー化

 Wi-Fi通信をするにあたって、ESP32はサーバーにもクライアントにもすることができます。例えば、計測用デバイスをクライアントとして動作させて、別に存在するサーバーに定期的にコンタクトして計測データを送信することができます。この機能はすでに『ESP32による近距離無線通信の実験② BLE通信』で取り組んだように、BLEを使ってブロードキャストすることで、省電力性能の良いデバイスにできることがわかっています。
 Wi-Fiでも、同じ考え方でESP32のDeep SleepとWake Up機能を利用して、大量のデータを高速に送ることが可能です。しかしこのようにしても、Bluetoothに比べると消費電力が多いのが難点です。IoTで扱う個々のデータの長さは一般的に短く、送信速度も低速でかまわないのが普通です。その代わりに、電池1個で長期間(1年程度)の使用に耐えるような省電力の能力が要求されます。このためここでは、クライアント方式はBLEに譲ることにしましょう。
 ESP32をサーバーとして運用する場合は、ネットワークへの常時接続が必要なので、電源も電池でなく商用電源からの安定した供給が前提になります。このサーバーにWebアプリケーションを仕込んで、Webサーバーとして運用します。そうすることで、利用できるクライアント(端末)の幅がぐっと広がります。パソコンだけでなくスマートフォンやタブレットのWebブラウザーを使って接続し、計測情報を表示したりデバイスを制御することが可能になります。


3.Webアプリケーションの基礎

 Webアプリケーションについては、以前に『Raspberry Piによるデータベース構築とWebアプリケーションの開発』において「Webアプリケーションの基礎知識」としてとりまとめました。その内容と重複しますが、以下に今回必要となる部分を抜粋して掲載します。
 まずWebアプリケーションの仕組みとHTTPについて説明し、続いてクライアントサイドの仕組みとしてHTML,CSS, JavaScriptを解説します。基本的な事項だけなので、すでにこれらの知識をお持ちの方は 次節に進んでください。

§1.Webアプリケーションの仕組み

 まず、Webアプリケーションがどのようなものであるかを簡単に整理しておきましょう。
 図のように、クライアントであるノートPCやタブレット端末上のWebブラウザーから、インターネット越しにWebサーバー上で動作するアプリケーションに処理を要求するものです。アプリケーションはユーザーの要求に従って計算やデータベース処理などを行って、その結果を表示するために動的なページを生成しクライアントに送信します。このように、静的なページを閲覧するWebサイトとは大きく異なります。


 ソフトウェア技術的に見ると、Webブラウザで動作するクライアントサイドと、Webサーバーで実行されるサーバーサイドに二分することができます。Webアプリケーションを開発するためには、この2つがどのように連携し、あるいは独立して動作するかを理解することが大切です。これらの具体的な内容は次節以降で説明します。
 クライアントとサーバーの間は、HTTP(HyperText Transfer Protocol)という通信規約に従ってやり取りが行われます。ここではHTTPについて理解しておきましょう。

①HTTPの概要

  HTTPではクライアントからサーバに要求(HTTPリクエスト)を送り、サーバがクライアントに応答(HTTPレスポンス)を返す方法で通信します。Webページを構成するHTMLやスタイルシート、スクリプトといったファイルのやりとりと、画像・音声・動画などのデータファイルを送受信することができます。
 クライアントに対してレスポンスを返すというシンプルな仕組みであり、処理の内容を持ち越したり、過去のやり取りを参照することはいっさいしません。したがってサーバーの負荷が軽く、多数のクライアントからのリクエストに効率良く応じることができます。
 このように複数回の通信をまたぐ状態を管理しないことはステートレス(stateless)と呼ばれ、HTTPはステートレスであることが大きな特徴です。現在の通信状態を次の通信に持ち越したい場合は、プログラムを記述するなどして対応する必要があります。

②リクエスト

 クライアントがサーバーに送るリクエストは、リクエスト行、メッセージヘッダー、メッセージボディーで構成されます。リクエスト行には次のメソッドと共に、対象のURLとHTTPのバージョン情報が送信されます。
    ・GETメソッド:クライアントがサーバーの情報を要求する
    ・POSTメソッド:クライアントがサーバーに情報を送信する
    ・HEADメソッド:サーバー情報のヘッダー部分を取得する
 GETは要求する情報をサーバーに伝えるためのものなので、リクエスト行のURLの後に?で始まるクエリ文字列を付けて送り、メッセージボディーは伴いません。これに対してPOSTはサーバーに情報を送ることが目的なので、メッセージボディーを伴い長さの制限はありません。またバイナリデータも送信できます。

③レスポンス

 レスポンスはステイタス行、メッセージヘッダー、メッセージボディーで構成されます。ステイタス行には下記のような処理結果を表す3桁のステイタスコードが入り、メッセージヘッダーにはWebサーバー名や作成日時が記録され、メッセージボディーにクライアント宛の情報本体が格納されます。
    ・1xx : Information(情報)
    ・2xx : Success(成功)
    ・3xx : Redirection(移転通知)
    ・4xx : Client Error(クライアントエラー)
        401:Unauthorized(認証失敗)
        403:Forbidden(アクセス権なし)
        404:Not Found(該当URL無し)
    ・5xx : Server Error(サーバーエラー)

④HTMLによる呼び出し

 HTMLについては節を改めて述べますが、HTMLはクライアントサイドのWebブラウザ上で動作すること、そして次の2通りの方法でHTTPリクエストを送信することを記憶しておいてください。
 1) formタグによる送信
<form action="CGIプログラムのURI" method="POST">
    ・・・・
</form>
  「CGIプログラムのURI」で示すプログラムが呼び出されます。
 2) aタグによる送信
<a href="QueryPage.html?code=8765">検索処理</a>
  画面に表示された「検索処理」の部分をクリックするとQueryPage.htmlにリクエストを送信します。


§2.クライアントサイドの仕組み

 画面の表示や入力など、ユーザーとのインターフェイスにかかわる処理は、クライアントサイドのWebブラウザによって処理されます。これらの仕組みは、HTML、CSS、JavaScriptといったクライアントサイド・スクリプトと呼ばれるプログラム言語で記述します。記述したファイルはサーバー上に配置され、ブラウザからのリクエストによってブラウザに送信されます。ブラウザに取り込まれると、ネットワークを介さずにブラウザ上で動作するため、処理時間が短くサーバーへの負荷を減らすことができます。
 他の言語もありますが、ここではHTML、CSS、JavaScriptについて概要を説明します。いずれも、さらにそれぞれのマニュアルを読んで、自由に応用できるようにしたい言語です。


(1)HTML(HyperText Markup Language)

 HTMLはWebページの「内容」を記述するための言語です。サーバーからHTMLを受け取ると、その記述に従って文字や画像を表示したり、入力用のパーツを画面上に配置したりします。最新のHTML5(HTMLの第5版)は以前の版に比べて記述が簡素化されています。
 最も簡単なWebページは次のような記述で成り立っています。
<!DOCTYPE html>
<html lang="ja">
<head>

サイトの標題

</head>
<body>

    

</body>
</html>
 先頭の<!DOCTYPE html>は、この文書がHTML5で作成されたものであることを宣言するためのものです。
 文書中の"<"と">"で囲まれた文字列をタグと言います(例えば<html>など)。タグは「<tag>」の形式の開始タグで始まり「</tag>」の終了タグで終わり、それに囲まれた部分に特別な意味を持たせています。少し細かい話になりますが、開始タグと終了タグとその間に記述されたものを合わせて「要素」と呼びます。
 <html>ではlang属性で言語を指定します。またmetaタグに"charset="を記述して文字エンコーディングを指定することで文字化けを防ぐことができます。linkタグではrel="stylesheet"を指定して、"href="で表示スタイルを記述したCSSファイルを読み込むよう指定できます。
 <body>では文字や画像の表示、入力用のテキストボックスやボタン類の配置などを記述します。データを入力してサーバーに送信するようなページでは、<body>~</body>の中にform要素を設定して、「どこ」に「どのよう」に送信するかを指定します。
  ---- 略 ----
<body>
  
  名前を入力してください:         
  ---- 略 ---- </body>
 上の例は、画面上に入力メッセージとテキスト入力フィールド、送信ボタンを配置しています。名前を入力して[送信]ボタンをクリックすると、「送信先URL」のサーバー上のプログラムに送信するようになっています。methodに"GET"を指定しているので、情報(ここではusername)は次のように、URLの後の ?で始まる文字列(クエリ文字列)に付加されて送られます。
http://~~~?username=入力された名前
 これに対してmethodに"POST"を指定すると、情報はURLに現れない形式で送られます。"GET"を指定して情報を簡単に送信できますが、送信内容が見えてしまうためセキュリティ面では問題があり、データサイズも255文字以内に制限されます。"POST"メソッドはテキストだけでなくバイナリも送信でき、データサイズの制約はありません。
  ---- 略 ----
<body>
  ---- 略 ----
  選んでください:賛成ですか、反対ですか?
  ・賛成です
  ・反対です   ---- 略 ---- </body>
 アンカータグ(<a>)を使った例です。このようにクエリ文字列に情報を付加することができます。これから分かるように、アンカータグによる呼び出しでは必ず"GET"メソッドが使われます。
 HTMLにはこの他にもラジオボタンやリストボックスを始めいくつもの入力パーツを記述でき、写真・動画や表などを表示することもできます。それぞれの特徴と使い方を習得することが重要です。また、サーバー上で動作するPHPのコードや、ブラウザ上で動作するJavaScriptなどもHTMLの中に記述することができます。


(2)CSS(Cascading Style Sheets)

 CSSはブラウザがHTML文書を解釈して画面に表示する際のスタイルを指定する言語です。文字や背景に色を付けたり、文字フォントの種類やサイズなどを細かく指定することができます。
 CSSには3種類の書き方があります。
   ・HTMLのタグに直接書き込む
   ・HTMLファイル内に埋め込む
   ・独立したCSSファイルに記述する
 HTMLが読みにくくならないように独立したCSSファイルに記述することを基本にして、部分的な調整が必要な場合だけタグなどに直接書くことにします。先のHTMLで例示したように、link要素でrel="stylesheet"を指定して、"href="でCSSのファイル名を記述して読み込ませます。
 CSSの基本構造を示します。
セレクタ {
  スタイルプロパティ: 値;
 セレクタにはHTML要素(タグ)の名前、id名(HTML要素のid属性の値)、class名(class属性の値)などを書いて、画面上のどのような要素に対して作用するかを規定します。id名は先頭に#を、class名は.を付けます。
タグ名 {
  スタイルプロパティ: 値;

#id名 {
  スタイルプロパティ: 値;

.class名 {
  スタイルプロパティ: 値;
 スタイルプロパティにはcolor(文字の色)、background-color(背景色)、font-size(フォントサイズ)などを記述しコロンで区切って値を指定します。値は、色ならredとか#ff0000、サイズなら16pxや1.5emなどと記述します。スタイルプロパティと値のセットは、セミコロンで区切っていくつでも指定することができます。
 以下にそれぞれを例示します。  まずは<p>~</p>の間で文字色と背景色を指定するケース。
p {
  color: white;
  background-color: black;
}
 次にid「container」でフォントのサイズと太さ、色を指定するケース。
#container {
  font-size: 24px;
  font-weight: bold;
  color:#ff0000;
}
 最後はクラス「photo」の表示位置を、上方マージン幅と中央揃えで指定するケースです。
.photo {
  margin-top: 10px;
  text-align: center;
}
 以上から分かるようにスタイルプロパティにはたくさんの種類があります。表示に関するものを大別しても、文字用、ボックス用、テーブル用、リスト用などがあり、それぞれがいくつものプロパティを持っています。さらに音声や印刷に関するもの、また新しいCSS3では表現が多様になったことからプロパティは増える一方です。書き方の基本を理解しておき、対象を絞って必要な情報をインターネットなどから手早く収集するといった対応が必要になります。
 CSSの最後で、できるだけ避けたいHTMLタグへの直書きを例示しておきます。CSSでは同じセレクターが現れると後に指定したものが有効になるので、スタイルシートの内容を部分的に変更する場合に便利です。しかし、くれぐれも多用はしないようにしましょう。
<p style="color: red;">〔注意事項〕</p>


(3)JavaScript

 JavaScriptはWebブラウザで実行できるプログラム言語です。Javaという名がついていますがJava言語とはまったく別のものです。
 JavaScriptの機能は、入力データのチェック、画面の動的な書き換え、計算処理などをクライアント内で行い、サーバーとの通信を制御します。
 早速ですが、典型的な入力データをチェックするコードを眺めてみましょう。
<!DOCTYPE html>
<html lang="ja">
<head>

JavaScriptのテスト
</head>



<body>
	

1~100までの数字を入力してください:

</body> </html>
 JavaScriptも通常は独立したファイルに記録するべきですが、簡単なテストなどのロジックやページが更新される都度実行させたい処理は、HTMLに埋め込むこともできます。8行と23行の<script>タグの中にJavaScriptを記述しています。9行と22行はHTMLのコメントの開始と終了です。JavaScriptをサポートしていない場合は、この部分をコメントとして無視します。
 <body>タグにはtestJavaScriptという名前のフォームを定義して、その上に入力メッセージとtext_dataというテキストボックスと送信ボタンを配置しています。HTMLがブラウザに解釈されると次のような画面が表示されます。
 29行目のボタンtype="button"のonclickに注目してください。これはボタンがクリックされた時にcheckDataというメソッドを実行するように指定しています。JavaScriptにはこのように何らかの出来事(イベント)をきっかけにして動作する仕組みが設けられていて、これをイベントハンドラと言います。主なイベントハンドラとして次のようなものがあります。
・onClick   : マウスがクリックされたとき
・onKeyDown : キーが押されたとき
・onFocus: オブジェクトが選択された状態になったとき
・onBlur: オブジェクトからフォーカスが外れたとき
・onSubmit: フォームを送信しようとしたとき
・onChange: フォーム要素の選択または内容が変わったとき
・onLoad: ページの読み込みが完了したとき
 そのcheckDataメソッドは10行目に記述されています。まず変数dtにテキストボックスtext_dataの内容を取り出しています。documentは画面に表示されている大元のオブジェクトなので、まずこれを指定します。続いてフォーム名testJavaScriptとそのフォーム上のテキストボックスtext_dataと続き、これらをピリオドでつなぎます。そして最後にテキストボックスの内容であるvalueを指定します。
 こうして変数dtに取得した内容が数値でないかどうかを調べます。isNaNメソッドは引数が数値でない場合にtrueを返します。数値でなければalertメソッドで「数字以外が入力されています!」というメッセージを表示させます。returnではこのメソッドの終わりに伴う返却値を指定します。入力が正しくない場合はfalseを返すことによって、onclick後のリクエストの送信を無効にします。
 入力は1~100の値を求めているので、引き続き数値の範囲チェックを行い、これも範囲外なら「数字が範囲以外です!」のメッセージを表示してリクエストを無効にします。両方のチェックを通過するとtrueを返却し、リクエストが送信されます。
 このようにして、サーバーにデータを送信する前にブラウザ側でチェックをすることにより、サーバーの負荷を軽減できるわけです。

 もう一つ参考までに、リストボックスの選択処理と選択結果を次のページに引き渡す方法を紹介しておきましょう。
<!DOCTYPE html>
<html lang="ja">
<head>

JavaScriptのテスト
</head>



<body>
	

曜日を選択してください:



</body> </html>
 26行目でリストボックスを定義しています。size=7を指定しているので、すべての曜日がリストボックスに表示された状態になります。optionタグではvalueで曜日に対応したコードを記述しています。リストボックスの下に[ 検 索 ]ボタンを設置して、これをクリックするとcheckSelectionメソッドを実行させます。HTMLを実行すると次のような画面が表示されます。
 続いて、10行目から記述されたcheckSelectionメソッドの内容を眺めてみましょう。先の例と同様に、変数idxにselectboxの選択位置selectedIndexの値を取り出しています。選択が行われた場合、selectedIndexには先頭項目位置をゼロとする相対位置が格納されます。どの選択肢も選ばれなかった場合は-1が設定されます。12行目ではその状態を調べて、マイナスならalertメソッドで「曜日を選択してください!」と表示させてfalseを返却します。
 選択されていたら、selectbox.options[idx].valueで選択された曜日のコードを取り出し、文字列"code="につないでdocument.cookieに格納しています。同様にselectbox.options[idx].textで選択された曜日名そのものを取得して、文字列"name="と連結してdocument.cookieに格納します。そしてwindow.location.hrefで次のページに制御を移行(サーバーにリクエストを送信)しています。先にも述べたようにHTTPはステートレスですが、このようにして、クッキーに格納した内容は、次のページへつながれて参照され使用されます。


4.今後の実験予定

 次回から5回にわたってWi-Fi通信の実験を行います。それぞれの実験の予定とポイントを以下に取りまとめておきます(変更が生じた場合この部分は適宜書き直されます)。

①計測値の受信1

計測用デバイスをWebサーバーにして、クライアントのブラウザーに温度と湿度の計測値を表示させます。
ブラウザーの更新ボタンを押すと再計測して表示を更新します。
 ・スケッチ名: WiFiMeasurement.ino
 ・デバイス:  計測用デバイス
 ・ポイント:  ESP32のWi-Fi通信におけるHTTPリスン処理の定型化(パターン化)を試みます。

②計測値の受信2

計測用デバイスを非同期Webサーバーにして、クライアントのブラウザーに計測値を継続表示させます。
ブラウザーの更新ボタン操作は不要で、所定間隔の計測結果をブラウザーに送って計測値表示を自動更新します。
 ・スケッチ名: WiFiMeasureAsync.ino
 ・デバイス:  計測用デバイス
 ・ポイント:  GETリクエストと非同期サーバーの振る舞い。

③LEDをブラウザーから点灯/消灯させる

ブラウザーに表示されたボタンのクリックでLEDを点灯/消灯させます。
同時に温度と湿度を計測して表示します。
 ・スケッチ名: WiFiDigitalSwitch.ino
 ・デバイス:  計測用デバイス
 ・ポイント:  HTTPリクエスト処理とHTML内の可変フィールドの編集方法。

④ブラウザー上のスライダーを操作してLEDの輝度を変える

 ・スケッチ名: WiFiDigitalSlider.ino
 ・デバイス:  監視用デバイス
 ・ポイント:  スライダーとAjaxによるスライダー値の更新。
         DAC(Digital Analog Converter)とPWM(Pulse Width Modulation)によるLEDの明るさ制御。
         GoogleにホスティングされているライブラリーCDN(Content Delivery Network)の利用。

⑤リレーモジュールを組み込んで、外部電源をON/OFFさせる

 ・スケッチ名: WiFiRelayModule.ino
 ・デバイス:  監視用デバイス
 ・ポイント:  2 CHANNEL 5V RELAY MODULEの構造と配線。
         リレーによる外部回路の制御方法。


では、次回をお楽しみに!