mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 19:03:16 +00:00
Development service work in progress
This commit is contained in:
parent
b7b11e88a8
commit
e66033c1c6
@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
if (DEFINED ENV{ESP_IDF_VERSION})
|
if (DEFINED ENV{ESP_IDF_VERSION})
|
||||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
||||||
|
|
||||||
list(APPEND REQUIRES_LIST TactilityCore lvgl driver elf_loader lv_screenshot QRCode esp_lvgl_port minmea esp_wifi nvs_flash spiffs vfs fatfs lwip)
|
list(APPEND REQUIRES_LIST TactilityCore lvgl driver elf_loader lv_screenshot QRCode esp_lvgl_port minmea esp_wifi nvs_flash spiffs vfs fatfs lwip esp_http_server)
|
||||||
if ("${IDF_TARGET}" STREQUAL "esp32s3")
|
if ("${IDF_TARGET}" STREQUAL "esp32s3")
|
||||||
list(APPEND REQUIRES_LIST esp_tinyusb)
|
list(APPEND REQUIRES_LIST esp_tinyusb)
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
|
#include "Tactility/service/Service.h"
|
||||||
|
|
||||||
|
#include <Tactility/Mutex.h>
|
||||||
|
|
||||||
|
#include <esp_event.h>
|
||||||
|
#include <esp_http_server.h>
|
||||||
|
#include <Tactility/kernel/SystemEvents.h>
|
||||||
|
|
||||||
|
namespace tt::service::development {
|
||||||
|
|
||||||
|
class Development final : public Service {
|
||||||
|
|
||||||
|
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||||
|
httpd_handle_t server = nullptr;
|
||||||
|
bool enabled = false;
|
||||||
|
kernel::SystemEventSubscription networkConnectEventSubscription = 0;
|
||||||
|
kernel::SystemEventSubscription networkDisconnectEventSubscription = 0;
|
||||||
|
std::string deviceResponse;
|
||||||
|
|
||||||
|
httpd_uri_t getDeviceEndpoint = {
|
||||||
|
.uri = "/device",
|
||||||
|
.method = HTTP_GET,
|
||||||
|
.handler = getDevice,
|
||||||
|
.user_ctx = this
|
||||||
|
};
|
||||||
|
|
||||||
|
void onNetworkConnected();
|
||||||
|
void onNetworkDisconnected();
|
||||||
|
|
||||||
|
void startServer();
|
||||||
|
void stopServer();
|
||||||
|
|
||||||
|
static esp_err_t getDevice(httpd_req_t* request);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// region Overrides
|
||||||
|
|
||||||
|
void onStart(ServiceContext& service) override;
|
||||||
|
void onStop(ServiceContext& service) override;
|
||||||
|
|
||||||
|
// endregion Overrides
|
||||||
|
|
||||||
|
// region Internal API
|
||||||
|
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
|
bool isEnabled() const;
|
||||||
|
|
||||||
|
bool isStarted() const;
|
||||||
|
|
||||||
|
// region Internal API
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<Development> findService();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ESP_PLATFORM
|
||||||
@ -20,6 +20,7 @@ namespace service::gps { extern const ServiceManifest manifest; }
|
|||||||
namespace service::wifi { extern const ServiceManifest manifest; }
|
namespace service::wifi { extern const ServiceManifest manifest; }
|
||||||
namespace service::sdcard { extern const ServiceManifest manifest; }
|
namespace service::sdcard { extern const ServiceManifest manifest; }
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
namespace service::development { extern const ServiceManifest manifest; }
|
||||||
namespace service::espnow { extern const ServiceManifest manifest; }
|
namespace service::espnow { extern const ServiceManifest manifest; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ static void registerAndStartSystemServices() {
|
|||||||
addService(service::sdcard::manifest);
|
addService(service::sdcard::manifest);
|
||||||
addService(service::wifi::manifest);
|
addService(service::wifi::manifest);
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
addService(service::development::manifest);
|
||||||
addService(service::espnow::manifest);
|
addService(service::espnow::manifest);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -118,7 +118,7 @@ static void statusbar_pubsub_event(TT_UNUSED const void* message, void* obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onNetworkConnected(TT_UNUSED kernel::SystemEvent event) {
|
static void onTimeChanged(TT_UNUSED kernel::SystemEvent event) {
|
||||||
if (statusbar_data.mutex.lock(100 / portTICK_PERIOD_MS)) {
|
if (statusbar_data.mutex.lock(100 / portTICK_PERIOD_MS)) {
|
||||||
statusbar_data.time_update_timer->stop();
|
statusbar_data.time_update_timer->stop();
|
||||||
statusbar_data.time_update_timer->start(5);
|
statusbar_data.time_update_timer->start(5);
|
||||||
@ -139,7 +139,7 @@ static void statusbar_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj)
|
|||||||
statusbar_data.time_update_timer->start(50 / portTICK_PERIOD_MS);
|
statusbar_data.time_update_timer->start(50 / portTICK_PERIOD_MS);
|
||||||
statusbar_data.systemEventSubscription = kernel::subscribeSystemEvent(
|
statusbar_data.systemEventSubscription = kernel::subscribeSystemEvent(
|
||||||
kernel::SystemEvent::Time,
|
kernel::SystemEvent::Time,
|
||||||
onNetworkConnected
|
onTimeChanged
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
193
Tactility/Source/service/development/Development.cpp
Normal file
193
Tactility/Source/service/development/Development.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
|
#include "Tactility/service/development/Development.h"
|
||||||
|
|
||||||
|
#include "Tactility/TactilityHeadless.h"
|
||||||
|
#include "Tactility/service/ServiceManifest.h"
|
||||||
|
#include "Tactility/service/ServiceRegistry.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <esp_wifi.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace tt::service::development {
|
||||||
|
|
||||||
|
extern const ServiceManifest manifest;
|
||||||
|
|
||||||
|
constexpr const char* TAG = "DevService";
|
||||||
|
|
||||||
|
|
||||||
|
static char* rest_read_buffer(httpd_req_t* request) {
|
||||||
|
static char buffer[1024];
|
||||||
|
int contentLength = request->content_len;
|
||||||
|
int currentLength = 0;
|
||||||
|
int received = 0;
|
||||||
|
if (contentLength >= 1024) {
|
||||||
|
// Respond with 500 Internal Server Error
|
||||||
|
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
while (currentLength < contentLength) {
|
||||||
|
received = httpd_req_recv(request, buffer + currentLength, contentLength);
|
||||||
|
if (received <= 0) {
|
||||||
|
// Respond with 500 Internal Server Error
|
||||||
|
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to post control value");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
currentLength += received;
|
||||||
|
}
|
||||||
|
buffer[contentLength] = '\0';
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Development::onStart(ServiceContext& service) {
|
||||||
|
auto lock = mutex.asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
networkConnectEventSubscription = kernel::subscribeSystemEvent(
|
||||||
|
kernel::SystemEvent::NetworkConnected,
|
||||||
|
[this](kernel::SystemEvent) { onNetworkConnected(); }
|
||||||
|
);
|
||||||
|
networkConnectEventSubscription = kernel::subscribeSystemEvent(
|
||||||
|
kernel::SystemEvent::NetworkDisconnected,
|
||||||
|
[this](kernel::SystemEvent) { onNetworkDisconnected(); }
|
||||||
|
);
|
||||||
|
|
||||||
|
setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Development::onStop(ServiceContext& service) {
|
||||||
|
auto lock = mutex.asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
kernel::unsubscribeSystemEvent(networkConnectEventSubscription);
|
||||||
|
kernel::unsubscribeSystemEvent(networkDisconnectEventSubscription);
|
||||||
|
|
||||||
|
if (isEnabled()) {
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Enable/disable
|
||||||
|
|
||||||
|
void Development::setEnabled(bool enabled) {
|
||||||
|
auto lock = mutex.asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
this->enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Development::isEnabled() const {
|
||||||
|
auto lock = mutex.asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Enable/disable
|
||||||
|
|
||||||
|
// region Handlers
|
||||||
|
|
||||||
|
void Development::startServer() {
|
||||||
|
auto lock = mutex.asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
if (isStarted()) {
|
||||||
|
TT_LOG_W(TAG, "Already started");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Starting server");
|
||||||
|
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << "{";
|
||||||
|
stream << "\"cpuFamily\" : \"" << CONFIG_IDF_TARGET << "\"";
|
||||||
|
stream << "}";
|
||||||
|
deviceResponse = stream.str();
|
||||||
|
|
||||||
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||||
|
|
||||||
|
config.server_port = 6666;
|
||||||
|
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||||
|
|
||||||
|
if (httpd_start(&server, &config) == ESP_OK) {
|
||||||
|
httpd_register_uri_handler(server, &getDeviceEndpoint);
|
||||||
|
TT_LOG_I(TAG, "Started on port %d", config.server_port);
|
||||||
|
} else {
|
||||||
|
TT_LOG_E(TAG, "Failed to start");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Development::stopServer() {
|
||||||
|
auto lock = mutex.asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
if (!isStarted()) {
|
||||||
|
TT_LOG_W(TAG, "Not started");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TT_LOG_I(TAG, "Stopping server");
|
||||||
|
if (httpd_stop(server) != ESP_OK) {
|
||||||
|
TT_LOG_W(TAG, "Error while stopping");
|
||||||
|
}
|
||||||
|
server = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Development::isStarted() const {
|
||||||
|
auto lock = mutex.asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
return server != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Development::onNetworkConnected() {
|
||||||
|
TT_LOG_I(TAG, "onNetworkConnected");
|
||||||
|
mutex.withLock([this] {
|
||||||
|
if (isEnabled() && !isStarted()) {
|
||||||
|
startServer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Development::onNetworkDisconnected() {
|
||||||
|
TT_LOG_I(TAG, "onNetworkDisconnected");
|
||||||
|
mutex.withLock([this] {
|
||||||
|
if (isStarted()) {
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region endpoints
|
||||||
|
|
||||||
|
esp_err_t Development::getDevice(httpd_req_t* request) {
|
||||||
|
if (httpd_resp_set_type(request, "application/json") != ESP_OK) {
|
||||||
|
TT_LOG_W(TAG, "Failed to send header");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* service = static_cast<Development*>(request->user_ctx);
|
||||||
|
|
||||||
|
if (httpd_resp_sendstr(request, service->deviceResponse.c_str()) != ESP_OK) {
|
||||||
|
TT_LOG_W(TAG, "Failed to send response body");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TT_LOG_I(TAG, "[200] /device from");
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Development> findService() {
|
||||||
|
return std::static_pointer_cast<Development>(
|
||||||
|
findServiceById(manifest.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const ServiceManifest manifest = {
|
||||||
|
.id = "Development",
|
||||||
|
.createService = create<Development>
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ESP_PLATFORM
|
||||||
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <Tactility/kernel/SystemEvents.h>
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
namespace tt::service::wifi {
|
namespace tt::service::wifi {
|
||||||
@ -476,6 +477,7 @@ static void eventHandler(TT_UNUSED void* arg, esp_event_base_t event_base, int32
|
|||||||
}
|
}
|
||||||
wifi->setRadioState(RadioState::On);
|
wifi->setRadioState(RadioState::On);
|
||||||
publish_event_simple(wifi, EventType::Disconnected);
|
publish_event_simple(wifi, EventType::Disconnected);
|
||||||
|
kernel::publishSystemEvent(kernel::SystemEvent::NetworkDisconnected);
|
||||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
auto* event = static_cast<ip_event_got_ip_t*>(event_data);
|
auto* event = static_cast<ip_event_got_ip_t*>(event_data);
|
||||||
TT_LOG_I(TAG, "eventHandler: got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
TT_LOG_I(TAG, "eventHandler: got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||||
@ -485,6 +487,7 @@ static void eventHandler(TT_UNUSED void* arg, esp_event_base_t event_base, int32
|
|||||||
// TODO: Make thread-safe
|
// TODO: Make thread-safe
|
||||||
wifi->pause_auto_connect = false; // Resume auto-connection
|
wifi->pause_auto_connect = false; // Resume auto-connection
|
||||||
}
|
}
|
||||||
|
kernel::publishSystemEvent(kernel::SystemEvent::NetworkConnected);
|
||||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_SCAN_DONE) {
|
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_SCAN_DONE) {
|
||||||
auto* event = static_cast<wifi_event_sta_scan_done_t*>(event_data);
|
auto* event = static_cast<wifi_event_sta_scan_done_t*>(event_data);
|
||||||
TT_LOG_I(TAG, "eventHandler: wifi scanning done (scan id %u)", event->scan_id);
|
TT_LOG_I(TAG, "eventHandler: wifi scanning done (scan id %u)", event->scan_id);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user