TactilityC additions (#287)

New TactilityC implementations for:
- WiFi
- GPS
- Preferences
- Timezone

Also includes:
- Some fixes to enums/naming
- Cleanup elsewhere
This commit is contained in:
Ken Van Hoeylandt 2025-06-09 13:46:08 +02:00 committed by GitHub
parent 869a56125f
commit 1593eb80ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 528 additions and 64 deletions

View File

@ -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")

View File

@ -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:

View File

@ -24,8 +24,6 @@ extern const AppManifest manifest;
class GpsSettingsApp final : public App {
private:
std::unique_ptr<Timer> timer;
std::shared_ptr<GpsSettingsApp*> appReference = std::make_shared<GpsSettingsApp*>(this);
lv_obj_t* statusWrapper = nullptr;
@ -96,7 +94,7 @@ private:
memcpy(&index, &index_as_voidptr, sizeof(int));
std::vector<tt::hal::gps::GpsConfiguration> 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()) {

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -0,0 +1,83 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
/**
* 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

View File

@ -0,0 +1,42 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#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

View File

@ -0,0 +1,74 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#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

View File

@ -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>((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<tt::Bundle>(static_cast<tt::Bundle*>(bundle));
HANDLE_AS_APP_CONTEXT(handle)->getApp()->setResult(static_cast<tt::app::Result>(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>((tt::Bundle*)parameters));
tt::app::start(appId, std::shared_ptr<tt::Bundle>(static_cast<tt::Bundle*>(parameters)));
}
void tt_app_stop() {

View File

@ -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) {

View File

@ -0,0 +1,45 @@
#include "tt_gps.h"
#include <Tactility/service/gps/GpsService.h>
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;
}
}

View File

@ -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 <private/elf_symbol.h>
@ -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

View File

@ -0,0 +1,53 @@
#include "tt_preferences.h"
#include <Tactility/Preferences.h>
#include <cstring>
#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);
}
}

View File

@ -0,0 +1,42 @@
#include "tt_time.h"
#include <Tactility/time/Time.h>
#include <cstring>
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);
}
}

View File

@ -7,7 +7,6 @@ struct TimerWrapper {
extern "C" {
TimerHandle tt_timer_alloc(TimerType type, TimerCallback callback, void* callbackContext) {
auto wrapper = std::make_shared<TimerWrapper>();
wrapper->timer = std::make_unique<tt::Timer>((tt::Timer::Type)type, [callback, callbackContext](){ callback(callbackContext); });
@ -54,4 +53,3 @@ void tt_timer_set_thread_priority(TimerHandle handle, ThreadPriority priority) {
}
}

View File

@ -0,0 +1,55 @@
#include "tt_wifi.h"
#include <cstring>
#include <Tactility/service/wifi/Wifi.h>
#include <Tactility/service/wifi/WifiSettings.h>
using namespace tt::service;
extern "C" {
WifiRadioState tt_wifi_get_radio_state() {
return static_cast<WifiRadioState>(wifi::getRadioState());
}
const char* tt_wifi_radio_state_to_string(WifiRadioState state) {
return wifi::radioStateToString(static_cast<wifi::RadioState>(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();
}
}