2025年11月16日日曜日

platformIO 約束事 :: esp8266&esp32 webserver example

 #include <Arduino.h>は必須 terminal softはmicrosftのをextension install

関数プロトタイプは非有効 setup,loopで使用する関数は事前定義必須

-----------------------------------------------------------------

https://iot.keicode.com/esp8266/esp8266-webserver.php がうごいた

localipに/led/on,/led/offなどをつけてbrowseするとled on offにつかえる

ーーーーーーーーーーーーーーーーーーーーーーー

esp32には上記のライブラリがないとのことで自作してる人がいた softapなので注意

https://okiraku-camera.tokyo/blog/?p=6008

SimpleWebServer.h
----------------------------------------------------------------
// Get request のみ受け付ける マイコンなら十分です
#include <WiFi.h>
//line.indexOf(" ", 5)インデックス5以降から最初に現れるスペース(" ")の位置(インデックス)を
//検索し、その位置を返すメソッド呼び出し
//例えば、line の内容が "GET /path/to/file.html HTTP/1.1" だった場合を考えます。
//インデックス: 0123456789...
//文字列: "GET /path/to/file.html HTTP/1.1"
//line.indexOf(" ", 5); を実行すると:
//インデックス 5 は / の位置です。
//検索は /path/to/file.html HTTP/1.1 の部分から始まります。
//この範囲内で最初に見つかるスペースは、html の直後のスペースです。
//そのスペースのインデックス番号が戻り値として返されます。
//このメソッドは、文字列を解析して特定の部分を抽出する際によく利用されます。
#include <Arduino.h>
#include <WiFiServer.h>
#include <map>
using namespace std;
typedef void (*Handler_t)(void);
typedef void (*DefaultHandler_t)(String);
typedef struct {
  int status;
  const char* cpDesc;
} response_t;

const response_t responses[] = {
  {200,"200 OK"},
  {404,"404 Not Found"},
  {50, "500 Server Error"},
  {0,0}
};

class SimpleWebServer : public WiFiServer {
  IPAddress ap_addr;
  IPAddress ap_netmask;
  String ssid;
  String password;
  std::map<String, Handler_t>request_handlers; // request_handlersはmap
  DefaultHandler_t default_handler = 0;
  WiFiClient* client_connected; // connectしてきたclient

 public: // constructor ここ重要、引数の一部であるportはWiFiServerモジュールに丸投げ
 SimpleWebServer(const char* ssid,const char* password, \
 const IPAddress ap_addr, const IPAddress ap_netmask, int port = 80) \
 : WiFiServer(port) {
  this->ap_addr = ap_addr;
  this->ap_netmask = ap_netmask;
  this->ssid = ssid;
  this->password = password;
  client_connected = NULL; // 最初はだれもコネクトしていないので
 }

 void begin(){
  WiFi.softAP(ssid.c_str(),password.c_str());// 外部からの侵入口
  WiFi.softAPConfig(ap_addr,ap_addr, ap_netmask);// address is fixed
  Serial.print("SoftAp: ");
  Serial.print(WiFi.softAPIP());
  Serial.print(" ");
  Serial.print(ssid+String(" starts."));
  WiFiServer::begin(); // ここ重要、beginの仕事の大部分をWiFiServerモジュールへ丸投げ
  Serial.println("SimpleWebServer begin()");
 }

 void add_handler(String uri, Handler_t func){
  request_handlers[uri]=func;
 }

 void add_default_handler(DefaultHandler_t func){
  default_handler=func;//上と切り分けておくとdefault挙動をカスタムできる
 }

 void send_response(const char* cp) // clientへのpay?
 {
    if (client_connected)
      client_connected->print(cp);
 }

 void send_status(int status, const char* cp=NULL)
 {
   if (!client_connected)
     return;
   const response_t* p  = responses;
   while(p->status != 0){
     if (p->status == status){
       String s="HTTP/1.1"+String(status)+String(" ")+\
       String(p->cpDesc)+String("\r\n\r\n");
       const char* cpDesc = cp ? cp : p->cpDesc;
       s=s+String("<HTML><BODY>")+\
       String(cpDesc)+String("</BODY></HTML>\r\n");
       client_connected->print(s);
       return;
     }
     p++;
   } // 50,404の処理と以下で再帰で200処理?
   send_status(200);
  }

void handle_request(){
  WiFiClient client = available();
  if (!client)
    return;
  String request_line = "";
  while (client){
    client_connected = &client;
    while(client.available()){
      String line = client.readStringUntil('\r');
      line.trim();
      if (line.startsWith("GET")){ // Get onley built
        int index = line.indexOf(" ",5);
        if (index > 0)
           request_line = line.substring(4,index); // Req only?
        else
           request_line = line.substring(4); // Get only?
        request_line.trim();
        continue; // jump to while?
      }
      if (line.length()==0){ // end of request headers.
         Serial.println("request_line="+request_line);
         Handler_t f = request_handlers[request_line];
         if (!f) {
          if (default_handler)
           default_handler(request_line);
          else
           send_status(404);
         } else
            f();
         client.flush();
       }
    }
    client_connected=NULL;
    client.stop();
  }
 }
};
**************************************************************
main.cpp
-------------------------------------------------------------
#include <Arduino.h>
#include "SimpleWebServer.h"

// クライアントから/ledonをもらったら点灯し、ledoffなら消灯
// GPIO13にLEDを接続。

#define LED 13
SimpleWebServer server("ESP32AP", "password", IPAddress(192,168,4,1), IPAddress(255,255,255,0), 80);
void led_menu() {
  const char* cur = digitalRead(LED) ? "ON" : "OFF";
  String s =  "HTTP/1.1 200 OK\r\nContent-type:text/html\r\n\r\n"
              "<HTML><BODY style='font-size:48px;'>ESP32_HTTPD_LED1<br/>"
              "<br/><a href=/ledon>ON</a><br/><a href=/ledoff>OFF</a><br/><br/>"
              "Current Status = ";
  s = s + String(cur) + "</BODY></HTML>\r\n";
  server.send_response(s.c_str());
}

void led_on()
{
  digitalWrite(LED, 1);
  led_menu();
}

void led_off()
{
  digitalWrite(LED, 0);
  led_menu();
}

void led_500()
{
  server.send_status(500, "Internal Server Error");
}

void default_handler(String request_line)
{
  Serial.println("default_handler : " + request_line);  
  String s = request_line + " is not found";
  server.send_status(404, s.c_str());
}

void setup() {
  Serial.begin(9600);
  delay(10);
  Serial.println("");
  pinMode(LED, OUTPUT);
  digitalWrite(LED, 0);

  server.add_handler("/", led_menu);
  server.add_handler("/ledon", led_on);
  server.add_handler("/ledoff", led_off);
  server.add_handler("/led500", led_500);

  server.add_default_handler(default_handler);
  server.begin();
}

void loop() {
  server.handle_request();
  delay(10);
}





 

0 件のコメント:

コメントを投稿