Compare commits
5 Commits
f3df59b0fe
...
57d068ffad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57d068ffad | ||
|
|
b42bb7efa9 | ||
|
|
d012620386 | ||
|
|
2dd46ee686 | ||
|
|
0ed3d69906 |
@ -3,4 +3,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
project(hello_world)
|
project(esp-vfd-clock)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS "main.cpp" "wifi_provisioner.cpp"
|
SRCS "main.cpp" "wifi_provisioner.cpp" "clock_core.cpp"
|
||||||
INCLUDE_DIRS ""
|
INCLUDE_DIRS ""
|
||||||
REQUIRES nvs_flash esp_wifi esp_http_server etlcpp json
|
REQUIRES nvs_flash esp_wifi esp_http_server etlcpp json
|
||||||
EMBED_FILES "${CMAKE_CURRENT_LIST_DIR}/static/index.html"
|
EMBED_FILES "${CMAKE_CURRENT_LIST_DIR}/static/index.html"
|
||||||
|
|||||||
166
firmware/main/clock_core.cpp
Normal file
166
firmware/main/clock_core.cpp
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
//
|
||||||
|
// Created by erki on 25/01/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "clock_core.hpp"
|
||||||
|
|
||||||
|
#include "esp_expected.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <esp_event.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <esp_netif.h>
|
||||||
|
#include <esp_netif_sntp.h>
|
||||||
|
#include <esp_wifi.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
const char* TAG = "clock_core";
|
||||||
|
|
||||||
|
constexpr EventBits_t WIFI_FAIL_BIT = BIT0;
|
||||||
|
constexpr EventBits_t WIFI_CONNECTED_BIT = BIT1;
|
||||||
|
constexpr EventBits_t SNTP_SYNCED = BIT2;
|
||||||
|
EventGroupHandle_t clock_core_event_group_;
|
||||||
|
|
||||||
|
void wifiEventHandler(void* arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void* event_data)
|
||||||
|
{
|
||||||
|
static int retry_num = 0;
|
||||||
|
|
||||||
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
|
||||||
|
{
|
||||||
|
esp_wifi_connect();
|
||||||
|
}
|
||||||
|
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
|
||||||
|
{
|
||||||
|
if (retry_num < 10)
|
||||||
|
{
|
||||||
|
esp_wifi_connect();
|
||||||
|
retry_num++;
|
||||||
|
ESP_LOGI(TAG, "Retrying to connect to AP.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xEventGroupSetBits(clock_core_event_group_, WIFI_FAIL_BIT);
|
||||||
|
}
|
||||||
|
ESP_LOGW(TAG, "Connection to AP failed.");
|
||||||
|
}
|
||||||
|
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
|
||||||
|
{
|
||||||
|
auto* event = static_cast<ip_event_got_ip_t*>(event_data);
|
||||||
|
ESP_LOGI(TAG, "Connected to AP. Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
|
||||||
|
retry_num = 0;
|
||||||
|
|
||||||
|
xEventGroupSetBits(clock_core_event_group_, WIFI_CONNECTED_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sntpEventHandler(struct timeval*)
|
||||||
|
{
|
||||||
|
xEventGroupSetBits(clock_core_event_group_, SNTP_SYNCED);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t sntpInitialize()
|
||||||
|
{
|
||||||
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
|
||||||
|
config.smooth_sync = true;
|
||||||
|
config.server_from_dhcp = true;
|
||||||
|
config.renew_servers_after_new_IP = true;
|
||||||
|
config.sync_cb = sntpEventHandler;
|
||||||
|
config.start = false;
|
||||||
|
config.ip_event_to_renew = IP_EVENT_STA_GOT_IP;
|
||||||
|
|
||||||
|
return esp_netif_sntp_init(&config);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::expected<void, esp_err_t> wifiInitialize(const char* wifi_ssid, const char* wifi_password)
|
||||||
|
{
|
||||||
|
TRY_ESP(esp_netif_init());
|
||||||
|
TRY_ESP(esp_event_loop_create_default());
|
||||||
|
esp_netif_create_default_wifi_sta();
|
||||||
|
|
||||||
|
wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
TRY_ESP(esp_wifi_init(&config));
|
||||||
|
|
||||||
|
TRY_ESP(sntpInitialize());
|
||||||
|
|
||||||
|
esp_event_handler_instance_t instance_any_id;
|
||||||
|
esp_event_handler_instance_t instance_got_ip;
|
||||||
|
TRY_ESP(esp_event_handler_instance_register(WIFI_EVENT,
|
||||||
|
ESP_EVENT_ANY_ID,
|
||||||
|
&wifiEventHandler,
|
||||||
|
nullptr,
|
||||||
|
&instance_any_id));
|
||||||
|
TRY_ESP(esp_event_handler_instance_register(IP_EVENT,
|
||||||
|
IP_EVENT_STA_GOT_IP,
|
||||||
|
&wifiEventHandler,
|
||||||
|
nullptr,
|
||||||
|
&instance_got_ip));
|
||||||
|
|
||||||
|
wifi_sta_config_t sta_config;
|
||||||
|
std::memset(&sta_config, 0, sizeof(sta_config));
|
||||||
|
std::strncpy((char*) sta_config.ssid, wifi_ssid, 32);
|
||||||
|
std::strncpy((char*) sta_config.password, wifi_password, 64);
|
||||||
|
sta_config.threshold.authmode = WIFI_AUTH_WPA2_PSK;
|
||||||
|
|
||||||
|
wifi_config_t wifi_config = { .sta = sta_config };
|
||||||
|
|
||||||
|
TRY_ESP(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||||
|
TRY_ESP(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||||
|
TRY_ESP(esp_wifi_start());
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace clock_core
|
||||||
|
{
|
||||||
|
|
||||||
|
void run(const char* wifi_ssid, const char* wifi_password)
|
||||||
|
{
|
||||||
|
clock_core_event_group_ = xEventGroupCreate();
|
||||||
|
|
||||||
|
if (const auto res = wifiInitialize(wifi_ssid, wifi_password);
|
||||||
|
!res.has_value())
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "WiFi setup errored in clock_core::run. Error: %s", esp_err_to_name(res.error()));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const EventBits_t bits = xEventGroupWaitBits(clock_core_event_group_,
|
||||||
|
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT | SNTP_SYNCED,
|
||||||
|
pdTRUE,
|
||||||
|
pdFALSE,
|
||||||
|
portMAX_DELAY);
|
||||||
|
|
||||||
|
if (bits & WIFI_CONNECTED_BIT)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "WiFi setup in clock_core::run successful.");
|
||||||
|
if (const auto res = esp_netif_sntp_start();
|
||||||
|
res != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "SNTP setup failed. Error: %s", esp_err_to_name(res));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bits & WIFI_FAIL_BIT)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "WiFi setup in clock_core::run failed.");
|
||||||
|
}
|
||||||
|
else if (bits & SNTP_SYNCED)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "SNTP sync successful.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "WiFi setup encountered an unexpected set of bits. %lu", bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
firmware/main/clock_core.hpp
Normal file
12
firmware/main/clock_core.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Created by erki on 25/01/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace clock_core
|
||||||
|
{
|
||||||
|
|
||||||
|
void run(const char* wifi_ssid, const char* wifi_password);
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,7 +5,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <expected>
|
#include <expected>
|
||||||
|
#include <source_location>
|
||||||
|
#include <string_view>
|
||||||
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <esp_err.h>
|
#include <esp_err.h>
|
||||||
|
#include <esp_rom_sys.h>
|
||||||
|
|
||||||
#define TRY(x) ({ \
|
#define TRY(x) ({ \
|
||||||
const auto& _x = (x); \
|
const auto& _x = (x); \
|
||||||
@ -21,3 +27,33 @@
|
|||||||
return std::unexpected(_x); \
|
return std::unexpected(_x); \
|
||||||
_x; \
|
_x; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
[[noreturn]] inline void abortWithError(const char* error, const std::source_location location = std::source_location::current())
|
||||||
|
{
|
||||||
|
esp_rom_printf("abortWithError called, reason: %s\n", error);
|
||||||
|
esp_rom_printf("file: \"%s\" line %d\n", location.file_name(), location.line());
|
||||||
|
if (location.function_name() != nullptr)
|
||||||
|
esp_rom_printf("func: %s\n", location.function_name());
|
||||||
|
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Expected>
|
||||||
|
decltype(auto) unwrapOrAbort(Expected&& expected, const std::source_location location = std::source_location::current())
|
||||||
|
{
|
||||||
|
if (!expected.has_value())
|
||||||
|
abortWithError("Unwrapped an errored expected.", location);
|
||||||
|
else
|
||||||
|
return std::forward<Expected>(expected).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Expected, typename F>
|
||||||
|
decltype(auto) unwrapOr(Expected&& expected, F&& f)
|
||||||
|
{
|
||||||
|
if (!expected.has_value())
|
||||||
|
std::invoke(std::forward<F>(f), expected.error());
|
||||||
|
else
|
||||||
|
return std::forward<Expected>(expected).value();
|
||||||
|
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
|||||||
@ -1,16 +1,17 @@
|
|||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "nvs.h"
|
#include "nvs.h"
|
||||||
#include "nvs_handle.hpp"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <cinttypes>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <expected>
|
#include <expected>
|
||||||
|
|
||||||
|
#include "esp_expected.hpp"
|
||||||
#include "wifi_provisioner.hpp"
|
#include "wifi_provisioner.hpp"
|
||||||
|
#include "clock_core.hpp"
|
||||||
|
|
||||||
extern "C" void app_main(void)
|
extern "C" void app_main(void)
|
||||||
{
|
{
|
||||||
@ -25,9 +26,10 @@ extern "C" void app_main(void)
|
|||||||
|
|
||||||
ESP_ERROR_CHECK(err);
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
auto* provisioner = new WifiProvisioner("wifi_settings", [](const auto& params)
|
auto* provisioner = new WifiProvisioner("wifi_settings", [task_id = xTaskGetCurrentTaskHandle()](const auto& params)
|
||||||
{
|
{
|
||||||
printf("Settings successfully done.");
|
printf("Settings successfully done.");
|
||||||
|
xTaskNotify(task_id, 0, eNoAction);
|
||||||
});
|
});
|
||||||
if (!provisioner->addParameter("SSID", "ssid", WifiProvisioner::Parameter::Type::STRING).has_value())
|
if (!provisioner->addParameter("SSID", "ssid", WifiProvisioner::Parameter::Type::STRING).has_value())
|
||||||
{
|
{
|
||||||
@ -41,12 +43,45 @@ extern "C" void app_main(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo: Remove later.
|
||||||
|
// provisioner->clearSettings();
|
||||||
|
|
||||||
if (!provisioner->parametersAreConfigured())
|
if (!provisioner->parametersAreConfigured())
|
||||||
{
|
{
|
||||||
auto result = provisioner->startProvisioning();
|
auto result = provisioner->startProvisioning();
|
||||||
if (!result.has_value())
|
if (!result.has_value())
|
||||||
printf("Error: %s\n", esp_err_to_name(result.error()));
|
{
|
||||||
else
|
ESP_ERROR_CHECK(result.error());
|
||||||
printf("Provisioning started...\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Provisioning started...\n");
|
||||||
|
|
||||||
|
const auto notification_received = xTaskNotifyWait(pdFALSE, ULONG_MAX, nullptr, portMAX_DELAY);
|
||||||
|
if (notification_received == pdPASS)
|
||||||
|
{
|
||||||
|
printf("Notification happened.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
abortWithError("Main task notification timed out.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto password = unwrapOrAbort(provisioner->getParameter("password")
|
||||||
|
.and_then([] (const auto& value)
|
||||||
|
{
|
||||||
|
return value.template getValue<etl::string<100>>();
|
||||||
|
}));
|
||||||
|
const auto ssid = unwrapOrAbort(provisioner->getParameter("ssid")
|
||||||
|
.and_then([] (const auto& value)
|
||||||
|
{
|
||||||
|
return value.template getValue<etl::string<100>>();
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Pack up the provisioner.
|
||||||
|
delete provisioner;
|
||||||
|
|
||||||
|
printf("We now have a wifi with SSID: %s, password: %s\n", ssid.c_str(), password.c_str());
|
||||||
|
|
||||||
|
clock_core::run(ssid.c_str(), password.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ extern const char index_end[] asm("_binary_index_html_end");
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
const char* TAG = "wifi softAP";
|
const char* TAG = "ParamProvisioner";
|
||||||
const char* NVS_IS_INITED = "_is_inited";
|
const char* NVS_IS_INITED = "_is_inited";
|
||||||
|
|
||||||
ssize_t indexHtmlLength()
|
ssize_t indexHtmlLength()
|
||||||
@ -156,20 +156,23 @@ esp_err_t parametersGetHandler_(httpd_req_t* req)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::expected<WifiProvisioner::Parameter::Value, esp_err_t> WifiProvisioner::Parameter::getValue(nvs::NVSHandle* file_handle) const
|
std::expected<WifiProvisioner::Parameter::Value, esp_err_t> WifiProvisioner::Parameter::tryReadAndAssignValue(nvs::NVSHandle* file_handle)
|
||||||
{
|
{
|
||||||
if (type == Type::INT)
|
if (type == Type::INT)
|
||||||
{
|
{
|
||||||
std::int32_t value = 0;
|
std::int32_t value = 0;
|
||||||
TRY_ESP(file_handle->get_item(nvs_name.c_str(), value));
|
TRY_ESP(file_handle->get_item(nvs_name.c_str(), value));
|
||||||
|
data = value;
|
||||||
|
|
||||||
return value;
|
return data;
|
||||||
}
|
}
|
||||||
else if (type == Type::FLOAT)
|
else if (type == Type::FLOAT)
|
||||||
{
|
{
|
||||||
std::int32_t value_raw = 0;
|
std::int32_t value_raw = 0;
|
||||||
TRY_ESP(file_handle->get_item(nvs_name.c_str(), value_raw));
|
TRY_ESP(file_handle->get_item(nvs_name.c_str(), value_raw));
|
||||||
return std::bit_cast<float>(value_raw);
|
data = std::bit_cast<float>(value_raw);
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
else if (type == Type::STRING)
|
else if (type == Type::STRING)
|
||||||
{
|
{
|
||||||
@ -179,7 +182,9 @@ std::expected<WifiProvisioner::Parameter::Value, esp_err_t> WifiProvisioner::Par
|
|||||||
TRY_ESP(file_handle->get_string(nvs_name.c_str(), value.data(), value.size() - 1));
|
TRY_ESP(file_handle->get_string(nvs_name.c_str(), value.data(), value.size() - 1));
|
||||||
value.trim_to_terminator();
|
value.trim_to_terminator();
|
||||||
|
|
||||||
return value;
|
data = value;
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
@ -241,18 +246,34 @@ WifiProvisioner::~WifiProvisioner()
|
|||||||
{
|
{
|
||||||
httpd_stop(http_server_);
|
httpd_stop(http_server_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (esp_netif_)
|
||||||
|
{
|
||||||
|
esp_wifi_stop();
|
||||||
|
esp_wifi_deinit();
|
||||||
|
|
||||||
|
esp_netif_destroy_default_wifi(esp_netif_);
|
||||||
|
esp_event_loop_delete_default();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WifiProvisioner::parametersAreConfigured()
|
bool WifiProvisioner::parametersAreConfigured()
|
||||||
{
|
{
|
||||||
|
if (!settings_initialized_)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (params_.empty())
|
if (params_.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (const auto& param : params_)
|
for (auto& param : params_)
|
||||||
{
|
{
|
||||||
if (const auto value = param.getValue(file_handle_.get());
|
if (const auto value = param.tryReadAndAssignValue(file_handle_.get());
|
||||||
!value.has_value())
|
!value.has_value())
|
||||||
{
|
{
|
||||||
|
settings_initialized_ = false;
|
||||||
|
file_handle_->set_item(NVS_IS_INITED, settings_initialized_);
|
||||||
|
file_handle_->commit();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,6 +281,16 @@ bool WifiProvisioner::parametersAreConfigured()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WifiProvisioner::clearSettings()
|
||||||
|
{
|
||||||
|
if (!settings_initialized_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
settings_initialized_ = false;
|
||||||
|
ESP_ERROR_CHECK(file_handle_->set_item(NVS_IS_INITED, settings_initialized_));
|
||||||
|
ESP_ERROR_CHECK(file_handle_->commit());
|
||||||
|
}
|
||||||
|
|
||||||
std::expected<void, esp_err_t> WifiProvisioner::startProvisioning()
|
std::expected<void, esp_err_t> WifiProvisioner::startProvisioning()
|
||||||
{
|
{
|
||||||
TRY(initializeWifiAp_());
|
TRY(initializeWifiAp_());
|
||||||
@ -269,6 +300,28 @@ std::expected<void, esp_err_t> WifiProvisioner::startProvisioning()
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const etl::vector<WifiProvisioner::Parameter, 10>& WifiProvisioner::getParameters()
|
||||||
|
{
|
||||||
|
if (!settings_initialized_)
|
||||||
|
abortWithError("WifiProvisioner read parameters without initialization.");
|
||||||
|
|
||||||
|
return params_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::expected<WifiProvisioner::Parameter, std::error_code> WifiProvisioner::getParameter(const etl::string<15>& name)
|
||||||
|
{
|
||||||
|
if (!settings_initialized_)
|
||||||
|
return std::unexpected{std::make_error_code(std::errc::not_connected)};
|
||||||
|
|
||||||
|
for (const auto& param : params_)
|
||||||
|
{
|
||||||
|
if (param.nvs_name == name)
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::unexpected{std::make_error_code(std::errc::invalid_argument)};
|
||||||
|
}
|
||||||
|
|
||||||
std::expected<void, std::error_code> WifiProvisioner::addParameter(const char* name, const char* nvs_name, const Parameter::Type type)
|
std::expected<void, std::error_code> WifiProvisioner::addParameter(const char* name, const char* nvs_name, const Parameter::Type type)
|
||||||
{
|
{
|
||||||
if (params_.full())
|
if (params_.full())
|
||||||
@ -338,7 +391,7 @@ std::expected<void, esp_err_t> WifiProvisioner::initializeWifiAp_()
|
|||||||
{
|
{
|
||||||
TRY_ESP(esp_netif_init());
|
TRY_ESP(esp_netif_init());
|
||||||
TRY_ESP(esp_event_loop_create_default());
|
TRY_ESP(esp_event_loop_create_default());
|
||||||
esp_netif_create_default_wifi_ap();
|
esp_netif_ = esp_netif_create_default_wifi_ap();
|
||||||
|
|
||||||
wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
|
wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
TRY_ESP(esp_wifi_init(&config));
|
TRY_ESP(esp_wifi_init(&config));
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include <etl/vector.h>
|
#include <etl/vector.h>
|
||||||
#include <etl/string.h>
|
#include <etl/string.h>
|
||||||
#include <etl/delegate.h>
|
#include <etl/delegate.h>
|
||||||
|
#include <cstdint>
|
||||||
#include <expected>
|
#include <expected>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -53,7 +54,7 @@ public:
|
|||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
|
|
||||||
using Value = std::variant<std::int32_t, float, etl::string<100>>;
|
using Value = std::variant<std::monostate, std::int32_t, float, etl::string<100>>;
|
||||||
Value data;
|
Value data;
|
||||||
|
|
||||||
Parameter() = default;
|
Parameter() = default;
|
||||||
@ -61,10 +62,43 @@ public:
|
|||||||
: name(name)
|
: name(name)
|
||||||
, nvs_name(nvs_name)
|
, nvs_name(nvs_name)
|
||||||
, type(type)
|
, type(type)
|
||||||
|
, data(std::monostate())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
std::expected<Value, esp_err_t> getValue(nvs::NVSHandle* file_handle) const;
|
std::expected<Value, esp_err_t> tryReadAndAssignValue(nvs::NVSHandle* file_handle);
|
||||||
std::expected<Value, const char*> tryValidateAndAssign(cJSON* object);
|
std::expected<Value, const char*> tryValidateAndAssign(cJSON* object);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::expected<T, std::error_code> getValue() const
|
||||||
|
{
|
||||||
|
static_assert(std::is_same_v<T, std::int32_t> || std::is_same_v<T, float> || std::is_same_v<T, etl::string<100>>,
|
||||||
|
"T must be in the Value variant.");
|
||||||
|
|
||||||
|
if (holds_alternative<std::monostate>(data))
|
||||||
|
return std::unexpected(std::make_error_code(std::errc::io_error));
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, std::int32_t>)
|
||||||
|
{
|
||||||
|
if (type != Type::INT)
|
||||||
|
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
|
||||||
|
|
||||||
|
return std::get<std::int32_t>(data);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, float>)
|
||||||
|
{
|
||||||
|
if (type != Type::FLOAT)
|
||||||
|
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
|
||||||
|
|
||||||
|
return std::get<float>(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (type != Type::STRING)
|
||||||
|
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
|
||||||
|
|
||||||
|
return std::get<etl::string<100>>(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit WifiProvisioner(const char* settings_namespace, etl::delegate<void (const etl::vector<Parameter, 10>&)> success_cb);
|
explicit WifiProvisioner(const char* settings_namespace, etl::delegate<void (const etl::vector<Parameter, 10>&)> success_cb);
|
||||||
@ -77,8 +111,10 @@ public:
|
|||||||
WifiProvisioner& operator=(WifiProvisioner&&) = delete;
|
WifiProvisioner& operator=(WifiProvisioner&&) = delete;
|
||||||
|
|
||||||
bool parametersAreConfigured();
|
bool parametersAreConfigured();
|
||||||
|
void clearSettings();
|
||||||
std::expected<void, esp_err_t> startProvisioning();
|
std::expected<void, esp_err_t> startProvisioning();
|
||||||
|
const etl::vector<Parameter, 10>& getParameters();
|
||||||
|
std::expected<Parameter, std::error_code> getParameter(const etl::string<15>& name);
|
||||||
|
|
||||||
std::expected<void, std::error_code> addParameter(const char* name, const char* nvs_name, const Parameter::Type type);
|
std::expected<void, std::error_code> addParameter(const char* name, const char* nvs_name, const Parameter::Type type);
|
||||||
CJsonPtr getParameterObjects() const;
|
CJsonPtr getParameterObjects() const;
|
||||||
@ -88,6 +124,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::unique_ptr<nvs::NVSHandle> file_handle_;
|
std::unique_ptr<nvs::NVSHandle> file_handle_;
|
||||||
bool settings_initialized_ = false;
|
bool settings_initialized_ = false;
|
||||||
|
void* esp_netif_ = nullptr;
|
||||||
httpd_handle_t http_server_ = nullptr;
|
httpd_handle_t http_server_ = nullptr;
|
||||||
etl::vector<Parameter, 10> params_;
|
etl::vector<Parameter, 10> params_;
|
||||||
etl::delegate<void (const etl::vector<Parameter, 10>& params)> success_cb_;
|
etl::delegate<void (const etl::vector<Parameter, 10>& params)> success_cb_;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user