WiFiサーバの製作
ESP32にはWiFiモジュールが内蔵されています。せっかくなので、早速ですがLチカの次は無線LAN接続を試してみようと思います。
『Hello,World!』サーバ
今回は無線LAN接続の基本を確認するため、最小限度の機能を持ったサーバプログラムを作成します。Arduinoでも製作した 『Hello,World!サーバ』です。
機能はごく単純で、
telnetでクライアントが接続したら、”Hello,World!”という文字列を送信して直ちに通信を切断する
というものです。このプログラムで、ESP32をサーバとして動作させる方法について確認していきましょう。
製作&実験
回路
今回は、ESP-Devkit を PC とUSBケーブルで接続するだけです。外付けの部品は一切必要ありません。
プログラム
全ソースコード
メインプログラム:helloWorldServer
#include "WiFi.h"
#include "wifisecret.h"
// リスンポートを23番としてサーバのインスタンスを作成
WiFiServer server(23);
void setup(){
// シリアルインターフェイスの初期化
Serial.begin(115200);
delay(1000);
// 無線LANへの接続
Serial.print("接続中...");
WiFi.begin(_SSID, _PASS);
while(true){
if(WiFi.status() == WL_CONNECTED)break;
Serial.print(".");
delay(1000);
}
Serial.println("完了");
// ESP32に割り当てられたIPアドレスの確認
Serial.print("IPアドレス:");
Serial.println(WiFi.localIP());
// サーバの起動
server.begin();
}
void loop(){
WiFiClient client = server.available();
if(client){
// クライアントと接続した時の処理
Serial.println("new client");
client.println("Hello,World!");
client.stop();
}
}
wifisecret.h
#define _SSID "xxxxxxxx"
#define _PASS "yyyyyyyy"
※ご利用の無線LAN環境にあわせて、”xxxxxxxx” の部分には SSID、”yyyyyyyy” の部分にはパスワードを記述してください
プログラムの解説
ライブラリのインクルードなど
#include "WiFi.h"
#include "wifisecret.h"
プログラム冒頭で2つのファイルをインクルードしています。このうち “WiFi.h” が無線LAN接続のために必要なライブラリです。“wifisecret.h” は接続先の無線LANのSSIDとパスワードを定義したファイルです。
サーバのインスタンスを生成
// リスンポートを23番としてサーバのインスタンスを作成
WiFiServer server(23);
ESP32をサーバとして動作させるには、WiFiServerクラスを使用するのが簡単です。コンストラクタの引数 23 はListen port番号(クライアントの接続を待ち受けるポート)です。この例では、Listen portとしてtelnetのポートである23番を指定して、serverという名前のインスタンスを生成しています。
シリアルインターフェイスの設定
// シリアルインターフェイスの初期化
Serial.begin(115200);
delay(1000);
今回のプログラムでは、動作確認のためのメッセージをシリアルインターフェイスを通じてPCに送信します。そのためsetup()関数の最初にシリアルインターフェイスの初期化をしています。
Arduinoのソフトウェアシリアルと違ってESP32は高速でも安定してシリアル通信できるようなので(苦笑)、通信速度は 115,200bpsを指定しています。
アクセスポイントへの接続
// 無線LANへの接続
Serial.print("接続中...");
WiFi.begin(_SSID, _PASS);
while(true){
if(WiFi.status() == WL_CONNECTED)break;
Serial.print(".");
delay(1000);
}
Serial.println("完了");
Arduino版と異なり、無線LANモジュールの実在チェックはしていません。まぁESP32なら自信がWiFiモジュールを内蔵しているのでチェックに意味がありません。
無線LANへの接続には WiFi.begin()関数を使用します。関数の仕様は Arduino R4のものと同じです。
書式
int WiFi.begin(char* ssid, char* pass)
引数
名前 | 型 | 意味 |
---|---|---|
ssid | char* | 接続するネットワークのSSID(文字列へのポインタ) |
pass | char* | 接続するネットワークのパスワード(文字列へのポインタ) |
返却値
接続に成功した場合:WM_CONNECTED
接続に失敗した場合:WM_CONNECT_FAILED
WM_CONNECTED および WM_CONNECT_FAILED は、 WiFiTypes.h 内で定義された定数(enum型の列挙子)です。
IPアドレスの表示
// ESP32に割り当てられたIPアドレスの確認
Serial.print("IPアドレス:");
Serial.println(WiFi.localIP());
このプログラムはDHCPを利用して動的にIPアドレスの割り当てを受ける前提です。あとでPCから接続するためにはESP32に割り当てられたIPアドレスが必要なので、WiFiServer.localIP()関数でIPアドレスを取得し、シリアル通信でPCに送出しています。
書式
IPAddress WiFi.localIP()
返却値
返却値は割り当てられたIPアドレスですが、IPAddressクラスで返されることに注意してください。
なお、Arduino版のサンプルではIPアドレスの文字列化のために localIP().toString() としていましたが、今回は toString() は省略しました。
サーバの起動
// サーバの起動
server.begin();
サーバの起動には、WiFiServer.begin()関数を使用します。この関数の仕様はArduino R4版と同じです。
書式
void WiFiServer.begin()
この関数には引数も返却値もありません。
クライアントからの接続を取得
WiFiClient client = server.available();
loop()関数内では、まずクライアントからの接続を取得します。クライアントからの接続リクエストを取得するには、WiFiServer.available()関数を使用します。
書式
WiFiClient WiFiServer.available()
返却値
新たに接続したクライアントがある場合は、そのクライアントを表す WiFiClientクラスのインスタスが返却されます。
WiFiServer.available()関数は、クライアントからの接続リクエストが届くまで待ち受ける関数ではありません。新たに接続してきたクライアントがあってもなくても、関数自体はすぐに結果を返して処理は先に進んでしまいます。
接続したクライアントがあったかどうかの判定
if(client){
// クライアントと接続した時の処理
Serial.println("new client");
client.println("Hello,World!");
client.stop();
}
前項にも書いたとおり、WiFiServer.available()関数は新たに接続してきたクライアントがあってもなくても処理が先に進んでしまいます。ここでは返却値clientをチェックして、新たに接続してきたクライアントがあった場合のみ、クライアントに対する送信処理を行うようにしています。
クライアントと接続した場合の処理
if(client){
// クライアントと接続した時の処理
Serial.println("new client");
client.println("Hello,World!");
client.stop();
}
Serial.println()は動作確認用です。クライアントが接続した場合に『new clilent』とシリアル出力します。不要な場合は削除して構いません。
クライアントに対して文字列を出力する場合は、WiFiClient.print()関数/WiFiClient.println()関数を使用します。使い方はSirial.print()関数/Sirial.println()関数とまったく同じです。
この例では、『Hello,World!』+改行文字という文字列をクライアントに送信しています。
このサーバの仕様は『telnetで接続すると”Hello,World!”という文字列をクライアントに送信して直ちに切断する』なので、文字列送信後には client.stop()関数でクライアントとの通信を終了(コネクションを切断)します。
以上で、クライアントと接続した場合の処理は終了です。
実行
Windowsのtelnetコマンドで接続する場合
Windowsではじめてtelnetコマンドを使う場合、コマンドの有効化を行う必要があります。以下の記事を参考にしてtelnetコマンドを有効化しておいてください。
1.サーバを起動する
ESP32 をPCに接続し、Arduino IDEでシリアルモニタを表示した状態でプログラムを実行すると、自動的に無線LANに接続してサーバとしての動作を開始します。
数秒程度でDHCPからIPアドレスを取得し、シリアルモニタに結果が表示されます。この例では『192.168.0.15』が ESP32 に割り当てられたIPアドレスです。
2.telnetでESP32に接続
telnetクライアントを用いて、ESP32 の IPアドレスに接続します。
上の画面写真では、もっとも手軽に使用できるtelnetクライアントとしてWindowsのコマンドプロンプトから telnetコマンド を使用しています。telnetコマンドは、
telnet 接続先のIPアドレス [ポート番号]
の書式で使用します。ポート番号の指定はオプションで、今回は使用していません(Arduinoのサーバプログラム側でtelnetコマンドのデフォルト使用ポートで待ち受けするようになっているため)。
3.サーバから文字列”Hello,World!”が送信されてくる
telnetクライアントは、サーバから送信されてきた文字列をそのまま表示します。このプログラムでは、サーバはクライアントと接続すると『Hello,World!』という文字列を送信し、すぐに通信を終了しますので、telnetクライアント泡では『Hello,World!』という文字列表示され、接続が切断されます。
このように動作すれば成功です。
TeraTermで接続する場合
ターミナルエミュレータの定番、TeraTermでも実験することができます。ただTeraTermは初期設定ではサーバとの通信が切断されると自動的にウィンドウを閉じてしまうため『Hello,World!』というメッセージを確認できません。そこで、あらかじめウィンドウを閉じないように設定を変更します。
※TeraTermをお持ちでない場合は、窓の杜などでダウンロード&インストールしてください。
1.『新しい接続』のウィンドウをいったん閉じる
TeraTermを起動すると自動的に『新しい接続』ダイアログが開くので、『キャンセル』をクリックしていったんダイアログを閉じます。
2.『TCP/IP設定』ダイアログ
メニューの『設定』→『TCP/IP』を選択します。
『TCP/IP設定』ダイアログが開くので、
①『自動的にウィンドウを閉じる』のチェックを外します。
②『OK』ボタンをクリックします。
3.ESP32に接続
メニューの『ファイル』→『新しい接続』を選択します。
『新しい接続』ダイアログが開くので、
①TCP/IPを選択します。
②ESP32に割り当てられたIPアドレスを入力します。
③『サービス』で『Telnet』を選択します。
④『OK』ボタンをクリックします。
4.サーバから文字列”Hello,World!”が送信されてくる
『Hello,World!』という文字列を送信し、すぐに通信を終了します。
まとめ
- ESP32 で無線LANに接続するには、WiFiS.h を使用するのが簡単
- サーバプログラムを作るには、WiFiServerクラスを使うと簡単
コメント