EasyWebSocket ライブラリ Beta 1.51 ( ESP32 , ESP8266 )をアップしました

ESP32 ( ESP-WROOM-32 )
ESP32_SD_EasyWebSocket Beta 1.51.1 にアップデートしました。
HTML文字列を外部ファイルから読み込む時に、UTF-8日本語文字列を読み込まない不具合を修正しました。
外部テキストファイルは必ず UTF-8 形式で保存してください。
コメントでご指摘くださった、copperceleさん、ありがとうございました。
m(_ _)m
(2017/4/26)

こんばんは。

今回は、スマホのブラウザで双方向リアルタイム通信ができる、私の自作ライブラリ、EasyWebSocket をバージョンアップしましたのでお知らせします。
Arduino IDE 専用です。
素人の自作なので、永遠にベータバージョンのままです。
過去バージョンと互換性が無いところがありますのでお気を付けください。

前回や、前々回の記事では、ESP8266 ( ESP-WROOM-02 )版の EasyWebSocket を 更新しましたが、今回は、ESP32 ( ESP-WROOM-32 )版も同じ形式でアップデートし、Beta 1.51 としました。
そして、ESP8266 用も足りない関数を追加しました。

前回や、前々回の記事でも述べましたが、大きく変えたところは、WebSocket ハンドシェイク関数構成です。

以前はブラウザへ送信する HTML文字列をグローバル変数領域に格納していましたが、これをローカル関数内に置くことによって、その関数を抜けるとメモリを解放するようにしました。
特に ESP8266 では SRAM が少ないので、https ( SSL )ページを取得しようとすると、たちまちオーバーロードして例外エラーとなってしまいます。

ESP32 でも ESP8266 の5倍程度の SRAM しかありませんので、極力節約してプログラミングしておいた方が良いです。
ブラウザへ吐き出すHTML は全て SD カード、または SPIFFSに記述してしまった方が良いと思います。

では、改良した点を説明します。

スポンサーリンク

使用デバイス例

ESP32-DevKitC ( ESP-WROOM-32 開発ボード)

waves ESP32 DevKitC V4 ESP-WROOM-32 ESP-32 WiFi BLE
waves
¥1,170(2024/11/22 21:53時点)

ESPr Developer ( ESP-WROOM-02 開発ボード )

ESP-WROOM-02 の開発ボードで超おすすめなのが、スイッチサイエンスさん販売のものです。

ESP-WROOM-02開発ボード
スイッチサイエンス(Switch Science)

ESPr Developer(ピンソケット実装済)
スイッチサイエンス(Switch Science)

micro SDHC カード

以下のカードで動作確認済みです。
他のカードは動作しない場合がありますので、注意してください。

Transcend microSDHCカード 8GB Class10 UHS-I対応 Nintendo Switch 動作確認済 TS8GUSDU1
トランセンドジャパン
¥1,080(2024/11/22 20:28時点)


micro SD カードスロット

SparkFun マイクロSDカードスロット・ピッチ変換基板

この接続例は以下の記事を参照してください。
以下の接続でも動作しない場合は、信号ピンに10kΩの抵抗でプルアップすると動作する可能性があります。

【ESP32 編】
ESP32 ( ESP-WROOM-32 ) で micro SDHC メモリカードを使う場合の注意点

ESP32 -DevKitC ( ESP-WROOM-32 )でスマホとWi-Fi リアルタイム双方向同時通信

【ESP8266編】
ESP8266 ( ESP-WROOM-02 ) SPI 通信高速化、その2 ( 複数デバイス、Mode、Watchdog Timer 問題 )

ライブラリの掲載先

GitHub の以下のページにアップしてあります。

ESP32_SD_EasyWebSocket Beta 1.51.1 にアップデートしました。
HTML文字列を外部ファイルから読み込む時に、UTF-8日本語文字列を読み込まない不具合を修正しました。
外部テキストファイルは必ず UTF-8 形式で保存してください。
コメントでご指摘くださった、copperceleさん、ありがとうございました。
m(_ _)m
(2017/4/26)

【 ESP32 (SDカード用) 】
https://github.com/mgo-tec/ESP32_SD_EasyWebSocket

【 ESP8266 ( SPIFFS用 ) 】
https://github.com/mgo-tec/ESP8266_SPIFFS_EasyWebSocket

【 ESP8266 ( SDカード用 ) 】
https://github.com/mgo-tec/ESP8266_SD_EasyWebSocket

ZIPファイルをダウンロードして、Arduino IDE にインストールしてください。
ただし、古い EasyWebSocket ライブラリは必ずフォルダごと削除してからインストールしてください
インストール方法は以下の記事を参照してください。

GitHubにある ZIP形式ライブラリ のインストール方法

必要なdata ファイルのアップロード

HTML ヘッダなどの必要なファイルは以前と変わりありません。

micro SDHC の場合

microSDHC カードに最低限必要なファイルは以下のファイルです。

EwsHead2.txt
HTMhead1.txt
HTMhead2.txt

これらのファイルは、sampleスケッチフォルダの中の data フォルダ内にあります。

micro SDHC カードは FAT32 に予めフォーマットされたものを使用してください。
フォーマットに関する記事は以下を参照してください。

micro SD 、micro SDHC カードの初期化(フォーマット)方法

そして、EWS というフォルダを作成し、上記のファイルをその中にコピーしておいてください。

ESP8266 SPIFFS の場合

上記と同じファイルが必要です。
上記のファイルを SPIFFS ファイルアップローダーを使用して、ESP8266 へアップロードしておいてください。
ただし、このファイルだけアップロードしてしまうと、フォントファイルなどは全て消えてしまいますので、ご注意ください。
フォントファイルが必要な場合はそれも一緒にアップロードしてください。
アップロード方法は以下のページを参照してください。

Arduino IDE に ESP8266 SPIFFS ファイルシステムアップローダーをインストールする方法

4M/3M SPIFFS アップロード方法は以下のページ参照。

4M ( 3M SPIFFS ) をシリアルポートでアップロードできない場合のトラブルシューティング

更新概要

WebSocket ハンドシェイク(コネクション確立)構成の変更

前回や、前々回の記事の記事で述べましたが、今回はESP32 ( ESP-WROOM-32 )用も更新しました。
以下のサンプルスケッチをご覧ください。

ESP32 用ローカル IP 自動取得 LED点灯サンプルスケッチ
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#include <ESP32_SD_EasyWebSocket.h> //beta ver 1.51 
 
const char* ssid = "xxxx"; //ご自分のルーターのSSIDに書き換えてください
const char* password = "xxxx"; //ご自分のルーターのパスワードに書き換えてください
 
const char* HTM_head_file1 = "/EWS/LIPhead1.txt"; //HTMLヘッダファイル1
const char* HTM_head_file2 = "/EWS/LIPhead2.txt"; //HTMLヘッダファイル2
const char* HTML_body_file = "/EWS/dummy.txt"; //HTML body要素ファイル(ここではダミーファイルとしておく)
const char* dummy_file = "/EWS/dummy.txt"; //HTMLファイル連結のためのダミーファイル
 
const uint8_t cs_SD = 5; //SDcard CS(ChipSelect)

SD_EasyWebSocket ews;
 
IPAddress LIP; //ローカルIPアドレス自動取得用
 
String ret_str; //ブラウザから送られてくる文字列格納用
String txt = "text send?"; //ブラウザから受信した文字列を ESP32から再送信する文字列
 
int PingSendTime = 10000; //ESP32からブラウザへPing送信する間隔(ms)
bool get_http_req_status = false; //ブラウザからGETリクエストがあったかどうかの判定変数
 
long ESP32_send_LastTime;
int ESP32_send_Rate = 300;
byte cnt = 0;
 
#define ledPin1 12 //GPIO #12
#define ledPin2 13 //GPIO #13
#define ledPin3 14 //GPIO #14
 
void setup() 
{
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
     
  ews.AP_Connect(ssid, password);
  delay(1000);
   
  LIP = WiFi.localIP(); //ESP32のローカルIPアドレスを自動取得
 
  Serial.println(); Serial.println("Initializing SD card...");
 
  if (!SD.begin(cs_SD, SPI, 40000000, "/sd")) {
    Serial.println("Card failed, or not present");
    return;
  }
 
  Serial.println("card initialized. OK!");
 
  sigmaDeltaSetup(0, 312500);
  sigmaDeltaSetup(1, 312500);
  sigmaDeltaSetup(2, 312500);
  sigmaDeltaAttachPin(ledPin1,0);
  sigmaDeltaAttachPin(ledPin2,1);
  sigmaDeltaAttachPin(ledPin3,2);
  sigmaDeltaWrite(0, 0); // LED OFF
  sigmaDeltaWrite(1, 0); // LED OFF
  sigmaDeltaWrite(2, 0); // LED OFF
   
  ESP32_send_LastTime = millis();
}
 
void loop() {
  websocket_handshake();
   
  if(ret_str != "_close"){
    if(millis()-ESP32_send_LastTime > ESP32_send_Rate){
      if(cnt > 3){
        cnt = 0;
      }
      websocket_send(cnt, txt);
      cnt++;
      ESP32_send_LastTime = millis();
    }
 
    ret_str = ews.EWS_ESP32CharReceive(PingSendTime);
    if(ret_str != "\0"){
      Serial.println(ret_str);
      if(ret_str != "Ping"){
        if(ret_str[0] != 't'){
          int ws_data = (ret_str[0]-0x30)*100 + (ret_str[1]-0x30)*10 + (ret_str[2]-0x30);
          switch(ret_str[4]){
            case '!':
              ESP32_send_Rate = ws_data;
              break;
            case 'B':
              LED_PWM(1, 0, floor(ws_data/2));
              break;
            case 'G':
              LED_PWM(1, 1, floor(ws_data/2));
              break;
            case 'R':
              LED_PWM(1, 2, floor(ws_data/2));
              break;
            case '_':
              LED_PWM(2, 0, floor(ws_data/2));
              break;
            case 'A':
              LED_PWM(3, 0, ws_data);
              break;
            case 'O':
              LED_PWM(4, 0, ws_data);
              break;
          }
        }else if(ret_str[0] == 't'){
          txt = ret_str.substring(ret_str.indexOf('|')+1, ret_str.length()-1);
          Serial.println(txt);
        }
      }
    }
  }else if(ret_str == "_close"){
    ESP32_send_LastTime = millis();
    ret_str = "";
  }
    yield(); //これ重要かも
}
//**************************************************************
void LED_PWM(byte Led_gr, byte channel, int data_i)
{
  Serial.println(data_i);
  switch(Led_gr){
    case 1: //1つのLEDを調光制御
      sigmaDeltaWrite(channel, floor(data_i*2.5));
      break;
    case 2: //3つのLEDを順番に点灯、消灯
      if(data_i < 34){
        sigmaDeltaWrite(0, data_i*7);
        sigmaDeltaWrite(1, 0);
        sigmaDeltaWrite(2, 0);
      }else if(data_i > 33 && data_i < 67){
        sigmaDeltaWrite(1, (data_i-33)*7);
        sigmaDeltaWrite(0, 0);
        sigmaDeltaWrite(2, 0);
      }else if(data_i > 66){
        sigmaDeltaWrite(2, (data_i-66)*7);
        sigmaDeltaWrite(0, 0);
        sigmaDeltaWrite(1, 0);
      }
      break;
    case 3: //3つのLED全点灯
      sigmaDeltaWrite(0, 255);
      sigmaDeltaWrite(1, 255);
      sigmaDeltaWrite(2, 255);
      break;
    case 4: //3つのLED全消灯
      sigmaDeltaWrite(0, 0);
      sigmaDeltaWrite(1, 0);
      sigmaDeltaWrite(2, 0);
      break;
  }
}
//*********************************************
void websocket_send(uint8_t count, String txt1){
  String str;
  
  switch(cnt){
    case 0:
      str = txt1;
      break;
    case 1:
      str = "WebSockets";
      break;
    case 2:
      str = "Hello!!";
      break;
    case 3:
      str = "World!!";
      break;
  }
   
  ews.EWS_ESP32_Str_SEND(str, "wroomTXT"); //ブラウザに文字列を送信
}
//************************* Websocket handshake **************************************
void websocket_handshake(){  
  if(ews.Get_Http_Req_Status()){ //ブラウザからGETリクエストがあったかどうかの判定
    String html_str1="", html_str2="", html_str3="", html_str4="", html_str5="", html_str6="", html_str7="";

    //※String変数一つにEWS_Canvas_Slider_T関数は2つまでしか入らない
    html_str1 += "<body style='background:#000; color:#fff;'>\r\n";
    html_str1 += "<font size=3>\r\n";
    html_str1 += "ESP-WROOM-32(ESP32)\r\n";
    html_str1 += "<br>\r\n";
    html_str1 += "SD_EasyWebSocket Beta1.51 Sample\r\n";
    html_str1 += "</font><br>\r\n";
    html_str1 += ews.EWS_BrowserSendRate();
    html_str1 += "<br>\r\n";
    html_str1 += ews.EWS_ESP32_SendRate("!esp32t-Rate");
    html_str1 += "<br>\r\n";
    html_str1 += ews.EWS_BrowserReceiveTextTag2("wroomTXT", "from ESP32 DATA", "#555", 20,"#00FF00");
    html_str1 += "<br>\r\n";
    html_str1 += ews.EWS_Status_Text2("WebSocket Status","#555", 20,"#FF00FF");
    html_str1 += "<br><br>\r\n";
    
    html_str2 += ews.EWS_TextBox_Send("txt1", "Hello Easy WebSocket Beta1.51","送信");
    html_str2 += "<br><br>\r\n";
    html_str2 += "LED \r\n";
    html_str2 += ews.EWS_On_Momentary_Button("ALL", "ALL-ON", 80,25,15,"#000000","#AAAAAA");
    html_str2 += ews.EWS_On_Momentary_Button("OUT", "ALL-OFF", 80,25,15,"#FFFFFF","#555555");
    html_str2 += "<br>\r\n";
     
    html_str3 += "<br>LED BLUE... Dim\r\n";
    html_str3 += ews.EWS_Canvas_Slider_T("BLUE",200,40,"#777777","#0000ff"); //CanvasスライダーはString文字列に2つまでしか入らない
    html_str3 += "<br>LED GREEN Dim\r\n";
    html_str3 += ews.EWS_Canvas_Slider_T("GREEN",200,40,"#777777","#00ff00"); //CanvasスライダーはString文字列に2つまでしか入らない
     
    html_str4 += "<br>LED RED..... Dim\r\n";
    html_str4 += ews.EWS_Canvas_Slider_T("RED",200,40,"#777777","#ff0000"); //CanvasスライダーはString文字列に2つまでしか入らない
    html_str4 += "<br>LED RGB..... Dim\r\n";
    html_str4 += ews.EWS_Canvas_Slider_T("_RGB",200,40,"#777777","#ffff00");
    
    html_str5 += "<br><br>\r\n";
    html_str5 += ews.EWS_WebSocket_Reconnection_Button2("WS-Reconnect", "grey", 200, 40, "black" , 17);
    html_str5 += "<br><br>\r\n";  
    html_str5 += ews.EWS_Close_Button2("WS CLOSE", "#bbb", 150, 40, "red", 17);
    html_str5 += ews.EWS_Window_ReLoad_Button2("ReLoad", "#bbb", 150, 40, "blue", 17);
    html_str5 += "</body></html>";

    //WebSocket ハンドシェイク関数
    ews.EWS_HandShake_main(3, cs_SD, HTM_head_file1, HTM_head_file2, HTML_body_file, dummy_file, LIP, html_str1, html_str2, html_str3, html_str4, html_str5, html_str6, html_str7);
  }
}

ESP8266 SPIFFS用ローカル IP 自動取得 LED点灯サンプルスケッチ
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

/*
EasyWebSocket_SPIFFS for ESP-WROOM-02 ( ESP8266 ) Sample Sketch
for Beta version 1.51
---> https://www.mgo-tec.com
Please rewrite their own the ssid and password.
Requied HTML header files. "/data/HTMhead1.txt" & "/data/HTMhead2.txt" in the sketch folder.
Use the SPIFFS file system uploader, please upload the HTMhead1.txt & HTMhead2.txt file to flash.
*/
#include <EasyWebSocket.h>

const char* ssid = "xxxx"; //ご自分のルーターのSSIDに書き換えてください
const char* password = "xxxx"; //ご自分のルーターのパスワードに書き換えてください

const char* HTM_head_file1 = "/HTMhead1.txt"; //HTMLヘッダファイル1
const char* HTM_head_file2 = "/HTMhead2.txt"; //HTMLヘッダファイル2
const char* HTML_body_file = "/dummy.txt"; //HTML body要素ファイル(ここではダミーファイルとしておく)
const char* dummy_file = "/dummy.txt"; //HTMLファイル連結のためのダミーファイル

uint32_t ESP8266_send_LastTime;
uint16_t ESP8266_send_Rate = 300;
byte cnt = 0;

EasyWebSocket ews;
IPAddress LIP; //ESP-WROOM-02(ESP8266) ローカルIPアドレス自動取得用

String ret_str;
String txt = "text send??";

int PingSendTime = 10000;

#define ledPin1 16 //GPIO #16 ※16番ピンはGPIOダイレクトアクセスは使えないので注意
#define ledPin2 5 //GPIO #5
#define ledPin3 4 //GPIO #4

void setup() 
{
  delay(1000);
  pinMode(16, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT);
  
  ews.AP_Connect(ssid, password);

  LIP = WiFi.localIP(); //ESP8266のローカルIPアドレスを自動取得
  
  ESP8266_send_LastTime = millis();
}

void loop() {
  websocket_handshake();
  
  String str;

  if(ret_str != "_close"){
    if(millis()-ESP8266_send_LastTime > ESP8266_send_Rate){
      if(cnt > 3){
        cnt = 0;
      }
      websocket_send(cnt, txt);
      cnt++;
      ESP8266_send_LastTime = millis();
    }

    ret_str = ews.EWS_ESP8266CharReceive(PingSendTime);
    if(ret_str != "\0"){
      Serial.println(ret_str);
      if(ret_str != "Ping"){
        if(ret_str[0] != 't'){
          int ws_data = (ret_str[0]-0x30)*100 + (ret_str[1]-0x30)*10 + (ret_str[2]-0x30);
          switch(ret_str[4]){
            case '!':
              ESP8266_send_Rate = ws_data;
              break;
            case 'B':
              LED_PWM(1, ledPin1, floor(ws_data/2));
              break;
            case 'G':
              LED_PWM(1, ledPin2, floor(ws_data/2));
              break;
            case 'R':
              LED_PWM(1, ledPin3, floor(ws_data/2));
              break;
            case '_':
              LED_PWM(2, 0, floor(ws_data/2));
              break;
            case 'A':
              LED_PWM(3, 0, ws_data);
              break;
            case 'O':
              LED_PWM(4, 0, ws_data);
              break;
          }
        }else if(ret_str[0] == 't'){
          txt = ret_str.substring(ret_str.indexOf('|')+1, ret_str.length()-1);
          Serial.println(txt);
        }
      }
    }
  }else if(ret_str == "_close"){
    ESP8266_send_LastTime = millis();
    ret_str = "";
  }
	yield(); //これ重要
}

//**************************************************************
void LED_PWM(byte Led_gr, byte Led_Pin, int data_i)
{
Serial.println(data_i);
  switch(Led_gr){
    case 1:
      analogWrite(Led_Pin, data_i);
      break;
    case 2:
      if(data_i < 34){
        analogWrite(ledPin1, data_i*8);
        analogWrite(ledPin2, 0);
        analogWrite(ledPin3, 0);
      }else if(data_i > 33 && data_i < 67){
        analogWrite(ledPin2, (data_i-33)*8);
        analogWrite(ledPin1, 0);
        analogWrite(ledPin3, 0);
      }else if(data_i > 66){
        analogWrite(ledPin3, (data_i-66)*7.78);
        analogWrite(ledPin1, 0);
        analogWrite(ledPin2, 0);
      }
      break;
    case 3:
      analogWrite(ledPin1, 100);
      analogWrite(ledPin2, 100);
      analogWrite(ledPin3, 100);
      break;
    case 4:
      analogWrite(ledPin1, 0);
      analogWrite(ledPin2, 0);
      analogWrite(ledPin3, 0);
      break;
  }
}
//*********************************************
void websocket_send(uint8_t count, String txt1){
  String str;
  
  switch(count){
    case 0:
      str = txt1;
      break;
    case 1:
      str = "WebSockets";
      break;
    case 2:
      str = "Hello!!";
      break;
    case 3:
      str = "World!!";
      break;
  }
   
  ews.EWS_ESP8266_Str_SEND(str, "wroomTXT"); //ブラウザに文字列を送信
}
//************************* Websocket handshake **************************************
void websocket_handshake(){
  
  if(ews.Get_Http_Req_Status()){ //ブラウザからGETリクエストがあったかどうかの判定
    String html_str1="", html_str2="", html_str3="", html_str4="", html_str5="", html_str6="", html_str7="";

    //※String変数一つにEWS_Canvas_Slider_T関数は2つまでしか入らない
    html_str1 += "<body style='background:#000; color:#fff;'>\r\n";
    html_str1 += "<font size=3>\r\n";
    html_str1 += "ESP-WROOM-02(ESP8266)\r\n";
    html_str1 += "<br>\r\n";
    html_str1 += "SPIFFS_EasyWebSocket Beta1.51 Sample\r\n";
    html_str1 += "</font><br>\r\n";
    html_str1 += ews.EWS_BrowserSendRate();
    html_str1 += "<br>\r\n";
    html_str1 += ews.EWS_ESP8266_SendRate("!esp8266t-Rate");
    html_str1 += "<br>\r\n";
    html_str1 += ews.EWS_BrowserReceiveTextTag2("wroomTXT", "from WROOM DATA", "#555", 20,"green");
    html_str1 += "<br>\r\n";
    html_str1 += ews.EWS_Status_Text2("WebSocket Status","#555", 20,"#FF00FF");
    html_str1 += "<br><br>\r\n";

    html_str2 += ews.EWS_TextBox_Send("txt1", "Hello Easy WebSocket Beta1.51","送信");
    html_str2 += "<br><br>\r\n";
    html_str2 += "LED \r\n";
    html_str2 += ews.EWS_On_Momentary_Button("ALL", "ALL-ON", 80,25,15,"#000000","#AAAAAA");
    html_str2 += ews.EWS_On_Momentary_Button("OUT", "ALL-OFF", 80,25,15,"#FFFFFF","#555555");
    html_str2 += "<br>\r\n";
     
    html_str3 += "<br>LED BLUE... Dim\r\n";
    html_str3 += ews.EWS_Canvas_Slider_T("BLUE",200,40,"#777777","#0000ff"); //CanvasスライダーはString文字列に2つまでしか入らない
    html_str3 += "<br>LED GREEN Dim\r\n";
    html_str3 += ews.EWS_Canvas_Slider_T("GREEN",200,40,"#777777","#00ff00"); //CanvasスライダーはString文字列に2つまでしか入らない
     
    html_str4 += "<br>LED RED..... Dim\r\n";
    html_str4 += ews.EWS_Canvas_Slider_T("RED",200,40,"#777777","#ff0000"); //CanvasスライダーはString文字列に2つまでしか入らない
    html_str4 += "<br>LED RGB..... Dim\r\n";
    html_str4 += ews.EWS_Canvas_Slider_T("_RGB",200,40,"#777777","#ffff00");
    
    html_str5 += "<br><br>\r\n";
    html_str5 += ews.EWS_WebSocket_Reconnection_Button2("WS-Reconnect", "grey", 200, 40, "black" , 17);
    html_str5 += "<br><br>\r\n";  
    html_str5 += ews.EWS_Close_Button2("WS CLOSE", "#bbb", 150, 40, "red", 17);
    html_str5 += ews.EWS_Window_ReLoad_Button2("ReLoad", "#bbb", 150, 40, "blue", 17);
    html_str5 += "</body></html>";

    //WebSocket ハンドシェイク関数
    ews.EWS_HandShake_main(3, HTM_head_file1, HTM_head_file2, HTML_body_file, dummy_file, LIP, html_str1, html_str2, html_str3, html_str4, html_str5, html_str6, html_str7);
  }
  
}

以前のバージョンでは HTML タグの String文字列をグローバル変数領域で宣言して格納していましたが、それでは常に SRAM を消費した状態になってしまいます。

そこで、今回はローカル関数 websocket_handshake() 内で定義して、その関数を抜けるとメモリを解放するようにしました。

Get_Http_Req_Status() 関数はブラウザから GET リクエストがあったかどうかの判定です。
ブラウザの URL 入力欄に ESP32 または ESP8266 の IP アドレスを入力されると、
GET / HTTP
という文字列が送信されてきますので、それを検出したらtrue を返します。
そうしたら、WebSocket ハンドシェイクの開始になります。
WebSocket ハンドシェイクについては、以下の記事を参照ください。

Arduino化 WROOM で WebSocket ハンドシェイク 確立方法

EWS_HandShake_main 関数の使い方を説明します。
これは、ブラウザと WebSocket ハンドシェイク(コネクション確立)をする関数です。

ローカル IP 自動取得して、分割したHTML ヘッダファイルを使い、html_str 文字列を7つ使うならば、最初の数値を3にします。
1や2の場合は html_str 文字列を3つまでしか送信しません。
これは過去のスケッチでそういう使い方をしていたためのモードです。
通常は3で良いと思います。

MicroSD カードを使った場合、Arduino core for ESP32 では、同時に開けるファイルに制限があるようです。
その場合は4にして、ヘッダファイルを2つまでしか開かないモードにします。
つまり、スケッチ上でいうと、HTML_body_file, dummy_file のファイルは開きませんので、文字列無しの ”” としておきます。
これについては、近いうちに詳しく説明したいと思います。

EWS_ESP32( ESP8266 )_SendRate 関数の追加

これはESP32 の以前の記事で登場した関数です。
今回は ESP8266 用にも追加しました。

要するに、ブラウザにセレクトボックスを表示させ、ESP32 や ESP8266 から送信するデータの転送レートを変える HTML 文字列を排出する関数です。
使い方は以前の記事も参照ください。

Android スマホ Google Chrome でセレクトボックスをタッチすると下図の様になります。
25ms というのは、ESP32 もしくは ESP8266 から 25ms でデータを送信するという意味になります。

これをセレクトしたら、「Rate Exec」ボタンを押したら決定になり、ESP32 の場合は

025|!esp32t-Rate;

という文字列を ESP32 が受信します。
スケッチ上では、“!”という文字が見つかったら、その 025 という文字列を抽出して、
ESP32_send_Rate ( ESP8266_send_Rate )
という変数へ代入する形になります。
そうすれば、ESP32 若しくは ESP8266 の送信レートが反映されるという仕組みです。

EWS_https_Web_Get 関数の追加

前回や、前々回の記事で紹介しましたが、今回は ESP32 でも追加しました。
使い方は ESP8266 と同じです。
主に、Yahoo! RSS ニュースのトップ記事のテキストを取得する関数です。

最近、Yahoo! RSS ニュースサイトがhttps ( SSL )化したことによって、それの対策済み関数です。
これは、WiFiClientSecure.h のインクルードにより、暗号の復号化処理をしているので、メモリを多量に消費します。
使う場合には要注意です。

この関数のESP32 での工作例はまだ記事にしていませんが、私自身の工作では既に実証済みですので、近々記事にしたいと思っています。

推奨ブラウザ

私が試験したブラウザは以下の通りです。

◆Android 7.0 Google Chrome  ◎
◆iOS 10.3.1  Safari  ◎
◆Windows10 Edge  ×
◆Windows10 Internet Explore  ×
◆Windows10 Google Chrome ○

とにかく、できるだけ高性能CPU 、高速 Wi-Fi のスマホまたはPCで、Google Chrome をお勧めします。

動作の様子

ESP32 の以前の記事よりは劣りますが、Auto_Local_IPのサンプルスケッチを使用した例です。

いかがでしょうか。

ESP32 の場合は、怒涛のようにスマホから連続データ送信してフリーズしても、確実にタイムアウトしてくれる感じがあります。
ただ、やはりフリーズは通信トラフィックが原因の場合が多いので、通信レートを調節して、確実に動くようにした方が良いですね。
こうやって、スマホ側で通信レートを調整できるのはイイですよね。

初回接続時はWebSocket ハンドシェイクが完了するまで少々時間がかかりますが、1回接続できてしまえば次回接続は早いです。

スマホブラウザ、Google Chrome の画面はこんな感じです。

シリアルモニターの表示は従来と一緒です。

以上、自作ライブラリ EasyWebSocket beta 1.51 の説明でした。

何か不具合等ありましたらコメント等でご連絡いただけると助かります。

ということで、今回はここまでです。
ではまた・・・。

Amazon.co.jp 当ブログのおすすめ

スイッチサイエンス ESPr Developer 32 Type-C SSCI-063647
スイッチサイエンス
¥2,420(2024/11/23 17:23時点)
ZEROPLUS ロジックアナライザ LAP-C(16032)
ZEROPLUS
¥19,358(2024/11/22 22:35時点)
Excelでわかるディープラーニング超入門
技術評論社
¥2,068(2024/11/23 14:03時点)

コメント

  1. coppercele より:

    いつもお世話になっております。

    こちらを参考にSDカードからHTMLをbody.txtとして読み込ませていたのですが
    途中で止まってしまうという不具合が起きました。

    結果としては2バイト文字の所で止まっていましたので
    UTF-8エスケープに変換したら解消しました(゚∀゚)

    傾きセンサ→&#x50BE;&#x304D;&#x30BB;&#x30F3;&#x30B5;
    • mgo-tec mgo-tec より:

      copperceleさん

      当ブログをご覧いただき、そしてライブラリを使っていただき、ありがとうございます。

      そうですか・・・。
      body.txt をテキストエディタで UTF-8形式で保存してもダメでしょうか?

      • coppercele より:

        返事が遅くなってすみませんでした

        ファイルのエンコードがSHIFT-JISになっていましたので
        UTF-8にしたのですがやはり全角文字で止まってしまいました

        以上よろしくお願いします

        • mgo-tec mgo-tec より:

          あれぇ~、ほんとですね~・・・。
          以前は問題なかったと思うのですが・・・。
          何かしらの仕様が変わったっぽいです。
          いろいろと調べてみます。

          ご報告ありがとうございました。
          m(_ _)m

        • mgo-tec mgo-tec より:

          copperceleさん

          原因が分かりました。
          ESP32_SD_EasyWebSocket.cpp ファイルの 408行目を以下のように変えてください。

          if(c>0xEF) break;
          

          実は、ESP8266 ではこのあたりの構文は不要で、ESP32 ではこれらを使わないとうまくいかなかったので、使ってみた次第です。
          昔は漢字を使うことを考えてなかったので、そのまま昔の構文が残っていました。
          つまり、0xDD以下ということは、すべて半角アスキー文字に制限されていたということです。
          今はArduino IDE もブラウザも UTF-8 漢字をそのまま使えるので、0xEF までということに変更すればOKです。
          この修正は GitHub上でもやっておきます。

          とても有難いご指摘、感謝いたします。
          また何かありましたら、ご連絡くださいませ・・・。
          m(_ _)m

  2. coppercele より:

    素早い対応ありがとうございます。

    こちらも何とか通信できるようになりましたのでご報告までに・・・

    https://twitter.com/coppercele/status/857822679532937216

    • mgo-tec mgo-tec より:

      ご報告ありがとうございます。
      Twitter の方だったんですね。
      今、知りました。

      イイ具合にモーター動いていて、良かった・・・。

      フォローとか、いいね、とかもいろいろありがとうございました。
      何分、素人自作ライブラリですので、今後も不具合とかあったらお知らせいただけると助かります。
      今後ともいろいろとよろしくお願いします。

  3. Han より:

    いつもお世話になっております。

    私ESP32を使っています.
    SoftAPモードでやってみたいですが,
    37行目をews.SoftAP_setup(ssid,password); に書き換えればよろしいでしょうか.
    コンパイル,書き込みは問題なくできましたが,
    スマホでやって見たらWebSocket StatusのところはWebSocket.Disconnectedでした.

    それの原因を教えて頂けますか.
    宜しくお願いします.

  4. Han より:

    すみません
    SoftAPモードの件解決しました.
    37行目を ews.SoftAP_setup(ssid,password);
    40行目を LIP = WiFi.softAPIP();
    に書き換えればいいですね!

    mgo-tecさんが作ったライブラリが使いやすく本当に助かります.

    • mgo-tec mgo-tec より:

      Hanさん。

      記事をご覧いただき、ありがとうございます。

      しばらく WebSocket を使っていなかったもので、思い出すまで時間がかかってしまいました。
      SoftAPモードもしばらく使ってなかったので、うまく動作するかはちょっと疑問です。

      因みに、ESP-WROOM-02 ( ESP8266 )や ESP32 の SoftAPモードの IPアドレスは、
      192.168.4.1
      で固定だったと思います。
      でも、WiFi.softAPIP()なる関数で使えればOKです。
      そもそも、そんな関数があったとは知りませんでした。
      逆に教えていただき有難うございます。

      私のライブラリは穴だらけだと思いますが、使っていただけて感謝感謝です。
      他に何か不具合ありましたら、ご連絡くださいませ。
      m(_ _)m

  5. 太田 耕正 より:

    mgo-tecさん製作のライブラリEasyWebSocket_SPIFFS(ESP-WROOME-02)用を使用して電子工作を楽しんでます。
    ESP_32用のライブラリはESP32_SD_EasyWebSocket//beta ver1.51が有りますが
    SDカード無しのライブラリEasyWebSocket_SPIFFSも開発公開して下さい。
    有意義なブログ内容に感謝してます。

    • mgo-tec mgo-tec より:

      太田さん

      いつもコメント投稿ありがとうございます。

      あ、そうですね、ESP32 の Websocket用 SPIFFS ライブラリですね。
      最近、ESP32 の SPIFFS が有効になったばかりで、まだ手をつけてませんでした。

      今、Google Home 関連記事の制作中で、それが気が狂うほど大変なんです。
      自分で作り始めて後悔したりしています。
      その他、SSD1306 ライブラリや SD_MMCライブラリの要望もあって、いろいろ山積しています。
      時々、気が変わって別の物を作ったりしちゃう場合があります。
      そんなわけで、今しばらくお待ちくださいませ。
      スイマセン・・・
      m(_ _)m

    • mgo-tec mgo-tec より:

      太田さん

      大変お待たせしました。
      ESP32 SPIFFS 用 EasyWebSocket ライブラリを作りました。
      以下の記事をご参照ください。

      ESP32 SPIFFS 用 Easy WebSocket ライブラリを作ってみました

  6. ヤスペ より:

    はじめまして!

    WROOM32をまだいじったことのない者なのですが、この記事をみて興味が湧いてきました!

    ただ一つ疑問なのですが、ルーターが自宅にない場合はアクセスポイントはどう設定すればよいですか。つまり、WROOM32 をアクセスポイントとしてスマホと通信する手段が知りたいです!

    よろしくお願いいたします!

    • mgo-tec mgo-tec より:

      ヤスペさん

      ブログをご覧いただき、ありがとうございます。

      ESP-WROOM-32 ( ESP32 )では、Soft_AP モードがあります。
      Arduino IDE でもライブラリがあります。
      それは、ESP-WROOM-32自体がルーター(アクセスポイント)になるモードです。
      デフォルトのIPアドレスが、192.168.4.1 になります。

      一応、ESP32_SD_EasyWebSocketライブラリでも Soft_APモード対応していたのですが、今見直したら、少々誤っていたので、修正しました。
      アクセスポイント接続クラスに、
      SoftAP_setup
      という関数を使います。

      また、ローカルIPアドレス取得に、Arduino-ESP32 WiFiライブラリの、WiFi.softAPIP()関数を使うところがポイントです。

      ということで、ESP32_SD_EasyWebSocketライブラリを修正し、
      Beta ver 1.51.2
      としました。
      そして、example にサンプルスケッチを追加しましたので、
      ESP32_SD_EWS_SoftAP_sample
      を使ってみて下さい。
      SSIDとパスワードは適当に変えてください。
      パスワードは8文字以上にしてください。
      サンプルスケッチは、Arduino IDE の
      「ファイル」→「スケッチ例」→「ESP32_SD_EasyWebSocket151.2」
      にあります。
      ここの記事にあるように、microSDカードに
      LIPhead1.txt
      LIPhead2.txt
      dummy.txt
      を/EWS/フォルダ内に作ることを忘れないでください。

      コンパイルしたら、スマホでWiFi接続し、「インターネット接続がありません」と警告出ますが、無視してください。
      ブラウザURL欄に 192.168.4.1 と入力すると、初期接続は15~30秒くらいハンドシェイクに時間がかかると思われます。

      また、ESP32のSoft_APモードでは、通信能力が弱く、双方向通信トラフィックが混むとフリーズしますのでご了承ください。
      アクセスポイント能力としては非力です。
      快適な双方向同時通信をするならば、高性能ルーターを通した方が良いです。

      以上、試してみて下さい。

  7. nobu より:

    家のシーリングライトをled化しているんのですが、どうせならとIOT化という事で、ESP-02と組み合わせて調光しようと色々探して、ここにたどり着きました。
    基本的にはうまくいってるのですが、静的IPの割り振りで躓いています。
    ews.AP_Connect(ssid, password)の前にWifi.configでIPを割り当てようとしたのですが、そうするとconnect自体が成功しません。静的IPの成功例とかはありますでしょうか。

    • mgo-tec mgo-tec より:

      nobuさん

      記事をご覧いただき、ありがとうございます。

      最近私は、ESP8266 は全く使っておらず、ESP32 ばかり使用していて、超久々に ESP-WROOM-02 を使ってみました。
      私が検証したところによると、以下のバーションで固定 IP でも特に問題無く動作しました。

      ●ESPr Developer ( ESP-WROOM-02開発ボード ) Rev.3 ( 昔の Flash 4MBタイプ )
      ●Arduino core for the ESP8266 stable ver 2.4.2
      ●SPIFFS EasyWebSocket beta ver 1.52.0

      ews.AP_Connect(ssid, password);
      の前にconfigを加えただけです。

      WiFi.config(IPAddress(192,168,0,??),IPAddress(192,168,0,1),IPAddress(255,255,255,0));
      ews.AP_Connect(ssid, password);
      

      ローカルIPアドレスが設定したものとルーター側とで変わってしまうとコネクションできません。
      私の想像では、もしかしたら、esp8266側で固定IPにしていても、ルーター側で強制的にIPが変わっているということはありませんでしょうか?
      また、ルーターによっては、DHCP の最大数設定やサブネットの設定でそのIPが弾かれている可能性があります。
      私はルーターのDHCP最大数設定を超えてしまっていることに気付かずに、接続できなくて、何度も無駄な時間を費やしたことがありました。
      SPIFFSスケッチの場合、45行目辺りに、
      Serial.println(LIP);
      を置いて、IPアドレスが合っているか確認してみてください。

      あと、考えられるのは、SPIFFS や SDカードにある、HTMhead1.txtファイルやHTMhead2.txtファイルの保存およびSPIFFSのアップロードが上手くいっていないとかでしょうか。

      因みに、ESP32 でも Static IP 設定で特に問題無く使用できています。

      • nobu より:

        やはり皆さん簡単にできてますよね。やはり私の環境かな。
        私の場合は、NTTのONU PR-400NEをDHCPサーバーにして、無線ルーターはAPモードで使ってます。無線ルーターをルーターモードにすれば問題を切り分けできそうですね。
        皆さん普通に使えてるようなので、もう少し悩んでみます。
        いずれは、外部からIPマスカレードかなんかでアクセスできるようにしたいと思っていて、その場合はIPアドレスは固定の方が安心できるので。

        • mgo-tec mgo-tec より:

          私は最新の ESP-WROOM-02 は持っていないので、最新のものはどうか正直わかりません。
          あまりお役に立てず、すみません。

タイトルとURLをコピーしました