使用するプログラムの紹介
ESP32用プログラム(サーバ側)
Arduino側には次のようなスケッチを使用します。
このスケッチはESP32のボードマネージャのサンプルプログラム"simpleWifiServer"を一部改変することで作成しました。
#include <WiFi.h>
const char* ssid = "yourSsid";
const char* password = "yourPassword";
WiFiServer server(5000);
String message;
String oneLetter;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
int value = 0;
void loop(){
WiFiClient client = server.available();
if (client) {
Serial.println("New Client.");
String currentLine = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n') {
Serial.print("クライアントからのメッセージ: ");
Serial.println(currentLine);
message = "hello,client! by server";
client.print(message);
client.stop();
Serial.println("Client Disconnected.");
} else if (c != '\r') {
currentLine += c;
}
}
}
}
}
ESP32スケッチの説明
上で示したスケッチについて簡単に説明します。
まずスケッチの最初の部分について。
#include <WiFi.h>
const char* ssid = "yourSsid";
const char* password = "yourPassword";
WiFiServer server(5000);
String message;
String oneLetter;
の部分では、スケッチ内で使用するWifiライブラリや各種変数の定義を行います。
ネットワークのssidやパスワードもここで設定します。
次に、setup関数の中身について説明します。
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
の部分では、シリアル通信を開始し、ESP32の接続情報をシリアルモニタ上に表示する準備を行っています。
次に、
WiFi.begin(ssid, password);
でESP32をネットワークに接続します。
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
の部分では、ESP32がネットワークに接続されるのを待ちます。ネットワークに接続されると、変数WiFi.status()の値が WL_CONNECTEDになります。
その後、
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
の部分で、ネットワークへの接続が完了したことと、自身のIPアドレスをシリアルモニタ上に表示します。最後に server.begin()とすることで、ESP32はサーバとして動作し始めます。
|
次にloop関数の中身について説明します。
WiFiClient client = server.available();
の部分では、サーバに接続してきたクライアントの情報を変数clientに格納します。
次に、
if (client) {
Serial.println("New Client.");
String currentLine = "";
の部分では、if (client)という条件分岐があります。これは、新たにサーバーに接続してきたクライアントがいた場合のみ、以降の処理を行う、という意味です。
変数String currentLineは、サーバクライアント間でメッセージをやり取りするために用意された空の文字列です。
その後、
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n') {
Serial.print("クライアントからのメッセージ: ");
Serial.println(currentLine);
message = "hello,client! by server";
client.print(message);
client.stop();
Serial.println("Client Disconnected.");
} else if (c != '\r') {
currentLine += c;
の部分はサーバクライアント間の通信が維持されている場合のみ実行します。
この部分ではクライアントから送られてきたメッセージを受信し、シリアルモニタ上に表示するまでの一連の処理を行います。
なお、今回はクライアントからサーバーへ送信するメッセージの末尾に改行コード("\n")を付け加えることで、メッセージの文末が分かりやすいような工夫がされています。
まず、サーバーはクライアントから送られてきたデータを先頭から1バイトずつ読み取っていき、読み取った文字が通常の文字であれば変数currentLineに加えます。
これをくり返し行うことでメッセージを1文字ずつ読み込み、メッセージの文末を表す改行コード"\n"が読み込まれたところで、変数currentLineの中身をシリアルモニタ上に表示します。
この部分を説明した図を作成したので下に載せておきます。
最後に、メッセージの受信が無事に行えたことをクライアントに伝えるために、
message = "hello,client! by server";
client.print(message);
の部分でクライアントへメッセージを送信し、
client.stop();
でクライアントとの通信を切断します。
pythonプログラム(クライアント側)
クライアントとして、次のようなpythonプログラムを使用しました。
import socket
ip_address = '192.168.10.115'
port = 5000
buffer_size = 4092
recieve_message = ""
recieve_status = True
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((ip_address, port))
message = input("送信するメッセージを入力してください\n→")
message += "\n"
client.sendall(bytes(message, encoding='ASCII'))
print("サーバーへデータ送信")
data = client.recv(buffer_size)
print("サーバからのメッセージ")
print(data.decode())
client.close()
print("ソケット通信を終了")
python用プログラムの説明
import socket
の部分で、今回用いるsocketライブラリをインポートします。
socketライブラリは、今回用いるソケット通信を行うために必要なライブラリです。
ソケット通信は通信方法の一種で、簡単に言えば、相手のIPアドレスとポート番号を指定して通信を行う方法のことです。
これは私たちが郵便物を送る際に送り先の住所と郵便番号を記入するのと似ていますね。
次の部分では、各変数の設定を行っています。
ip_address = '192.168.10.115'
port = 5000
buffer_size = 4092
recieve_message = ""
recieve_status = True
ipアドレスの欄は、適宜お使いのESP32のipアドレスに変更してください。
その他の変数については、特に変更する必要はありません。
次の部分、
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
では、socketクラスのインスタンスを生成しています。
また、インスタンスを生成する際に引数を2つ与える必要があり、ここでは通信に用いるプロトコルの指定を行っています。
この部分に関して詳しく解説してある記事があったので、リンクを載せておきます。
qiita.com
次に、サーバーに接続を要求するために、
client.connect((ip_address, port))
とします。
サーバーとの接続が確立されたら、いよいよサーバに向けてメッセージを送る処理に入ります。
メッセージを送信する処は次のようになります。
message = input("送信するメッセージを入力してください\n→")
message += "\n"
client.sendall(bytes(message, encoding='ASCII'))
print("サーバーへデータ送信")
まずinput関数を用いてサーバーへ送信するメッセージを決定したのち、メッセージの文末に改行コード"\n"を付け加えておきます。
これは上でも解説したように、メッセージを受信したときにメッセージの文末がどこなのかを簡単に判別できるように付け加えられています。
その後、client.sendall(bytes(message, encoding='ASCII'))とすることで、接続先のサーバーに変数messageの中身を送信します。
なお、引数のencoding='ASCII'は、送信時に使用する文字コードとしてASCIIを選択するために与えています。
その後、サーバーから送られてくるメッセージを受け取るために、
data = client.recv(buffer_size)
print("サーバからのメッセージ")
print(data.decode())
という処理を行います。
サーバから送られてくるメッセージは、そのまま読める文字ではなくバイト形式で送られてくるので、print(data.decode())とすることで、バイト形式から読める形式に変換してから、コマンドプロンプト上に出力します。
最後に
client.close()
として、サーバーとの通信を切断します。
実行例
まずはESP32をネットワークに接続します。
ネットワークのssidとパスワードが正しく入力されていれば、電源投入時に自動でネットワークに接続します。
接続が完了すると、ESP32に割り当てられたIPアドレスがシリアルモニタに表示されます。
次にクライアント側として機能するpythonプログラムを起動します。
プログラムを起動すると、送信するメッセージの入力受付画面となるので、メッセージを入力しEnterを押します。
その後、メッセージがサーバーに正常に送られると、サーバーからの返信がコマンドプロンプトに表示されます。
この時、ESP32のシリアルモニタには、クライアントから送られてきたメッセージが表示されます。
以上をもって、ESP32-python間でwifi経由でメッセージをやり取りすることができました!