mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-04-18 17:35:05 +00:00
App hub and more (#383)
- Added `AppHub` app - Added `AppHubDetails` app - Added `cJSON` dependency - Renamed `AppSim` module to `FirmwareSim` - Added extra `tt::app::alertdialg::start()` - Renamed `addApp()`, `removeApp()`, `findAppById()` and `getApps()` to `addAppManifest()`, `removeAppManifest()`, `findAppManifestById()` and `getAppManifests()` - Added `tt::lvgl::toolbar_clear_actions()` - Added `tt::network::EspHttpClient` as a thread-safe wrapper around `esp_http_client` - Added `tt::network::http::download()` to download files - Added `tt::network::ntp::isSynced()` - When time is synced, the timestamp is stored in NVS flash. On boot, it is restored. This helps SSL connections when doing a quick reset: when WiFi reconnects, the user doesn't have to wait for NTP sync before SSL works. - Added `tt::json::Reader` as a `cJSON` wrapper - Added `int64_t` support for `Preferences` - Added `int64_t` support for `Bundle` - Added dependencies: `cJSON`, `esp-tls` - When time is synced via NTP, disable time sync. - Added docs to 'tt::file::` functions - Added `tt::string::join()` that works with `std::vector<const char*>` - Fixed `tt::file::getLastPathSegment()` for the scenario when a path was passed with only a single segment - Set `CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120` (from about 3k) for all boards - Set `CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y` for all boards
This commit is contained in:
parent
e9384e0c11
commit
f660550f86
8
.github/actions/build-simulator/action.yml
vendored
8
.github/actions/build-simulator/action.yml
vendored
@ -36,14 +36,16 @@ runs:
|
|||||||
WLR_LIBINPUT_NO_DEVICES: 1
|
WLR_LIBINPUT_NO_DEVICES: 1
|
||||||
WAYLAND_DISPLAY: wayland-1
|
WAYLAND_DISPLAY: wayland-1
|
||||||
GTK_USE_PORTAL: 0
|
GTK_USE_PORTAL: 0
|
||||||
- name: "Configure Project"
|
- name: Setup cmake
|
||||||
uses: threeal/cmake-action@v1.3.0
|
uses: jwlawson/actions-setup-cmake@v2
|
||||||
|
with:
|
||||||
|
cmake-version: '3.31.x'
|
||||||
- name: "Prepare Project"
|
- name: "Prepare Project"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake -S ./ -B buildsim
|
run: cmake -S ./ -B buildsim
|
||||||
- name: "Build Tests"
|
- name: "Build Tests"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake --build buildsim --target AppSim
|
run: cmake --build buildsim --target FirmwareSim
|
||||||
- name: 'Release'
|
- name: 'Release'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: Buildscripts/release-simulator.sh buildsim release/Simulator-${{ inputs.os_name }}-${{ inputs.platform_name }}
|
run: Buildscripts/release-simulator.sh buildsim release/Simulator-${{ inputs.os_name }}-${{ inputs.platform_name }}
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -13,3 +13,6 @@
|
|||||||
[submodule "Libraries/minitar/minitar"]
|
[submodule "Libraries/minitar/minitar"]
|
||||||
path = Libraries/minitar/minitar
|
path = Libraries/minitar/minitar
|
||||||
url = https://github.com/ByteWelder/minitar.git
|
url = https://github.com/ByteWelder/minitar.git
|
||||||
|
[submodule "Libraries/cJSON/cJSON"]
|
||||||
|
path = Libraries/cJSON/cJSON
|
||||||
|
url = git@github.com:DaveGamble/cJSON.git
|
||||||
|
|||||||
@ -12,6 +12,6 @@ target_path=$2
|
|||||||
mkdir -p $target_path
|
mkdir -p $target_path
|
||||||
|
|
||||||
cp version.txt $target_path
|
cp version.txt $target_path
|
||||||
cp $build_path/App/AppSim $target_path/
|
cp $build_path/Firmware/FirmwareSim $target_path/
|
||||||
cp -r Data/data $target_path/
|
cp -r Data/data $target_path/
|
||||||
cp -r Data/system $target_path/
|
cp -r Data/system $target_path/
|
||||||
|
|||||||
@ -77,6 +77,8 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
# FreeRTOS
|
# FreeRTOS
|
||||||
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Boards/Simulator/Source CACHE STRING "")
|
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Boards/Simulator/Source CACHE STRING "")
|
||||||
set(FREERTOS_PORT GCC_POSIX CACHE STRING "")
|
set(FREERTOS_PORT GCC_POSIX CACHE STRING "")
|
||||||
|
|
||||||
|
add_subdirectory(Libraries/cJSON)
|
||||||
add_subdirectory(Libraries/FreeRTOS-Kernel)
|
add_subdirectory(Libraries/FreeRTOS-Kernel)
|
||||||
add_subdirectory(Libraries/lv_screenshot)
|
add_subdirectory(Libraries/lv_screenshot)
|
||||||
add_subdirectory(Libraries/QRCode)
|
add_subdirectory(Libraries/QRCode)
|
||||||
@ -92,18 +94,20 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
set(ENABLE_PROGRAMS OFF)
|
set(ENABLE_PROGRAMS OFF)
|
||||||
add_subdirectory(Libraries/mbedtls)
|
add_subdirectory(Libraries/mbedtls)
|
||||||
|
|
||||||
|
# SDL
|
||||||
|
set(SDL_STATIC ON CACHE BOOL "" FORCE)
|
||||||
|
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
|
||||||
|
add_subdirectory(Libraries/SDL) # Added as idf component for ESP and as library for other targets
|
||||||
|
|
||||||
|
# LVGL
|
||||||
|
add_compile_definitions($<$<BOOL:${LV_USE_DRAW_SDL}>:LV_USE_DRAW_SDL=1>)
|
||||||
|
add_subdirectory(Libraries/lvgl) # Added as idf component for ESP and as library for other targets
|
||||||
|
target_link_libraries(lvgl PRIVATE SDL2-static)
|
||||||
|
|
||||||
# Sim app
|
# Sim app
|
||||||
add_subdirectory(Firmware)
|
add_subdirectory(Firmware)
|
||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
add_subdirectory(Tests)
|
add_subdirectory(Tests)
|
||||||
|
|
||||||
# SDL
|
|
||||||
add_compile_definitions($<$<BOOL:${LV_USE_DRAW_SDL}>:LV_USE_DRAW_SDL=1>)
|
|
||||||
add_subdirectory(Libraries/SDL) # Added as idf component for ESP and as library for other targets
|
|
||||||
|
|
||||||
# LVGL
|
|
||||||
add_subdirectory(Libraries/lvgl) # Added as idf component for ESP and as library for other targets
|
|
||||||
target_link_libraries(lvgl PRIVATE SDL2-static)
|
|
||||||
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
17
Data/system/certificates/WE1.pem
Normal file
17
Data/system/certificates/WE1.pem
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICnzCCAiWgAwIBAgIQf/MZd5csIkp2FV0TttaF4zAKBggqhkjOPQQDAzBHMQsw
|
||||||
|
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
|
||||||
|
MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIwMTQw
|
||||||
|
MDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp
|
||||||
|
Y2VzMQwwCgYDVQQDEwNXRTEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARvzTr+
|
||||||
|
Z1dHTCEDhUDCR127WEcPQMFcF4XGGTfn1XzthkubgdnXGhOlCgP4mMTG6J7/EFmP
|
||||||
|
LCaY9eYmJbsPAvpWo4H+MIH7MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggr
|
||||||
|
BgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU
|
||||||
|
kHeSNWfE/6jMqeZ72YB5e8yT+TgwHwYDVR0jBBgwFoAUgEzW63T/STaj1dj8tT7F
|
||||||
|
avCUHYwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzAChhhodHRwOi8vaS5wa2ku
|
||||||
|
Z29vZy9yNC5jcnQwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2MucGtpLmdvb2cv
|
||||||
|
ci9yNC5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwMDaAAwZQIx
|
||||||
|
AOcCq1HW90OVznX+0RGU1cxAQXomvtgM8zItPZCuFQ8jSBJSjz5keROv9aYsAm5V
|
||||||
|
sQIwJonMaAFi54mrfhfoFNZEfuNMSQ6/bIBiNLiyoX46FohQvKeIoJ99cx7sUkFN
|
||||||
|
7uJW
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@ -9,6 +9,7 @@
|
|||||||
## Higher Priority
|
## Higher Priority
|
||||||
|
|
||||||
- Calculator bugs (see GitHub issue)
|
- Calculator bugs (see GitHub issue)
|
||||||
|
- Store last synced timestamp in NVS (see how HTTPS client example app)
|
||||||
- External app loading: Check the version of Tactility and check ESP target hardware to check for compatibility
|
- External app loading: Check the version of Tactility and check ESP target hardware to check for compatibility
|
||||||
Check during installation process, but also when starting (SD card might have old app install from before Tactility OS update)
|
Check during installation process, but also when starting (SD card might have old app install from before Tactility OS update)
|
||||||
- Make a URL handler. Use it for handling local files. Match file types with apps.
|
- Make a URL handler. Use it for handling local files. Match file types with apps.
|
||||||
|
|||||||
@ -15,8 +15,8 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
)
|
)
|
||||||
else ()
|
else ()
|
||||||
|
|
||||||
add_executable(AppSim ${SOURCE_FILES})
|
add_executable(FirmwareSim ${SOURCE_FILES})
|
||||||
target_link_libraries(AppSim
|
target_link_libraries(FirmwareSim
|
||||||
PRIVATE Tactility
|
PRIVATE Tactility
|
||||||
PRIVATE TactilityCore
|
PRIVATE TactilityCore
|
||||||
PRIVATE Simulator
|
PRIVATE Simulator
|
||||||
|
|||||||
6
Libraries/cJSON/CMakeLists.txt
Normal file
6
Libraries/cJSON/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
file(GLOB SOURCES "cJSON/*.c")
|
||||||
|
|
||||||
|
add_library(cJSON STATIC)
|
||||||
|
target_sources(cJSON PRIVATE ${SOURCES})
|
||||||
|
include_directories(cJSON "cJSON/")
|
||||||
|
target_include_directories(cJSON PUBLIC "cJSON/")
|
||||||
3
Libraries/cJSON/README.md
Normal file
3
Libraries/cJSON/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# cJSON
|
||||||
|
|
||||||
|
This wrapper exists because the original CMake scripts break the builds for Linux and macOS (linker errors)
|
||||||
1
Libraries/cJSON/cJSON
Submodule
1
Libraries/cJSON/cJSON
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit acc76239bee01d8e9c858ae2cab296704e52d916
|
||||||
@ -15,8 +15,10 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
QRCode
|
QRCode
|
||||||
esp_http_server
|
esp_http_server
|
||||||
esp_http_client
|
esp_http_client
|
||||||
|
esp-tls
|
||||||
esp_lvgl_port
|
esp_lvgl_port
|
||||||
esp_wifi
|
esp_wifi
|
||||||
|
json
|
||||||
minitar
|
minitar
|
||||||
minmea
|
minmea
|
||||||
nvs_flash
|
nvs_flash
|
||||||
@ -68,6 +70,7 @@ else()
|
|||||||
add_definitions(-D_Nonnull=)
|
add_definitions(-D_Nonnull=)
|
||||||
|
|
||||||
target_link_libraries(Tactility
|
target_link_libraries(Tactility
|
||||||
|
PUBLIC cJSON
|
||||||
PUBLIC TactilityCore
|
PUBLIC TactilityCore
|
||||||
PUBLIC freertos_kernel
|
PUBLIC freertos_kernel
|
||||||
PUBLIC lvgl
|
PUBLIC lvgl
|
||||||
|
|||||||
@ -24,14 +24,17 @@ public:
|
|||||||
|
|
||||||
bool hasBool(const std::string& key) const;
|
bool hasBool(const std::string& key) const;
|
||||||
bool hasInt32(const std::string& key) const;
|
bool hasInt32(const std::string& key) const;
|
||||||
|
bool hasInt64(const std::string& key) const;
|
||||||
bool hasString(const std::string& key) const;
|
bool hasString(const std::string& key) const;
|
||||||
|
|
||||||
bool optBool(const std::string& key, bool& out) const;
|
bool optBool(const std::string& key, bool& out) const;
|
||||||
bool optInt32(const std::string& key, int32_t& out) const;
|
bool optInt32(const std::string& key, int32_t& out) const;
|
||||||
|
bool optInt64(const std::string& key, int64_t& out) const;
|
||||||
bool optString(const std::string& key, std::string& out) const;
|
bool optString(const std::string& key, std::string& out) const;
|
||||||
|
|
||||||
void putBool(const std::string& key, bool value);
|
void putBool(const std::string& key, bool value);
|
||||||
void putInt32(const std::string& key, int32_t value);
|
void putInt32(const std::string& key, int32_t value);
|
||||||
|
void putInt64(const std::string& key, int64_t value);
|
||||||
void putString(const std::string& key, const std::string& value);
|
void putString(const std::string& key, const std::string& value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -9,18 +9,18 @@ namespace tt::app {
|
|||||||
struct AppManifest;
|
struct AppManifest;
|
||||||
|
|
||||||
/** Register an application with its manifest */
|
/** Register an application with its manifest */
|
||||||
void addApp(const AppManifest& manifest);
|
void addAppManifest(const AppManifest& manifest);
|
||||||
|
|
||||||
/** Remove an app from the registry */
|
/** Remove an app from the registry */
|
||||||
bool removeApp(const std::string& id);
|
bool removeAppManifest(const std::string& id);
|
||||||
|
|
||||||
/** Find an application manifest by its id
|
/** Find an application manifest by its id
|
||||||
* @param[in] id the manifest id
|
* @param[in] id the manifest id
|
||||||
* @return the application manifest if it was found
|
* @return the application manifest if it was found
|
||||||
*/
|
*/
|
||||||
_Nullable std::shared_ptr<AppManifest> findAppById(const std::string& id);
|
_Nullable std::shared_ptr<AppManifest> findAppManifestById(const std::string& id);
|
||||||
|
|
||||||
/** @return a list of all registered apps. This includes user and system apps. */
|
/** @return a list of all registered apps. This includes user and system apps. */
|
||||||
std::vector<std::shared_ptr<AppManifest>> getApps();
|
std::vector<std::shared_ptr<AppManifest>> getAppManifests();
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -22,6 +22,14 @@ namespace tt::app::alertdialog {
|
|||||||
* @return the launch id
|
* @return the launch id
|
||||||
*/
|
*/
|
||||||
LaunchId start(const std::string& title, const std::string& message, const std::vector<std::string>& buttonLabels);
|
LaunchId start(const std::string& title, const std::string& message, const std::vector<std::string>& buttonLabels);
|
||||||
|
/**
|
||||||
|
* Show a dialog with the provided title, message and 0, 1 or more buttons.
|
||||||
|
* @param[in] title the title to show in the toolbar
|
||||||
|
* @param[in] message the message to display
|
||||||
|
* @param[in] buttonLabels the buttons to show
|
||||||
|
* @return the launch id
|
||||||
|
*/
|
||||||
|
LaunchId start(const std::string& title, const std::string& message, const std::vector<const char*>& buttonLabels);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a dialog with the provided title, message and an OK button
|
* Show a dialog with the provided title, message and an OK button
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
|
||||||
namespace tt::lvgl {
|
namespace tt::lvgl {
|
||||||
|
|
||||||
#define TOOLBAR_ACTION_LIMIT 4
|
#define TOOLBAR_ACTION_LIMIT 4
|
||||||
|
|
||||||
/** Create a toolbar widget that shows the app name as title */
|
/** Create a toolbar widget that shows the app name as title */
|
||||||
@ -60,4 +59,10 @@ lv_obj_t* toolbar_add_switch_action(lv_obj_t* obj);
|
|||||||
*/
|
*/
|
||||||
lv_obj_t* toolbar_add_spinner_action(lv_obj_t* obj);
|
lv_obj_t* toolbar_add_spinner_action(lv_obj_t* obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all actions from the toolbar
|
||||||
|
* @param[in] obj the toolbar instance
|
||||||
|
*/
|
||||||
|
void toolbar_clear_actions(lv_obj_t* obj);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
104
Tactility/Include/Tactility/network/EspHttpClient.h
Normal file
104
Tactility/Include/Tactility/network/EspHttpClient.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
|
#include <esp_http_client.h>
|
||||||
|
|
||||||
|
namespace tt::network {
|
||||||
|
|
||||||
|
class EspHttpClient {
|
||||||
|
|
||||||
|
static constexpr auto* TAG = "EspHttpClient";
|
||||||
|
|
||||||
|
std::unique_ptr<esp_http_client_config_t> config = nullptr;
|
||||||
|
esp_http_client_handle_t client;
|
||||||
|
bool isOpen = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
~EspHttpClient() {
|
||||||
|
if (isOpen) {
|
||||||
|
esp_http_client_close(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client != nullptr) {
|
||||||
|
esp_http_client_cleanup(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool init(std::unique_ptr<esp_http_client_config_t> inConfig) {
|
||||||
|
TT_LOG_I(TAG, "init(%s)", inConfig->url);
|
||||||
|
assert(this->config == nullptr);
|
||||||
|
config = std::move(inConfig);
|
||||||
|
client = esp_http_client_init(config.get());
|
||||||
|
return client != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open() {
|
||||||
|
assert(client != nullptr);
|
||||||
|
TT_LOG_I(TAG, "open()");
|
||||||
|
auto result = esp_http_client_open(client, 0);
|
||||||
|
|
||||||
|
if (result != ESP_OK) {
|
||||||
|
TT_LOG_E(TAG, "open() failed: %s", esp_err_to_name(result));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isOpen = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fetchHeaders() const {
|
||||||
|
assert(client != nullptr);
|
||||||
|
TT_LOG_I(TAG, "fetchHeaders()");
|
||||||
|
return esp_http_client_fetch_headers(client) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isStatusCodeOk() const {
|
||||||
|
assert(client != nullptr);
|
||||||
|
const auto status_code = getStatusCode();
|
||||||
|
return status_code >= 200 && status_code < 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getStatusCode() const {
|
||||||
|
assert(client != nullptr);
|
||||||
|
const auto status_code = esp_http_client_get_status_code(client);
|
||||||
|
TT_LOG_I(TAG, "Status code %d", status_code);
|
||||||
|
return status_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getContentLength() const {
|
||||||
|
assert(client != nullptr);
|
||||||
|
return esp_http_client_get_content_length(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
int read(char* bytes, int size) const {
|
||||||
|
assert(client != nullptr);
|
||||||
|
TT_LOG_I(TAG, "read(%d)", size);
|
||||||
|
return esp_http_client_read(client, bytes, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int readResponse(char* bytes, int size) const {
|
||||||
|
assert(client != nullptr);
|
||||||
|
TT_LOG_I(TAG, "readResponse(%d)", size);
|
||||||
|
return esp_http_client_read_response(client, bytes, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool close() {
|
||||||
|
assert(client != nullptr);
|
||||||
|
TT_LOG_I(TAG, "close()");
|
||||||
|
return esp_http_client_close(client) == ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cleanup() {
|
||||||
|
assert(client != nullptr);
|
||||||
|
TT_LOG_I(TAG, "cleanup()");
|
||||||
|
const auto result = esp_http_client_cleanup(client);
|
||||||
|
client = nullptr;
|
||||||
|
return result == ESP_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
15
Tactility/Include/Tactility/network/Http.h
Normal file
15
Tactility/Include/Tactility/network/Http.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace tt::network::http {
|
||||||
|
|
||||||
|
void download(
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& certFilePath,
|
||||||
|
const std::string &downloadFilePath,
|
||||||
|
std::function<void()> onSuccess,
|
||||||
|
std::function<void(const char* errorMessage)> onError
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
7
Tactility/Include/Tactility/network/Ntp.h
Normal file
7
Tactility/Include/Tactility/network/Ntp.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace tt::network::ntp {
|
||||||
|
|
||||||
|
bool isSynced();
|
||||||
|
|
||||||
|
}
|
||||||
13
Tactility/Private/Tactility/app/apphub/AppHub.h
Normal file
13
Tactility/Private/Tactility/app/apphub/AppHub.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace tt::app::apphub {
|
||||||
|
|
||||||
|
constexpr auto* CERTIFICATE_PATH = "/system/certificates/WE1.pem";
|
||||||
|
|
||||||
|
std::string getAppsJsonUrl();
|
||||||
|
|
||||||
|
std::string getDownloadUrl(const std::string& relativePath);
|
||||||
|
|
||||||
|
}
|
||||||
21
Tactility/Private/Tactility/app/apphub/AppHubEntry.h
Normal file
21
Tactility/Private/Tactility/app/apphub/AppHubEntry.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace tt::app::apphub {
|
||||||
|
|
||||||
|
struct AppHubEntry {
|
||||||
|
std::string appId;
|
||||||
|
std::string appVersionName;
|
||||||
|
int32_t appVersionCode;
|
||||||
|
std::string appName;
|
||||||
|
std::string appDescription;
|
||||||
|
std::string targetSdk;
|
||||||
|
std::vector<std::string> targetPlatforms;
|
||||||
|
std::string file;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool parseJson(const std::string& filePath, std::vector<AppHubEntry>& entries);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Tactility/app/apphub/AppHubEntry.h>
|
||||||
|
|
||||||
|
namespace tt::app::apphubdetails {
|
||||||
|
|
||||||
|
void start(const apphub::AppHubEntry& entry);
|
||||||
|
|
||||||
|
} // namespace
|
||||||
77
Tactility/Private/Tactility/json/Reader.h
Normal file
77
Tactility/Private/Tactility/json/Reader.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cJSON.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace tt::json {
|
||||||
|
|
||||||
|
class Reader {
|
||||||
|
|
||||||
|
const cJSON* root;
|
||||||
|
static constexpr const char* TAG = "json::Reader";
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit Reader(const cJSON* root) : root(root) {}
|
||||||
|
|
||||||
|
bool readString(const char* key, std::string& output) const {
|
||||||
|
const auto* child = cJSON_GetObjectItemCaseSensitive(root, key);
|
||||||
|
if (!cJSON_IsString(child)) {
|
||||||
|
TT_LOG_E(TAG, "%s is not a string", key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
output = cJSON_GetStringValue(child);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readInt32(const char* key, int32_t& output) const {
|
||||||
|
double buffer;
|
||||||
|
if (!readNumber(key, buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
output = buffer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readInt(const char* key, int& output) const {
|
||||||
|
double buffer;
|
||||||
|
if (!readNumber(key, buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
output = buffer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readNumber(const char* key, double& output) const {
|
||||||
|
const auto* child = cJSON_GetObjectItemCaseSensitive(root, key);
|
||||||
|
if (!cJSON_IsNumber(child)) {
|
||||||
|
TT_LOG_E(TAG, "%s is not a string", key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
output = cJSON_GetNumberValue(child);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readStringArray(const char* key, std::vector<std::string>& output) const {
|
||||||
|
const auto* child = cJSON_GetObjectItemCaseSensitive(root, key);
|
||||||
|
if (!cJSON_IsArray(child)) {
|
||||||
|
TT_LOG_E(TAG, "%s is not an array", key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto size = cJSON_GetArraySize(child);
|
||||||
|
TT_LOG_I(TAG, "Processing %d array children", size);
|
||||||
|
output.resize(size);
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
const auto string_json = cJSON_GetArrayItem(child, i);
|
||||||
|
if (!cJSON_IsString(string_json)) {
|
||||||
|
TT_LOG_E(TAG, "array child of %s is not a string", key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
output[i] = cJSON_GetStringValue(string_json);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,14 +1,14 @@
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
#include "nvs_flash.h"
|
#include <Tactility/Preferences.h>
|
||||||
#include "Tactility/Preferences.h"
|
|
||||||
|
|
||||||
#include <Tactility/TactilityCore.h>
|
#include <Tactility/TactilityCore.h>
|
||||||
|
|
||||||
#define TAG "preferences"
|
#include <nvs_flash.h>
|
||||||
|
|
||||||
namespace tt {
|
namespace tt {
|
||||||
|
|
||||||
|
constexpr auto* TAG = "Preferences";
|
||||||
|
|
||||||
bool Preferences::optBool(const std::string& key, bool& out) const {
|
bool Preferences::optBool(const std::string& key, bool& out) const {
|
||||||
nvs_handle_t handle;
|
nvs_handle_t handle;
|
||||||
if (nvs_open(namespace_, NVS_READWRITE, &handle) != ESP_OK) {
|
if (nvs_open(namespace_, NVS_READWRITE, &handle) != ESP_OK) {
|
||||||
@ -37,6 +37,18 @@ bool Preferences::optInt32(const std::string& key, int32_t& out) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Preferences::optInt64(const std::string& key, int64_t& out) const {
|
||||||
|
nvs_handle_t handle;
|
||||||
|
if (nvs_open(namespace_, NVS_READWRITE, &handle) != ESP_OK) {
|
||||||
|
TT_LOG_E(TAG, "Failed to open namespace %s", namespace_);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
bool success = nvs_get_i64(handle, key.c_str(), &out) == ESP_OK;
|
||||||
|
nvs_close(handle);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Preferences::optString(const std::string& key, std::string& out) const {
|
bool Preferences::optString(const std::string& key, std::string& out) const {
|
||||||
nvs_handle_t handle;
|
nvs_handle_t handle;
|
||||||
if (nvs_open(namespace_, NVS_READWRITE, &handle) != ESP_OK) {
|
if (nvs_open(namespace_, NVS_READWRITE, &handle) != ESP_OK) {
|
||||||
@ -63,6 +75,11 @@ bool Preferences::hasInt32(const std::string& key) const {
|
|||||||
return optInt32(key, temp);
|
return optInt32(key, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Preferences::hasInt64(const std::string& key) const {
|
||||||
|
int64_t temp;
|
||||||
|
return optInt64(key, temp);
|
||||||
|
}
|
||||||
|
|
||||||
bool Preferences::hasString(const std::string& key) const {
|
bool Preferences::hasString(const std::string& key) const {
|
||||||
std::string temp;
|
std::string temp;
|
||||||
return optString(key, temp);
|
return optString(key, temp);
|
||||||
@ -92,6 +109,18 @@ void Preferences::putInt32(const std::string& key, int32_t value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Preferences::putInt64(const std::string& key, int64_t value) {
|
||||||
|
nvs_handle_t handle;
|
||||||
|
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
|
||||||
|
if (nvs_set_i64(handle, key.c_str(), value) != ESP_OK) {
|
||||||
|
TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str());
|
||||||
|
}
|
||||||
|
nvs_close(handle);
|
||||||
|
} else {
|
||||||
|
TT_LOG_E(TAG, "Failed to open namespace %s", namespace_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Preferences::putString(const std::string& key, const std::string& text) {
|
void Preferences::putString(const std::string& key, const std::string& text) {
|
||||||
nvs_handle_t handle;
|
nvs_handle_t handle;
|
||||||
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
|
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
|
||||||
|
|||||||
@ -30,6 +30,11 @@ bool Preferences::hasInt32(const std::string& key) const {
|
|||||||
return preferences.hasInt32(bundle_key);
|
return preferences.hasInt32(bundle_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Preferences::hasInt64(const std::string& key) const {
|
||||||
|
std::string bundle_key = get_bundle_key(namespace_, key);
|
||||||
|
return preferences.hasInt64(bundle_key);
|
||||||
|
}
|
||||||
|
|
||||||
bool Preferences::hasString(const std::string& key) const {
|
bool Preferences::hasString(const std::string& key) const {
|
||||||
std::string bundle_key = get_bundle_key(namespace_, key);
|
std::string bundle_key = get_bundle_key(namespace_, key);
|
||||||
return preferences.hasString(bundle_key);
|
return preferences.hasString(bundle_key);
|
||||||
@ -45,6 +50,11 @@ bool Preferences::optInt32(const std::string& key, int32_t& out) const {
|
|||||||
return preferences.optInt32(bundle_key, out);
|
return preferences.optInt32(bundle_key, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Preferences::optInt64(const std::string& key, int64_t& out) const {
|
||||||
|
std::string bundle_key = get_bundle_key(namespace_, key);
|
||||||
|
return preferences.optInt64(bundle_key, out);
|
||||||
|
}
|
||||||
|
|
||||||
bool Preferences::optString(const std::string& key, std::string& out) const {
|
bool Preferences::optString(const std::string& key, std::string& out) const {
|
||||||
std::string bundle_key = get_bundle_key(namespace_, key);
|
std::string bundle_key = get_bundle_key(namespace_, key);
|
||||||
return preferences.optString(bundle_key, out);
|
return preferences.optString(bundle_key, out);
|
||||||
@ -60,6 +70,11 @@ void Preferences::putInt32(const std::string& key, int32_t value) {
|
|||||||
return preferences.putInt32(bundle_key, value);
|
return preferences.putInt32(bundle_key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Preferences::putInt64(const std::string& key, int64_t value) {
|
||||||
|
std::string bundle_key = get_bundle_key(namespace_, key);
|
||||||
|
return preferences.putInt64(bundle_key, value);
|
||||||
|
}
|
||||||
|
|
||||||
void Preferences::putString(const std::string& key, const std::string& value) {
|
void Preferences::putString(const std::string& key, const std::string& value) {
|
||||||
std::string bundle_key = get_bundle_key(namespace_, key);
|
std::string bundle_key = get_bundle_key(namespace_, key);
|
||||||
return preferences.putString(bundle_key, value);
|
return preferences.putString(bundle_key, value);
|
||||||
|
|||||||
@ -56,6 +56,8 @@ namespace service {
|
|||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
namespace addgps { extern const AppManifest manifest; }
|
namespace addgps { extern const AppManifest manifest; }
|
||||||
|
namespace apphub { extern const AppManifest manifest; }
|
||||||
|
namespace apphubdetails { extern const AppManifest manifest; }
|
||||||
namespace alertdialog { extern const AppManifest manifest; }
|
namespace alertdialog { extern const AppManifest manifest; }
|
||||||
namespace appdetails { extern const AppManifest manifest; }
|
namespace appdetails { extern const AppManifest manifest; }
|
||||||
namespace applist { extern const AppManifest manifest; }
|
namespace applist { extern const AppManifest manifest; }
|
||||||
@ -99,53 +101,55 @@ namespace app {
|
|||||||
|
|
||||||
// List of all apps excluding Boot app (as Boot app calls this function indirectly)
|
// List of all apps excluding Boot app (as Boot app calls this function indirectly)
|
||||||
static void registerInternalApps() {
|
static void registerInternalApps() {
|
||||||
addApp(app::alertdialog::manifest);
|
addAppManifest(app::alertdialog::manifest);
|
||||||
addApp(app::appdetails::manifest);
|
addAppManifest(app::appdetails::manifest);
|
||||||
addApp(app::applist::manifest);
|
addAppManifest(app::apphub::manifest);
|
||||||
addApp(app::appsettings::manifest);
|
addAppManifest(app::apphubdetails::manifest);
|
||||||
addApp(app::display::manifest);
|
addAppManifest(app::applist::manifest);
|
||||||
addApp(app::files::manifest);
|
addAppManifest(app::appsettings::manifest);
|
||||||
addApp(app::fileselection::manifest);
|
addAppManifest(app::display::manifest);
|
||||||
addApp(app::imageviewer::manifest);
|
addAppManifest(app::files::manifest);
|
||||||
addApp(app::inputdialog::manifest);
|
addAppManifest(app::fileselection::manifest);
|
||||||
addApp(app::launcher::manifest);
|
addAppManifest(app::imageviewer::manifest);
|
||||||
addApp(app::localesettings::manifest);
|
addAppManifest(app::inputdialog::manifest);
|
||||||
addApp(app::notes::manifest);
|
addAppManifest(app::launcher::manifest);
|
||||||
addApp(app::settings::manifest);
|
addAppManifest(app::localesettings::manifest);
|
||||||
addApp(app::selectiondialog::manifest);
|
addAppManifest(app::notes::manifest);
|
||||||
addApp(app::systeminfo::manifest);
|
addAppManifest(app::settings::manifest);
|
||||||
addApp(app::timedatesettings::manifest);
|
addAppManifest(app::selectiondialog::manifest);
|
||||||
addApp(app::timezone::manifest);
|
addAppManifest(app::systeminfo::manifest);
|
||||||
addApp(app::wifiapsettings::manifest);
|
addAppManifest(app::timedatesettings::manifest);
|
||||||
addApp(app::wificonnect::manifest);
|
addAppManifest(app::timezone::manifest);
|
||||||
addApp(app::wifimanage::manifest);
|
addAppManifest(app::wifiapsettings::manifest);
|
||||||
|
addAppManifest(app::wificonnect::manifest);
|
||||||
|
addAppManifest(app::wifimanage::manifest);
|
||||||
|
|
||||||
#if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED
|
#if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED
|
||||||
addApp(app::usbsettings::manifest);
|
addAppManifest(app::usbsettings::manifest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TT_FEATURE_SCREENSHOT_ENABLED
|
#if TT_FEATURE_SCREENSHOT_ENABLED
|
||||||
addApp(app::screenshot::manifest);
|
addAppManifest(app::screenshot::manifest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
addApp(app::chat::manifest);
|
addAppManifest(app::chat::manifest);
|
||||||
addApp(app::crashdiagnostics::manifest);
|
addAppManifest(app::crashdiagnostics::manifest);
|
||||||
addApp(app::development::manifest);
|
addAppManifest(app::development::manifest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!hal::getConfiguration()->i2c.empty()) {
|
if (!hal::getConfiguration()->i2c.empty()) {
|
||||||
addApp(app::i2cscanner::manifest);
|
addAppManifest(app::i2cscanner::manifest);
|
||||||
addApp(app::i2csettings::manifest);
|
addAppManifest(app::i2csettings::manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hal::getConfiguration()->uart.empty()) {
|
if (!hal::getConfiguration()->uart.empty()) {
|
||||||
addApp(app::addgps::manifest);
|
addAppManifest(app::addgps::manifest);
|
||||||
addApp(app::gpssettings::manifest);
|
addAppManifest(app::gpssettings::manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hal::hasDevice(hal::Device::Type::Power)) {
|
if (hal::hasDevice(hal::Device::Type::Power)) {
|
||||||
addApp(app::power::manifest);
|
addAppManifest(app::power::manifest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +176,7 @@ static void registerInstalledApp(std::string path) {
|
|||||||
manifest.appCategory = app::Category::User;
|
manifest.appCategory = app::Category::User;
|
||||||
manifest.appLocation = app::Location::external(path);
|
manifest.appLocation = app::Location::external(path);
|
||||||
|
|
||||||
app::addApp(manifest);
|
app::addAppManifest(manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registerInstalledApps(const std::string& path) {
|
static void registerInstalledApps(const std::string& path) {
|
||||||
@ -266,7 +270,7 @@ void run(const Configuration& config) {
|
|||||||
|
|
||||||
TT_LOG_I(TAG, "Starting boot app");
|
TT_LOG_I(TAG, "Starting boot app");
|
||||||
// The boot app takes care of registering system apps, user services and user apps
|
// The boot app takes care of registering system apps, user services and user apps
|
||||||
addApp(app::boot::manifest);
|
addAppManifest(app::boot::manifest);
|
||||||
app::start(app::boot::manifest.appId);
|
app::start(app::boot::manifest.appId);
|
||||||
|
|
||||||
TT_LOG_I(TAG, "Main dispatcher ready");
|
TT_LOG_I(TAG, "Main dispatcher ready");
|
||||||
|
|||||||
@ -188,7 +188,7 @@ bool install(const std::string& path) {
|
|||||||
|
|
||||||
manifest.appLocation = Location::external(renamed_target_path);
|
manifest.appLocation = Location::external(renamed_target_path);
|
||||||
|
|
||||||
addApp(manifest);
|
addAppManifest(manifest);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ bool uninstall(const std::string& appId) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!removeApp(appId)) {
|
if (!removeAppManifest(appId)) {
|
||||||
TT_LOG_W(TAG, "Failed to remove app %s from registry", appId.c_str());
|
TT_LOG_W(TAG, "Failed to remove app %s from registry", appId.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ typedef std::unordered_map<std::string, std::shared_ptr<AppManifest>> AppManifes
|
|||||||
static AppManifestMap app_manifest_map;
|
static AppManifestMap app_manifest_map;
|
||||||
static Mutex hash_mutex(Mutex::Type::Normal);
|
static Mutex hash_mutex(Mutex::Type::Normal);
|
||||||
|
|
||||||
void addApp(const AppManifest& manifest) {
|
void addAppManifest(const AppManifest& manifest) {
|
||||||
TT_LOG_I(TAG, "Registering manifest %s", manifest.appId.c_str());
|
TT_LOG_I(TAG, "Registering manifest %s", manifest.appId.c_str());
|
||||||
|
|
||||||
hash_mutex.lock();
|
hash_mutex.lock();
|
||||||
@ -29,7 +29,7 @@ void addApp(const AppManifest& manifest) {
|
|||||||
hash_mutex.unlock();
|
hash_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool removeApp(const std::string& id) {
|
bool removeAppManifest(const std::string& id) {
|
||||||
TT_LOG_I(TAG, "Removing manifest for %s", id.c_str());
|
TT_LOG_I(TAG, "Removing manifest for %s", id.c_str());
|
||||||
|
|
||||||
auto lock = hash_mutex.asScopedLock();
|
auto lock = hash_mutex.asScopedLock();
|
||||||
@ -38,7 +38,7 @@ bool removeApp(const std::string& id) {
|
|||||||
return app_manifest_map.erase(id) == 1;
|
return app_manifest_map.erase(id) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Nullable std::shared_ptr<AppManifest> findAppById(const std::string& id) {
|
_Nullable std::shared_ptr<AppManifest> findAppManifestById(const std::string& id) {
|
||||||
hash_mutex.lock();
|
hash_mutex.lock();
|
||||||
auto result = app_manifest_map.find(id);
|
auto result = app_manifest_map.find(id);
|
||||||
hash_mutex.unlock();
|
hash_mutex.unlock();
|
||||||
@ -49,7 +49,7 @@ _Nullable std::shared_ptr<AppManifest> findAppById(const std::string& id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<AppManifest>> getApps() {
|
std::vector<std::shared_ptr<AppManifest>> getAppManifests() {
|
||||||
std::vector<std::shared_ptr<AppManifest>> manifests;
|
std::vector<std::shared_ptr<AppManifest>> manifests;
|
||||||
hash_mutex.lock();
|
hash_mutex.lock();
|
||||||
for (const auto& item: app_manifest_map) {
|
for (const auto& item: app_manifest_map) {
|
||||||
|
|||||||
@ -31,6 +31,15 @@ LaunchId start(const std::string& title, const std::string& message, const std::
|
|||||||
return app::start(manifest.appId, bundle);
|
return app::start(manifest.appId, bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LaunchId start(const std::string& title, const std::string& message, const std::vector<const char*>& buttonLabels) {
|
||||||
|
std::string items_joined = string::join(buttonLabels, PARAMETER_ITEM_CONCATENATION_TOKEN);
|
||||||
|
auto bundle = std::make_shared<Bundle>();
|
||||||
|
bundle->putString(PARAMETER_BUNDLE_KEY_TITLE, title);
|
||||||
|
bundle->putString(PARAMETER_BUNDLE_KEY_MESSAGE, message);
|
||||||
|
bundle->putString(PARAMETER_BUNDLE_KEY_BUTTON_LABELS, items_joined);
|
||||||
|
return app::start(manifest.appId, bundle);
|
||||||
|
}
|
||||||
|
|
||||||
LaunchId start(const std::string& title, const std::string& message) {
|
LaunchId start(const std::string& title, const std::string& message) {
|
||||||
auto bundle = std::make_shared<Bundle>();
|
auto bundle = std::make_shared<Bundle>();
|
||||||
bundle->putString(PARAMETER_BUNDLE_KEY_TITLE, title);
|
bundle->putString(PARAMETER_BUNDLE_KEY_TITLE, title);
|
||||||
@ -57,8 +66,6 @@ static std::string getTitleParameter(std::shared_ptr<const Bundle> bundle) {
|
|||||||
|
|
||||||
class AlertDialogApp : public App {
|
class AlertDialogApp : public App {
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static void onButtonClickedCallback(lv_event_t* e) {
|
static void onButtonClickedCallback(lv_event_t* e) {
|
||||||
auto app = std::static_pointer_cast<AlertDialogApp>(getCurrentApp());
|
auto app = std::static_pointer_cast<AlertDialogApp>(getCurrentApp());
|
||||||
assert(app != nullptr);
|
assert(app != nullptr);
|
||||||
@ -66,7 +73,6 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onButtonClicked(lv_event_t* e) {
|
void onButtonClicked(lv_event_t* e) {
|
||||||
lv_event_code_t code = lv_event_get_code(e);
|
|
||||||
auto index = reinterpret_cast<std::size_t>(lv_event_get_user_data(e));
|
auto index = reinterpret_cast<std::size_t>(lv_event_get_user_data(e));
|
||||||
TT_LOG_I(TAG, "Selected item at index %d", index);
|
TT_LOG_I(TAG, "Selected item at index %d", index);
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ public:
|
|||||||
const auto parameters = app.getParameters();
|
const auto parameters = app.getParameters();
|
||||||
tt_check(parameters != nullptr, "Parameters missing");
|
tt_check(parameters != nullptr, "Parameters missing");
|
||||||
auto app_id = parameters->getString("appId");
|
auto app_id = parameters->getString("appId");
|
||||||
manifest = findAppById(app_id);
|
manifest = findAppManifestById(app_id);
|
||||||
assert(manifest != nullptr);
|
assert(manifest != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
Tactility/Source/app/apphub/AppHub.cpp
Normal file
27
Tactility/Source/app/apphub/AppHub.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <Tactility/app/apphub/AppHub.h>
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
namespace tt::app::apphub {
|
||||||
|
|
||||||
|
constexpr auto* BASE_URL = "https://cdn.tactility.one/apps";
|
||||||
|
|
||||||
|
static std::string getVersionWithoutPostfix() {
|
||||||
|
std::string version(TT_VERSION);
|
||||||
|
auto index = version.find_first_of('-');
|
||||||
|
if (index == std::string::npos) {
|
||||||
|
return version;
|
||||||
|
} else {
|
||||||
|
return version.substr(0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getAppsJsonUrl() {
|
||||||
|
return std::format("{}/{}/apps.json", BASE_URL, getVersionWithoutPostfix());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getDownloadUrl(const std::string& relativePath) {
|
||||||
|
return std::format("{}/{}/{}", BASE_URL, getVersionWithoutPostfix(), relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
186
Tactility/Source/app/apphub/AppHubApp.cpp
Normal file
186
Tactility/Source/app/apphub/AppHubApp.cpp
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
#include <Tactility/app/apphub/AppHub.h>
|
||||||
|
#include <Tactility/app/apphub/AppHubEntry.h>
|
||||||
|
#include <Tactility/app/apphubdetails/AppHubDetailsApp.h>
|
||||||
|
#include <Tactility/file/File.h>
|
||||||
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
|
#include <Tactility/lvgl/Spinner.h>
|
||||||
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
|
#include <Tactility/network/Http.h>
|
||||||
|
#include <Tactility/Paths.h>
|
||||||
|
#include <Tactility/service/loader/Loader.h>
|
||||||
|
#include <Tactility/service/wifi/Wifi.h>
|
||||||
|
|
||||||
|
#include <lvgl.h>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
namespace tt::app::apphub {
|
||||||
|
|
||||||
|
constexpr auto* TAG = "AppHub";
|
||||||
|
|
||||||
|
extern const AppManifest manifest;
|
||||||
|
|
||||||
|
class AppHubApp final : public App {
|
||||||
|
|
||||||
|
lv_obj_t* contentWrapper = nullptr;
|
||||||
|
lv_obj_t* refreshButton = nullptr;
|
||||||
|
std::string cachedAppsJsonFile = std::format("{}/app_hub.json", getTempPath());
|
||||||
|
std::unique_ptr<Thread> thread;
|
||||||
|
std::vector<AppHubEntry> entries;
|
||||||
|
Mutex mutex;
|
||||||
|
|
||||||
|
static std::shared_ptr<AppHubApp> _Nullable findAppInstance() {
|
||||||
|
auto app_context = getCurrentAppContext();
|
||||||
|
if (app_context->getManifest().appId != manifest.appId) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::static_pointer_cast<AppHubApp>(app_context->getApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onAppPressed(lv_event_t* e) {
|
||||||
|
const auto* self = static_cast<AppHubApp*>(lv_event_get_user_data(e));
|
||||||
|
auto* widget = lv_event_get_target_obj(e);
|
||||||
|
const auto* user_data = lv_obj_get_user_data(widget);
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
const int index = reinterpret_cast<int>(user_data);
|
||||||
|
#else
|
||||||
|
const long long index = reinterpret_cast<long long>(user_data);
|
||||||
|
#endif
|
||||||
|
self->mutex.lock();
|
||||||
|
if (index < self->entries.size()) {
|
||||||
|
apphubdetails::start(self->entries[index]);
|
||||||
|
}
|
||||||
|
self->mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onRefreshPressed(lv_event_t* e) {
|
||||||
|
auto* self = static_cast<AppHubApp*>(lv_event_get_user_data(e));
|
||||||
|
self->refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onRefreshSuccess() {
|
||||||
|
TT_LOG_I(TAG, "Request success");
|
||||||
|
auto lock = lvgl::getSyncLock()->asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
showApps();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onRefreshError(const char* error) {
|
||||||
|
TT_LOG_E(TAG, "Request failed: %s", error);
|
||||||
|
auto lock = lvgl::getSyncLock()->asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
showRefreshFailedError("Cannot reach server");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createAppWidget(const std::shared_ptr<AppManifest>& manifest, lv_obj_t* list) {
|
||||||
|
lv_obj_t* btn = lv_list_add_button(list, nullptr, manifest->appName.c_str());
|
||||||
|
lv_obj_add_event_cb(btn, &onAppPressed, LV_EVENT_SHORT_CLICKED, manifest.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void showRefreshFailedError(const char* message) {
|
||||||
|
lv_obj_clean(contentWrapper);
|
||||||
|
|
||||||
|
auto* label = lv_label_create(contentWrapper);
|
||||||
|
lv_label_set_text(label, message);
|
||||||
|
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
|
||||||
|
lv_obj_remove_flag(refreshButton, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showNoInternet() {
|
||||||
|
showRefreshFailedError("No Internet Connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
void showTimeNotSynced() {
|
||||||
|
showRefreshFailedError("Time is not synced yet.\nIt's required to establish a secure connection.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void showApps() {
|
||||||
|
lv_obj_clean(contentWrapper);
|
||||||
|
mutex.lock();
|
||||||
|
if (parseJson(cachedAppsJsonFile, entries)) {
|
||||||
|
std::ranges::sort(entries, [](auto left, auto right) {
|
||||||
|
return left.appName < right.appName;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto* list = lv_list_create(contentWrapper);
|
||||||
|
lv_obj_set_style_pad_all(list, 0, LV_STATE_DEFAULT);
|
||||||
|
lv_obj_set_size(list, LV_PCT(100), LV_SIZE_CONTENT);
|
||||||
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
|
auto& entry = entries[i];
|
||||||
|
TT_LOG_I(TAG, "Adding %s", entry.appName.c_str());
|
||||||
|
const char* icon = findAppManifestById(entry.appId) != nullptr ? LV_SYMBOL_OK : nullptr;
|
||||||
|
auto* entry_button = lv_list_add_button(list, icon, entry.appName.c_str());
|
||||||
|
lv_obj_set_user_data(entry_button, reinterpret_cast<void*>(i));
|
||||||
|
lv_obj_add_event_cb(entry_button, onAppPressed, LV_EVENT_SHORT_CLICKED, this);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showRefreshFailedError("Failed to load content");
|
||||||
|
}
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
lv_obj_clean(contentWrapper);
|
||||||
|
auto* spinner = lvgl::spinner_create(contentWrapper);
|
||||||
|
lv_obj_align(spinner, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
|
||||||
|
lv_obj_add_flag(refreshButton, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
if (service::wifi::getRadioState() != service::wifi::RadioState::ConnectionActive) {
|
||||||
|
showNoInternet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file::isFile(cachedAppsJsonFile)) {
|
||||||
|
showApps();
|
||||||
|
}
|
||||||
|
|
||||||
|
network::http::download(
|
||||||
|
getAppsJsonUrl(),
|
||||||
|
CERTIFICATE_PATH,
|
||||||
|
cachedAppsJsonFile,
|
||||||
|
[] {
|
||||||
|
auto app = findAppInstance();
|
||||||
|
if (app != nullptr) {
|
||||||
|
app->onRefreshSuccess();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const char* error) {
|
||||||
|
auto app = findAppInstance();
|
||||||
|
if (app != nullptr) {
|
||||||
|
app->onRefreshError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void onShow(TT_UNUSED AppContext& app, lv_obj_t* parent) override {
|
||||||
|
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
|
||||||
|
|
||||||
|
auto* toolbar = lvgl::toolbar_create(parent, app);
|
||||||
|
refreshButton = lvgl::toolbar_add_image_button_action(toolbar, LV_SYMBOL_REFRESH, onRefreshPressed, this);
|
||||||
|
lv_obj_add_flag(refreshButton, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
contentWrapper = lv_obj_create(parent);
|
||||||
|
lv_obj_set_width(contentWrapper, LV_PCT(100));
|
||||||
|
lv_obj_set_flex_grow(contentWrapper, 1);
|
||||||
|
lv_obj_set_style_pad_all(contentWrapper, 0, LV_STATE_DEFAULT);
|
||||||
|
lv_obj_set_style_pad_ver(contentWrapper, 0, LV_STATE_DEFAULT);
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const AppManifest manifest = {
|
||||||
|
.appId = "AppHub",
|
||||||
|
.appName = "App Hub",
|
||||||
|
.appCategory = Category::System,
|
||||||
|
.createApp = create<AppHubApp>,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
56
Tactility/Source/app/apphub/AppHubEntry.cpp
Normal file
56
Tactility/Source/app/apphub/AppHubEntry.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <Tactility/app/apphub/AppHubEntry.h>
|
||||||
|
#include <Tactility/file/File.h>
|
||||||
|
#include <Tactility/json/Reader.h>
|
||||||
|
|
||||||
|
namespace tt::app::apphub {
|
||||||
|
|
||||||
|
constexpr auto* TAG = "AppHubJson";
|
||||||
|
|
||||||
|
static bool parseEntry(const cJSON* object, AppHubEntry& entry) {
|
||||||
|
const json::Reader reader(object);
|
||||||
|
return reader.readString("appId", entry.appId) &&
|
||||||
|
reader.readString("appVersionName", entry.appVersionName) &&
|
||||||
|
reader.readInt32("appVersionCode", entry.appVersionCode) &&
|
||||||
|
reader.readString("appName", entry.appName) &&
|
||||||
|
reader.readString("appDescription", entry.appDescription) &&
|
||||||
|
reader.readString("targetSdk", entry.targetSdk) &&
|
||||||
|
reader.readString("file", entry.file) &&
|
||||||
|
reader.readStringArray("targetPlatforms", entry.targetPlatforms);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseJson(const std::string& filePath, std::vector<AppHubEntry>& entries) {
|
||||||
|
auto lock = file::getLock(filePath)->asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
auto data = file::readString(filePath);
|
||||||
|
auto data_ptr = reinterpret_cast<const char*>(data.get());
|
||||||
|
auto* json = cJSON_Parse(data_ptr);
|
||||||
|
if (json == nullptr) {
|
||||||
|
TT_LOG_E(TAG, "Failed to parse %s", filePath.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cJSON* apps_json = cJSON_GetObjectItemCaseSensitive(json, "apps");
|
||||||
|
if (!cJSON_IsArray(apps_json)) {
|
||||||
|
cJSON_Delete(json);
|
||||||
|
TT_LOG_E(TAG, "apps is not an array");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto apps_size = cJSON_GetArraySize(apps_json);
|
||||||
|
entries.resize(apps_size);
|
||||||
|
for (int i = 0; i < apps_size; ++i) {
|
||||||
|
auto& entry = entries.at(i);
|
||||||
|
auto* entry_json = cJSON_GetArrayItem(apps_json, i);
|
||||||
|
if (!parseEntry(entry_json, entry)) {
|
||||||
|
TT_LOG_E(TAG, "Failed to read entry");
|
||||||
|
cJSON_Delete(json);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_Delete(json);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
248
Tactility/Source/app/apphubdetails/AppHubDetailsApp.cpp
Normal file
248
Tactility/Source/app/apphubdetails/AppHubDetailsApp.cpp
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
#include <Tactility/app/alertdialog/AlertDialog.h>
|
||||||
|
#include <Tactility/app/apphub/AppHub.h>
|
||||||
|
#include <Tactility/app/apphub/AppHubEntry.h>
|
||||||
|
#include <Tactility/app/AppRegistration.h>
|
||||||
|
#include <Tactility/file/File.h>
|
||||||
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
|
#include <Tactility/network/Http.h>
|
||||||
|
#include <Tactility/Paths.h>
|
||||||
|
#include <Tactility/service/loader/Loader.h>
|
||||||
|
#include <Tactility/StringUtils.h>
|
||||||
|
|
||||||
|
#include <lvgl.h>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
namespace tt::app::apphubdetails {
|
||||||
|
|
||||||
|
extern const AppManifest manifest;
|
||||||
|
constexpr auto* TAG = "AppHubDetails";
|
||||||
|
|
||||||
|
static std::shared_ptr<Bundle> toBundle(const apphub::AppHubEntry& entry) {
|
||||||
|
auto bundle = std::make_shared<Bundle>();
|
||||||
|
bundle->putString("appId", entry.appId);
|
||||||
|
bundle->putString("appVersionName", entry.appVersionName);
|
||||||
|
bundle->putInt32("appVersionCode", entry.appVersionCode);
|
||||||
|
bundle->putString("appName", entry.appName);
|
||||||
|
bundle->putString("appDescription", entry.appDescription);
|
||||||
|
bundle->putString("targetSdk", entry.targetSdk);
|
||||||
|
bundle->putString("file", entry.file);
|
||||||
|
bundle->putString("targetPlatforms", string::join(entry.targetPlatforms, ","));
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool fromBundle(const Bundle& bundle, apphub::AppHubEntry& entry) {
|
||||||
|
std::string target_platforms_string;
|
||||||
|
auto result = bundle.optString("appId", entry.appId) &&
|
||||||
|
bundle.optString("appVersionName", entry.appVersionName) &&
|
||||||
|
bundle.optInt32("appVersionCode", entry.appVersionCode) &&
|
||||||
|
bundle.optString("appName", entry.appName) &&
|
||||||
|
bundle.optString("appDescription", entry.appDescription) &&
|
||||||
|
bundle.optString("targetSdk", entry.targetSdk) &&
|
||||||
|
bundle.optString("file", entry.file) &&
|
||||||
|
bundle.optString("targetPlatforms", target_platforms_string);
|
||||||
|
entry.targetPlatforms = string::split(target_platforms_string, ",");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppHubDetailsApp final : public App {
|
||||||
|
|
||||||
|
static constexpr auto* CONFIRM_TEXT = "Confirm";
|
||||||
|
static constexpr auto* CANCEL_TEXT = "Cancel";
|
||||||
|
static constexpr auto CONFIRMATION_BUTTON_INDEX = 0;
|
||||||
|
const std::vector<const char*> CONFIRM_CANCEL_LABELS = { CONFIRM_TEXT, CANCEL_TEXT };
|
||||||
|
|
||||||
|
apphub::AppHubEntry entry;
|
||||||
|
std::shared_ptr<AppManifest> entryManifest;
|
||||||
|
lv_obj_t* toolbar = nullptr;
|
||||||
|
lv_obj_t* spinner = nullptr;
|
||||||
|
lv_obj_t* updateButton = nullptr;
|
||||||
|
lv_obj_t* updateLabel = nullptr;
|
||||||
|
LaunchId installLaunchId = -1;
|
||||||
|
LaunchId uninstallLaunchId = -1;
|
||||||
|
LaunchId updateLaunchId = -1;
|
||||||
|
|
||||||
|
LaunchId showConfirmDialog(const char* action) {
|
||||||
|
const auto message = std::format("{} {}?", action, entry.appName);
|
||||||
|
return alertdialog::start(CONFIRM_TEXT, message, CONFIRM_CANCEL_LABELS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onInstallPressed(lv_event_t* e) {
|
||||||
|
auto* self = static_cast<AppHubDetailsApp*>(lv_event_get_user_data(e));
|
||||||
|
self->installLaunchId = self->showConfirmDialog("Install");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onUninstallPressed(lv_event_t* e) {
|
||||||
|
auto* self = static_cast<AppHubDetailsApp*>(lv_event_get_user_data(e));
|
||||||
|
self->uninstallLaunchId = self->showConfirmDialog("Uninstall");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onUpdatePressed(lv_event_t* e) {
|
||||||
|
auto* self = static_cast<AppHubDetailsApp*>(lv_event_get_user_data(e));
|
||||||
|
self->updateLaunchId = self->showConfirmDialog("Update");
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstallApp() {
|
||||||
|
TT_LOG_I(TAG, "Uninstall");
|
||||||
|
|
||||||
|
lvgl::getSyncLock()->lock();
|
||||||
|
lv_obj_remove_flag(spinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lvgl::getSyncLock()->unlock();
|
||||||
|
|
||||||
|
uninstall(entry.appId);
|
||||||
|
|
||||||
|
lvgl::getSyncLock()->lock();
|
||||||
|
updateViews();
|
||||||
|
lvgl::getSyncLock()->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void doInstall() {
|
||||||
|
auto url = apphub::getDownloadUrl(entry.file);
|
||||||
|
auto file_name = file::getLastPathSegment(entry.file);
|
||||||
|
auto temp_file_path = std::format("{}/{}", getTempPath(), file_name);
|
||||||
|
network::http::download(
|
||||||
|
url,
|
||||||
|
apphub::CERTIFICATE_PATH,
|
||||||
|
temp_file_path,
|
||||||
|
[this, temp_file_path] {
|
||||||
|
install(temp_file_path);
|
||||||
|
|
||||||
|
if (!file::deleteFile(temp_file_path.c_str())) {
|
||||||
|
TT_LOG_W(TAG, "Failed to remove %s", temp_file_path.c_str());
|
||||||
|
} else {
|
||||||
|
TT_LOG_I(TAG, "Deleted temporary file %s", temp_file_path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
lvgl::getSyncLock()->lock();
|
||||||
|
updateViews();
|
||||||
|
lvgl::getSyncLock()->unlock();
|
||||||
|
},
|
||||||
|
[temp_file_path](const char* errorMessage) {
|
||||||
|
TT_LOG_E(TAG, "Download failed: %s", errorMessage);
|
||||||
|
alertdialog::start("Error", "Failed to install app");
|
||||||
|
|
||||||
|
if (file::isFile(temp_file_path) && !file::deleteFile(temp_file_path.c_str())) {
|
||||||
|
TT_LOG_W(TAG, "Failed to remove %s", temp_file_path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void installApp() {
|
||||||
|
TT_LOG_I(TAG, "Install");
|
||||||
|
|
||||||
|
lvgl::getSyncLock()->lock();
|
||||||
|
lv_obj_remove_flag(spinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lvgl::getSyncLock()->unlock();
|
||||||
|
|
||||||
|
doInstall();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateApp() {
|
||||||
|
TT_LOG_I(TAG, "Update");
|
||||||
|
|
||||||
|
lvgl::getSyncLock()->lock();
|
||||||
|
lv_obj_remove_flag(spinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lvgl::getSyncLock()->unlock();
|
||||||
|
|
||||||
|
TT_LOG_I(TAG, "Removing previous version");
|
||||||
|
uninstall(entry.appId);
|
||||||
|
TT_LOG_I(TAG, "Installing new version");
|
||||||
|
doInstall();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateViews() {
|
||||||
|
lvgl::toolbar_clear_actions(toolbar);
|
||||||
|
const auto manifest = findAppManifestById(entry.appId);
|
||||||
|
spinner = lvgl::toolbar_add_spinner_action(toolbar);
|
||||||
|
lv_obj_add_flag(spinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_add_flag(updateLabel, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
if (manifest != nullptr) {
|
||||||
|
if (manifest->appVersionCode < entry.appVersionCode) {
|
||||||
|
updateButton = lvgl::toolbar_add_image_button_action(toolbar, LV_SYMBOL_DOWNLOAD, onUpdatePressed, this);
|
||||||
|
lv_obj_remove_flag(updateLabel, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
lvgl::toolbar_add_image_button_action(toolbar, LV_SYMBOL_TRASH, onUninstallPressed, this);
|
||||||
|
} else {
|
||||||
|
lvgl::toolbar_add_image_button_action(toolbar, LV_SYMBOL_DOWNLOAD, onInstallPressed, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void onCreate(AppContext& appContext) override {
|
||||||
|
auto parameters = appContext.getParameters();
|
||||||
|
if (parameters == nullptr) {
|
||||||
|
TT_LOG_E(TAG, "No parameters");
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fromBundle(*parameters.get(), entry)) {
|
||||||
|
TT_LOG_E(TAG, "Invalid parameters");
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onShow(TT_UNUSED AppContext& app, lv_obj_t* parent) override {
|
||||||
|
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
|
||||||
|
|
||||||
|
toolbar = lvgl::toolbar_create(parent, entry.appName.c_str());
|
||||||
|
auto* wrapper = lv_obj_create(parent);
|
||||||
|
lv_obj_set_width(wrapper, LV_PCT(100));
|
||||||
|
lv_obj_set_flex_grow(wrapper, 1);
|
||||||
|
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
|
||||||
|
|
||||||
|
updateLabel = lv_label_create(wrapper);
|
||||||
|
lv_label_set_text(updateLabel, "Update available!");
|
||||||
|
lv_obj_set_style_text_color(updateLabel, lv_color_make(0xff, 0xff, 00), LV_STATE_DEFAULT);
|
||||||
|
|
||||||
|
auto* description_label = lv_label_create(wrapper);
|
||||||
|
lv_obj_set_width(description_label, LV_PCT(100));
|
||||||
|
lv_label_set_long_mode(description_label, LV_LABEL_LONG_MODE_WRAP);
|
||||||
|
if (!entry.appDescription.empty()) {
|
||||||
|
lv_label_set_text(description_label, entry.appDescription.c_str());
|
||||||
|
} else {
|
||||||
|
lv_label_set_text(description_label, "This app has no description yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* version_label = lv_label_create(wrapper);
|
||||||
|
lv_label_set_text_fmt(version_label, "Version %s", entry.appVersionName.c_str());
|
||||||
|
|
||||||
|
updateViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onResult(AppContext& appContext, LaunchId launchId, Result result, std::unique_ptr<Bundle> resultData) override {
|
||||||
|
if (result != Result::Ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alertdialog::getResultIndex(*resultData.get()) != CONFIRMATION_BUTTON_INDEX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (launchId == installLaunchId) {
|
||||||
|
installApp();
|
||||||
|
} else if (launchId == uninstallLaunchId) {
|
||||||
|
uninstallApp();
|
||||||
|
} else if (launchId == updateLaunchId) {
|
||||||
|
updateApp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void start(const apphub::AppHubEntry& entry) {
|
||||||
|
const auto bundle = toBundle(entry);
|
||||||
|
app::start(manifest.appId, bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const AppManifest manifest = {
|
||||||
|
.appId = "AppHubDetails",
|
||||||
|
.appName = "App Details",
|
||||||
|
.appCategory = Category::System,
|
||||||
|
.appFlags = AppManifest::Flags::Hidden,
|
||||||
|
.createApp = create<AppHubDetailsApp>,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
@ -36,7 +36,7 @@ public:
|
|||||||
auto parent_content_height = lv_obj_get_content_height(parent);
|
auto parent_content_height = lv_obj_get_content_height(parent);
|
||||||
lv_obj_set_height(list, parent_content_height - toolbar_height);
|
lv_obj_set_height(list, parent_content_height - toolbar_height);
|
||||||
|
|
||||||
auto manifests = getApps();
|
auto manifests = getAppManifests();
|
||||||
std::ranges::sort(manifests, SortAppManifestByName);
|
std::ranges::sort(manifests, SortAppManifestByName);
|
||||||
|
|
||||||
for (const auto& manifest: manifests) {
|
for (const auto& manifest: manifests) {
|
||||||
|
|||||||
@ -37,7 +37,7 @@ public:
|
|||||||
auto parent_content_height = lv_obj_get_content_height(parent);
|
auto parent_content_height = lv_obj_get_content_height(parent);
|
||||||
lv_obj_set_height(list, parent_content_height - toolbar_height);
|
lv_obj_set_height(list, parent_content_height - toolbar_height);
|
||||||
|
|
||||||
auto manifests = getApps();
|
auto manifests = getAppManifests();
|
||||||
std::ranges::sort(manifests, SortAppManifestByName);
|
std::ranges::sort(manifests, SortAppManifestByName);
|
||||||
|
|
||||||
size_t app_count = 0;
|
size_t app_count = 0;
|
||||||
|
|||||||
@ -92,7 +92,8 @@ void View::viewFile(const std::string& path, const std::string& filename) {
|
|||||||
// install(filename);
|
// install(filename);
|
||||||
auto message = std::format("Do you want to install {}?", filename);
|
auto message = std::format("Do you want to install {}?", filename);
|
||||||
installAppPath = processed_filepath;
|
installAppPath = processed_filepath;
|
||||||
installAppLaunchId = alertdialog::start("Install?", message, { "Yes", "No" });
|
auto choices = std::vector { "Yes", "No" };
|
||||||
|
installAppLaunchId = alertdialog::start("Install?", message, choices);
|
||||||
#endif
|
#endif
|
||||||
} else if (isSupportedImageFile(filename)) {
|
} else if (isSupportedImageFile(filename)) {
|
||||||
imageviewer::start(processed_filepath);
|
imageviewer::start(processed_filepath);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ class SettingsApp final : public App {
|
|||||||
lv_obj_set_width(list, LV_PCT(100));
|
lv_obj_set_width(list, LV_PCT(100));
|
||||||
lv_obj_set_flex_grow(list, 1);
|
lv_obj_set_flex_grow(list, 1);
|
||||||
|
|
||||||
auto manifests = getApps();
|
auto manifests = getAppManifests();
|
||||||
std::ranges::sort(manifests, SortAppManifestByName);
|
std::ranges::sort(manifests, SortAppManifestByName);
|
||||||
for (const auto& manifest: manifests) {
|
for (const auto& manifest: manifests) {
|
||||||
if (manifest->appCategory == Category::Settings) {
|
if (manifest->appCategory == Category::Settings) {
|
||||||
|
|||||||
@ -220,4 +220,9 @@ lv_obj_t* toolbar_add_spinner_action(lv_obj_t* obj) {
|
|||||||
return spinner;
|
return spinner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toolbar_clear_actions(lv_obj_t* obj) {
|
||||||
|
auto* toolbar = reinterpret_cast<Toolbar*>(obj);
|
||||||
|
lv_obj_clean(toolbar->action_container);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
102
Tactility/Source/network/Http.cpp
Normal file
102
Tactility/Source/network/Http.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#include <Tactility/Tactility.h>
|
||||||
|
#include <Tactility/file/File.h>
|
||||||
|
#include <Tactility/network/Http.h>
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
#include <Tactility/network/EspHttpClient.h>
|
||||||
|
#include <esp_sntp.h>
|
||||||
|
#include <esp_http_client.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace tt::network::http {
|
||||||
|
|
||||||
|
constexpr auto* TAG = "HTTP";
|
||||||
|
|
||||||
|
void download(
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& certFilePath,
|
||||||
|
const std::string &downloadFilePath,
|
||||||
|
std::function<void()> onSuccess,
|
||||||
|
std::function<void(const char* errorMessage)> onError
|
||||||
|
) {
|
||||||
|
TT_LOG_I(TAG, "Downloading %s to %s", url.c_str(), downloadFilePath.c_str());
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
getMainDispatcher().dispatch([url, certFilePath, downloadFilePath, onSuccess, onError] {
|
||||||
|
TT_LOG_I(TAG, "Loading certificate");
|
||||||
|
auto certificate = file::readString(certFilePath);
|
||||||
|
auto certificate_length = strlen(reinterpret_cast<const char*>(certificate.get())) + 1;
|
||||||
|
|
||||||
|
auto config = std::make_unique<esp_http_client_config_t>(esp_http_client_config_t {
|
||||||
|
.url = url.c_str(),
|
||||||
|
.auth_type = HTTP_AUTH_TYPE_NONE,
|
||||||
|
.cert_pem = reinterpret_cast<const char*>(certificate.get()),
|
||||||
|
.cert_len = certificate_length,
|
||||||
|
.tls_version = ESP_HTTP_CLIENT_TLS_VER_TLS_1_3,
|
||||||
|
.method = HTTP_METHOD_GET,
|
||||||
|
.timeout_ms = 5000,
|
||||||
|
.transport_type = HTTP_TRANSPORT_OVER_SSL
|
||||||
|
});
|
||||||
|
|
||||||
|
auto client = std::make_unique<EspHttpClient>();
|
||||||
|
if (!client->init(std::move(config))) {
|
||||||
|
onError("Failed to initialize client");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!client->open()) {
|
||||||
|
onError("Failed to open connection");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!client->fetchHeaders()) {
|
||||||
|
onError("Failed to get request headers");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!client->isStatusCodeOk()) {
|
||||||
|
onError("Server response is not OK");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bytes_left = client->getContentLength();
|
||||||
|
|
||||||
|
auto lock = file::getLock(downloadFilePath)->asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
auto file_exists = file::isFile(downloadFilePath);
|
||||||
|
auto* file_mode = file_exists ? "r+" : "w";
|
||||||
|
TT_LOG_I(TAG, "opening %s with mode %s", downloadFilePath.c_str(), file_mode);
|
||||||
|
auto* file = fopen(downloadFilePath.c_str(), file_mode);
|
||||||
|
if (file == nullptr) {
|
||||||
|
onError("Failed to open file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TT_LOG_I(TAG, "Writing %d bytes to %s", bytes_left, downloadFilePath.c_str());
|
||||||
|
char buffer[512];
|
||||||
|
while (bytes_left > 0) {
|
||||||
|
int data_read = client->read(buffer, 512);
|
||||||
|
if (data_read <= 0) {
|
||||||
|
fclose(file);
|
||||||
|
onError("Failed to read data");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bytes_left -= data_read;
|
||||||
|
if (fwrite(buffer, 1, data_read, file) != data_read) {
|
||||||
|
fclose(file);
|
||||||
|
onError("Failed to write all bytes");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
TT_LOG_I(TAG, "Downloaded %s to %s", url.c_str(), downloadFilePath.c_str());
|
||||||
|
onSuccess();
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
#else
|
||||||
|
getMainDispatcher().dispatch([onError] {
|
||||||
|
onError("Not implemented");
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -14,7 +14,7 @@ bool HttpServer::startInternal() {
|
|||||||
config.uri_match_fn = matchUri;
|
config.uri_match_fn = matchUri;
|
||||||
|
|
||||||
if (httpd_start(&server, &config) != ESP_OK) {
|
if (httpd_start(&server, &config) != ESP_OK) {
|
||||||
TT_LOG_E(TAG, "Failed to start http server on port %d", port);
|
TT_LOG_E(TAG, "Failed to start http server on port %lu", port);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
#include <Tactility/network/HttpdReq.h>
|
#include <Tactility/network/HttpdReq.h>
|
||||||
|
#include <Tactility/Log.h>
|
||||||
|
#include <Tactility/StringUtils.h>
|
||||||
|
#include <Tactility/file/File.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <Tactility/Log.h>
|
|
||||||
#include <Tactility/StringUtils.h>
|
|
||||||
#include <Tactility/file/File.h>
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#include "Tactility/network/NtpPrivate.h"
|
#include <Tactility/network/NtpPrivate.h>
|
||||||
|
#include <Tactility/Preferences.h>
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
#include <Tactility/kernel/SystemEvents.h>
|
#include <Tactility/kernel/SystemEvents.h>
|
||||||
@ -7,19 +8,43 @@
|
|||||||
#include <esp_sntp.h>
|
#include <esp_sntp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TAG "ntp"
|
|
||||||
|
|
||||||
namespace tt::network::ntp {
|
namespace tt::network::ntp {
|
||||||
|
|
||||||
|
constexpr auto* TAG = "NTP";
|
||||||
|
static bool processedSyncEvent = false;
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
static void onTimeSynced(struct timeval* tv) {
|
void storeTimeInNvs() {
|
||||||
|
time_t now;
|
||||||
|
time(&now);
|
||||||
|
|
||||||
|
auto preferences = std::make_unique<Preferences>("time");
|
||||||
|
preferences->putInt64("syncTime", now);
|
||||||
|
TT_LOG_I(TAG, "Stored time %llu", now);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTimeFromNvs() {
|
||||||
|
auto preferences = std::make_unique<Preferences>("time");
|
||||||
|
time_t synced_time;
|
||||||
|
if (preferences->optInt64("syncTime", synced_time)) {
|
||||||
|
TT_LOG_I(TAG, "Restoring last known time to %llu", synced_time);
|
||||||
|
timeval get_nvs_time;
|
||||||
|
get_nvs_time.tv_sec = synced_time;
|
||||||
|
settimeofday(&get_nvs_time, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onTimeSynced(timeval* tv) {
|
||||||
TT_LOG_I(TAG, "Time synced (%llu)", tv->tv_sec);
|
TT_LOG_I(TAG, "Time synced (%llu)", tv->tv_sec);
|
||||||
|
processedSyncEvent = true;
|
||||||
|
esp_netif_sntp_deinit();
|
||||||
|
storeTimeInNvs();
|
||||||
kernel::publishSystemEvent(kernel::SystemEvent::Time);
|
kernel::publishSystemEvent(kernel::SystemEvent::Time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("time.cloudflare.com");
|
||||||
config.sync_cb = onTimeSynced;
|
config.sync_cb = onTimeSynced;
|
||||||
esp_netif_sntp_init(&config);
|
esp_netif_sntp_init(&config);
|
||||||
}
|
}
|
||||||
@ -27,8 +52,13 @@ void init() {
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
|
processedSyncEvent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool isSynced() {
|
||||||
|
return processedSyncEvent;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -209,7 +209,7 @@ esp_err_t DevelopmentService::handleAppUninstall(httpd_req_t* request) {
|
|||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!app::findAppById(id_key_pos->second)) {
|
if (!app::findAppManifestById(id_key_pos->second)) {
|
||||||
TT_LOG_I(TAG, "[200] /app/uninstall %s (app wasn't installed)", id_key_pos->second.c_str());
|
TT_LOG_I(TAG, "[200] /app/uninstall %s (app wasn't installed)", id_key_pos->second.c_str());
|
||||||
httpd_resp_send(request, nullptr, 0);
|
httpd_resp_send(request, nullptr, 0);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
|||||||
@ -43,7 +43,7 @@ static const char* appStateToString(app::State state) {
|
|||||||
void LoaderService::onStartAppMessage(const std::string& id, app::LaunchId launchId, std::shared_ptr<const Bundle> parameters) {
|
void LoaderService::onStartAppMessage(const std::string& id, app::LaunchId launchId, std::shared_ptr<const Bundle> parameters) {
|
||||||
TT_LOG_I(TAG, "Start by id %s", id.c_str());
|
TT_LOG_I(TAG, "Start by id %s", id.c_str());
|
||||||
|
|
||||||
auto app_manifest = app::findAppById(id);
|
auto app_manifest = app::findAppManifestById(id);
|
||||||
if (app_manifest == nullptr) {
|
if (app_manifest == nullptr) {
|
||||||
TT_LOG_E(TAG, "App not found: %s", id.c_str());
|
TT_LOG_E(TAG, "App not found: %s", id.c_str());
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -60,6 +60,13 @@ lv_obj_t* tt_lvgl_toolbar_add_switch_action(lv_obj_t* obj);
|
|||||||
*/
|
*/
|
||||||
lv_obj_t* tt_lvgl_toolbar_add_spinner_action(lv_obj_t* obj);
|
lv_obj_t* tt_lvgl_toolbar_add_spinner_action(lv_obj_t* obj);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all actions from the toolbar
|
||||||
|
* @param[in] obj the toolbar instance
|
||||||
|
*/
|
||||||
|
void tt_lvgl_toolbar_clear_actions(lv_obj_t* obj);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -276,6 +276,7 @@ const esp_elfsym main_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_add_text_button_action),
|
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_add_text_button_action),
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_add_switch_action),
|
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_add_switch_action),
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_add_spinner_action),
|
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_add_spinner_action),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_clear_actions),
|
||||||
ESP_ELFSYM_EXPORT(tt_message_queue_alloc),
|
ESP_ELFSYM_EXPORT(tt_message_queue_alloc),
|
||||||
ESP_ELFSYM_EXPORT(tt_message_queue_free),
|
ESP_ELFSYM_EXPORT(tt_message_queue_free),
|
||||||
ESP_ELFSYM_EXPORT(tt_message_queue_put),
|
ESP_ELFSYM_EXPORT(tt_message_queue_put),
|
||||||
|
|||||||
@ -35,4 +35,8 @@ lv_obj_t* tt_lvgl_toolbar_add_spinner_action(lv_obj_t* obj) {
|
|||||||
return tt::lvgl::toolbar_add_spinner_action(obj);
|
return tt::lvgl::toolbar_add_spinner_action(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tt_lvgl_toolbar_clear_actions(lv_obj_t* obj) {
|
||||||
|
tt::lvgl::toolbar_clear_actions(obj);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ class Bundle final {
|
|||||||
enum class Type {
|
enum class Type {
|
||||||
Bool,
|
Bool,
|
||||||
Int32,
|
Int32,
|
||||||
|
Int64,
|
||||||
String,
|
String,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ class Bundle final {
|
|||||||
union {
|
union {
|
||||||
bool value_bool;
|
bool value_bool;
|
||||||
int32_t value_int32;
|
int32_t value_int32;
|
||||||
|
int64_t value_int64;
|
||||||
};
|
};
|
||||||
std::string value_string;
|
std::string value_string;
|
||||||
} Value;
|
} Value;
|
||||||
@ -44,18 +46,22 @@ public:
|
|||||||
|
|
||||||
bool getBool(const std::string& key) const;
|
bool getBool(const std::string& key) const;
|
||||||
int32_t getInt32(const std::string& key) const;
|
int32_t getInt32(const std::string& key) const;
|
||||||
|
int64_t getInt64(const std::string& key) const;
|
||||||
std::string getString(const std::string& key) const;
|
std::string getString(const std::string& key) const;
|
||||||
|
|
||||||
bool hasBool(const std::string& key) const;
|
bool hasBool(const std::string& key) const;
|
||||||
bool hasInt32(const std::string& key) const;
|
bool hasInt32(const std::string& key) const;
|
||||||
|
bool hasInt64(const std::string& key) const;
|
||||||
bool hasString(const std::string& key) const;
|
bool hasString(const std::string& key) const;
|
||||||
|
|
||||||
bool optBool(const std::string& key, bool& out) const;
|
bool optBool(const std::string& key, bool& out) const;
|
||||||
bool optInt32(const std::string& key, int32_t& out) const;
|
bool optInt32(const std::string& key, int32_t& out) const;
|
||||||
|
bool optInt64(const std::string& key, int64_t& out) const;
|
||||||
bool optString(const std::string& key, std::string& out) const;
|
bool optString(const std::string& key, std::string& out) const;
|
||||||
|
|
||||||
void putBool(const std::string& key, bool value);
|
void putBool(const std::string& key, bool value);
|
||||||
void putInt32(const std::string& key, int32_t value);
|
void putInt32(const std::string& key, int32_t value);
|
||||||
|
void putInt64(const std::string& key, int64_t value);
|
||||||
void putString(const std::string& key, const std::string& value);
|
void putString(const std::string& key, const std::string& value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -51,6 +51,16 @@ void split(const std::string& input, const std::string& delimiter, std::function
|
|||||||
*/
|
*/
|
||||||
std::string join(const std::vector<std::string>& input, const std::string& delimiter);
|
std::string join(const std::vector<std::string>& input, const std::string& delimiter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join a set of tokens into a single string, given a delimiter (separator).
|
||||||
|
* If the input is an empty list, the result will be an empty string.
|
||||||
|
* The delimeter is only placed inbetween tokens and not appended at the end of the resulting string.
|
||||||
|
*
|
||||||
|
* @param input the tokens to join together
|
||||||
|
* @param delimiter the separator to join with
|
||||||
|
*/
|
||||||
|
std::string join(const std::vector<const char*>& input, const std::string& delimiter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the lowercase value of a string.
|
* Returns the lowercase value of a string.
|
||||||
* @warning This only works for strings with 1 byte per character
|
* @warning This only works for strings with 1 byte per character
|
||||||
|
|||||||
@ -99,8 +99,18 @@ bool deleteDirectory(const std::string& path);
|
|||||||
*/
|
*/
|
||||||
std::string getChildPath(const std::string& basePath, const std::string& childPath);
|
std::string getChildPath(const std::string& basePath, const std::string& childPath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the last part of the path. This can either be the filename or the deepest folder name.
|
||||||
|
* @param path an absolute or relative path
|
||||||
|
* @return the last segment of the specified path
|
||||||
|
*/
|
||||||
std::string getLastPathSegment(const std::string& path);
|
std::string getLastPathSegment(const std::string& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the first part of the path. This is either the root folder, or a file if the latter has no parent folder.
|
||||||
|
* @param path an absolute or relative path
|
||||||
|
* @return the first segment of the specified path
|
||||||
|
*/
|
||||||
std::string getFirstPathSegment(const std::string& path);
|
std::string getFirstPathSegment(const std::string& path);
|
||||||
|
|
||||||
typedef int (*ScandirFilter)(const dirent*);
|
typedef int (*ScandirFilter)(const dirent*);
|
||||||
|
|||||||
@ -10,6 +10,10 @@ int32_t Bundle::getInt32(const std::string& key) const {
|
|||||||
return this->entries.find(key)->second.value_int32;
|
return this->entries.find(key)->second.value_int32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t Bundle::getInt64(const std::string& key) const {
|
||||||
|
return this->entries.find(key)->second.value_int64;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Bundle::getString(const std::string& key) const {
|
std::string Bundle::getString(const std::string& key) const {
|
||||||
return this->entries.find(key)->second.value_string;
|
return this->entries.find(key)->second.value_string;
|
||||||
}
|
}
|
||||||
@ -24,6 +28,11 @@ bool Bundle::hasInt32(const std::string& key) const {
|
|||||||
return entry != std::end(this->entries) && entry->second.type == Type::Int32;
|
return entry != std::end(this->entries) && entry->second.type == Type::Int32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Bundle::hasInt64(const std::string& key) const {
|
||||||
|
auto entry = this->entries.find(key);
|
||||||
|
return entry != std::end(this->entries) && entry->second.type == Type::Int64;
|
||||||
|
}
|
||||||
|
|
||||||
bool Bundle::hasString(const std::string& key) const {
|
bool Bundle::hasString(const std::string& key) const {
|
||||||
auto entry = this->entries.find(key);
|
auto entry = this->entries.find(key);
|
||||||
return entry != std::end(this->entries) && entry->second.type == Type::String;
|
return entry != std::end(this->entries) && entry->second.type == Type::String;
|
||||||
@ -49,6 +58,16 @@ bool Bundle::optInt32(const std::string& key, int32_t& out) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Bundle::optInt64(const std::string& key, int64_t& out) const {
|
||||||
|
auto entry = this->entries.find(key);
|
||||||
|
if (entry != std::end(this->entries) && entry->second.type == Type::Int64) {
|
||||||
|
out = entry->second.value_int32;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Bundle::optString(const std::string& key, std::string& out) const {
|
bool Bundle::optString(const std::string& key, std::string& out) const {
|
||||||
auto entry = this->entries.find(key);
|
auto entry = this->entries.find(key);
|
||||||
if (entry != std::end(this->entries) && entry->second.type == Type::String) {
|
if (entry != std::end(this->entries) && entry->second.type == Type::String) {
|
||||||
@ -75,6 +94,14 @@ void Bundle::putInt32(const std::string& key, int32_t value) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bundle::putInt64(const std::string& key, int64_t value) {
|
||||||
|
this->entries[key] = {
|
||||||
|
.type = Type::Int64,
|
||||||
|
.value_int64 = value,
|
||||||
|
.value_string = ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void Bundle::putString(const std::string& key, const std::string& value) {
|
void Bundle::putString(const std::string& key, const std::string& value) {
|
||||||
this->entries[key] = {
|
this->entries[key] = {
|
||||||
.type = Type::String,
|
.type = Type::String,
|
||||||
|
|||||||
@ -54,6 +54,28 @@ std::vector<std::string> split(const std::string&input, const std::string&delimi
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string join(const std::vector<const char*>& input, const std::string& delimiter) {
|
||||||
|
std::stringstream stream;
|
||||||
|
size_t size = input.size();
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return "";
|
||||||
|
} else if (size == 1) {
|
||||||
|
return input.front();
|
||||||
|
} else {
|
||||||
|
auto iterator = input.begin();
|
||||||
|
while (iterator != input.end()) {
|
||||||
|
stream << *iterator;
|
||||||
|
iterator++;
|
||||||
|
if (iterator != input.end()) {
|
||||||
|
stream << delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string join(const std::vector<std::string>& input, const std::string& delimiter) {
|
std::string join(const std::vector<std::string>& input, const std::string& delimiter) {
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
size_t size = input.size();
|
size_t size = input.size();
|
||||||
|
|||||||
@ -247,7 +247,7 @@ std::string getLastPathSegment(const std::string& path) {
|
|||||||
if (index != std::string::npos) {
|
if (index != std::string::npos) {
|
||||||
return path.substr(index + 1);
|
return path.substr(index + 1);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
@ -56,4 +58,4 @@ CONFIG_LV_DISP_DEF_REFR_PERIOD=10
|
|||||||
CONFIG_LV_THEME_DEFAULT_DARK=y
|
CONFIG_LV_THEME_DEFAULT_DARK=y
|
||||||
# USB
|
# USB
|
||||||
CONFIG_TINYUSB_MSC_ENABLED=y
|
CONFIG_TINYUSB_MSC_ENABLED=y
|
||||||
CONFIG_TINYUSB_MSC_MOUNT_PATH="/sdcard"
|
CONFIG_TINYUSB_MSC_MOUNT_PATH="/sdcard"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware: Main
|
# Hardware: Main
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# Software defaults
|
# Software defaults
|
||||||
# Increase stack size for WiFi (fixes crash after scan)
|
# Increase stack size for WiFi (fixes crash after scan)
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
|
||||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
@ -28,6 +29,7 @@ CONFIG_WL_SECTOR_SIZE_512=y
|
|||||||
CONFIG_WL_SECTOR_SIZE=512
|
CONFIG_WL_SECTOR_SIZE=512
|
||||||
CONFIG_WL_SECTOR_MODE_SAFE=y
|
CONFIG_WL_SECTOR_MODE_SAFE=y
|
||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
|
||||||
# Hardware defaults
|
# Hardware defaults
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user