Compare commits
3 Commits
63680cc379
...
552e085282
| Author | SHA1 | Date | |
|---|---|---|---|
| 552e085282 | |||
| 694d69252d | |||
| 083ce1a150 |
26
.clang-format
Normal file
26
.clang-format
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
Language: Cpp
|
||||||
|
|
||||||
|
IndentWidth: 4
|
||||||
|
UseTab: Never
|
||||||
|
|
||||||
|
PointerAlignment: Left
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
|
||||||
|
MaxEmptyLinesToKeep: 2
|
||||||
|
|
||||||
|
CompactNamespaces: true
|
||||||
|
FixNamespaceComments: true
|
||||||
|
|
||||||
|
LambdaBodyIndentation: Signature
|
||||||
|
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
AllowShortLambdasOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
|
||||||
|
AlignConsecutiveAssignments: true
|
||||||
|
AlignConsecutiveBitFields: true
|
||||||
|
AlignConsecutiveDeclarations: true
|
||||||
|
AlignConsecutiveMacros: true
|
||||||
|
|
||||||
1
components/http_server/CMakeLists.txt
Normal file
1
components/http_server/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
idf_component_register(INCLUDE_DIRS include REQUIRES util esp_http_server)
|
||||||
147
components/http_server/include/http/server.h
Normal file
147
components/http_server/include/http/server.h
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <esp_http_server.h>
|
||||||
|
|
||||||
|
#include <util/inplace_function.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define RESPONSE_BUFFER_LEN 512
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Types
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
|
||||||
|
enum class Method { get = HTTP_GET, post = HTTP_POST };
|
||||||
|
|
||||||
|
struct response_t {
|
||||||
|
response_t() = default;
|
||||||
|
response_t(const char* str) {
|
||||||
|
std::size_t respLen =
|
||||||
|
std::min(strlen(str), static_cast<unsigned>(RESPONSE_BUFFER_LEN));
|
||||||
|
std::copy(str, str + respLen, text.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<char, RESPONSE_BUFFER_LEN> text = {0};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct handler_t {
|
||||||
|
Method method;
|
||||||
|
const char* path;
|
||||||
|
inplace_function<response_t()> handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct server_settings_t {
|
||||||
|
int port = 80;
|
||||||
|
inplace_function<void()> on_error = [] {};
|
||||||
|
inplace_function<void()> on_not_found = [] {};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace http
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Implementation details
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
namespace http::detail {
|
||||||
|
|
||||||
|
|
||||||
|
inline auto& get_server() {
|
||||||
|
static httpd_handle_t server = nullptr;
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
inline auto& get_handler_storage() {
|
||||||
|
static std::array<inplace_function<response_t()>, N> handlers;
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
inline auto& get_esp_uri_storage() {
|
||||||
|
static std::array<httpd_uri_t, N> uris;
|
||||||
|
return uris;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Currently, the set handler is only valid for GET requests
|
||||||
|
template <std::size_t N, std::size_t I>
|
||||||
|
inline void set_handlers_impl(const handler_t (&handlers)[N]) {
|
||||||
|
auto& uriStorage = get_esp_uri_storage<N>();
|
||||||
|
|
||||||
|
uriStorage[I] = httpd_uri_t{
|
||||||
|
.uri = handlers[I].path,
|
||||||
|
.method = static_cast<httpd_method_t>(handlers[I].method),
|
||||||
|
.handler =
|
||||||
|
[](httpd_req_t* req) {
|
||||||
|
auto resp = get_handler_storage<N>()[I]();
|
||||||
|
httpd_resp_send(req, resp.text.data(), HTTPD_RESP_USE_STRLEN);
|
||||||
|
return ESP_OK;
|
||||||
|
},
|
||||||
|
.user_ctx = nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
httpd_register_uri_handler(get_server(), &(uriStorage[I]));
|
||||||
|
|
||||||
|
if constexpr (I < N - 1) set_handlers_impl<N, I + 1>(handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace http::detail
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Public API
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Give request information to handlers
|
||||||
|
template <std::size_t N>
|
||||||
|
inline void set_handlers(const handler_t (&handlers)[N]) {
|
||||||
|
auto& handlerStorage = detail::get_handler_storage<N>();
|
||||||
|
std::transform(handlers, handlers + N, handlerStorage.begin(),
|
||||||
|
[](const auto& handler) {
|
||||||
|
return handler.handler;
|
||||||
|
});
|
||||||
|
|
||||||
|
detail::set_handlers_impl<N, 0>(handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void start_server(server_settings_t settings) {
|
||||||
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||||
|
config.server_port = settings.port;
|
||||||
|
|
||||||
|
if (httpd_start(&detail::get_server(), &config) != ESP_OK) {
|
||||||
|
throw std::runtime_error("Failed to start server");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Set error and not found handlers
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void stop_server() {
|
||||||
|
if (httpd_stop(detail::get_server()) != ESP_OK) {
|
||||||
|
throw std::runtime_error("Failed to stop server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace http
|
||||||
@ -59,7 +59,7 @@ public:
|
|||||||
|
|
||||||
return_t operator()(args_t... args) {
|
return_t operator()(args_t... args) {
|
||||||
if (mWrapper)
|
if (mWrapper)
|
||||||
mWrapper(mStorage, args...);
|
return mWrapper(mStorage, args...);
|
||||||
else
|
else
|
||||||
throw std::bad_function_call();
|
throw std::bad_function_call();
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ public:
|
|||||||
requires std::is_invocable_r_v<return_t, decltype(F), args_t...>
|
requires std::is_invocable_r_v<return_t, decltype(F), args_t...>
|
||||||
void bind() {
|
void bind() {
|
||||||
mWrapper = [](storage_t, args_t... args) {
|
mWrapper = [](storage_t, args_t... args) {
|
||||||
std::invoke(F, std::forward<args_t>(args)...);
|
return std::invoke(F, std::forward<args_t>(args)...);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +96,8 @@ public:
|
|||||||
new (mStorage)(class_t*){&c};
|
new (mStorage)(class_t*){&c};
|
||||||
|
|
||||||
mWrapper = [](storage_t storage, args_t... args) {
|
mWrapper = [](storage_t storage, args_t... args) {
|
||||||
std::invoke(F, reinterpret_cast<class_t*>(storage),
|
return std::invoke(F, reinterpret_cast<class_t*>(storage),
|
||||||
std::forward<args_t>(args)...);
|
std::forward<args_t>(args)...);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,8 +111,8 @@ public:
|
|||||||
void bind(F f) {
|
void bind(F f) {
|
||||||
new (mStorage) F{std::move(f)};
|
new (mStorage) F{std::move(f)};
|
||||||
mWrapper = [](storage_t storage, args_t... args) {
|
mWrapper = [](storage_t storage, args_t... args) {
|
||||||
std::invoke(*reinterpret_cast<F*>(storage),
|
return std::invoke(*reinterpret_cast<F*>(storage),
|
||||||
std::forward<args_t>(args)...);
|
std::forward<args_t>(args)...);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
set(SOURCES src/main.cpp)
|
set(SOURCES src/main.cpp)
|
||||||
set(INCLUDES include)
|
set(INCLUDES include)
|
||||||
|
|
||||||
idf_component_register(SRCS ${SOURCES} INCLUDE_DIRS ${INCLUDES} REQUIRES wifi nvs nanofmt)
|
idf_component_register(SRCS ${SOURCES} INCLUDE_DIRS ${INCLUDES} REQUIRES wifi nvs nanofmt http_server)
|
||||||
|
|||||||
@ -1,45 +1,60 @@
|
|||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#include <http/server.h>
|
||||||
#include <nvs/nvs.h>
|
#include <nvs/nvs.h>
|
||||||
#include <wifi/wifi.h>
|
#include <wifi/wifi.h>
|
||||||
|
|
||||||
#include "esp_log.h"
|
|
||||||
|
void start_ap() {
|
||||||
|
nvs::init();
|
||||||
|
wifi::init();
|
||||||
|
|
||||||
|
wifi::set_mode(wifi::Mode::soft_ap);
|
||||||
|
wifi::configure_soft_ap(
|
||||||
|
"HyperLink", "1234567890",
|
||||||
|
{.connected =
|
||||||
|
[](auto mac, auto aid) {
|
||||||
|
ESP_LOGI("DEBUG - ap callback", "Connected to mac %s",
|
||||||
|
mac.data());
|
||||||
|
},
|
||||||
|
.disconnected =
|
||||||
|
[](auto mac, auto aid) {
|
||||||
|
ESP_LOGI("DEBUG - ap callback", "Disconnected from mac %s",
|
||||||
|
mac.data());
|
||||||
|
}});
|
||||||
|
wifi::start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_http_server() {
|
||||||
|
http::start_server({.port = 80,
|
||||||
|
.on_error =
|
||||||
|
[]() {
|
||||||
|
// TODO
|
||||||
|
},
|
||||||
|
.on_not_found =
|
||||||
|
[]() {
|
||||||
|
// TODO
|
||||||
|
}});
|
||||||
|
http::set_handlers({{http::Method::get, "/",
|
||||||
|
[]() {
|
||||||
|
return http::response_t{
|
||||||
|
"<html><body style=\"background:black; color: "
|
||||||
|
"white\">Home</body></html>"};
|
||||||
|
}},
|
||||||
|
{http::Method::get, "/hello1",
|
||||||
|
[]() {
|
||||||
|
return http::response_t{"Hello 1"};
|
||||||
|
}},
|
||||||
|
{http::Method::get, "/hello2", []() {
|
||||||
|
return http::response_t{"Hello 2"};
|
||||||
|
}}});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" void app_main(void) {
|
extern "C" void app_main(void) {
|
||||||
try {
|
try {
|
||||||
nvs::init();
|
start_ap();
|
||||||
wifi::init();
|
start_http_server();
|
||||||
|
|
||||||
// wifi::set_mode(wifi::Mode::station);
|
|
||||||
// wifi::configure_station(
|
|
||||||
// "Vodafone-180C", "giraffen!",
|
|
||||||
// {.stationStarted = []() { wifi::station_connect(); },
|
|
||||||
// .disconnected = [] { wifi::station_connect(); },
|
|
||||||
// .gotIp =
|
|
||||||
// [](auto ip) {
|
|
||||||
// ESP_LOGI("DEBUG - ip callback ", "Got ip: %s",
|
|
||||||
// ip.data());
|
|
||||||
// }});
|
|
||||||
// wifi::start();
|
|
||||||
|
|
||||||
// wifi::stop();
|
|
||||||
// wifi::clear_callbacks();
|
|
||||||
// wifi::stop();
|
|
||||||
// wifi::deinit();
|
|
||||||
|
|
||||||
wifi::set_mode(wifi::Mode::soft_ap);
|
|
||||||
wifi::configure_soft_ap(
|
|
||||||
"HyperLink", "1234567890",
|
|
||||||
{.connected =
|
|
||||||
[](auto mac, auto aid) {
|
|
||||||
ESP_LOGI("DEBUG - ap callback", "Connected to mac %s",
|
|
||||||
mac.data());
|
|
||||||
},
|
|
||||||
.disconnected =
|
|
||||||
[](auto mac, auto aid) {
|
|
||||||
ESP_LOGI("DEBUG - ap callback", "Disconnected from mac %s",
|
|
||||||
mac.data());
|
|
||||||
}});
|
|
||||||
wifi::start();
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
ESP_LOGE("main", "Exception: %s", e.what());
|
ESP_LOGE("main", "Exception: %s", e.what());
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user