シーリングライトや扇風機用のコントローラを作っていたところ、一つのコアで制御、もう一つのコアでHTTPリクエストの受け答えをしたい、ということが増えました。そこでサブコア(core 0)を使用してHTTPリクエストの受け答えをするサンプルプログラムを作成しました。いろいろなとことから参考にしています。
//ESP32でマルチコアでHTTPを処理
//http://IPアドレス/number/数字 でその数字を返すプログラム
#include <WiFi.h>
const int Blue_LED = 2;
//WiFi関係と固定アドレスなどの設定
const char SSID[] = "WiFiのSSID"; //SSID
const char PASSWORD[] = "WiFiのパスワード"; //WiFiパスワード
WiFiServer server(80);
IPAddress ip(192, 168, 10, 12); // for fixed IP Address
IPAddress gateway(192,168, 10, 1); //
IPAddress subnet(255, 255, 255, 0); //
IPAddress DNS(192, 168, 10, 1); //
//接続してきたクライアントのコマンドを取り込むバッファなどの用意
#define BUFFLEN 256 //length of the receive buffer
char buff[BUFFLEN]; //buffer
int count = 0; //counter for the buffer
volatile int command = 0; //2つのコアで同時に使用される可能性があるのでvolatile
bool isBlankLine = false; //if the last line is empty, the end of request
int number = 0;
//クライアントから受け取った1バイトをバッファに溜めてGETコマンドをチェックする
//リクエスト行が空行ならば、リクエストは終了と判断してisBlankLineに反映する
//put received char in buffer and check the GET command and empty line
void processReequest(char c) {
if(c == '\r') return; //if the code is CR, ignore it
if(c == '\n') { //if the code is NL, read the GET request
buff[count]='\0'; //put null character at the end
String buffS = buff; //convert to String
//Serial.print("command is: "); //for debug
//Serial.println(bufferS); //for degub
if(buffS.startsWith("GET /info")){
command = 0;
}
else if (buffS.startsWith("GET /number/")){
number = buffS.substring(12).toInt();//GET /number という文字列なので先頭から12文字(GET /number/)を削除
command = 1;
Serial.print("number:");
Serial.println(number);
}
Serial.print("command ==");
Serial.println(command);
isBlankLine = (count == 0); //and check if the line is empty
count=0;
}
else { //if the code is not control code, record it
isBlankLine = false;
if(count >= (BUFFLEN - 1) ) count=0; //if almost overflow, reset the counter
buff[count++]=c; //add char at the end of buffer
}
}
//最初に実行される関数
void setup() {
int status = WL_IDLE_STATUS;
int wifi_led_flag = 0;
pinMode(Blue_LED, OUTPUT);
Serial.begin(115200); // シリアル通信のボーレートを115200に設定
while (!Serial) ; // wait for serial port to connect.
WiFi.config(ip, gateway, subnet, DNS); // Set fixed IP address
while (status != WL_CONNECTED) {
Serial.print("\nAttempting to connect to SSID: ");
Serial.print(SSID);
WiFi.begin(SSID, PASSWORD);
for (int i=0; i<15; i++) { //wait up to 15 sec to be connected
delay(1000);
status = WiFi.status();
Serial.print(".");
if(wifi_led_flag == 0){
digitalWrite(Blue_LED, HIGH);
wifi_led_flag = 1;}
else{
digitalWrite(Blue_LED, LOW);
wifi_led_flag =0;}
if(status == WL_CONNECTED){
digitalWrite(Blue_LED, LOW);
break;}
}
}
xTaskCreatePinnedToCore(task0, "Task0", 4096, NULL, 1, NULL, 0); //core0でtask0を実行
}
//繰り返し呼び出される関数
void loop() {
}
void task0(void* arg){
server.begin(); //start the server
Serial.print("\nHTTP server started at: ");
Serial.println(WiFi.localIP());
while(1){
WiFiClient client = server.available();
if (client) {
Serial.println("new client");
number = 0;
while(client.connected()) {
if(client.available()) {
char c = client.read();
Serial.write(c);
processReequest(c);
//if the line is blank, the request has ended.
if(isBlankLine) {
//空行ならばリクエスト終了と判断して応答
// send a http response
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed
client.println();
client.println("");
client.println("");
if (command == 1){
client.println(number);
}
else if (command == 0){
client.print("http://");
client.print(ip);
client.println("/number/x (x is int) return x");
}
client.println("");
break;
}
}
}
}
delay(1);
}
}