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);
}