DreamerDreamのブログ

夢想家の夢です。〜揚げたてのモヤっとしたものをラフレシアと共に〜

ESP32で基本のSocket通信 null文字に注意しましょう

前回赤外線リモコン信号のコピーに成功したので、

dreamerdream.hateblo.jp

 

今回は遠隔操作をすべくESP32で基本のSocket通信を試みます。

 

 

早速ですが完成したESP32用Socketサーバーのコードです。

#include <WiFi.h>
#include <WiFiClient.h>

 

const char *ssid = "SSID";
const char *password = "PASSWORD";

 

WiFiServer server(5000);

void connectToWiFi() {
  WiFi.begin(ssid, password);
  WiFi.setSleep(false); // WiFiスリープを無効にする

  // WiFi接続が確立されるまで待機
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // WiFi接続が確立した場合の処理
  String ip = WiFi.localIP().toString().c_str();

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.printf("IP Address  : ");
  Serial.println(WiFi.localIP());

  //サーバー立ち上げ
  server.begin();
  Serial.println("server.begin()");
}


void setup() {
  Serial.begin(115200);
  connectToWiFi();
}

 

//自前タイムアウト処理
bool timeout(WiFiClient client){
  int waitloops = 0;
  while (!client.available()){
    waitloops++;
    delay(1); //delay 1 msec
    if( 10000 < waitloops ){
      return true;
    }
  }
  return false;
}

void loop() {

  WiFiClient client = server.available();

  if (client) {
    Serial.println("New Client.");
    while (client.connected()) {
      if( timeout(client) ) break;
      int size = client.available();
      if (size) {
        Serial.println();
        Serial.print("size:");
        Serial.println(size);

        //null文字対策込めてメッセージ受信
        char cmd[size + 1];  // command
        memset(cmd, 0, sizeof( cmd ));
        client.read( ( uint8_t* )cmd, size);
        cmd[size] = '';  // Add null terminator
        Serial.println( cmd );
        
        if( strcmp( cmd, "TMP" ) == 0 ){
          Serial.println( "receive temp" );
          if( timeout( client ) ) break;
          //現在温度の送信

        }else if( strcmp( cmd, "IR" ) == 0 ){
          client.write(String("wait").c_str());
          //delay(10);
          if( timeout(client) ) break;
          size = client.available();
          Serial.print("size:");
          Serial.println(size);
          char input[size + 1];  // +1 for the null terminator
          memset(input, 0, sizeof(input));
          client.read( ( uint8_t* )input, size);
          input[size] = '';  // Add null terminator

          Serial.println( "sendIR" );
          Serial.println( input );
          //赤外線送信
          
        }else if( strcmp( cmd, "LEARN" ) == 0 ){
          Serial.println( "learnIR" );
          if( timeout(client) ) break;
          //赤外線学習
          
        }
        
      }

      delay(1);
    }
    client.stop();
    Serial.println();
    Serial.println("client.stop()");
  }

  // WiFi接続が失われた場合に再接続を試みる
  if (WiFi.status() != WL_CONNECTED) {
      connectToWiFi();
  }
  delay(1);
}

 

ひとまずWiFi切断時の再接続と通信中のタイムアウトを込めたコードになっています。

 

通信実験において、受信時に謎なエラーに遭遇しました。

なぜか4,8,16,32の文字数で文字化けが起こるという状態です。

こういうときにはchatGPTさんが大いに役立ちます。

すごいですね!

要するにnull文字の対策ができていないぞ。ということのようで、null文字が何かよく知りませんがchtatGPTさんが出力してくれた対策コードをそのまま入れて解決出来ました笑

 

そしてクライアントから長いエアコンのリモコン信号が遅れるのかもチェックをします。

# coding: utf-8

 

# ソケット通信(クライアント側)

import socket

 

ip = '192.168.0.9' #ESP32のIPアドレス

port = 5000 #ESP32の待ち受けポート

server = (ip, port)

 

sct = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sct.connect(server)

 

code = "0000 006D 0092 0000 0089 003F 0014 002B 0014 002D 0014 000D 0014 000D 0012 000D 0014 002D 0014 000D 0014 000D 0014 002B 0014 002D 0014 000D 0014 002B 0016 000B 0014 000D 0014 002D 0012 002D 0014 000D 0014 002D 0012 002D 0014 000D 0014 000D 0014 002B 0014 000D 0014 000D 0014 002D 0014 000B 0016 000B 0014 000D 0014 000D 0014 000D 0012 000D 0016 000B 0014 000D 0014 000D 0014 000D 0012 000D 0014 000D 0014 000D 0014 000D 0014 000B 0014 000D 0016 000B 0014 000D 0014 000D 0012 000D 0014 002D 0014 000D 0014 000D 0012 000D 0014 000D 0014 000D 0014 002D 0012 002D 0016 000B 0014 000D 0014 000D 0012 002D 0014 002D 0014 000D 0014 002B 0016 000B 0014 000D 0014 000D 0014 000B 0014 000D 0016 002B 0014 002D 0014 000B 0016 002B 0014 002D 0012 000D 0014 000D 0014 000D 0014 000D 0014 000D 0012 000D 0016 000B 0014 000D 0014 002D 0012 000D 0014 000D 0014 000D 0014 000D 0012 000D 0014 000D 0014 000D 0014 000D 0014 000D 0012 000D 0014 000D 0014 000D 0014 000D 0014 000B 0016 000B 0014 000D 0014 000D 0014 000B 0014 000D 0014 000D 0014 000D 0014 000D 0014 000D 0012 000D 0014 000D 0014 000D 0014 000D 0014 000B 0014 000D 0016 000B 0014 000D 0014 000D 0012 000D 0014 000D 0016 000B 0014 000D 0014 000D 0012 000D 0014 000D 0014 000D 0014 000D 0014 000B 0014 000D 0014 000D 0014 000D 0014 000D 0012 000D 0014 000D 0014 000D 0014 000D 0014 000B 0014 000D 0014 000D 0014 000D 0014 000D 0012 000D 0014 000D 0016 000B 0014 002D 0014 002B 0014 002D 0014 000D 0014 000D 0012 002D 0014 002D 0014 06C3 "

 

sct.send("IR".encode("UTF-8"))

#sct.send("LEARN".encode("UTF-8"))

 

if sct.recv(16).decode() == 'wait': //サーバーからのコード受信待ち信号

  //赤外線コード送信

  sct.send( code.encode("UTF-8") )

 

sct.close()

 

狙い通りに送れているようです。



これで前回のと組み合わせるとエアコンの遠隔操作が実現できそうです。

後はインジケータをどうするかとか、もう少し要件を詰めて作成していく予定です。

 

しかし、ESP32便利!

ラズパイもすごいけれど、ここ最近はESP32推しです。

dreamerdream.hateblo.jp

乾電池でも駆動できちゃうんですよね。

dreamerdream.hateblo.jp

 

 

 

kampa.me