~aleteoryx/muditaos

6533aba24ef55cde97a89ef8040b9da21425d571 — KacperLewandowski 5 years ago d86d3ae
[EGD-4073] Alarms database rework (#1006)

Adaptation to the query approach.
M changelog.md => changelog.md +4 -0
@@ 9,6 9,10 @@

* `[audio]` Fix playback of mono sound using headphones

## Changed

* `[alarms]` Database refactor

## [0.48.1 2020-11-23]

### Added

M image/user/db/alarms_001.sql => image/user/db/alarms_001.sql +13 -7
@@ 1,8 1,14 @@
CREATE TABLE IF NOT EXISTS alarms
(
    _id    INTEGER PRIMARY KEY,
    time   INTEGER,
    snooze INTEGER,
    status INTEGER,
    path   TEXT DEFAULT ''
CREATE TABLE IF NOT EXISTS alarms(
                  _id INTEGER PRIMARY KEY,
                  time DATETIME,
                  snooze INTEGER,
                  status INTEGER,
                  repeat INTEGER,
                  path TEXT DEFAULT '',
                  FOREIGN KEY(status) REFERENCES alarmStatuses(_id)
);

CREATE TABLE IF NOT EXISTS alarmStatuses(
                  _id INTEGER PRIMARY KEY,
                  name TEXT NOT NULL
);

M image/user/db/alarms_002.sql => image/user/db/alarms_002.sql +7 -2
@@ 1,2 1,7 @@
INSERT or ignore INTO alarms (_id, time, snooze, status, path)
VALUES (1, 0, 0, 0, '');
INSERT or IGNORE INTO alarmStatuses (_id, name) VALUES (1, 'Off');
INSERT or IGNORE INTO alarmStatuses (_id, name) VALUES (2, 'On');
INSERT or IGNORE INTO alarmStatuses (_id, name) VALUES (3, 'FirstSnooze');
INSERT or IGNORE INTO alarmStatuses (_id, name) VALUES (4, 'SecondSnooze');
INSERT or IGNORE INTO alarmStatuses (_id, name) VALUES (5, 'ThirdSnooze');
INSERT or IGNORE INTO alarmStatuses (_id, name) VALUES (6, 'FourthSnooze');
INSERT or IGNORE INTO alarmStatuses (_id, name) VALUES (7, 'FifthSnooze');

M module-db/CMakeLists.txt => module-db/CMakeLists.txt +7 -0
@@ 38,6 38,7 @@ set(SOURCES
        Tables/ContactsGroups.cpp
        Tables/SettingsTable.cpp
        Tables/AlarmsTable.cpp
        Tables/AlarmsStatusTable.cpp
        Tables/NotesTable.cpp
        Tables/CalllogTable.cpp
        Tables/CountryCodesTable.cpp


@@ 116,6 117,12 @@ set(SOURCES
        queries/settings/QuerySettingsGet_v2.cpp
        queries/settings/QuerySettingsUpdate_v2.cpp
        queries/settings/QuerySettingsAddOrIgnore_v2.cpp
        queries/alarms/QueryAlarmsAdd.cpp
        queries/alarms/QueryAlarmsRemove.cpp
        queries/alarms/QueryAlarmsEdit.cpp
        queries/alarms/QueryAlarmsGet.cpp
        queries/alarms/QueryAlarmsGetLimited.cpp
        queries/alarms/QueryAlarmsTurnOffAll.cpp
)

if(NOT ${PROJECT_TARGET} STREQUAL "TARGET_Linux")

M module-db/Databases/AlarmsDB.cpp => module-db/Databases/AlarmsDB.cpp +1 -8
@@ 1,17 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * AlarmsDB.cpp
 *
 *  Created on: 15 lip 2019
 *      Author: kuba
 */

#include <vfs.hpp>
#include "AlarmsDB.hpp"

const char *AlarmsDB::dbName = USER_PATH("alarms.db");

AlarmsDB::AlarmsDB() : Database(dbName), alarms(this)
AlarmsDB::AlarmsDB() : Database(dbName), alarms(this), alarmStatuses(this)
{}

M module-db/Databases/AlarmsDB.hpp => module-db/Databases/AlarmsDB.hpp +3 -9
@@ 1,17 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * AlarmsDB.hpp
 *
 *  Created on: 15 lip 2019
 *      Author: kuba
 */

#pragma once
#include "Database/Database.hpp"
#include "../Tables/AlarmsTable.hpp"
#include "../Tables/ThreadsTable.hpp"
#include "Tables/AlarmsTable.hpp"
#include "Tables/AlarmsStatusTable.hpp"

class AlarmsDB : public Database
{


@@ 20,6 13,7 @@ class AlarmsDB : public Database
    ~AlarmsDB() = default;

    AlarmsTable alarms;
    AlarmsStatusTable alarmStatuses;

    static const char *GetDBName()
    {

M module-db/Interface/AlarmsRecord.cpp => module-db/Interface/AlarmsRecord.cpp +103 -35
@@ 1,15 1,18 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * AlarmsRecord.cpp
 *
 *  Created on: 15 lip 2019
 *      Author: kuba
 */

#include "AlarmsRecord.hpp"
#include "AlarmsTable.hpp"
#include "queries/alarms/QueryAlarmsAdd.hpp"
#include "queries/alarms/QueryAlarmsRemove.hpp"
#include "queries/alarms/QueryAlarmsEdit.hpp"
#include "queries/alarms/QueryAlarmsGet.hpp"
#include "queries/alarms/QueryAlarmsGetLimited.hpp"
#include "queries/alarms/QueryAlarmsTurnOffAll.hpp"

AlarmsRecord::AlarmsRecord(const AlarmsTableRow &tableRow)
    : Record{tableRow.ID}, time{tableRow.time}, snooze{tableRow.snooze}, status{tableRow.status},
      repeat{tableRow.repeat}, path{tableRow.path}
{}

AlarmsRecordInterface::AlarmsRecordInterface(AlarmsDB *alarmsDb) : alarmsDB(alarmsDb)
{}


@@ 20,10 23,7 @@ AlarmsRecordInterface::~AlarmsRecordInterface()
bool AlarmsRecordInterface::Add(const AlarmsRecord &rec)
{
    // Create alarm
    alarmsDB->alarms.add(
        AlarmsTableRow{.time = rec.time, .snooze = rec.snooze, .status = rec.status, .path = rec.path});

    // TODO: error check
    alarmsDB->alarms.add(AlarmsTableRow(rec));

    return true;
}


@@ 60,22 60,12 @@ std::unique_ptr<std::vector<AlarmsRecord>> AlarmsRecordInterface::GetLimitOffset

std::unique_ptr<std::vector<AlarmsRecord>> AlarmsRecordInterface::GetLimitOffset(uint32_t offset, uint32_t limit)
{
    auto alarm = alarmsDB->alarms.getLimitOffset(offset, limit);
    auto alarms = alarmsDB->alarms.getLimitOffset(offset, limit);

    auto records = std::make_unique<std::vector<AlarmsRecord>>();

    AlarmsRecordInterface alarmsInterface(alarmsDB);
    for (const auto &w : alarm) {

        auto alarmsRec = alarmsInterface.GetByID(w.ID);

        records->push_back({
            .ID     = w.ID,
            .time   = w.time,
            .snooze = w.snooze,
            .status = w.status,
            .path   = w.path,
        });
    for (const auto &alarm : alarms) {
        records->push_back(AlarmsRecord(alarm));
    }

    return records;


@@ 89,8 79,7 @@ bool AlarmsRecordInterface::Update(const AlarmsRecord &rec)
        return false;
    }

    alarmsDB->alarms.update(
        AlarmsTableRow{.ID = rec.ID, .time = rec.time, .snooze = rec.snooze, .status = rec.status, .path = rec.path});
    alarmsDB->alarms.update(AlarmsTableRow(rec));

    return true;
}


@@ 115,7 104,7 @@ bool AlarmsRecordInterface::RemoveByField(AlarmsRecordField field, const char *s
{

    switch (field) {
    case AlarmsRecordField ::Time:
    case AlarmsRecordField::Time:
        return alarmsDB->alarms.removeByField(AlarmsTableFields::Time, str);

    default:


@@ 125,16 114,95 @@ bool AlarmsRecordInterface::RemoveByField(AlarmsRecordField field, const char *s

AlarmsRecord AlarmsRecordInterface::GetByID(uint32_t id)
{
    auto alarm = alarmsDB->alarms.getById(id);
    return AlarmsRecord(alarmsDB->alarms.getById(id));
}

bool AlarmsRecordInterface::TurnOffAll()
{
    return alarmsDB->alarms.updateStatuses(AlarmStatus::Off);
}

std::unique_ptr<db::QueryResult> AlarmsRecordInterface::runQuery(std::shared_ptr<db::Query> query)
{
    if (typeid(*query) == typeid(db::query::alarms::Get)) {
        return runQueryImplGetResult(query);
    }
    if (typeid(*query) == typeid(db::query::alarms::GetLimited)) {
        return runQueryImplGetLimitedResult(query);
    }
    if (typeid(*query) == typeid(db::query::alarms::TurnOffAll)) {
        return runQueryImplTurnOffAll(query);
    }
    if (typeid(*query) == typeid(db::query::alarms::Add)) {
        return runQueryImplAdd(query);
    }
    if (typeid(*query) == typeid(db::query::alarms::Remove)) {
        return runQueryImplRemove(query);
    }
    if (typeid(*query) == typeid(db::query::alarms::Edit)) {
        return runQueryImplEdit(query);
    }
    return nullptr;
}

    return AlarmsRecord{
        .ID = alarm.ID, .time = alarm.time, .snooze = alarm.snooze, .status = alarm.status, .path = alarm.path};
std::unique_ptr<db::query::alarms::GetResult> AlarmsRecordInterface::runQueryImplGetResult(
    std::shared_ptr<db::Query> query)
{
    auto getQuery = static_cast<db::query::alarms::Get *>(query.get());
    auto records  = GetByID(getQuery->id);
    auto response = std::make_unique<db::query::alarms::GetResult>(records);
    response->setRequestQuery(query);
    return response;
}

AlarmsRecord AlarmsRecordInterface::GetNext(time_t time)
std::unique_ptr<db::query::alarms::GetLimitedResult> AlarmsRecordInterface::runQueryImplGetLimitedResult(
    std::shared_ptr<db::Query> query)
{
    auto alarm = alarmsDB->alarms.next(time);
    auto getLimitedQuery = static_cast<db::query::alarms::GetLimited *>(query.get());
    auto records         = GetLimitOffset(getLimitedQuery->offset, getLimitedQuery->limit);
    std::vector<AlarmsRecord> recordVector;

    return AlarmsRecord{
        .ID = alarm.ID, .time = alarm.time, .snooze = alarm.snooze, .status = alarm.status, .path = alarm.path};
    for (const auto &alarm : *records) {
        recordVector.emplace_back(alarm);
    }
    auto response = std::make_unique<db::query::alarms::GetLimitedResult>(recordVector, GetCount());
    response->setRequestQuery(query);
    return response;
}

std::unique_ptr<db::query::alarms::AddResult> AlarmsRecordInterface::runQueryImplAdd(std::shared_ptr<db::Query> query)
{
    auto addQuery = static_cast<db::query::alarms::Add *>(query.get());
    bool ret      = Add(addQuery->getRecord());
    auto response = std::make_unique<db::query::alarms::AddResult>(ret);
    response->setRequestQuery(query);
    return response;
}

std::unique_ptr<db::query::alarms::RemoveResult> AlarmsRecordInterface::runQueryImplRemove(
    std::shared_ptr<db::Query> query)
{
    auto removeQuery = static_cast<db::query::alarms::Remove *>(query.get());
    bool ret         = RemoveByID(removeQuery->id);
    auto response    = std::make_unique<db::query::alarms::RemoveResult>(ret);
    response->setRequestQuery(query);
    return response;
}

std::unique_ptr<db::query::alarms::EditResult> AlarmsRecordInterface::runQueryImplEdit(std::shared_ptr<db::Query> query)
{
    auto editQuery = static_cast<db::query::alarms::Edit *>(query.get());
    bool ret       = Update(editQuery->getRecord());
    auto response  = std::make_unique<db::query::alarms::EditResult>(ret);
    response->setRequestQuery(query);
    return response;
}

std::unique_ptr<db::query::alarms::TurnOffAllResult> AlarmsRecordInterface::runQueryImplTurnOffAll(
    std::shared_ptr<db::Query> query)
{
    auto result   = TurnOffAll();
    auto response = std::make_unique<db::query::alarms::TurnOffAllResult>(result);
    response->setRequestQuery(query);
    return response;
}

M module-db/Interface/AlarmsRecord.hpp => module-db/Interface/AlarmsRecord.hpp +37 -16
@@ 1,27 1,41 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * AlarmsRecord.hpp
 *
 *  Created on: 15 lip 2019
 *      Author: kuba
 */
#pragma once

#include "Record.hpp"
#include "module-db/Databases/AlarmsDB.hpp"
#include "module-db/Common/Common.hpp"
#include <module-utils/utf8/UTF8.hpp>
#include <module-apps/application-calendar/data/dateCommon.hpp>
#include <stdint.h>
#include "../Databases/AlarmsDB.hpp"
#include "utf8/UTF8.hpp"
#include "../Common/Common.hpp"

struct AlarmsRecord
namespace db::query::alarms
{
    uint32_t ID;
    uint32_t time;
    uint32_t snooze;
    uint32_t status;
    class Add;
    class AddResult;
    class Edit;
    class EditResult;
    class Get;
    class GetResult;
    class GetLimited;
    class GetLimitedResult;
    class Remove;
    class RemoveResult;
    class TurnOffAll;
    class TurnOffAllResult;
} // namespace db::query::alarms

struct AlarmsRecord : public Record
{
    TimePoint time     = TIME_POINT_INVALID;
    uint32_t snooze    = 0;
    AlarmStatus status = AlarmStatus::On;
    uint32_t repeat    = 0;
    UTF8 path;

    AlarmsRecord() = default;
    explicit AlarmsRecord(const AlarmsTableRow &tableRow);
};

enum class AlarmsRecordField


@@ 45,16 59,23 @@ class AlarmsRecordInterface : public RecordInterface<AlarmsRecord, AlarmsRecordF
    AlarmsRecord GetByID(uint32_t id) override final;

    uint32_t GetCount() override final;
    bool TurnOffAll();

    std::unique_ptr<std::vector<AlarmsRecord>> GetLimitOffset(uint32_t offset, uint32_t limit) override final;

    std::unique_ptr<std::vector<AlarmsRecord>> GetLimitOffsetByField(uint32_t offset,
                                                                     uint32_t limit,
                                                                     AlarmsRecordField field,
                                                                     const char *str) override final;

    AlarmsRecord GetNext(time_t time);
    std::unique_ptr<db::QueryResult> runQuery(std::shared_ptr<db::Query> query) override;

  private:
    AlarmsDB *alarmsDB;

    std::unique_ptr<db::query::alarms::AddResult> runQueryImplAdd(std::shared_ptr<db::Query> query);
    std::unique_ptr<db::query::alarms::RemoveResult> runQueryImplRemove(std::shared_ptr<db::Query> query);
    std::unique_ptr<db::query::alarms::EditResult> runQueryImplEdit(std::shared_ptr<db::Query> query);
    std::unique_ptr<db::query::alarms::GetResult> runQueryImplGetResult(std::shared_ptr<db::Query> query);
    std::unique_ptr<db::query::alarms::GetLimitedResult> runQueryImplGetLimitedResult(std::shared_ptr<db::Query> query);
    std::unique_ptr<db::query::alarms::TurnOffAllResult> runQueryImplTurnOffAll(std::shared_ptr<db::Query> query);
};

A module-db/Tables/AlarmsStatusTable.cpp => module-db/Tables/AlarmsStatusTable.cpp +61 -0
@@ 0,0 1,61 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "AlarmsStatusTable.hpp"

AlarmsStatusTable::AlarmsStatusTable(Database *db) : Table(db)
{}

bool AlarmsStatusTable::create()
{
    return true;
}

bool AlarmsStatusTable::add(AlarmsStatusRow entry)
{
    return db->execute("INSERT or ignore INTO alarmStatuses ( name ) VALUES ('%q');", entry.name.c_str());
}

uint32_t AlarmsStatusTable::count()
{
    auto queryRet = db->query("SELECT COUNT(*) FROM alarmStatuses;");

    if (queryRet->getRowCount() == 0) {
        return 0;
    }

    return (*queryRet)[0].getUInt32();
}

bool AlarmsStatusTable::removeById(uint32_t id)
{
    return false;
}

bool AlarmsStatusTable::update(AlarmsStatusRow entry)
{
    return false;
}

AlarmsStatusRow AlarmsStatusTable::getById(uint32_t id)
{
    return AlarmsStatusRow();
}

std::vector<AlarmsStatusRow> AlarmsStatusTable::getLimitOffset(uint32_t offset, uint32_t limit)
{
    return std::vector<AlarmsStatusRow>();
}

std::vector<AlarmsStatusRow> AlarmsStatusTable::getLimitOffsetByField(uint32_t offset,
                                                                      uint32_t limit,
                                                                      AlarmsStatusFields field,
                                                                      const char *str)
{
    return std::vector<AlarmsStatusRow>();
}

uint32_t AlarmsStatusTable::countByFieldId(const char *field, uint32_t id)
{
    return count();
}

A module-db/Tables/AlarmsStatusTable.hpp => module-db/Tables/AlarmsStatusTable.hpp +39 -0
@@ 0,0 1,39 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "Common/Common.hpp"
#include "Database/Database.hpp"
#include "Record.hpp"
#include "Table.hpp"
#include <string>

struct AlarmsStatusRow : public Record
{
    std::string name;
};

enum class AlarmsStatusFields
{
    name
};

class AlarmsStatusTable : public Table<AlarmsStatusRow, AlarmsStatusFields>
{
  public:
    explicit AlarmsStatusTable(Database *db);
    ~AlarmsStatusTable() override = default;
    bool create() final;

    uint32_t count() final;
    bool add(AlarmsStatusRow entry) final;
    bool removeById(uint32_t id) final;
    bool update(AlarmsStatusRow entry) final;
    AlarmsStatusRow getById(uint32_t id) final;
    std::vector<AlarmsStatusRow> getLimitOffset(uint32_t offset, uint32_t limit) final;
    std::vector<AlarmsStatusRow> getLimitOffsetByField(uint32_t offset,
                                                       uint32_t limit,
                                                       AlarmsStatusFields field,
                                                       const char *str) final;
    uint32_t countByFieldId(const char *field, uint32_t id) final;
};

M module-db/Tables/AlarmsTable.cpp => module-db/Tables/AlarmsTable.cpp +40 -57
@@ 1,14 1,23 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * AlarmsTable.cpp
 *
 *  Created on: 15 lip 2019
 *      Author: kuba
 */

#include "AlarmsTable.hpp"
#include "AlarmsRecord.hpp"

AlarmsTableRow::AlarmsTableRow(const AlarmsRecord &rec)
    : Record{rec.ID}, time{rec.time}, snooze{rec.snooze}, status{rec.status}, repeat{rec.repeat}, path{rec.path}
{}

AlarmsTableRow::AlarmsTableRow(
    uint32_t id, TimePoint time, uint32_t snooze, AlarmStatus status, uint32_t repeat, UTF8 path)
    : Record{id}, time{time}, snooze{snooze}, status{status}, repeat{repeat}, path{std::move(path)}
{}

AlarmsTableRow::AlarmsTableRow(const QueryResult &result)
    : Record{(result)[0].getUInt32()}, time{TimePointFromString((result)[1].getString().c_str())},
      snooze{(result)[2].getUInt32()}, status{static_cast<AlarmStatus>((result)[3].getInt32())},
      repeat{(result)[4].getUInt32()}, path{(result)[5].getString()}
{}

AlarmsTable::AlarmsTable(Database *db) : Table(db)
{}


@@ 20,11 29,13 @@ bool AlarmsTable::create()

bool AlarmsTable::add(AlarmsTableRow entry)
{
    return db->execute("INSERT or ignore INTO alarms ( time, snooze, status, path ) VALUES (%lu,%lu,%lu,'%q');",
                       entry.time,
                       entry.snooze,
                       entry.status,
                       entry.path.c_str());
    return db->execute(
        "INSERT or ignore INTO alarms ( time, snooze, status, repeat, path ) VALUES ('%q', %lu, %i, %lu,'%q');",
        TimePointToString(entry.time).c_str(),
        entry.snooze,
        entry.status,
        entry.repeat,
        entry.path.c_str());
}

bool AlarmsTable::removeById(uint32_t id)


@@ 57,12 68,14 @@ bool AlarmsTable::removeByField(AlarmsTableFields field, const char *str)

bool AlarmsTable::update(AlarmsTableRow entry)
{
    return db->execute("UPDATE alarms SET time = %lu, snooze = %lu ,status = %lu, path = '%q' WHERE _id=%lu;",
                       entry.time,
                       entry.snooze,
                       entry.status,
                       entry.path.c_str(),
                       entry.ID);
    return db->execute(
        "UPDATE alarms SET time = '%q', snooze = %lu ,status = %i, repeat = %lu, path = '%q' WHERE _id=%lu;",
        TimePointToString(entry.time).c_str(),
        entry.snooze,
        entry.status,
        entry.repeat,
        entry.path.c_str(),
        entry.ID);
}

AlarmsTableRow AlarmsTable::getById(uint32_t id)


@@ 73,18 86,12 @@ AlarmsTableRow AlarmsTable::getById(uint32_t id)
        return AlarmsTableRow();
    }

    return AlarmsTableRow{
        (*retQuery)[0].getUInt32(), // ID
        (*retQuery)[1].getUInt32(), // time
        (*retQuery)[2].getUInt32(), // snooze
        (*retQuery)[3].getUInt32(), // status
        (*retQuery)[4].getString(), // path
    };
    return AlarmsTableRow(*retQuery);
}

std::vector<AlarmsTableRow> AlarmsTable::getLimitOffset(uint32_t offset, uint32_t limit)
{
    auto retQuery = db->query("SELECT * from alarms ORDER BY time ASC LIMIT %lu OFFSET %lu;", limit, offset);
    auto retQuery = db->query("SELECT * from alarms ORDER BY time(time) ASC LIMIT %lu OFFSET %lu;", limit, offset);

    if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) {
        return std::vector<AlarmsTableRow>();


@@ 93,13 100,7 @@ std::vector<AlarmsTableRow> AlarmsTable::getLimitOffset(uint32_t offset, uint32_
    std::vector<AlarmsTableRow> ret;

    do {
        ret.push_back(AlarmsTableRow{
            (*retQuery)[0].getUInt32(), // ID
            (*retQuery)[1].getUInt32(), // time
            (*retQuery)[2].getUInt32(), // snooze
            (*retQuery)[3].getUInt32(), // status
            (*retQuery)[4].getString(), // path
        });
        ret.push_back(AlarmsTableRow(*retQuery));
    } while (retQuery->nextRow());

    return ret;


@@ 126,7 127,7 @@ std::vector<AlarmsTableRow> AlarmsTable::getLimitOffsetByField(uint32_t offset,
        return std::vector<AlarmsTableRow>();
    }

    auto retQuery = db->query("SELECT * from alarms WHERE %q='%q' ORDER BY time LIMIT %lu OFFSET %lu;",
    auto retQuery = db->query("SELECT * from alarms WHERE %q='%q' ORDER BY time(time) LIMIT %lu OFFSET %lu;",
                              fieldName.c_str(),
                              str,
                              limit,


@@ 139,13 140,7 @@ std::vector<AlarmsTableRow> AlarmsTable::getLimitOffsetByField(uint32_t offset,
    std::vector<AlarmsTableRow> ret;

    do {
        ret.push_back(AlarmsTableRow{
            (*retQuery)[0].getUInt32(), // ID
            (*retQuery)[1].getUInt32(), // time
            (*retQuery)[2].getUInt32(), // snooze
            (*retQuery)[3].getUInt32(), // status
            (*retQuery)[4].getString(), // path
        });
        ret.push_back(AlarmsTableRow(*retQuery));
    } while (retQuery->nextRow());

    return ret;


@@ 159,7 154,7 @@ uint32_t AlarmsTable::count()
        return 0;
    }

    return uint32_t{(*queryRet)[0].getUInt32()};
    return (*queryRet)[0].getUInt32();
}

uint32_t AlarmsTable::countByFieldId(const char *field, uint32_t id)


@@ 170,22 165,10 @@ uint32_t AlarmsTable::countByFieldId(const char *field, uint32_t id)
        return 0;
    }

    return uint32_t{(*queryRet)[0].getUInt32()};
    return (*queryRet)[0].getUInt32();
}

AlarmsTableRow AlarmsTable::next(time_t time)
bool AlarmsTable::updateStatuses(AlarmStatus status)
{
    auto retQuery = db->query("SELECT * from alarms WHERE status=1 AND time>=%u ORDER BY time ASC LIMIT 1;", time);

    if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) {
        return AlarmsTableRow();
    }

    return AlarmsTableRow{
        (*retQuery)[0].getUInt32(), // ID
        (*retQuery)[1].getUInt32(), // time
        (*retQuery)[2].getUInt32(), // snooze
        (*retQuery)[3].getUInt32(), // status
        (*retQuery)[4].getString(), // path
    };
    return db->execute("UPDATE alarms SET status = %i;", status);
}

M module-db/Tables/AlarmsTable.hpp => module-db/Tables/AlarmsTable.hpp +26 -14
@@ 1,27 1,40 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * AlarmsTable.hpp
 *
 *  Created on: 15 lip 2019
 *      Author: kuba
 */
#pragma once

#include "Table.hpp"
#include "Record.hpp"
#include "Database/Database.hpp"
#include "utf8/UTF8.hpp"
#include "Common/Common.hpp"
#include <module-utils/utf8/UTF8.hpp>
#include <module-apps/application-calendar/data/dateCommon.hpp>

struct AlarmsTableRow
struct AlarmsRecord;

enum class AlarmStatus
{
    Off,
    On,
    FirstSnooze,
    SecondSnooze,
    ThirdSnooze,
    FourthSnooze,
    FifthSnooze
};

struct AlarmsTableRow : public Record
{
    uint32_t ID = DB_ID_NONE;
    uint32_t time;
    uint32_t snooze;
    uint32_t status;
    TimePoint time     = TIME_POINT_INVALID;
    uint32_t snooze    = 0;
    AlarmStatus status = AlarmStatus::On;
    uint32_t repeat    = 0;
    UTF8 path;

    AlarmsTableRow() = default;
    AlarmsTableRow(uint32_t id, TimePoint time, uint32_t snooze, AlarmStatus status, uint32_t repeat, UTF8 path);
    explicit AlarmsTableRow(const AlarmsRecord &rec);
    explicit AlarmsTableRow(const QueryResult &result);
};

enum class AlarmsTableFields


@@ 52,6 65,5 @@ class AlarmsTable : public Table<AlarmsTableRow, AlarmsTableFields>

    uint32_t count() override final;
    uint32_t countByFieldId(const char *field, uint32_t id) override final;

    AlarmsTableRow next(time_t time);
    bool updateStatuses(AlarmStatus status);
};

A module-db/queries/alarms/QueryAlarmsAdd.cpp => module-db/queries/alarms/QueryAlarmsAdd.cpp +33 -0
@@ 0,0 1,33 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmsAdd.hpp"

namespace db::query::alarms
{
    Add::Add(const AlarmsRecord &record) : Query(Query::Type::Create), record(record)
    {}

    auto Add::getRecord() const -> AlarmsRecord
    {
        return record;
    }

    auto Add::debugInfo() const -> std::string
    {
        return std::string{"Add"};
    }

    AddResult::AddResult(bool ret) : ret(ret)
    {}

    auto AddResult::succeed() const -> bool
    {
        return ret;
    }

    auto AddResult::debugInfo() const -> std::string
    {
        return std::string{"AddResult"};
    }
} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsAdd.hpp => module-db/queries/alarms/QueryAlarmsAdd.hpp +31 -0
@@ 0,0 1,31 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "Interface/AlarmsRecord.hpp"
#include "Common/Query.hpp"
#include <string>

namespace db::query::alarms
{
    class Add : public Query
    {
        AlarmsRecord record;

      public:
        explicit Add(const AlarmsRecord &record);
        [[nodiscard]] auto getRecord() const -> AlarmsRecord;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

    class AddResult : public QueryResult
    {
        bool ret = true;

      public:
        explicit AddResult(bool ret);
        [[nodiscard]] auto succeed() const -> bool;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsEdit.cpp => module-db/queries/alarms/QueryAlarmsEdit.cpp +33 -0
@@ 0,0 1,33 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmsEdit.hpp"

namespace db::query::alarms
{
    Edit::Edit(const AlarmsRecord &record) : Query(Query::Type::Update), record(record)
    {}

    auto Edit::getRecord() const -> AlarmsRecord
    {
        return record;
    }

    auto Edit::debugInfo() const -> std::string
    {
        return std::string{"Edit"};
    }

    EditResult::EditResult(bool ret) : ret(ret)
    {}

    auto EditResult::succeed() const -> bool
    {
        return ret;
    }

    auto EditResult::debugInfo() const -> std::string
    {
        return std::string{"EditResult"};
    }
} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsEdit.hpp => module-db/queries/alarms/QueryAlarmsEdit.hpp +32 -0
@@ 0,0 1,32 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "Interface/AlarmsRecord.hpp"
#include "Common/Query.hpp"
#include <string>

namespace db::query::alarms
{
    class Edit : public Query
    {
        AlarmsRecord record;

      public:
        explicit Edit(const AlarmsRecord &record);

        [[nodiscard]] auto getRecord() const -> AlarmsRecord;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

    class EditResult : public QueryResult
    {
        bool ret = true;

      public:
        explicit EditResult(bool ret);
        [[nodiscard]] auto succeed() const -> bool;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsGet.cpp => module-db/queries/alarms/QueryAlarmsGet.cpp +28 -0
@@ 0,0 1,28 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmsGet.hpp"

namespace db::query::alarms
{
    Get::Get(uint32_t id) : Query(Query::Type::Read), id(id)
    {}

    auto Get::debugInfo() const -> std::string
    {
        return std::string{"Get"};
    }

    GetResult::GetResult(const AlarmsRecord &record) : record(record)
    {}

    auto GetResult::getResult() const -> AlarmsRecord
    {
        return record;
    }

    auto GetResult::debugInfo() const -> std::string
    {
        return std::string{"GetResult"};
    }
} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsGet.hpp => module-db/queries/alarms/QueryAlarmsGet.hpp +31 -0
@@ 0,0 1,31 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "module-db/Interface/AlarmsRecord.hpp"
#include "Common/Query.hpp"
#include <string>

namespace db::query::alarms
{
    class Get : public Query
    {
      public:
        const uint32_t id;
        explicit Get(uint32_t id);

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

    class GetResult : public QueryResult
    {
        AlarmsRecord record;

      public:
        explicit GetResult(const AlarmsRecord &record);
        [[nodiscard]] auto getResult() const -> AlarmsRecord;

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsGetLimited.cpp => module-db/queries/alarms/QueryAlarmsGetLimited.cpp +35 -0
@@ 0,0 1,35 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmsGetLimited.hpp"

#include <utility>

namespace db::query::alarms
{
    GetLimited::GetLimited(uint32_t offset, uint32_t limit) : Query(Query::Type::Read), offset(offset), limit(limit)
    {}

    auto GetLimited::debugInfo() const -> std::string
    {
        return std::string{"GetLimited"};
    }

    GetLimitedResult::GetLimitedResult(std::vector<AlarmsRecord> records, uint32_t count)
        : records(std::move(records)), recordsCount(count)
    {}

    auto GetLimitedResult::getResult() -> std::vector<AlarmsRecord>
    {
        return records;
    }
    auto GetLimitedResult::getCountResult() -> uint32_t
    {
        return recordsCount;
    }

    auto GetLimitedResult::debugInfo() const -> std::string
    {
        return std::string{"GetLimitedResult"};
    }
} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsGetLimited.hpp => module-db/queries/alarms/QueryAlarmsGetLimited.hpp +35 -0
@@ 0,0 1,35 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "module-db/Interface/AlarmsRecord.hpp"
#include "Common/Query.hpp"
#include <string>

namespace db::query::alarms
{
    class GetLimited : public Query
    {
      public:
        explicit GetLimited(uint32_t offset, uint32_t limit);
        [[nodiscard]] auto debugInfo() const -> std::string override;

        uint32_t offset = 0;
        uint32_t limit  = 0;
    };

    class GetLimitedResult : public QueryResult
    {
        std::vector<AlarmsRecord> records;
        uint32_t recordsCount;

      public:
        explicit GetLimitedResult(std::vector<AlarmsRecord> records, uint32_t count);
        [[nodiscard]] auto getResult() -> std::vector<AlarmsRecord>;
        [[nodiscard]] auto getCountResult() -> uint32_t;

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsRemove.cpp => module-db/queries/alarms/QueryAlarmsRemove.cpp +28 -0
@@ 0,0 1,28 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmsRemove.hpp"

namespace db::query::alarms
{
    Remove::Remove(const uint32_t &id) : Query(Query::Type::Delete), id(id)
    {}

    auto Remove::debugInfo() const -> std::string
    {
        return std::string{"Remove"};
    }

    RemoveResult::RemoveResult(const bool &ret) : ret(ret)
    {}

    auto RemoveResult::succeed() const -> bool
    {
        return ret;
    }

    auto RemoveResult::debugInfo() const -> std::string
    {
        return std::string{"RemoveResult"};
    }
} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsRemove.hpp => module-db/queries/alarms/QueryAlarmsRemove.hpp +30 -0
@@ 0,0 1,30 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "Common/Query.hpp"
#include <string>

namespace db::query::alarms
{

    class Remove : public Query
    {
      public:
        explicit Remove(const uint32_t &id);
        [[nodiscard]] auto debugInfo() const -> std::string override;

        const uint32_t id;
    };

    class RemoveResult : public QueryResult
    {
        bool ret = true;

      public:
        explicit RemoveResult(const bool &ret);
        [[nodiscard]] auto succeed() const -> bool;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsTurnOffAll.cpp => module-db/queries/alarms/QueryAlarmsTurnOffAll.cpp +23 -0
@@ 0,0 1,23 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmsTurnOffAll.hpp"

namespace db::query::alarms
{
    TurnOffAll::TurnOffAll() : Query(Query::Type::Update)
    {}

    auto TurnOffAll::debugInfo() const -> std::string
    {
        return std::string{"TurnOffAll"};
    }

    TurnOffAllResult::TurnOffAllResult(bool ret) : ret(ret)
    {}

    [[nodiscard]] auto TurnOffAllResult::debugInfo() const -> std::string
    {
        return std::string{"TurnOffAllResult"};
    }
} // namespace db::query::alarms

A module-db/queries/alarms/QueryAlarmsTurnOffAll.hpp => module-db/queries/alarms/QueryAlarmsTurnOffAll.hpp +27 -0
@@ 0,0 1,27 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "Common/Query.hpp"
#include <string>

namespace db::query::alarms
{
    class TurnOffAll : public Query
    {
      public:
        TurnOffAll();

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

    class TurnOffAllResult : public QueryResult
    {
        bool ret = true;

      public:
        explicit TurnOffAllResult(bool ret);
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarms

M module-db/tests/AlarmsRecord_tests.cpp => module-db/tests/AlarmsRecord_tests.cpp +255 -24
@@ 1,22 1,19 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * AlarmsRecord_tests.cpp
 *
 *  Created on: 16 lip 2019
 *      Author: kuba
 */

#include "vfs.hpp"

#include <catch2/catch.hpp>

#include <Interface/ContactRecord.hpp>

#include "Database/Database.hpp"
#include "Databases/AlarmsDB.hpp"
#include "Interface/AlarmsRecord.hpp"
#include "queries/alarms/QueryAlarmsGet.hpp"
#include "queries/alarms/QueryAlarmsGetLimited.hpp"
#include "queries/alarms/QueryAlarmsRemove.hpp"
#include "queries/alarms/QueryAlarmsEdit.hpp"
#include "queries/alarms/QueryAlarmsAdd.hpp"
#include "queries/alarms/QueryAlarmsTurnOffAll.hpp"

#include <algorithm>



@@ 30,27 27,261 @@ TEST_CASE("Alarms Record tests")

    vfs.remove(AlarmsDB::GetDBName());

    auto alarmsDB = std::make_unique<AlarmsDB>();
    REQUIRE(alarmsDB->isInitialized());
    auto alarmsDB = AlarmsDB();
    REQUIRE(alarmsDB.isInitialized());

    SECTION("Default Constructor")
    {
        AlarmsRecord test;
        REQUIRE(test.snooze == 0);
        REQUIRE(test.status == AlarmStatus::On);
        REQUIRE(test.repeat == 0);
        REQUIRE(test.path == "");
    }

    auto time = TimePointFromString("2020-11-11 15:15:00");
    SECTION("Constructor from AlarmsTableRow")
    {
        AlarmsTableRow tableRow(1, time, 0, AlarmStatus::On, 0, "musicFile.mp3");
        AlarmsRecord test(tableRow);
        REQUIRE(test.time == time);
        REQUIRE(test.snooze == 0);
        REQUIRE(test.status == AlarmStatus::On);
        REQUIRE(test.repeat == 0);
        REQUIRE(test.path == "musicFile.mp3");
        REQUIRE(test.isValid());
    }

    AlarmsRecord test;
    AlarmsRecordInterface alarmsRecordInterface(&alarmsDB);
    auto recordsNumber = alarmsRecordInterface.GetCount();
    REQUIRE(recordsNumber == 0);

    AlarmsTableRow tableRow(1, time, 2, AlarmStatus::Off, 3, "musicFile.mp3");
    auto rec = AlarmsRecord(tableRow);
    REQUIRE(rec.time == time);
    REQUIRE(rec.snooze == 2);
    REQUIRE(rec.status == AlarmStatus::Off);
    REQUIRE(rec.repeat == 3);
    REQUIRE(rec.path == "musicFile.mp3");
    REQUIRE(rec.isValid());

    REQUIRE(alarmsRecordInterface.Add(rec));

    recordsNumber = alarmsRecordInterface.GetCount();
    REQUIRE(recordsNumber == 1);

    SECTION("Get entry by ID")
    {
        auto entry = alarmsRecordInterface.GetByID(1);
        REQUIRE(entry.ID == 1);
        REQUIRE(entry.time == time);
        REQUIRE(entry.snooze == 2);
        REQUIRE(entry.status == AlarmStatus::Off);
        REQUIRE(entry.repeat == 3);
        REQUIRE(entry.path == "musicFile.mp3");
        REQUIRE(entry.isValid());
    }

    SECTION("Get entry - invalid ID")
    {
        auto entry = alarmsRecordInterface.GetByID(100);
        REQUIRE(entry.ID == DB_ID_NONE);
        REQUIRE(entry.time == TIME_POINT_INVALID);
        REQUIRE(entry.snooze == 0);
        REQUIRE(entry.status == AlarmStatus::On);
        REQUIRE(entry.repeat == 0);
        REQUIRE(entry.path == "");
        REQUIRE_FALSE(entry.isValid());
    }

    AlarmsTableRow tableRow2(2, TimePointFromString("2020-11-12 18:00:00"), 3, AlarmStatus::On, 0, "musicFile123.mp3");
    auto rec2 = AlarmsRecord(tableRow2);
    REQUIRE(rec2.time == TimePointFromString("2020-11-12 18:00:00"));
    REQUIRE(rec2.snooze == 3);
    REQUIRE(rec2.status == AlarmStatus::On);
    REQUIRE(rec2.repeat == 0);
    REQUIRE(rec2.path == "musicFile123.mp3");
    REQUIRE(rec2.isValid());

    REQUIRE(alarmsRecordInterface.Add(rec2));

    recordsNumber = alarmsRecordInterface.GetCount();
    REQUIRE(recordsNumber == 2);

    SECTION("Entry update")
    {
        auto entryUpdate   = alarmsRecordInterface.GetByID(1);
        entryUpdate.time   = TimePointFromString("2020-12-31 23:59:00");
        entryUpdate.snooze = 0;
        entryUpdate.status = AlarmStatus::On;
        entryUpdate.path   = "musicFileUpdate.mp3";

        REQUIRE(alarmsRecordInterface.Update(entryUpdate));

        auto entry = alarmsRecordInterface.GetByID(1);
        REQUIRE(entry.ID == entryUpdate.ID);
        REQUIRE(entry.time == entryUpdate.time);
        REQUIRE(entry.snooze == entryUpdate.snooze);
        REQUIRE(entry.status == entryUpdate.status);
        REQUIRE(entry.repeat == entryUpdate.repeat);
        REQUIRE(entry.path == entryUpdate.path);
        REQUIRE(recordsNumber == 2);
    }

    SECTION("Get entries")
    {
        SECTION("Get table rows using valid offset/limit parameters")
        {
            auto retOffsetLimit = alarmsRecordInterface.GetLimitOffset(0, recordsNumber);
            REQUIRE(retOffsetLimit->size() == recordsNumber);
        }

        SECTION("Get table rows using limit which exceeds number of records in database")
        {
            auto retOffsetLimit = alarmsRecordInterface.GetLimitOffset(0, 100);
            REQUIRE(retOffsetLimit->size() == recordsNumber);
        }

        SECTION("Get table rows using invalid offset/limit parameters(should return empty object)")
        {
            auto retOffsetLimit = alarmsRecordInterface.GetLimitOffset(5, 4);
            REQUIRE(retOffsetLimit->empty());
        }
    }
    SECTION("Turn off all alarms")
    {
        REQUIRE(alarmsRecordInterface.TurnOffAll());
        auto retOffsetLimit = alarmsRecordInterface.GetLimitOffset(0, alarmsRecordInterface.GetCount());
        for (const auto &record : *retOffsetLimit) {
            REQUIRE(record.status == AlarmStatus::Off);
        }
    }

    SECTION("Turn off all alarms with query")
    {
        auto query  = std::make_shared<db::query::alarms::TurnOffAll>();
        auto ret    = alarmsRecordInterface.runQuery(query);
        auto result = dynamic_cast<db::query::alarms::TurnOffAllResult *>(ret.get());
        REQUIRE(result != nullptr);
        auto retOffsetLimit = alarmsRecordInterface.GetLimitOffset(0, alarmsRecordInterface.GetCount());
        for (const auto &record : *retOffsetLimit) {
            REQUIRE(record.status == AlarmStatus::Off);
        }
    }

    SECTION("Remove entries")
    {
        REQUIRE(alarmsRecordInterface.RemoveByID(2));
        REQUIRE(alarmsRecordInterface.GetCount() == 1);

        REQUIRE_FALSE(alarmsRecordInterface.RemoveByID(100));

        REQUIRE(alarmsRecordInterface.RemoveByID(1));
        REQUIRE(alarmsRecordInterface.GetCount() == 0);
    }

    auto getQuery = [&](uint32_t id,
                        TimePoint alarmTime,
                        uint32_t snooze,
                        AlarmStatus status,
                        uint32_t repeat,
                        const std::string &path) {
        auto query  = std::make_shared<db::query::alarms::Get>(id);
        auto ret    = alarmsRecordInterface.runQuery(query);
        auto result = dynamic_cast<db::query::alarms::GetResult *>(ret.get());
        REQUIRE(result != nullptr);
        auto alarmRec = result->getResult();
        REQUIRE(alarmRec.ID == id);
        REQUIRE(alarmRec.time == alarmTime);
        REQUIRE(alarmRec.snooze == snooze);
        REQUIRE(alarmRec.status == status);
        REQUIRE(alarmRec.repeat == repeat);
        REQUIRE(alarmRec.path == path);

        return alarmRec;
    };

    SECTION("Get all available records with query")
    {
        auto query  = std::make_shared<db::query::alarms::GetLimited>(0, UINT32_MAX);
        auto ret    = alarmsRecordInterface.runQuery(query);
        auto result = dynamic_cast<db::query::alarms::GetLimitedResult *>(ret.get());
        REQUIRE(result != nullptr);
        auto results = result->getResult();
        REQUIRE(results.size() == 2);
    }

    SECTION("Get offset and limited records with query")
    {
        REQUIRE(alarmsRecordInterface.Add(rec2));
        REQUIRE(alarmsRecordInterface.Add(rec2));
        auto query  = std::make_shared<db::query::alarms::GetLimited>(1, 3);
        auto ret    = alarmsRecordInterface.runQuery(query);
        auto result = dynamic_cast<db::query::alarms::GetLimitedResult *>(ret.get());
        REQUIRE(result != nullptr);
        auto results = result->getResult();
        REQUIRE(results.size() == 3);
        REQUIRE(result->getCountResult() == alarmsRecordInterface.GetCount());
    }

    SECTION("Get record by id with query")
    {
        getQuery(1, time, 2, AlarmStatus::Off, 3, "musicFile.mp3");
    }

    SECTION("Remove records with query")
    {
        auto query1  = std::make_shared<db::query::alarms::Remove>(1);
        auto ret1    = alarmsRecordInterface.runQuery(query1);
        auto result1 = dynamic_cast<db::query::alarms::RemoveResult *>(ret1.get());
        REQUIRE(result1 != nullptr);
        REQUIRE(result1->succeed());

        auto query2  = std::make_shared<db::query::alarms::Remove>(2);
        auto ret2    = alarmsRecordInterface.runQuery(query2);
        auto result2 = dynamic_cast<db::query::alarms::RemoveResult *>(ret2.get());
        REQUIRE(result2 != nullptr);
        REQUIRE(result2->succeed());

        REQUIRE(alarmsRecordInterface.GetCount() == 0);
    }

    AlarmsRecordInterface alarmsRecordInterface(alarmsDB.get());
    SECTION("Edit record with query")
    {
        auto entryQueryGet = std::make_shared<db::query::alarms::Get>(1);
        auto entryRetGet   = alarmsRecordInterface.runQuery(entryQueryGet);
        auto entryResult   = dynamic_cast<db::query::alarms::GetResult *>(entryRetGet.get());
        REQUIRE(entryResult != nullptr);

    auto alarmsRecord = alarmsRecordInterface.GetByID(1);
        auto record   = entryResult->getResult();
        record.time   = TimePointFromString("2021-01-01 09:00:00");
        record.snooze = 1;
        record.status = AlarmStatus::On;
        record.repeat = 0;
        record.path   = "newFile.wav";

    REQUIRE(alarmsRecord.ID == 1);
    REQUIRE(alarmsRecord.time == 0);
    REQUIRE(alarmsRecord.snooze == 0);
    REQUIRE(alarmsRecord.status == 0);
    REQUIRE(alarmsRecord.path == "");
        auto query  = std::make_shared<db::query::alarms::Edit>(record);
        auto ret    = alarmsRecordInterface.runQuery(query);
        auto result = dynamic_cast<db::query::alarms::EditResult *>(ret.get());
        REQUIRE(result != nullptr);

    alarmsRecord.time = 1234;
    alarmsRecord.path = "awesome.mp3";
    REQUIRE(alarmsRecordInterface.Update(alarmsRecord));
        getQuery(1, TimePointFromString("2021-01-01 09:00:00"), 1, AlarmStatus::On, 0, "newFile.wav");
    }

    alarmsRecord = alarmsRecordInterface.GetByID(1);
    SECTION("Add with query")
    {
        AlarmsTableRow tableRow3(4, TimePointFromString("2020-11-11 09:00:00"), 0, AlarmStatus::Off, 9, "music.wav");
        auto record = AlarmsRecord(tableRow3);
        auto query  = std::make_shared<db::query::alarms::Add>(record);
        auto ret    = alarmsRecordInterface.runQuery(query);
        auto result = dynamic_cast<db::query::alarms::AddResult *>(ret.get());
        REQUIRE(result != nullptr);
        REQUIRE(result->succeed());
        auto maxID = alarmsRecordInterface.GetCount();

    REQUIRE(alarmsRecord.time == 1234);
    REQUIRE(alarmsRecord.path == "awesome.mp3");
        getQuery(maxID, TimePointFromString("2020-11-11 09:00:00"), 0, AlarmStatus::Off, 9, "music.wav");
    }

    Database::deinitialize();
}

M module-db/tests/AlarmsTable_tests.cpp => module-db/tests/AlarmsTable_tests.cpp +135 -94
@@ 1,12 1,6 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * AlarmsTable_tests.cpp
 *
 *  Created on: 16 lip 2019
 *      Author: kuba
 */
#include "vfs.hpp"

#include <catch2/catch.hpp>


@@ 30,94 24,141 @@ TEST_CASE("Alarms Table tests")
    AlarmsDB alarmsDb;
    REQUIRE(alarmsDb.isInitialized());

    auto alarmsRow = alarmsDb.alarms.getById(1);
    REQUIRE(alarmsRow.ID == 1);

    alarmsRow.time   = 1234;
    alarmsRow.snooze = 2345;
    alarmsRow.status = 1;
    alarmsRow.path   = "awesome.jp2";

    REQUIRE(alarmsDb.alarms.update(alarmsRow));

    auto alarmsRow2 = alarmsDb.alarms.getById(1);

    REQUIRE(alarmsRow2.time == 1234);
    REQUIRE(alarmsRow2.snooze == 2345);
    REQUIRE(alarmsRow2.status == 1);
    REQUIRE(alarmsRow2.path == "awesome.jp2");

    // add 3 elements into table
    REQUIRE(alarmsDb.alarms.add(alarmsRow));
    REQUIRE(alarmsDb.alarms.add(alarmsRow));
    REQUIRE(alarmsDb.alarms.add(alarmsRow));

    // Table should have 4 elements
    REQUIRE(alarmsDb.alarms.count() == 4);

    // update existing element in table
    alarmsRow.ID   = 4;
    alarmsRow.path = "updated";
    REQUIRE(alarmsDb.alarms.update(alarmsRow));

    // Get table row using valid ID & check if it was updated
    auto alarm = alarmsDb.alarms.getById(4);
    REQUIRE(alarm.path == alarmsRow.path);

    // Get table row using invalid ID(should return empty alarmsDb.alarmsRow)
    auto alarmFailed = alarmsDb.alarms.getById(100);
    REQUIRE(alarmFailed.path == "");

    // Get table rows using valid offset/limit parameters
    auto retOffsetLimit = alarmsDb.alarms.getLimitOffset(0, 4);
    REQUIRE(retOffsetLimit.size() == 4);

    // Get table rows using valid offset/limit parameters and specific field's ID
    REQUIRE(alarmsDb.alarms.getLimitOffsetByField(0, 4, AlarmsTableFields::Status, "1").size() == 4);

    // Get table rows using invalid limit parameters(should return 4 elements instead of 100)
    auto retOffsetLimitBigger = alarmsDb.alarms.getLimitOffset(0, 100);
    REQUIRE(retOffsetLimitBigger.size() == 4);

    // Get table rows using invalid offset/limit parameters(should return empty object)
    auto retOffsetLimitFailed = alarmsDb.alarms.getLimitOffset(5, 4);
    REQUIRE(retOffsetLimitFailed.size() == 0);

    // Get count of elements by field's ID
    REQUIRE(alarmsDb.alarms.countByFieldId("status", 1) == 4);

    // Get count of elements by invalid field's ID
    REQUIRE(alarmsDb.alarms.countByFieldId("invalid_field", 0) == 0);

    // update existing element in table
    alarmsRow.ID   = 4;
    alarmsRow.path = "updated";
    alarmsRow.time = 2222;
    REQUIRE(alarmsDb.alarms.update(alarmsRow));

    // Get record by time
    auto alarmByTime = alarmsDb.alarms.next(2000);

    REQUIRE(alarmByTime.ID == 4);
    REQUIRE(alarmByTime.time == 2222);

    // Table should have now 3 elements
    REQUIRE(alarmsDb.alarms.removeById(3));

    REQUIRE(alarmsDb.alarms.count() == 3);

    // Remove non existing element
    REQUIRE(alarmsDb.alarms.removeById(13));

    REQUIRE(alarmsDb.alarms.count() == 3);

    // Remove all elements from table
    REQUIRE(alarmsDb.alarms.removeById(1));
    REQUIRE(alarmsDb.alarms.removeById(2));
    REQUIRE(alarmsDb.alarms.removeById(4));

    // Table should be empty now
    REQUIRE(alarmsDb.alarms.count() == 0);
    auto &alarmsTbl = alarmsDb.alarms;
    REQUIRE(alarmsTbl.count() == 0);

    SECTION("Default Constructor")
    {
        AlarmsTableRow test;
        REQUIRE(test.time == TIME_POINT_INVALID);
        REQUIRE(test.snooze == 0);
        REQUIRE(test.status == AlarmStatus::On);
        REQUIRE(test.repeat == 0);
        REQUIRE(test.path == "");
    }

    REQUIRE(alarmsTbl.add(
        AlarmsTableRow(1, TimePointFromString("2020-11-11 15:10:00"), 0, AlarmStatus::Off, 0, "file.mp3")));
    REQUIRE(alarmsTbl.add(
        AlarmsTableRow(2, TimePointFromString("2020-11-11 15:15:00"), 1, AlarmStatus::On, 1, "file2.mp3")));

    REQUIRE(alarmsTbl.count() == 2);
    REQUIRE(alarmsTbl.countByFieldId("status", 0) == 1);

    SECTION("Get entry by ID")
    {
        auto entry = alarmsTbl.getById(1);
        REQUIRE(entry.ID == 1);
        REQUIRE(entry.time == TimePointFromString("2020-11-11 15:10:00"));
        REQUIRE(entry.snooze == 0);
        REQUIRE(entry.status == AlarmStatus::Off);
        REQUIRE(entry.repeat == 0);
        REQUIRE(entry.path == "file.mp3");
        REQUIRE(entry.isValid());
    }

    SECTION("Get entry - invalid ID")
    {
        auto entry = alarmsTbl.getById(100);
        REQUIRE(entry.ID == DB_ID_NONE);
        REQUIRE(entry.time == TIME_POINT_INVALID);
        REQUIRE(entry.snooze == 0);
        REQUIRE(entry.status == AlarmStatus::On);
        REQUIRE(entry.repeat == 0);
        REQUIRE(entry.path == "");
        REQUIRE_FALSE(entry.isValid());
    }

    SECTION("Entry update")
    {
        auto entryUpdate   = alarmsTbl.getById(1);
        entryUpdate.time   = TimePointFromString("2020-12-31 23:59:00");
        entryUpdate.snooze = 0;
        entryUpdate.status = AlarmStatus::On;
        entryUpdate.path   = "musicFileUpdate.mp3";

        REQUIRE(alarmsTbl.update(entryUpdate));

        auto entry = alarmsTbl.getById(1);
        REQUIRE(entry.ID == entryUpdate.ID);
        REQUIRE(entry.time == entryUpdate.time);
        REQUIRE(entry.snooze == entryUpdate.snooze);
        REQUIRE(entry.status == entryUpdate.status);
        REQUIRE(entry.repeat == entryUpdate.repeat);
        REQUIRE(entry.path == entryUpdate.path);
    }

    SECTION("Remove entries")
    {
        REQUIRE(alarmsTbl.removeById(2));
        REQUIRE(alarmsTbl.count() == 1);

        REQUIRE(alarmsTbl.removeById(100));

        REQUIRE(alarmsTbl.removeById(1));
        REQUIRE(alarmsTbl.count() == 0);
    }

    SECTION("Turn off all alarms")
    {
        REQUIRE(alarmsTbl.updateStatuses(AlarmStatus::Off));
        auto retOffsetLimit = alarmsTbl.getLimitOffset(0, alarmsTbl.count());
        for (const auto &record : retOffsetLimit) {
            REQUIRE(record.status == AlarmStatus::Off);
        }
    }

    SECTION("Get limit/offset")
    {
        auto retOffsetLimit = alarmsTbl.getLimitOffset(0, 2);
        REQUIRE(retOffsetLimit.size() == 2);

        retOffsetLimit = alarmsTbl.getLimitOffset(0, 100);
        REQUIRE(retOffsetLimit.size() == 2);

        retOffsetLimit = alarmsTbl.getLimitOffset(5, 5);
        REQUIRE(retOffsetLimit.empty());

        retOffsetLimit = alarmsTbl.getLimitOffsetByField(
            0, 5, AlarmsTableFields::Status, std::to_string(static_cast<int>(AlarmStatus::Off)).c_str());
        REQUIRE(retOffsetLimit.size() == 1);

        retOffsetLimit = alarmsTbl.getLimitOffsetByField(0, 5, AlarmsTableFields::Path, ".mp3");
        REQUIRE(retOffsetLimit.empty());
    }

    SECTION("Check limit/offset sorting correctness")
    {
        REQUIRE(alarmsTbl.add(
            AlarmsTableRow(3, TimePointFromString("2020-11-12 17:10:00"), 0, AlarmStatus::Off, 0, "file.mp3")));
        REQUIRE(alarmsTbl.add(
            AlarmsTableRow(4, TimePointFromString("2020-11-11 19:25:00"), 1, AlarmStatus::On, 1, "file2.mp3")));
        REQUIRE(alarmsTbl.add(
            AlarmsTableRow(5, TimePointFromString("2020-12-11 07:15:00"), 1, AlarmStatus::On, 1, "file2.mp3")));

        const std::array<TimePoint, 5> paramTime{TimePointFromString("2020-12-11 07:15:00"),
                                                 TimePointFromString("2020-11-11 15:10:00"),
                                                 TimePointFromString("2020-11-11 15:15:00"),
                                                 TimePointFromString("2020-11-12 17:10:00"),
                                                 TimePointFromString("2020-11-11 19:25:00")};

        REQUIRE(alarmsTbl.count() == 5);
        auto entries   = alarmsTbl.getLimitOffset(0, 5);
        uint32_t index = 0;
        for (const auto &entry : entries) {
            REQUIRE(entry.time == paramTime[index]);
            REQUIRE(entry.isValid());
            ++index;
        }
    }

    SECTION("Remove by field")
    {
        REQUIRE(alarmsTbl.updateStatuses(AlarmStatus::Off));
        REQUIRE(alarmsTbl.removeByField(AlarmsTableFields::Status,
                                        std::to_string(static_cast<int>(AlarmStatus::Off)).c_str()));
        REQUIRE(alarmsTbl.count() == 0);
    }

    Database::deinitialize();
}

M module-services/service-db/CMakeLists.txt => module-services/service-db/CMakeLists.txt +1 -2
@@ 7,8 7,7 @@ set(SOURCES
    DBServiceAPI_GetByQuery.cpp
    DatabaseAgent.cpp
    ServiceDB.cpp
    messages/DBAlarmMessage.cpp
    messages/DBCalllogMessage.cpp
        messages/DBCalllogMessage.cpp
    messages/DBContactMessage.cpp
    messages/DBCountryCodeMessage.cpp
    messages/DBNotesMessage.cpp

M module-services/service-db/DBServiceAPI.cpp => module-services/service-db/DBServiceAPI.cpp +0 -91
@@ 7,7 7,6 @@
#include "service-db/DBSMSMessage.hpp"
#include "service-db/DBSMSTemplateMessage.hpp"
#include "service-db/DBContactMessage.hpp"
#include "service-db/DBAlarmMessage.hpp"
#include "service-db/DBNotesMessage.hpp"
#include "service-db/DBCalllogMessage.hpp"
#include "service-db/DBCountryCodeMessage.hpp"


@@ 605,96 604,6 @@ std::unique_ptr<std::vector<ContactRecord>> DBServiceAPI::ContactSearch(sys::Ser
    }
}

bool DBServiceAPI::AlarmAdd(sys::Service *serv, const AlarmsRecord &rec)
{
    std::shared_ptr<DBAlarmMessage> msg = std::make_shared<DBAlarmMessage>(MessageType::DBAlarmAdd, rec);

    auto ret                              = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
    DBAlarmResponseMessage *alarmResponse = reinterpret_cast<DBAlarmResponseMessage *>(ret.second.get());
    if ((ret.first == sys::ReturnCodes::Success) && (alarmResponse->retCode == true)) {
        return true;
    }
    else {
        return false;
    }
}

bool DBServiceAPI::AlarmRemove(sys::Service *serv, uint32_t id)
{
    std::shared_ptr<DBAlarmMessage> msg = std::make_shared<DBAlarmMessage>(MessageType::DBAlarmRemove);
    msg->id                             = id;

    auto ret                              = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
    DBAlarmResponseMessage *alarmResponse = reinterpret_cast<DBAlarmResponseMessage *>(ret.second.get());
    if ((ret.first == sys::ReturnCodes::Success) && (alarmResponse->retCode == true)) {
        return true;
    }
    else {
        return false;
    }
}

bool DBServiceAPI::AlarmUpdate(sys::Service *serv, const AlarmsRecord &rec)
{
    std::shared_ptr<DBAlarmMessage> msg = std::make_shared<DBAlarmMessage>(MessageType::DBAlarmUpdate, rec);

    auto ret                              = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
    DBAlarmResponseMessage *alarmResponse = reinterpret_cast<DBAlarmResponseMessage *>(ret.second.get());
    if ((ret.first == sys::ReturnCodes::Success) && (alarmResponse->retCode == true)) {
        return true;
    }
    else {
        return false;
    }
}

uint32_t DBServiceAPI::AlarmGetCount(sys::Service *serv)
{
    std::shared_ptr<DBAlarmMessage> msg = std::make_shared<DBAlarmMessage>(MessageType::DBAlarmGetCount);

    auto ret                              = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
    DBAlarmResponseMessage *alarmResponse = reinterpret_cast<DBAlarmResponseMessage *>(ret.second.get());
    if ((ret.first == sys::ReturnCodes::Success) && (alarmResponse->retCode == true)) {
        return alarmResponse->count;
    }
    else {
        return false;
    }
}

std::unique_ptr<std::vector<AlarmsRecord>> DBServiceAPI::AlarmGetLimitOffset(sys::Service *serv,
                                                                             uint32_t offset,
                                                                             uint32_t limit)
{
    std::shared_ptr<DBAlarmMessage> msg = std::make_shared<DBAlarmMessage>(MessageType::DBAlarmGetLimitOffset);
    msg->offset                         = offset;
    msg->limit                          = limit;

    auto ret                              = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
    DBAlarmResponseMessage *alarmResponse = reinterpret_cast<DBAlarmResponseMessage *>(ret.second.get());
    if ((ret.first == sys::ReturnCodes::Success) && (alarmResponse->retCode == true)) {
        return std::move(alarmResponse->records);
    }
    else {
        return std::make_unique<std::vector<AlarmsRecord>>();
    }
}

AlarmsRecord DBServiceAPI::AlarmGetNext(sys::Service *serv, time_t time)
{

    std::shared_ptr<DBAlarmMessage> msg   = std::make_shared<DBAlarmMessage>(MessageType::DBAlarmGetNext);
    msg->time                             = time;
    auto ret                              = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
    DBAlarmResponseMessage *alarmResponse = reinterpret_cast<DBAlarmResponseMessage *>(ret.second.get());
    if ((ret.first == sys::ReturnCodes::Success) && (alarmResponse->retCode == true)) {
        return std::move((*alarmResponse->records)[0]);
    }
    else {
        return AlarmsRecord{};
    }
}

bool DBServiceAPI::NotesAdd(sys::Service *serv, const NotesRecord &rec)
{
    std::shared_ptr<DBNotesMessage> msg = std::make_shared<DBNotesMessage>(MessageType::DBNotesAdd, rec);

M module-services/service-db/ServiceDB.cpp => module-services/service-db/ServiceDB.cpp +0 -50
@@ 3,7 3,6 @@

#include "ServiceDB.hpp"

#include "service-db/DBAlarmMessage.hpp"
#include "service-db/DBCalllogMessage.hpp"
#include "service-db/DBContactMessage.hpp"
#include "service-db/DBCountryCodeMessage.hpp"


@@ 427,55 426,6 @@ sys::MessagePointer ServiceDB::DataReceivedHandler(sys::DataMessage *msgl, sys::
    } break;

        /**
         * Alarm records
         */

    case MessageType::DBAlarmAdd: {
        auto time           = utils::time::Scoped("DBAlarmAdd");
        DBAlarmMessage *msg = reinterpret_cast<DBAlarmMessage *>(msgl);
        auto ret            = alarmsRecordInterface->Add(msg->record);
        responseMsg         = std::make_shared<DBAlarmResponseMessage>(nullptr, ret);
        if (ret == true) {
            sendUpdateNotification(db::Interface::Name::Alarms, db::Query::Type::Create);
        }
    } break;

    case MessageType::DBAlarmRemove: {
        auto time           = utils::time::Scoped("DBAlarmRemove");
        DBAlarmMessage *msg = reinterpret_cast<DBAlarmMessage *>(msgl);
        auto ret            = alarmsRecordInterface->RemoveByID(msg->id);
        responseMsg         = std::make_shared<DBAlarmResponseMessage>(nullptr, ret);
    } break;

    case MessageType::DBAlarmUpdate: {
        auto time           = utils::time::Scoped("DBAlarmUpdate");
        DBAlarmMessage *msg = reinterpret_cast<DBAlarmMessage *>(msgl);
        auto ret            = alarmsRecordInterface->Update(msg->record);
        responseMsg         = std::make_shared<DBAlarmResponseMessage>(nullptr, ret);
    } break;

    case MessageType::DBAlarmGetCount: {
        auto time   = utils::time::Scoped("DBAlarmGetCount");
        auto ret    = alarmsRecordInterface->GetCount();
        responseMsg = std::make_shared<DBAlarmResponseMessage>(nullptr, true, ret);
    } break;

    case MessageType::DBAlarmGetLimitOffset: {
        auto time           = utils::time::Scoped("DBAlarmGetLimitOffset");
        DBAlarmMessage *msg = reinterpret_cast<DBAlarmMessage *>(msgl);
        auto ret            = alarmsRecordInterface->GetLimitOffset(msg->offset, msg->limit);
        responseMsg         = std::make_shared<DBAlarmResponseMessage>(std::move(ret), true);
    } break;
    case MessageType::DBAlarmGetNext: {
        auto time           = utils::time::Scoped("DBAlarmGetNext");
        DBAlarmMessage *msg = reinterpret_cast<DBAlarmMessage *>(msgl);
        auto ret            = alarmsRecordInterface->GetNext(msg->time);
        auto records        = std::make_unique<std::vector<AlarmsRecord>>();
        records->push_back(ret);
        responseMsg = std::make_shared<DBAlarmResponseMessage>(std::move(records), ret.ID == 0 ? false : true);
    } break;

        /**
         * Notes records
         */


D module-services/service-db/messages/DBAlarmMessage.cpp => module-services/service-db/messages/DBAlarmMessage.cpp +0 -19
@@ 1,19 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-db/DBAlarmMessage.hpp>

#include <AlarmsRecord.hpp>
#include <service-db/DBMessage.hpp>

#include <utility> // for move

DBAlarmMessage ::DBAlarmMessage(MessageType messageType, const AlarmsRecord &rec) : DBMessage(messageType), record(rec)
{}

DBAlarmResponseMessage::DBAlarmResponseMessage(std::unique_ptr<std::vector<AlarmsRecord>> rec,
                                               uint32_t retCode,
                                               uint32_t count,
                                               MessageType respTo)
    : DBResponseMessage(retCode, count, respTo), records(std::move(rec))
{}

D module-services/service-db/service-db/DBAlarmMessage.hpp => module-services/service-db/service-db/DBAlarmMessage.hpp +0 -32
@@ 1,32 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "DBMessage.hpp"

#include <Interface/AlarmsRecord.hpp>
#include <MessageType.hpp>

#include <cstdint>
#include <memory>
#include <sys/types.h>
#include <vector>

class DBAlarmMessage : public DBMessage
{
  public:
    DBAlarmMessage(MessageType messageType, const AlarmsRecord &rec = AlarmsRecord{});
    AlarmsRecord record;
    time_t time = 0;
};

class DBAlarmResponseMessage : public DBResponseMessage
{
  public:
    DBAlarmResponseMessage(std::unique_ptr<std::vector<AlarmsRecord>> rec,
                           uint32_t retCode   = 0,
                           uint32_t count     = 0,
                           MessageType respTo = MessageType::MessageTypeUninitialized);
    std::unique_ptr<std::vector<AlarmsRecord>> records;
};

M module-services/service-db/service-db/DBServiceAPI.hpp => module-services/service-db/service-db/DBServiceAPI.hpp +0 -8
@@ 151,14 151,6 @@ class DBServiceAPI
    static std::unique_ptr<utils::PhoneNumber::View> GetNumberById(sys::Service *serv,
                                                                   std::uint32_t numberId,
                                                                   std::uint32_t timeout = DefaultTimeoutInMs);
    static bool AlarmAdd(sys::Service *serv, const AlarmsRecord &rec);
    static bool AlarmRemove(sys::Service *serv, uint32_t id);
    static bool AlarmUpdate(sys::Service *serv, const AlarmsRecord &rec);
    static uint32_t AlarmGetCount(sys::Service *serv);
    static std::unique_ptr<std::vector<AlarmsRecord>> AlarmGetLimitOffset(sys::Service *serv,
                                                                          uint32_t offset,
                                                                          uint32_t limit);
    static AlarmsRecord AlarmGetNext(sys::Service *serv, time_t time);

    static bool NotesAdd(sys::Service *serv, const NotesRecord &rec);
    static bool NotesRemove(sys::Service *serv, uint32_t id);

M module-services/service-evtmgr/alarm/EventManagerAlarm.cpp => module-services/service-evtmgr/alarm/EventManagerAlarm.cpp +0 -15
@@ 63,18 63,3 @@ void EventManager::HandleAlarmTrigger(sys::DataMessage *msgl)
        }
    }
}

void EventManager::GetNextAlarmTimestamp(time_t timestamp)
{
    AlarmsRecord record;
    record = DBServiceAPI::AlarmGetNext(this, ((timestamp) % 86400));

    if (record.ID != 0) {
        alarmIsValid   = true;
        alarmTimestamp = record.time;
        alarmID        = record.ID;
    }
    else {
        alarmDBEmpty = true;
    }
}