Encapsulate Notification management in NotificationManager. It implement a static array of notifications to avoid dynamic allocation.

This commit is contained in:
JF 2020-03-28 19:05:28 +01:00
parent 68240704c7
commit baca0fc3e5
13 changed files with 105 additions and 116 deletions

View file

@ -223,6 +223,7 @@ list(APPEND SOURCE_FILES
BLE/BleManager.c BLE/BleManager.c
Components/Battery/BatteryController.cpp Components/Battery/BatteryController.cpp
Components/Ble/BleController.cpp Components/Ble/BleController.cpp
Components/Ble/NotificationManager.cpp
Components/DateTime/DateTimeController.cpp Components/DateTime/DateTimeController.cpp
Components/Brightness/BrightnessController.cpp Components/Brightness/BrightnessController.cpp
drivers/Cst816s.cpp drivers/Cst816s.cpp
@ -264,6 +265,7 @@ set(INCLUDE_FILES
BLE/BleManager.h BLE/BleManager.h
Components/Battery/BatteryController.h Components/Battery/BatteryController.h
Components/Ble/BleController.h Components/Ble/BleController.h
Components/Ble/NotificationManager.h
Components/DateTime/DateTimeController.h Components/DateTime/DateTimeController.h
Components/Brightness/BrightnessController.h Components/Brightness/BrightnessController.h
drivers/Cst816s.h drivers/Cst816s.h

View file

@ -4,10 +4,6 @@
using namespace Pinetime::Controllers; using namespace Pinetime::Controllers;
Ble::Ble() {
notificationQueue = xQueueCreate(10, sizeof(NotificationMessage));
}
void Ble::Connect() { void Ble::Connect() {
isConnected = true; isConnected = true;
} }
@ -16,24 +12,4 @@ void Ble::Disconnect() {
isConnected = false; isConnected = false;
} }
void Ble::PushNotification(const char *message, uint8_t size) {
char* messageCopy = static_cast<char *>(malloc(sizeof(char) * size));
std::memcpy(messageCopy, message, size);
NotificationMessage msg;
msg.size = size;
msg.message = messageCopy;
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(notificationQueue, &msg, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) {
/* Actual macro used here is port specific. */
// TODO : should I do something here?
}
}
bool Ble::PopNotification(Ble::NotificationMessage& msg) {
return xQueueReceive(notificationQueue, &msg, 0) != 0;
}

View file

@ -7,22 +7,13 @@ namespace Pinetime {
namespace Controllers { namespace Controllers {
class Ble { class Ble {
public: public:
struct NotificationMessage {
uint8_t size = 0;
const char* message = nullptr;
};
Ble(); Ble() = default;
bool IsConnected() const {return isConnected;} bool IsConnected() const {return isConnected;}
void Connect(); void Connect();
void Disconnect(); void Disconnect();
void PushNotification(const char* message, uint8_t size);
bool PopNotification(NotificationMessage& msg);
private: private:
bool isConnected = false; bool isConnected = false;
QueueHandle_t notificationQueue;
}; };
} }

View file

@ -0,0 +1,29 @@
#include <cstring>
#include "NotificationManager.h"
using namespace Pinetime::Controllers;
void NotificationManager::Push(Pinetime::Controllers::NotificationManager::Categories category,
const char *message, uint8_t messageSize) {
// TODO handle edge cases on read/write index
auto& notif = notifications[writeIndex];
std::memcpy(notif.message.data(), message, messageSize);
notif.message[messageSize] = '\0';
notif.category = category;
writeIndex = (writeIndex + 1 < TotalNbNotifications) ? writeIndex + 1 : 0;
if(!empty && writeIndex == readIndex)
readIndex = writeIndex + 1;
}
NotificationManager::Notification Pinetime::Controllers::NotificationManager::Pop() {
// TODO handle edge cases on read/write index
NotificationManager::Notification notification = notifications[readIndex];
if(readIndex != writeIndex) {
readIndex = (readIndex + 1 < TotalNbNotifications) ? readIndex + 1 : 0;
}
// TODO Check move optimization on return
return notification;
}

View file

@ -0,0 +1,29 @@
#pragma once
#include <array>
namespace Pinetime {
namespace Controllers {
class NotificationManager {
public:
enum class Categories {Unknown, SimpleAlert, Email, News, IncomingCall, MissedCall, Sms, VoiceMail, Schedule, HighProriotyAlert, InstantMessage };
static constexpr uint8_t MessageSize = 18;
struct Notification {
std::array<char, MessageSize> message;
Categories category = Categories::Unknown;
};
void Push(Categories category, const char* message, uint8_t messageSize);
Notification Pop();
private:
static constexpr uint8_t TotalNbNotifications = 5;
std::array<Notification, TotalNbNotifications> notifications;
uint8_t readIndex = 0;
uint8_t writeIndex = 0;
bool empty = true;
};
}
}

View file

@ -15,18 +15,16 @@
#include <DisplayApp/Screens/Gauge.h> #include <DisplayApp/Screens/Gauge.h>
#include <DisplayApp/Screens/Brightness.h> #include <DisplayApp/Screens/Brightness.h>
#include <DisplayApp/Screens/ScreenList.h> #include <DisplayApp/Screens/ScreenList.h>
#include <Components/Ble/NotificationManager.h>
#include "../SystemTask/SystemTask.h" #include "../SystemTask/SystemTask.h"
using namespace Pinetime::Applications; using namespace Pinetime::Applications;
DisplayApp::DisplayApp(Pinetime::Drivers::St7789& lcd, DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Drivers::Cst816S &touchPanel,
Pinetime::Components::LittleVgl& lvgl, Controllers::Battery &batteryController, Controllers::Ble &bleController,
Pinetime::Drivers::Cst816S& touchPanel, Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog,
Controllers::Battery &batteryController, System::SystemTask &systemTask,
Controllers::Ble &bleController, Pinetime::Controllers::NotificationManager& notificationManager) :
Controllers::DateTime &dateTimeController,
Pinetime::Drivers::WatchdogView& watchdog,
Pinetime::System::SystemTask& systemTask) :
lcd{lcd}, lcd{lcd},
lvgl{lvgl}, lvgl{lvgl},
batteryController{batteryController}, batteryController{batteryController},
@ -35,7 +33,8 @@ DisplayApp::DisplayApp(Pinetime::Drivers::St7789& lcd,
watchdog{watchdog}, watchdog{watchdog},
touchPanel{touchPanel}, touchPanel{touchPanel},
currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController) }, currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController) },
systemTask{systemTask} { systemTask{systemTask},
notificationManager{notificationManager} {
msgQueue = xQueueCreate(queueSize, itemSize); msgQueue = xQueueCreate(queueSize, itemSize);
onClockApp = true; onClockApp = true;
modal.reset(new Screens::Modal(this)); modal.reset(new Screens::Modal(this));
@ -113,12 +112,8 @@ void DisplayApp::Refresh() {
// clockScreen.SetBatteryPercentRemaining(batteryController.PercentRemaining()); // clockScreen.SetBatteryPercentRemaining(batteryController.PercentRemaining());
break; break;
case Messages::NewNotification: { case Messages::NewNotification: {
Pinetime::Controllers::Ble::NotificationMessage notificationMessage; auto notification = notificationManager.Pop();
if (bleController.PopNotification(notificationMessage)) { modal->Show(notification.message.data());
std::string m {notificationMessage.message, notificationMessage.size};
modal->Show(m);
// TODO delete message
}
} }
break; break;
case Messages::TouchEvent: { case Messages::TouchEvent: {

View file

@ -17,6 +17,7 @@
#include <DisplayApp/Screens/Clock.h> #include <DisplayApp/Screens/Clock.h>
#include <drivers/Watchdog.h> #include <drivers/Watchdog.h>
#include <DisplayApp/Screens/Modal.h> #include <DisplayApp/Screens/Modal.h>
#include <Components/Ble/NotificationManager.h>
#include "TouchEvents.h" #include "TouchEvents.h"
@ -34,14 +35,11 @@ namespace Pinetime {
enum class FullRefreshDirections { None, Up, Down }; enum class FullRefreshDirections { None, Up, Down };
DisplayApp(Pinetime::Drivers::St7789& lcd, DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Drivers::Cst816S &,
Pinetime::Components::LittleVgl& lvgl, Controllers::Battery &batteryController, Controllers::Ble &bleController,
Pinetime::Drivers::Cst816S&, Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog,
Controllers::Battery &batteryController, System::SystemTask &systemTask,
Controllers::Ble &bleController, Pinetime::Controllers::NotificationManager& notificationManager);
Controllers::DateTime& dateTimeController,
Pinetime::Drivers::WatchdogView& watchdog,
Pinetime::System::SystemTask& systemTask);
void Start(); void Start();
void PushMessage(Messages msg); void PushMessage(Messages msg);
@ -82,7 +80,7 @@ namespace Pinetime {
bool onClockApp = false; // TODO find a better way to know that we should handle gestures and button differently for the Clock app. bool onClockApp = false; // TODO find a better way to know that we should handle gestures and button differently for the Clock app.
Controllers::BrightnessController brightnessController; Controllers::BrightnessController brightnessController;
std::unique_ptr<Screens::Modal> modal; std::unique_ptr<Screens::Modal> modal;
Pinetime::Controllers::NotificationManager& notificationManager;
}; };
} }
} }

View file

@ -25,42 +25,6 @@ bool Modal::OnButtonPushed() {
return true; return true;
} }
void Modal::Show() {
if(isVisible) return;
isVisible = true;
lv_style_copy(&modal_style, &lv_style_plain_color);
modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK;
modal_style.body.opa = LV_OPA_50;
obj = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(obj, &modal_style);
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_HOR_RES, LV_VER_RES);
lv_obj_set_opa_scale_enable(obj, true); /* Enable opacity scaling for the animation */
static const char * btns2[] = {"Ok", ""};
/* Create the message box as a child of the modal background */
mbox = lv_mbox_create(obj, NULL);
lv_mbox_add_btns(mbox, btns2);
char versionStr[20];
sprintf(versionStr, "VERSION: %d.%d.%d", Version::Major(), Version::Minor(), Version::Patch());
lv_mbox_set_text(mbox, versionStr);
// lv_mbox_set_text(mbox, "Hello world!");
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_event_cb(mbox, Modal::mbox_event_cb);
mbox->user_data = this;
/* Fade the message box in with an animation */
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_time(&a, 500, 0);
lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER);
lv_anim_set_exec_cb(&a, obj, (lv_anim_exec_xcb_t)lv_obj_set_opa_scale);
lv_anim_create(&a);
}
void Modal::Hide() { void Modal::Hide() {
/* Delete the parent modal background */ /* Delete the parent modal background */
lv_obj_del_async(lv_obj_get_parent(mbox)); lv_obj_del_async(lv_obj_get_parent(mbox));
@ -83,9 +47,8 @@ void Modal::OnEvent(lv_obj_t *event_obj, lv_event_t evt) {
} }
} }
void Modal::Show(const std::string& message) { void Modal::Show(const char* msg) {
if(isVisible) return; if(isVisible) return;
this->message = message;
isVisible = true; isVisible = true;
lv_style_copy(&modal_style, &lv_style_plain_color); lv_style_copy(&modal_style, &lv_style_plain_color);
modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK; modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK;
@ -102,7 +65,7 @@ void Modal::Show(const std::string& message) {
/* Create the message box as a child of the modal background */ /* Create the message box as a child of the modal background */
mbox = lv_mbox_create(obj, NULL); mbox = lv_mbox_create(obj, NULL);
lv_mbox_add_btns(mbox, btns2); lv_mbox_add_btns(mbox, btns2);
lv_mbox_set_text(mbox, message.data()); lv_mbox_set_text(mbox, msg);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_event_cb(mbox, Modal::mbox_event_cb); lv_obj_set_event_cb(mbox, Modal::mbox_event_cb);

View file

@ -22,8 +22,7 @@ namespace Pinetime {
Modal(DisplayApp* app); Modal(DisplayApp* app);
~Modal() override; ~Modal() override;
void Show(); void Show(const char* msg);
void Show(const std::string& message);
void Hide(); void Hide();
bool Refresh() override; bool Refresh() override;
@ -39,7 +38,6 @@ namespace Pinetime {
lv_obj_t *info; lv_obj_t *info;
bool running = true; bool running = true;
bool isVisible = false; bool isVisible = false;
std::string message;
}; };
} }

View file

@ -123,7 +123,9 @@ void Tile::OnObjectEvent(lv_obj_t *obj, lv_event_t event, uint32_t buttonId) {
tile->StartClockApp(); tile->StartClockApp();
break; break;
case 3: case 3:
modal->Show(); char versionStr[20];
sprintf(versionStr, "VERSION: %d.%d.%d", Version::Major(), Version::Minor(), Version::Patch());
modal->Show(versionStr);
break; break;
case 4: case 4:
tile->StartSysInfoApp(); tile->StartSysInfoApp();

View file

@ -5,17 +5,19 @@
#include <hal/nrf_rtc.h> #include <hal/nrf_rtc.h>
#include <BLE/BleManager.h> #include <BLE/BleManager.h>
#include <softdevice/common/nrf_sdh_freertos.h> #include <softdevice/common/nrf_sdh_freertos.h>
#include <Components/Ble/NotificationManager.h>
#include "SystemTask.h" #include "SystemTask.h"
#include "../main.h" #include "../main.h"
using namespace Pinetime::System; using namespace Pinetime::System;
SystemTask::SystemTask(Pinetime::Drivers::SpiMaster &spi, Pinetime::Drivers::St7789 &lcd, SystemTask::SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd, Drivers::Cst816S &touchPanel,
Pinetime::Drivers::Cst816S &touchPanel, Pinetime::Components::LittleVgl &lvgl, Components::LittleVgl &lvgl,
Pinetime::Controllers::Battery &batteryController, Pinetime::Controllers::Ble &bleController, Controllers::Battery &batteryController, Controllers::Ble &bleController,
Pinetime::Controllers::DateTime& dateTimeController) : Controllers::DateTime &dateTimeController,
Pinetime::Controllers::NotificationManager& notificationManager) :
spi{spi}, lcd{lcd}, touchPanel{touchPanel}, lvgl{lvgl}, batteryController{batteryController}, spi{spi}, lcd{lcd}, touchPanel{touchPanel}, lvgl{lvgl}, batteryController{batteryController},
bleController{bleController}, dateTimeController{dateTimeController}, bleController{bleController}, dateTimeController{dateTimeController},
watchdog{}, watchdogView{watchdog}{ watchdog{}, watchdogView{watchdog}, notificationManager{notificationManager} {
systemTaksMsgQueue = xQueueCreate(10, 1); systemTaksMsgQueue = xQueueCreate(10, 1);
} }
@ -44,7 +46,8 @@ void SystemTask::Work() {
touchPanel.Init(); touchPanel.Init();
batteryController.Init(); batteryController.Init();
displayApp.reset(new Pinetime::Applications::DisplayApp(lcd, lvgl, touchPanel, batteryController, bleController, dateTimeController, watchdogView, *this)); displayApp.reset(new Pinetime::Applications::DisplayApp(lcd, lvgl, touchPanel, batteryController, bleController,
dateTimeController, watchdogView, *this, notificationManager));
displayApp->Start(); displayApp->Start();
batteryController.Update(); batteryController.Update();

View file

@ -16,13 +16,11 @@ namespace Pinetime {
enum class Messages {GoToSleep, GoToRunning, OnNewTime, OnNewNotification enum class Messages {GoToSleep, GoToRunning, OnNewTime, OnNewNotification
}; };
SystemTask(Pinetime::Drivers::SpiMaster& spi, SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd, Drivers::Cst816S &touchPanel,
Pinetime::Drivers::St7789& lcd, Components::LittleVgl &lvgl,
Pinetime::Drivers::Cst816S& touchPanel, Controllers::Battery &batteryController, Controllers::Ble &bleController,
Pinetime::Components::LittleVgl& lvgl, Controllers::DateTime &dateTimeController,
Pinetime::Controllers::Battery& batteryController, Pinetime::Controllers::NotificationManager& manager);
Pinetime::Controllers::Ble& bleController,
Pinetime::Controllers::DateTime& dateTimeController);
void Start(); void Start();
@ -45,6 +43,7 @@ namespace Pinetime {
bool isSleeping = false; bool isSleeping = false;
Pinetime::Drivers::Watchdog watchdog; Pinetime::Drivers::Watchdog watchdog;
Pinetime::Drivers::WatchdogView watchdogView; Pinetime::Drivers::WatchdogView watchdogView;
Pinetime::Controllers::NotificationManager& notificationManager;
static constexpr uint8_t pinSpiSck = 2; static constexpr uint8_t pinSpiSck = 2;

View file

@ -16,6 +16,7 @@
#include <drivers/SpiMaster.h> #include <drivers/SpiMaster.h>
#include <DisplayApp/LittleVgl.h> #include <DisplayApp/LittleVgl.h>
#include <SystemTask/SystemTask.h> #include <SystemTask/SystemTask.h>
#include <Components/Ble/NotificationManager.h>
#if NRF_LOG_ENABLED #if NRF_LOG_ENABLED
#include "Logging/NrfLogger.h" #include "Logging/NrfLogger.h"
@ -55,6 +56,8 @@ void ble_manager_set_ble_disconnection_callback(void (*disconnection)());
static constexpr uint8_t pinTouchIrq = 28; static constexpr uint8_t pinTouchIrq = 28;
std::unique_ptr<Pinetime::System::SystemTask> systemTask; std::unique_ptr<Pinetime::System::SystemTask> systemTask;
Pinetime::Controllers::NotificationManager notificationManager;
void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
if(pin == pinTouchIrq) { if(pin == pinTouchIrq) {
systemTask->OnTouchEvent(); systemTask->OnTouchEvent();
@ -86,7 +89,7 @@ void OnBleDisconnection() {
} }
void OnNewNotification(const char* message, uint8_t size) { void OnNewNotification(const char* message, uint8_t size) {
bleController.PushNotification(message, size); notificationManager.Push(Pinetime::Controllers::NotificationManager::Categories::SimpleAlert, message, size);
systemTask->PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification); systemTask->PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification);
} }
@ -128,7 +131,8 @@ int main(void) {
debounceTimer = xTimerCreate ("debounceTimer", 200, pdFALSE, (void *) 0, DebounceTimerCallback); debounceTimer = xTimerCreate ("debounceTimer", 200, pdFALSE, (void *) 0, DebounceTimerCallback);
systemTask.reset(new Pinetime::System::SystemTask(spi, lcd, touchPanel, lvgl, batteryController, bleController, dateTimeController)); systemTask.reset(new Pinetime::System::SystemTask(spi, lcd, touchPanel, lvgl, batteryController, bleController,
dateTimeController, notificationManager));
systemTask->Start(); systemTask->Start();
ble_manager_init(); ble_manager_init();