Tactility.py 3.0.0 and SDK updates for 0.7.0-dev (#19)

- Remove `Libraries/Str`
- Replaced usage of `TactilityC` FreeRtos features with `TactilityFreeRtos` library
- Update `tactility.py`
- Removed redundant code from `TactilityCpp`
This commit is contained in:
Ken Van Hoeylandt
2026-01-04 02:20:06 +01:00
committed by GitHub
parent 3bc1e7a373
commit b6c27b64d4
41 changed files with 521 additions and 1329 deletions
-4
View File
@@ -1,15 +1,11 @@
file(GLOB_RECURSE SOURCE_FILES
Source/*.c*
# Library source files must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
../../../Libraries/Str/Source/*.c**
)
idf_component_register(
SRCS ${SOURCE_FILES}
# Library headers must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
INCLUDE_DIRS ../../../Libraries/Str/Include
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
REQUIRES TactilitySDK
)
+11 -10
View File
@@ -4,6 +4,7 @@
#include <ctype.h>
#include <tt_lvgl_toolbar.h>
#include <stack>
#include <cstring>
constexpr auto* TAG = "Calculator";
@@ -45,10 +46,10 @@ void Calculator::handleInput(const char* txt) {
}
}
std::deque<Str> Calculator::infixToRPN(const Str& infix) {
std::deque<std::string> Calculator::infixToRPN(const std::string& infix) {
std::stack<char> opStack;
std::deque<Str> output;
Str token;
std::deque<std::string> output;
std::string token;
size_t i = 0;
while (i < infix.length()) {
@@ -56,20 +57,20 @@ std::deque<Str> Calculator::infixToRPN(const Str& infix) {
if (isdigit(ch)) {
token.clear();
while (i < infix.length() && (isdigit(infix[i]) || infix[i] == '.')) { token.append(infix[i++]); }
while (i < infix.length() && (isdigit(infix[i]) || infix[i] == '.')) { token += infix[i++]; }
output.push_back(token);
continue;
}
if (ch == '(') { opStack.push(ch); } else if (ch == ')') {
while (!opStack.empty() && opStack.top() != '(') {
output.push_back(Str(1, opStack.top()));
output.push_back(std::string(1, opStack.top()));
opStack.pop();
}
opStack.pop();
} else if (strchr("+-*/", ch)) {
while (!opStack.empty() && precedence(opStack.top()) >= precedence(ch)) {
output.push_back(Str(1, opStack.top()));
output.push_back(std::string(1, opStack.top()));
opStack.pop();
}
opStack.push(ch);
@@ -79,18 +80,18 @@ std::deque<Str> Calculator::infixToRPN(const Str& infix) {
}
while (!opStack.empty()) {
output.push_back(Str(1, opStack.top()));
output.push_back(std::string(1, opStack.top()));
opStack.pop();
}
return output;
}
double Calculator::evaluateRPN(std::deque<Str> rpnQueue) {
double Calculator::evaluateRPN(std::deque<std::string> rpnQueue) {
std::stack<double> values;
while (!rpnQueue.empty()) {
Str token = rpnQueue.front();
std::string token = rpnQueue.front();
rpnQueue.pop_front();
if (isdigit(token[0])) {
@@ -132,7 +133,7 @@ void Calculator::evaluateExpression() {
}
double Calculator::computeFormula() {
return evaluateRPN(infixToRPN(Str(formulaBuffer)));
return evaluateRPN(infixToRPN(std::string(formulaBuffer)));
}
void Calculator::resetCalculator() {
+3 -3
View File
@@ -4,7 +4,7 @@
#include <lvgl.h>
#include <deque>
#include <Str.h>
#include <string>
#include <TactilityCpp/App.h>
class Calculator final : public App {
@@ -18,8 +18,8 @@ class Calculator final : public App {
void handleInput(const char* txt);
void evaluateExpression();
double computeFormula();
static std::deque<Str> infixToRPN(const Str& infix);
static double evaluateRPN(std::deque<Str> rpnQueue);
static std::deque<std::string> infixToRPN(const std::string& infix);
static double evaluateRPN(std::deque<std::string> rpnQueue);
void resetCalculator();
public:
+4 -4
View File
@@ -1,10 +1,10 @@
[manifest]
version=0.1
[target]
sdk=0.6.0
platforms=esp32,esp32s3
sdk=0.7.0-dev
platforms=esp32,esp32s3,esp32c6,esp32p4
[app]
id=one.tactility.calculator
versionName=0.2.0
versionCode=2
versionName=0.3.0
versionCode=3
name=Calculator
+54 -51
View File
@@ -12,7 +12,7 @@ import requests
import tarfile
ttbuild_path = ".tactility"
ttbuild_version = "2.5.0"
ttbuild_version = "3.1.0"
ttbuild_cdn = "https://cdn.tactility.one"
ttbuild_sdk_json_validity = 3600 # seconds
ttport = 6666
@@ -20,20 +20,12 @@ verbose = False
use_local_sdk = False
local_base_path = None
if sys.platform == "win32":
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
else:
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
def print_help():
print("Usage: python tactility.py [action] [options]")
@@ -115,9 +107,9 @@ def read_properties_file(path):
#region SDK helpers
def read_sdk_json():
json_file_path = os.path.join(ttbuild_path, "sdk.json")
json_file = open(json_file_path)
return json.load(json_file)
json_file_path = os.path.join(ttbuild_path, "tool.json")
with open(json_file_path) as json_file:
return json.load(json_file)
def get_sdk_dir(version, platform):
global use_local_sdk, local_base_path
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
global ttbuild_cdn
return os.path.join(ttbuild_path, f"{version}-{platform}")
def get_sdk_url(version, platform):
def get_sdk_url(version, file):
global ttbuild_cdn
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
return f"{ttbuild_cdn}/sdk/{version}/{file}"
def sdk_exists(version, platform):
sdk_dir = get_sdk_dir(version, platform)
return os.path.isdir(sdk_dir)
def should_update_sdk_json():
def should_update_tool_json():
global ttbuild_cdn
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_filepath = os.path.join(ttbuild_path, "tool.json")
if os.path.exists(json_filepath):
json_modification_time = os.path.getmtime(json_filepath)
now = time.time()
@@ -168,10 +160,10 @@ def should_update_sdk_json():
else:
return True
def update_sdk_json():
def update_tool_json():
global ttbuild_cdn, ttbuild_path
json_url = f"{ttbuild_cdn}/sdk.json"
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_url = f"{ttbuild_cdn}/sdk/tool.json"
json_filepath = os.path.join(ttbuild_path, "tool.json")
return download_file(json_url, json_filepath)
def should_fetch_sdkconfig_files(platform_targets):
@@ -206,16 +198,6 @@ def validate_environment():
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 validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
version_map = sdk_json["versions"]
if not sdk_version in version_map:
exit_with_error(f"Version not found: {sdk_version}")
version_data = version_map[sdk_version]
available_platforms = version_data["platforms"]
for desired_platform in platforms_to_build:
if not desired_platform in available_platforms:
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
def validate_self(sdk_json):
if not "toolVersion" in sdk_json:
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
def sdk_download(version, platform):
sdk_root_dir = get_sdk_root_dir(version, platform)
os.makedirs(sdk_root_dir, exist_ok=True)
sdk_url = get_sdk_url(version, platform)
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
sdk_index_url = get_sdk_url(version, "index.json")
print(f"Downloading SDK version {version} for {platform}")
if download_file(sdk_url, filepath):
with zipfile.ZipFile(filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
else:
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
if verbose:
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
if not download_file(sdk_index_url, sdk_index_filepath):
# TODO: 404 check, print a more accurate error
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
return False
with open(sdk_index_filepath) as sdk_index_json_file:
sdk_index_json = json.load(sdk_index_json_file)
sdk_platforms = sdk_index_json["platforms"]
if platform not in sdk_platforms:
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
return False
sdk_platform_file = sdk_platforms[platform]
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
if verbose:
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
return False
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
def sdk_download_all(version, platforms):
for platform in platforms:
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "build"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
if process.returncode == 0:
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "elf"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
if process.returncode == 0:
print_status_success(f"Building {platform} ELF")
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
if not use_local_sdk:
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
sdk_version = manifest["target"]["sdk"]
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")
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
@@ -613,7 +615,7 @@ if __name__ == "__main__":
# Argument validation
if len(sys.argv) == 1:
print_help()
sys.exit()
sys.exit(1)
if "--verbose" in sys.argv:
verbose = True
sys.argv.remove("--verbose")
@@ -633,8 +635,8 @@ if __name__ == "__main__":
manifest = read_manifest()
validate_manifest(manifest)
all_platform_targets = manifest["target"]["platforms"].split(",")
# Update SDK cache (sdk.json)
if should_update_sdk_json() and not update_sdk_json():
# Update SDK cache (tool.json)
if should_update_tool_json() and not update_tool_json():
exit_with_error("Failed to retrieve SDK info")
# Actions
if action_arg == "build":
@@ -644,7 +646,8 @@ if __name__ == "__main__":
platform = None
if len(sys.argv) > 2:
platform = sys.argv[2]
build_action(manifest, platform)
if not build_action(manifest, platform):
sys.exit(1)
elif action_arg == "clean":
clean_action()
elif action_arg == "clearcache":
-1
View File
@@ -14,4 +14,3 @@ set(EXTRA_COMPONENT_DIRS ${TACTILITY_SDK_PATH})
project(Diceware)
tactility_project(Diceware)
-4
View File
@@ -1,15 +1,11 @@
file(GLOB_RECURSE SOURCE_FILES
Source/*.c*
# Library source files must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
../../../Libraries/Str/Source/*.c**
)
idf_component_register(
SRCS ${SOURCE_FILES}
# Library headers must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
INCLUDE_DIRS ../../../Libraries/Str/Include
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
REQUIRES TactilitySDK
)
+22 -19
View File
@@ -8,6 +8,8 @@
#include <esp_random.h>
#include <esp_log.h>
#include <Tactility/kernel/Kernel.h>
constexpr char* TAG = "Diceware";
static void skipNewlines(FILE* file, const int count) {
@@ -20,15 +22,15 @@ static void skipNewlines(FILE* file, const int count) {
}
}
static Str readWord(FILE* file) {
static std::string readWord(FILE* file) {
char c;
Str result;
std::string result;
// Read word until newline
while (fread(&c, 1, 1, file) && c != '\n') { result.append(c); }
while (fread(&c, 1, 1, file) && c != '\n') { result += c; }
return result;
}
static Str readWordAtLine(const AppHandle handle, const int lineIndex) {
static std::string readWordAtLine(const AppHandle handle, const int lineIndex) {
char path[256];
size_t size = 256;
tt_app_get_assets_child_path(handle, "eff_large_wordlist.txt", path, &size);
@@ -38,8 +40,8 @@ static Str readWordAtLine(const AppHandle handle, const int lineIndex) {
}
auto lock = tt_lock_alloc_for_path(path);
Str word;
if (tt_lock_acquire(lock, TT_MAX_TICKS)) {
std::string word;
if (tt_lock_acquire(lock, tt::kernel::MAX_TICKS)) {
FILE* file = fopen(path, "r");
if (file != nullptr) {
skipNewlines(file, lineIndex);
@@ -52,25 +54,24 @@ static Str readWordAtLine(const AppHandle handle, const int lineIndex) {
return word;
}
int32_t Diceware::jobMain(void* data) {
Diceware* application = static_cast<Diceware*>(data);
Str result;
for (int i = 0; i < application->wordCount; i++) {
int32_t Diceware::jobMain() {
std::string result;
for (int i = 0; i < wordCount; i++) {
constexpr int line_count = 7776;
const auto line_index = esp_random() % line_count;
auto word = readWordAtLine(application->handle, line_index);
result.appendf("%s ", word.c_str());
auto word = readWordAtLine(handle, line_index);
result += word;
result += " ";
}
application->onFinishJob(result);
onFinishJob(result);
return 0;
}
void Diceware::cleanupJob() {
if (jobThread != nullptr) {
tt_thread_join(jobThread, TT_MAX_TICKS);
tt_thread_free(jobThread);
jobThread->join();
jobThread = nullptr;
}
}
@@ -79,12 +80,14 @@ void Diceware::startJob(uint32_t jobWordCount) {
cleanupJob();
wordCount = jobWordCount;
jobThread = tt_thread_alloc_ext("Diceware", 4096, jobMain, this);
tt_thread_start(jobThread);
jobThread = std::make_unique<tt::Thread>("Diceware", 4096, [this] {
return jobMain();
});
jobThread->start();
}
void Diceware::onFinishJob(Str result) {
tt_lvgl_lock(TT_MAX_TICKS);
void Diceware::onFinishJob(std::string result) {
tt_lvgl_lock(tt::kernel::MAX_TICKS);
lv_label_set_text(resultLabel, result.c_str());
tt_lvgl_unlock();
}
+8 -5
View File
@@ -1,18 +1,21 @@
#pragma once
#include "tt_app.h"
#include "tt_thread.h"
#include <Str.h>
#include <Tactility/Thread.h>
#include <string>
#include <lvgl.h>
#include <TactilityCpp/App.h>
#include <memory>
class Diceware final : public App {
AppHandle handle = nullptr;
lv_obj_t* spinbox = nullptr;
lv_obj_t* resultLabel = nullptr;
ThreadHandle jobThread = nullptr;
std::unique_ptr<tt::Thread> jobThread = nullptr;
uint32_t wordCount = 5;
static void onClickGenerate(lv_event_t* e);
@@ -20,10 +23,10 @@ class Diceware final : public App {
static void onSpinboxIncrement(lv_event_t* e);
static void onHelpClicked(lv_event_t* e);
static int32_t jobMain(void* data);
int32_t jobMain();
void startJob(uint32_t jobWordCount);
void onFinishJob(Str result);
void onFinishJob(std::string result);
void cleanupJob();
public:
+4 -4
View File
@@ -1,10 +1,10 @@
[manifest]
version=0.1
[target]
sdk=0.6.0
platforms=esp32,esp32s3
sdk=0.7.0-dev
platforms=esp32,esp32s3,esp32c6,esp32p4
[app]
id=one.tactility.diceware
versionName=0.2.0
versionCode=2
versionName=0.3.0
versionCode=3
name=Diceware
+54 -51
View File
@@ -12,7 +12,7 @@ import requests
import tarfile
ttbuild_path = ".tactility"
ttbuild_version = "2.5.0"
ttbuild_version = "3.1.0"
ttbuild_cdn = "https://cdn.tactility.one"
ttbuild_sdk_json_validity = 3600 # seconds
ttport = 6666
@@ -20,20 +20,12 @@ verbose = False
use_local_sdk = False
local_base_path = None
if sys.platform == "win32":
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
else:
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
def print_help():
print("Usage: python tactility.py [action] [options]")
@@ -115,9 +107,9 @@ def read_properties_file(path):
#region SDK helpers
def read_sdk_json():
json_file_path = os.path.join(ttbuild_path, "sdk.json")
json_file = open(json_file_path)
return json.load(json_file)
json_file_path = os.path.join(ttbuild_path, "tool.json")
with open(json_file_path) as json_file:
return json.load(json_file)
def get_sdk_dir(version, platform):
global use_local_sdk, local_base_path
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
global ttbuild_cdn
return os.path.join(ttbuild_path, f"{version}-{platform}")
def get_sdk_url(version, platform):
def get_sdk_url(version, file):
global ttbuild_cdn
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
return f"{ttbuild_cdn}/sdk/{version}/{file}"
def sdk_exists(version, platform):
sdk_dir = get_sdk_dir(version, platform)
return os.path.isdir(sdk_dir)
def should_update_sdk_json():
def should_update_tool_json():
global ttbuild_cdn
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_filepath = os.path.join(ttbuild_path, "tool.json")
if os.path.exists(json_filepath):
json_modification_time = os.path.getmtime(json_filepath)
now = time.time()
@@ -168,10 +160,10 @@ def should_update_sdk_json():
else:
return True
def update_sdk_json():
def update_tool_json():
global ttbuild_cdn, ttbuild_path
json_url = f"{ttbuild_cdn}/sdk.json"
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_url = f"{ttbuild_cdn}/sdk/tool.json"
json_filepath = os.path.join(ttbuild_path, "tool.json")
return download_file(json_url, json_filepath)
def should_fetch_sdkconfig_files(platform_targets):
@@ -206,16 +198,6 @@ def validate_environment():
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 validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
version_map = sdk_json["versions"]
if not sdk_version in version_map:
exit_with_error(f"Version not found: {sdk_version}")
version_data = version_map[sdk_version]
available_platforms = version_data["platforms"]
for desired_platform in platforms_to_build:
if not desired_platform in available_platforms:
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
def validate_self(sdk_json):
if not "toolVersion" in sdk_json:
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
def sdk_download(version, platform):
sdk_root_dir = get_sdk_root_dir(version, platform)
os.makedirs(sdk_root_dir, exist_ok=True)
sdk_url = get_sdk_url(version, platform)
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
sdk_index_url = get_sdk_url(version, "index.json")
print(f"Downloading SDK version {version} for {platform}")
if download_file(sdk_url, filepath):
with zipfile.ZipFile(filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
else:
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
if verbose:
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
if not download_file(sdk_index_url, sdk_index_filepath):
# TODO: 404 check, print a more accurate error
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
return False
with open(sdk_index_filepath) as sdk_index_json_file:
sdk_index_json = json.load(sdk_index_json_file)
sdk_platforms = sdk_index_json["platforms"]
if platform not in sdk_platforms:
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
return False
sdk_platform_file = sdk_platforms[platform]
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
if verbose:
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
return False
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
def sdk_download_all(version, platforms):
for platform in platforms:
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "build"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
if process.returncode == 0:
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "elf"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
if process.returncode == 0:
print_status_success(f"Building {platform} ELF")
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
if not use_local_sdk:
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
sdk_version = manifest["target"]["sdk"]
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")
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
@@ -613,7 +615,7 @@ if __name__ == "__main__":
# Argument validation
if len(sys.argv) == 1:
print_help()
sys.exit()
sys.exit(1)
if "--verbose" in sys.argv:
verbose = True
sys.argv.remove("--verbose")
@@ -633,8 +635,8 @@ if __name__ == "__main__":
manifest = read_manifest()
validate_manifest(manifest)
all_platform_targets = manifest["target"]["platforms"].split(",")
# Update SDK cache (sdk.json)
if should_update_sdk_json() and not update_sdk_json():
# Update SDK cache (tool.json)
if should_update_tool_json() and not update_tool_json():
exit_with_error("Failed to retrieve SDK info")
# Actions
if action_arg == "build":
@@ -644,7 +646,8 @@ if __name__ == "__main__":
platform = None
if len(sys.argv) > 2:
platform = sys.argv[2]
build_action(manifest, platform)
if not build_action(manifest, platform):
sys.exit(1)
elif action_arg == "clean":
clean_action()
elif action_arg == "clearcache":
-5
View File
@@ -1,16 +1,11 @@
file(GLOB_RECURSE SOURCE_FILES
Source/*.c*
# Library source files must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
../../../Libraries/Str/Source/*.c**
../../../Libraries/TactilityCpp/Source/*.c**
)
idf_component_register(
SRCS ${SOURCE_FILES}
# Library headers must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
INCLUDE_DIRS ../../../Libraries/Str/Include
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
REQUIRES TactilitySDK
)
+10 -16
View File
@@ -1,6 +1,7 @@
#include "Gpio.h"
#include <tt_app_alertdialog.h>
#include <Tactility/kernel/Kernel.h>
#include <tt_hal.h>
#include <tt_hal_gpio.h>
#include <tt_lvgl.h>
@@ -18,7 +19,7 @@ void Gpio::updatePinStates() {
}
void Gpio::updatePinWidgets() {
tt_lvgl_lock(TT_MAX_TICKS);
tt_lvgl_lock(tt::kernel::MAX_TICKS);
for (int j = 0; j < pinStates.size(); ++j) {
int level = pinStates[j];
lv_obj_t* label = pinWidgets[j];
@@ -46,28 +47,21 @@ lv_obj_t* Gpio::createGpioRowWrapper(lv_obj_t* parent) {
// region Task
void Gpio::onTimer(void* context) {
Gpio* app = static_cast<Gpio*>(context);
app->mutex.lock();
app->updatePinStates();
app->updatePinWidgets();
app->mutex.unlock();
void Gpio::onTimer() {
mutex.lock();
updatePinStates();
updatePinWidgets();
mutex.unlock();
}
void Gpio::startTask() {
mutex.lock();
assert(timer == nullptr);
timer = tt_timer_alloc(TimerTypePeriodic, onTimer, this);
tt_timer_start(timer, 100 / portTICK_PERIOD_MS);
timer.start();
mutex.unlock();
}
void Gpio::stopTask() {
assert(timer);
tt_timer_stop(timer);
tt_timer_free(timer);
timer = nullptr;
timer.stop();
}
// endregion Task
+7 -5
View File
@@ -3,9 +3,9 @@
#include <TactilityCpp/App.h>
#include <tt_app.h>
#include <tt_timer.h>
#include <TactilityCpp/Mutex.h>
#include <Tactility/RecursiveMutex.h>
#include <Tactility/Timer.h>
#include <lvgl.h>
#include <vector>
@@ -14,11 +14,13 @@ class Gpio final : public App {
std::vector<lv_obj_t*> pinWidgets;
std::vector<bool> pinStates;
TimerHandle timer;
Mutex mutex = Mutex(MutexTypeRecursive);
tt::Timer timer = tt::Timer(tt::Timer::Type::Periodic, pdMS_TO_TICKS(100), [this]{
onTimer();
});
tt::RecursiveMutex mutex;
static lv_obj_t* createGpioRowWrapper(lv_obj_t* parent);
static void onTimer(void* parameter);
void onTimer();
public:
+4 -4
View File
@@ -1,10 +1,10 @@
[manifest]
version=0.1
[target]
sdk=0.6.0
platforms=esp32,esp32s3
sdk=0.7.0-dev
platforms=esp32,esp32s3,esp32c6,esp32p4
[app]
id=one.tactility.gpio
versionName=0.2.0
versionCode=2
versionName=0.3.0
versionCode=3
name=GPIO
+54 -51
View File
@@ -12,7 +12,7 @@ import requests
import tarfile
ttbuild_path = ".tactility"
ttbuild_version = "2.5.0"
ttbuild_version = "3.1.0"
ttbuild_cdn = "https://cdn.tactility.one"
ttbuild_sdk_json_validity = 3600 # seconds
ttport = 6666
@@ -20,20 +20,12 @@ verbose = False
use_local_sdk = False
local_base_path = None
if sys.platform == "win32":
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
else:
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
def print_help():
print("Usage: python tactility.py [action] [options]")
@@ -115,9 +107,9 @@ def read_properties_file(path):
#region SDK helpers
def read_sdk_json():
json_file_path = os.path.join(ttbuild_path, "sdk.json")
json_file = open(json_file_path)
return json.load(json_file)
json_file_path = os.path.join(ttbuild_path, "tool.json")
with open(json_file_path) as json_file:
return json.load(json_file)
def get_sdk_dir(version, platform):
global use_local_sdk, local_base_path
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
global ttbuild_cdn
return os.path.join(ttbuild_path, f"{version}-{platform}")
def get_sdk_url(version, platform):
def get_sdk_url(version, file):
global ttbuild_cdn
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
return f"{ttbuild_cdn}/sdk/{version}/{file}"
def sdk_exists(version, platform):
sdk_dir = get_sdk_dir(version, platform)
return os.path.isdir(sdk_dir)
def should_update_sdk_json():
def should_update_tool_json():
global ttbuild_cdn
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_filepath = os.path.join(ttbuild_path, "tool.json")
if os.path.exists(json_filepath):
json_modification_time = os.path.getmtime(json_filepath)
now = time.time()
@@ -168,10 +160,10 @@ def should_update_sdk_json():
else:
return True
def update_sdk_json():
def update_tool_json():
global ttbuild_cdn, ttbuild_path
json_url = f"{ttbuild_cdn}/sdk.json"
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_url = f"{ttbuild_cdn}/sdk/tool.json"
json_filepath = os.path.join(ttbuild_path, "tool.json")
return download_file(json_url, json_filepath)
def should_fetch_sdkconfig_files(platform_targets):
@@ -206,16 +198,6 @@ def validate_environment():
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 validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
version_map = sdk_json["versions"]
if not sdk_version in version_map:
exit_with_error(f"Version not found: {sdk_version}")
version_data = version_map[sdk_version]
available_platforms = version_data["platforms"]
for desired_platform in platforms_to_build:
if not desired_platform in available_platforms:
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
def validate_self(sdk_json):
if not "toolVersion" in sdk_json:
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
def sdk_download(version, platform):
sdk_root_dir = get_sdk_root_dir(version, platform)
os.makedirs(sdk_root_dir, exist_ok=True)
sdk_url = get_sdk_url(version, platform)
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
sdk_index_url = get_sdk_url(version, "index.json")
print(f"Downloading SDK version {version} for {platform}")
if download_file(sdk_url, filepath):
with zipfile.ZipFile(filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
else:
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
if verbose:
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
if not download_file(sdk_index_url, sdk_index_filepath):
# TODO: 404 check, print a more accurate error
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
return False
with open(sdk_index_filepath) as sdk_index_json_file:
sdk_index_json = json.load(sdk_index_json_file)
sdk_platforms = sdk_index_json["platforms"]
if platform not in sdk_platforms:
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
return False
sdk_platform_file = sdk_platforms[platform]
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
if verbose:
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
return False
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
def sdk_download_all(version, platforms):
for platform in platforms:
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "build"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
if process.returncode == 0:
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "elf"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
if process.returncode == 0:
print_status_success(f"Building {platform} ELF")
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
if not use_local_sdk:
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
sdk_version = manifest["target"]["sdk"]
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")
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
@@ -613,7 +615,7 @@ if __name__ == "__main__":
# Argument validation
if len(sys.argv) == 1:
print_help()
sys.exit()
sys.exit(1)
if "--verbose" in sys.argv:
verbose = True
sys.argv.remove("--verbose")
@@ -633,8 +635,8 @@ if __name__ == "__main__":
manifest = read_manifest()
validate_manifest(manifest)
all_platform_targets = manifest["target"]["platforms"].split(",")
# Update SDK cache (sdk.json)
if should_update_sdk_json() and not update_sdk_json():
# Update SDK cache (tool.json)
if should_update_tool_json() and not update_tool_json():
exit_with_error("Failed to retrieve SDK info")
# Actions
if action_arg == "build":
@@ -644,7 +646,8 @@ if __name__ == "__main__":
platform = None
if len(sys.argv) > 2:
platform = sys.argv[2]
build_action(manifest, platform)
if not build_action(manifest, platform):
sys.exit(1)
elif action_arg == "clean":
clean_action()
elif action_arg == "clearcache":
+3 -1
View File
@@ -2,6 +2,8 @@ file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRC_DIRS "Source"
INCLUDE_DIRS "Include"
# Library headers must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
INCLUDE_DIRS "Include" "../../../Libraries/TactilityCpp/Include"
REQUIRES TactilitySDK
)
@@ -2,6 +2,7 @@
#include <cassert>
#include <tt_hal_display.h>
#include <Tactility/kernel/Kernel.h>
/**
* Wrapper for tt_hal_display_driver_*
@@ -22,7 +23,7 @@ public:
tt_hal_display_driver_free(handle);
}
bool lock(TickType timeout = TT_MAX_TICKS) const {
bool lock(TickType_t timeout = tt::kernel::MAX_TICKS) const {
return tt_hal_display_driver_lock(handle, timeout);
}
@@ -2,7 +2,7 @@
#include "PixelBuffer.h"
#include "esp_log.h"
#include <tt_kernel.h>
#include <Tactility/kernel/Kernel.h>
constexpr auto TAG = "Application";
@@ -66,7 +66,7 @@ void runApplication(DisplayDriver* display, TouchDriver* touch) {
// Give other tasks space to breathe
// SPI displays would otherwise time out SPI SD card access
tt_kernel_delay_ticks(1);
tt::kernel::delayTicks(1);
} while (!isTouched(touch));
}
+4 -4
View File
@@ -1,10 +1,10 @@
[manifest]
version=0.1
[target]
sdk=0.6.0
platforms=esp32,esp32s3
sdk=0.7.0-dev
platforms=esp32,esp32s3,esp32c6,esp32p4
[app]
id=one.tactility.graphicsdemo
versionName=0.2.0
versionCode=2
versionName=0.3.0
versionCode=3
name=Graphics Demo
+54 -51
View File
@@ -12,7 +12,7 @@ import requests
import tarfile
ttbuild_path = ".tactility"
ttbuild_version = "2.5.0"
ttbuild_version = "3.1.0"
ttbuild_cdn = "https://cdn.tactility.one"
ttbuild_sdk_json_validity = 3600 # seconds
ttport = 6666
@@ -20,20 +20,12 @@ verbose = False
use_local_sdk = False
local_base_path = None
if sys.platform == "win32":
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
else:
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
def print_help():
print("Usage: python tactility.py [action] [options]")
@@ -115,9 +107,9 @@ def read_properties_file(path):
#region SDK helpers
def read_sdk_json():
json_file_path = os.path.join(ttbuild_path, "sdk.json")
json_file = open(json_file_path)
return json.load(json_file)
json_file_path = os.path.join(ttbuild_path, "tool.json")
with open(json_file_path) as json_file:
return json.load(json_file)
def get_sdk_dir(version, platform):
global use_local_sdk, local_base_path
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
global ttbuild_cdn
return os.path.join(ttbuild_path, f"{version}-{platform}")
def get_sdk_url(version, platform):
def get_sdk_url(version, file):
global ttbuild_cdn
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
return f"{ttbuild_cdn}/sdk/{version}/{file}"
def sdk_exists(version, platform):
sdk_dir = get_sdk_dir(version, platform)
return os.path.isdir(sdk_dir)
def should_update_sdk_json():
def should_update_tool_json():
global ttbuild_cdn
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_filepath = os.path.join(ttbuild_path, "tool.json")
if os.path.exists(json_filepath):
json_modification_time = os.path.getmtime(json_filepath)
now = time.time()
@@ -168,10 +160,10 @@ def should_update_sdk_json():
else:
return True
def update_sdk_json():
def update_tool_json():
global ttbuild_cdn, ttbuild_path
json_url = f"{ttbuild_cdn}/sdk.json"
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_url = f"{ttbuild_cdn}/sdk/tool.json"
json_filepath = os.path.join(ttbuild_path, "tool.json")
return download_file(json_url, json_filepath)
def should_fetch_sdkconfig_files(platform_targets):
@@ -206,16 +198,6 @@ def validate_environment():
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 validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
version_map = sdk_json["versions"]
if not sdk_version in version_map:
exit_with_error(f"Version not found: {sdk_version}")
version_data = version_map[sdk_version]
available_platforms = version_data["platforms"]
for desired_platform in platforms_to_build:
if not desired_platform in available_platforms:
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
def validate_self(sdk_json):
if not "toolVersion" in sdk_json:
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
def sdk_download(version, platform):
sdk_root_dir = get_sdk_root_dir(version, platform)
os.makedirs(sdk_root_dir, exist_ok=True)
sdk_url = get_sdk_url(version, platform)
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
sdk_index_url = get_sdk_url(version, "index.json")
print(f"Downloading SDK version {version} for {platform}")
if download_file(sdk_url, filepath):
with zipfile.ZipFile(filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
else:
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
if verbose:
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
if not download_file(sdk_index_url, sdk_index_filepath):
# TODO: 404 check, print a more accurate error
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
return False
with open(sdk_index_filepath) as sdk_index_json_file:
sdk_index_json = json.load(sdk_index_json_file)
sdk_platforms = sdk_index_json["platforms"]
if platform not in sdk_platforms:
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
return False
sdk_platform_file = sdk_platforms[platform]
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
if verbose:
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
return False
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
def sdk_download_all(version, platforms):
for platform in platforms:
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "build"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
if process.returncode == 0:
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "elf"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
if process.returncode == 0:
print_status_success(f"Building {platform} ELF")
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
if not use_local_sdk:
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
sdk_version = manifest["target"]["sdk"]
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")
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
@@ -613,7 +615,7 @@ if __name__ == "__main__":
# Argument validation
if len(sys.argv) == 1:
print_help()
sys.exit()
sys.exit(1)
if "--verbose" in sys.argv:
verbose = True
sys.argv.remove("--verbose")
@@ -633,8 +635,8 @@ if __name__ == "__main__":
manifest = read_manifest()
validate_manifest(manifest)
all_platform_targets = manifest["target"]["platforms"].split(",")
# Update SDK cache (sdk.json)
if should_update_sdk_json() and not update_sdk_json():
# Update SDK cache (tool.json)
if should_update_tool_json() and not update_tool_json():
exit_with_error("Failed to retrieve SDK info")
# Actions
if action_arg == "build":
@@ -644,7 +646,8 @@ if __name__ == "__main__":
platform = None
if len(sys.argv) > 2:
platform = sys.argv[2]
build_action(manifest, platform)
if not build_action(manifest, platform):
sys.exit(1)
elif action_arg == "clean":
clean_action()
elif action_arg == "clearcache":
+4 -4
View File
@@ -1,10 +1,10 @@
[manifest]
version=0.1
[target]
sdk=0.6.0
platforms=esp32,esp32s3
sdk=0.7.0-dev
platforms=esp32,esp32s3,esp32c6,esp32p4
[app]
id=one.tactility.helloworld
versionName=0.2.0
versionCode=2
versionName=0.3.0
versionCode=3
name=Hello World
+54 -51
View File
@@ -12,7 +12,7 @@ import requests
import tarfile
ttbuild_path = ".tactility"
ttbuild_version = "2.5.0"
ttbuild_version = "3.1.0"
ttbuild_cdn = "https://cdn.tactility.one"
ttbuild_sdk_json_validity = 3600 # seconds
ttport = 6666
@@ -20,20 +20,12 @@ verbose = False
use_local_sdk = False
local_base_path = None
if sys.platform == "win32":
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
else:
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
def print_help():
print("Usage: python tactility.py [action] [options]")
@@ -115,9 +107,9 @@ def read_properties_file(path):
#region SDK helpers
def read_sdk_json():
json_file_path = os.path.join(ttbuild_path, "sdk.json")
json_file = open(json_file_path)
return json.load(json_file)
json_file_path = os.path.join(ttbuild_path, "tool.json")
with open(json_file_path) as json_file:
return json.load(json_file)
def get_sdk_dir(version, platform):
global use_local_sdk, local_base_path
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
global ttbuild_cdn
return os.path.join(ttbuild_path, f"{version}-{platform}")
def get_sdk_url(version, platform):
def get_sdk_url(version, file):
global ttbuild_cdn
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
return f"{ttbuild_cdn}/sdk/{version}/{file}"
def sdk_exists(version, platform):
sdk_dir = get_sdk_dir(version, platform)
return os.path.isdir(sdk_dir)
def should_update_sdk_json():
def should_update_tool_json():
global ttbuild_cdn
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_filepath = os.path.join(ttbuild_path, "tool.json")
if os.path.exists(json_filepath):
json_modification_time = os.path.getmtime(json_filepath)
now = time.time()
@@ -168,10 +160,10 @@ def should_update_sdk_json():
else:
return True
def update_sdk_json():
def update_tool_json():
global ttbuild_cdn, ttbuild_path
json_url = f"{ttbuild_cdn}/sdk.json"
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_url = f"{ttbuild_cdn}/sdk/tool.json"
json_filepath = os.path.join(ttbuild_path, "tool.json")
return download_file(json_url, json_filepath)
def should_fetch_sdkconfig_files(platform_targets):
@@ -206,16 +198,6 @@ def validate_environment():
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 validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
version_map = sdk_json["versions"]
if not sdk_version in version_map:
exit_with_error(f"Version not found: {sdk_version}")
version_data = version_map[sdk_version]
available_platforms = version_data["platforms"]
for desired_platform in platforms_to_build:
if not desired_platform in available_platforms:
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
def validate_self(sdk_json):
if not "toolVersion" in sdk_json:
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
def sdk_download(version, platform):
sdk_root_dir = get_sdk_root_dir(version, platform)
os.makedirs(sdk_root_dir, exist_ok=True)
sdk_url = get_sdk_url(version, platform)
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
sdk_index_url = get_sdk_url(version, "index.json")
print(f"Downloading SDK version {version} for {platform}")
if download_file(sdk_url, filepath):
with zipfile.ZipFile(filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
else:
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
if verbose:
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
if not download_file(sdk_index_url, sdk_index_filepath):
# TODO: 404 check, print a more accurate error
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
return False
with open(sdk_index_filepath) as sdk_index_json_file:
sdk_index_json = json.load(sdk_index_json_file)
sdk_platforms = sdk_index_json["platforms"]
if platform not in sdk_platforms:
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
return False
sdk_platform_file = sdk_platforms[platform]
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
if verbose:
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
return False
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
def sdk_download_all(version, platforms):
for platform in platforms:
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "build"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
if process.returncode == 0:
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "elf"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
if process.returncode == 0:
print_status_success(f"Building {platform} ELF")
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
if not use_local_sdk:
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
sdk_version = manifest["target"]["sdk"]
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")
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
@@ -613,7 +615,7 @@ if __name__ == "__main__":
# Argument validation
if len(sys.argv) == 1:
print_help()
sys.exit()
sys.exit(1)
if "--verbose" in sys.argv:
verbose = True
sys.argv.remove("--verbose")
@@ -633,8 +635,8 @@ if __name__ == "__main__":
manifest = read_manifest()
validate_manifest(manifest)
all_platform_targets = manifest["target"]["platforms"].split(",")
# Update SDK cache (sdk.json)
if should_update_sdk_json() and not update_sdk_json():
# Update SDK cache (tool.json)
if should_update_tool_json() and not update_tool_json():
exit_with_error("Failed to retrieve SDK info")
# Actions
if action_arg == "build":
@@ -644,7 +646,8 @@ if __name__ == "__main__":
platform = None
if len(sys.argv) > 2:
platform = sys.argv[2]
build_action(manifest, platform)
if not build_action(manifest, platform):
sys.exit(1)
elif action_arg == "clean":
clean_action()
elif action_arg == "clearcache":
-5
View File
@@ -1,16 +1,11 @@
file(GLOB_RECURSE SOURCE_FILES
Source/*.c*
# Library source files must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
../../../Libraries/Str/Source/*.c**
../../../Libraries/TactilityCpp/Source/*.c**
)
idf_component_register(
SRCS ${SOURCE_FILES}
# Library headers must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
INCLUDE_DIRS ../../../Libraries/Str/Include
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
REQUIRES TactilitySDK
)
+3 -4
View File
@@ -5,7 +5,6 @@
#include <string>
#include <vector>
#include <lvgl.h>
#include <Str.h>
#include <functional>
#include <memory>
@@ -21,7 +20,7 @@ class ConnectView final : public View {
public:
typedef std::function<void(std::unique_ptr<Uart>)> OnConnectedFunction;
std::vector<Str> uartNames;
std::vector<std::string> uartNames;
Preferences preferences = Preferences("SerialConsole");
LvglLock lvglLock;
@@ -31,8 +30,8 @@ private:
lv_obj_t* busDropdown = nullptr;
lv_obj_t* speedTextarea = nullptr;
Str join(const std::vector<Str>& list) {
Str output;
std::string join(const std::vector<std::string>& list) {
std::string output;
for (int i = list.size() - 1; i >= 0; i--) {
output.append(list[i].c_str());
if (i < list.size() - 1) {
+28 -44
View File
@@ -3,16 +3,15 @@
#include "View.h"
#include "esp_log.h"
#include <Str.h>
#include <string>
#include <sstream>
#include <lvgl.h>
#include <memory>
#include <tt_lvgl.h>
#include <tt_thread.h>
#include <TactilityCpp/Mutex.h>
#include <TactilityCpp/Thread.h>
#include <Tactility/RecursiveMutex.h>
#include <Tactility/Thread.h>
#include <TactilityCpp/LvglLock.h>
constexpr size_t receiveBufferSize = 512;
@@ -26,15 +25,15 @@ class ConsoleView final : public View {
lv_obj_t* _Nullable logTextarea = nullptr;
lv_obj_t* _Nullable inputTextarea = nullptr;
std::shared_ptr<Uart> _Nullable uart = nullptr;
std::shared_ptr<Thread> uartThread _Nullable = nullptr;
std::unique_ptr<tt::Thread> uartThread _Nullable = nullptr;
bool uartThreadInterrupted = false;
std::shared_ptr<Thread> viewThread _Nullable = nullptr;
std::unique_ptr<tt::Thread> viewThread _Nullable = nullptr;
bool viewThreadInterrupted = false;
Mutex mutex = Mutex(MutexTypeRecursive);
tt::RecursiveMutex mutex;
uint8_t receiveBuffer[receiveBufferSize];
uint8_t renderBuffer[renderBufferSize];
size_t receiveBufferPosition = 0;
Str terminatorString = "\n";
std::string terminatorString = "\n";
LvglLock lvglLock;
@@ -51,11 +50,6 @@ class ConsoleView final : public View {
}
void updateViews() {
auto scoped_lvgl_lock = lvglLock.asScopedLock();
if (!scoped_lvgl_lock.lock()) {
return;
}
if (parent == nullptr) {
return;
}
@@ -73,38 +67,35 @@ class ConsoleView final : public View {
mutex.unlock();
}
tt_lvgl_lock(TT_MAX_TICKS);
lv_textarea_set_text(logTextarea, (const char*)renderBuffer);
tt_lvgl_unlock();
if (lvglLock.lock()) {
lv_textarea_set_text(logTextarea, (const char*)renderBuffer);
lvglLock.unlock();
}
}
int32_t viewThreadMain() {
while (!isViewThreadInterrupted()) {
auto start_time = tt_kernel_get_ticks();
auto start_time = tt::kernel::getTicks();
updateViews();
auto end_time = tt_kernel_get_ticks();
auto end_time = tt::kernel::getTicks();
auto time_diff = end_time - start_time;
if (time_diff < 500U) {
tt_kernel_delay_ticks((500U - time_diff) / portTICK_PERIOD_MS);
auto target_delay = tt::kernel::millisToTicks(500U);
if (time_diff < target_delay) {
tt::kernel::delayTicks(target_delay - time_diff);
}
}
return 0;
}
static int32_t viewThreadMainStatic(void* context) {
auto* self = static_cast<ConsoleView*>(context);
return self->viewThreadMain();
}
int32_t uartThreadMain() {
char byte;
while (!isUartThreadInterrupted()) {
assert(uart != nullptr);
bool success = uart->readByte(&byte, 50 / portTICK_PERIOD_MS);
bool success = uart->readByte(&byte, tt::kernel::millisToTicks(50));
// Thread might've been interrupted in the meanwhile
if (isUartThreadInterrupted()) {
@@ -125,11 +116,6 @@ class ConsoleView final : public View {
return 0;
}
static int32_t uartThreadMainStatic(void* view) {
auto* self = static_cast<ConsoleView*>(view);
return self->uartThreadMain();
}
static void onSendClickedCallback(lv_event_t* event) {
auto* view = (ConsoleView*)lv_event_get_user_data(event);
view->onSendClicked();
@@ -156,9 +142,9 @@ class ConsoleView final : public View {
void onSendClicked() {
mutex.lock();
Str input_text = lv_textarea_get_text(inputTextarea);
Str to_send;
to_send.appendf("%s%s", input_text.c_str(), terminatorString.c_str());
std::string input_text = lv_textarea_get_text(inputTextarea);
std::string to_send;
to_send.append(input_text + terminatorString);
mutex.unlock();
if (uart != nullptr) {
@@ -181,13 +167,12 @@ public:
uart = std::move(newUart);
uartThreadInterrupted = false;
uartThread = std::make_unique<Thread>(
uartThread = std::make_unique<tt::Thread>(
"SerConsUart",
4096,
uartThreadMainStatic,
this
[this] { return uartThreadMain(); }
);
uartThread->setPriority(ThreadPriorityHigh);
uartThread->setPriority(tt::Thread::Priority::High);
uartThread->start();
}
@@ -228,13 +213,12 @@ public:
lv_obj_add_event_cb(button, onSendClickedCallback, LV_EVENT_SHORT_CLICKED, this);
viewThreadInterrupted = false;
viewThread = std::make_unique<Thread>(
viewThread = std::make_unique<tt::Thread>(
"SerConsView",
4096,
viewThreadMainStatic,
this
[this] { return viewThreadMain(); }
);
viewThread->setPriority(ThreadPriorityHigher);
viewThread->setPriority(tt::Thread::Priority::Higher);
viewThread->start();
}
@@ -249,7 +233,7 @@ public:
// Unlock so thread can lock
lock.unlock();
if (old_uart_thread->getState() != ThreadStateStopped) {
if (old_uart_thread->getState() != tt::Thread::State::Stopped) {
// Wait for thread to finish
old_uart_thread->join();
}
@@ -267,7 +251,7 @@ public:
// Unlock so thread can lock
lock.unlock();
if (old_view_thread->getState() != ThreadStateStopped) {
if (old_view_thread->getState() != tt::Thread::State::Stopped) {
// Wait for thread to finish
old_view_thread->join();
}
+4 -4
View File
@@ -1,10 +1,10 @@
[manifest]
version=0.1
[target]
sdk=0.6.0
platforms=esp32,esp32s3
sdk=0.7.0-dev
platforms=esp32,esp32s3,esp32c6,esp32p4
[app]
id=one.tactility.serialconsole
versionName=0.2.0
versionCode=2
versionName=0.3.0
versionCode=3
name=Serial Console
+54 -51
View File
@@ -12,7 +12,7 @@ import requests
import tarfile
ttbuild_path = ".tactility"
ttbuild_version = "2.5.0"
ttbuild_version = "3.1.0"
ttbuild_cdn = "https://cdn.tactility.one"
ttbuild_sdk_json_validity = 3600 # seconds
ttport = 6666
@@ -20,20 +20,12 @@ verbose = False
use_local_sdk = False
local_base_path = None
if sys.platform == "win32":
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
else:
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
def print_help():
print("Usage: python tactility.py [action] [options]")
@@ -115,9 +107,9 @@ def read_properties_file(path):
#region SDK helpers
def read_sdk_json():
json_file_path = os.path.join(ttbuild_path, "sdk.json")
json_file = open(json_file_path)
return json.load(json_file)
json_file_path = os.path.join(ttbuild_path, "tool.json")
with open(json_file_path) as json_file:
return json.load(json_file)
def get_sdk_dir(version, platform):
global use_local_sdk, local_base_path
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
global ttbuild_cdn
return os.path.join(ttbuild_path, f"{version}-{platform}")
def get_sdk_url(version, platform):
def get_sdk_url(version, file):
global ttbuild_cdn
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
return f"{ttbuild_cdn}/sdk/{version}/{file}"
def sdk_exists(version, platform):
sdk_dir = get_sdk_dir(version, platform)
return os.path.isdir(sdk_dir)
def should_update_sdk_json():
def should_update_tool_json():
global ttbuild_cdn
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_filepath = os.path.join(ttbuild_path, "tool.json")
if os.path.exists(json_filepath):
json_modification_time = os.path.getmtime(json_filepath)
now = time.time()
@@ -168,10 +160,10 @@ def should_update_sdk_json():
else:
return True
def update_sdk_json():
def update_tool_json():
global ttbuild_cdn, ttbuild_path
json_url = f"{ttbuild_cdn}/sdk.json"
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_url = f"{ttbuild_cdn}/sdk/tool.json"
json_filepath = os.path.join(ttbuild_path, "tool.json")
return download_file(json_url, json_filepath)
def should_fetch_sdkconfig_files(platform_targets):
@@ -206,16 +198,6 @@ def validate_environment():
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 validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
version_map = sdk_json["versions"]
if not sdk_version in version_map:
exit_with_error(f"Version not found: {sdk_version}")
version_data = version_map[sdk_version]
available_platforms = version_data["platforms"]
for desired_platform in platforms_to_build:
if not desired_platform in available_platforms:
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
def validate_self(sdk_json):
if not "toolVersion" in sdk_json:
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
def sdk_download(version, platform):
sdk_root_dir = get_sdk_root_dir(version, platform)
os.makedirs(sdk_root_dir, exist_ok=True)
sdk_url = get_sdk_url(version, platform)
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
sdk_index_url = get_sdk_url(version, "index.json")
print(f"Downloading SDK version {version} for {platform}")
if download_file(sdk_url, filepath):
with zipfile.ZipFile(filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
else:
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
if verbose:
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
if not download_file(sdk_index_url, sdk_index_filepath):
# TODO: 404 check, print a more accurate error
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
return False
with open(sdk_index_filepath) as sdk_index_json_file:
sdk_index_json = json.load(sdk_index_json_file)
sdk_platforms = sdk_index_json["platforms"]
if platform not in sdk_platforms:
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
return False
sdk_platform_file = sdk_platforms[platform]
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
if verbose:
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
return False
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
def sdk_download_all(version, platforms):
for platform in platforms:
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "build"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
if process.returncode == 0:
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "elf"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
if process.returncode == 0:
print_status_success(f"Building {platform} ELF")
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
if not use_local_sdk:
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
sdk_version = manifest["target"]["sdk"]
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")
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
@@ -613,7 +615,7 @@ if __name__ == "__main__":
# Argument validation
if len(sys.argv) == 1:
print_help()
sys.exit()
sys.exit(1)
if "--verbose" in sys.argv:
verbose = True
sys.argv.remove("--verbose")
@@ -633,8 +635,8 @@ if __name__ == "__main__":
manifest = read_manifest()
validate_manifest(manifest)
all_platform_targets = manifest["target"]["platforms"].split(",")
# Update SDK cache (sdk.json)
if should_update_sdk_json() and not update_sdk_json():
# Update SDK cache (tool.json)
if should_update_tool_json() and not update_tool_json():
exit_with_error("Failed to retrieve SDK info")
# Actions
if action_arg == "build":
@@ -644,7 +646,8 @@ if __name__ == "__main__":
platform = None
if len(sys.argv) > 2:
platform = sys.argv[2]
build_action(manifest, platform)
if not build_action(manifest, platform):
sys.exit(1)
elif action_arg == "clean":
clean_action()
elif action_arg == "clearcache":
+1 -5
View File
@@ -1,15 +1,11 @@
file(GLOB_RECURSE SOURCE_FILES
Source/*.c*
# Library source files must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
../../../Libraries/Str/Source/*.c**
)
idf_component_register(
SRCS ${SOURCE_FILES}
# Library headers must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
INCLUDE_DIRS ../../../Libraries/Str/Include
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
REQUIRES TactilitySDK
)
)
+5 -5
View File
@@ -1,11 +1,11 @@
[manifest]
version=0.1
[target]
sdk=0.7.0-SNAPSHOT2
platforms=esp32,esp32s3
sdk=0.7.0-dev
platforms=esp32,esp32s3,esp32c6,esp32p4
[app]
id=one.tactility.twoeleven
versionName=0.2.0
versionCode=2
versionName=0.3.0
versionCode=3
name=2048
description=A fun, customizable 2048 sliding tile game for tactility!\nSlide tiles to combine numbers and reach 2048.\nChoose grid sizes: 3x3 (easy), 4x4 (classic), 5x5, or 6x6 (expert).
description=A fun, customizable 2048 sliding tile game for tactility!\nSlide tiles to combine numbers and reach 2048.\nChoose grid sizes: 3x3 (easy), 4x4 (classic), 5x5, or 6x6 (expert).
+54 -51
View File
@@ -12,7 +12,7 @@ import requests
import tarfile
ttbuild_path = ".tactility"
ttbuild_version = "2.5.0"
ttbuild_version = "3.1.0"
ttbuild_cdn = "https://cdn.tactility.one"
ttbuild_sdk_json_validity = 3600 # seconds
ttport = 6666
@@ -20,20 +20,12 @@ verbose = False
use_local_sdk = False
local_base_path = None
if sys.platform == "win32":
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
else:
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_green = "\033[32m"
shell_color_purple = "\033[35m"
shell_color_cyan = "\033[36m"
shell_color_reset = "\033[m"
def print_help():
print("Usage: python tactility.py [action] [options]")
@@ -115,9 +107,9 @@ def read_properties_file(path):
#region SDK helpers
def read_sdk_json():
json_file_path = os.path.join(ttbuild_path, "sdk.json")
json_file = open(json_file_path)
return json.load(json_file)
json_file_path = os.path.join(ttbuild_path, "tool.json")
with open(json_file_path) as json_file:
return json.load(json_file)
def get_sdk_dir(version, platform):
global use_local_sdk, local_base_path
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
global ttbuild_cdn
return os.path.join(ttbuild_path, f"{version}-{platform}")
def get_sdk_url(version, platform):
def get_sdk_url(version, file):
global ttbuild_cdn
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
return f"{ttbuild_cdn}/sdk/{version}/{file}"
def sdk_exists(version, platform):
sdk_dir = get_sdk_dir(version, platform)
return os.path.isdir(sdk_dir)
def should_update_sdk_json():
def should_update_tool_json():
global ttbuild_cdn
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_filepath = os.path.join(ttbuild_path, "tool.json")
if os.path.exists(json_filepath):
json_modification_time = os.path.getmtime(json_filepath)
now = time.time()
@@ -168,10 +160,10 @@ def should_update_sdk_json():
else:
return True
def update_sdk_json():
def update_tool_json():
global ttbuild_cdn, ttbuild_path
json_url = f"{ttbuild_cdn}/sdk.json"
json_filepath = os.path.join(ttbuild_path, "sdk.json")
json_url = f"{ttbuild_cdn}/sdk/tool.json"
json_filepath = os.path.join(ttbuild_path, "tool.json")
return download_file(json_url, json_filepath)
def should_fetch_sdkconfig_files(platform_targets):
@@ -206,16 +198,6 @@ def validate_environment():
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 validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
version_map = sdk_json["versions"]
if not sdk_version in version_map:
exit_with_error(f"Version not found: {sdk_version}")
version_data = version_map[sdk_version]
available_platforms = version_data["platforms"]
for desired_platform in platforms_to_build:
if not desired_platform in available_platforms:
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
def validate_self(sdk_json):
if not "toolVersion" in sdk_json:
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
def sdk_download(version, platform):
sdk_root_dir = get_sdk_root_dir(version, platform)
os.makedirs(sdk_root_dir, exist_ok=True)
sdk_url = get_sdk_url(version, platform)
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
sdk_index_url = get_sdk_url(version, "index.json")
print(f"Downloading SDK version {version} for {platform}")
if download_file(sdk_url, filepath):
with zipfile.ZipFile(filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
else:
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
if verbose:
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
if not download_file(sdk_index_url, sdk_index_filepath):
# TODO: 404 check, print a more accurate error
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
return False
with open(sdk_index_filepath) as sdk_index_json_file:
sdk_index_json = json.load(sdk_index_json_file)
sdk_platforms = sdk_index_json["platforms"]
if platform not in sdk_platforms:
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
return False
sdk_platform_file = sdk_platforms[platform]
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
if verbose:
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
return False
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
return True
def sdk_download_all(version, platforms):
for platform in platforms:
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "build"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
if process.returncode == 0:
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
cmake_path = get_cmake_path(platform)
print_status_busy(f"Building {platform} ELF")
shell_needed = sys.platform == "win32"
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_command = ["idf.py", "-B", cmake_path, "elf"]
if verbose:
print(f"Running command: {" ".join(build_command)}")
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
build_output = wait_for_process(process)
if process.returncode == 0:
print_status_success(f"Building {platform} ELF")
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
if not use_local_sdk:
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
sdk_version = manifest["target"]["sdk"]
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")
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
@@ -613,7 +615,7 @@ if __name__ == "__main__":
# Argument validation
if len(sys.argv) == 1:
print_help()
sys.exit()
sys.exit(1)
if "--verbose" in sys.argv:
verbose = True
sys.argv.remove("--verbose")
@@ -633,8 +635,8 @@ if __name__ == "__main__":
manifest = read_manifest()
validate_manifest(manifest)
all_platform_targets = manifest["target"]["platforms"].split(",")
# Update SDK cache (sdk.json)
if should_update_sdk_json() and not update_sdk_json():
# Update SDK cache (tool.json)
if should_update_tool_json() and not update_tool_json():
exit_with_error("Failed to retrieve SDK info")
# Actions
if action_arg == "build":
@@ -644,7 +646,8 @@ if __name__ == "__main__":
platform = None
if len(sys.argv) > 2:
platform = sys.argv[2]
build_action(manifest, platform)
if not build_action(manifest, platform):
sys.exit(1)
elif action_arg == "clean":
clean_action()
elif action_arg == "clearcache":