This commit is contained in:
Ken Van Hoeylandt 2026-10-13 18:30:51 +02:00
parent 080aa088cf
commit 4e828dd0a6
5 changed files with 23 additions and 17 deletions

View File

@ -7,11 +7,14 @@
## Higher Priority
- Create location service, which works with location providers. GPS is a location provider. IP is also a location provider (must have wifi connected)
- https://github.com/TactilityProject/Tactility/blob/main/LICENSE.md#overview -> put overview table on top
- Fix Wi-Fi so it actually connects to something
- Support http/https on posix
- Vi apps are both named "Vi" in the App Hub
- Use GPS time to set/update the current time: when enabled, at boot, when wifi is not enabled, start the gps device and wait until a lock is acquired, then get the time and sync it. Then stop the GPS device.
- lvgl-module's spinner relies on hard-coded spinner asset from Tactility main project, should be sized based on DPI
- Cursor is hard-coded, needs size based on DPI
- Improve Setup: Show progress of some kind
- Improve Setup: Show progress of some kind. Put skip/next buttons closer? And add outline button style (update docs!)
- Files app should have a page indicator like Launcher.
- Move Bluetooth code from kernel to Modules/bluetooth-module, and have includes in path bluetooth/ then make a bluetooth_command.cpp like wifi_command.cpp
- Inspect code for memory improvements: replace `std::*` with `tt::std::*`
@ -30,6 +33,8 @@
## Medium Priority
- CL-32 display driver performance
- Move more window management code from Tactility/ to window-manager
- Implement signal/raise for terminal apps (for CTRL+C and window resize signals)
- Build the simulator with `-fno-exceptions` to match ESP32. First make app exit() work without C++ unwinding there:
scheduler.cpp's DeferredUnload relies on pthread_exit()'s forced unwind running its destructor.

View File

@ -21,7 +21,6 @@ namespace {
constexpr uint32_t AWAIT_TIMEOUT_MS = 250;
constexpr uint32_t DEVICE_POLL_INTERVAL_MS = 1000;
constexpr uint32_t THREAD_STOP_TIMEOUT_MS = 3000;
constexpr float METERS_PER_SECOND_PER_KNOT = 0.514444f;
// Typical user equivalent range error of consumer receivers, which turns dilution of precision into meters
constexpr float RANGE_ERROR_METERS = 5.0f;
@ -203,10 +202,8 @@ void* create(LocationHost* host) {
void destroy(void*) {
provider.running = false;
if (thread_join(provider.thread, millis_to_ticks(THREAD_STOP_TIMEOUT_MS), millis_to_ticks(10)) != ERROR_NONE) {
LOG_E(TAG, "Thread did not stop in time");
return;
}
// The provider state can only be reused after the worker exits. It does so within AWAIT_TIMEOUT_MS.
thread_join(provider.thread, portMAX_DELAY, millis_to_ticks(10));
device_listener_remove(onDeviceEvent, nullptr);
thread_free(provider.thread);
provider.thread = nullptr;

View File

@ -40,8 +40,6 @@ constexpr uint64_t MIN_INTERVAL_MS = 10 * 1000;
constexpr uint32_t CHECK_INTERVAL_MS = 10 * 1000;
constexpr int SOCKET_TIMEOUT_SECONDS = 5;
constexpr size_t RESPONSE_MAX_LENGTH = 1024;
// DNS resolution has no timeout of its own
constexpr uint32_t THREAD_STOP_TIMEOUT_MS = 30 * 1000;
// IP geolocation is accurate to roughly city level
constexpr float ACCURACY_METERS = 25000.0f;
@ -264,10 +262,8 @@ void* create(LocationHost* host) {
void destroy(void*) {
provider.running = false;
task_event_group_signal(&provider.group, provider.stopBit);
if (thread_join(provider.thread, millis_to_ticks(THREAD_STOP_TIMEOUT_MS), millis_to_ticks(10)) != ERROR_NONE) {
LOG_E(TAG, "Thread did not stop in time");
return;
}
// The provider state can only be reused after the worker exits. All its blocking calls time out.
thread_join(provider.thread, portMAX_DELAY, millis_to_ticks(10));
thread_free(provider.thread);
provider.thread = nullptr;
system_event_unsubscribe(&provider.networkSubscription);
@ -347,7 +343,9 @@ bool ip_api_parse_response(const char* response, IpApiResponse* out) {
char* longitudeEnd;
out->latitude = strtod(latitude.c_str(), &latitudeEnd);
out->longitude = strtod(longitude.c_str(), &longitudeEnd);
if (latitude.empty() || *latitudeEnd != '\0' || longitude.empty() || *longitudeEnd != '\0') {
if (latitude.empty() || *latitudeEnd != '\0' || longitude.empty() || *longitudeEnd != '\0' ||
!std::isfinite(out->latitude) || !std::isfinite(out->longitude) ||
std::fabs(out->latitude) > 90.0 || std::fabs(out->longitude) > 180.0) {
return false;
}
out->success = true;

View File

@ -50,4 +50,8 @@ TEST_CASE("ip_api_parse_response rejects malformed responses") {
CHECK_FALSE(ip_api_parse_response("HTTP/1.1 200 OK\r\nX-Rl: 1\r\n", &parsed));
CHECK_FALSE(ip_api_parse_response("HTTP/1.1 200 OK\r\n\r\nsuccess\nabc\n1.0\n", &parsed));
CHECK_FALSE(ip_api_parse_response("HTTP/1.1 200 OK\r\n\r\nunknown\n", &parsed));
CHECK_FALSE(ip_api_parse_response("HTTP/1.1 200 OK\r\n\r\nsuccess\nnan\n1.0\n", &parsed));
CHECK_FALSE(ip_api_parse_response("HTTP/1.1 200 OK\r\n\r\nsuccess\n1.0\ninf\n", &parsed));
CHECK_FALSE(ip_api_parse_response("HTTP/1.1 200 OK\r\n\r\nsuccess\n90.5\n1.0\n", &parsed));
CHECK_FALSE(ip_api_parse_response("HTTP/1.1 200 OK\r\n\r\nsuccess\n1.0\n-180.5\n", &parsed));
}

View File

@ -81,8 +81,8 @@ static void thread_main_body(void* context) {
vTaskSetThreadLocalStoragePointer(nullptr, LOCAL_STORAGE_SELF_POINTER_INDEX, nullptr);
// The thread can be freed once taskHandle is cleared
const bool createdWithCaps = thread->createdWithCaps;
thread->lock();
const bool createdWithCaps = thread->createdWithCaps;
thread->taskHandle = nullptr;
thread->unlock();
@ -223,7 +223,9 @@ error_t thread_start(Thread* thread) {
affinity != -1 ? affinity : tskNO_AFFINITY,
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT
);
thread->createdWithCaps = (result == pdPASS);
if (result != pdPASS) {
thread->createdWithCaps = false;
}
}
#endif
if (result == pdPASS) {