Open sgawad opened 1 year ago
as discussed, a few C++ server generators have been added but none of these would meet your requirement right out-of-the-box and customize the templates (e.g. -t via CLI) seem to meet your requirement so far.
I have written some code to do the task (trying to mimic the pistache server c++) but although it compiles it seems to crash when the request is being passed to the overriding impl:
Apparently I can't attach cpp or zip so here is the code I have so far
/*
* ModuleApiImpl.h
*
*
*/
#ifndef MODULE_API_IMPL_H_
#define MODULE_API_IMPL_H_
#include <memory>
#include <ModuleApi.h>
namespace org::openapitools::server::api
{
//using namespace org::openapitools::server::model;
class ModuleApiImpl : public org::openapitools::server::api::ModuleApi {
public:
//The syntax : MuduleApi(server) after the constructor parameter list is called an initializer list. It allows you to pass arguments to the constructors of base classes and member variables.
//explicit ModuleApiImpl(const std::shared_ptr<AsyncWebServer>& server) : ModuleApi(*server), ptServer(server.get()) {}
//explicit ModuleApiImpl(std::shared_ptr<AsyncWebServer> serverPtr);
explicit ModuleApiImpl(std::shared_ptr<AsyncWebServer> serverPtr);
void rotor_get_over(AsyncWebServerRequest* request) override;
};
} // namespace org::openapitools::server::api
#endif
/*
*
* ModuleApiImpl.cpp
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "ModuleApiImpl.h"
namespace org::openapitools::server::api {
//using namespace org::openapitools::server::model;
//ModuleApiImpl::ModuleApiImpl(const std::shared_ptr<AsyncWebServer>& server) : ModuleApi(server), serverPtr_(server) {}
//ModuleApiImpl::ModuleApiImpl(std::shared_ptr<AsyncWebServer> serverPtr)
//: ModuleApi(serverPtr){}
ModuleApiImpl::ModuleApiImpl(std::shared_ptr<AsyncWebServer> serverPtr) : ModuleApi(serverPtr){}
void ModuleApiImpl::rotor_get_over(AsyncWebServerRequest* request){
Serial.print("rotor_get");
request->send(200, "text/plain", "Hello, GET: " + request->url() + "!");
}
}
/*
* ModuleApi.h
*
*
*/
#ifndef ModuleApi_H_
#define ModuleApi_H_
#include <Portenta_H7_AsyncWebServer.h>
//#include <optional>
#include <utility>
namespace org::openapitools::server::api {
class ModuleApi {
public:
//explicit ModuleApi(AsyncWebServer& server);
//void init();
static const std::string base;
//explicit ModuleApi(AsyncWebServer& server);
explicit ModuleApi(std::shared_ptr<AsyncWebServer> serverPtr);
virtual ~ModuleApi() = default;
void init();
virtual void rotor_get_over(AsyncWebServerRequest* request) = 0;
void rotor_get(AsyncWebServerRequest* request);
//void addRoute(const std::string& path, const std::string& httpMethod, std::function<void(AsyncWebServerRequest*)> callback);
void setupRoutes();
//void setupRoutes2();
void rotor_get_handler(AsyncWebServerRequest* request);
void rotor_over_get_handler(AsyncWebServerRequest* request);
protected:
std::shared_ptr<AsyncWebServer> serverPtr_;
};
} // namespace org::openapitools::server::api
#endif /* ModuleApi_H_ */
/**
* ModuleApi.cpp
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "ModuleApi.h"
#include "Helpers.h"
#include <ArduinoJson.h>
namespace org::openapitools::server::api {
ModuleApi::ModuleApi(std::shared_ptr<AsyncWebServer> serverPtr) : serverPtr_(serverPtr) {
Serial.println("instance of moduleAPI object created");
//server_ = server;
init();
//ptServer = &server;
}
void ModuleApi::init() {
Serial.println("init function called");
setupRoutes();
}
//The third argument passed to the on function is ModuleApi::rotor_get_handler, which is a member function of the ModuleApi class.
//However, the on function expects a callback function that is not a member function of a class.
//You can fix this issue by using a lambda function or std::bind to bind the rotor_get_handler member function to an instance of the ModuleApi class
//and pass it as the third argument to the on function.
void ModuleApi::setupRoutes(){
//lamda solution:
Serial.println("defining route rotor ");
serverPtr_->on("/rotor", HTTP_GET, [this](AsyncWebServerRequest *request){ this->rotor_get_handler(request); });
serverPtr_->on("/rotorover", HTTP_GET, [this](AsyncWebServerRequest *request){ this->rotor_over_get_handler(request); });
Serial.println("route rotor defined");
//bind solution:
//ptServer->on("/rotor", HTTP_GET, std::bind(&ModuleApi::rotor_get_handler, this, std::placeholders::_1));
}
void ModuleApi::rotor_get_handler(AsyncWebServerRequest *request){
Serial.println("rotor_get_handler called");
//this->rotor_get(request);
//ModuleApiImpl* impl = dynamic_cast<ModuleApiImpl*>(this);
this->rotor_get(request);
}
void ModuleApi::rotor_over_get_handler(AsyncWebServerRequest *request){
Serial.println("rotor_get_handler called");
Serial.println(request->url());
this->rotor_get_over(request);
//ModuleApiImpl* impl = static_cast<ModuleApiImpl*>(this);
//impl->rotor_get_over(request);
//this->rotor_get(request);
// ModuleApiImpl* impl = dynamic_cast<ModuleApiImpl*>(this);
// if (impl != nullptr) {
// impl->rotor_get_over(request);
// } else {
// Serial.println("Failed to cast 'this' to ModuleApiImpl*");
// }
}
void ModuleApi::rotor_get(AsyncWebServerRequest* request){
Serial.println("rotor_get");
Serial.println(request->url());
request->send(200, "text/plain", "Hello from API, GET: " + request->url() + "!");
}
}// namespace org::openapitools::server::api
the call to build the server in main.cpp are as follow:
defined as global:
std::shared_ptr<AsyncWebServer> serverPtr = std::make_shared<AsyncWebServer>(80);
in setup(){
org::openapitools::server::api::ModuleApiImpl ModuleApiImpl(serverPtr);
}
I have implemented a rotor and a rotor_over path in the api... the "rotor" callback method is within the ModuleApi.cpp and does respond in postman... although the server and microcontroller crashes not too long after. the rotor_over I tried to do the impl class and it never gets there.. As you will see in some of the comments lying around I have tried with other ways of getting the callback to respond but nothing worked so far.
So any advice or support from someone knowing about C++ callbacks in overriden classes + implementing it on a microcontroller would be very very welcome. Also since I am working on the arduino framework with PIO I can't really trace or debug which doesn't really help.
My target is to use it to develop a REST api for automation on a microcontroller (although it is a pretty large one it doesn't allow pistache, restbed or qt)
so I would need to generate some generic C++ code that would be able to interface with one of those (microcontroller) servers that use very similiar architecture: https://github.com/me-no-dev/ESPAsyncWebServe (ESP32) or https://github.com/khoih-prog/Portenta_H7_AsyncWebServer. (ARM)
The dependencies should be limited to whatever may run on an microcontroller.
I see in the road map that there is a mid term goal: C++ Server, any framework (server)
What does it actually mean? Is there some way to help or someone that could help me (mentoring).