ESP32/ArduinoでWebServer.hとHttpsOTAUpdate.hの共存について

Arduino/ESP32Arduino,ESP32,HttpsOTAUpdate,redeclaration,WebServer

一個前の記事で、Webサーバー経由でのOTAアップデートを試してみたところサクサク動きましたので、本題の方に組み込もうとしてみたところエラーになってしまい。

HttpsOTAUpdate.h と WebServer.h をincludeするとエラーになるみたいですん。

ソースを一応貼っておきます。

#include <Arduino.h>

#include <HttpsOTAUpdate.h>
#include <WebServer.h>

void setup()
{
}

void loop()
{
}

そんでエラー内容は以下に。

長いのでアコーディオンで。

> Executing task in folder ExampleController: C:\Users\YOUR_NAME\.platformio\penv\Scripts\platformio.exe run <

Processing nodemcu-32s (platform: espressif32; board: nodemcu-32s; framework: arduino)
---------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/nodemcu-32s.html
PLATFORM: Espressif 32 (3.1.0) > NodeMCU-32S
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (esp-prog) External (esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 3.10005.210308 (1.0.5)
 - tool-esptoolpy 1.30000.201119 (3.0.0)
 - toolchain-xtensa32 2.50200.97 (5.2.0)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 29 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <Update> 1.0   
|-- <WebServer> 1.0
|   |-- <WiFi> 1.0 
|   |-- <FS> 1.0
Building in release mode
Compiling .pio\build\nodemcu-32s\src\main.cpp.o
Generating partitions .pio\build\nodemcu-32s\partitions.bin
Compiling .pio\build\nodemcu-32s\lib8cd\Update\HttpsOTAUpdate.cpp.o
Compiling .pio\build\nodemcu-32s\lib8cd\Update\Updater.cpp.o
Compiling .pio\build\nodemcu-32s\libd3a\WiFi\ETH.cpp.o
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/WebServer.h:30:0,
                 from src\main.cpp:4:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/HTTP_Method.h:5:18: error: redeclaration of 'HTTP_GET'
   HTTP_GET     = 0b00000001,
                  ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\esp_http_client/esp_http_client.h:19:0,
                 from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\Update\src/HttpsOTAUpdate.h:1,
                 from src\main.cpp:3:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:138:31: note: previous declaration 'http_method HTTP_GET'
 #define XX(num, name, string) HTTP_##name = num,
                               ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:96:3: note: in expansion of macro 'XX'
   XX(1,  GET,         GET)          \
   ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/WebServer.h:30:0,
                 from src\main.cpp:4:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/HTTP_Method.h:6:18: error: redeclaration of 'HTTP_POST'
   HTTP_POST    = 0b00000010,
                  ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\esp_http_client/esp_http_client.h:19:0,
                 from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\Update\src/HttpsOTAUpdate.h:1,
                 from src\main.cpp:3:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:138:31: note: previous declaration 'http_method HTTP_POST'
 #define XX(num, name, string) HTTP_##name = num,
                               ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:98:3: note: in expansion of macro 'XX'
   XX(3,  POST,        POST)         \
   ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/WebServer.h:30:0,
                 from src\main.cpp:4:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/HTTP_Method.h:7:18: error: redeclaration of 'HTTP_DELETE'
   HTTP_DELETE  = 0b00000100,
                  ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\esp_http_client/esp_http_client.h:19:0,
                 from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\Update\src/HttpsOTAUpdate.h:1,
                 from src\main.cpp:3:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:138:31: note: previous declaration 'http_method HTTP_DELETE'
 #define XX(num, name, string) HTTP_##name = num,
                               ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:95:3: note: in expansion of macro 'XX'
   XX(0,  DELETE,      DELETE)       \
   ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/WebServer.h:30:0,
                 from src\main.cpp:4:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/HTTP_Method.h:8:18: error: redeclaration of 'HTTP_PUT'
   HTTP_PUT     = 0b00001000,
                  ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\esp_http_client/esp_http_client.h:19:0,
                 from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\Update\src/HttpsOTAUpdate.h:1,
                 from src\main.cpp:3:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:138:31: note: previous declaration 'http_method HTTP_PUT'
 #define XX(num, name, string) HTTP_##name = num,
                               ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:99:3: note: in expansion of macro 'XX'
   XX(4,  PUT,         PUT)          \
   ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/WebServer.h:30:0,
                 from src\main.cpp:4:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/HTTP_Method.h:9:18: error: redeclaration of 'HTTP_PATCH'        
   HTTP_PATCH   = 0b00010000,
                  ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\esp_http_client/esp_http_client.h:19:0,
                 from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\Update\src/HttpsOTAUpdate.h:1,
                 from src\main.cpp:3:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:138:31: note: previous declaration 'http_method HTTP_PATCH'
 #define XX(num, name, string) HTTP_##name = num,
                               ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:128:3: note: in expansion of macro 'XX'
   XX(28, PATCH,       PATCH)        \
   ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/WebServer.h:30:0,
                 from src\main.cpp:4:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/HTTP_Method.h:10:18: error: redeclaration of 'HTTP_HEAD'        
   HTTP_HEAD    = 0b00100000,
                  ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\esp_http_client/esp_http_client.h:19:0,
                 from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\Update\src/HttpsOTAUpdate.h:1,
                 from src\main.cpp:3:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:138:31: note: previous declaration 'http_method HTTP_HEAD'
 #define XX(num, name, string) HTTP_##name = num,
                               ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:97:3: note: in expansion of macro 'XX'
   XX(2,  HEAD,        HEAD)         \
   ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/WebServer.h:30:0,
                 from src\main.cpp:4:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/HTTP_Method.h:11:18: error: redeclaration of 'HTTP_OPTIONS'     
   HTTP_OPTIONS = 0b01000000,
                  ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\esp_http_client/esp_http_client.h:19:0,
                 from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\Update\src/HttpsOTAUpdate.h:1,
                 from src\main.cpp:3:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:138:31: note: previous declaration 'http_method HTTP_OPTIONS'
 #define XX(num, name, string) HTTP_##name = num,
                               ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:102:3: note: in expansion of macro 'XX'
   XX(6,  OPTIONS,     OPTIONS)      \
   ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^
Compiling .pio\build\nodemcu-32s\libd3a\WiFi\WiFi.cpp.o
*** [.pio\build\nodemcu-32s\src\main.cpp.o] Error 1
============================================================== [FAILED] Took 6.36 seconds ==============================================================
ターミナル プロセス "C:\Users\YOUR_NAME\.platformio\penv\Scripts\platformio.exe 'run'" が終了コード 1 で終了しました。

ターミナルはタスクで再利用されます、閉じるには任意のキーを押してください。

内容を見ると、どうやらHTTPMethodを再定義してしまっている様子。

とりあえずひと塊を取り出してHTTP_GETだけ見てみると

In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/WebServer.h:30:0,
                 from src\main.cpp:4:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/HTTP_Method.h:5:18: error: redeclaration of 'HTTP_GET'
   HTTP_GET     = 0b00000001,
                  ^
In file included from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\esp_http_client/esp_http_client.h:19:0,
                 from C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\libraries\Update\src/HttpsOTAUpdate.h:1,
                 from src\main.cpp:3:
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:138:31: note: previous declaration 'http_method HTTP_GET'
 #define XX(num, name, string) HTTP_##name = num,
                               ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:96:3: note: in expansion of macro 'XX'
   XX(1,  GET,         GET)          \
   ^
C:\Users\YOUR_NAME\.platformio\packages\framework-arduinoespressif32\tools\sdk\include\nghttp/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^
  • WebServer.hでHTTP_Method.hを呼んでるけど、http_methodとしてHTTP_GETを再定義しようとしてるze!
  • 参考までにHttpsOTAUpdate.hでhttp_parser.hを呼んでるけど、そこでhttp_methodとしてHTTP_GETを既に定義してるna!

って事らしい。

ライブラリに手を入れるのはやりたく無いのでどうしようかとWebを漁ってみると、こんな記事が。

GitHub:Redeclaration errors when including both WebServer.h and HttpsOTAUpdate.h #4758

うん、ほぼ一緒。

この質問の中で、以下のIssuesを紹介していたので見てみますと

GitHub:Using both WebServer.h and esp_http_server.h at the same time??? #1184

とりあえず一個目のやつは適当な別名で定義しとけ。

後で正しい名前で定義するから一緒やろ。

的な事が書かれている。

ほんとか?と思いつつも中身を見てみると、

libraries\WebServer\src\HTTP_Method.h

#ifndef _HTTP_Method_H_
#define _HTTP_Method_H_

typedef enum {
  HTTP_GET     = 0b00000001,
  HTTP_POST    = 0b00000010,
  HTTP_DELETE  = 0b00000100,
  HTTP_PUT     = 0b00001000,
  HTTP_PATCH   = 0b00010000,
  HTTP_HEAD    = 0b00100000,
  HTTP_OPTIONS = 0b01000000,
  HTTP_ANY     = 0b01111111,
} HTTPMethod;

#endif /* _HTTP_Method_H_ */

tools\sdk\include\nghttp\http_parser.h

/* Request Methods */
#define HTTP_METHOD_MAP(XX)         \
  XX(0,  DELETE,      DELETE)       \
  XX(1,  GET,         GET)          \
  XX(2,  HEAD,        HEAD)         \
  XX(3,  POST,        POST)         \
  XX(4,  PUT,         PUT)          \
  /* pathological */                \
  XX(5,  CONNECT,     CONNECT)      \
  XX(6,  OPTIONS,     OPTIONS)      \
  XX(7,  TRACE,       TRACE)        \
  /* WebDAV */                      \
  XX(8,  COPY,        COPY)         \
  XX(9,  LOCK,        LOCK)         \
  XX(10, MKCOL,       MKCOL)        \
  XX(11, MOVE,        MOVE)         \
  XX(12, PROPFIND,    PROPFIND)     \
  XX(13, PROPPATCH,   PROPPATCH)    \
  XX(14, SEARCH,      SEARCH)       \
  XX(15, UNLOCK,      UNLOCK)       \
  XX(16, BIND,        BIND)         \
  XX(17, REBIND,      REBIND)       \
  XX(18, UNBIND,      UNBIND)       \
  XX(19, ACL,         ACL)          \
  /* subversion */                  \
  XX(20, REPORT,      REPORT)       \
  XX(21, MKACTIVITY,  MKACTIVITY)   \
  XX(22, CHECKOUT,    CHECKOUT)     \
  XX(23, MERGE,       MERGE)        \
  /* upnp */                        \
  XX(24, MSEARCH,     M-SEARCH)     \
  XX(25, NOTIFY,      NOTIFY)       \
  XX(26, SUBSCRIBE,   SUBSCRIBE)    \
  XX(27, UNSUBSCRIBE, UNSUBSCRIBE)  \
  /* RFC-5789 */                    \
  XX(28, PATCH,       PATCH)        \
  XX(29, PURGE,       PURGE)        \
  /* CalDAV */                      \
  XX(30, MKCALENDAR,  MKCALENDAR)   \
  /* RFC-2068, section 19.6.1.2 */  \
  XX(31, LINK,        LINK)         \
  XX(32, UNLINK,      UNLINK)       \

enum http_method
  {
#define XX(num, name, string) HTTP_##name = num,
  HTTP_METHOD_MAP(XX)
#undef XX
  };

HTTP_ANYが無いけどまぁ一緒っぽいですぬ。

というわけで後者の方法でも良さそうです。

もっとスマートにならんかいなと思って調べてみましたら、12日前のコミットでWebServerの方のHTTP_Method.hで修正が入っている様子。

Use HTTP method table from ESP-IDF’s nghttp (#4900)
libraries/WebServer/src/HTTP_Method.h

ベタ書きをやめてhttp_parser.hの方の定義を使う様に変え、再定義をifndefで抑止している様ですね。

ついでに未定義の0b01111111のHTTP_ANYを個別に追加しているのは可愛い。

というわけでstableリリースになれば勝手に直ると思いますが、、、

現状では以下の様に修正すれば問題無く使えそうです。

#include <Arduino.h>

#include <HttpsOTAUpdate.h>
#ifndef _HTTP_Method_H_
#define _HTTP_Method_H_
#include <http_parser.h>
typedef enum http_method HTTPMethod;
#define HTTP_ANY (HTTPMethod)(255)
#endif /* _HTTP_Method_H_ */
#include <WebServer.h>

void setup()
{
}

void loop()
{
}

ちょっと引っかかったのでメモにでも・・・。