From 1593eb80ce6b32180f57e5d9ed702d53f72af8c5 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Jun 2025 13:46:08 +0200 Subject: [PATCH] TactilityC additions (#287) New TactilityC implementations for: - WiFi - GPS - Preferences - Timezone Also includes: - Some fixes to enums/naming - Cleanup elsewhere --- ExternalApps/HelloWorld/tactility.py | 94 +++++++++++-------- Tactility/Include/Tactility/Preferences.h | 6 +- .../Source/app/gpssettings/GpsSettings.cpp | 4 +- TactilityC/Include/tt_app.h | 2 +- TactilityC/Include/tt_app_manifest.h | 12 +-- TactilityC/Include/tt_gps.h | 21 +++++ TactilityC/Include/tt_preferences.h | 83 ++++++++++++++++ TactilityC/Include/tt_time.h | 42 +++++++++ TactilityC/Include/tt_wifi.h | 74 +++++++++++++++ TactilityC/Source/tt_app.cpp | 8 +- TactilityC/Source/tt_bundle.cpp | 20 ++-- TactilityC/Source/tt_gps.cpp | 45 +++++++++ TactilityC/Source/tt_init.cpp | 29 ++++++ TactilityC/Source/tt_preferences.cpp | 53 +++++++++++ TactilityC/Source/tt_time.cpp | 42 +++++++++ TactilityC/Source/tt_timer.cpp | 2 - TactilityC/Source/tt_wifi.cpp | 55 +++++++++++ 17 files changed, 528 insertions(+), 64 deletions(-) create mode 100644 TactilityC/Include/tt_gps.h create mode 100644 TactilityC/Include/tt_preferences.h create mode 100644 TactilityC/Include/tt_time.h create mode 100644 TactilityC/Include/tt_wifi.h create mode 100644 TactilityC/Source/tt_gps.cpp create mode 100644 TactilityC/Source/tt_preferences.cpp create mode 100644 TactilityC/Source/tt_time.cpp create mode 100644 TactilityC/Source/tt_wifi.cpp diff --git a/ExternalApps/HelloWorld/tactility.py b/ExternalApps/HelloWorld/tactility.py index 8b5e2843..c41b2040 100644 --- a/ExternalApps/HelloWorld/tactility.py +++ b/ExternalApps/HelloWorld/tactility.py @@ -9,13 +9,18 @@ import time import urllib.request import zipfile -esp_platforms = ["esp32", "esp32s3"] +# Targetable platforms that represent a specific hardware target +platform_targets = ["esp32", "esp32s3"] +# All valid platform commandline arguments +platform_arguments = platform_targets.copy() +platform_arguments.append("all") ttbuild_path = ".tactility" -ttbuild_version = "0.1.0" +ttbuild_version = "0.3.0" ttbuild_properties_file = "tactility.properties" ttbuild_cdn = "https://cdn.tactility.one" ttbuild_sdk_json_validity = 3600 # seconds verbose = False +use_local_sdk = False spinner_pattern = [ "⠋", @@ -49,15 +54,19 @@ def print_help(): print("Usage: python tactility.py [action] [options]") print("") print("Actions:") - print(" build [esp32,esp32s3,all] Build the app for 1 or more platforms") - print(" clean Clean the build folders") - print(" clearcache Clear the SDK cache") - print(" updateself Update this tool") + print(" build [esp32,esp32s3,all,local] Build the app for the specified platform") + print(" esp32: ESP32") + print(" esp32s3: ESP32 S3") + print(" all: all supported ESP platforms") + print(" clean Clean the build folders") + print(" clearcache Clear the SDK cache") + print(" updateself Update this tool") print("") print("Options:") - print(" --help Show this commandline info") - print(" --skip-build Run everything except the idf.py/CMake commands") - print(" --verbose Show extra console output") + print(" --help Show this commandline info") + print(" --local-sdk Use SDK specifiedc by environment variable TACTILITY_SDK_PATH") + print(" --skip-build Run everything except the idf.py/CMake commands") + print(" --verbose Show extra console output") def download_file(url, filepath): global verbose @@ -92,24 +101,32 @@ def exit_with_error(message): sys.exit(1) def is_valid_platform_name(name): - return name == "all" or name == "esp32" or name == "esp32s3" + global platform_arguments + return name in platform_arguments def validate_environment(): - global ttbuild_properties_file + global ttbuild_properties_file, use_local_sdk if os.environ.get("IDF_PATH") is None: - exit_with_error("IDF is not installed or activated. Ensure you installed the toolset and ran the export command.") - if os.environ.get("TACTILITY_SDK_PATH") is not None: - print_warning("TACTILITY_SDK_PATH is set, but will be ignored by this command") + exit_with_error("Cannot find the Espressif IDF SDK. Ensure it is installed and that it is activated via $PATH_TO_IDF_SDK/export.sh") if not os.path.exists(ttbuild_properties_file): exit_with_error(f"{ttbuild_properties_file} file not found") + if use_local_sdk == False and os.environ.get("TACTILITY_SDK_PATH") is not None: + print_warning("TACTILITY_SDK_PATH is set, but will be ignored by this command.") + print_warning("If you want to use it, use the 'build local' parameters.") + elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None: + exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.") def setup_environment(): global ttbuild_path os.makedirs(ttbuild_path, exist_ok=True) def get_sdk_dir(version, platform): - global ttbuild_cdn - return os.path.join(ttbuild_path, f"{version}-{platform}", "TactilitySDK") + global use_local_sdk + if use_local_sdk: + return os.environ.get("TACTILITY_SDK_PATH") + else: + global ttbuild_cdn + return os.path.join(ttbuild_path, f"{version}-{platform}", "TactilitySDK") def get_sdk_version(): global ttbuild_properties_file @@ -151,14 +168,14 @@ def update_sdk_json(): return download_file(json_url, json_filepath) def should_fetch_sdkconfig_files(): - for platform in esp_platforms: + for platform in platform_targets: sdkconfig_filename = f"sdkconfig.app.{platform}" if not os.path.exists(os.path.join(ttbuild_path, sdkconfig_filename)): return True return False def fetch_sdkconfig_files(): - for platform in esp_platforms: + for platform in platform_targets: sdkconfig_filename = f"sdkconfig.app.{platform}" target_path = os.path.join(ttbuild_path, sdkconfig_filename) if not download_file(f"{ttbuild_cdn}/{sdkconfig_filename}", target_path): @@ -190,7 +207,7 @@ def validate_self(sdk_json): if re.search(tool_compatibility, ttbuild_version) is None: print_error("The tool is not compatible anymore.") print_error("Run 'tactility.py updateself' to update.") - sys.exit() + sys.exit(1) def sdk_download(version, platform): sdk_root_dir = get_sdk_root_dir(version, platform) @@ -316,25 +333,27 @@ def build_action(platform_arg): validate_environment() # Environment setup setup_environment() + platforms_to_build = platform_targets if platform_arg == "all" else [platform_arg] if not is_valid_platform_name(platform_arg): print_help() exit_with_error("Invalid platform name") - if should_fetch_sdkconfig_files(): - fetch_sdkconfig_files() - # Update SDK cache - if should_update_sdk_json() and not update_sdk_json(): - exit_with_error("Failed to retrieve SDK info") - sdk_json = read_sdk_json() - validate_self(sdk_json) - if not "versions" in sdk_json: - exit_with_error("Version data not found in sdk.json") + if not use_local_sdk: + if should_fetch_sdkconfig_files(): + fetch_sdkconfig_files() + # Update SDK cache + if should_update_sdk_json() and not update_sdk_json(): + exit_with_error("Failed to retrieve SDK info") + sdk_json = read_sdk_json() + validate_self(sdk_json) + if not "versions" in sdk_json: + exit_with_error("Version data not found in sdk.json") # Build - platforms_to_build = esp_platforms if platform_arg == "all" else [platform_arg] sdk_version = get_sdk_version() - validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build) - if not sdk_download_all(sdk_version, platforms_to_build): - exit_with_error("Failed to download one or more SDKs") - build_all(sdk_version, platforms_to_build, skip_build) # Environment validation + if not use_local_sdk: + validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build) + if not sdk_download_all(sdk_version, platforms_to_build): + exit_with_error("Failed to download one or more SDKs") + build_all(sdk_version, platforms_to_build, skip_build) # Environment validation def clean_action(): count = 0 @@ -373,14 +392,13 @@ if __name__ == "__main__": action_arg = sys.argv[1] verbose = "--verbose" in sys.argv skip_build = "--skip-build" in sys.argv + use_local_sdk = "--local-sdk" in sys.argv # Actions if action_arg == "build": if len(sys.argv) < 3: print_help() - sys.exit() - else: - platform_arg = sys.argv[2] - build_action(platform_arg) + exit_with_error("Commandline parameter missing") + build_action(sys.argv[2]) elif action_arg == "clean": clean_action() elif action_arg == "clearcache": @@ -389,4 +407,4 @@ if __name__ == "__main__": update_self_action() else: print_help() - sys.exit() + exit_with_error("Unknown commandline parameter") diff --git a/Tactility/Include/Tactility/Preferences.h b/Tactility/Include/Tactility/Preferences.h index d2a34812..b1f778ac 100644 --- a/Tactility/Include/Tactility/Preferences.h +++ b/Tactility/Include/Tactility/Preferences.h @@ -8,9 +8,13 @@ namespace tt { /** * Settings that persist on NVS flash for ESP32. * On simulator, the settings are only in-memory. + * + * Note that on ESP32, there are limitations: + * - namespace name is limited by NVS_NS_NAME_MAX_SIZE (generally 16 characters) + * - key is limited by NVS_KEY_NAME_MAX_SIZE (generally 16 characters) */ class Preferences { -private: + const char* namespace_; public: diff --git a/Tactility/Source/app/gpssettings/GpsSettings.cpp b/Tactility/Source/app/gpssettings/GpsSettings.cpp index 3c1f3e8d..c80de746 100644 --- a/Tactility/Source/app/gpssettings/GpsSettings.cpp +++ b/Tactility/Source/app/gpssettings/GpsSettings.cpp @@ -24,8 +24,6 @@ extern const AppManifest manifest; class GpsSettingsApp final : public App { -private: - std::unique_ptr timer; std::shared_ptr appReference = std::make_shared(this); lv_obj_t* statusWrapper = nullptr; @@ -96,7 +94,7 @@ private: memcpy(&index, &index_as_voidptr, sizeof(int)); std::vector configurations; - auto gps_service = tt::service::gps::findGpsService(); + auto gps_service = service::gps::findGpsService(); if (gps_service && gps_service->getGpsConfigurations(configurations)) { TT_LOG_I(TAG, "Found service and configs %d %d", index, configurations.size()); if (index <= configurations.size()) { diff --git a/TactilityC/Include/tt_app.h b/TactilityC/Include/tt_app.h index b1e97bd2..1e5dbbb0 100644 --- a/TactilityC/Include/tt_app.h +++ b/TactilityC/Include/tt_app.h @@ -18,7 +18,7 @@ BundleHandle _Nullable tt_app_get_parameters(AppHandle handle); * @param[in] result the result state to set * @param[in] bundle the result bundle to set */ -void tt_app_set_result(AppHandle handle, Result result, BundleHandle _Nullable bundle); +void tt_app_set_result(AppHandle handle, AppResult result, BundleHandle _Nullable bundle); /** @return true if a result was set for this app context */ bool tt_app_has_result(AppHandle handle); diff --git a/TactilityC/Include/tt_app_manifest.h b/TactilityC/Include/tt_app_manifest.h index 0640b1d3..7551b4f3 100644 --- a/TactilityC/Include/tt_app_manifest.h +++ b/TactilityC/Include/tt_app_manifest.h @@ -9,14 +9,14 @@ extern "C" { /** Important: These values must map to tt::app::Result values exactly */ typedef enum { - AppResultOk = 0, - AppResultCancelled = 1, - AppResultError = 2 -} Result; + APP_RESULT_OK = 0, + APP_RESULT_CANCELLED = 1, + APP_RESULT_ERROR = 2 +} AppResult; typedef void* AppHandle; -typedef unsigned int LaunchId; +typedef unsigned int AppLaunchId; /** Important: These function types must map to t::app types exactly */ typedef void* (*AppCreateData)(); @@ -25,7 +25,7 @@ typedef void (*AppOnCreate)(AppHandle app, void* _Nullable data); typedef void (*AppOnDestroy)(AppHandle app, void* _Nullable data); typedef void (*AppOnShow)(AppHandle app, void* _Nullable data, lv_obj_t* parent); typedef void (*AppOnHide)(AppHandle app, void* _Nullable data); -typedef void (*AppOnResult)(AppHandle app, void* _Nullable data, LaunchId launchId, Result result, BundleHandle resultData); +typedef void (*AppOnResult)(AppHandle app, void* _Nullable data, AppLaunchId launchId, AppResult result, BundleHandle resultData); typedef struct { /** The application's human-readable name */ diff --git a/TactilityC/Include/tt_gps.h b/TactilityC/Include/tt_gps.h new file mode 100644 index 00000000..8d9bcfae --- /dev/null +++ b/TactilityC/Include/tt_gps.h @@ -0,0 +1,21 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +bool tt_gps_has_coordinates(); + +bool tt_gps_get_coordinates( + float* longitude, + float* latitude, + float* speed, + float* course, + int* day, + int* month, + int* year +); + +#ifdef __cplusplus +} +#endif diff --git a/TactilityC/Include/tt_preferences.h b/TactilityC/Include/tt_preferences.h new file mode 100644 index 00000000..735982b3 --- /dev/null +++ b/TactilityC/Include/tt_preferences.h @@ -0,0 +1,83 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * Note that on ESP32, there are limitations: + * - namespace name is limited by NVS_NS_NAME_MAX_SIZE (generally 16 characters) + * - key is limited by NVS_KEY_NAME_MAX_SIZE (generally 16 characters) + */ + +/** The handle that represents a Preferences instance */ +typedef void* PreferencesHandle; + +/** + * @param[in] identifier the name of the preferences. This determines the NVS namespace on ESP. + * @return a new preferences instance + */ +PreferencesHandle tt_preferences_alloc(const char* identifier); + +/** Dealloc an existing preferences instance */ +void tt_preferences_free(PreferencesHandle handle); + +/** + * Try to get a boolean value + * @param[in] handle the handle that represents the preferences + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[out] out the output value (only set when return value is set to true) + * @return true if "out" was set + */ +bool tt_preferences_opt_bool(PreferencesHandle handle, const char* key, bool* out); + +/** + * Try to get an int32_t value + * @param[in] handle the handle that represents the preferences + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[out] out the output value (only set when return value is set to true) + * @return true if "out" was set + */ +bool tt_preferences_opt_int32(PreferencesHandle handle, const char* key, int32_t* out); + +/** + * Try to get a string + * @warning outSize must be large enough to include null terminator. This means that your string has to be the expected text length + 1 extra character. + * @param[in] handle the handle that represents the preferences + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[out] out the buffer to store the string in + * @param[in] outSize the size of the buffer + * @return true if "out" was set + */ +bool tt_preferences_opt_string(PreferencesHandle handle, const char* key, char* out, uint32_t outSize); + +/** + * Store a boolean value + * @param[in] handle the handle that represents the preferences + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[in] value the value to store + */ +void tt_preferences_put_bool(PreferencesHandle handle, const char* key, bool value); + +/** + * Store an int32_t value + * @param[in] handle the handle that represents the preferences + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[in] value the value to store + */ +void tt_preferences_put_int32(PreferencesHandle handle, const char* key, int32_t value); + +/** + * Store a string value + * @param[in] handle the handle that represents the preferences + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[in] value the value to store + */ +void tt_preferences_put_string(PreferencesHandle handle, const char* key, const char* value); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/TactilityC/Include/tt_time.h b/TactilityC/Include/tt_time.h new file mode 100644 index 00000000..db9f972d --- /dev/null +++ b/TactilityC/Include/tt_time.h @@ -0,0 +1,42 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define TT_TIMEZONE_NAME_BUFFER_LENGTH 32 +#define TT_TIMEZONE_CODE_BUFFER_LENGTH 48 + +/** + * Set the timezone + * @param[in] name human-readable name + * @param[in] code the technical code (from timezones.csv) + */ +void tt_timezone_set(const char* name, const char* code); + +/** + * Get the name of the timezone + * @param[out] buffer the output buffer which will include a null terminator (should be TT_TIMEZONE_NAME_BUFFER_LENGTH) + * @param[in] bufferSize the size of the output buffer + */ +bool tt_timezone_get_name(char* buffer, size_t bufferSize); + +/** + * Get the code of the timezone (see timezones.csv) + */ +bool tt_timezone_get_code(char* buffer, size_t bufferSize); + +/** @return true when clocks should be shown as a 24 hours one instead of 12 hours */ +bool tt_timezone_is_format_24_hour(); + +/** Set whether clocks should be shown as a 24 hours instead of 12 hours + * @param[in] show24Hour + */ +void tt_timezone_set_format_24_hour(bool show24Hour); + +#ifdef __cplusplus +} +#endif diff --git a/TactilityC/Include/tt_wifi.h b/TactilityC/Include/tt_wifi.h new file mode 100644 index 00000000..659fd750 --- /dev/null +++ b/TactilityC/Include/tt_wifi.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include + +#define TT_WIFI_SSID_LIMIT 32 // 32 characters/octets, according to IEEE 802.11-2020 spec +#define TT_WIFI_CREDENTIALS_PASSWORD_LIMIT 64 // 64 characters/octets, according to IEEE 802.11-2020 spec + +#ifdef __cplusplus +extern "C" { +#endif + +/** Important: These values must map to tt::service::wifi::RadioState values exactly */ +typedef enum { + WIFI_RADIO_STATE_ON_PENDING, + WIFI_RADIO_STATE_ON, + WIFI_RADIO_STATE_CONNECTION_PENDING, + WIFI_RADIO_STATE_CONNECTION_ACTIVE, + WIFI_RADIO_STATE_OFF_PENDING, + WIFI_RADIO_STATE_OFF, +} WifiRadioState; + +/** @return the state of the WiFi radio */ +WifiRadioState tt_wifi_get_radio_state(); + +/** @return a textual representation of the WiFi radio state */ +const char* tt_wifi_radio_state_to_string(WifiRadioState state); + +/** Start scanning */ +void tt_wifi_scan(); + +/** @return true if a scan is active/pending */ +bool tt_wifi_is_scanning(); + +/** + * Return the WiFi SSID that the system tries to connect to, or is connected to. + * @param[out] buffer an allocated string buffer. Its size must be (WIFI_SSID_LIMIT + 1). + */ +void tt_wifi_get_connection_target(char* buffer); + +/** + * @brief Enable/disable the radio. Ignores input if desired state matches current state. + * @param[in] enabled + */ +void tt_wifi_set_enabled(bool enabled); + +/** + * + * @param ssid The access point identifier - maximal 32 characters/octets + * @param password the password - maximum 64 characters/octets + * @param channel 0 means "any" + * @param autoConnect whether we want to automatically reconnect if a disconnect occurs + * @param remember whether the record should be stored permanently on the device (it is only stored if this connection attempt succeeds) + */ +void tt_wifi_connect(const char* ssid, const char* password, int32_t channel, bool autoConnect, bool remember); + +/** + * If WiFi is connected, this disconnects it. + */ +void tt_wifi_disconnect(); + +/** + * @return true if WiFi is active and encrypted + */ +bool tt_wifi_is_connnection_secure(); + +/** + * @return the current radio connection link quality + */ +int tt_wifi_get_rssi(); + +#ifdef __cplusplus +} +#endif diff --git a/TactilityC/Source/tt_app.cpp b/TactilityC/Source/tt_app.cpp index bf770720..2a50ddbf 100644 --- a/TactilityC/Source/tt_app.cpp +++ b/TactilityC/Source/tt_app.cpp @@ -10,9 +10,9 @@ BundleHandle _Nullable tt_app_get_parameters(AppHandle handle) { return (BundleHandle)HANDLE_AS_APP_CONTEXT(handle)->getParameters().get(); } -void tt_app_set_result(AppHandle handle, Result result, BundleHandle _Nullable bundle) { - auto shared_bundle = std::unique_ptr((tt::Bundle*)bundle); - HANDLE_AS_APP_CONTEXT(handle)->getApp()->setResult((tt::app::Result)result, std::move(shared_bundle)); +void tt_app_set_result(AppHandle handle, AppResult result, BundleHandle _Nullable bundle) { + auto shared_bundle = std::unique_ptr(static_cast(bundle)); + HANDLE_AS_APP_CONTEXT(handle)->getApp()->setResult(static_cast(result), std::move(shared_bundle)); } bool tt_app_has_result(AppHandle handle) { @@ -24,7 +24,7 @@ void tt_app_start(const char* appId) { } void tt_app_start_with_bundle(const char* appId, BundleHandle parameters) { - tt::app::start(appId, std::shared_ptr((tt::Bundle*)parameters)); + tt::app::start(appId, std::shared_ptr(static_cast(parameters))); } void tt_app_stop() { diff --git a/TactilityC/Source/tt_bundle.cpp b/TactilityC/Source/tt_bundle.cpp index 14530a32..4172bf2c 100644 --- a/TactilityC/Source/tt_bundle.cpp +++ b/TactilityC/Source/tt_bundle.cpp @@ -23,17 +23,19 @@ bool tt_bundle_opt_int32(BundleHandle handle, const char* key, int32_t* out) { } bool tt_bundle_opt_string(BundleHandle handle, const char* key, char* out, uint32_t outSize) { std::string out_string; - if (HANDLE_AS_BUNDLE(handle)->optString(key, out_string)) { - if (out_string.length() < outSize) { // Need 1 byte to add 0 at the end - memcpy(out, out_string.c_str(), out_string.length()); - out[out_string.length()] = 0x00; - return true; - } else { - return false; - } - } else { + + if (!HANDLE_AS_BUNDLE(handle)->optString(key, out_string)) { return false; } + + if (out_string.length() >= outSize) { + // Need 1 byte to add 0 at the end + return false; + } + + memcpy(out, out_string.c_str(), out_string.length()); + out[out_string.length()] = 0x00; + return true; } void tt_bundle_put_bool(BundleHandle handle, const char* key, bool value) { diff --git a/TactilityC/Source/tt_gps.cpp b/TactilityC/Source/tt_gps.cpp new file mode 100644 index 00000000..5131193c --- /dev/null +++ b/TactilityC/Source/tt_gps.cpp @@ -0,0 +1,45 @@ +#include "tt_gps.h" +#include + +using namespace tt::service; + +extern "C" { + +bool tt_gps_has_coordinates() { + auto service = gps::findGpsService(); + return service != nullptr && service->hasCoordinates(); +} + +bool tt_gps_get_coordinates( + float* longitude, + float* latitude, + float* speed, + float* course, + int* day, + int* month, + int* year +) { + auto service = gps::findGpsService(); + + if (service == nullptr) { + return false; + } + + minmea_sentence_rmc rmc; + + if (!service->getCoordinates(rmc)) { + return false; + } + + *longitude = minmea_tocoord(&rmc.longitude); + *latitude = minmea_tocoord(&rmc.latitude); + *speed = minmea_tocoord(&rmc.speed); + *course = minmea_tocoord(&rmc.course); + *day = rmc.date.day; + *month = rmc.date.month; + *year = rmc.date.year; + + return true; +} + +} \ No newline at end of file diff --git a/TactilityC/Source/tt_init.cpp b/TactilityC/Source/tt_init.cpp index a766a883..42e72bf1 100644 --- a/TactilityC/Source/tt_init.cpp +++ b/TactilityC/Source/tt_init.cpp @@ -5,15 +5,19 @@ #include "tt_app_manifest.h" #include "tt_app_selectiondialog.h" #include "tt_bundle.h" +#include "tt_gps.h" #include "tt_hal_i2c.h" #include "tt_lvgl_keyboard.h" #include "tt_lvgl_spinner.h" #include "tt_lvgl_toolbar.h" #include "tt_message_queue.h" #include "tt_mutex.h" +#include "tt_preferences.h" #include "tt_semaphore.h" #include "tt_thread.h" +#include "tt_time.h" #include "tt_timer.h" +#include "tt_wifi.h" #include @@ -39,6 +43,8 @@ const struct esp_elfsym elf_symbols[] { ESP_ELFSYM_EXPORT(tt_bundle_put_bool), ESP_ELFSYM_EXPORT(tt_bundle_put_int32), ESP_ELFSYM_EXPORT(tt_bundle_put_string), + ESP_ELFSYM_EXPORT(tt_gps_has_coordinates), + ESP_ELFSYM_EXPORT(tt_gps_get_coordinates), ESP_ELFSYM_EXPORT(tt_hal_i2c_start), ESP_ELFSYM_EXPORT(tt_hal_i2c_stop), ESP_ELFSYM_EXPORT(tt_hal_i2c_is_started), @@ -72,6 +78,14 @@ const struct esp_elfsym elf_symbols[] { ESP_ELFSYM_EXPORT(tt_mutex_free), ESP_ELFSYM_EXPORT(tt_mutex_lock), ESP_ELFSYM_EXPORT(tt_mutex_unlock), + ESP_ELFSYM_EXPORT(tt_preferences_alloc), + ESP_ELFSYM_EXPORT(tt_preferences_free), + ESP_ELFSYM_EXPORT(tt_preferences_opt_bool), + ESP_ELFSYM_EXPORT(tt_preferences_opt_int32), + ESP_ELFSYM_EXPORT(tt_preferences_opt_string), + ESP_ELFSYM_EXPORT(tt_preferences_put_bool), + ESP_ELFSYM_EXPORT(tt_preferences_put_int32), + ESP_ELFSYM_EXPORT(tt_preferences_put_string), ESP_ELFSYM_EXPORT(tt_semaphore_alloc), ESP_ELFSYM_EXPORT(tt_semaphore_free), ESP_ELFSYM_EXPORT(tt_semaphore_acquire), @@ -99,6 +113,21 @@ const struct esp_elfsym elf_symbols[] { ESP_ELFSYM_EXPORT(tt_timer_get_expire_time), ESP_ELFSYM_EXPORT(tt_timer_set_pending_callback), ESP_ELFSYM_EXPORT(tt_timer_set_thread_priority), + ESP_ELFSYM_EXPORT(tt_timezone_set), + ESP_ELFSYM_EXPORT(tt_timezone_get_name), + ESP_ELFSYM_EXPORT(tt_timezone_get_code), + ESP_ELFSYM_EXPORT(tt_timezone_is_format_24_hour), + ESP_ELFSYM_EXPORT(tt_timezone_set_format_24_hour), + ESP_ELFSYM_EXPORT(tt_wifi_get_radio_state), + ESP_ELFSYM_EXPORT(tt_wifi_radio_state_to_string), + ESP_ELFSYM_EXPORT(tt_wifi_scan), + ESP_ELFSYM_EXPORT(tt_wifi_is_scanning), + ESP_ELFSYM_EXPORT(tt_wifi_get_connection_target), + ESP_ELFSYM_EXPORT(tt_wifi_set_enabled), + ESP_ELFSYM_EXPORT(tt_wifi_connect), + ESP_ELFSYM_EXPORT(tt_wifi_disconnect), + ESP_ELFSYM_EXPORT(tt_wifi_is_connnection_secure), + ESP_ELFSYM_EXPORT(tt_wifi_get_rssi), // tt::lvgl ESP_ELFSYM_EXPORT(tt_lvgl_spinner_create), // lv_event diff --git a/TactilityC/Source/tt_preferences.cpp b/TactilityC/Source/tt_preferences.cpp new file mode 100644 index 00000000..5aeb6d1d --- /dev/null +++ b/TactilityC/Source/tt_preferences.cpp @@ -0,0 +1,53 @@ +#include "tt_preferences.h" +#include +#include + +#define HANDLE_AS_PREFERENCES(handle) ((tt::Preferences*)(handle)) + +extern "C" { + +PreferencesHandle tt_preferences_alloc(const char* identifier) { + return new tt::Preferences(identifier); +} + +void tt_preferences_free(PreferencesHandle handle) { + delete HANDLE_AS_PREFERENCES(handle); +} + +bool tt_preferences_opt_bool(PreferencesHandle handle, const char* key, bool* out) { + return HANDLE_AS_PREFERENCES(handle)->optBool(key, *out); +} + +bool tt_preferences_opt_int32(PreferencesHandle handle, const char* key, int32_t* out) { + return HANDLE_AS_PREFERENCES(handle)->optInt32(key, *out); +} +bool tt_preferences_opt_string(PreferencesHandle handle, const char* key, char* out, uint32_t outSize) { + std::string out_string; + + if (!HANDLE_AS_PREFERENCES(handle)->optString(key, out_string)) { + return false; + } + + if (out_string.length() >= outSize) { + // Need 1 byte to add 0 at the end + return false; + } + + memcpy(out, out_string.c_str(), out_string.length()); + out[out_string.length()] = 0x00; + return true; +} + +void tt_preferences_put_bool(PreferencesHandle handle, const char* key, bool value) { + HANDLE_AS_PREFERENCES(handle)->putBool(key, value); +} + +void tt_preferences_put_int32(PreferencesHandle handle, const char* key, int32_t value) { + HANDLE_AS_PREFERENCES(handle)->putInt32(key, value); +} + +void tt_preferences_put_string(PreferencesHandle handle, const char* key, const char* value) { + HANDLE_AS_PREFERENCES(handle)->putString(key, value); +} + +} \ No newline at end of file diff --git a/TactilityC/Source/tt_time.cpp b/TactilityC/Source/tt_time.cpp new file mode 100644 index 00000000..9a255e8f --- /dev/null +++ b/TactilityC/Source/tt_time.cpp @@ -0,0 +1,42 @@ +#include "tt_time.h" + +#include +#include + +using namespace tt; + +extern "C" { + +void tt_timezone_set(const char* name, const char* code) { + time::setTimeZone(name, code); +} + +bool tt_timezone_get_name(char* buffer, size_t bufferSize) { + auto name = time::getTimeZoneName(); + if (bufferSize < (name.length() + 1)) { + return false; + } else { + strcpy(buffer, name.c_str()); + return true; + } +} + +bool tt_timezone_get_code(char* buffer, size_t bufferSize) { + auto code = time::getTimeZoneCode(); + if (bufferSize < (code.length() + 1)) { + return false; + } else { + strcpy(buffer, code.c_str()); + return true; + } +} + +bool tt_timezone_is_format_24_hour() { + return time::isTimeFormat24Hour(); +} + +void tt_timezone_set_format_24_hour(bool show24Hour) { + return time::setTimeFormat24Hour(show24Hour); +} + +} diff --git a/TactilityC/Source/tt_timer.cpp b/TactilityC/Source/tt_timer.cpp index 62ad2bbb..42143511 100644 --- a/TactilityC/Source/tt_timer.cpp +++ b/TactilityC/Source/tt_timer.cpp @@ -7,7 +7,6 @@ struct TimerWrapper { extern "C" { - TimerHandle tt_timer_alloc(TimerType type, TimerCallback callback, void* callbackContext) { auto wrapper = std::make_shared(); wrapper->timer = std::make_unique((tt::Timer::Type)type, [callback, callbackContext](){ callback(callbackContext); }); @@ -54,4 +53,3 @@ void tt_timer_set_thread_priority(TimerHandle handle, ThreadPriority priority) { } } - diff --git a/TactilityC/Source/tt_wifi.cpp b/TactilityC/Source/tt_wifi.cpp new file mode 100644 index 00000000..b64441f7 --- /dev/null +++ b/TactilityC/Source/tt_wifi.cpp @@ -0,0 +1,55 @@ +#include "tt_wifi.h" + +#include +#include +#include + +using namespace tt::service; + +extern "C" { + +WifiRadioState tt_wifi_get_radio_state() { + return static_cast(wifi::getRadioState()); +} +const char* tt_wifi_radio_state_to_string(WifiRadioState state) { + return wifi::radioStateToString(static_cast(state)); +} + +void tt_wifi_scan() { + wifi::scan(); +} + +bool tt_wifi_is_scanning() { + return wifi::isScanning(); +} + +void tt_wifi_get_connection_target(char* buffer) { + auto target = wifi::getConnectionTarget(); + strcpy(buffer, target.c_str()); +} + +void tt_wifi_set_enabled(bool enabled) { + wifi::setEnabled(enabled); +} + +void tt_wifi_connect(const char* ssid, const char* password, int32_t channel, bool autoConnect, bool remember) { + wifi::settings::WifiApSettings settings; + strcpy(settings.ssid, ssid); + strcpy(settings.password, password); + settings.channel = channel; + settings.auto_connect = autoConnect; +} + +void tt_wifi_disconnect() { + wifi::disconnect(); +} + +bool tt_wifi_is_connnection_secure() { + return wifi::isConnectionSecure(); +} + +int tt_wifi_get_rssi() { + return wifi::getRssi(); +} + +}