yoursunny / esp32cam

OV2640 camera on ESP32-CAM, Arduino library
https://esp32cam.yoursunny.dev
ISC License
472 stars 168 forks source link

Cannot bind non-const lvalue reference of type 'Client&' to an rvalue of type 'Client' #58

Closed victorbnl closed 1 week ago

victorbnl commented 1 week ago

I have a class which has a WebServer webServer member, as well as a setup function, in which I declare the handlers, including one for testing the camera, as follows.

  webServer.on("/photo", HTTP_GET, [&] {
    auto frame = esp32cam::capture();
    webServer.setContentLength(frame->size());
    webServer.send(200, "image/jpeg");
    frame->writeTo(webServer.client());
  });

However this produces the following error:

src/server.cpp: In lambda function:
src/server.cpp:37:36: error: cannot bind non-const lvalue reference of type 'Client&' to an rvalue of type 'Client'
     frame->writeTo(webServer.client());
                    ~~~~~~~~~~~~~~~~^~
In file included from .pio/libdeps/debug/esp32cam/src/internal/mjpeg.hpp:4,
                 from .pio/libdeps/debug/esp32cam/src/esp32cam.h:11,
                 from src/server.cpp:3:
.pio/libdeps/debug/esp32cam/src/internal/frame.hpp:49:8: note:   initializing argument 1 of 'bool esp32cam::Frame::writeTo(Client&, int)'
   bool writeTo(Client& os, int timeout = 10000);
        ^~~~~~~
*** [.pio/build/debug/src/server.cpp.o] Error 1

I don’t understand what, in my code, differs from the examples.

Full class ```cpp #include #include "laser/laser.h" class LaserServer { private: WebServer webServer; Laser* laser; public: LaserServer(int port, Laser &laser); void setup(); void handle(); }; #include LaserServer::LaserServer(int port, Laser &laser_) : webServer(port) { laser = &laser_; } void LaserServer::setup() { webServer.on("/ping", [&]() { webServer.send(200, "text/plain", "Pong"); }); webServer.on("/laser-on", [&]() { if (laser->start()) { webServer.send(200); } else { webServer.send(500); } }); webServer.on("/measure", [&]() { int res = laser->measure(); if (res == -1) { webServer.send(500); } else { char resText[10]; itoa(res, resText, 10); webServer.send(200, "text/plain", resText); } }); webServer.on("/photo", HTTP_GET, [&] { auto frame = esp32cam::capture(); webServer.setContentLength(frame->size()); webServer.send(200, "image/jpeg"); frame->writeTo(webServer.client()); }); webServer.begin(); } void LaserServer::handle() { webServer.handleClient(); } ```
yoursunny commented 1 week ago

You have arduino-esp32 v2.x or older, in which WebServer::client() returns a copy of WiFiClient: https://github.com/espressif/arduino-esp32/blob/2.0.17/libraries/WebServer/src/WebServer.h#L112

esp32cam library has been upgraded to work with arduino-esp32 v3.x or newer, in which WebServer::client() returns a reference of NetworkClient&: https://github.com/espressif/arduino-esp32/blob/3.0.0/libraries/WebServer/src/WebServer.h#L161

You need to upgrade to arduino-esp32 v3.x through Arduino Boards Manager.

victorbnl commented 1 week ago

Uh, PlatformIO does not seem to support arduino-esp32 v3.x natively at the moment. Adding the following into my project’s platform.ini worked as a workaround.

platform_packages =
    platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc1
    platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1