PR review fixes (#384)

This commit is contained in:
Ken Van Hoeylandt 2025-10-25 13:47:43 +02:00 committed by GitHub
parent f660550f86
commit d0d05c67ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 56 additions and 28 deletions

View File

@ -11,7 +11,7 @@ class EspHttpClient {
static constexpr auto* TAG = "EspHttpClient"; static constexpr auto* TAG = "EspHttpClient";
std::unique_ptr<esp_http_client_config_t> config = nullptr; std::unique_ptr<esp_http_client_config_t> config = nullptr;
esp_http_client_handle_t client; esp_http_client_handle_t client = nullptr;
bool isOpen = false; bool isOpen = false;
public: public:
@ -87,11 +87,15 @@ public:
bool close() { bool close() {
assert(client != nullptr); assert(client != nullptr);
TT_LOG_I(TAG, "close()"); TT_LOG_I(TAG, "close()");
return esp_http_client_close(client) == ESP_OK; if (esp_http_client_close(client) == ESP_OK) {
isOpen = false;
}
return !isOpen;
} }
bool cleanup() { bool cleanup() {
assert(client != nullptr); assert(client != nullptr);
assert(!isOpen);
TT_LOG_I(TAG, "cleanup()"); TT_LOG_I(TAG, "cleanup()");
const auto result = esp_http_client_cleanup(client); const auto result = esp_http_client_cleanup(client);
client = nullptr; client = nullptr;

View File

@ -1,10 +1,19 @@
#pragma once #pragma once
#include <string> #include <string>
#include <functional>
namespace tt::network::http { namespace tt::network::http {
/**
void download( * Download a file from a URL.
* The server must send the Content-Length header.
* @param url download source URL
* @param certFilePath the path to the .pem file
* @param downloadFilePath The path to downloadd the file to. The parent directories must exist.
* @param onSuccess the success result callback
* @param onError the error result callback
*/
void download(
const std::string& url, const std::string& url,
const std::string& certFilePath, const std::string& certFilePath,
const std::string &downloadFilePath, const std::string &downloadFilePath,

View File

@ -46,7 +46,7 @@ public:
bool readNumber(const char* key, double& output) const { bool readNumber(const char* key, double& output) const {
const auto* child = cJSON_GetObjectItemCaseSensitive(root, key); const auto* child = cJSON_GetObjectItemCaseSensitive(root, key);
if (!cJSON_IsNumber(child)) { if (!cJSON_IsNumber(child)) {
TT_LOG_E(TAG, "%s is not a string", key); TT_LOG_E(TAG, "%s is not a number", key);
return false; return false;
} }
output = cJSON_GetNumberValue(child); output = cJSON_GetNumberValue(child);

View File

@ -90,6 +90,8 @@ void Preferences::putBool(const std::string& key, bool value) {
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) { if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
if (nvs_set_u8(handle, key.c_str(), (uint8_t)value) != ESP_OK) { if (nvs_set_u8(handle, key.c_str(), (uint8_t)value) != ESP_OK) {
TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str()); TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str());
} else if (nvs_commit(handle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to commit %s:%s", namespace_, key.c_str());
} }
nvs_close(handle); nvs_close(handle);
} else { } else {
@ -102,6 +104,8 @@ void Preferences::putInt32(const std::string& key, int32_t value) {
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) { if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
if (nvs_set_i32(handle, key.c_str(), value) != ESP_OK) { if (nvs_set_i32(handle, key.c_str(), value) != ESP_OK) {
TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str()); TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str());
} else if (nvs_commit(handle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to commit %s:%s", namespace_, key.c_str());
} }
nvs_close(handle); nvs_close(handle);
} else { } else {
@ -114,6 +118,8 @@ void Preferences::putInt64(const std::string& key, int64_t value) {
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) { if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
if (nvs_set_i64(handle, key.c_str(), value) != ESP_OK) { if (nvs_set_i64(handle, key.c_str(), value) != ESP_OK) {
TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str()); TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str());
} else if (nvs_commit(handle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to commit %s:%s", namespace_, key.c_str());
} }
nvs_close(handle); nvs_close(handle);
} else { } else {
@ -125,6 +131,9 @@ void Preferences::putString(const std::string& key, const std::string& text) {
nvs_handle_t handle; nvs_handle_t handle;
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) { if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
nvs_set_str(handle, key.c_str(), text.c_str()); nvs_set_str(handle, key.c_str(), text.c_str());
if (nvs_commit(handle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to commit %s:%s", namespace_, key.c_str());
}
nvs_close(handle); nvs_close(handle);
} else { } else {
TT_LOG_E(TAG, "Failed to open namespace %s", namespace_); TT_LOG_E(TAG, "Failed to open namespace %s", namespace_);

View File

@ -40,11 +40,7 @@ class AppHubApp final : public App {
const auto* self = static_cast<AppHubApp*>(lv_event_get_user_data(e)); const auto* self = static_cast<AppHubApp*>(lv_event_get_user_data(e));
auto* widget = lv_event_get_target_obj(e); auto* widget = lv_event_get_target_obj(e);
const auto* user_data = lv_obj_get_user_data(widget); const auto* user_data = lv_obj_get_user_data(widget);
#ifdef ESP_PLATFORM const intptr_t index = reinterpret_cast<intptr_t>(user_data);
const int index = reinterpret_cast<int>(user_data);
#else
const long long index = reinterpret_cast<long long>(user_data);
#endif
self->mutex.lock(); self->mutex.lock();
if (index < self->entries.size()) { if (index < self->entries.size()) {
apphubdetails::start(self->entries[index]); apphubdetails::start(self->entries[index]);
@ -112,7 +108,8 @@ class AppHubApp final : public App {
TT_LOG_I(TAG, "Adding %s", entry.appName.c_str()); TT_LOG_I(TAG, "Adding %s", entry.appName.c_str());
const char* icon = findAppManifestById(entry.appId) != nullptr ? LV_SYMBOL_OK : nullptr; const char* icon = findAppManifestById(entry.appId) != nullptr ? LV_SYMBOL_OK : nullptr;
auto* entry_button = lv_list_add_button(list, icon, entry.appName.c_str()); auto* entry_button = lv_list_add_button(list, icon, entry.appName.c_str());
lv_obj_set_user_data(entry_button, reinterpret_cast<void*>(i)); auto int_as_voidptr = reinterpret_cast<void*>(i);
lv_obj_set_user_data(entry_button, int_as_voidptr);
lv_obj_add_event_cb(entry_button, onAppPressed, LV_EVENT_SHORT_CLICKED, this); lv_obj_add_event_cb(entry_button, onAppPressed, LV_EVENT_SHORT_CLICKED, this);
} }
} else { } else {

View File

@ -23,6 +23,11 @@ bool parseJson(const std::string& filePath, std::vector<AppHubEntry>& entries) {
lock.lock(); lock.lock();
auto data = file::readString(filePath); auto data = file::readString(filePath);
if (data == nullptr) {
TT_LOG_E(TAG, "Failed to read %s", filePath.c_str());
return false;
}
auto data_ptr = reinterpret_cast<const char*>(data.get()); auto data_ptr = reinterpret_cast<const char*>(data.get());
auto* json = cJSON_Parse(data_ptr); auto* json = cJSON_Parse(data_ptr);
if (json == nullptr) { if (json == nullptr) {

View File

@ -16,10 +16,9 @@ bool ObjectFileWriter::open() {
} }
// Edit existing or create a new file // Edit existing or create a new file
auto* mode = edit_existing ? "r+" : "w"; auto opening_file = std::unique_ptr<FILE, FileCloser>(std::fopen(filePath.c_str(), "wb"));
auto opening_file = std::unique_ptr<FILE, FileCloser>(std::fopen(filePath.c_str(), mode));
if (opening_file == nullptr) { if (opening_file == nullptr) {
TT_LOG_E(TAG, "Failed to open file %s in %s mode", filePath.c_str(), mode); TT_LOG_E(TAG, "Failed to open file %s", filePath.c_str());
return false; return false;
} }

View File

@ -223,6 +223,7 @@ lv_obj_t* toolbar_add_spinner_action(lv_obj_t* obj) {
void toolbar_clear_actions(lv_obj_t* obj) { void toolbar_clear_actions(lv_obj_t* obj) {
auto* toolbar = reinterpret_cast<Toolbar*>(obj); auto* toolbar = reinterpret_cast<Toolbar*>(obj);
lv_obj_clean(toolbar->action_container); lv_obj_clean(toolbar->action_container);
toolbar->action_count = 0;
} }
} // namespace } // namespace

View File

@ -24,6 +24,11 @@ void download(
getMainDispatcher().dispatch([url, certFilePath, downloadFilePath, onSuccess, onError] { getMainDispatcher().dispatch([url, certFilePath, downloadFilePath, onSuccess, onError] {
TT_LOG_I(TAG, "Loading certificate"); TT_LOG_I(TAG, "Loading certificate");
auto certificate = file::readString(certFilePath); auto certificate = file::readString(certFilePath);
if (certificate == nullptr) {
onError("Failed to read certificate");
return;
}
auto certificate_length = strlen(reinterpret_cast<const char*>(certificate.get())) + 1; auto certificate_length = strlen(reinterpret_cast<const char*>(certificate.get())) + 1;
auto config = std::make_unique<esp_http_client_config_t>(esp_http_client_config_t { auto config = std::make_unique<esp_http_client_config_t>(esp_http_client_config_t {
@ -40,35 +45,33 @@ void download(
auto client = std::make_unique<EspHttpClient>(); auto client = std::make_unique<EspHttpClient>();
if (!client->init(std::move(config))) { if (!client->init(std::move(config))) {
onError("Failed to initialize client"); onError("Failed to initialize client");
return -1; return;
} }
if (!client->open()) { if (!client->open()) {
onError("Failed to open connection"); onError("Failed to open connection");
return -1; return;
} }
if (!client->fetchHeaders()) { if (!client->fetchHeaders()) {
onError("Failed to get request headers"); onError("Failed to get request headers");
return -1; return;
} }
if (!client->isStatusCodeOk()) { if (!client->isStatusCodeOk()) {
onError("Server response is not OK"); onError("Server response is not OK");
return -1; return;
} }
auto bytes_left = client->getContentLength(); auto bytes_left = client->getContentLength();
auto lock = file::getLock(downloadFilePath)->asScopedLock(); auto lock = file::getLock(downloadFilePath)->asScopedLock();
lock.lock(); lock.lock();
auto file_exists = file::isFile(downloadFilePath); TT_LOG_I(TAG, "opening %s", downloadFilePath.c_str());
auto* file_mode = file_exists ? "r+" : "w"; auto* file = fopen(downloadFilePath.c_str(), "wb");
TT_LOG_I(TAG, "opening %s with mode %s", downloadFilePath.c_str(), file_mode);
auto* file = fopen(downloadFilePath.c_str(), file_mode);
if (file == nullptr) { if (file == nullptr) {
onError("Failed to open file"); onError("Failed to open file");
return -1; return;
} }
TT_LOG_I(TAG, "Writing %d bytes to %s", bytes_left, downloadFilePath.c_str()); TT_LOG_I(TAG, "Writing %d bytes to %s", bytes_left, downloadFilePath.c_str());
@ -78,19 +81,18 @@ void download(
if (data_read <= 0) { if (data_read <= 0) {
fclose(file); fclose(file);
onError("Failed to read data"); onError("Failed to read data");
return -1; return;
} }
bytes_left -= data_read; bytes_left -= data_read;
if (fwrite(buffer, 1, data_read, file) != data_read) { if (fwrite(buffer, 1, data_read, file) != data_read) {
fclose(file); fclose(file);
onError("Failed to write all bytes"); onError("Failed to write all bytes");
return -1; return;
} }
} }
fclose(file); fclose(file);
TT_LOG_I(TAG, "Downloaded %s to %s", url.c_str(), downloadFilePath.c_str()); TT_LOG_I(TAG, "Downloaded %s to %s", url.c_str(), downloadFilePath.c_str());
onSuccess(); onSuccess();
return 0;
}); });
#else #else
getMainDispatcher().dispatch([onError] { getMainDispatcher().dispatch([onError] {

View File

@ -22,7 +22,7 @@ bool HttpServer::startInternal() {
httpd_register_uri_handler(server, &handler); httpd_register_uri_handler(server, &handler);
} }
TT_LOG_I(TAG, "Started on port %d", config.server_port); TT_LOG_I(TAG, "Started on port %lu", config.server_port);
return true; return true;
} }

View File

@ -44,6 +44,8 @@ static void onTimeSynced(timeval* tv) {
} }
void init() { void init() {
setTimeFromNvs();
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("time.cloudflare.com"); esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("time.cloudflare.com");
config.sync_cb = onTimeSynced; config.sync_cb = onTimeSynced;
esp_netif_sntp_init(&config); esp_netif_sntp_init(&config);

View File

@ -61,7 +61,7 @@ bool Bundle::optInt32(const std::string& key, int32_t& out) const {
bool Bundle::optInt64(const std::string& key, int64_t& out) const { bool Bundle::optInt64(const std::string& key, int64_t& out) const {
auto entry = this->entries.find(key); auto entry = this->entries.find(key);
if (entry != std::end(this->entries) && entry->second.type == Type::Int64) { if (entry != std::end(this->entries) && entry->second.type == Type::Int64) {
out = entry->second.value_int32; out = entry->second.value_int64;
return true; return true;
} else { } else {
return false; return false;