Boot apps refactored (#498)

- Specify launcher via menuconfig
- Specify auto-start app via menuconfig
- Implement more rigid boot.properties fallbacks
- Devices with tiny screen now auto-start ApWebServer
- ApWebServer UI fixes
This commit is contained in:
Ken Van Hoeylandt 2026-02-12 00:10:04 +01:00 committed by GitHub
parent 49632d15c9
commit 8ff990d635
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
53 changed files with 243 additions and 35 deletions

View File

@ -70,6 +70,8 @@ else ()
message("Building for sim target")
add_compile_definitions(CONFIG_TT_DEVICE_ID="simulator")
add_compile_definitions(CONFIG_TT_DEVICE_NAME="Simulator")
add_compile_definitions(CONFIG_TT_LAUNCHER_APP_ID="Launcher")
add_compile_definitions(CONFIG_TT_AUTO_START_APP_ID="")
endif ()
project(Tactility)

View File

@ -1,2 +0,0 @@
launcherAppId=Launcher
#autoStartAppId=

View File

@ -2,6 +2,9 @@
vendor=BigTreeTech
name=Panda Touch,K Touch
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=CYD
name=2432S024C
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=CYD
name=2432S028R
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=CYD
name=2432S028R v3
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=CYD
name=2432S032C
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=CYD
name=4848S040C
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -3,6 +3,9 @@ vendor=CYD
name=8048S043C
incubating=false
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=CYD
name=E32R28T
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=CYD
name=E32R32P
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Elecrow
name=CrowPanel Advance 2.8"
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=Elecrow
name=CrowPanel Advance 3.5"
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=Elecrow
name=CrowPanel Advance 5.0"
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=Elecrow
name=CrowPanel Basic 2.8"
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Elecrow
name=CrowPanel Basic 3.5"
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Elecrow
name=CrowPanel Basic 5.0"
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Generic
name=ESP32
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Generic
name=ESP32-C6
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32C6
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Generic
name=ESP32-P4
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32P4
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Generic
name=ESP32-S3
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Guition
name=JC1060P470C-I-W-Y
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32P4
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=Guition
name=JC2432W328C
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Guition
name=JC3248W535C
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=Guition
name=JC8048W550C
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -3,6 +3,9 @@ vendor=Heltec
name=WiFi LoRa 32 v3
incubating=true
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=8MB

View File

@ -2,6 +2,9 @@
vendor=LilyGO
name=T-Deck,T-Deck Plus
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -2,6 +2,10 @@
vendor=LilyGO
name=T-Display S3
[apps]
launcherAppId=Launcher
autoStartAppId=ApWebServer
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -3,6 +3,10 @@ vendor=LilyGO
name=T-Display
incubating=true
[apps]
launcherAppId=Launcher
autoStartAppId=ApWebServer
[hardware]
target=ESP32
flashSize=16MB

View File

@ -3,6 +3,10 @@ vendor=LilyGO
name=T-Dongle S3
incubating=true
[apps]
launcherAppId=Launcher
autoStartAppId=ApWebServer
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=LilyGO
name=T-Lora Pager
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=M5Stack
name=Cardputer Adv
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=8MB

View File

@ -2,6 +2,9 @@
vendor=M5Stack
name=Cardputer,Cardputer v1.1
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=8MB

View File

@ -2,6 +2,9 @@
vendor=M5Stack
name=Core2
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=M5Stack
name=CoreS3
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -3,6 +3,9 @@ vendor=M5Stack
name=PaperS3
incubating=true
[apps]
launcherAppId=Launcher
[hardware]
target=esp32s3
flashSize=16MB

View File

@ -3,6 +3,10 @@ vendor=M5Stack
name=StickC Plus
incubating=true
[apps]
launcherAppId=Launcher
autoStartAppId=ApWebServer
[hardware]
target=ESP32
flashSize=4MB

View File

@ -3,6 +3,10 @@ vendor=M5Stack
name=StickC Plus2
incubating=true
[apps]
launcherAppId=Launcher
autoStartAppId=ApWebServer
[hardware]
target=ESP32
flashSize=8MB

View File

@ -2,6 +2,9 @@
vendor=M5Stack
name=Tab5
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32P4
flashSize=16MB

View File

@ -2,6 +2,9 @@
vendor=unPhone
name=unPhone
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=8MB

View File

@ -3,6 +3,10 @@ vendor=Waveshare
name=ESP32 S3 GEEK
incubating=true
[apps]
launcherAppId=Launcher
autoStartAppId=ApWebServer
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -3,6 +3,10 @@ vendor=WaveShare
name=S3 LCD 1.3"
incubating=true
[apps]
launcherAppId=Launcher
autoStartAppId=ApWebServer
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -3,6 +3,10 @@ vendor=WaveShare
name=S3 Touch LCD 1.28"
incubating=true
[apps]
launcherAppId=Launcher
autoStartAppId=ApWebServer
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -3,6 +3,10 @@ vendor=WaveShare
name=S3 Touch LCD 1.47"
incubating=true
[apps]
launcherAppId=Launcher
autoStartAppId=ApWebServer
[hardware]
target=ESP32S3
flashSize=16MB
@ -17,5 +21,8 @@ size=1.47"
shape=rectangle
dpi=247
[cdn]
warningMessage=Touch doesn't work yet
[lvgl]
colorDepth=16

View File

@ -2,6 +2,9 @@
vendor=WaveShare
name=S3 Touch LCD 4.3"
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=4MB

View File

@ -2,6 +2,9 @@
vendor=Wireless Tag
name=WT32 SC01 Plus
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB

View File

@ -3,20 +3,39 @@ menu "Tactility App"
config TT_DEVICE_NAME
string "Device Name"
default ""
help
Human-readable device name, including vendor
config TT_DEVICE_ID
string "Device Identifier"
default ""
# T-Deck device-related code was directly referenced from Tactility in a pull request.
# This breaks other devices because the code does not exist in those implementations.
# Until we move it out into a proper driver, we have to have pre-processor definition for that.
config TT_TDECK_WORKAROUND
bool "Temporary work-around until we fix the T-Deck keyboard and trackball settings"
default n
config TT_SPLASH_DURATION
int "Splash Duration (ms)"
default 1000
range 0 3000
help
The minimum time to show the splash screen in milliseconds.
When set to 0, startup will continue to desktop as soon as boot operations are finished.
The name of the directory in Devices/
See https://docs.tactilityproject.org for formatting guidance.
config TT_LAUNCHER_APP_ID
string "Launcher App ID"
default "Launcher"
help
The applications that gives access to other application.
This is the first thing that starts after the boot screen.
The user can override it from a boot.properties file.
config TT_AUTO_START_APP_ID
string "Auto Start App ID"
default ""
help
An application that gets automatically started from the launcher application.
This is optional and can be left empty.
The user can override it from a boot.properties file.
# T-Deck device-related code was directly referenced from Tactility in a pull request.
# This breaks other devices because the code does not exist in those implementations.
# Until we move it out into a proper driver, we have to have pre-processor definition for that.
config TT_TDECK_WORKAROUND
bool "Temporary work-around until we fix the T-Deck keyboard and trackball settings"
default n
config TT_SPLASH_DURATION
int "Splash Duration (ms)"
default 1000
range 0 3000
help
The minimum time to show the splash screen in milliseconds.
When set to 0, startup will continue to desktop as soon as boot operations are finished.
endmenu

View File

@ -17,7 +17,7 @@ struct BootSettings {
* then it will try to load the one from the data mount point.
*
* @param[out] properties the resulting properties
* @return true when the properties were successfully loaded and the result was set
* @return true when the properties were successfully loaded (they might still be empty strings!)
*/
bool loadBootSettings(BootSettings& properties);

View File

@ -44,18 +44,30 @@ public:
lv_obj_set_style_text_color(labelSsid, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
labelSsidValue = lv_label_create(wrapper);
lv_obj_set_style_text_align(labelSsidValue, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
lv_obj_set_width(labelSsidValue, LV_PCT(100));
lv_label_set_long_mode(labelSsidValue, LV_LABEL_LONG_SCROLL);
lv_obj_set_style_margin_hor(labelSsidValue, 2, LV_PART_MAIN);
lv_obj_t* labelPassword = lv_label_create(wrapper);
lv_label_set_text(labelPassword, "Pass:");
lv_obj_set_style_text_color(labelPassword, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
labelPasswordValue = lv_label_create(wrapper);
lv_obj_set_style_text_align(labelPasswordValue, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
lv_obj_set_width(labelPasswordValue, LV_PCT(100));
lv_label_set_long_mode(labelPasswordValue, LV_LABEL_LONG_SCROLL);
lv_obj_set_style_margin_hor(labelPasswordValue, 2, LV_PART_MAIN);
lv_obj_t* labelIp = lv_label_create(wrapper);
lv_label_set_text(labelIp, "IP:");
lv_obj_set_style_text_color(labelIp, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
labelIpValue = lv_label_create(wrapper);
lv_obj_set_style_text_align(labelIpValue, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
lv_obj_set_width(labelIpValue, LV_PCT(100));
lv_label_set_long_mode(labelIpValue, LV_LABEL_LONG_SCROLL);
lv_obj_set_style_margin_hor(labelIpValue, 2, LV_PART_MAIN);
// Start AP Mode and WebServer
settings::webserver::WebServerSettings apSettings = wsSettings;

View File

@ -130,6 +130,29 @@ class BootApp : public App {
return 0;
}
static std::string getLauncherAppId() {
settings::BootSettings boot_properties;
// When boot.properties hasn't been overridden, return default
if (!settings::loadBootSettings(boot_properties)) {
return CONFIG_TT_LAUNCHER_APP_ID;
}
// When boot properties didn't specify an override, return default
if (boot_properties.launcherAppId.empty()) {
LOGGER.error("Failed to load launcher configuration, or launcher not configured");
return CONFIG_TT_LAUNCHER_APP_ID;
}
// If the app in the boot.properties does not exist, return default
if (findAppManifestById(boot_properties.launcherAppId) == nullptr) {
LOGGER.error("Launcher app {} not found", boot_properties.launcherAppId);
return CONFIG_TT_LAUNCHER_APP_ID;
}
// The boot.properties launcher app id is valid
return boot_properties.launcherAppId;
}
static void startNextApp() {
#ifdef ESP_PLATFORM
if (esp_reset_reason() == ESP_RST_PANIC) {
@ -137,16 +160,7 @@ class BootApp : public App {
return;
}
#endif
settings::BootSettings boot_properties;
std::string launcher_app_id;
if (settings::loadBootSettings(boot_properties) && boot_properties.launcherAppId.empty()) {
LOGGER.error("Failed to load launcher configuration, or launcher not configured");
launcher_app_id = boot_properties.launcherAppId;
} else {
launcher_app_id = "Launcher";
}
auto launcher_app_id = getLauncherAppId();
start(launcher_app_id);
}

View File

@ -8,6 +8,7 @@
#include <Tactility/service/loader/Loader.h>
#include <Tactility/settings/BootSettings.h>
#include <cstring>
#include <lvgl.h>
namespace tt::app::launcher {
@ -92,9 +93,22 @@ public:
void onCreate(AppContext& app) override {
settings::BootSettings boot_properties;
if (settings::loadBootSettings(boot_properties) && !boot_properties.autoStartAppId.empty()) {
LOGGER.info("Starting {}", boot_properties.autoStartAppId);
start(boot_properties.autoStartAppId);
if (settings::loadBootSettings(boot_properties)) {
if (
!boot_properties.autoStartAppId.empty() &&
findAppManifestById(boot_properties.autoStartAppId) != nullptr
) {
LOGGER.info("Starting {}", boot_properties.autoStartAppId);
start(boot_properties.autoStartAppId);
} else {
LOGGER.info("No auto-start app configured. Skipping default auto-start due to boot.properties presence.");
}
} else if (
strcmp(CONFIG_TT_AUTO_START_APP_ID, "") != 0 &&
findAppManifestById(CONFIG_TT_AUTO_START_APP_ID) != nullptr
) {
LOGGER.info("Starting {}", CONFIG_TT_AUTO_START_APP_ID);
start(CONFIG_TT_AUTO_START_APP_ID);
}
}

View File

@ -11,7 +11,7 @@
namespace tt::settings {
static const auto LOGGER = Logger("BootSettings");
constexpr auto* TAG = "BootSettings";
constexpr auto* PROPERTIES_FILE_FORMAT = "{}/settings/boot.properties";
constexpr auto* PROPERTIES_KEY_LAUNCHER_APP_ID = "launcherAppId";
@ -37,11 +37,11 @@ bool loadBootSettings(BootSettings& properties) {
properties.launcherAppId = value;
}
})) {
LOGGER.error("Failed to load {}", path);
LOG_I(TAG, "No settings at %s", path.c_str());
return false;
}
return !properties.launcherAppId.empty();
return true;
}
}

View File

@ -95,9 +95,7 @@ def write_partition_table(output_file, device_properties: ConfigParser, is_dev:
output_file.write(f"CONFIG_PARTITION_TABLE_FILENAME=\"partitions-{flash_size_number}mb.csv\"\n")
def write_tactility_variables(output_file, device_properties: ConfigParser, device_id: str):
device_selector_name = device_id.upper().replace("-", "_")
device_selector = f"CONFIG_TT_DEVICE_{device_selector_name}"
output_file.write(f"{device_selector}=y\n")
# Board and vendor
board_vendor = get_property_or_exit(device_properties, "general", "vendor").replace("\"", "\\\"")
board_name = get_property_or_exit(device_properties, "general", "name").replace("\"", "\\\"")
if board_name == board_vendor or board_vendor == "":
@ -107,7 +105,14 @@ def write_tactility_variables(output_file, device_properties: ConfigParser, devi
output_file.write(f"CONFIG_TT_DEVICE_ID=\"{device_id}\"\n")
if device_id == "lilygo-tdeck":
output_file.write("CONFIG_TT_TDECK_WORKAROUND=y\n")
# Launcher app id
launcher_app_id = get_property_or_exit(device_properties, "apps", "launcherAppId").replace("\"", "\\\"")
output_file.write(f"CONFIG_TT_LAUNCHER_APP_ID=\"{launcher_app_id}\"\n")
# Auto start app id
auto_start_app_id = get_property_or_none(device_properties, "apps", "autoStartAppId")
if auto_start_app_id is not None:
safe_auto_start_app_id = auto_start_app_id.replace("\"", "\\\"")
output_file.write(f"CONFIG_TT_AUTO_START_APP_ID=\"{safe_auto_start_app_id}\"\n")
def write_core_variables(output_file, device_properties: ConfigParser):
idf_target = get_property_or_exit(device_properties, "hardware", "target").lower()