Various services improved (#110)
This commit is contained in:
committed by
GitHub
parent
36bb25deba
commit
d52fe52d96
@@ -140,10 +140,10 @@ public:
|
||||
|
||||
struct Loader {
|
||||
Thread* thread;
|
||||
PubSub* pubsub_internal;
|
||||
PubSub* pubsub_external;
|
||||
std::shared_ptr<PubSub> pubsub_internal = std::make_shared<PubSub>();
|
||||
std::shared_ptr<PubSub> pubsub_external = std::make_shared<PubSub>();
|
||||
MessageQueue queue = MessageQueue(2, sizeof(LoaderMessage)); // 2 entries, so you can stop the current app while starting a new one without blocking
|
||||
Mutex* mutex;
|
||||
Mutex mutex = Mutex(MutexTypeRecursive);
|
||||
std::stack<app::AppInstance*> app_stack;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <Dispatcher.h>
|
||||
#include "Tactility.h"
|
||||
|
||||
#include "app/ManifestRegistry.h"
|
||||
@@ -127,7 +128,7 @@ static void register_and_start_user_services(const service::ServiceManifest* con
|
||||
}
|
||||
}
|
||||
|
||||
void init(const Configuration& config) {
|
||||
void run(const Configuration& config) {
|
||||
TT_LOG_I(TAG, "init started");
|
||||
|
||||
tt_assert(config.hardware);
|
||||
@@ -160,6 +161,11 @@ void init(const Configuration& config) {
|
||||
}
|
||||
|
||||
TT_LOG_I(TAG, "init complete");
|
||||
|
||||
TT_LOG_I(TAG, "Processing main dispatcher");
|
||||
while (true) {
|
||||
getMainDispatcher().consume(TtWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
const Configuration* _Nullable getConfiguration() {
|
||||
|
||||
@@ -19,7 +19,7 @@ typedef struct {
|
||||
* Attempts to initialize Tactility and all configured hardware.
|
||||
* @param config
|
||||
*/
|
||||
void init(const Configuration& config);
|
||||
void run(const Configuration& config);
|
||||
|
||||
/**
|
||||
* While technically nullable, this instance is always set if tt_init() succeeds.
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace tt::app::power {
|
||||
#define TAG "power"
|
||||
|
||||
extern const AppManifest manifest;
|
||||
static void on_timer(TT_UNUSED void* context);
|
||||
static void on_timer(TT_UNUSED std::shared_ptr<void> context);
|
||||
|
||||
struct Data {
|
||||
std::unique_ptr<Timer> update_timer = std::unique_ptr<Timer>(new Timer(Timer::TypePeriodic, &on_timer, nullptr));
|
||||
|
||||
@@ -54,7 +54,7 @@ static void onConnect(const service::wifi::settings::WifiApSettings* ap_settings
|
||||
}
|
||||
|
||||
WifiConnect::WifiConnect() {
|
||||
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
||||
auto wifi_pubsub = service::wifi::getPubsub();
|
||||
wifiSubscription = tt_pubsub_subscribe(wifi_pubsub, &eventCallback, this);
|
||||
bindings = (Bindings) {
|
||||
.onConnectSsid = onConnect,
|
||||
@@ -63,7 +63,7 @@ WifiConnect::WifiConnect() {
|
||||
}
|
||||
|
||||
WifiConnect::~WifiConnect() {
|
||||
PubSub* pubsub = service::wifi::getPubsub();
|
||||
auto pubsub = service::wifi::getPubsub();
|
||||
tt_pubsub_unsubscribe(pubsub, wifiSubscription);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ static void wifiManageEventCallback(const void* message, void* context) {
|
||||
}
|
||||
|
||||
void WifiManage::onShow(AppContext& app, lv_obj_t* parent) {
|
||||
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
||||
auto wifi_pubsub = service::wifi::getPubsub();
|
||||
wifiSubscription = tt_pubsub_subscribe(wifi_pubsub, &wifiManageEventCallback, this);
|
||||
|
||||
// State update (it has its own locking)
|
||||
@@ -128,6 +128,7 @@ void WifiManage::onShow(AppContext& app, lv_obj_t* parent) {
|
||||
bool can_scan = radio_state == service::wifi::WIFI_RADIO_ON ||
|
||||
radio_state == service::wifi::WIFI_RADIO_CONNECTION_PENDING ||
|
||||
radio_state == service::wifi::WIFI_RADIO_CONNECTION_ACTIVE;
|
||||
TT_LOG_I(TAG, "%d %d", radio_state, service::wifi::isScanning());
|
||||
if (can_scan && !service::wifi::isScanning()) {
|
||||
service::wifi::scan();
|
||||
}
|
||||
@@ -135,7 +136,7 @@ void WifiManage::onShow(AppContext& app, lv_obj_t* parent) {
|
||||
|
||||
void WifiManage::onHide(TT_UNUSED AppContext& app) {
|
||||
lock();
|
||||
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
||||
auto wifi_pubsub = service::wifi::getPubsub();
|
||||
tt_pubsub_unsubscribe(wifi_pubsub, wifiSubscription);
|
||||
wifiSubscription = nullptr;
|
||||
isViewEnabled = false;
|
||||
|
||||
@@ -22,7 +22,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
Mutex* mutex;
|
||||
PubSub* pubsub;
|
||||
std::shared_ptr<PubSub> pubsub;
|
||||
StatusbarIcon icons[STATUSBAR_ICON_LIMIT];
|
||||
} StatusbarData;
|
||||
|
||||
@@ -40,7 +40,7 @@ typedef struct {
|
||||
|
||||
static void statusbar_init() {
|
||||
statusbar_data.mutex = tt_mutex_alloc(MutexTypeRecursive);
|
||||
statusbar_data.pubsub = tt_pubsub_alloc();
|
||||
statusbar_data.pubsub = std::make_shared<PubSub>();
|
||||
for (int i = 0; i < STATUSBAR_ICON_LIMIT; i++) {
|
||||
statusbar_data.icons[i].image = nullptr;
|
||||
statusbar_data.icons[i].visible = false;
|
||||
|
||||
@@ -29,38 +29,30 @@ static Loader* loader_singleton = nullptr;
|
||||
static Loader* loader_alloc() {
|
||||
assert(loader_singleton == nullptr);
|
||||
loader_singleton = new Loader();
|
||||
loader_singleton->pubsub_internal = tt_pubsub_alloc();
|
||||
loader_singleton->pubsub_external = tt_pubsub_alloc();
|
||||
loader_singleton->thread = new Thread(
|
||||
"loader",
|
||||
4096, // Last known minimum was 2400 for starting Hello World app
|
||||
&loader_main,
|
||||
nullptr
|
||||
);
|
||||
loader_singleton->mutex = tt_mutex_alloc(MutexTypeRecursive);
|
||||
return loader_singleton;
|
||||
}
|
||||
|
||||
static void loader_free() {
|
||||
tt_assert(loader_singleton != nullptr);
|
||||
delete loader_singleton->thread;
|
||||
tt_pubsub_free(loader_singleton->pubsub_internal);
|
||||
tt_pubsub_free(loader_singleton->pubsub_external);
|
||||
tt_mutex_free(loader_singleton->mutex);
|
||||
delete loader_singleton;
|
||||
loader_singleton = nullptr;
|
||||
}
|
||||
|
||||
static void loader_lock() {
|
||||
tt_assert(loader_singleton);
|
||||
tt_assert(loader_singleton->mutex);
|
||||
tt_check(tt_mutex_acquire(loader_singleton->mutex, TtWaitForever) == TtStatusOk);
|
||||
tt_check(loader_singleton->mutex.acquire(TtWaitForever) == TtStatusOk);
|
||||
}
|
||||
|
||||
static void loader_unlock() {
|
||||
tt_assert(loader_singleton);
|
||||
tt_assert(loader_singleton->mutex);
|
||||
tt_check(tt_mutex_release(loader_singleton->mutex) == TtStatusOk);
|
||||
tt_check(loader_singleton->mutex.release() == TtStatusOk);
|
||||
}
|
||||
|
||||
LoaderStatus startApp(const std::string& id, bool blocking, std::shared_ptr<const Bundle> parameters) {
|
||||
@@ -107,7 +99,7 @@ app::AppContext* _Nullable getCurrentApp() {
|
||||
return dynamic_cast<app::AppContext*>(app);
|
||||
}
|
||||
|
||||
PubSub* getPubsub() {
|
||||
std::shared_ptr<PubSub> getPubsub() {
|
||||
tt_assert(loader_singleton);
|
||||
// it's safe to return pubsub without locking
|
||||
// because it's never freed and loader is never exited
|
||||
|
||||
@@ -37,6 +37,6 @@ app::AppContext* _Nullable getCurrentApp();
|
||||
/**
|
||||
* @brief PubSub for LoaderEvent
|
||||
*/
|
||||
PubSub* getPubsub();
|
||||
std::shared_ptr<PubSub> getPubsub();
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#include "Assets.h"
|
||||
#include "Mutex.h"
|
||||
#include "Timer.h"
|
||||
#include "Tactility.h"
|
||||
|
||||
#include "hal/Power.h"
|
||||
#include "hal/sdcard/Sdcard.h"
|
||||
#include "Mutex.h"
|
||||
#include "lvgl/Statusbar.h"
|
||||
#include "service/ServiceContext.h"
|
||||
#include "service/wifi/Wifi.h"
|
||||
#include "Tactility.h"
|
||||
#include "lvgl/Statusbar.h"
|
||||
#include "service/ServiceRegistry.h"
|
||||
|
||||
namespace tt::service::statusbar {
|
||||
@@ -16,8 +18,7 @@ extern const ServiceManifest manifest;
|
||||
|
||||
struct ServiceData {
|
||||
Mutex mutex;
|
||||
Thread thread;
|
||||
bool service_interrupted = false;
|
||||
std::unique_ptr<Timer> updateTimer;
|
||||
int8_t wifi_icon_id = lvgl::statusbar_icon_add(nullptr);
|
||||
const char* wifi_last_icon = nullptr;
|
||||
int8_t sdcard_icon_id = lvgl::statusbar_icon_add(nullptr);
|
||||
@@ -153,51 +154,35 @@ static void service_data_free(ServiceData* data) {
|
||||
free(data);
|
||||
}
|
||||
|
||||
int32_t serviceMain(TT_UNUSED void* parameter) {
|
||||
TT_LOG_I(TAG, "Started main loop");
|
||||
delay_ms(20); // TODO: Make service instance findable earlier on (but expose "starting" state?)
|
||||
auto context = tt::service::findServiceById(manifest.id);
|
||||
if (context == nullptr) {
|
||||
TT_LOG_E(TAG, "Service not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto data = std::static_pointer_cast<ServiceData>(context->getData());
|
||||
|
||||
while (!data->service_interrupted) {
|
||||
update_wifi_icon(data);
|
||||
update_sdcard_icon(data);
|
||||
update_power_icon(data);
|
||||
delay_ms(1000);
|
||||
}
|
||||
return 0;
|
||||
static void onUpdate(std::shared_ptr<void> parameter) {
|
||||
auto data = std::static_pointer_cast<ServiceData>(parameter);
|
||||
// TODO: Make thread-safe for LVGL
|
||||
update_wifi_icon(data);
|
||||
update_sdcard_icon(data);
|
||||
update_power_icon(data);
|
||||
}
|
||||
|
||||
static void onStart(ServiceContext& service) {
|
||||
auto data = std::make_shared<ServiceData>();
|
||||
service.setData(data);
|
||||
|
||||
// TODO: Make thread-safe for LVGL
|
||||
lvgl::statusbar_icon_set_visibility(data->wifi_icon_id, true);
|
||||
update_wifi_icon(data);
|
||||
update_sdcard_icon(data); // also updates visibility
|
||||
update_power_icon(data);
|
||||
|
||||
|
||||
data->thread.setCallback(serviceMain, nullptr);
|
||||
data->thread.setPriority(Thread::PriorityLow);
|
||||
data->thread.setStackSize(3000);
|
||||
data->thread.setName("statusbar");
|
||||
data->thread.start();
|
||||
data->updateTimer = std::make_unique<Timer>(Timer::TypePeriodic, onUpdate, data);
|
||||
// We want to try and scan more often in case of startup or scan lock failure
|
||||
data->updateTimer->start(1000);
|
||||
}
|
||||
|
||||
static void onStop(ServiceContext& service) {
|
||||
auto data = std::static_pointer_cast<ServiceData>(service.getData());
|
||||
|
||||
// Stop thread
|
||||
data->lock();
|
||||
data->service_interrupted = true;
|
||||
data->unlock();
|
||||
data->thread.join();
|
||||
data->updateTimer->stop();
|
||||
data->updateTimer = nullptr;
|
||||
}
|
||||
|
||||
extern const ServiceManifest manifest = {
|
||||
|
||||
Reference in New Issue
Block a user