M image/user/db/events_001.sql => image/user/db/events_001.sql +2 -1
@@ 17,5 17,6 @@ CREATE TABLE IF NOT EXISTS alarm_events(
music_tone TEXT,
enabled BOOLEAN,
snooze_duration INTEGER,
- FOREIGN KEY (event_id) REFERENCES events (_id) ON DELETE CASCADE
+ FOREIGN KEY (event_id) REFERENCES events (_id)
);
+
M image/user/db/settings_bell_002.sql => image/user/db/settings_bell_002.sql +6 -2
@@ 40,6 40,10 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
('\ServiceTime\\gs_automatic_date_and_time_is_on', '1'),
('temperature_unit', 'C'),
('ringing_duration', '10000'),
- ('ringing_tone', 'Nick_Lewis_-_Kristies_Elephant.mp3');
-
+ ('ringing_tone', 'Nick_Lewis_-_Kristies_Elephant.mp3'),
+ ('snooze_active', '1'),
+ ('snooze_length','10'),
+ ('snooze_interval','1'),
+ ('snooze_tone','Meditative surprises'),
+ ('snooze_volume','10');
M module-db/Interface/EventRecord.hpp => module-db/Interface/EventRecord.hpp +2 -0
@@ 59,6 59,8 @@ struct SingleEventRecord : public Record, public EventInfo
{
std::shared_ptr<EventRecord> parent;
+ virtual ~SingleEventRecord() = default;
+
SingleEventRecord() = default;
SingleEventRecord(std::shared_ptr<EventRecord> parent, TimePoint startDate, TimePoint endDate)
: EventInfo{parent->name, startDate, endDate, parent->duration, parent->isAllDay}, parent{parent} {};
M module-services/service-appmgr/model/ApplicationManagerCommon.cpp => module-services/service-appmgr/model/ApplicationManagerCommon.cpp +2 -0
@@ 13,6 13,7 @@
#include <SystemManager/messages/SystemManagerMessage.hpp>
#include <application-onboarding/data/OnBoardingMessages.hpp>
#include <apps-common/messages/AppMessage.hpp>
+#include <apps-common/actions/AlarmTriggeredAction.hpp>
#include <i18n/i18n.hpp>
#include <log/log.hpp>
#include <service-audio/AudioMessage.hpp>
@@ 270,6 271,7 @@ namespace app::manager
auto convertibleToActionHandler = [this](sys::Message *request) { return handleMessageAsAction(request); };
connect(typeid(sys::CriticalBatteryLevelNotification), convertibleToActionHandler);
connect(typeid(VolumeChanged), convertibleToActionHandler);
+ connect(typeid(app::actions::AlarmTriggeredAction), convertibleToActionHandler);
}
sys::ReturnCodes ApplicationManagerCommon::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
M module-services/service-time/AlarmMessageHandler.cpp => module-services/service-time/AlarmMessageHandler.cpp +18 -0
@@ 77,6 77,24 @@ namespace alarms
});
}
+ auto AlarmMessageHandler::handleTurnOffRingingAlarm(RingingAlarmTurnOffRequestMessage *request)
+ -> std::shared_ptr<RingingAlarmTurnOffResponseMessage>
+ {
+ return handleWithCallback<RingingAlarmTurnOffRequestMessage, RingingAlarmTurnOffResponseMessage, bool>(
+ request, [&](RingingAlarmTurnOffRequestMessage *request, IAlarmOperations::OnTurnOffRingingAlarm callback) {
+ alarmOperations->turnOffRingingAlarm(request->id, callback);
+ });
+ }
+
+ auto AlarmMessageHandler::handleSnoozeRingingAlarm(RingingAlarmSnoozeRequestMessage *request)
+ -> std::shared_ptr<RingingAlarmSnoozeResponseMessage>
+ {
+ return handleWithCallback<RingingAlarmSnoozeRequestMessage, RingingAlarmSnoozeResponseMessage, bool>(
+ request, [&](RingingAlarmSnoozeRequestMessage *request, IAlarmOperations::OnSnoozeRingingAlarm callback) {
+ alarmOperations->snoozeRingingAlarm(request->id, request->nextAlarmTime, callback);
+ });
+ }
+
auto AlarmMessageHandler::handleMinuteUpdated() -> void
{
alarmOperations->minuteUpdated(TimePointNow());
M module-services/service-time/AlarmMessageHandler.hpp => module-services/service-time/AlarmMessageHandler.hpp +4 -0
@@ 29,6 29,10 @@ namespace alarms
-> std::shared_ptr<AlarmsGetInRangeResponseMessage>;
auto handleGetNextSingleEvents(AlarmGetNextSingleEventsRequestMessage *request)
-> std::shared_ptr<AlarmGetNextSingleEventsResponseMessage>;
+ auto handleTurnOffRingingAlarm(RingingAlarmTurnOffRequestMessage *request)
+ -> std::shared_ptr<RingingAlarmTurnOffResponseMessage>;
+ auto handleSnoozeRingingAlarm(RingingAlarmSnoozeRequestMessage *request)
+ -> std::shared_ptr<RingingAlarmSnoozeResponseMessage>;
auto handleMinuteUpdated() -> void;
auto addAlarmExecutionHandler(const alarms::AlarmType type, const std::shared_ptr<alarms::AlarmHandler> handler)
M module-services/service-time/AlarmOperations.cpp => module-services/service-time/AlarmOperations.cpp +110 -14
@@ 6,6 6,8 @@
#include <module-db/Interface/AlarmEventRecord.hpp>
#include <module-db/Interface/EventRecord.hpp>
+#include <vector>
+
namespace alarms
{
AlarmOperations::AlarmOperations(std::unique_ptr<AbstractAlarmEventsRepository> &&alarmEventsRepo,
@@ 15,7 17,11 @@ namespace alarms
void AlarmOperations::updateEventsCache(TimePoint now)
{
OnGetNextSingleProcessed callback = [&](std::vector<SingleEventRecord> singleEvents) {
- nextSingleEvents = std::move(singleEvents);
+ nextSingleEvents.clear();
+ nextSingleEvents.reserve(singleEvents.size());
+ for (auto &ev : singleEvents) {
+ nextSingleEvents.emplace_back(std::make_unique<SingleEventRecord>(ev));
+ }
};
getNextSingleEvents(now, callback);
}
@@ 38,10 44,11 @@ namespace alarms
void AlarmOperations::updateAlarm(AlarmEventRecord record, OnUpdateAlarmProcessed callback)
{
OnUpdateAlarmEventCallback repoCallback = [&, callback, record](bool success) mutable {
- auto found =
- std::find_if(nextSingleEvents.begin(),
- nextSingleEvents.end(),
- [recordId = record.ID](const SingleEventRecord &e) { return e.parent->ID == recordId; });
+ auto found = std::find_if(nextSingleEvents.begin(),
+ nextSingleEvents.end(),
+ [recordId = record.ID](const std::unique_ptr<SingleEventRecord> &e) {
+ return e->parent->ID == recordId;
+ });
if (found != std::end(nextSingleEvents)) {
updateEventsCache(getCurrentTime());
@@ 57,9 64,10 @@ namespace alarms
void AlarmOperations::removeAlarm(const std::uint32_t alarmId, OnRemoveAlarmProcessed callback)
{
OnRemoveAlarmEventCallback repoCallback = [&, callback, alarmId](bool success) {
- auto found = std::find_if(nextSingleEvents.begin(),
- nextSingleEvents.end(),
- [alarmId](const SingleEventRecord &e) { return e.parent->ID == alarmId; });
+ auto found = std::find_if(
+ nextSingleEvents.begin(),
+ nextSingleEvents.end(),
+ [alarmId](const std::unique_ptr<SingleEventRecord> &e) { return e->parent->ID == alarmId; });
if (found != std::end(nextSingleEvents) && nextSingleEvents.size() == 1) {
updateEventsCache(getCurrentTime());
@@ 93,6 101,57 @@ namespace alarms
alarmEventsRepo->getNext(start, getNextSingleEventsOffset, getNextSingleEventsLimit, repoGetNextCallback);
}
+ void AlarmOperations::turnOffRingingAlarm(const std::uint32_t id, OnTurnOffRingingAlarm callback)
+ {
+ auto found =
+ std::find_if(ongoingSingleEvents.begin(),
+ ongoingSingleEvents.end(),
+ [id](const std::unique_ptr<SingleEventRecord> &event) { return id == event->parent->ID; });
+ if (found == ongoingSingleEvents.end()) {
+ LOG_ERROR("Trying to turn off nonexisting event");
+ callback(false);
+ return;
+ }
+ switchAlarmExecution(*(*found), false);
+ ongoingSingleEvents.erase(found);
+ callback(true);
+ }
+
+ void AlarmOperations::snoozeRingingAlarm(const std::uint32_t id,
+ const TimePoint nextAlarmTime,
+ OnSnoozeRingingAlarm callback)
+ {
+ auto found =
+ std::find_if(ongoingSingleEvents.begin(),
+ ongoingSingleEvents.end(),
+ [id](const std::unique_ptr<SingleEventRecord> &event) { return id == event->parent->ID; });
+ if (found == ongoingSingleEvents.end()) {
+ LOG_ERROR("Trying to snooze nonexisting event");
+ callback(false);
+ return;
+ }
+
+ auto newSnoozed = std::make_unique<SnoozedAlarmEventRecord>((*found).get());
+
+ if (typeid(*(*found)) == typeid(SnoozedAlarmEventRecord)) {
+ auto oldSnoozedPtr = dynamic_cast<SnoozedAlarmEventRecord *>((*found).get());
+ newSnoozed->snoozeCount = oldSnoozedPtr->snoozeCount + 1;
+ }
+ else if (typeid(*(*found)) != typeid(SingleEventRecord)) {
+ LOG_ERROR("Unkown alarm type detected");
+ callback(false);
+ return;
+ }
+
+ newSnoozed->startDate = nextAlarmTime;
+ snoozedSingleEvents.push_back(std::move(newSnoozed));
+
+ switchAlarmExecution(*(*found), false);
+ ongoingSingleEvents.erase(found);
+
+ callback(true);
+ }
+
void AlarmOperations::onRepoGetNextResponse(OnGetNextSingleProcessed handledCallback,
std::shared_ptr<std::vector<AlarmEventRecord>> nextEvents,
TimePoint start,
@@ 148,7 207,7 @@ namespace alarms
if (nearestNewSingleEvent.EventInfo::isValid() && nearestNewSingleEvent.startDate > getCurrentTime()) {
auto alarmEvent = std::dynamic_pointer_cast<AlarmEventRecord>(nearestNewSingleEvent.parent);
if (record.enabled &&
- (nextSingleEvents.empty() || nearestNewSingleEvent.startDate <= nextSingleEvents.front().startDate)) {
+ (nextSingleEvents.empty() || nearestNewSingleEvent.startDate <= nextSingleEvents.front()->startDate)) {
updateEventsCache(getCurrentTime());
}
}
@@ 156,11 215,19 @@ namespace alarms
auto AlarmOperations::minuteUpdated(TimePoint now) -> void
{
- if (nextSingleEvents.empty() || nextSingleEvents.front().startDate > now) {
- return;
+ auto isHandlingInProgress = !ongoingSingleEvents.empty();
+
+ if (!nextSingleEvents.empty()) {
+ processNextEventsQueue(now);
}
- executeAlarm(nextSingleEvents.front());
+ if (!snoozedSingleEvents.empty()) {
+ processSnoozedEventsQueue(now);
+ }
+
+ if (!isHandlingInProgress && !ongoingSingleEvents.empty()) {
+ switchAlarmExecution(*(ongoingSingleEvents.front()), true);
+ }
}
void AlarmOperations::addAlarmExecutionHandler(const alarms::AlarmType type,
@@ 169,7 236,7 @@ namespace alarms
alarmHandlerFactory.addHandler(type, handler);
}
- void AlarmOperations::executeAlarm(const SingleEventRecord &singleAlarmEvent)
+ void AlarmOperations::switchAlarmExecution(const SingleEventRecord &singleAlarmEvent, bool newStateOn)
{
alarms::AlarmType alarmType = alarms::AlarmType::None;
if (typeid(*(singleAlarmEvent.parent)) == typeid(AlarmEventRecord)) {
@@ 180,7 247,12 @@ namespace alarms
if (alarmEventPtr) {
auto handler = alarmHandlerFactory.getHandler(alarmType);
if (handler) {
- handler->handle(*alarmEventPtr);
+ if (newStateOn) {
+ handler->handle(*alarmEventPtr);
+ }
+ else {
+ handler->handleOff(*alarmEventPtr);
+ }
}
}
else {
@@ 188,6 260,29 @@ namespace alarms
}
}
+ auto AlarmOperations::processNextEventsQueue(const TimePoint now) -> void
+ {
+ if (nextSingleEvents.front()->startDate <= now) {
+ ongoingSingleEvents.insert(ongoingSingleEvents.end(),
+ std::make_move_iterator(nextSingleEvents.begin()),
+ std::make_move_iterator(nextSingleEvents.end()));
+ nextSingleEvents.clear();
+ }
+ }
+
+ auto AlarmOperations::processSnoozedEventsQueue(const TimePoint now) -> void
+ {
+ for (auto it = snoozedSingleEvents.begin(); it != snoozedSingleEvents.end();) {
+ if ((*it)->startDate <= now) {
+ ongoingSingleEvents.push_back(std::move(*it));
+ it = snoozedSingleEvents.erase(it);
+ }
+ else {
+ ++it;
+ }
+ }
+ }
+
TimePoint AlarmOperations::getCurrentTime()
{
if (!getCurrentTimeCallback) {
@@ 195,4 290,5 @@ namespace alarms
}
return getCurrentTimeCallback();
}
+
} // namespace alarms
M module-services/service-time/AlarmOperations.hpp => module-services/service-time/AlarmOperations.hpp +18 -2
@@ 4,6 4,7 @@
#pragma once
#include "AlarmRepository.hpp"
+#include "SnoozedAlarmEventRecord.hpp"
#include <service-time/AlarmHandlerFactory.hpp>
@@ 21,6 22,8 @@ namespace alarms
using OnUpdateAlarmProcessed = std::function<void(bool)>;
using OnRemoveAlarmProcessed = std::function<void(bool)>;
using OnGetNextSingleProcessed = std::function<void(std::vector<SingleEventRecord>)>;
+ using OnSnoozeRingingAlarm = std::function<void(bool)>;
+ using OnTurnOffRingingAlarm = std::function<void(bool)>;
virtual ~IAlarmOperations() noexcept = default;
@@ 38,6 41,10 @@ namespace alarms
std::uint32_t limit,
OnGetAlarmsInRangeProcessed callback) = 0;
virtual void getNextSingleEvents(TimePoint start, OnGetNextSingleProcessed callback) = 0;
+ virtual void turnOffRingingAlarm(const std::uint32_t id, OnTurnOffRingingAlarm callback) = 0;
+ virtual void snoozeRingingAlarm(const std::uint32_t id,
+ const TimePoint nextAlarmTime,
+ OnSnoozeRingingAlarm callback) = 0;
virtual void minuteUpdated(TimePoint now) = 0;
virtual void addAlarmExecutionHandler(const alarms::AlarmType type,
const std::shared_ptr<alarms::AlarmHandler> handler) = 0;
@@ 61,6 68,10 @@ namespace alarms
std::uint32_t limit,
OnGetAlarmsInRangeProcessed callback) override;
void getNextSingleEvents(TimePoint start, OnGetNextSingleProcessed callback) override;
+ void turnOffRingingAlarm(const std::uint32_t id, OnTurnOffRingingAlarm callback) override;
+ void snoozeRingingAlarm(const std::uint32_t id,
+ const TimePoint nextAlarmTime,
+ OnSnoozeRingingAlarm callback) override;
void minuteUpdated(TimePoint now) override;
void addAlarmExecutionHandler(const alarms::AlarmType type,
const std::shared_ptr<alarms::AlarmHandler> handler) override;
@@ 70,7 81,9 @@ namespace alarms
AlarmHandlerFactory alarmHandlerFactory;
// Events we are waiting for (on one timepoint)
- std::vector<SingleEventRecord> nextSingleEvents;
+ std::vector<std::unique_ptr<SingleEventRecord>> nextSingleEvents;
+ std::vector<std::unique_ptr<SingleEventRecord>> ongoingSingleEvents;
+ std::vector<std::unique_ptr<SnoozedAlarmEventRecord>> snoozedSingleEvents;
GetCurrentTime getCurrentTimeCallback;
@@ 89,7 102,10 @@ namespace alarms
std::vector<AlarmEventRecord> records);
void checkAndUpdateCache(AlarmEventRecord record);
- void executeAlarm(const SingleEventRecord &singleAlarmEvent);
+ void switchAlarmExecution(const SingleEventRecord &singleAlarmEvent, bool newStateOn);
+ void processNextEventsQueue(const TimePoint now);
+ void processSnoozedEventsQueue(const TimePoint now);
+
TimePoint getCurrentTime();
};
} // namespace alarms
M module-services/service-time/AlarmServiceAPI.cpp => module-services/service-time/AlarmServiceAPI.cpp +9 -0
@@ 50,6 50,15 @@ namespace alarms
return sendRequest<AlarmGetNextSingleEventsRequestMessage>(serv);
}
+ bool requestTurnOffRingingAlarm(sys::Service *serv, const std::uint32_t id)
+ {
+ return sendRequest<RingingAlarmTurnOffRequestMessage>(serv, id);
+ }
+
+ bool requestSnoozeRingingAlarm(sys::Service *serv, const std::uint32_t id, const TimePoint nextAlarmTime)
+ {
+ return sendRequest<RingingAlarmSnoozeRequestMessage>(serv, id, nextAlarmTime);
+ }
}; // namespace AlarmServiceAPI
} // namespace alarms
M module-services/service-time/ServiceTime.cpp => module-services/service-time/ServiceTime.cpp +8 -0
@@ 158,6 158,14 @@ namespace stm
return alarmMessageHandler->handleGetNextSingleEvents(
static_cast<alarms::AlarmGetNextSingleEventsRequestMessage *>(request));
});
+ connect(typeid(alarms::RingingAlarmTurnOffRequestMessage), [&](sys::Message *request) -> sys::MessagePointer {
+ return alarmMessageHandler->handleTurnOffRingingAlarm(
+ static_cast<alarms::RingingAlarmTurnOffRequestMessage *>(request));
+ });
+ connect(typeid(alarms::RingingAlarmSnoozeRequestMessage), [&](sys::Message *request) -> sys::MessagePointer {
+ return alarmMessageHandler->handleSnoozeRingingAlarm(
+ static_cast<alarms::RingingAlarmSnoozeRequestMessage *>(request));
+ });
}
auto ServiceTime::handleSetAutomaticDateAndTimeRequest(sys::Message *request)
A module-services/service-time/SnoozedAlarmEventRecord.hpp => module-services/service-time/SnoozedAlarmEventRecord.hpp +20 -0
@@ 0,0 1,20 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <module-db/Interface/AlarmEventRecord.hpp>
+
+struct SnoozedAlarmEventRecord : public SingleEventRecord
+{
+ public:
+ std::uint32_t snoozeCount = 1;
+
+ explicit SnoozedAlarmEventRecord(SingleEventRecord *singleAlarm)
+ : SingleEventRecord(singleAlarm->parent, singleAlarm->startDate, singleAlarm->endDate){};
+
+ std::uint32_t snooze() noexcept
+ {
+ return ++snoozeCount;
+ }
+};
M module-services/service-time/include/service-time/AlarmHandler.hpp => module-services/service-time/include/service-time/AlarmHandler.hpp +1 -0
@@ 21,5 21,6 @@ namespace alarms
virtual ~AlarmHandler() = default;
virtual auto handle(const AlarmEventRecord &record) -> bool = 0;
+ virtual auto handleOff(const AlarmEventRecord &record) -> bool = 0;
};
} // namespace alarms
M module-services/service-time/include/service-time/AlarmMessage.hpp => module-services/service-time/include/service-time/AlarmMessage.hpp +30 -0
@@ 119,4 119,34 @@ namespace alarms
std::vector<SingleEventRecord> singleEvents;
};
+ class RingingAlarmTurnOffRequestMessage : public AlarmMessage
+ {
+ public:
+ explicit RingingAlarmTurnOffRequestMessage(const std::uint32_t id = 0) : id(id){};
+ const std::uint32_t id;
+ };
+
+ class RingingAlarmTurnOffResponseMessage : public AlarmResponse
+ {
+ public:
+ explicit RingingAlarmTurnOffResponseMessage(const bool success = false) : success(success){};
+ const bool success;
+ };
+
+ class RingingAlarmSnoozeRequestMessage : public AlarmMessage
+ {
+ public:
+ RingingAlarmSnoozeRequestMessage(const std::uint32_t id, const TimePoint nextAlarmTime = TIME_POINT_INVALID)
+ : id(id), nextAlarmTime(nextAlarmTime){};
+ const std::uint32_t id;
+ const TimePoint nextAlarmTime;
+ };
+
+ class RingingAlarmSnoozeResponseMessage : public AlarmResponse
+ {
+ public:
+ explicit RingingAlarmSnoozeResponseMessage(const bool success = false) : success(success){};
+ const bool success;
+ };
+
} // namespace alarms
M module-services/service-time/include/service-time/AlarmServiceAPI.hpp => module-services/service-time/include/service-time/AlarmServiceAPI.hpp +2 -0
@@ 27,6 27,8 @@ namespace alarms
bool requestGetAlarmsInRange(
sys::Service *serv, TimePoint start, TimePoint end, unsigned int offset, unsigned int limit);
bool requestGetNextSingleEvents(sys::Service *serv);
+ bool requestTurnOffRingingAlarm(sys::Service *serv, const std::uint32_t id);
+ bool requestSnoozeRingingAlarm(sys::Service *serv, const std::uint32_t id, const TimePoint nextAlarmTime);
}; // namespace AlarmServiceAPI
} // namespace alarms
M module-services/service-time/tests/MockAlarmHandler.hpp => module-services/service-time/tests/MockAlarmHandler.hpp +5 -0
@@ 16,5 16,10 @@ namespace alarms
LOG_DEBUG("MockAlarmHandler");
return true;
}
+ auto handleOff(const AlarmEventRecord &record) -> bool
+ {
+ LOG_DEBUG("MockAlarmHandler");
+ return true;
+ }
};
} // namespace alarms
M module-services/service-time/tests/tests-AlarmOperations.cpp => module-services/service-time/tests/tests-AlarmOperations.cpp +1 -0
@@ 14,6 14,7 @@ class MockAlarmHandler : public alarms::AlarmHandler
{
public:
MOCK_METHOD(bool, handle, (const AlarmEventRecord &record), ());
+ MOCK_METHOD(bool, handleOff, (const AlarmEventRecord &record), ());
};
class MockAlarmEventsRepository : public alarms::AbstractAlarmEventsRepository
{
M products/BellHybrid/alarms/BellAlarmHandler.cpp => products/BellHybrid/alarms/BellAlarmHandler.cpp +16 -2
@@ 30,11 30,25 @@ namespace alarms
return result;
}
- auto EveningReminderHandler::handle(const AlarmEventRecord &record) -> bool
+ auto BellAlarmClockHandler::handleOff([[maybe_unused]] const AlarmEventRecord &record) -> bool
+ {
+ auto result{true};
+ for (const auto &action : actions) {
+ result &= action->turnOff();
+ }
+
+ return result;
+ }
+
+ auto EveningReminderHandler::handle([[maybe_unused]] const AlarmEventRecord &record) -> bool
{
- LOG_DEBUG("EveningReminderHandler");
// implement this alarm type handling here
return true;
}
+ auto EveningReminderHandler::handleOff([[maybe_unused]] const AlarmEventRecord &record) -> bool
+ {
+ return true;
+ }
+
} // namespace alarms
M products/BellHybrid/alarms/include/AbstractAlarmAction.hpp => products/BellHybrid/alarms/include/AbstractAlarmAction.hpp +1 -0
@@ 10,5 10,6 @@ namespace alarms
public:
virtual ~AbstractAlarmAction() = default;
virtual bool execute() = 0;
+ virtual bool turnOff() = 0;
};
} // namespace alarms
M products/BellHybrid/alarms/include/BellAlarmHandler.hpp => products/BellHybrid/alarms/include/BellAlarmHandler.hpp +2 -0
@@ 14,6 14,7 @@ namespace alarms
public:
explicit BellAlarmClockHandler(sys::Service *service);
auto handle(const AlarmEventRecord &record) -> bool;
+ auto handleOff(const AlarmEventRecord &record) -> bool;
static constexpr auto name = "BellAlarmClockHandler";
@@ 26,5 27,6 @@ namespace alarms
{
public:
auto handle(const AlarmEventRecord &record) -> bool;
+ auto handleOff(const AlarmEventRecord &record) -> bool;
};
} // namespace alarms
M products/BellHybrid/alarms/src/actions/FrontlightAction.cpp => products/BellHybrid/alarms/src/actions/FrontlightAction.cpp +6 -0
@@ 10,4 10,10 @@ namespace alarms
// turnOnFrontlight after it will be implemented [BH-756]
return true;
}
+
+ bool FrontlightAction::turnOff()
+ {
+ // turnOffFrontlight after it will be implemented [BH-756]
+ return true;
+ }
} // namespace alarms
M products/BellHybrid/alarms/src/actions/FrontlightAction.hpp => products/BellHybrid/alarms/src/actions/FrontlightAction.hpp +1 -0
@@ 12,6 12,7 @@ namespace alarms
{
public:
bool execute() override;
+ bool turnOff() override;
};
} // namespace alarms
M products/BellHybrid/alarms/src/actions/NotifyGUIAction.cpp => products/BellHybrid/alarms/src/actions/NotifyGUIAction.cpp +4 -0
@@ 14,4 14,8 @@ namespace alarms
{
return service.bus.sendUnicast(std::make_shared<app::actions::AlarmTriggeredAction>(), service::name::appmgr);
}
+ bool NotifyGUIAction::turnOff()
+ {
+ return true;
+ }
} // namespace alarms
M products/BellHybrid/alarms/src/actions/NotifyGUIAction.hpp => products/BellHybrid/alarms/src/actions/NotifyGUIAction.hpp +1 -0
@@ 14,6 14,7 @@ namespace alarms
public:
explicit NotifyGUIAction(sys::Service &service);
bool execute() override;
+ bool turnOff() override;
private:
sys::Service &service;
M products/BellHybrid/alarms/src/actions/PlayToneAction.cpp => products/BellHybrid/alarms/src/actions/PlayToneAction.cpp +5 -0
@@ 32,6 32,11 @@ namespace alarms
return AudioServiceAPI::PlaybackStart(&service, audio::PlaybackType::Alarm, tonePath);
}
+ bool alarms::PlayToneAction::turnOff()
+ {
+ return true;
+ }
+
void PlayToneAction::detachTimer()
{
if (timer.isValid()) {
M products/BellHybrid/alarms/src/actions/PlayToneAction.hpp => products/BellHybrid/alarms/src/actions/PlayToneAction.hpp +1 -0
@@ 15,6 15,7 @@ namespace alarms
public:
explicit PlayToneAction(sys::Service &service);
bool execute() override;
+ bool turnOff() override;
private:
void spawnTimer(std::chrono::seconds timeout);
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 +1 -1
@@ 48,7 48,7 @@ namespace app
{
static auto GetManifest() -> manager::ApplicationManifest
{
- return {{manager::actions::Launch}};
+ return {{manager::actions::Launch, manager::actions::ShowAlarm}};
}
};
} // namespace app
M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp => products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp +6 -1
@@ 42,7 42,7 @@ namespace app::home_screen
{
if (not timer.isValid()) {
auto callback = [this](sys::Timer &) { stateController->handleTimerEvent(); };
- timer = sys::TimerFactory::createSingleShotTimer(app, timerName, defaultTimeout, callback);
+ timer = sys::TimerFactory::createSingleShotTimer(app, timerName, timeout, callback);
}
timer.stop();
timer.start();
@@ 84,4 84,9 @@ namespace app::home_screen
alarmModel->update();
}
}
+ void HomeScreenPresenter::handleAlarmModelReady()
+ {
+ getView()->setAlarmTime(alarmModel->getAlarmTime());
+ stateController->handleAlarmModelReady();
+ }
} // namespace app::home_screen
M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.hpp => products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.hpp +4 -1
@@ 14,6 14,7 @@
#include <utf8/UTF8.hpp>
#include <chrono>
+#include <functional>
namespace app
{
@@ 79,6 80,7 @@ namespace app::home_screen
virtual void spawnTimer(std::chrono::milliseconds timeout = defaultTimeout) = 0;
virtual void detachTimer() = 0;
virtual void handleAlarmRingingEvent() = 0;
+ virtual void handleAlarmModelReady() = 0;
static constexpr auto defaultTimeout = std::chrono::milliseconds{5000};
};
@@ 104,9 106,10 @@ namespace app::home_screen
void onDatabaseMessage(db::NotificationMessage *msg) override;
void refreshWindow() override;
- void spawnTimer(std::chrono::milliseconds timeout) override;
+ void spawnTimer(std::chrono::milliseconds timeout = defaultTimeout) override;
void detachTimer() override;
void handleAlarmRingingEvent() override;
+ void handleAlarmModelReady() override;
private:
Application *app;
M products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp => products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp +51 -33
@@ 37,25 37,14 @@ namespace app::home_screen
auto updateTemperature = [](AbstractView &view, AbstractTemperatureModel &temperatureModel) {
view.setTemperature(temperatureModel.getTemperature());
};
-
- auto setDefaultAlarmTime =
- [](AbstractView &view, AbstractAlarmModel &alarmModel, AbstractTimeModel &timeModel) {
- constexpr auto defaultAlarmTimeHour = 7U;
- constexpr auto defaultAlarmTimeMin = 0U;
- const auto now = timeModel.getCurrentTime();
- const auto newTime = std::localtime(&now);
- newTime->tm_hour = defaultAlarmTimeHour;
- newTime->tm_min = defaultAlarmTimeMin;
- auto alarmTime = std::mktime(newTime);
-
- if (alarmTime < now) {
- alarmTime += utils::time::secondsInDay;
- }
- view.setAlarmTime(alarmTime);
- alarmModel.setAlarmTime(alarmTime);
+ auto setNewAlarmTime =
+ [](AbstractView &view, AbstractAlarmModel &alarmModel, AbstractPresenter &presenter) {
+ alarmModel.setAlarmTime(view.getAlarmTime());
+ detachTimer(presenter);
};
auto isAlarmActive = [](AbstractAlarmModel &alarmModel) -> bool { return alarmModel.isActive(); };
+ auto isSnoozeAllowed = [](AbstractAlarmModel &alarmModel) -> bool { return alarmModel.isSnoozeAllowed(); };
} // namespace Helpers
@@ 79,15 68,30 @@ namespace app::home_screen
{};
struct AlarmRinging
{};
+ struct ModelReady
+ {};
} // namespace Events
+ namespace Init
+ {
+ auto entry = [](AbstractView &view,
+ AbstractTemperatureModel &temperatureModel,
+ AbstractPresenter &presenter,
+ AbstractAlarmModel &alarmModel) {
+ alarmModel.update([&]() { presenter.handleAlarmModelReady(); });
+ view.setAlarmEdit(false);
+ view.setAlarmActive(false);
+ view.setAlarmVisible(false);
+ view.setTemperature(temperatureModel.getTemperature());
+ };
+ } // namespace Init
+
namespace Deactivated
{
auto entry = [](AbstractView &view,
AbstractTemperatureModel &temperatureModel,
AbstractAlarmModel &alarmModel,
AbstractTimeModel &timeModel) {
- Helpers::setDefaultAlarmTime(view, alarmModel, timeModel);
view.setAlarmEdit(false);
view.setAlarmActive(false);
view.setAlarmVisible(false);
@@ 147,7 151,6 @@ namespace app::home_screen
AbstractPresenter &presenter,
AbstractAlarmModel &alarmModel,
AbstractTimeModel &timeModel) {
- alarmModel.setAlarmTime(view.getAlarmTime());
alarmModel.activate(true);
presenter.spawnTimer();
view.setBottomDescription(utils::time::getBottomDescription(
@@ 172,7 175,7 @@ namespace app::home_screen
namespace AlarmRinging
{
auto entry = [](AbstractView &view, AbstractPresenter &presenter) {
- presenter.spawnTimer();
+ presenter.spawnTimer(defaultAlarmRingingTime);
view.setAlarmTimeVisible(false);
view.setAlarmTriggered();
};
@@ 181,8 184,9 @@ namespace app::home_screen
namespace AlarmRingingDeactivatedWait
{
- auto entry = [](AbstractView &view, AbstractPresenter &presenter) {
+ auto entry = [](AbstractView &view, AbstractAlarmModel &alarmModel, AbstractPresenter &presenter) {
presenter.spawnTimer();
+ alarmModel.turnOff();
view.setBottomDescription(utils::translate("app_bell_alarm_ringing_deactivated"));
view.setAlarmActive(false);
};
@@ 191,12 195,13 @@ namespace app::home_screen
namespace AlarmSnoozedWait
{
- auto entry = [](AbstractView &view, AbstractPresenter &presenter) {
+ auto entry = [](AbstractView &view, AbstractAlarmModel &alarmModel, AbstractPresenter &presenter) {
presenter.spawnTimer();
+ alarmModel.snooze();
view.setAlarmTimeVisible(false);
view.setAlarmSnoozed();
- const auto bottomDescription = utils::translate("app_bellmain_home_screen_bottom_desc") +
- " 10 min"; // TODO: Get duration from settings
+ const auto bottomDescription = utils::translate("app_bellmain_home_screen_bottom_desc") + " " +
+ std::to_string(alarmModel.getSnoozeDuration()) + " min";
view.setBottomDescription(bottomDescription);
};
auto exit = [](AbstractPresenter &presenter) { presenter.detachTimer(); };
@@ 221,7 226,10 @@ namespace app::home_screen
{
using namespace sml;
// clang-format off
- return make_transition_table(*"Deactivated"_s + sml::on_entry<_> / Deactivated::entry,
+ return make_transition_table(*"Init"_s + sml::on_entry<_> / Init::entry,
+ "Init"_s + event<Events::ModelReady> = "Deactivated"_s,
+
+ "Deactivated"_s + sml::on_entry<_> / Deactivated::entry,
"Deactivated"_s [Helpers::isAlarmActive] = "Activated"_s,
"Deactivated"_s + event<Events::LightPress>/ Helpers::switchToMenu = "Deactivated"_s,
"Deactivated"_s + event<Events::RotateRightPress> / Helpers::makeAlarmEditable = "DeactivatedEdit"_s,
@@ 239,8 247,8 @@ namespace app::home_screen
"DeactivatedEdit"_s + event<Events::RotateLeftPress> / AlarmEdit::processRotateLeft,
"DeactivatedEdit"_s + event<Events::RotateRightPress> / AlarmEdit::processRotateRight,
"DeactivatedEdit"_s + event<Events::DeepUpPress> / Helpers::detachTimer = "ActivatedWait"_s,
- "DeactivatedEdit"_s + event<Events::Timer> = "WaitForConfirmation"_s,
- "DeactivatedEdit"_s + event<Events::LightPress> / Helpers::detachTimer = "WaitForConfirmation"_s,
+ "DeactivatedEdit"_s + event<Events::Timer> / Helpers::setNewAlarmTime = "WaitForConfirmation"_s,
+ "DeactivatedEdit"_s + event<Events::LightPress> / Helpers::setNewAlarmTime = "WaitForConfirmation"_s,
"WaitForConfirmation"_s + sml::on_entry<_> / WaitForConfirmation::entry,
"WaitForConfirmation"_s + sml::on_exit<_> / WaitForConfirmation::exit,
@@ 265,15 273,19 @@ namespace app::home_screen
"ActivatedEdit"_s + event<Events::TimeUpdate> / Helpers::updateTemperature,
"ActivatedEdit"_s + event<Events::RotateLeftPress> / AlarmEdit::processRotateLeft,
"ActivatedEdit"_s + event<Events::RotateRightPress> / AlarmEdit::processRotateRight,
- "ActivatedEdit"_s + event<Events::Timer> = "ActivatedWait"_s,
- "ActivatedEdit"_s + event<Events::LightPress> / Helpers::detachTimer = "ActivatedWait"_s,
+ "ActivatedEdit"_s + event<Events::Timer> / Helpers::setNewAlarmTime = "ActivatedWait"_s,
+ "ActivatedEdit"_s + event<Events::LightPress> / Helpers::setNewAlarmTime = "ActivatedWait"_s,
"AlarmRinging"_s + sml::on_entry<_> / AlarmRinging::entry,
"AlarmRinging"_s + sml::on_exit<_> / AlarmRinging::exit,
- "AlarmRinging"_s + event<Events::Timer> = "AlarmSnoozedWait"_s,
- "AlarmRinging"_s + event<Events::LightPress> = "AlarmSnoozedWait"_s,
- "AlarmRinging"_s + event<Events::RotateLeftPress> = "AlarmSnoozedWait"_s,
- "AlarmRinging"_s + event<Events::RotateRightPress> = "AlarmSnoozedWait"_s,
+ "AlarmRinging"_s + event<Events::Timer> [Helpers::isSnoozeAllowed] = "AlarmSnoozedWait"_s,
+ "AlarmRinging"_s + event<Events::Timer> [!Helpers::isSnoozeAllowed] = "AlarmRingingDeactivatedWait"_s,
+ "AlarmRinging"_s + event<Events::LightPress> [Helpers::isSnoozeAllowed] = "AlarmSnoozedWait"_s,
+ "AlarmRinging"_s + event<Events::LightPress> [!Helpers::isSnoozeAllowed] = "AlarmRingingDeactivatedWait"_s,
+ "AlarmRinging"_s + event<Events::RotateLeftPress> [Helpers::isSnoozeAllowed] = "AlarmSnoozedWait"_s,
+ "AlarmRinging"_s + event<Events::RotateLeftPress> [!Helpers::isSnoozeAllowed] = "AlarmRingingDeactivatedWait"_s,
+ "AlarmRinging"_s + event<Events::RotateRightPress> [Helpers::isSnoozeAllowed] = "AlarmSnoozedWait"_s,
+ "AlarmRinging"_s + event<Events::RotateRightPress> [!Helpers::isSnoozeAllowed] = "AlarmRingingDeactivatedWait"_s,
"AlarmRinging"_s + event<Events::DeepDownPress> = "AlarmRingingDeactivatedWait"_s,
"AlarmRingingDeactivatedWait"_s + sml::on_entry<_> / AlarmRingingDeactivatedWait::entry,
@@ 288,7 300,7 @@ namespace app::home_screen
"AlarmSnoozed"_s + sml::on_entry<_> / AlarmSnoozed::entry,
"AlarmSnoozed"_s + sml::on_entry<_> / AlarmSnoozed::exit,
- "AlarmSnoozed"_s + event<Events::Timer> = "AlarmRinging"_s,
+ "AlarmSnoozed"_s + event<Events::AlarmRinging> = "AlarmRinging"_s,
"AlarmSnoozed"_s + event<Events::DeepDownPress> = "DeactivatedWait"_s
);
// clang-format on
@@ 379,4 391,10 @@ namespace app::home_screen
pimpl->sm.process_event(Events::AlarmRinging{});
return true;
}
+
+ bool StateController::handleAlarmModelReady()
+ {
+ pimpl->sm.process_event(Events::ModelReady{});
+ return true;
+ }
} // namespace app::home_screen
M products/BellHybrid/apps/application-bell-main/presenters/StateController.hpp => products/BellHybrid/apps/application-bell-main/presenters/StateController.hpp +7 -0
@@ 5,10 5,15 @@
#include <common/models/AbstractAlarmModel.hpp>
#include <gui/input/InputEvent.hpp>
+
+#include <chrono>
#include <memory>
namespace app::home_screen
{
+
+ inline constexpr auto defaultAlarmRingingTime = std::chrono::minutes(5);
+
class AbstractView;
class AbstractPresenter;
class AbstractTemperatureModel;
@@ 22,6 27,7 @@ namespace app::home_screen
virtual bool handleTimerEvent() = 0;
virtual bool handleTimeUpdateEvent() = 0;
virtual bool handleAlarmRingingEvent() = 0;
+ virtual bool handleAlarmModelReady() = 0;
};
class StateController : public AbstractController
@@ 37,6 43,7 @@ namespace app::home_screen
bool handleTimerEvent() override;
bool handleTimeUpdateEvent() override;
bool handleAlarmRingingEvent() override;
+ bool handleAlarmModelReady() override;
private:
class Impl;
M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp => products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp +1 -1
@@ 6,7 6,7 @@
#include <application-bell-main/ApplicationBellMain.hpp>
#include <apps-common/widgets/BellBaseLayout.hpp>
-#include <apps-common/actions/AlarmTriggeredAction.hpp>
+#include <apps-common/actions/AlarmRingingData.hpp>
#include <gui/input/InputEvent.hpp>
#include <gui/widgets/TextFixedSize.hpp>
#include <gui/widgets/Style.hpp>
M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +1 -0
@@ 28,6 28,7 @@ target_link_libraries(application-bell-common
apps-common
PRIVATE
+ bell::db
module-gui
service-time
)
M products/BellHybrid/apps/common/include/common/models/AbstractAlarmModel.hpp => products/BellHybrid/apps/common/include/common/models/AbstractAlarmModel.hpp +14 -5
@@ 4,20 4,29 @@
#pragma once
#include <ctime>
+#include <cstdint>
+#include <functional>
namespace app
{
+
+ using AlarmModelReadyHandler = std::function<void()>;
+
class AbstractAlarmModel
{
public:
virtual ~AbstractAlarmModel() noexcept = default;
- virtual bool isActive() const = 0;
- virtual void setAlarmTime(time_t time) = 0;
- virtual time_t getAlarmTime() const = 0;
- virtual void activate(bool value) = 0;
+ virtual bool isActive() const = 0;
+ virtual void setAlarmTime(time_t time) = 0;
+ virtual time_t getAlarmTime() const = 0;
+ virtual void activate(bool value) = 0;
+ virtual std::uint32_t getSnoozeDuration() = 0;
+ virtual bool isSnoozeAllowed() = 0;
+ virtual void turnOff() = 0;
+ virtual void snooze() = 0;
/// Command model to update its internal data
- virtual void update() = 0;
+ virtual void update(AlarmModelReadyHandler callback = AlarmModelReadyHandler()) = 0;
};
} // namespace app
M products/BellHybrid/apps/common/include/common/models/AlarmModel.hpp => products/BellHybrid/apps/common/include/common/models/AlarmModel.hpp +16 -3
@@ 7,6 7,7 @@
#include <apps-common/AsyncTask.hpp>
#include <module-db/Interface/AlarmEventRecord.hpp>
+#include <service-db/Settings.hpp>
#include <functional>
@@ 17,6 18,8 @@ namespace app
namespace app
{
+ constexpr std::uint32_t maxSnoozeCount = 3;
+
class AlarmModel : public AbstractAlarmModel, public AsyncCallbackReceiver
{
public:
@@ 26,7 29,11 @@ namespace app
void setAlarmTime(time_t time) override;
time_t getAlarmTime() const override;
void activate(bool value) override;
- void update() override;
+ void update(AlarmModelReadyHandler callback) override;
+ std::uint32_t getSnoozeDuration() override;
+ bool isSnoozeAllowed() override;
+ void turnOff() override;
+ void snooze() override;
private:
enum class State
@@ 36,11 43,17 @@ namespace app
Valid
};
- void updateAlarm(const AlarmEventRecord &alarm);
+ void updateAlarm(AlarmEventRecord &alarm);
+ AlarmEventRecord generateDefaultAlarm() const;
+ std::shared_ptr<AlarmEventRecord> getAlarmPtr() const;
+
Application *app{};
- AlarmEventRecord cachedRecord;
State state{State::Invalid};
+ SingleEventRecord cachedRecord;
+ std::uint32_t snoozeCount = 0;
std::function<bool(sys::ResponseMessage *)> responseCallback;
+
+ mutable settings::Settings settings;
};
} // namespace app
M products/BellHybrid/apps/common/src/AlarmModel.cpp => products/BellHybrid/apps/common/src/AlarmModel.cpp +98 -17
@@ 4,8 4,10 @@
#include "models/AlarmModel.hpp"
#include <apps-common/Application.hpp>
+#include <db/SystemSettings.hpp>
#include <module-db/Interface/AlarmEventRecord.hpp>
#include <time/dateCommon.hpp>
+#include <service-time/AlarmServiceAPI.hpp>
#include <service-time/api/TimeSettingsApi.hpp>
#include <service-time/Constants.hpp>
#include <service-time/AlarmMessage.hpp>
@@ 14,40 16,52 @@ namespace app
{
AlarmModel::AlarmModel(Application *app) : app::AsyncCallbackReceiver{app}, app{app}
{
- responseCallback = [this](const auto response) -> bool {
+ state = State::InitInProgress;
+ settings.init(service::ServiceProxy{app->weak_from_this()});
+ }
+
+ void AlarmModel::update(AlarmModelReadyHandler callback)
+ {
+ responseCallback = [this, callback](const auto response) -> bool {
const auto resp = dynamic_cast<alarms::AlarmGetResponseMessage *>(response);
if (resp) {
if (resp->alarm.isValid()) {
- cachedRecord = resp->alarm;
+ auto alarm = resp->alarm;
+ cachedRecord = alarm.getNextSingleEvent(TimePointNow());
state = State::Valid;
+ snoozeCount = 0;
+ if (callback) {
+ callback();
+ }
}
else if (state == State::InitInProgress) {
/// We received invalid response from DB during model initialization. It means alarm record does not
/// exist, hence we need to create one.
- auto request = AsyncRequest::createFromMessage(
- std::make_unique<alarms::AlarmAddRequestMessage>(cachedRecord), service::name::service_time);
+ auto defaultAlarm = generateDefaultAlarm();
+ auto request = AsyncRequest::createFromMessage(
+ std::make_unique<alarms::AlarmAddRequestMessage>(defaultAlarm), service::name::service_time);
request->execute(this->app, this, responseCallback);
state = State::Valid;
- this->update();
+ this->update(callback);
}
}
return true;
};
- state = State::InitInProgress;
- update();
- }
- void AlarmModel::update()
- {
+
auto request = AsyncRequest::createFromMessage(std::make_unique<alarms::AlarmGetRequestMessage>(),
service::name::service_time);
request->execute(app, this, responseCallback);
}
void AlarmModel::setAlarmTime(time_t time)
{
- cachedRecord.startDate = Clock::from_time_t(time);
+ auto alarmEventPtr = getAlarmPtr();
+ if (!alarmEventPtr) {
+ return;
+ }
+ alarmEventPtr->startDate = Clock::from_time_t(time);
- updateAlarm(cachedRecord);
+ updateAlarm(*alarmEventPtr);
}
time_t AlarmModel::getAlarmTime() const
{
@@ 55,19 69,86 @@ namespace app
}
void AlarmModel::activate(bool value)
{
- cachedRecord.enabled = value;
- updateAlarm(cachedRecord);
+ auto alarmEventPtr = getAlarmPtr();
+ if (!alarmEventPtr) {
+ return;
+ }
+ alarmEventPtr->enabled = value;
+ updateAlarm(*alarmEventPtr);
}
- void AlarmModel::updateAlarm(const AlarmEventRecord &alarm)
+ void AlarmModel::updateAlarm(AlarmEventRecord &alarm)
{
auto request = AsyncRequest::createFromMessage(std::make_unique<alarms::AlarmUpdateRequestMessage>(alarm),
service::name::service_time);
request->execute(app, this, responseCallback);
- cachedRecord = alarm;
+ cachedRecord = alarm.getNextSingleEvent(TimePointNow());
}
bool AlarmModel::isActive() const
{
- return cachedRecord.enabled;
+ if (!cachedRecord.parent) {
+ return false;
+ }
+
+ auto alarmEventPtr = getAlarmPtr();
+ if (!alarmEventPtr) {
+ return false;
+ }
+ return alarmEventPtr->enabled;
+ }
+ std::uint32_t AlarmModel::getSnoozeDuration()
+ {
+ const auto snoozeDurationStr =
+ settings.getValue(bell::settings::Snooze::length, settings::SettingsScope::Global);
+ const auto snoozeDuration = utils::getNumericValue<std::uint32_t>(snoozeDurationStr);
+
+ return snoozeDuration;
+ }
+ bool AlarmModel::isSnoozeAllowed()
+ {
+ const auto snoozeActiveStr = settings.getValue(bell::settings::Snooze::active, settings::SettingsScope::Global);
+ const auto snoozeActive = utils::getNumericValue<bool>(snoozeActiveStr);
+
+ return (snoozeActive && snoozeCount < maxSnoozeCount);
+ }
+ void AlarmModel::turnOff()
+ {
+ snoozeCount = 0;
+ alarms::AlarmServiceAPI::requestTurnOffRingingAlarm(app, cachedRecord.parent->ID);
+ }
+
+ void AlarmModel::snooze()
+ {
+ const auto snoozeDurationStr =
+ settings.getValue(bell::settings::Snooze::length, settings::SettingsScope::Global);
+ const auto snoozeDuration = utils::getNumericValue<std::uint32_t>(snoozeDurationStr);
+
+ snoozeCount++;
+ auto newAlarmTime =
+ std::chrono::floor<std::chrono::minutes>(TimePointNow()) + std::chrono::minutes(snoozeDuration);
+ alarms::AlarmServiceAPI::requestSnoozeRingingAlarm(app, cachedRecord.parent->ID, newAlarmTime);
+ }
+
+ AlarmEventRecord AlarmModel::generateDefaultAlarm() const
+ {
+ auto defaultAlarm = AlarmEventRecord{};
+ defaultAlarm.startDate = TimePointFromString("2021-01-01 07:00:00");
+ defaultAlarm.rruleText = "FREQ=DAILY";
+ defaultAlarm.endDate = TIME_POINT_MAX;
+ return defaultAlarm;
+ }
+
+ std::shared_ptr<AlarmEventRecord> AlarmModel::getAlarmPtr() const
+ {
+ if (!cachedRecord.parent) {
+ LOG_ERROR("Cached event has no parent");
+ return nullptr;
+ }
+ auto alarmEventPtr = std::dynamic_pointer_cast<AlarmEventRecord>(cachedRecord.parent);
+ if (!alarmEventPtr) {
+ LOG_ERROR("Processed event is not an alarm");
+ return nullptr;
+ }
+ return alarmEventPtr;
}
} // namespace app
M products/BellHybrid/services/db/include/db/SystemSettings.hpp => products/BellHybrid/services/db/include/db/SystemSettings.hpp +8 -0
@@ 14,4 14,12 @@ namespace bell::settings
constexpr inline auto duration = "ringing_duration";
constexpr inline auto tone = "ringing_tone";
} // namespace Ringing
+ namespace Snooze
+ {
+ constexpr inline auto active = "snooze_active";
+ constexpr inline auto length = "snooze_length";
+ constexpr inline auto interval = "snooze_interval";
+ constexpr inline auto tone = "snooze_tone";
+ constexpr inline auto volume = "snooze_volume";
+ } // namespace Snooze
}; // namespace bell::settings