Fixes and improvements

This commit is contained in:
Ken Van Hoeylandt 2025-08-21 23:38:34 +02:00
parent fa1418d37b
commit 8fdcb51258
8 changed files with 152 additions and 24 deletions

View File

@ -28,6 +28,7 @@ enum class SystemEvent {
/** Value 0 mean "no subscription" */
typedef uint32_t SystemEventSubscription;
constexpr SystemEventSubscription NoSystemEventSubscription = 0U;
typedef std::function<void(SystemEvent)> OnSystemEvent;

View File

@ -0,0 +1,7 @@
#pragma once
namespace tt::service::wifi {
void bootSplashInit();
}

View File

@ -10,7 +10,8 @@
#include "Tactility/lvgl/LvglSync.h"
#include <Tactility/Tactility.h>
#include "Tactility/file/File.h"
#include <Tactility/file/File.h>
#include <Tactility/Log.h>
#include <Tactility/StringUtils.h>
#include <cstring>

View File

@ -108,7 +108,7 @@ static bool decrypt(const std::string& ssidInput, std::string& ssidOutput) {
bool contains(const std::string& ssid) {
const auto file_path = getApPropertiesFilePath(ssid);
return file::exists(file_path);
return file::isFile(file_path);
}
bool load(const std::string& ssid, WifiApSettings& apSettings) {
@ -177,7 +177,7 @@ bool save(const WifiApSettings& apSettings) {
bool remove(const std::string& ssid) {
const auto path = getApPropertiesFilePath(ssid);
if (!file::exists(path)) {
if (!file::isFile(path)) {
return false;
}
return ::remove(path.c_str()) == 0;

View File

@ -0,0 +1,115 @@
#include "Tactility/service/wifi/WifiBootSplashInit.h"
#include <Tactility/file/File.h>
#include <Tactility/Log.h>
#include <string>
#include <Tactility/file/PropertiesFile.h>
#include <Tactility/service/wifi/WifiApSettings.h>
namespace tt::service::wifi {
constexpr auto* TAG = "WifiBootSplashInit";
// TODO: Avoid hard-coding this
constexpr auto* AP_PROPERTIES_PATH = "/sdcard";
constexpr auto* AP_PROPERTIES_KEY_SSID = "ssid";
constexpr auto* AP_PROPERTIES_KEY_PASSWORD = "password";
constexpr auto* AP_PROPERTIES_KEY_AUTO_CONNECT = "autoConnect";
constexpr auto* AP_PROPERTIES_KEY_CHANNEL = "channel";
constexpr auto* AP_PROPERTIES_KEY_AUTO_REMOVE = "autoRemovePropertiesFile";
struct ApProperties {
std::string ssid;
std::string password;
bool autoConnect;
int32_t channel;
bool autoRemovePropertiesFile;
};
static void importWifiAp(const std::string& filePath) {
std::map<std::string, std::string> map;
if (!file::loadPropertiesFile(filePath, map)) {
return;
}
const auto ssid_iterator = map.find(AP_PROPERTIES_KEY_SSID);
if (ssid_iterator == map.end()) {
TT_LOG_E(TAG, "%s is missing ssid", filePath.c_str());
return;
}
const auto ssid = ssid_iterator->second;
if (!settings::contains(ssid)) {
const auto password_iterator = map.find(AP_PROPERTIES_KEY_PASSWORD);
const auto password = password_iterator == map.end() ? "" : password_iterator->second;
const auto auto_connect_iterator = map.find(AP_PROPERTIES_KEY_AUTO_CONNECT);
const auto auto_connect = auto_connect_iterator == map.end() ? true : (auto_connect_iterator->second == "true");
const auto channel_iterator = map.find(AP_PROPERTIES_KEY_CHANNEL);
const auto channel = channel_iterator == map.end() ? 0 : std::stoi(channel_iterator->second);
settings::WifiApSettings settings(
ssid,
password,
auto_connect,
channel
);
if (!settings::save(settings)) {
TT_LOG_E(TAG, "Failed to save settings for %s", ssid.c_str());
} else {
TT_LOG_I(TAG, "Imported %s from %s", ssid.c_str(), filePath.c_str());
}
}
const auto auto_remove_iterator = map.find(AP_PROPERTIES_KEY_AUTO_REMOVE);
if (auto_remove_iterator != map.end() && auto_remove_iterator->second == "true") {
if (!remove(filePath.c_str())) {
TT_LOG_E(TAG, "Failed to auto-remove %s", filePath.c_str());
} else {
TT_LOG_I(TAG, "Auto-removed %s", filePath.c_str());
}
}
}
void bootSplashInit() {
if (!file::isDirectory(AP_PROPERTIES_PATH)) {
TT_LOG_I(TAG, "%s not available", AP_PROPERTIES_PATH);
return;
}
std::vector<dirent> dirent_list;
if (file::scandir(AP_PROPERTIES_PATH, dirent_list, [](const dirent* entry) {
switch (entry->d_type) {
case file::TT_DT_DIR:
case file::TT_DT_CHR:
case file::TT_DT_LNK:
return -1;
case file::TT_DT_REG:
default: {
std::string name = entry->d_name;
if (name.ends_with(".ap.properties")) {
return 0;
} else {
return -1;
}
}
}
}, nullptr) == 0) {
return;
}
if (dirent_list.empty()) {
return;
}
for (auto& dirent : dirent_list) {
std::string absolute_path = std::format("{}/{}", AP_PROPERTIES_PATH, dirent.d_name);
importWifiAp(absolute_path);
}
}
}

View File

@ -6,6 +6,7 @@
#include "Tactility/service/ServiceContext.h"
#include "Tactility/service/wifi/WifiGlobals.h"
#include "Tactility/service/wifi/WifiSettings.h"
#include "Tactility/service/wifi/WifiBootSplashInit.h"
#include <Tactility/kernel/SystemEvents.h>
#include <Tactility/Timer.h>
@ -68,6 +69,7 @@ public:
bool pause_auto_connect = false; // Pause when manually disconnecting until manually connecting again
bool connection_target_remember = false; // Whether to store the connection_target on successful connection or not
esp_netif_ip_info_t ip_info;
kernel::SystemEventSubscription bootEventSubscription = kernel::NoSystemEventSubscription;
RadioState getRadioState() const {
auto lock = dataMutex.asScopedLock();
@ -900,13 +902,17 @@ public:
assert(wifi_singleton == nullptr);
wifi_singleton = std::make_shared<Wifi>();
wifi_singleton->bootEventSubscription = kernel::subscribeSystemEvent(kernel::SystemEvent::BootSplash, [](auto) {
bootSplashInit();
});
wifi_singleton->autoConnectTimer = std::make_unique<Timer>(Timer::Type::Periodic, []() { onAutoConnectTimer(); });
// We want to try and scan more often in case of startup or scan lock failure
wifi_singleton->autoConnectTimer->start(std::min(2000, AUTO_SCAN_INTERVAL));
if (settings::shouldEnableOnBoot()) {
TT_LOG_I(TAG, "Auto-enabling due to setting");
getMainDispatcher().dispatch([]() { dispatchEnable(wifi_singleton); });
getMainDispatcher().dispatch([] { dispatchEnable(wifi_singleton); });
}
}

View File

@ -11,24 +11,15 @@ namespace tt::file {
/** File types for `dirent`'s `d_type`. */
enum {
TT_DT_UNKNOWN = 0,
#define TT_DT_UNKNOWN TT_DT_UNKNOWN // Unknown type
TT_DT_FIFO = 1,
#define TT_DT_FIFO TT_DT_FIFO // Named pipe or FIFO
TT_DT_CHR = 2,
#define TT_DT_CHR TT_DT_CHR // Character device
TT_DT_DIR = 4,
#define TT_DT_DIR TT_DT_DIR // Directory
TT_DT_BLK = 6,
#define TT_DT_BLK TT_DT_BLK // Block device
TT_DT_REG = 8,
#define TT_DT_REG TT_DT_REG // Regular file
TT_DT_LNK = 10,
#define TT_DT_LNK TT_DT_LNK // Symbolic link
TT_DT_SOCK = 12,
#define TT_DT_SOCK TT_DT_SOCK // Local-domain socket
TT_DT_WHT = 14
#define TT_DT_WHT TT_DT_WHT // Whiteout inodes
TT_DT_UNKNOWN = 0, // Unknown type
TT_DT_FIFO = 1, // Named pipe or FIFO
TT_DT_CHR = 2, // Character device
TT_DT_DIR = 4, // Directory
TT_DT_BLK = 6, // Block device
TT_DT_REG = 8, // Regular file
TT_DT_LNK = 10, // Symbolic link
TT_DT_SOCK = 12, // Local-domain socket
TT_DT_WHT = 14 // Whiteout inodes
};
#ifdef _WIN32
@ -92,7 +83,9 @@ bool direntSortAlphaAndType(const dirent& left, const dirent& right);
/** A filter for filtering out "." and ".." */
int direntFilterDotEntries(const dirent* entry);
bool exists(const std::string& path);
bool isFile(const std::string& path);
bool isDirectory(const std::string& path);
/**
* A scandir()-like implementation that works on ESP32.

View File

@ -209,8 +209,13 @@ bool findOrCreateDirectory(std::string path, mode_t mode) {
return true;
}
bool exists(const std::string& path) {
bool isFile(const std::string& path) {
return access(path.c_str(), F_OK) == 0;
}
bool isDirectory(const std::string& path) {
struct stat stat_result;
return stat(path.c_str(), &stat_result) == 0 && S_ISDIR(stat_result.st_mode);
}
}