M module-services/service-time/AlarmEventsDBRepository.cpp => module-services/service-time/AlarmEventsDBRepository.cpp +2 -2
@@ 13,7 13,7 @@
#include <module-db/queries/alarm_events/QueryAlarmEventsGetRecurringBetweenDates.hpp>
#include <module-db/queries/alarm_events/QueryAlarmEventsRemove.hpp>
-namespace alarmEvents
+namespace alarms
{
AlarmEventsDBRepository::AlarmEventsDBRepository(sys::Service *service) : service{service}
{}
@@ 108,4 108,4 @@ namespace alarmEvents
DBServiceAPI::GetQuery(service, db::Interface::Name::AlarmEvents, std::move(query));
}
-} // namespace alarmEvents
+} // namespace alarms
M module-services/service-time/AlarmEventsDBRepository.hpp => module-services/service-time/AlarmEventsDBRepository.hpp +4 -2
@@ 1,12 1,14 @@
// 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 "AlarmRepository.hpp"
#include <Service/Service.hpp>
#include <time/dateCommon.hpp>
-namespace alarmEvents
+namespace alarms
{
class AlarmEventsDBRepository : public AbstractAlarmEventsRepository
{
@@ 41,4 43,4 @@ namespace alarmEvents
template <typename requestT, typename responseT, typename callbackT, typename... Types>
void sendQueryWithCallback(const callbackT &callback, Types... queryArgs);
};
-} // namespace alarmEvents
+} // namespace alarms
A module-services/service-time/AlarmMessageHandler.cpp => module-services/service-time/AlarmMessageHandler.cpp +98 -0
@@ 0,0 1,98 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "AlarmMessageHandler.hpp"
+#include "ServiceTime.hpp"
+
+#include <module-db/Interface/AlarmEventRecord.hpp>
+#include <module-db/Interface/EventRecord.hpp>
+
+#include <service-time/AlarmMessage.hpp>
+
+namespace alarms
+{
+
+ AlarmMessageHandler::AlarmMessageHandler(stm::ServiceTime *service,
+ std::unique_ptr<IAlarmOperations> &&alarmOperations)
+ : service{service}, alarmOperations{std::move(alarmOperations)} {};
+
+ auto AlarmMessageHandler::handleGetAlarm(AlarmGetRequestMessage *request)
+ -> std::shared_ptr<AlarmGetResponseMessage>
+ {
+ return handleWithCallback<AlarmGetRequestMessage, AlarmGetResponseMessage, AlarmEventRecord>(
+ request, [&](AlarmGetRequestMessage *request, IAlarmOperations::OnGetAlarmProcessed callback) {
+ alarmOperations->getAlarm(request->id, callback);
+ });
+ }
+
+ auto AlarmMessageHandler::handleAddAlarm(AlarmAddRequestMessage *request)
+ -> std::shared_ptr<AlarmAddResponseMessage>
+ {
+ return handleWithCallback<AlarmAddRequestMessage, AlarmAddResponseMessage, bool>(
+ request, [&](AlarmAddRequestMessage *request, IAlarmOperations::OnAddAlarmProcessed callback) {
+ alarmOperations->addAlarm(request->alarmEvent, callback);
+ });
+ }
+
+ auto AlarmMessageHandler::handleUpdateAlarm(AlarmUpdateRequestMessage *request)
+ -> std::shared_ptr<AlarmUpdateResponseMessage>
+ {
+ return handleWithCallback<AlarmUpdateRequestMessage, AlarmUpdateResponseMessage, bool>(
+ request, [&](AlarmUpdateRequestMessage *request, IAlarmOperations::OnUpdateAlarmProcessed callback) {
+ alarmOperations->updateAlarm(request->alarmEvent, callback);
+ });
+ }
+
+ auto AlarmMessageHandler::handleRemoveAlarm(AlarmRemoveRequestMessage *request)
+ -> std::shared_ptr<AlarmRemoveResponseMessage>
+ {
+ return handleWithCallback<AlarmRemoveRequestMessage, AlarmRemoveResponseMessage, bool>(
+ request, [&](AlarmRemoveRequestMessage *request, IAlarmOperations::OnRemoveAlarmProcessed callback) {
+ alarmOperations->removeAlarm(request->id, callback);
+ });
+ }
+
+ auto AlarmMessageHandler::handleGetAlarmsInRange(AlarmsGetInRangeRequestMessage *request)
+ -> std::shared_ptr<AlarmsGetInRangeResponseMessage>
+ {
+ return handleWithCallback<AlarmsGetInRangeRequestMessage,
+ AlarmsGetInRangeResponseMessage,
+ std::vector<AlarmEventRecord>>(
+ request,
+ [&](AlarmsGetInRangeRequestMessage *request, IAlarmOperations::OnGetAlarmsInRangeProcessed callback) {
+ alarmOperations->getAlarmsInRange(
+ request->start, request->end, request->offset, request->limit, callback);
+ });
+ }
+
+ auto AlarmMessageHandler::handleGetNextSingleEvents(AlarmGetNextSingleEventsRequestMessage *request)
+ -> std::shared_ptr<AlarmGetNextSingleEventsResponseMessage>
+ {
+ return handleWithCallback<AlarmGetNextSingleEventsRequestMessage,
+ AlarmGetNextSingleEventsResponseMessage,
+ std::vector<SingleEventRecord>>(
+ request,
+ [&](AlarmGetNextSingleEventsRequestMessage *request, IAlarmOperations::OnGetNextSingleProcessed callback) {
+ alarmOperations->getNextSingleEvents(TimePointNow(), callback);
+ });
+ }
+
+ template <class RequestType, class ResponseType, class CallbackParamType>
+ auto AlarmMessageHandler::handleWithCallback(
+ RequestType *request,
+ const std::function<void(RequestType *request, std::function<void(CallbackParamType)>)>
+ &alarmOperationsCallback) -> std::shared_ptr<ResponseType>
+ {
+ auto uniID = request->uniID;
+ auto sender = request->sender;
+ auto callback = [&, uniID, sender](CallbackParamType param) {
+ auto response = std::make_shared<ResponseType>(param);
+ response->uniID = uniID;
+ service->bus.sendUnicast(response, sender);
+ };
+
+ alarmOperationsCallback(request, callback);
+ return sys::MessageNone{};
+ }
+
+} // namespace alarms
A module-services/service-time/AlarmMessageHandler.hpp => module-services/service-time/AlarmMessageHandler.hpp +42 -0
@@ 0,0 1,42 @@
+// 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 "AlarmOperations.hpp"
+
+#include <service-time/AlarmMessage.hpp>
+
+#include <Service/Service.hpp>
+
+namespace stm
+{
+ class ServiceTime;
+}
+
+namespace alarms
+{
+ class AlarmMessageHandler
+ {
+ public:
+ AlarmMessageHandler(stm::ServiceTime *service, std::unique_ptr<IAlarmOperations> &&alarmOperations);
+
+ auto handleGetAlarm(AlarmGetRequestMessage *request) -> std::shared_ptr<AlarmGetResponseMessage>;
+ auto handleAddAlarm(AlarmAddRequestMessage *request) -> std::shared_ptr<AlarmAddResponseMessage>;
+ auto handleUpdateAlarm(AlarmUpdateRequestMessage *request) -> std::shared_ptr<AlarmUpdateResponseMessage>;
+ auto handleRemoveAlarm(AlarmRemoveRequestMessage *request) -> std::shared_ptr<AlarmRemoveResponseMessage>;
+ auto handleGetAlarmsInRange(AlarmsGetInRangeRequestMessage *request)
+ -> std::shared_ptr<AlarmsGetInRangeResponseMessage>;
+ auto handleGetNextSingleEvents(AlarmGetNextSingleEventsRequestMessage *request)
+ -> std::shared_ptr<AlarmGetNextSingleEventsResponseMessage>;
+
+ private:
+ stm::ServiceTime *service = nullptr;
+ std::unique_ptr<IAlarmOperations> alarmOperations;
+
+ template <class RequestType, class ResponseType, class CallbackParamType>
+ auto handleWithCallback(RequestType *request,
+ const std::function<void(RequestType *request, std::function<void(CallbackParamType)>)>
+ &alarmOperationsCallback) -> std::shared_ptr<ResponseType>;
+ };
+} // namespace alarms
A module-services/service-time/AlarmOperations.cpp => module-services/service-time/AlarmOperations.cpp +107 -0
@@ 0,0 1,107 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "AlarmOperations.hpp"
+
+namespace alarms
+{
+ AlarmOperations::AlarmOperations(std::unique_ptr<AbstractAlarmEventsRepository> &&alarmEventsRepo)
+ : alarmEventsRepo{std::move(alarmEventsRepo)} {};
+
+ void AlarmOperations::getAlarm(const std::uint32_t alarmId, OnGetAlarmProcessed callback)
+ {
+ OnGetAlarmEventCallback repoCallback = [callback](AlarmEventRecord record) { callback(record); };
+ alarmEventsRepo->getAlarmEvent(alarmId, repoCallback);
+ }
+
+ void AlarmOperations::addAlarm(AlarmEventRecord record, OnAddAlarmProcessed callback)
+ {
+ OnAddAlarmEventCallback repoCallback = [callback](bool success) { callback(success); };
+ alarmEventsRepo->addAlarmEvent(record, repoCallback);
+ }
+ void AlarmOperations::updateAlarm(AlarmEventRecord record, OnUpdateAlarmProcessed callback)
+ {
+ OnUpdateAlarmEventCallback repoCallback = [callback](bool success) { callback(success); };
+ alarmEventsRepo->updateAlarmEvent(record, repoCallback);
+ }
+
+ void AlarmOperations::removeAlarm(const std::uint32_t alarmId, OnRemoveAlarmProcessed callback)
+ {
+ OnRemoveAlarmEventCallback repoCallback = [callback](bool success) { callback(success); };
+ alarmEventsRepo->removeAlarmEvent(alarmId, repoCallback);
+ }
+
+ void AlarmOperations::getAlarmsInRange(
+ TimePoint start, TimePoint end, std::uint32_t offset, std::uint32_t limit, OnGetAlarmsInRangeProcessed callback)
+ {
+ OnGetAlarmEventsInRangeCallback repoCallback = [callback](std::vector<AlarmEventRecord> records) {
+ callback(records);
+ };
+ alarmEventsRepo->getAlarmEventsInRange(start, end, offset, limit, repoCallback);
+ }
+
+ void AlarmOperations::getNextSingleEvents(TimePoint start, OnGetNextSingleProcessed callback)
+ {
+ auto nextEvents = std::make_shared<std::vector<AlarmEventRecord>>();
+
+ OnGetAlarmEventsRecurringInRange repoGetRecurringCallback =
+ [&, callback, nextEvents, start](std::vector<AlarmEventRecord> records) {
+ onRepoGetRecurringInRangeResponse(callback, nextEvents, start, records);
+ };
+
+ OnGetNextCallback repoGetNextCallback =
+ [&, callback, nextEvents, start, repoGetRecurringCallback](std::vector<AlarmEventRecord> records) {
+ onRepoGetNextResponse(callback, nextEvents, start, repoGetRecurringCallback, records);
+ };
+
+ alarmEventsRepo->getNext(start, getNextSingleEventsOffset, getNextSingleEventsLimit, repoGetNextCallback);
+ }
+
+ void AlarmOperations::onRepoGetNextResponse(OnGetNextSingleProcessed handledCallback,
+ std::shared_ptr<std::vector<AlarmEventRecord>> nextEvents,
+ TimePoint start,
+ OnGetAlarmEventsRecurringInRange recurringCallback,
+ std::vector<AlarmEventRecord> records)
+ {
+ if (records.empty()) {
+ handledCallback({});
+ }
+ else {
+ *nextEvents = std::move(records);
+ auto firstEventTimePoint = (*nextEvents)[0].startDate;
+ nextEvents->erase(std::remove_if(nextEvents->begin(),
+ nextEvents->end(),
+ [](AlarmEventRecord rec) { return !rec.rruleText.empty(); }),
+ nextEvents->end());
+ alarmEventsRepo->getAlarmEventsRecurringInRange(
+ start, firstEventTimePoint, getNextSingleEventsOffset, getNextSingleEventsLimit, recurringCallback);
+ }
+ }
+
+ void AlarmOperations::onRepoGetRecurringInRangeResponse(OnGetNextSingleProcessed handledCallback,
+ std::shared_ptr<std::vector<AlarmEventRecord>> nextEvents,
+ TimePoint start,
+ std::vector<AlarmEventRecord> records)
+ {
+ std::vector<SingleEventRecord> outEvents;
+ if (!records.empty()) {
+ (*nextEvents)
+ .insert(nextEvents->end(),
+ std::make_move_iterator(records.begin()),
+ std::make_move_iterator(records.end()));
+ }
+ TimePoint nearestTimePoint = TIME_POINT_MAX;
+ for (auto &event : (*nextEvents)) {
+ auto newSingle = event.getNextSingleEvent(start);
+ if (newSingle.startDate == nearestTimePoint) {
+ outEvents.push_back(newSingle);
+ }
+ else if (newSingle.startDate < nearestTimePoint) {
+ nearestTimePoint = newSingle.startDate;
+ outEvents.clear();
+ outEvents.push_back(newSingle);
+ }
+ }
+ handledCallback(outEvents);
+ }
+} // namespace alarms
A module-services/service-time/AlarmOperations.hpp => module-services/service-time/AlarmOperations.hpp +68 -0
@@ 0,0 1,68 @@
+// 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 "AlarmRepository.hpp"
+
+#include <module-db/Interface/AlarmEventRecord.hpp>
+
+namespace alarms
+{
+
+ class IAlarmOperations
+ {
+ public:
+ using OnGetAlarmProcessed = std::function<void(AlarmEventRecord)>;
+ using OnGetAlarmsInRangeProcessed = std::function<void(std::vector<AlarmEventRecord>)>;
+ using OnAddAlarmProcessed = std::function<void(bool)>;
+ using OnUpdateAlarmProcessed = std::function<void(bool)>;
+ using OnRemoveAlarmProcessed = std::function<void(bool)>;
+ using OnGetNextSingleProcessed = std::function<void(std::vector<SingleEventRecord>)>;
+
+ virtual void getAlarm(const std::uint32_t alarmId, OnGetAlarmProcessed callback) = 0;
+ virtual void addAlarm(AlarmEventRecord record, OnAddAlarmProcessed callback) = 0;
+ virtual void updateAlarm(AlarmEventRecord record, OnUpdateAlarmProcessed callback) = 0;
+ virtual void removeAlarm(const std::uint32_t alarmId, OnRemoveAlarmProcessed callback) = 0;
+ virtual void getAlarmsInRange(TimePoint start,
+ TimePoint end,
+ std::uint32_t offset,
+ std::uint32_t limit,
+ OnGetAlarmsInRangeProcessed callback) = 0;
+ virtual void getNextSingleEvents(TimePoint start, OnGetNextSingleProcessed callback) = 0;
+ };
+
+ class AlarmOperations : public IAlarmOperations
+ {
+ public:
+ explicit AlarmOperations(std::unique_ptr<AbstractAlarmEventsRepository> &&alarmEventsRepo);
+
+ void getAlarm(const std::uint32_t alarmId, OnGetAlarmProcessed callback) override;
+ void addAlarm(AlarmEventRecord record, OnAddAlarmProcessed callback) override;
+ void updateAlarm(AlarmEventRecord record, OnUpdateAlarmProcessed callback) override;
+ void removeAlarm(const std::uint32_t alarmId, OnRemoveAlarmProcessed callback) override;
+ void getAlarmsInRange(TimePoint start,
+ TimePoint end,
+ std::uint32_t offset,
+ std::uint32_t limit,
+ OnGetAlarmsInRangeProcessed callback) override;
+ void getNextSingleEvents(TimePoint start, OnGetNextSingleProcessed callback) override;
+
+ private:
+ std::unique_ptr<AbstractAlarmEventsRepository> alarmEventsRepo;
+
+ // Max 100 alarms for one minute seems reasonable, next events will be dropped
+ constexpr static auto getNextSingleEventsOffset = 0;
+ constexpr static auto getNextSingleEventsLimit = 100;
+
+ void onRepoGetNextResponse(OnGetNextSingleProcessed handledCallback,
+ std::shared_ptr<std::vector<AlarmEventRecord>> nextEvents,
+ TimePoint start,
+ OnGetAlarmEventsRecurringInRange recurringCallback,
+ std::vector<AlarmEventRecord> records);
+ void onRepoGetRecurringInRangeResponse(OnGetNextSingleProcessed handledCallback,
+ std::shared_ptr<std::vector<AlarmEventRecord>> nextEvents,
+ TimePoint start,
+ std::vector<AlarmEventRecord> records);
+ };
+} // namespace alarms
M module-services/service-time/AlarmRepository.hpp => module-services/service-time/AlarmRepository.hpp +10 -13
@@ 3,7 3,6 @@
#pragma once
-#include <service-time/AlarmMessage.hpp>
#include <module-sys/Service/Service.hpp>
#include <time/dateCommon.hpp>
@@ 18,22 17,20 @@ class AlarmEventRecord;
/**
* @brief Basic interface alarm API
*/
-namespace alarmEvents
+namespace alarms
{
+ using OnGetAlarmEventCallback = std::function<void(AlarmEventRecord)>;
+ using OnGetAlarmEventsCallback = std::function<void(std::vector<AlarmEventRecord>)>;
+ using OnGetAlarmEventsInRangeCallback = std::function<void(std::vector<AlarmEventRecord>)>;
+ using OnAddAlarmEventCallback = std::function<void(bool)>;
+ using OnUpdateAlarmEventCallback = std::function<void(bool)>;
+ using OnRemoveAlarmEventCallback = std::function<void(bool)>;
+ using OnGetNextCallback = std::function<void(std::vector<AlarmEventRecord>)>;
+ using OnGetAlarmEventsRecurringInRange = std::function<void(std::vector<AlarmEventRecord>)>;
class AbstractAlarmEventsRepository
{
public:
- using OnGetAlarmEventCallback = std::function<void(AlarmEventRecord)>;
- using OnGetAlarmEventsCallback = std::function<void(std::vector<AlarmEventRecord>)>;
- using OnGetAlarmEventsInRangeCallback = std::function<void(std::vector<AlarmEventRecord>)>;
- using OnAddAlarmEventCallback = std::function<void(bool)>;
- using OnUpdateAlarmEventCallback = std::function<void(bool)>;
- using OnRemoveAlarmEventCallback = std::function<void(bool)>;
- using OnGetNextCallback = std::function<void(std::vector<AlarmEventRecord>)>;
- using OnGetAlarmEventsRecurringInRange = std::function<void(std::vector<AlarmEventRecord>)>;
-
- public:
/**
* Default destructor
*/
@@ 112,4 109,4 @@ namespace alarmEvents
std::uint32_t limit,
const OnGetAlarmEventsRecurringInRange &callback) = 0;
};
-} // namespace alarmEvents
+} // namespace alarms
M module-services/service-time/CMakeLists.txt => module-services/service-time/CMakeLists.txt +8 -0
@@ 4,11 4,18 @@ message( "${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}" )
set(SOURCES
AlarmHandlerFactory.cpp
AlarmEventsDBRepository.cpp
+ AlarmMessageHandler.cpp
+ AlarmOperations.cpp
ServiceTime.cpp
TimeManager.cpp
RTCcommand.cpp
TimezoneHandler.cpp
internal/StaticData.cpp
+
+ include/service-time/AlarmHandler.hpp
+ include/service-time/AlarmHandlerFactory.hpp
+ include/service-time/AlarmMessage.hpp
+ include/service-time/AlarmServiceAPI.hpp
)
add_library(${PROJECT_NAME} STATIC ${SOURCES})
@@ 21,6 28,7 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME}
PRIVATE
+ module-db
time
service-db
service-time-api
M module-services/service-time/ServiceTime.cpp => module-services/service-time/ServiceTime.cpp +32 -3
@@ 1,17 1,20 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include "AlarmMessageHandler.hpp"
#include "ServiceTime.hpp"
-#include "service-time/TimeMessage.hpp"
-#include "service-time/RTCCommand.hpp"
+#include <service-time/AlarmMessage.hpp>
#include <service-time/internal/StaticData.hpp>
+#include <service-time/RTCCommand.hpp>
+#include <service-time/TimeMessage.hpp>
#include <service-time/TimeSettings.hpp>
#include <service-time/TimezoneHandler.hpp>
#include <BaseInterface.hpp>
#include <Common/Query.hpp>
-#include <MessageType.hpp>
#include <log.hpp>
+#include <MessageType.hpp>
+#include <module-db/Interface/EventRecord.hpp>
#include <service-db/DBNotificationMessage.hpp>
#include <service-db/QueryMessage.hpp>
#include <service-cellular/service-cellular/CellularMessage.hpp>
@@ 37,6 40,10 @@ namespace stm
bus.channels.push_back(sys::BusChannel::ServiceDBNotifications);
timeManager = std::make_unique<TimeManager>(std::make_unique<RTCCommand>(this));
+
+ auto alarmEventsRepo = std::make_unique<alarms::AlarmEventsDBRepository>(this);
+ auto alarmOperations = std::make_unique<alarms::AlarmOperations>(std::move(alarmEventsRepo));
+ alarmMessageHandler = std::make_unique<alarms::AlarmMessageHandler>(this, std::move(alarmOperations));
}
ServiceTime::~ServiceTime()
@@ 105,6 112,28 @@ namespace stm
});
connect(typeid(stm::message::GetAutomaticDateAndTimeRequest),
[&](sys::Message *request) -> sys::MessagePointer { return handleGetAutomaticDateAndTimeRequest(); });
+
+ connect(typeid(alarms::AlarmGetRequestMessage), [&](sys::Message *request) -> sys::MessagePointer {
+ return alarmMessageHandler->handleGetAlarm(static_cast<alarms::AlarmGetRequestMessage *>(request));
+ });
+ connect(typeid(alarms::AlarmAddRequestMessage), [&](sys::Message *request) -> sys::MessagePointer {
+ return alarmMessageHandler->handleAddAlarm(static_cast<alarms::AlarmAddRequestMessage *>(request));
+ });
+ connect(typeid(alarms::AlarmUpdateRequestMessage), [&](sys::Message *request) -> sys::MessagePointer {
+ return alarmMessageHandler->handleUpdateAlarm(static_cast<alarms::AlarmUpdateRequestMessage *>(request));
+ });
+ connect(typeid(alarms::AlarmRemoveRequestMessage), [&](sys::Message *request) -> sys::MessagePointer {
+ return alarmMessageHandler->handleRemoveAlarm(static_cast<alarms::AlarmRemoveRequestMessage *>(request));
+ });
+ connect(typeid(alarms::AlarmsGetInRangeRequestMessage), [&](sys::Message *request) -> sys::MessagePointer {
+ return alarmMessageHandler->handleGetAlarmsInRange(
+ static_cast<alarms::AlarmsGetInRangeRequestMessage *>(request));
+ });
+ connect(typeid(alarms::AlarmGetNextSingleEventsRequestMessage),
+ [&](sys::Message *request) -> sys::MessagePointer {
+ return alarmMessageHandler->handleGetNextSingleEvents(
+ static_cast<alarms::AlarmGetNextSingleEventsRequestMessage *>(request));
+ });
}
auto ServiceTime::handleSetAutomaticDateAndTimeRequest(sys::Message *request)
M module-services/service-time/ServiceTime.hpp => module-services/service-time/ServiceTime.hpp +5 -0
@@ 3,6 3,8 @@
#pragma once
+#include "AlarmEventsDBRepository.hpp"
+#include "AlarmMessageHandler.hpp"
#include "Constants.hpp"
#include "service-time/TimeManager.hpp"
#include "service-time/ServiceTime.hpp"
@@ 33,6 35,8 @@ namespace stm
std::unique_ptr<settings::Settings> settings;
+ std::unique_ptr<alarms::AlarmMessageHandler> alarmMessageHandler;
+
void registerMessageHandlers();
auto handleSetAutomaticDateAndTimeRequest(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>;
auto handleSetTimeFormatRequest(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>;
@@ 40,6 44,7 @@ namespace stm
auto handleSetTimezoneRequest(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>;
auto handleCellularTimeNotificationMessage(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>;
auto handleGetAutomaticDateAndTimeRequest() -> std::shared_ptr<sys::ResponseMessage>;
+
void initStaticData();
public:
M module-services/service-time/include/service-time/AlarmMessage.hpp => module-services/service-time/include/service-time/AlarmMessage.hpp +18 -15
@@ 25,29 25,28 @@ namespace alarms
{
public:
AlarmGetRequestMessage(const unsigned int id = 1) : id(id){};
- unsigned int id;
+ const unsigned int id;
};
class AlarmGetResponseMessage : public AlarmMessage
{
public:
- AlarmGetResponseMessage(const std::vector<AlarmEventRecord> alarms = std::vector<AlarmEventRecord>())
- : alarms(alarms){};
- std::vector<AlarmEventRecord> alarms;
+ AlarmGetResponseMessage(const AlarmEventRecord alarm = AlarmEventRecord{}) : alarm(alarm){};
+ const AlarmEventRecord alarm;
};
class AlarmAddRequestMessage : public AlarmMessage
{
public:
AlarmAddRequestMessage(const AlarmEventRecord &alarmEvent = AlarmEventRecord()) : alarmEvent(alarmEvent){};
- AlarmEventRecord alarmEvent;
+ const AlarmEventRecord alarmEvent;
};
class AlarmAddResponseMessage : public AlarmMessage
{
public:
- AlarmAddResponseMessage(const AlarmEventRecord &alarmEvent = AlarmEventRecord()) : alarmEvent(alarmEvent){};
- AlarmEventRecord alarmEvent;
+ AlarmAddResponseMessage(const bool success = false) : success(success){};
+ const bool success;
};
class AlarmUpdateRequestMessage : public AlarmMessage
@@ 60,22 59,22 @@ namespace alarms
class AlarmUpdateResponseMessage : public AlarmMessage
{
public:
- AlarmUpdateResponseMessage(const AlarmEventRecord &alarmEvent = AlarmEventRecord()) : alarmEvent(alarmEvent){};
- AlarmEventRecord alarmEvent;
+ AlarmUpdateResponseMessage(const bool success = false) : success(success){};
+ const bool success;
};
class AlarmRemoveRequestMessage : public AlarmMessage
{
public:
AlarmRemoveRequestMessage(const unsigned int id = 0) : id(id){};
- unsigned int id;
+ const unsigned int id;
};
class AlarmRemoveResponseMessage : public AlarmMessage
{
public:
AlarmRemoveResponseMessage(const bool success = false) : success(success){};
- bool success;
+ const bool success;
};
class AlarmsGetInRangeRequestMessage : public AlarmMessage
@@ 83,10 82,14 @@ namespace alarms
public:
AlarmsGetInRangeRequestMessage(
const std::chrono::time_point<std::chrono::system_clock> start = TIME_POINT_INVALID,
- const std::chrono::time_point<std::chrono::system_clock> end = TIME_POINT_INVALID)
- : start(start), end(end){};
- std::chrono::time_point<std::chrono::system_clock> start;
- std::chrono::time_point<std::chrono::system_clock> end;
+ const std::chrono::time_point<std::chrono::system_clock> end = TIME_POINT_INVALID,
+ std::uint32_t offset = 0,
+ std::uint32_t limit = 0)
+ : start(start), end(end), offset(offset), limit(limit){};
+ const std::chrono::time_point<std::chrono::system_clock> start;
+ const std::chrono::time_point<std::chrono::system_clock> end;
+ const std::uint32_t offset;
+ const std::uint32_t limit;
};
class AlarmsGetInRangeResponseMessage : public AlarmMessage
M module-services/service-time/tests/CMakeLists.txt => module-services/service-time/tests/CMakeLists.txt +12 -0
@@ 19,3 19,15 @@ add_catch2_executable(
service-time
module-db
)
+
+add_gtest_executable(
+ NAME
+ service-time-alarm-operations
+ SRCS
+ tests-AlarmOperations.cpp
+ LIBS
+ module-sys
+ service-time
+ INCLUDE
+ $<TARGET_PROPERTY:service-time,INCLUDE_DIRECTORIES>
+)
A module-services/service-time/tests/tests-AlarmOperations.cpp => module-services/service-time/tests/tests-AlarmOperations.cpp +368 -0
@@ 0,0 1,368 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <AlarmOperations.hpp>
+#include <AlarmRepository.hpp>
+#include <module-db/Interface/AlarmEventRecord.hpp>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+class MockAlarmEventsRepository : public alarms::AbstractAlarmEventsRepository
+{
+ public:
+ std::vector<AlarmEventRecord> nextRecords;
+ std::vector<AlarmEventRecord> recurringRecords;
+
+ MOCK_METHOD(void,
+ getAlarmEvent,
+ (const std::uint32_t alarmId, const alarms::OnGetAlarmEventCallback &callback),
+ ());
+ MOCK_METHOD(void,
+ getAlarmEvents,
+ (std::uint32_t offset, std::uint32_t limit, const alarms::OnGetAlarmEventsCallback &callback),
+ ());
+ MOCK_METHOD(void,
+ getAlarmEventsInRange,
+ (TimePoint start,
+ TimePoint end,
+ std::uint32_t offset,
+ std::uint32_t limit,
+ const alarms::OnGetAlarmEventsInRangeCallback &callback),
+ ());
+ MOCK_METHOD(void,
+ addAlarmEvent,
+ (const AlarmEventRecord &alarmEvent, const alarms::OnAddAlarmEventCallback &callback),
+ ());
+ MOCK_METHOD(void,
+ updateAlarmEvent,
+ (const AlarmEventRecord &alarmEvent, const alarms::OnUpdateAlarmEventCallback &callback),
+ ());
+ MOCK_METHOD(void,
+ removeAlarmEvent,
+ (const std::uint32_t id, const alarms::OnRemoveAlarmEventCallback &callback),
+ ());
+ void getAlarmEventsRecurringInRange(TimePoint start,
+ TimePoint end,
+ std::uint32_t offset,
+ std::uint32_t limit,
+ const alarms::OnGetAlarmEventsRecurringInRange &callback)
+ {
+ callback({recurringRecords});
+ }
+
+ void getNext(TimePoint start, std::uint32_t offset, std::uint32_t limit, const alarms::OnGetNextCallback &callback)
+ {
+ callback({nextRecords});
+ }
+
+ void addSingleEvent(const AlarmEventRecord record)
+ {
+ nextRecords.push_back(record);
+ }
+
+ void addRecurringEvent(const AlarmEventRecord record)
+ {
+ addSingleEvent(record);
+ recurringRecords.push_back(record);
+ }
+};
+
+class AlarmOperationsFixture : public ::testing::Test
+{
+ protected:
+ auto getMockedAlarmOperations(std::unique_ptr<MockAlarmEventsRepository> &alarmRepo)
+ {
+ return std::make_unique<alarms::AlarmOperations>(std::move(alarmRepo));
+ }
+};
+
+constexpr auto defName = "";
+constexpr auto defDuration = 60;
+constexpr auto defAllDay = false;
+constexpr auto defRRule = "";
+constexpr auto defMusic = "";
+constexpr auto defEnabled = true;
+constexpr auto defSnooze = 15;
+
+TEST_F(AlarmOperationsFixture, getNextOneEvent)
+{
+ alarms::IAlarmOperations::OnGetNextSingleProcessed callback = [](std::vector<SingleEventRecord> records) {
+ EXPECT_EQ(records.size(), 1);
+ EXPECT_EQ(records[0].startDate, TimePointFromString("2022-11-11 09:00:00"));
+ EXPECT_EQ(records[0].parent->ID, 1);
+ };
+
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+ alarmRepoMock->nextRecords.push_back(AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-11-11 09:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ auto alarmOperations = getMockedAlarmOperations(alarmRepoMock);
+ alarmOperations->getNextSingleEvents(TimePointFromString("2020-01-01 00:00:00"), callback);
+}
+
+TEST_F(AlarmOperationsFixture, getNextTwoEvents)
+{
+ alarms::IAlarmOperations::OnGetNextSingleProcessed callback = [](std::vector<SingleEventRecord> records) {
+ EXPECT_EQ(records.size(), 1);
+ EXPECT_EQ(records[0].startDate, TimePointFromString("2022-11-11 09:00:00"));
+ EXPECT_EQ(records[0].parent->ID, 1);
+ };
+
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-11-11 09:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(2,
+ defName,
+ TimePointFromString("2022-12-11 02:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ auto alarmOperations = getMockedAlarmOperations(alarmRepoMock);
+ alarmOperations->getNextSingleEvents(TimePointFromString("2020-01-01 00:00:00"), callback);
+}
+
+TEST_F(AlarmOperationsFixture, getNextTwoEventsReversedOrder)
+{
+ alarms::IAlarmOperations::OnGetNextSingleProcessed callback = [](std::vector<SingleEventRecord> records) {
+ EXPECT_EQ(records.size(), 1);
+ EXPECT_EQ(records[0].startDate, TimePointFromString("2022-11-11 09:00:00"));
+ EXPECT_EQ(records[0].parent->ID, 2);
+ };
+
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-12-11 02:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(2,
+ defName,
+ TimePointFromString("2022-11-11 09:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ auto alarmOperations = getMockedAlarmOperations(alarmRepoMock);
+ alarmOperations->getNextSingleEvents(TimePointFromString("2020-01-01 00:00:00"), callback);
+}
+
+TEST_F(AlarmOperationsFixture, getNextWithRecursiveFirst)
+{
+ alarms::IAlarmOperations::OnGetNextSingleProcessed callback = [](std::vector<SingleEventRecord> records) {
+ EXPECT_EQ(records.size(), 1);
+ EXPECT_EQ(records[0].startDate, TimePointFromString("2022-01-11 02:00:00"));
+ EXPECT_EQ(records[0].parent->ID, 1);
+ };
+
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+
+ alarmRepoMock->addRecurringEvent(AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-01-11 02:00:00"),
+ defDuration,
+ defAllDay,
+ "FREQ=DAILY",
+ defMusic,
+ defEnabled,
+ defSnooze));
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(2,
+ defName,
+ TimePointFromString("2022-11-11 09:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ auto alarmOperations = getMockedAlarmOperations(alarmRepoMock);
+ alarmOperations->getNextSingleEvents(TimePointFromString("2020-01-01 00:00:00"), callback);
+}
+
+TEST_F(AlarmOperationsFixture, getNextWithRecursiveBeforeRange)
+{
+ alarms::IAlarmOperations::OnGetNextSingleProcessed callback = [](std::vector<SingleEventRecord> records) {
+ EXPECT_EQ(records.size(), 1);
+ EXPECT_EQ(records[0].startDate, TimePointFromString("2022-10-01 02:00:00"));
+ EXPECT_EQ(records[0].parent->ID, 1);
+ };
+
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+
+ alarmRepoMock->addRecurringEvent(AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-01-11 02:00:00"),
+ defDuration,
+ defAllDay,
+ "FREQ=DAILY",
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(2,
+ defName,
+ TimePointFromString("2022-11-11 09:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ auto alarmOperations = getMockedAlarmOperations(alarmRepoMock);
+ alarmOperations->getNextSingleEvents(TimePointFromString("2022-10-01 00:00:00"), callback);
+}
+
+TEST_F(AlarmOperationsFixture, getNextWithTwoRecursive)
+{
+ alarms::IAlarmOperations::OnGetNextSingleProcessed callback1 = [](std::vector<SingleEventRecord> records) {
+ EXPECT_EQ(records.size(), 1);
+ EXPECT_EQ(records[0].startDate, TimePointFromString("2022-10-01 09:00:00"));
+ EXPECT_EQ(records[0].parent->ID, 2);
+ };
+ alarms::IAlarmOperations::OnGetNextSingleProcessed callback2 = [](std::vector<SingleEventRecord> records) {
+ EXPECT_EQ(records.size(), 1);
+ EXPECT_EQ(records[0].startDate, TimePointFromString("2022-10-02 02:00:00"));
+ EXPECT_EQ(records[0].parent->ID, 1);
+ };
+
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+ alarmRepoMock->addRecurringEvent(AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-01-11 02:00:00"),
+ defDuration,
+ defAllDay,
+ "FREQ=DAILY",
+ defMusic,
+ defEnabled,
+ defSnooze));
+ alarmRepoMock->addRecurringEvent(AlarmEventRecord(2,
+ defName,
+ TimePointFromString("2022-01-11 09:00:00"),
+ defDuration,
+ defAllDay,
+ "FREQ=DAILY",
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ auto alarmOperations = getMockedAlarmOperations(alarmRepoMock);
+ alarmOperations->getNextSingleEvents(TimePointFromString("2022-10-01 03:00:00"), callback1);
+ alarmOperations->getNextSingleEvents(TimePointFromString("2022-10-01 17:00:00"), callback2);
+}
+
+TEST_F(AlarmOperationsFixture, getNextMultipleEvents)
+{
+ alarms::IAlarmOperations::OnGetNextSingleProcessed callback = [](std::vector<SingleEventRecord> records) {
+ EXPECT_EQ(records.size(), 2);
+ EXPECT_EQ(records[0].startDate, TimePointFromString("2022-01-01 02:00:00"));
+ EXPECT_EQ(records[0].parent->ID, 1);
+ EXPECT_EQ(records[1].startDate, TimePointFromString("2022-01-01 02:00:00"));
+ EXPECT_EQ(records[1].parent->ID, 3);
+ };
+
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-01-01 02:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(2,
+ defName,
+ TimePointFromString("2022-11-11 09:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(3,
+ defName,
+ TimePointFromString("2022-01-01 02:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ auto alarmOperations = getMockedAlarmOperations(alarmRepoMock);
+ alarmOperations->getNextSingleEvents(TimePointFromString("2020-01-01 00:00:00"), callback);
+}
+
+TEST_F(AlarmOperationsFixture, getNextMultipleEventsWithRecursive)
+{
+ alarms::IAlarmOperations::OnGetNextSingleProcessed callback = [](std::vector<SingleEventRecord> records) {
+ EXPECT_EQ(records.size(), 2);
+ EXPECT_EQ(records[0].startDate, TimePointFromString("2022-01-01 02:00:00"));
+ EXPECT_EQ(records[0].parent->ID, 1);
+ EXPECT_EQ(records[1].startDate, TimePointFromString("2022-01-01 02:00:00"));
+ EXPECT_EQ(records[1].parent->ID, 3);
+ };
+
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+ alarmRepoMock->addSingleEvent(AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-01-01 02:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ alarmRepoMock->addRecurringEvent(AlarmEventRecord(2,
+ defName,
+ TimePointFromString("2021-01-01 09:00:00"),
+ defDuration,
+ defAllDay,
+ "FREQ=MONTHLY;BYMONTHDAY=1;INTERVAL=1",
+ defMusic,
+ defEnabled,
+ defSnooze));
+ alarmRepoMock->addRecurringEvent(AlarmEventRecord(3,
+ defName,
+ TimePointFromString("2021-01-01 02:00:00"),
+ defDuration,
+ defAllDay,
+ "FREQ=MONTHLY;BYMONTHDAY=1;INTERVAL=1",
+ defMusic,
+ defEnabled,
+ defSnooze));
+
+ auto alarmOperations = getMockedAlarmOperations(alarmRepoMock);
+ alarmOperations->getNextSingleEvents(TimePointFromString("2022-01-01 00:00:00"), callback);
+}
M products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +1 -0
@@ 51,6 51,7 @@ target_link_libraries(BellHybrid
service-bluetooth
service-desktop
service-lwip
+ service-time
sys
platform
${LWIP_LIBRARIES}
M products/PurePhone/CMakeLists.txt => products/PurePhone/CMakeLists.txt +1 -0
@@ 67,6 67,7 @@ target_link_libraries(PurePhone
service-bluetooth
service-desktop
service-lwip
+ service-time
sys
${LWIP_LIBRARIES}
"$<$<STREQUAL:${PROJECT_TARGET},TARGET_Linux>:iosyscalls>"