M harmony_changelog.md => harmony_changelog.md +1 -0
@@ 14,6 14,7 @@
* Added gradual alarm volume increase
* Added progress bar for all volume control windows
* Improved factory reset procedure to remove user files
+* Added low battery notification on the home screen
### Changed / Improved
* Increased clock font in Relaxation, Meditation, Power nap mode
M image/system_a/data/lang/Deutsch.json => image/system_a/data/lang/Deutsch.json +3 -1
@@ 734,5 734,7 @@
"tethering_menu_access_decline": "<text>Tethering ist eingeschaltet.<br /><br />Schalten Sie Tethering aus,<br />um auf das Men\u00fc zuzugreifen</text>",
"tethering_phone_mode_change_prohibited": "<text>Tethering ist eingeschaltet.<br /><br />Andere Betriebsarten (Verbunden, DND,<br />Offline) werden von dieser Betriebsart \u00fcberlagert<br />und funktionieren nicht.</text>",
"tethering_turn_off_question": "Tethering ausschalten?",
- "unsaved_changes": "Ungespeicherte \u00c4nderungen"
+ "unsaved_changes": "Ungespeicherte \u00c4nderungen",
+ "battery_low": "Niedriger Batteriestand",
+ "battery_remaining": "<text><token>$BATTERY</token>% Batterie verbleibend</text>"
}
M image/system_a/data/lang/English.json => image/system_a/data/lang/English.json +3 -1
@@ 745,5 745,7 @@
"tethering_menu_access_decline": "<text>Tethering is on.<br /><br />To access menu,<br />turn tethering off.</text>",
"tethering_phone_mode_change_prohibited": "<text>Tethering is on.<br /><br />Other modes (Connected, DND,<br />Offline) are overriden by this mode<br />and are not working.</text>",
"tethering_turn_off_question": "Turn tethering off?",
- "unsaved_changes": "Unsaved changes"
+ "unsaved_changes": "Unsaved4 changes",
+ "battery_low": "Low battery",
+ "battery_remaining": "<text><token>$BATTERY</token>% battery remaining</text>"
}
M image/system_a/data/lang/Espanol.json => image/system_a/data/lang/Espanol.json +3 -1
@@ 734,5 734,7 @@
"tethering_menu_access_decline": "<text>El anclaje de red est\u00e1 activado.<br /><br />Para acceder al men\u00fa,<br />desactiva el tethering.</text>",
"tethering_phone_mode_change_prohibited": "<text>El anclaje de red est\u00e1 activado.<br /><br />Este modo anula otros modos (Conectado, No molestar,<br />Desconectado) <br />y hace que dejen de funcionar.</text>",
"tethering_turn_off_question": "\u00bfDesactivar el anclaje de red?",
- "unsaved_changes": "Cambios no guardados"
+ "unsaved_changes": "Cambios no guardados",
+ "battery_low": "Bater\u00EDa baja",
+ "battery_remaining": "<text>Queda un <token>$BATTERY</token>% de bater\u00EDa</text>"
}
M image/system_a/data/lang/Francais.json => image/system_a/data/lang/Francais.json +3 -1
@@ 705,5 705,7 @@
"tethering_menu_access_decline": "<text>Le partage de connexion est activ\u00e9.<br /><br />Pour acc\u00e9der au menu, veuillez<br />d\u00e9sactiver le partage de connextion.</text>",
"tethering_phone_mode_change_prohibited": "<text>Le partage de connexion est activ\u00e9.<br /><br />Ce mode-ci remplace et d\u00e9sactive les autres modes<br />(Connect\u00e9, NPD, Hors ligne)</text>",
"tethering_turn_off_question": "Voulez-vous d\u00e9sactiver le partage de connexion?",
- "unsaved_changes": "Modifications non enregistr\u00e9es"
+ "unsaved_changes": "Modifications non enregistr\u00e9es",
+ "battery_low": "Batterie faible",
+ "battery_remaining": "<text><token>$BATTERY</token>% de batterie restant</text>"
}
M image/system_a/data/lang/Polski.json => image/system_a/data/lang/Polski.json +3 -1
@@ 733,5 733,7 @@
"tethering_menu_access_decline": "<text>Tethering w\u0142\u0105czony.<br /><br />Aby przej\u015b\u0107 do menu,<br />wy\u0142\u0105cz tethering.</text>",
"tethering_phone_mode_change_prohibited": "<text>Tethering w\u0142\u0105czony.<br /><br />Ten tryb powoduje, \u017ce inne tryby (Po\u0142\u0105czony, Nie przeszkadza\u0107,<br />Offline) nie dzia\u0142aj\u0105.</text>",
"tethering_turn_off_question": "Wy\u0142\u0105czy\u0107 tethering?",
- "unsaved_changes": "Niezapisane zmiany"
+ "unsaved_changes": "Niezapisane zmiany",
+ "battery_low": "Niski poziom baterii",
+ "battery_remaining": "<text>Pozosta\u0142o <token>$BATTERY</token>% baterii</text>"
}
M products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp => products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp +19 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "include/application-bell-main/ApplicationBellMain.hpp"
@@ 104,11 104,18 @@ namespace app
return ret;
}
- timeModel = std::make_unique<app::TimeModel>();
- batteryModel = std::make_unique<app::BatteryModel>(this);
- temperatureModel = std::make_unique<app::home_screen::TemperatureModel>(this);
- homeScreenPresenter = std::make_shared<app::home_screen::HomeScreenPresenter>(
- this, *alarmModel, *batteryModel, *temperatureModel, *timeModel);
+ timeModel = std::make_unique<app::TimeModel>();
+ batteryModel = std::make_unique<app::BatteryModel>(this);
+ temperatureModel = std::make_unique<app::home_screen::TemperatureModel>(this);
+ userSessionModel = std::make_unique<app::UserSessionModel>(this);
+ batteryLevelNotificationModel = std::make_unique<app::BatteryLevelNotificationModel>();
+ homeScreenPresenter = std::make_shared<app::home_screen::HomeScreenPresenter>(this,
+ *alarmModel,
+ *batteryModel,
+ *temperatureModel,
+ *timeModel,
+ *userSessionModel,
+ *batteryLevelNotificationModel);
createUserInterface();
@@ 191,6 198,7 @@ namespace app
const auto newWindowName = msg->getWindowName();
if (newWindowName == gui::name::window::main_window) {
stopIdleTimer();
+ startUserSessionEndTimer();
}
else if (newWindowName == gui::window::name::bell_main_menu ||
newWindowName == gui::window::name::bell_main_menu_dialog ||
@@ 213,5 221,10 @@ namespace app
return true;
}
+ void ApplicationBellMain::startUserSessionEndTimer()
+ {
+ userSessionModel->deactivateUserSessionWithDelay();
+ }
+
ApplicationBellMain::~ApplicationBellMain() = default;
} // namespace app
M products/BellHybrid/apps/application-bell-main/include/application-bell-main/ApplicationBellMain.hpp => products/BellHybrid/apps/application-bell-main/include/application-bell-main/ApplicationBellMain.hpp +4 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 46,10 46,13 @@ namespace app
void onStart() override;
sys::MessagePointer handleSwitchWindow(sys::Message *msgl) override;
bool setHomeScreenLayout(std::string layoutName);
+ void startUserSessionEndTimer();
std::unique_ptr<AbstractTimeModel> timeModel;
std::unique_ptr<AbstractBatteryModel> batteryModel;
std::unique_ptr<home_screen::AbstractTemperatureModel> temperatureModel;
+ std::unique_ptr<AbstractUserSessionModel> userSessionModel;
+ std::unique_ptr<AbstractBatteryLevelNotificationModel> batteryLevelNotificationModel;
std::shared_ptr<app::home_screen::HomeScreenPresenter> homeScreenPresenter;
};
M products/BellHybrid/apps/application-bell-main/include/application-bell-main/presenters/HomeScreenPresenter.hpp => products/BellHybrid/apps/application-bell-main/include/application-bell-main/presenters/HomeScreenPresenter.hpp +25 -7
@@ 1,10 1,12 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <apps-common/BasePresenter.hpp>
#include <common/models/AbstractAlarmModel.hpp>
+#include <common/models/UserSessionModel.hpp>
+#include <common/models/BatteryLevelNotificationModel.hpp>
#include <common/layouts/BaseHomeScreenLayoutProvider.hpp>
#include <common/layouts/HomeScreenLayouts.hpp>
#include <gui/Common.hpp>
@@ 22,8 24,10 @@ namespace app
{
class AbstractTimeModel;
class AbstractBatteryModel;
+ class AbstractBatteryLevelNotificationModel;
class ApplicationCommon;
class TemperatureModel;
+ class AbstractUserSessionModel;
class ProgressTimerWithSnoozeTimer;
} // namespace app
@@ 97,8 101,13 @@ namespace app::home_screen
virtual void decAlarmMinute() = 0;
virtual void switchToMenu() = 0;
virtual void switchToBatteryStatus() = 0;
+ virtual void switchToLowBatteryWarning() = 0;
virtual UTF8 getGreeting() = 0;
virtual void setUSBStatusConnected() = 0;
+ virtual void handleLowBatteryWarning() = 0;
+ virtual bool isLowBatteryWarningNeeded() = 0;
+ virtual void updateBatteryLevelInterval() = 0;
+ virtual void refreshUserSession() = 0;
static constexpr auto defaultTimeout = std::chrono::milliseconds{5000};
};
@@ 110,7 119,9 @@ namespace app::home_screen
AbstractAlarmModel &alarmModel,
AbstractBatteryModel &batteryModel,
AbstractTemperatureModel &temperatureModel,
- AbstractTimeModel &timeModel);
+ AbstractTimeModel &timeModel,
+ AbstractUserSessionModel &userSessionModel,
+ AbstractBatteryLevelNotificationModel &batteryLevelNotificationModel);
virtual ~HomeScreenPresenter();
HomeScreenPresenter() = delete;
HomeScreenPresenter &operator=(const HomeScreenPresenter &oth) = delete;
@@ 140,11 151,16 @@ namespace app::home_screen
bool isAlarmActivatedByLatch() const override;
void setUSBStatusConnected() override;
- void incAlarmMinute();
- void decAlarmMinute();
- void switchToMenu();
- void switchToBatteryStatus();
- UTF8 getGreeting();
+ void incAlarmMinute() override;
+ void decAlarmMinute() override;
+ void switchToMenu() override;
+ void switchToBatteryStatus() override;
+ void switchToLowBatteryWarning() override;
+ UTF8 getGreeting() override;
+ void handleLowBatteryWarning() override;
+ bool isLowBatteryWarningNeeded() override;
+ void updateBatteryLevelInterval() override;
+ void refreshUserSession() override;
void setLayout(gui::LayoutGenerator layoutGenerator) override;
@@ 155,6 171,8 @@ namespace app::home_screen
AbstractBatteryModel &batteryModel;
AbstractTemperatureModel &temperatureModel;
AbstractTimeModel &timeModel;
+ AbstractUserSessionModel &userSessionModel;
+ AbstractBatteryLevelNotificationModel &batteryLevelNotificationModel;
std::unique_ptr<AbstractController> stateController;
std::unique_ptr<ProgressTimerWithSnoozeTimer> snoozeTimer;
std::unique_ptr<std::mt19937> rngEngine;
M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp => products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp +47 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "application-bell-main/presenters/HomeScreenPresenter.hpp"
@@ 75,9 75,13 @@ namespace app::home_screen
AbstractAlarmModel &alarmModel,
AbstractBatteryModel &batteryModel,
AbstractTemperatureModel &temperatureModel,
- AbstractTimeModel &timeModel)
- : app{app}, alarmModel{alarmModel}, batteryModel{batteryModel}, temperatureModel{temperatureModel},
- timeModel{timeModel}, rngEngine{std::make_unique<std::mt19937>(bsp::trng::getRandomValue())}
+ AbstractTimeModel &timeModel,
+ AbstractUserSessionModel &userSessionModel,
+ AbstractBatteryLevelNotificationModel &batteryLevelNotificationModel)
+ : app{app}, alarmModel{alarmModel}, batteryModel{batteryModel},
+ temperatureModel{temperatureModel}, timeModel{timeModel}, userSessionModel{userSessionModel},
+ batteryLevelNotificationModel{batteryLevelNotificationModel}, rngEngine{std::make_unique<std::mt19937>(
+ bsp::trng::getRandomValue())}
{}
gui::RefreshModes HomeScreenPresenter::handleUpdateTimeEvent()
@@ 131,8 135,8 @@ namespace app::home_screen
}
void HomeScreenPresenter::createData()
{
- stateController =
- std::make_unique<StateController>(*getView(), *this, batteryModel, temperatureModel, alarmModel, timeModel);
+ stateController = std::make_unique<StateController>(
+ *getView(), *this, batteryModel, temperatureModel, alarmModel, timeModel, userSessionModel);
}
void HomeScreenPresenter::refreshWindow()
@@ 250,6 254,13 @@ namespace app::home_screen
std::make_unique<gui::BellBatteryStatusWindow::Data>(getBatteryLvl(), isBatteryCharging()));
}
+ void HomeScreenPresenter::switchToLowBatteryWarning()
+ {
+ app->switchWindow(
+ gui::BellBatteryStatusWindow::name,
+ std::make_unique<gui::BellBatteryStatusWindow::Data>(getBatteryLvl(), isBatteryCharging(), true));
+ }
+
UTF8 HomeScreenPresenter::getGreeting()
{
const auto greetingCollection = utils::translate_array("app_bell_greeting_msg");
@@ 267,4 278,34 @@ namespace app::home_screen
getView()->setUSBStatusConnected();
}
+ bool HomeScreenPresenter::isLowBatteryWarningNeeded()
+ {
+ batteryLevelNotificationModel.updateBatteryLevelInterval(getBatteryLvl());
+ return !userSessionModel.isActiveUserSessionHandled() &&
+ !batteryLevelNotificationModel.isBatteryIntervalHandled() && !isBatteryCharging();
+ }
+
+ void HomeScreenPresenter::handleLowBatteryWarning()
+ {
+ if (batteryLevelNotificationModel.getBatteryLevelInterval() != BatteryLevelInterval::Unknown &&
+ batteryLevelNotificationModel.getBatteryLevelInterval() != BatteryLevelInterval::Above15Percent) {
+ switchToLowBatteryWarning();
+ }
+ else {
+ userSessionModel.setCurrentUserSessionAsHandled();
+ }
+ batteryLevelNotificationModel.setCurrentBatteryIntervalAsHandled();
+ userSessionModel.setCurrentUserSessionAsHandled();
+ }
+
+ void HomeScreenPresenter::refreshUserSession()
+ {
+ userSessionModel.activateUserSession();
+ }
+
+ void HomeScreenPresenter::updateBatteryLevelInterval()
+ {
+ batteryLevelNotificationModel.updateBatteryLevelInterval(getBatteryLvl());
+ }
+
} // namespace app::home_screen
M products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp => products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp +59 -26
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "StateController.hpp"
@@ 65,9 65,15 @@ namespace app::home_screen
return true;
};
- auto switchToMenu = [](AbstractPresenter &presenter) { presenter.switchToMenu(); };
- auto switchToBatteryStatus = [](AbstractPresenter &presenter) { presenter.switchToBatteryStatus(); };
- auto updateTemperature = [](AbstractView &view, AbstractTemperatureModel &temperatureModel) {
+ auto switchToMenu = [](AbstractPresenter &presenter) { presenter.switchToMenu(); };
+ auto isLowBatteryWarningToShow = [](AbstractPresenter &presenter) {
+ return presenter.isLowBatteryWarningNeeded();
+ };
+ auto showLowBatteryWarning = [](AbstractPresenter &presenter) { presenter.handleLowBatteryWarning(); };
+ auto endUserSessionWithDelay = [](AbstractUserSessionModel &userSession) {
+ userSession.deactivateUserSessionWithDelay();
+ };
+ auto updateTemperature = [](AbstractView &view, AbstractTemperatureModel &temperatureModel) {
view.setTemperature(temperatureModel.getTemperature());
};
auto setNewAlarmTime = [](AbstractView &view, AbstractAlarmModel &alarmModel) {
@@ 84,6 90,7 @@ namespace app::home_screen
auto updateBatteryStatus = [](AbstractView &view, AbstractBatteryModel &batteryModel) {
view.setBatteryLevelState(batteryModel.getLevelState());
};
+ auto switchToBatteryStatus = [](AbstractPresenter &presenter) { presenter.switchToBatteryStatus(); };
} // namespace Helpers
@@ 115,6 122,8 @@ namespace app::home_screen
{};
struct BatteryUpdate
{};
+ struct LowBatteryWarning
+ {};
} // namespace Events
namespace Init
@@ 135,11 144,13 @@ namespace app::home_screen
auto entry = [](AbstractController &controller,
AbstractView &view,
AbstractTemperatureModel &temperatureModel,
- AbstractBatteryModel &batteryModel) {
+ AbstractBatteryModel &batteryModel,
+ AbstractUserSessionModel &userSession) {
controller.snooze(false);
view.setViewState(ViewState::Deactivated);
view.setTemperature(temperatureModel.getTemperature());
view.setBatteryLevelState(batteryModel.getLevelState());
+ userSession.deactivateUserSessionWithDelay();
};
} // namespace Deactivated
@@ 212,12 223,14 @@ namespace app::home_screen
AbstractView &view,
AbstractAlarmModel &alarmModel,
AbstractTemperatureModel &temperatureModel,
- AbstractBatteryModel &batteryModel) {
+ AbstractBatteryModel &batteryModel,
+ AbstractUserSessionModel &userSession) {
controller.snooze(false);
view.setTemperature(temperatureModel.getTemperature());
view.setViewState(ViewState::Activated);
view.setAlarmTime(alarmModel.getAlarmTime());
view.setBatteryLevelState(batteryModel.getLevelState());
+ userSession.deactivateUserSessionWithDelay();
};
} // namespace Activated
@@ 262,11 275,13 @@ namespace app::home_screen
auto entry = [](AbstractView &view,
AbstractAlarmModel &alarmModel,
AbstractTemperatureModel &temperatureModel,
- AbstractBatteryModel &batteryModel) {
+ AbstractBatteryModel &batteryModel,
+ AbstractUserSessionModel &userSession) {
view.setViewState(ViewState::AlarmSnoozed);
view.setSnoozeTime(Clock::to_time_t(alarmModel.getTimeOfNextSnooze()));
view.setTemperature(temperatureModel.getTemperature());
view.setBatteryLevelState(batteryModel.getLevelState());
+ userSession.deactivateUserSessionWithDelay();
};
auto exit = [](AbstractPresenter &presenter) { presenter.stopSnoozeTimer(); };
} // namespace AlarmSnoozed
@@ 285,13 300,15 @@ namespace app::home_screen
"Init"_s + event<Events::ModelReady> [Helpers::shouldSwitchToActivated] = "Activated"_s,
"Deactivated"_s + sml::on_entry<_> / Deactivated::entry,
- "Deactivated"_s + event<Events::LightPress>/ Helpers::switchToMenu,
- "Deactivated"_s + event<Events::RotateLeftPress> = "DeactivatedEdit"_s,
- "Deactivated"_s + event<Events::RotateRightPress> = "DeactivatedEdit"_s,
- "Deactivated"_s + event<Events::DeepUpPress> = "ActivatedWait"_s,
+ "Deactivated"_s + event<Events::LightPress> [not Helpers::isLowBatteryWarningToShow] / Helpers::switchToMenu,
+ "Deactivated"_s + event<Events::RotateLeftPress> [not Helpers::isLowBatteryWarningToShow] = "DeactivatedEdit"_s,
+ "Deactivated"_s + event<Events::RotateRightPress> [not Helpers::isLowBatteryWarningToShow] = "DeactivatedEdit"_s,
+ "Deactivated"_s + event<Events::DeepUpPress> [not Helpers::isLowBatteryWarningToShow] = "ActivatedWait"_s,
"Deactivated"_s + event<Events::TimeUpdate> / Helpers::updateTemperature,
- "Deactivated"_s + event<Events::LongBackPress> / Helpers::switchToBatteryStatus,
+ "Deactivated"_s + event<Events::BackPress> / Helpers::endUserSessionWithDelay,
+ "Deactivated"_s + event<Events::LongBackPress> [not Helpers::isLowBatteryWarningToShow] / Helpers::switchToBatteryStatus,
"Deactivated"_s + event<Events::BatteryUpdate> / Helpers::updateBatteryStatus,
+ "Deactivated"_s + event<Events::LowBatteryWarning> [Helpers::isLowBatteryWarningToShow] / Helpers::showLowBatteryWarning,
"DeactivatedWait"_s + sml::on_entry<_> / DeactivatedWait::entry,
"DeactivatedWait"_s + sml::on_exit<_> / DeactivatedWait::exit,
@@ 334,14 351,16 @@ namespace app::home_screen
"Activated"_s + sml::on_entry<_> / Activated::entry,
"Activated"_s [not Helpers::isAlarmActive] = "Deactivated"_s,
- "Activated"_s + event<Events::LightPress>/ Helpers::switchToMenu = "Activated"_s,
- "Activated"_s + event<Events::RotateLeftPress> = "ActivatedEdit"_s,
- "Activated"_s + event<Events::RotateRightPress> = "ActivatedEdit"_s,
+ "Activated"_s + event<Events::LightPress> [not Helpers::isLowBatteryWarningToShow]/ Helpers::switchToMenu = "Activated"_s,
+ "Activated"_s + event<Events::RotateLeftPress> [not Helpers::isLowBatteryWarningToShow] = "ActivatedEdit"_s,
+ "Activated"_s + event<Events::RotateRightPress> [not Helpers::isLowBatteryWarningToShow] = "ActivatedEdit"_s,
"Activated"_s + event<Events::TimeUpdate> / Helpers::updateTemperature,
- "Activated"_s + event<Events::DeepDownPress> = "DeactivatedWait"_s,
+ "Activated"_s + event<Events::DeepDownPress> [not Helpers::isLowBatteryWarningToShow] = "DeactivatedWait"_s,
"Activated"_s + event<Events::AlarmRinging> = "AlarmRinging"_s,
- "Activated"_s + event<Events::LongBackPress> / Helpers::switchToBatteryStatus,
+ "Activated"_s + event<Events::BackPress> / Helpers::endUserSessionWithDelay,
+ "Activated"_s + event<Events::LongBackPress> [not Helpers::isLowBatteryWarningToShow] / Helpers::switchToBatteryStatus,
"Activated"_s + event<Events::BatteryUpdate> / Helpers::updateBatteryStatus,
+ "Activated"_s + event<Events::LowBatteryWarning> [Helpers::isLowBatteryWarningToShow] / Helpers::showLowBatteryWarning,
"ActivatedEdit"_s + sml::on_entry<_> / AlarmEdit::entry,
"ActivatedEdit"_s + sml::on_exit<_> / AlarmEdit::exit,
@@ 389,11 408,12 @@ namespace app::home_screen
"AlarmSnoozed"_s + sml::on_entry<_> / AlarmSnoozed::exit,
"AlarmSnoozed"_s + event<Events::ModelReady> [not Helpers::isSnoozeActive] = "Activated"_s,
"AlarmSnoozed"_s + event<Events::AlarmRinging> = "AlarmRinging"_s,
- "AlarmSnoozed"_s + event<Events::DeepDownPress> = "DeactivatedWait"_s,
- "AlarmSnoozed"_s + event<Events::LightPress>/Helpers::switchToMenu,
+ "AlarmSnoozed"_s + event<Events::DeepDownPress> [not Helpers::isLowBatteryWarningToShow] = "DeactivatedWait"_s,
+ "AlarmSnoozed"_s + event<Events::LightPress> [not Helpers::isLowBatteryWarningToShow]/Helpers::switchToMenu,
"AlarmSnoozed"_s + event<Events::TimeUpdate> / Helpers::updateTemperature,
- "AlarmSnoozed"_s + event<Events::BatteryUpdate> / Helpers::updateBatteryStatus,
- "AlarmSnoozed"_s + event<Events::LongBackPress> / Helpers::switchToBatteryStatus
+ "AlarmSnoozed"_s + event<Events::BatteryUpdate> / Helpers::updateBatteryStatus,
+ "AlarmSnoozed"_s + event<Events::LongBackPress> [not Helpers::isLowBatteryWarningToShow] / Helpers::switchToBatteryStatus,
+ "AlarmSnoozed"_s + event<Events::LowBatteryWarning> [Helpers::isLowBatteryWarningToShow] / Helpers::showLowBatteryWarning
);
// clang-format on
}
@@ 416,9 436,11 @@ namespace app::home_screen
AbstractBatteryModel &batteryModel,
AbstractTemperatureModel &temperatureModel,
AbstractAlarmModel &alarmModel,
- AbstractTimeModel &timeModel)
+ AbstractTimeModel &timeModel,
+ AbstractUserSessionModel &userSessionModel)
: controller{controller}, view{view}, presenter{presenter}, batteryModel{batteryModel},
- temperatureModel{temperatureModel}, alarmModel{alarmModel}, timeModel{timeModel}
+ temperatureModel{temperatureModel}, alarmModel{alarmModel}, timeModel{timeModel}, userSessionModel{
+ userSessionModel}
{
resetSM();
}
@@ 445,7 467,8 @@ namespace app::home_screen
batteryModel,
temperatureModel,
alarmModel,
- timeModel};
+ timeModel,
+ userSessionModel};
}
AbstractController &controller;
@@ 455,6 478,7 @@ namespace app::home_screen
AbstractTemperatureModel &temperatureModel;
AbstractAlarmModel &alarmModel;
AbstractTimeModel &timeModel;
+ AbstractUserSessionModel &userSessionModel;
};
StateController::StateController(AbstractView &view,
@@ 462,9 486,10 @@ namespace app::home_screen
AbstractBatteryModel &batteryModel,
AbstractTemperatureModel &temperatureModel,
AbstractAlarmModel &alarmModel,
- AbstractTimeModel &timeModel)
+ AbstractTimeModel &timeModel,
+ AbstractUserSessionModel &userSessionModel)
: pimpl{std::make_unique<StateController::Impl>(
- *this, view, presenter, batteryModel, temperatureModel, alarmModel, timeModel)},
+ *this, view, presenter, batteryModel, temperatureModel, alarmModel, timeModel, userSessionModel)},
presenter{presenter}
{}
@@ 474,6 499,10 @@ namespace app::home_screen
{
using namespace sml;
const auto key = mapKey(inputEvent.getKeyCode());
+
+ presenter.refreshUserSession();
+ presenter.updateBatteryLevelInterval();
+
switch (key) {
case KeyMap::Back:
if (inputEvent.getState() == gui::InputEvent::State::keyReleasedLong) {
@@ 502,6 531,10 @@ namespace app::home_screen
break;
}
+ if (key != KeyMap::DeepPressUp && key != KeyMap::DeepPressDown && presenter.isLowBatteryWarningNeeded()) {
+ pimpl->sm->process_event(Events::LowBatteryWarning{});
+ }
+
return true;
}
M products/BellHybrid/apps/application-bell-main/presenters/StateController.hpp => products/BellHybrid/apps/application-bell-main/presenters/StateController.hpp +4 -2
@@ 1,9 1,10 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <common/models/AbstractAlarmModel.hpp>
+#include <common/models/UserSessionModel.hpp>
#include <gui/input/InputEvent.hpp>
#include <chrono>
@@ 46,7 47,8 @@ namespace app::home_screen
AbstractBatteryModel &batteryModel,
AbstractTemperatureModel &temperatureModel,
AbstractAlarmModel &alarmModel,
- AbstractTimeModel &timeModel);
+ AbstractTimeModel &timeModel,
+ AbstractUserSessionModel &userSessionModel);
~StateController();
void resetStateMachine() override;
M products/BellHybrid/apps/application-bell-main/windows/BellBatteryStatusWindow.cpp => products/BellHybrid/apps/application-bell-main/windows/BellBatteryStatusWindow.cpp +12 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "BellBatteryStatusWindow.hpp"
@@ 53,7 53,6 @@ namespace gui
topDescription->setEdges(RectangleEdge::None);
topDescription->activeItem = false;
topDescription->drawUnderline(false);
- topDescription->setText(utils::translate("app_settings_tech_info_battery"));
hbox = new HBox(body->lastBox);
hbox->setMinimumSize(style::bell_base_layout::outer_layouts_w, style::bell_base_layout::outer_layouts_h);
@@ 113,10 112,19 @@ namespace gui
if (data != nullptr) {
const auto &switchData = static_cast<Data &>(*data);
const auto image = battery_utils::getBatteryLevelImage(batteryEntries, switchData.chargeLevel);
- if (image) {
- center->setImage(image->data(), imageType);
+ if (switchData.isLowBatteryWarning) {
+ topDescription->setText(utils::translate("battery_low"));
+ auto tokenMap = text::RichTextParser::TokenMap({{"$BATTERY", std::to_string(switchData.chargeLevel)}});
+ bottomDescription->setRichText(utils::translate("battery_remaining"), std::move(tokenMap));
+ chargingIcon->setVisible(false);
+ }
+ else {
+ topDescription->setText(utils::translate("app_settings_tech_info_battery"));
bottomDescription->setText(std::to_string(switchData.chargeLevel) + "%");
chargingIcon->setVisible(switchData.isCharging);
+ }
+ if (image) {
+ center->setImage(image->data(), imageType);
hbox->resizeItems();
body->resize();
}
M products/BellHybrid/apps/application-bell-main/windows/BellBatteryStatusWindow.hpp => products/BellHybrid/apps/application-bell-main/windows/BellBatteryStatusWindow.hpp +5 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 17,10 17,12 @@ namespace gui
public:
struct Data : public gui::SwitchData
{
- Data(std::uint32_t lvl, bool chargeState) : chargeLevel{lvl}, isCharging{chargeState}
+ Data(std::uint32_t lvl, bool chargeState, bool lowBatteryWaring = false)
+ : chargeLevel{lvl}, isCharging{chargeState}, isLowBatteryWarning{lowBatteryWaring}
{}
const std::uint32_t chargeLevel;
const bool isCharging;
+ const bool isLowBatteryWarning;
};
static constexpr auto name = "BellBatteryStatusWindow";
explicit BellBatteryStatusWindow(app::ApplicationCommon *app);
@@ 28,7 30,7 @@ namespace gui
private:
static constexpr auto top_description_font = style::window::font::largelight;
static constexpr auto bottom_description_font = style::window::font::verybiglight;
- static constexpr auto bottom_description_max_size_w = 85U;
+ static constexpr auto bottom_description_max_size_w = style::bell_base_layout::outer_layouts_w;
static constexpr auto bottom_description_max_size_h = 85U;
void buildInterface() override;
M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp => products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "BellHomeScreenWindow.hpp"
M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +4 -0
@@ 18,7 18,9 @@ target_sources(application-bell-common
src/AudioModel.cpp
src/LanguageUtils.cpp
src/TimeModel.cpp
+ src/UserSessionModel.cpp
src/BatteryModel.cpp
+ src/BatteryLevelNotificationModel.cpp
src/SoundsRepository.cpp
src/BellListItemProvider.cpp
src/SoundsProvider.cpp
@@ 95,7 97,9 @@ target_sources(application-bell-common
include/common/models/SettingsModel.hpp
include/common/models/BedtimeModel.hpp
include/common/models/BatteryModel.hpp
+ include/common/models/BatteryLevelNotificationModel.hpp
include/common/models/TimeModel.hpp
+ include/common/models/UserSessionModel.hpp
include/common/models/AudioModel.hpp
include/common/models/FrontlightModel.hpp
include/common/models/AlarmSettingsModel.hpp
A products/BellHybrid/apps/common/include/common/models/BatteryLevelNotificationModel.hpp => products/BellHybrid/apps/common/include/common/models/BatteryLevelNotificationModel.hpp +60 -0
@@ 0,0 1,60 @@
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <module-utils/EventStore/EventStore.hpp>
+#include <service-db/Settings.hpp>
+
+#include <cstdint>
+#include <functional>
+#include <string>
+#include <Units.hpp>
+
+namespace app
+{
+ class ApplicationCommon;
+}
+
+namespace app
+{
+ enum class BatteryLevelInterval
+ {
+ Unknown,
+ Above15Percent, // 16-100%
+ Below15Percent, // 10-15%
+ Below10Percent, // 5-9%
+ Below5Percent, // 0-4%
+ };
+
+ class AbstractBatteryLevelNotificationModel
+ {
+ public:
+ virtual ~AbstractBatteryLevelNotificationModel() noexcept = default;
+
+ virtual void updateBatteryLevelInterval(units::SOC currentBatteryLevel) = 0;
+ [[nodiscard]] virtual BatteryLevelInterval getBatteryLevelInterval() const = 0;
+ [[nodiscard]] virtual bool isBatteryIntervalHandled() const = 0;
+ virtual void setCurrentBatteryIntervalAsHandled() = 0;
+ };
+
+ class BatteryLevelNotificationModel : public AbstractBatteryLevelNotificationModel
+ {
+ static constexpr auto batteryLevelIntervalUpperHysteresis = 2;
+ static constexpr auto above15PercentMinVal = 16;
+ static constexpr auto below15PercentMaxVal = 15;
+ static constexpr auto below10PercentMaxVal = 9;
+ static constexpr auto below5PercentMaxVal = 4;
+
+ public:
+ explicit BatteryLevelNotificationModel();
+ void updateBatteryLevelInterval(units::SOC currentBatteryLevel) override;
+ [[nodiscard]] BatteryLevelInterval getBatteryLevelInterval() const override;
+ [[nodiscard]] bool isBatteryIntervalHandled() const override;
+ void setCurrentBatteryIntervalAsHandled() override;
+
+ private:
+ BatteryLevelInterval currentBatteryLevelInterval = BatteryLevelInterval::Unknown;
+ bool isCurrentBatteryIntervalHandled = false;
+ };
+} // namespace app
A products/BellHybrid/apps/common/include/common/models/UserSessionModel.hpp => products/BellHybrid/apps/common/include/common/models/UserSessionModel.hpp +60 -0
@@ 0,0 1,60 @@
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <cstdint>
+#include <functional>
+#include <string>
+#include <Timers/TimerHandle.hpp>
+#include <Timers/TimerFactory.hpp>
+
+namespace app
+{
+ inline constexpr auto endOfUserSessionTimeout = std::chrono::seconds{5};
+
+ class AbstractUserSessionModel
+ {
+
+ public:
+ virtual ~AbstractUserSessionModel() noexcept = default;
+
+ virtual void activateUserSession() = 0;
+ virtual void restartUserSession() = 0;
+ virtual void deactivateUserSessionWithDelay() = 0;
+ virtual void setCurrentUserSessionAsHandled() = 0;
+
+ virtual bool isUserSessionActive() = 0;
+ virtual bool isActiveUserSessionHandled() = 0;
+ };
+
+ class UserSessionModel : public AbstractUserSessionModel
+ {
+ enum class SessionState
+ {
+ Inactive = 0,
+ Active,
+ EndingWithDelay
+ };
+
+ public:
+ explicit UserSessionModel(sys::Service *serv);
+
+ void activateUserSession() override;
+ void restartUserSession() override;
+ void deactivateUserSessionWithDelay() override;
+ void setCurrentUserSessionAsHandled() override;
+
+ bool isUserSessionActive() override;
+ bool isActiveUserSessionHandled() override;
+
+ protected:
+ void endOfSessionTimerCallback();
+
+ private:
+ SessionState sessionState = SessionState::Inactive;
+ sys::Service *serv;
+ sys::TimerHandle endSessionDelayTimer;
+ bool isCurrentUserSessionHandled = true;
+ };
+} // namespace app
A products/BellHybrid/apps/common/src/BatteryLevelNotificationModel.cpp => products/BellHybrid/apps/common/src/BatteryLevelNotificationModel.cpp +72 -0
@@ 0,0 1,72 @@
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "models/BatteryLevelNotificationModel.hpp"
+
+namespace app
+{
+ BatteryLevelNotificationModel::BatteryLevelNotificationModel()
+ {}
+
+ void BatteryLevelNotificationModel::updateBatteryLevelInterval(units::SOC currentBatteryLevel)
+ {
+ auto updateBatteryIntervalState = [&](BatteryLevelInterval newBatteryLevelIntervalState) {
+ if (currentBatteryLevelInterval == newBatteryLevelIntervalState) {
+ return;
+ }
+ currentBatteryLevelInterval = newBatteryLevelIntervalState;
+ isCurrentBatteryIntervalHandled = (newBatteryLevelIntervalState == BatteryLevelInterval::Above15Percent);
+ };
+
+ auto updateBatteryIntervalStateWithHysteresis = [&](units::SOC above15PercentHysteresis,
+ units::SOC below15PercentHysteresis,
+ units::SOC below10PercentHysteresis) {
+ if (currentBatteryLevel <= below5PercentMaxVal) {
+ updateBatteryIntervalState(BatteryLevelInterval::Below5Percent);
+ }
+ else if (currentBatteryLevel <= below10PercentMaxVal + below10PercentHysteresis) {
+ updateBatteryIntervalState(BatteryLevelInterval::Below10Percent);
+ }
+ else if (currentBatteryLevel <= below15PercentMaxVal + below15PercentHysteresis) {
+ updateBatteryIntervalState(BatteryLevelInterval::Below15Percent);
+ }
+ else if (currentBatteryLevel >= above15PercentMinVal + above15PercentHysteresis) {
+ updateBatteryIntervalState(BatteryLevelInterval::Above15Percent);
+ }
+ };
+
+ switch (currentBatteryLevelInterval) {
+ case (BatteryLevelInterval::Unknown):
+ case (BatteryLevelInterval::Above15Percent):
+ updateBatteryIntervalStateWithHysteresis(0, 0, 0);
+ break;
+ case (BatteryLevelInterval::Below15Percent):
+ updateBatteryIntervalStateWithHysteresis(batteryLevelIntervalUpperHysteresis, 0, 0);
+ break;
+ case (BatteryLevelInterval::Below10Percent):
+ updateBatteryIntervalStateWithHysteresis(0, batteryLevelIntervalUpperHysteresis, 0);
+ break;
+ case (BatteryLevelInterval::Below5Percent):
+ updateBatteryIntervalStateWithHysteresis(0, 0, batteryLevelIntervalUpperHysteresis);
+ break;
+ default:
+ break;
+ }
+ }
+
+ BatteryLevelInterval BatteryLevelNotificationModel::getBatteryLevelInterval() const
+ {
+ return currentBatteryLevelInterval;
+ }
+
+ bool BatteryLevelNotificationModel::isBatteryIntervalHandled() const
+ {
+ return isCurrentBatteryIntervalHandled;
+ }
+
+ void BatteryLevelNotificationModel::setCurrentBatteryIntervalAsHandled()
+ {
+ isCurrentBatteryIntervalHandled = true;
+ }
+
+} // namespace app
A products/BellHybrid/apps/common/src/UserSessionModel.cpp => products/BellHybrid/apps/common/src/UserSessionModel.cpp +64 -0
@@ 0,0 1,64 @@
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "models/UserSessionModel.hpp"
+#include <log/log.hpp>
+
+namespace app
+{
+
+ UserSessionModel::UserSessionModel(sys::Service *serv) : serv{serv}
+ {
+ endSessionDelayTimer = sys::TimerFactory::createPeriodicTimer(
+ serv, "EndOfUserSessionDelay", endOfUserSessionTimeout, [this](sys::Timer &) {
+ endOfSessionTimerCallback();
+ });
+ }
+
+ void UserSessionModel::activateUserSession()
+ {
+ if (sessionState == SessionState::Inactive) {
+ LOG_INFO("User session began");
+ isCurrentUserSessionHandled = false;
+ }
+ sessionState = SessionState::Active;
+ endSessionDelayTimer.stop();
+ }
+
+ void UserSessionModel::restartUserSession()
+ {
+ LOG_INFO("User session began (restarted)");
+ isCurrentUserSessionHandled = false;
+ sessionState = SessionState::Active;
+ endSessionDelayTimer.stop();
+ }
+
+ void UserSessionModel::deactivateUserSessionWithDelay()
+ {
+ sessionState = SessionState::EndingWithDelay;
+ endSessionDelayTimer.restart(endOfUserSessionTimeout);
+ }
+
+ void UserSessionModel::setCurrentUserSessionAsHandled()
+ {
+ isCurrentUserSessionHandled = true;
+ }
+
+ bool UserSessionModel::isUserSessionActive()
+ {
+ return (sessionState != SessionState::Inactive);
+ }
+
+ bool UserSessionModel::isActiveUserSessionHandled()
+ {
+ return isCurrentUserSessionHandled && isUserSessionActive();
+ }
+
+ void UserSessionModel::endOfSessionTimerCallback()
+ {
+ LOG_INFO("User session is ended");
+ endSessionDelayTimer.stop();
+ sessionState = SessionState::Inactive;
+ }
+
+} // namespace app
M products/BellHybrid/services/appmgr/include/appmgr/IdleHandler.hpp => products/BellHybrid/services/appmgr/include/appmgr/IdleHandler.hpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
M products/PurePhone/services/evtmgr/WorkerEvent.cpp => products/PurePhone/services/evtmgr/WorkerEvent.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "WorkerEvent.hpp"
@@ 79,7 79,7 @@ bool WorkerEvent::handleMessage(std::uint32_t queueID)
if (notification == bsp::cellular::statusPin) {
auto GSMstatus = bsp::cellular::status::getStatus();
LOG_DEBUG("GSM Status pin change: %s",
- (GSMstatus == bsp::cellular::status::value::ACTIVE ? "ACTIVE" : "INACTIVE"));
+ (GSMstatus == bsp::cellular::status::value::ACTIVE ? "Active" : "Inactive"));
auto message = std::make_shared<sevm::StatusStateMessage>(MessageType::EVMModemStatus);
message->state = GSMstatus;