This commit is contained in:
Ken Van Hoeylandt 2025-08-20 20:40:57 +02:00
parent 0bbf3a93a2
commit 017b6504ff
24 changed files with 73 additions and 204 deletions

View File

@ -5,10 +5,9 @@
- Store encrypted WiFi credentials in `/data/app/wifi/x.ap.properties` (fixes problem with long SSIDs)
- Move WiFi settings from flash to `/data/apps/wifi/wifi.properties` (just the "start on boot")
- Move Development settings from flash to `/data/apps/development/development.properties` (just the "start on boot")
- Move Display settings from flash to `/data/apps/display/display.properties` (just the "start on boot")
- Move Display settings from flash to `/data/apps/display/display.properties`
- App data directory should be automatically created (and then we can remove the custom code from Notes.cpp)
- When an external app fails to load (e.g. due to mapping error) then show an error dialog.
- Add a Keyboard setting in `keyboard.properties` to override the behaviour of soft keyboard hiding (e.g. keyboard hardware is present, but the user wants to use a soft keyboard)
- Expose app::Paths to TactilityC
- Call tt::lvgl::isSyncSet after HAL init and show an error (and crash?) when it is not set.
- External app loading: Check the version of Tactility and check ESP target hardware to check for compatibility.
@ -24,6 +23,7 @@
- Explore LVGL9's FreeRTOS functionality
- CrashHandler: use "corrupted" flag
- CrashHandler: process other types of crashes (WDT?)
- Add a Keyboard setting in `keyboard.properties` to override the behaviour of soft keyboard hiding (e.g. keyboard hardware is present, but the user wants to use a soft keyboard)
- Use GPS time to set/update the current time
- All drivers (e.g. display, touch, etc.) should call stop() in their destructor, or at least assert that they should not be running.
- Fix bug in T-Deck/etc: esp_lvgl_port settings has a large stack size (~9kB) to fix an issue where the T-Deck would get a stackoverflow. This sometimes happens when WiFi is auto-enabled and you open the app while it is still connecting.

View File

@ -1,15 +1,9 @@
#pragma once
#include "Tactility/app/ManifestRegistry.h"
#include <Tactility/CoreDefines.h>
#include <Tactility/Bundle.h>
#include "Tactility/app/AppRegistration.h"
#include <string>
// Forward declarations
typedef struct _lv_obj_t lv_obj_t;
namespace tt::app {
class App;
@ -40,8 +34,6 @@ enum class Result {
class Location {
private:
std::string path;
Location() = default;
explicit Location(const std::string& path) : path(path) {}
@ -54,7 +46,13 @@ public:
return Location(path);
}
/** Internal apps are all apps that are part of the firmware release. */
bool isInternal() const { return path.empty(); }
/**
* External apps are all apps that are not part of the firmware release.
* e.g. an application on the sd card or one that is installed in /data
*/
bool isExternal() const { return !path.empty(); }
const std::string& getPath() const { return path; }
};

View File

@ -1,11 +1,11 @@
#include "Tactility/Tactility.h"
#include "Tactility/app/ManifestRegistry.h"
#include "Tactility/app/AppRegistration.h"
#include "Tactility/lvgl/LvglPrivate.h"
#include "Tactility/service/ServiceManifest.h"
#include <Tactility/TactilityHeadless.h>
#include <Tactility/service/ServiceRegistry.h>
#include <Tactility/service/ServiceRegistration.h>
#include <Tactility/service/loader/Loader.h>
namespace tt {

View File

@ -3,7 +3,7 @@
#include "Tactility/hal/Hal_i.h"
#include "Tactility/network/NtpPrivate.h"
#include "Tactility/service/ServiceManifest.h"
#include "Tactility/service/ServiceRegistry.h"
#include "Tactility/service/ServiceRegistration.h"
#include <Tactility/Dispatcher.h>
#include <Tactility/time/TimePrivate.h>

View File

@ -1,9 +1,11 @@
#include "Tactility/app/ManifestRegistry.h"
#include "Tactility/app/AppRegistration.h"
#include "Tactility/app/AppManifest.h"
#include <Tactility/Mutex.h>
#include <unordered_map>
#include <Tactility/file/File.h>
#include <sys/stat.h>
#define TAG "app"
@ -14,12 +16,20 @@ typedef std::unordered_map<std::string, std::shared_ptr<AppManifest>> AppManifes
static AppManifestMap app_manifest_map;
static Mutex hash_mutex(Mutex::Type::Normal);
void ensureAppPathsExist(const AppManifest& manifest) {
std::string path = "/data/app/" + manifest.id;
if (!file::findOrCreateDirectory(path, 0777)) {
TT_LOG_E(TAG, "Failed to create app directory: %s", path.c_str());
}
}
void addApp(const AppManifest& manifest) {
TT_LOG_I(TAG, "Registering manifest %s", manifest.id.c_str());
hash_mutex.lock();
if (!app_manifest_map.contains(manifest.id)) {
ensureAppPathsExist(manifest);
app_manifest_map[manifest.id] = std::make_shared<AppManifest>(manifest);
} else {
TT_LOG_E(TAG, "App id in use: %s", manifest.id.c_str());

View File

@ -1,4 +1,4 @@
#include "Tactility/app/ManifestRegistry.h"
#include "Tactility/app/AppRegistration.h"
#include "Tactility/service/loader/Loader.h"
#include "Tactility/lvgl/Toolbar.h"

View File

@ -1,5 +1,5 @@
#include "Tactility/app/AppContext.h"
#include "Tactility/app/ManifestRegistry.h"
#include "Tactility/app/AppRegistration.h"
#include "Tactility/service/loader/Loader.h"
#include <Tactility/Check.h>

View File

@ -178,11 +178,6 @@ class NotesApp : public App {
lv_label_set_text(uiCurrentFileName, "Untitled");
lv_obj_align(uiCurrentFileName, LV_ALIGN_CENTER, 0, 0);
//TODO: Move this to SD Card?
if (!file::findOrCreateDirectory(context.getPaths()->getDataDirectory(), 0777)) {
TT_LOG_E(TAG, "Failed to find or create path %s", context.getPaths()->getDataDirectory().c_str());
}
if (!filePath.empty()) {
openFile(filePath);
}

View File

@ -1,4 +1,4 @@
#include "Tactility/app/ManifestRegistry.h"
#include "Tactility/app/AppRegistration.h"
#include "Tactility/lvgl/Toolbar.h"
#include "Tactility/service/loader/Loader.h"

View File

@ -15,7 +15,7 @@
#include <lvgl.h>
#include <Tactility/TactilityHeadless.h>
#include <Tactility/lvgl/LvglSync.h>
#include <Tactility/service/ServiceRegistry.h>
#include <Tactility/service/ServiceRegistration.h>
namespace tt::lvgl {

View File

@ -1,4 +1,4 @@
#include "Tactility/service/ServiceRegistry.h"
#include "Tactility/service/ServiceRegistration.h"
#include "Tactility/service/ServiceInstance.h"
#include "Tactility/service/ServiceManifest.h"
@ -8,6 +8,7 @@
#include <string>
#include <unordered_map>
#include <Tactility/app/AppInstance.h>
#include <Tactility/file/File.h>
namespace tt::service {
@ -22,14 +23,22 @@ static ServiceInstanceMap service_instance_map;
static Mutex manifest_mutex(Mutex::Type::Normal);
static Mutex instance_mutex(Mutex::Type::Normal);
void ensureServerPathsExist(const ServiceManifest& manifest) {
std::string path = "/data/service/" + manifest.id;
if (!file::findOrCreateDirectory(path, 0777)) {
TT_LOG_E(TAG, "Failed to create service directory: %s", path.c_str());
}
}
void addService(std::shared_ptr<const ServiceManifest> manifest, bool autoStart) {
assert(manifest != nullptr);
// We'll move the manifest pointer, but we'll need to id later
std::string id = manifest->id;
const auto& id = manifest->id;
TT_LOG_I(TAG, "Adding %s", id.c_str());
manifest_mutex.lock();
if (service_manifest_map[id] == nullptr) {
ensureServerPathsExist(*manifest);
service_manifest_map[id] = std::move(manifest);
} else {
TT_LOG_E(TAG, "Service id in use: %s", id.c_str());

View File

@ -6,7 +6,7 @@
#include "Tactility/network/Url.h"
#include "Tactility/TactilityHeadless.h"
#include "Tactility/service/ServiceManifest.h"
#include "Tactility/service/ServiceRegistry.h"
#include "Tactility/service/ServiceRegistration.h"
#include "Tactility/service/wifi/Wifi.h"
#include <cstring>
@ -17,7 +17,7 @@
#include <Tactility/StringUtils.h>
#include <Tactility/app/App.h>
#include <Tactility/app/ElfApp.h>
#include <Tactility/app/ManifestRegistry.h>
#include <Tactility/app/AppRegistration.h>
namespace tt::service::development {

View File

@ -3,7 +3,7 @@
#include "Tactility/service/espnow/EspNowService.h"
#include "Tactility/TactilityHeadless.h"
#include "Tactility/service/ServiceManifest.h"
#include "Tactility/service/ServiceRegistry.h"
#include "Tactility/service/ServiceRegistration.h"
#include "Tactility/service/espnow/EspNowWifi.h"
#include <cstring>
#include <esp_now.h>

View File

@ -1,6 +1,6 @@
#include "Tactility/service/gps/GpsService.h"
#include "Tactility/service/ServiceManifest.h"
#include "Tactility/service/ServiceRegistry.h"
#include "Tactility/service/ServiceRegistration.h"
#include <Tactility/Log.h>
#include <Tactility/file/File.h>

View File

@ -6,7 +6,7 @@
#include <Tactility/Tactility.h>
#include <Tactility/app/AppInstance.h>
#include <Tactility/service/ServiceRegistry.h>
#include <Tactility/service/ServiceRegistration.h>
namespace tt::service::gui {

View File

@ -1,12 +1,12 @@
#include "Tactility/service/loader/Loader.h"
#include "Tactility/app/AppInstance.h"
#include "Tactility/app/AppManifest.h"
#include "Tactility/app/ManifestRegistry.h"
#include "Tactility/app/AppRegistration.h"
#include <Tactility/RtosCompat.h>
#include <Tactility/DispatcherThread.h>
#include <Tactility/service/ServiceManifest.h>
#include <Tactility/service/ServiceRegistry.h>
#include <Tactility/service/ServiceRegistration.h>
#include <stack>

View File

@ -5,7 +5,7 @@
#include "Tactility/service/screenshot/Screenshot.h"
#include <Tactility/service/ServiceContext.h>
#include <Tactility/service/ServiceRegistry.h>
#include <Tactility/service/ServiceRegistration.h>
#include <memory>

View File

@ -1,6 +1,6 @@
#include "Tactility/service/ServiceContext.h"
#include "Tactility/TactilityHeadless.h"
#include "Tactility/service/ServiceRegistry.h"
#include "Tactility/service/ServiceRegistration.h"
#include <Tactility/Mutex.h>
#include <Tactility/Timer.h>

View File

@ -9,7 +9,7 @@
#include <Tactility/TactilityHeadless.h>
#include <Tactility/Timer.h>
#include <Tactility/service/ServiceContext.h>
#include <Tactility/service/ServiceRegistry.h>
#include <Tactility/service/ServiceRegistration.h>
#include <Tactility/service/wifi/Wifi.h>
namespace tt::service::statusbar {

View File

@ -1,3 +1,4 @@
#include "Tactility/service/wifi/WifiSettings.h"
#include "Tactility/Preferences.h"
#define WIFI_PREFERENCES_NAMESPACE "wifi"
@ -5,6 +6,8 @@
namespace tt::service::wifi::settings {
// region General settings
void setEnableOnBoot(bool enable) {
Preferences(WIFI_PREFERENCES_NAMESPACE).putBool(WIFI_PREFERENCES_KEY_ENABLE_ON_BOOT, enable);
}
@ -15,4 +18,26 @@ bool shouldEnableOnBoot() {
return enable;
}
// endregion
// region AP
bool contains(const char* ssid) {
return false;
}
bool load(const char* ssid, WifiApSettings* settings) {
return false;
}
bool save(const WifiApSettings* settings) {
return true;
}
bool remove(const char* ssid) {
return true;
}
// endregion
} // namespace

View File

@ -1,148 +0,0 @@
#ifdef ESP_PLATFORM
#include "Tactility/service/wifi/WifiGlobals.h"
#include "Tactility/service/wifi/WifiSettings.h"
#include <Tactility/Log.h>
#include <Tactility/crypt/Hash.h>
#include <Tactility/crypt/Crypt.h>
#include <nvs_flash.h>
#include <cstring>
#define TAG "wifi_settings"
#define TT_NVS_NAMESPACE "wifi_settings" // limited by NVS_KEY_NAME_MAX_SIZE
// region Wi-Fi Credentials - static
static esp_err_t credentials_nvs_open(nvs_handle_t* handle, nvs_open_mode_t mode) {
return nvs_open(TT_NVS_NAMESPACE, NVS_READWRITE, handle);
}
static void credentials_nvs_close(nvs_handle_t handle) {
nvs_close(handle);
}
// endregion Wi-Fi Credentials - static
// region Wi-Fi Credentials - public
namespace tt::service::wifi::settings {
bool contains(const char* ssid) {
nvs_handle_t handle;
esp_err_t result = credentials_nvs_open(&handle, NVS_READONLY);
if (result != ESP_OK) {
TT_LOG_E(TAG, "Failed to open NVS handle: %s", esp_err_to_name(result));
return false;
}
bool key_exists = nvs_find_key(handle, ssid, nullptr) == ESP_OK;
credentials_nvs_close(handle);
return key_exists;
}
bool load(const char* ssid, WifiApSettings* settings) {
nvs_handle_t handle;
esp_err_t result = credentials_nvs_open(&handle, NVS_READONLY);
if (result != ESP_OK) {
TT_LOG_E(TAG, "Failed to open NVS handle: %s", esp_err_to_name(result));
return false;
}
WifiApSettings encrypted_settings;
size_t length = sizeof(WifiApSettings);
result = nvs_get_blob(handle, ssid, &encrypted_settings, &length);
uint8_t iv[16];
crypt::getIv(ssid, strlen(ssid), iv);
int decrypt_result = crypt::decrypt(
iv,
(uint8_t*)encrypted_settings.password,
(uint8_t*)settings->password,
TT_WIFI_CREDENTIALS_PASSWORD_LIMIT
);
// Manually ensure null termination, because encryption must be a multiple of 16 bytes
encrypted_settings.password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT] = 0;
if (decrypt_result != 0) {
result = ESP_FAIL;
TT_LOG_E(TAG, "Failed to decrypt credentials for \"%s\": %d", ssid, decrypt_result);
}
if (result != ESP_OK && result != ESP_ERR_NVS_NOT_FOUND) {
TT_LOG_E(TAG, "Failed to get credentials for \"%s\": %s", ssid, esp_err_to_name(result));
}
credentials_nvs_close(handle);
settings->auto_connect = encrypted_settings.auto_connect;
strcpy((char*)settings->ssid, encrypted_settings.ssid);
return result == ESP_OK;
}
bool save(const WifiApSettings* settings) {
nvs_handle_t handle;
esp_err_t result = credentials_nvs_open(&handle, NVS_READWRITE);
if (result != ESP_OK) {
TT_LOG_E(TAG, "Failed to open NVS handle: %s", esp_err_to_name(result));
return false;
}
WifiApSettings encrypted_settings = {
.ssid = { 0 },
.password = { 0 },
.auto_connect = settings->auto_connect,
};
strcpy((char*)encrypted_settings.ssid, settings->ssid);
// We only decrypt multiples of 16, so we have to ensure the last byte is set to 0
encrypted_settings.password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT] = 0;
uint8_t iv[16];
crypt::getIv(settings->ssid, strlen(settings->ssid), iv);
int encrypt_result = crypt::encrypt(
iv,
(uint8_t*)settings->password,
(uint8_t*)encrypted_settings.password,
TT_WIFI_CREDENTIALS_PASSWORD_LIMIT
);
if (encrypt_result != 0) {
result = ESP_FAIL;
TT_LOG_E(TAG, "Failed to encrypt credentials \"%s\": %d", settings->ssid, encrypt_result);
}
if (result == ESP_OK) {
result = nvs_set_blob(handle, settings->ssid, &encrypted_settings, sizeof(WifiApSettings));
if (result != ESP_OK) {
TT_LOG_E(TAG, "Failed to get credentials for \"%s\": %s", settings->ssid, esp_err_to_name(result));
}
}
credentials_nvs_close(handle);
return result == ESP_OK;
}
bool remove(const char* ssid) {
nvs_handle_t handle;
esp_err_t result = credentials_nvs_open(&handle, NVS_READWRITE);
if (result != ESP_OK) {
TT_LOG_E(TAG, "Failed to open NVS handle to store \"%s\": %s", ssid, esp_err_to_name(result));
return false;
}
result = nvs_erase_key(handle, ssid);
if (result != ESP_OK) {
TT_LOG_E(TAG, "Failed to erase credentials for \"%s\": %s", ssid, esp_err_to_name(result));
}
credentials_nvs_close(handle);
return result == ESP_OK;
}
// end region Wi-Fi Credentials - public
} // nemespace
#endif // ESP_PLATFORM

View File

@ -2,26 +2,6 @@
#include "Tactility/service/wifi/WifiSettings.h"
namespace tt::service::wifi::settings {
#define TAG "wifi_settings_mock"
bool contains(const char* ssid) {
return false;
}
bool load(const char* ssid, WifiApSettings* settings) {
return false;
}
bool save(const WifiApSettings* settings) {
return true;
}
bool remove(const char* ssid) {
return true;
}
} // namespace
#endif // ESP_PLATFORM