Add config and wifi
This commit is contained in:
@ -1,8 +1,18 @@
|
||||
set(headers
|
||||
config.h
|
||||
debugconsole.h
|
||||
ota.h
|
||||
taskmanager.h
|
||||
wifi.h
|
||||
)
|
||||
|
||||
set(sources
|
||||
config.cpp
|
||||
debugconsole.cpp
|
||||
main.cpp
|
||||
ota.cpp
|
||||
taskmanager.cpp
|
||||
wifi.cpp
|
||||
)
|
||||
|
||||
set(dependencies
|
||||
|
33
main/config.cpp
Normal file
33
main/config.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// esp-idf includes
|
||||
#include <esp_log.h>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <configmanager_priv.h>
|
||||
#include <fmt/core.h>
|
||||
#include <espwifistack.h>
|
||||
|
||||
// local includes
|
||||
#include "configmanager_priv.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace {
|
||||
//constexpr const char * const TAG = "CONFIG";
|
||||
} // namespace
|
||||
|
||||
std::string defaultHostname()
|
||||
{
|
||||
if (const auto result = wifi_stack::get_default_mac_addr())
|
||||
return fmt::format("bobby_{:02x}{:02x}{:02x}", result->at(3), result->at(4), result->at(5));
|
||||
else
|
||||
ESP_LOGE(TAG, "get_default_mac_addr() failed: %.*s", result.error().size(), result.error().data());
|
||||
return "bobby";
|
||||
}
|
||||
|
||||
ConfigManager<ConfigContainer> configs;
|
||||
|
||||
INSTANTIATE_CONFIGMANAGER_TEMPLATES(ConfigContainer)
|
168
main/config.h
Normal file
168
main/config.h
Normal file
@ -0,0 +1,168 @@
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// system includes
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
|
||||
// esp-idf includes
|
||||
#include <esp_sntp.h>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <fmt/core.h>
|
||||
#include <configmanager.h>
|
||||
#include <configconstraints_base.h>
|
||||
#include <configconstraints_espchrono.h>
|
||||
#include <configwrapper.h>
|
||||
#include <espwifiutils.h>
|
||||
#include <espchrono.h>
|
||||
#include <makearray.h>
|
||||
|
||||
// local includes
|
||||
|
||||
using namespace espconfig;
|
||||
|
||||
std::string defaultHostname();
|
||||
|
||||
class WiFiConfig
|
||||
{
|
||||
public:
|
||||
WiFiConfig(const char *ssidNvsKey, const char *keyNvsKey,
|
||||
const char *useStaticIpKey, const char *staticIpKey, const char *staticSubnetKey, const char *staticGatewayKey,
|
||||
const char *useStaticDnsKey, const char *staticDns0Key, const char *staticDns1Key, const char *staticDns2Key) :
|
||||
ssid {std::string{}, DoReset, StringMaxSize<32>, ssidNvsKey },
|
||||
key {std::string{}, DoReset, StringOr<StringEmpty, StringMinMaxSize<8, 64>>, keyNvsKey },
|
||||
useStaticIp {false, DoReset, {}, useStaticIpKey },
|
||||
staticIp {wifi_stack::ip_address_t{}, DoReset, {}, staticIpKey },
|
||||
staticSubnet {wifi_stack::ip_address_t{}, DoReset, {}, staticSubnetKey },
|
||||
staticGateway{wifi_stack::ip_address_t{}, DoReset, {}, staticGatewayKey },
|
||||
useStaticDns {false, DoReset, {}, useStaticDnsKey },
|
||||
staticDns0 {wifi_stack::ip_address_t{}, DoReset, {}, staticDns0Key },
|
||||
staticDns1 {wifi_stack::ip_address_t{}, DoReset, {}, staticDns1Key },
|
||||
staticDns2 {wifi_stack::ip_address_t{}, DoReset, {}, staticDns2Key }
|
||||
{}
|
||||
|
||||
ConfigWrapper<std::string> ssid;
|
||||
ConfigWrapper<std::string> key;
|
||||
ConfigWrapper<bool> useStaticIp;
|
||||
ConfigWrapper<wifi_stack::ip_address_t> staticIp;
|
||||
ConfigWrapper<wifi_stack::ip_address_t> staticSubnet;
|
||||
ConfigWrapper<wifi_stack::ip_address_t> staticGateway;
|
||||
ConfigWrapper<bool> useStaticDns;
|
||||
ConfigWrapper<wifi_stack::ip_address_t> staticDns0;
|
||||
ConfigWrapper<wifi_stack::ip_address_t> staticDns1;
|
||||
ConfigWrapper<wifi_stack::ip_address_t> staticDns2;
|
||||
};
|
||||
|
||||
class ConfigContainer
|
||||
{
|
||||
using mac_t = wifi_stack::mac_t;
|
||||
|
||||
public:
|
||||
// default allowReset constraints nvsName
|
||||
ConfigWrapper<std::optional<mac_t>> baseMacAddressOverride{std::nullopt, DoReset, {}, "baseMacAddrOver" };
|
||||
ConfigWrapper<std::string> hostname {defaultHostname, DoReset, StringMinMaxSize<4, 32>, "hostname" };
|
||||
|
||||
#ifdef CONFIG_ETH_ENABLED
|
||||
ConfigWrapper<bool> ethEnabled {true, DoReset, {}, "ethEnabled" };
|
||||
ConfigWrapper<bool> ethUseStaticIp {false, DoReset, {}, "ethUseStatIp" };
|
||||
ConfigWrapper<ip_address_t> ethStaticIp {ip_address_t{}, DoReset, {}, "ethStaticIp" };
|
||||
ConfigWrapper<ip_address_t> ethStaticSubnet {ip_address_t{}, DoReset, {}, "ethStaticSub" };
|
||||
ConfigWrapper<ip_address_t> ethStaticGateway {ip_address_t{}, DoReset, {}, "ethStaticGw" };
|
||||
ConfigWrapper<bool> ethUseStaticDns {false, DoReset, {}, "ethUseStatDns" };
|
||||
ConfigWrapper<ip_address_t> ethStaticDns0 {ip_address_t{}, DoReset, {}, "ethStaticDns0" };
|
||||
ConfigWrapper<ip_address_t> ethStaticDns1 {ip_address_t{}, DoReset, {}, "ethStaticDns1" };
|
||||
ConfigWrapper<ip_address_t> ethStaticDns2 {ip_address_t{}, DoReset, {}, "ethStaticDns2" };
|
||||
#endif
|
||||
|
||||
ConfigWrapper<bool> wifiStaEnabled {true, DoReset, {}, "wifiStaEnabled" };
|
||||
std::array<WiFiConfig, 10> wifi_configs {
|
||||
WiFiConfig {"wifi_ssid0", "wifi_key0", "wifi_usestatic0", "wifi_static_ip0", "wifi_stati_sub0", "wifi_stat_gate0", "wifi_usestadns0", "wifi_stat_dnsA0", "wifi_stat_dnsB0", "wifi_stat_dnsC0"},
|
||||
WiFiConfig {"wifi_ssid1", "wifi_key1", "wifi_usestatic1", "wifi_static_ip1", "wifi_stati_sub1", "wifi_stat_gate1", "wifi_usestadns1", "wifi_stat_dnsA1", "wifi_stat_dnsB1", "wifi_stat_dnsC1"},
|
||||
WiFiConfig {"wifi_ssid2", "wifi_key2", "wifi_usestatic2", "wifi_static_ip2", "wifi_stati_sub2", "wifi_stat_gate2", "wifi_usestadns2", "wifi_stat_dnsA2", "wifi_stat_dnsB2", "wifi_stat_dnsC2"},
|
||||
WiFiConfig {"wifi_ssid3", "wifi_key3", "wifi_usestatic3", "wifi_static_ip3", "wifi_stati_sub3", "wifi_stat_gate3", "wifi_usestadns3", "wifi_stat_dnsA3", "wifi_stat_dnsB3", "wifi_stat_dnsC3"},
|
||||
WiFiConfig {"wifi_ssid4", "wifi_key4", "wifi_usestatic4", "wifi_static_ip4", "wifi_stati_sub4", "wifi_stat_gate4", "wifi_usestadns4", "wifi_stat_dnsA4", "wifi_stat_dnsB4", "wifi_stat_dnsC4"},
|
||||
WiFiConfig {"wifi_ssid5", "wifi_key5", "wifi_usestatic5", "wifi_static_ip5", "wifi_stati_sub5", "wifi_stat_gate5", "wifi_usestadns5", "wifi_stat_dnsA5", "wifi_stat_dnsB5", "wifi_stat_dnsC5"},
|
||||
WiFiConfig {"wifi_ssid6", "wifi_key6", "wifi_usestatic6", "wifi_static_ip6", "wifi_stati_sub6", "wifi_stat_gate6", "wifi_usestadns6", "wifi_stat_dnsA6", "wifi_stat_dnsB6", "wifi_stat_dnsC6"},
|
||||
WiFiConfig {"wifi_ssid7", "wifi_key7", "wifi_usestatic7", "wifi_static_ip7", "wifi_stati_sub7", "wifi_stat_gate7", "wifi_usestadns7", "wifi_stat_dnsA7", "wifi_stat_dnsB7", "wifi_stat_dnsC7"},
|
||||
WiFiConfig {"wifi_ssid8", "wifi_key8", "wifi_usestatic8", "wifi_static_ip8", "wifi_stati_sub8", "wifi_stat_gate8", "wifi_usestadns8", "wifi_stat_dnsA8", "wifi_stat_dnsB8", "wifi_stat_dnsC8"},
|
||||
WiFiConfig {"wifi_ssid9", "wifi_key9", "wifi_usestatic9", "wifi_static_ip9", "wifi_stati_sub9", "wifi_stat_gate9", "wifi_usestadns9", "wifi_stat_dnsA9", "wifi_stat_dnsB9", "wifi_stat_dnsC9"}
|
||||
};
|
||||
ConfigWrapper<int8_t> wifiStaMinRssi {-90, DoReset, {}, "wifiStaMinRssi" };
|
||||
|
||||
ConfigWrapper<bool> wifiApEnabled {true, DoReset, {}, "wifiApEnabled" };
|
||||
ConfigWrapper<std::string> wifiApName {defaultHostname, DoReset, StringMinMaxSize<4, 32>, "wifiApName" };
|
||||
ConfigWrapper<std::string> wifiApKey {"Passwort_123", DoReset, StringOr<StringEmpty, StringMinMaxSize<8, 64>>, "wifiApKey" };
|
||||
ConfigWrapper<wifi_stack::ip_address_t> wifiApIp{wifi_stack::ip_address_t{10, 0, 0, 1},DoReset, {}, "wifiApIp" };
|
||||
ConfigWrapper<wifi_stack::ip_address_t> wifiApMask{wifi_stack::ip_address_t{255, 255, 255, 0},DoReset, {}, "wifiApMask" };
|
||||
ConfigWrapper<uint8_t> wifiApChannel {1, DoReset, MinMaxValue<uint8_t, 1, 14>, "wifiApChannel" };
|
||||
ConfigWrapper<wifi_auth_mode_t> wifiApAuthmode{WIFI_AUTH_WPA2_PSK, DoReset, {}, "wifiApAuthmode" };
|
||||
|
||||
ConfigWrapper<bool> timeServerEnabled {true, DoReset, {}, "timeServerEnabl" };
|
||||
ConfigWrapper<std::string> timeServer {"europe.pool.ntp.org", DoReset, StringMaxSize<64>, "timeServer" };
|
||||
ConfigWrapper<sntp_sync_mode_t> timeSyncMode {SNTP_SYNC_MODE_IMMED, DoReset, {}, "timeSyncMode" };
|
||||
ConfigWrapper<espchrono::milliseconds32> timeSyncInterval{espchrono::milliseconds32{CONFIG_LWIP_SNTP_UPDATE_DELAY}, DoReset, MinTimeSyncInterval, "timeSyncInterva" };
|
||||
ConfigWrapper<espchrono::minutes32> timezoneOffset{espchrono::minutes32{60}, DoReset, {}, "timezoneOffset" }; // MinMaxValue<minutes32, -1440m, 1440m>
|
||||
ConfigWrapper<espchrono::DayLightSavingMode>timeDst{espchrono::DayLightSavingMode::EuropeanSummerTime, DoReset, {}, "time_dst" };
|
||||
|
||||
template<typename T>
|
||||
void callForEveryConfig(T &&callable)
|
||||
{
|
||||
#define REGISTER_CONFIG(name) \
|
||||
if (callable(name)) return;
|
||||
|
||||
REGISTER_CONFIG(baseMacAddressOverride)
|
||||
REGISTER_CONFIG(hostname)
|
||||
|
||||
#ifdef CONFIG_ETH_ENABLED
|
||||
REGISTER_CONFIG(ethEnabled)
|
||||
REGISTER_CONFIG(ethUseStaticIp)
|
||||
REGISTER_CONFIG(ethStaticIp)
|
||||
REGISTER_CONFIG(ethStaticSubnet)
|
||||
REGISTER_CONFIG(ethStaticGateway)
|
||||
REGISTER_CONFIG(ethUseStaticDns)
|
||||
REGISTER_CONFIG(ethStaticDns0)
|
||||
REGISTER_CONFIG(ethStaticDns1)
|
||||
REGISTER_CONFIG(ethStaticDns2)
|
||||
#endif
|
||||
|
||||
REGISTER_CONFIG(wifiStaEnabled)
|
||||
|
||||
for (auto &entry : wifi_configs)
|
||||
{
|
||||
REGISTER_CONFIG(entry.ssid)
|
||||
REGISTER_CONFIG(entry.key)
|
||||
REGISTER_CONFIG(entry.useStaticIp)
|
||||
REGISTER_CONFIG(entry.staticIp)
|
||||
REGISTER_CONFIG(entry.staticSubnet)
|
||||
REGISTER_CONFIG(entry.staticGateway)
|
||||
REGISTER_CONFIG(entry.useStaticDns)
|
||||
REGISTER_CONFIG(entry.staticDns0)
|
||||
REGISTER_CONFIG(entry.staticDns1)
|
||||
REGISTER_CONFIG(entry.staticDns2)
|
||||
}
|
||||
|
||||
REGISTER_CONFIG(wifiStaMinRssi)
|
||||
|
||||
REGISTER_CONFIG(wifiApEnabled)
|
||||
REGISTER_CONFIG(wifiApName)
|
||||
REGISTER_CONFIG(wifiApKey)
|
||||
REGISTER_CONFIG(wifiApIp)
|
||||
REGISTER_CONFIG(wifiApMask)
|
||||
REGISTER_CONFIG(wifiApChannel)
|
||||
REGISTER_CONFIG(wifiApAuthmode)
|
||||
|
||||
REGISTER_CONFIG(timeServerEnabled)
|
||||
REGISTER_CONFIG(timeServer)
|
||||
REGISTER_CONFIG(timeSyncMode)
|
||||
REGISTER_CONFIG(timeSyncInterval)
|
||||
REGISTER_CONFIG(timezoneOffset)
|
||||
REGISTER_CONFIG(timeDst)
|
||||
|
||||
#undef REGISTER_API_VALUE
|
||||
}
|
||||
};
|
||||
|
||||
extern ConfigManager<ConfigContainer> configs;
|
141
main/debugconsole.cpp
Normal file
141
main/debugconsole.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
#include "debugconsole.h"
|
||||
|
||||
// system includes
|
||||
#include <string_view>
|
||||
|
||||
// esp-idf includes
|
||||
#include <driver/uart.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <espstrutils.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char * const TAG = "DEBUG";
|
||||
|
||||
uint8_t consoleControlCharsReceived{};
|
||||
bool uart0Initialized{};
|
||||
|
||||
void handleNormalChar(char c);
|
||||
void handleSpecialChar(char c);
|
||||
} // namespace
|
||||
|
||||
MemoryDebug memoryDebug{Off};
|
||||
espchrono::millis_clock::time_point lastMemoryDebug;
|
||||
|
||||
void init_debugconsole()
|
||||
{
|
||||
if (const auto result = uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, 3, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); result != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "uart_set_pin() failed with %s", esp_err_to_name(result));
|
||||
}
|
||||
|
||||
if (const auto result = uart_driver_install(UART_NUM_0, SOC_UART_FIFO_LEN + 1, 0, 10, nullptr, 0); result != ESP_OK)
|
||||
ESP_LOGE(TAG, "uart_driver_install() failed with %s", esp_err_to_name(result));
|
||||
else
|
||||
uart0Initialized = true;
|
||||
}
|
||||
|
||||
void update_debugconsole()
|
||||
{
|
||||
if (!uart0Initialized)
|
||||
return;
|
||||
|
||||
size_t length{};
|
||||
if (const auto result = uart_get_buffered_data_len(UART_NUM_0, &length); result != ESP_OK)
|
||||
{
|
||||
ESP_LOGW(TAG, "uart_get_buffered_data_len() failed with %s", esp_err_to_name(result));
|
||||
}
|
||||
else if (length)
|
||||
{
|
||||
char data[length];
|
||||
length = uart_read_bytes(UART_NUM_0, data, length, 0);
|
||||
|
||||
for (char c : std::string_view{data, length})
|
||||
{
|
||||
if (consoleControlCharsReceived < 2)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\x1b':
|
||||
if (consoleControlCharsReceived == 0)
|
||||
consoleControlCharsReceived = 1;
|
||||
else
|
||||
consoleControlCharsReceived = 0;
|
||||
break;
|
||||
case '\x5b':
|
||||
if (consoleControlCharsReceived == 1)
|
||||
consoleControlCharsReceived = 2;
|
||||
else
|
||||
consoleControlCharsReceived = 0;
|
||||
break;
|
||||
default:
|
||||
consoleControlCharsReceived = 0;
|
||||
handleNormalChar(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
consoleControlCharsReceived = 0;
|
||||
handleSpecialChar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
void handleNormalChar(char c)
|
||||
{
|
||||
constexpr auto rotateLogLevel = [](const char *tag){
|
||||
const auto oldLogLevel = esp_log_level_get(tag);
|
||||
const auto newLogLevel = oldLogLevel == ESP_LOG_INFO ? ESP_LOG_DEBUG : (oldLogLevel == ESP_LOG_DEBUG ? ESP_LOG_VERBOSE : ESP_LOG_INFO);
|
||||
esp_log_level_set(tag, newLogLevel);
|
||||
ESP_LOGI(TAG, "%s loglevel set to %s (previous=%s)", tag, espcpputils::toString(newLogLevel).c_str(), espcpputils::toString(oldLogLevel).c_str());
|
||||
};
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'r': case 'R':
|
||||
ESP_LOGI(TAG, "Rebooting...");
|
||||
esp_restart();
|
||||
break;
|
||||
case 'm': case 'M':
|
||||
switch (memoryDebug)
|
||||
{
|
||||
case Off:
|
||||
memoryDebug = Normal;
|
||||
ESP_LOGI(TAG, "memory debug set to %s", "Normal");
|
||||
break;
|
||||
case Normal:
|
||||
memoryDebug = Fast;
|
||||
ESP_LOGI(TAG, "memory debug set to %s", "Fast");
|
||||
break;
|
||||
case Fast:
|
||||
memoryDebug = Off;
|
||||
ESP_LOGI(TAG, "memory debug set to %s", "Off");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'w': case 'W':
|
||||
rotateLogLevel("WEBSERVER");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handleSpecialChar(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'A': // Up arrow pressed
|
||||
break;
|
||||
case 'B': // Down arrow pressed
|
||||
break;
|
||||
case 'C': // Right arrow pressed
|
||||
break;
|
||||
case 'D': // Left arrow pressed
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "unknown control char received: %hhx", c);
|
||||
}
|
||||
}
|
||||
} // namespace
|
11
main/debugconsole.h
Normal file
11
main/debugconsole.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <espchrono.h>
|
||||
|
||||
enum MemoryDebug {Off,Normal,Fast};
|
||||
extern MemoryDebug memoryDebug;
|
||||
extern espchrono::millis_clock::time_point lastMemoryDebug;
|
||||
|
||||
void init_debugconsole();
|
||||
void update_debugconsole();
|
183
main/main.cpp
183
main/main.cpp
@ -1,10 +1,191 @@
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// esp-idf includes
|
||||
#include <esp_log.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#if defined(CONFIG_ESP_TASK_WDT_PANIC) || defined(CONFIG_ESP_TASK_WDT)
|
||||
#include <freertos/task.h>
|
||||
#include <esp_task_wdt.h>
|
||||
#endif
|
||||
#ifdef CONFIG_APP_ROLLBACK_ENABLE
|
||||
#include <esp_ota_ops.h>
|
||||
#endif
|
||||
#include <esp_heap_caps.h>
|
||||
|
||||
// Arduino includes
|
||||
#include <esp32-hal-gpio.h>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <schedulertask.h>
|
||||
#include <espchrono.h>
|
||||
#include <espasyncota.h>
|
||||
#include <espstrutils.h>
|
||||
#include <esprandom.h>
|
||||
#include <strutils.h>
|
||||
|
||||
// local includes
|
||||
#include "config.h"
|
||||
#include "debugconsole.h"
|
||||
#include "taskmanager.h"
|
||||
#include "ota.h"
|
||||
#include "wifi.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace {
|
||||
constexpr const char * const TAG = "MAIN";
|
||||
|
||||
espchrono::millis_clock::time_point lastLoopCount;
|
||||
int _loopCount{};
|
||||
int loopCountTemp{};
|
||||
} // namespace
|
||||
|
||||
const int &loopCount{_loopCount};
|
||||
|
||||
extern "C" void app_main()
|
||||
{
|
||||
ESP_LOGI(TAG, "hello world");
|
||||
#if defined(CONFIG_ESP_TASK_WDT_PANIC) || defined(CONFIG_ESP_TASK_WDT)
|
||||
{
|
||||
const auto taskHandle = xTaskGetCurrentTaskHandle();
|
||||
if (!taskHandle)
|
||||
{
|
||||
ESP_LOGE(TAG, "could not get handle to current main task!");
|
||||
}
|
||||
else if (const auto result = esp_task_wdt_add(taskHandle); result != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "could not add main task to watchdog: %s", esp_err_to_name(result));
|
||||
}
|
||||
}
|
||||
|
||||
bool wasPreviouslyUpdating{};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_APP_ROLLBACK_ENABLE
|
||||
esp_ota_img_states_t ota_state;
|
||||
if (const esp_partition_t * const running = esp_ota_get_running_partition())
|
||||
{
|
||||
if (const auto result = esp_ota_get_state_partition(running, &ota_state); result == ESP_ERR_NOT_FOUND)
|
||||
ota_state = ESP_OTA_IMG_VALID;
|
||||
else if (result != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_ota_get_state_partition() failed with %s", esp_err_to_name(result));
|
||||
ota_state = ESP_OTA_IMG_UNDEFINED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_ota_get_running_partition() returned nullptr");
|
||||
ota_state = ESP_OTA_IMG_UNDEFINED;
|
||||
}
|
||||
#endif
|
||||
|
||||
//init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz)
|
||||
//ESP_REG(APB_CTRL_PLL_TICK_CONF_REG) = APB_CLK_FREQ / REF_CLK_FREQ - 1;
|
||||
|
||||
pinMode(3, INPUT_PULLUP);
|
||||
|
||||
if (const auto result = configs.init("dmxnode"); result != ESP_OK)
|
||||
ESP_LOGE(TAG, "config_init_settings() failed with %s", esp_err_to_name(result));
|
||||
|
||||
for (const auto &task : schedulerTasks)
|
||||
task.setup();
|
||||
|
||||
while (true)
|
||||
{
|
||||
bool pushStats = espchrono::ago(lastLoopCount) >= 1s;
|
||||
if (pushStats)
|
||||
{
|
||||
lastLoopCount = espchrono::millis_clock::now();
|
||||
_loopCount = loopCountTemp;
|
||||
loopCountTemp = 0;
|
||||
}
|
||||
|
||||
loopCountTemp++;
|
||||
|
||||
for (auto &task : schedulerTasks)
|
||||
{
|
||||
task.loop();
|
||||
|
||||
#if defined(CONFIG_ESP_TASK_WDT_PANIC) || defined(CONFIG_ESP_TASK_WDT)
|
||||
if (wasPreviouslyUpdating)
|
||||
{
|
||||
if (const auto result = esp_task_wdt_reset(); result != ESP_OK)
|
||||
ESP_LOGE(TAG, "esp_task_wdt_reset() failed with %s", esp_err_to_name(result));
|
||||
//vPortYield();
|
||||
vTaskDelay(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pushStats)
|
||||
{
|
||||
sched_pushStats(memoryDebug == Fast);
|
||||
}
|
||||
|
||||
if constexpr (LOG_LOCAL_LEVEL >= ESP_LOG_WARN)
|
||||
{
|
||||
const auto free8 = heap_caps_get_free_size(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
if (free8 < 25000)
|
||||
{
|
||||
lastMemoryDebug = espchrono::millis_clock::now();
|
||||
ESP_LOGW(TAG, "MEMORY heap8=%zd (largest block: %zd) heap32=%zd lps=%i",
|
||||
free8,
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT),
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL|MALLOC_CAP_32BIT),
|
||||
_loopCount
|
||||
);
|
||||
}
|
||||
else if constexpr (LOG_LOCAL_LEVEL >= ESP_LOG_INFO)
|
||||
{
|
||||
if (memoryDebug != Off &&
|
||||
espchrono::ago(lastMemoryDebug) >= (memoryDebug == Fast ? 100ms : 1000ms))
|
||||
{
|
||||
lastMemoryDebug = espchrono::millis_clock::now();
|
||||
ESP_LOGI(TAG, "MEMORY heap8=%zd (largest block: %zd) heap32=%zd lps=%i",
|
||||
free8,
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT),
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL|MALLOC_CAP_32BIT),
|
||||
_loopCount
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ESP_TASK_WDT_PANIC) || defined(CONFIG_ESP_TASK_WDT)
|
||||
if (const auto result = esp_task_wdt_reset(); result != ESP_OK)
|
||||
ESP_LOGE(TAG, "esp_task_wdt_reset() failed with %s", esp_err_to_name(result));
|
||||
|
||||
if (const auto isUpdating = otaClient.status() == OtaCloudUpdateStatus::Updating; isUpdating != wasPreviouslyUpdating)
|
||||
{
|
||||
wasPreviouslyUpdating = isUpdating;
|
||||
|
||||
constexpr bool panic =
|
||||
#ifdef CONFIG_ESP_TASK_WDT_PANIC
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
;
|
||||
|
||||
const uint32_t timeout = isUpdating ?
|
||||
CONFIG_ESP_TASK_WDT_TIMEOUT_S * 4 :
|
||||
CONFIG_ESP_TASK_WDT_TIMEOUT_S;
|
||||
|
||||
const auto result = esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, panic);
|
||||
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "esp_task_wdt_init() with new timeout %u returned: %s", timeout, esp_err_to_name(result));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_APP_ROLLBACK_ENABLE
|
||||
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY)
|
||||
{
|
||||
const auto result = esp_ota_mark_app_valid_cancel_rollback();
|
||||
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "esp_ota_mark_app_valid_cancel_rollback() returned: %s", esp_err_to_name(result));
|
||||
ota_state = ESP_OTA_IMG_VALID;
|
||||
}
|
||||
#endif
|
||||
|
||||
//vPortYield();
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
|
58
main/ota.cpp
Normal file
58
main/ota.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "ota.h"
|
||||
|
||||
// system includes
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
// esp-idf includes
|
||||
#include <esp_log.h>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <fmt/core.h>
|
||||
#include <delayedconstruction.h>
|
||||
#include <espasyncota.h>
|
||||
#include <espwifistack.h>
|
||||
#include <recursivelockhelper.h>
|
||||
|
||||
// local includes
|
||||
#include "config.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace {
|
||||
constexpr const char * const TAG = "OTA_CLOUD";
|
||||
|
||||
cpputils::DelayedConstruction<EspAsyncOta> _otaClient;
|
||||
} // namespace
|
||||
|
||||
EspAsyncOta &otaClient{_otaClient.getUnsafe()};
|
||||
|
||||
void ota_cloud_init()
|
||||
{
|
||||
ESP_LOGI(TAG, "called");
|
||||
|
||||
_otaClient.construct("asyncOtaTask", 8192u);
|
||||
}
|
||||
|
||||
void ota_cloud_update()
|
||||
{
|
||||
_otaClient->update();
|
||||
}
|
||||
|
||||
tl::expected<void, std::string> otaClientTrigger(std::string_view url)
|
||||
{
|
||||
if (auto result = _otaClient->trigger(url, {}, {}, {}); !result)
|
||||
return tl::make_unexpected(std::move(result).error());
|
||||
|
||||
wifi_stack::delete_scan_result();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
tl::expected<void, std::string> otaClientAbort()
|
||||
{
|
||||
if (auto result = _otaClient->abort(); !result)
|
||||
return tl::make_unexpected(std::move(result).error());
|
||||
|
||||
return {};
|
||||
}
|
20
main/ota.h
Normal file
20
main/ota.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
// system includes
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <map>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
// forward declares
|
||||
class EspAsyncOta;
|
||||
|
||||
extern EspAsyncOta &otaClient;
|
||||
|
||||
void ota_cloud_init();
|
||||
void ota_cloud_update();
|
||||
|
||||
tl::expected<void, std::string> otaCloudTrigger(std::string_view url);
|
||||
tl::expected<void, std::string> otaCloudAbort();
|
44
main/taskmanager.cpp
Normal file
44
main/taskmanager.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "taskmanager.h"
|
||||
|
||||
// system includes
|
||||
#include <iterator>
|
||||
#include <chrono>
|
||||
|
||||
// esp-idf includes
|
||||
#include <esp_log.h>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <schedulertask.h>
|
||||
|
||||
// local includes
|
||||
#include "wifi.h"
|
||||
#include "debugconsole.h"
|
||||
#include "ota.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace {
|
||||
constexpr const char * const TAG = "TASKS";
|
||||
|
||||
void not_needed() {}
|
||||
|
||||
espcpputils::SchedulerTask schedulerTasksArr[] {
|
||||
espcpputils::SchedulerTask { "wifi", wifi_begin, wifi_update, 100ms },
|
||||
espcpputils::SchedulerTask { "debugconsole", init_debugconsole, update_debugconsole, 50ms },
|
||||
espcpputils::SchedulerTask { "ota_cloud", ota_cloud_init, ota_cloud_update, 100ms },
|
||||
};
|
||||
} // namespace
|
||||
|
||||
cpputils::ArrayView<espcpputils::SchedulerTask> schedulerTasks{std::begin(schedulerTasksArr), std::end(schedulerTasksArr)};
|
||||
|
||||
void sched_pushStats(bool printTasks)
|
||||
{
|
||||
if (printTasks)
|
||||
ESP_LOGI(TAG, "begin listing tasks...");
|
||||
|
||||
for (auto &schedulerTask : schedulerTasks)
|
||||
schedulerTask.pushStats(printTasks);
|
||||
|
||||
if (printTasks)
|
||||
ESP_LOGI(TAG, "end listing tasks");
|
||||
}
|
11
main/taskmanager.h
Normal file
11
main/taskmanager.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <arrayview.h>
|
||||
|
||||
// forward declares
|
||||
namespace espcpputils { class SchedulerTask; }
|
||||
|
||||
extern cpputils::ArrayView<espcpputils::SchedulerTask> schedulerTasks;
|
||||
|
||||
void sched_pushStats(bool printTasks);
|
146
main/wifi.cpp
Normal file
146
main/wifi.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
#include "wifi.h"
|
||||
|
||||
// system includes
|
||||
#include <optional>
|
||||
|
||||
// esp-idf includes
|
||||
#include <esp_log.h>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <espwifistack.h>
|
||||
|
||||
// local includes
|
||||
#include "config.h"
|
||||
|
||||
namespace {
|
||||
wifi_stack::config createConfig();
|
||||
std::optional<wifi_stack::sta_config> createStaConfig();
|
||||
wifi_stack::wifi_entry createWifiEntry(const WiFiConfig &wifi_config);
|
||||
std::optional<wifi_stack::ap_config> createApConfig();
|
||||
} // namespace
|
||||
|
||||
void wifi_begin()
|
||||
{
|
||||
wifi_stack::init(createConfig());
|
||||
}
|
||||
|
||||
void wifi_update()
|
||||
{
|
||||
wifi_stack::update(createConfig());
|
||||
}
|
||||
|
||||
esp_err_t wifi_scan()
|
||||
{
|
||||
const auto &sta_config = createStaConfig();
|
||||
if (!sta_config)
|
||||
{
|
||||
ESP_LOGE("BOBBY", "no sta enabled");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (const auto result = wifi_stack::begin_scan(*sta_config); !result)
|
||||
{
|
||||
ESP_LOGE("BOBBY", "begin_scan() failed with %.*s", result.error().size(), result.error().data());
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
namespace {
|
||||
wifi_stack::config createConfig()
|
||||
{
|
||||
return wifi_stack::config {
|
||||
.base_mac_override = configs.baseMacAddressOverride.value,
|
||||
//.dual_ant = dual_ant_config{},
|
||||
.sta = createStaConfig(),
|
||||
.ap = createApConfig(),
|
||||
#ifdef CONFIG_ETH_ENABLED
|
||||
.eth = createEthConfig()
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
std::optional<wifi_stack::sta_config> createStaConfig()
|
||||
{
|
||||
if (!configs.wifiStaEnabled.value)
|
||||
return std::nullopt;
|
||||
|
||||
return wifi_stack::sta_config{
|
||||
.hostname = configs.hostname.value,
|
||||
.wifis = std::array<wifi_stack::wifi_entry, 10> {
|
||||
createWifiEntry(configs.wifi_configs[0]),
|
||||
createWifiEntry(configs.wifi_configs[1]),
|
||||
createWifiEntry(configs.wifi_configs[2]),
|
||||
createWifiEntry(configs.wifi_configs[3]),
|
||||
createWifiEntry(configs.wifi_configs[4]),
|
||||
createWifiEntry(configs.wifi_configs[5]),
|
||||
createWifiEntry(configs.wifi_configs[6]),
|
||||
createWifiEntry(configs.wifi_configs[7]),
|
||||
createWifiEntry(configs.wifi_configs[8]),
|
||||
createWifiEntry(configs.wifi_configs[9])
|
||||
},
|
||||
.min_rssi = configs.wifiStaMinRssi.value,
|
||||
.long_range = false
|
||||
};
|
||||
}
|
||||
|
||||
wifi_stack::wifi_entry createWifiEntry(const WiFiConfig &wifi_config)
|
||||
{
|
||||
std::optional<wifi_stack::static_ip_config> static_ip;
|
||||
if (wifi_config.useStaticIp.value)
|
||||
static_ip = wifi_stack::static_ip_config {
|
||||
.ip = wifi_config.staticIp.value,
|
||||
.subnet = wifi_config.staticSubnet.value,
|
||||
.gateway = wifi_config.staticGateway.value
|
||||
};
|
||||
|
||||
wifi_stack::static_dns_config static_dns;
|
||||
if (wifi_config.useStaticDns.value)
|
||||
{
|
||||
if (wifi_config.staticDns0.value.value())
|
||||
static_dns.main = wifi_config.staticDns0.value;
|
||||
if (wifi_config.staticDns1.value.value())
|
||||
static_dns.backup = wifi_config.staticDns1.value;
|
||||
if (wifi_config.staticDns2.value.value())
|
||||
static_dns.fallback = wifi_config.staticDns2.value;
|
||||
}
|
||||
|
||||
return wifi_stack::wifi_entry {
|
||||
.ssid = wifi_config.ssid.value,
|
||||
.key = wifi_config.key.value,
|
||||
.static_ip = static_ip,
|
||||
.static_dns = static_dns
|
||||
};
|
||||
}
|
||||
|
||||
std::optional<wifi_stack::ap_config> createApConfig()
|
||||
{
|
||||
if (!configs.wifiApEnabled.value)
|
||||
return std::nullopt;
|
||||
|
||||
// if (configs.wifiDisableApWhenOnline.value &&
|
||||
// cloudStarted &&
|
||||
// cloudConnected &&
|
||||
// lastCloudConnectedToggled &&
|
||||
// espchrono::ago(*lastCloudConnectedToggled) >= 30s)
|
||||
// return std::nullopt;
|
||||
|
||||
return wifi_stack::ap_config {
|
||||
.hostname = configs.hostname.value,
|
||||
.ssid = configs.wifiApName.value,
|
||||
.key = configs.wifiApKey.value,
|
||||
.static_ip = {
|
||||
.ip = configs.wifiApIp.value,
|
||||
.subnet = configs.wifiApMask.value,
|
||||
.gateway = configs.wifiApIp.value,
|
||||
},
|
||||
.channel = configs.wifiApChannel.value,
|
||||
.authmode = configs.wifiApAuthmode.value,
|
||||
.ssid_hidden = false,
|
||||
.max_connection = 4,
|
||||
.beacon_interval = 100,
|
||||
.long_range = false
|
||||
};
|
||||
}
|
||||
} // namespace
|
13
main/wifi.h
Normal file
13
main/wifi.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
// esp-idf includes
|
||||
#include <esp_err.h>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <espwifiutils.h>
|
||||
|
||||
void wifi_begin();
|
||||
|
||||
void wifi_update();
|
||||
|
||||
esp_err_t wifi_scan();
|
Reference in New Issue
Block a user