Replace Tactility SystemEvents with new kernel implementation (#598)
TactilityKernel now has a system event API to replace the one from the Tactility subproject. It also implements several tests for it.
This commit is contained in:
committed by
GitHub
parent
6e55e71e67
commit
acb2f1d4c7
@@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
namespace tt::kernel {
|
||||
|
||||
enum class SystemEvent {
|
||||
BootSplash,
|
||||
/** Gained IP address */
|
||||
NetworkConnected,
|
||||
NetworkDisconnected,
|
||||
Time,
|
||||
};
|
||||
|
||||
/** Value 0 mean "no subscription" */
|
||||
typedef uint32_t SystemEventSubscription;
|
||||
constexpr SystemEventSubscription NoSystemEventSubscription = 0U;
|
||||
|
||||
typedef std::function<void(SystemEvent)> OnSystemEvent;
|
||||
|
||||
void publishSystemEvent(SystemEvent event);
|
||||
|
||||
SystemEventSubscription subscribeSystemEvent(SystemEvent event, OnSystemEvent handler);
|
||||
|
||||
void unsubscribeSystemEvent(SystemEventSubscription subscription);
|
||||
|
||||
}
|
||||
@@ -1,21 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/SystemEvents.h>
|
||||
#include <Tactility/service/Service.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct Device;
|
||||
struct SystemEvent;
|
||||
|
||||
namespace tt::service::rtctime {
|
||||
|
||||
class RtcTimeService final : public Service {
|
||||
|
||||
kernel::SystemEventSubscription timeEventSubscription = 0;
|
||||
bool timeEventSubscribed = false;
|
||||
Device* rtcDevice = nullptr;
|
||||
|
||||
Device* findRtcDevice();
|
||||
void onTimeChanged(kernel::SystemEvent event);
|
||||
void onTimeChanged();
|
||||
static void onTimeChangedTrampoline(struct SystemEvent* event, void* context);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
#include <Tactility/CoreDefines.h>
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <Tactility/SystemEvents.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/time.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace tt::kernel {
|
||||
|
||||
constexpr auto* TAG = "SystemEvents";
|
||||
|
||||
struct SubscriptionData {
|
||||
SystemEventSubscription id;
|
||||
SystemEvent event;
|
||||
OnSystemEvent handler;
|
||||
};
|
||||
|
||||
static Mutex mutex;
|
||||
static SystemEventSubscription subscriptionCounter = 0;
|
||||
static std::list<SubscriptionData> subscriptions;
|
||||
|
||||
static const char* getEventName(SystemEvent event) {
|
||||
switch (event) {
|
||||
using enum SystemEvent;
|
||||
case BootSplash:
|
||||
return TT_STRINGIFY(BootSplash);
|
||||
case NetworkConnected:
|
||||
return TT_STRINGIFY(NetworkConnected);
|
||||
case NetworkDisconnected:
|
||||
return TT_STRINGIFY(NetworkDisconnected);
|
||||
case Time:
|
||||
return TT_STRINGIFY(Time);
|
||||
}
|
||||
|
||||
check(false); // Missing case above
|
||||
}
|
||||
|
||||
void publishSystemEvent(SystemEvent event) {
|
||||
LOG_I(TAG, "%s", getEventName(event));
|
||||
|
||||
if (mutex.lock(MAX_TICKS)) {
|
||||
for (auto& subscription : subscriptions) {
|
||||
if (subscription.event == event) {
|
||||
subscription.handler(event);
|
||||
}
|
||||
}
|
||||
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
SystemEventSubscription subscribeSystemEvent(SystemEvent event, OnSystemEvent handler) {
|
||||
if (mutex.lock(MAX_TICKS)) {
|
||||
auto id = ++subscriptionCounter;
|
||||
|
||||
subscriptions.push_back({
|
||||
.id = id,
|
||||
.event = event,
|
||||
.handler = handler
|
||||
});
|
||||
|
||||
mutex.unlock();
|
||||
return id;
|
||||
} else {
|
||||
check(false);
|
||||
}
|
||||
}
|
||||
|
||||
void unsubscribeSystemEvent(SystemEventSubscription subscription) {
|
||||
if (mutex.lock(MAX_TICKS)) {
|
||||
std::erase_if(subscriptions, [subscription](auto& item) {
|
||||
return (item.id == subscription);
|
||||
});
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
#include "tactility/system_event.h"
|
||||
|
||||
|
||||
#include <tactility/delay.h>
|
||||
#include <tactility/drivers/backlight.h>
|
||||
#include <tactility/drivers/display.h>
|
||||
@@ -6,7 +9,6 @@
|
||||
|
||||
#include <Tactility/CpuAffinity.h>
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/SystemEvents.h>
|
||||
#include <Tactility/TactilityPrivate.h>
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/app/AppPaths.h>
|
||||
@@ -154,7 +156,7 @@ class BootApp : public App {
|
||||
// This event will likely block as other systems are initialized
|
||||
// e.g. Wi-Fi reads AP configs from SD card
|
||||
LOG_I(TAG, "Publish event");
|
||||
kernel::publishSystemEvent(kernel::SystemEvent::BootSplash);
|
||||
system_event_emit(KERNEL_EVENT_BOOT_COMPLETED, nullptr, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#define LV_USE_PRIVATE_API 1 // For actual lv_obj_t declaration
|
||||
|
||||
#include <Tactility/SystemEvents.h>
|
||||
#include <Tactility/PubSub.h>
|
||||
#include <Tactility/RecursiveMutex.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
@@ -11,6 +10,7 @@
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/system_event.h>
|
||||
#include <tactility/time.h>
|
||||
|
||||
#include <lvgl/fonts.h>
|
||||
@@ -38,7 +38,6 @@ struct StatusbarData {
|
||||
uint8_t time_hours = 0;
|
||||
uint8_t time_minutes = 0;
|
||||
bool time_set = false;
|
||||
kernel::SystemEventSubscription systemEventSubscription = 0;
|
||||
};
|
||||
|
||||
static StatusbarData statusbar_data;
|
||||
@@ -115,7 +114,7 @@ static void statusbar_pubsub_event(Statusbar* statusbar) {
|
||||
}
|
||||
}
|
||||
|
||||
static void onTimeChanged(kernel::SystemEvent event) {
|
||||
static void onTimeChanged(struct SystemEvent* /*event*/, void* /*context*/) {
|
||||
if (statusbar_data.mutex.lock()) {
|
||||
statusbar_data.time_update_timer->reset(5);
|
||||
statusbar_data.mutex.unlock();
|
||||
@@ -134,10 +133,7 @@ static void statusbar_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj)
|
||||
|
||||
if (!statusbar_data.time_update_timer->isRunning()) {
|
||||
statusbar_data.time_update_timer->start();
|
||||
statusbar_data.systemEventSubscription = kernel::subscribeSystemEvent(
|
||||
kernel::SystemEvent::Time,
|
||||
onTimeChanged
|
||||
);
|
||||
system_event_subscribe(KERNEL_EVENT_TIME_CHANGED, onTimeChanged, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include <memory>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include <Tactility/SystemEvents.h>
|
||||
#include <Tactility/TactilityCore.h>
|
||||
#include <tactility/system_event.h>
|
||||
#include <esp_netif_sntp.h>
|
||||
#include <esp_sntp.h>
|
||||
#endif
|
||||
@@ -45,7 +45,7 @@ static void onTimeSynced(timeval* tv) {
|
||||
processedSyncEvent = true;
|
||||
esp_netif_sntp_deinit();
|
||||
storeTimeInNvs();
|
||||
kernel::publishSystemEvent(kernel::SystemEvent::Time);
|
||||
system_event_emit(KERNEL_EVENT_TIME_CHANGED, nullptr, 0);
|
||||
}
|
||||
|
||||
void init() {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/rtc.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/system_event.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
@@ -96,15 +97,17 @@ static void writeRtcFromSystemTime(Device* rtc) {
|
||||
}
|
||||
}
|
||||
|
||||
void RtcTimeService::onTimeChanged(kernel::SystemEvent event) {
|
||||
if (event == kernel::SystemEvent::Time) {
|
||||
Device* rtc = findRtcDevice();
|
||||
if (rtc) {
|
||||
writeRtcFromSystemTime(rtc);
|
||||
}
|
||||
void RtcTimeService::onTimeChanged() {
|
||||
Device* rtc = findRtcDevice();
|
||||
if (rtc) {
|
||||
writeRtcFromSystemTime(rtc);
|
||||
}
|
||||
}
|
||||
|
||||
void RtcTimeService::onTimeChangedTrampoline(struct SystemEvent* /*event*/, void* context) {
|
||||
static_cast<RtcTimeService*>(context)->onTimeChanged();
|
||||
}
|
||||
|
||||
bool RtcTimeService::onStart(ServiceContext& serviceContext) {
|
||||
Device* rtc = findRtcDevice();
|
||||
if (!rtc) {
|
||||
@@ -113,22 +116,21 @@ bool RtcTimeService::onStart(ServiceContext& serviceContext) {
|
||||
}
|
||||
|
||||
if (setSystemTimeFromRtc(rtc)) {
|
||||
// Publish time event so other components know time is now valid
|
||||
kernel::publishSystemEvent(kernel::SystemEvent::Time);
|
||||
// Emit time event so other components know time is now valid
|
||||
system_event_emit(KERNEL_EVENT_TIME_CHANGED, nullptr, 0);
|
||||
}
|
||||
|
||||
timeEventSubscription = kernel::subscribeSystemEvent(
|
||||
kernel::SystemEvent::Time,
|
||||
[this](kernel::SystemEvent event) { onTimeChanged(event); }
|
||||
);
|
||||
if (system_event_subscribe(KERNEL_EVENT_TIME_CHANGED, &RtcTimeService::onTimeChangedTrampoline, this) == ERROR_NONE) {
|
||||
timeEventSubscribed = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RtcTimeService::onStop(ServiceContext& serviceContext) {
|
||||
if (timeEventSubscription != 0) {
|
||||
kernel::unsubscribeSystemEvent(timeEventSubscription);
|
||||
timeEventSubscription = 0;
|
||||
if (timeEventSubscribed) {
|
||||
system_event_unsubscribe(KERNEL_EVENT_TIME_CHANGED, &RtcTimeService::onTimeChangedTrampoline);
|
||||
timeEventSubscribed = false;
|
||||
}
|
||||
|
||||
if (rtcDevice) {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <Tactility/CoreDefines.h>
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/RecursiveMutex.h>
|
||||
#include <Tactility/SystemEvents.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/service/Service.h>
|
||||
@@ -16,6 +15,7 @@
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/wifi.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/system_event.h>
|
||||
#include <tactility/time.h>
|
||||
#include <tactility/wifi_auto_scan.h>
|
||||
|
||||
@@ -78,7 +78,7 @@ struct WifiServiceState {
|
||||
uint16_t scanRecordLimit = TT_WIFI_SCAN_RECORD_LIMIT;
|
||||
TickType_t lastScanTime = MAX_TICKS;
|
||||
std::unique_ptr<Timer> autoConnectTimer;
|
||||
kernel::SystemEventSubscription bootEventSubscription = kernel::NoSystemEventSubscription;
|
||||
bool bootEventSubscribed = false;
|
||||
};
|
||||
|
||||
WifiServiceState state;
|
||||
@@ -278,7 +278,7 @@ void onAutoConnectTimer() {
|
||||
|
||||
// ---- Kernel driver event bridge ----
|
||||
|
||||
void onWifiDeviceEvent(Device* /*device*/, void* /*context*/, ::WifiEvent event) {
|
||||
void onWifiDeviceEvent(Device* device, void* /*context*/, ::WifiEvent event) {
|
||||
switch (event.type) {
|
||||
case WIFI_EVENT_TYPE_SCAN_FINISHED:
|
||||
getMainDispatcher().dispatch([] { dispatchAutoConnect(); });
|
||||
@@ -291,7 +291,8 @@ void onWifiDeviceEvent(Device* /*device*/, void* /*context*/, ::WifiEvent event)
|
||||
// Resetting it on every disconnect (including deliberate ones) would
|
||||
// let auto-connect immediately reconnect the user. Attempts that fail
|
||||
// while pending are unpaused via WIFI_EVENT_TYPE_STATION_CONNECTION_RESULT below.
|
||||
kernel::publishSystemEvent(kernel::SystemEvent::NetworkDisconnected);
|
||||
NetworkDisconnectedEvent disconnected_event = { .device = device };
|
||||
system_event_emit(KERNEL_EVENT_NETWORK_DISCONNECTED, &disconnected_event, sizeof(disconnected_event));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -319,7 +320,6 @@ void onWifiDeviceEvent(Device* /*device*/, void* /*context*/, ::WifiEvent event)
|
||||
if (remember && !settings::save(target)) {
|
||||
LOG_E(TAG, "Failed to store credentials");
|
||||
}
|
||||
kernel::publishSystemEvent(kernel::SystemEvent::NetworkConnected);
|
||||
} else {
|
||||
// The pending connection attempt (which paused auto-connect via connect())
|
||||
// failed; unpause so auto-connect can try other saved APs.
|
||||
@@ -492,6 +492,10 @@ std::string getIp() {
|
||||
|
||||
namespace {
|
||||
|
||||
void onBootCompleted(struct SystemEvent* /*event*/, void* /*context*/) {
|
||||
bootSplashInit();
|
||||
}
|
||||
|
||||
class WifiService final : public Service {
|
||||
|
||||
public:
|
||||
@@ -506,9 +510,9 @@ public:
|
||||
LOG_W(TAG, "No WiFi device found");
|
||||
}
|
||||
|
||||
state.bootEventSubscription = kernel::subscribeSystemEvent(kernel::SystemEvent::BootSplash, [](auto) {
|
||||
bootSplashInit();
|
||||
});
|
||||
if (system_event_subscribe(KERNEL_EVENT_BOOT_COMPLETED, onBootCompleted, nullptr) == ERROR_NONE) {
|
||||
state.bootEventSubscribed = true;
|
||||
}
|
||||
|
||||
auto timer_interval = std::min(2000, AUTO_SCAN_INTERVAL);
|
||||
state.autoConnectTimer = std::make_unique<Timer>(Timer::Type::Periodic, timer_interval, [] { onAutoConnectTimer(); });
|
||||
@@ -526,8 +530,10 @@ public:
|
||||
state.autoConnectTimer->stop();
|
||||
state.autoConnectTimer = nullptr; // Must release as it holds a reference via its callback.
|
||||
|
||||
kernel::unsubscribeSystemEvent(state.bootEventSubscription);
|
||||
state.bootEventSubscription = kernel::NoSystemEventSubscription;
|
||||
if (state.bootEventSubscribed) {
|
||||
system_event_unsubscribe(KERNEL_EVENT_BOOT_COMPLETED, onBootCompleted);
|
||||
state.bootEventSubscribed = false;
|
||||
}
|
||||
|
||||
if (state.device != nullptr && device_is_ready(state.device)) {
|
||||
wifi_remove_event_callback(state.device, onWifiDeviceEvent);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include <Tactility/settings/Time.h>
|
||||
|
||||
#include <Tactility/SystemEvents.h>
|
||||
#include <Tactility/Preferences.h>
|
||||
#include <Tactility/settings/SystemSettings.h>
|
||||
|
||||
#include <tactility/system_event.h>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include <ctime>
|
||||
#endif
|
||||
@@ -36,7 +37,7 @@ void setTimeZone(const std::string& name, const std::string& code) {
|
||||
tzset();
|
||||
#endif
|
||||
|
||||
kernel::publishSystemEvent(kernel::SystemEvent::Time);
|
||||
system_event_emit(KERNEL_EVENT_TIME_CHANGED, nullptr, 0);
|
||||
}
|
||||
|
||||
std::string getTimeZoneName() {
|
||||
|
||||
Reference in New Issue
Block a user