~aleteoryx/muditaos

f724d9074ba9cfd662b18d7b9de7fcb18548824b — Adam Dobrowolski 4 years ago 1a165ee
[EGD-5701] Added DOM dump to harness

* Added generic handler to developerMode
* Added DOM message handling
54 files changed, 818 insertions(+), 207 deletions(-)

M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/CMakeLists.txt
A module-apps/DOMResponder.cpp
A module-apps/DOMResponder.hpp
M module-apps/messages/AppMessage.hpp
A module-apps/messages/BaseAppMessage.hpp
M module-bsp/board/linux/rtc/rtc.cpp
M module-gui/gui/dom/Item2JsonSerializer.cpp
M module-gui/gui/dom/Item2JsonSerializer.hpp
M module-services/service-appmgr/CMakeLists.txt
M module-services/service-appmgr/messages/BaseMessage.cpp
A module-services/service-appmgr/messages/DOMRequest.cpp
M module-services/service-appmgr/model/ApplicationManager.cpp
M module-services/service-appmgr/service-appmgr/messages/BaseMessage.hpp
A module-services/service-appmgr/service-appmgr/messages/DOMRequest.hpp
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp
A module-services/service-cellular/SMSSend.hpp
M module-services/service-desktop/CMakeLists.txt
A module-services/service-desktop/DesktopEvent.cpp
M module-services/service-desktop/DesktopMessages.cpp
A module-services/service-desktop/DeveloperModeMessage.cpp
M module-services/service-desktop/README.md
M module-services/service-desktop/ServiceDesktop.cpp
A module-services/service-desktop/doc/how_machine_works.puml
A module-services/service-desktop/doc/how_machine_works.svg
M module-services/service-desktop/endpoints/Context.hpp
A module-services/service-desktop/endpoints/ResponseContext.hpp
M module-services/service-desktop/endpoints/backup/BackupRestore.cpp
M module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp
M module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.hpp
M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp
M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.hpp
A module-services/service-desktop/endpoints/developerMode/Mode/BaseHelper.cpp
A module-services/service-desktop/endpoints/developerMode/Mode/BaseHelper.hpp
A module-services/service-desktop/endpoints/developerMode/Mode/UI_Helper.cpp
A module-services/service-desktop/endpoints/developerMode/Mode/UI_Helper.hpp
A module-services/service-desktop/endpoints/developerMode/event/DomRequest.cpp
A module-services/service-desktop/endpoints/developerMode/event/DomRequest.hpp
M module-services/service-desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp
M module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp
R module-services/service-desktop/parser/{ParserUtils => HttpEnums}.cpp
A module-services/service-desktop/parser/HttpEnums.hpp
M module-services/service-desktop/parser/ParserUtils.hpp
A module-services/service-desktop/service-desktop/DesktopEvent.hpp
M module-services/service-desktop/service-desktop/DesktopMessages.hpp
A module-services/service-desktop/service-desktop/DeveloperModeMessage.hpp
M module-sys/Service/Common.hpp
M module-sys/Service/Message.hpp
A module-sys/Service/MessageForward.hpp
A module-sys/Service/SystemReturnCodes.hpp
M module-sys/Service/Timer.cpp
M source/MessageType.hpp
A test/pytest/test_dom_dump.py
M module-apps/Application.cpp => module-apps/Application.cpp +23 -1
@@ 20,9 20,11 @@
#include <service-evtmgr/BatteryMessages.hpp>
#include <service-evtmgr/Constants.hpp>
#include <service-evtmgr/EVMessages.hpp>
#include <service-appmgr/service-appmgr/messages/DOMRequest.hpp>
#include "service-gui/messages/DrawMessage.hpp" // for DrawMessage
#include "task.h"                               // for xTaskGetTic...
#include "windows/AppWindow.hpp"                // for AppWindow
#include "DOMResponder.hpp"
#include <Text.hpp>                             // for Text
#include <algorithm>                            // for find
#include <iterator>                             // for distance, next


@@ 84,8 86,9 @@ namespace app

        connect(typeid(AppRefreshMessage),
                [this](sys::Message *msg) -> sys::MessagePointer { return handleAppRefresh(msg); });

        connect(sevm::BatteryStatusChangeMessage(), [&](sys::Message *) { return handleBatteryStatusChange(); });
        connect(typeid(app::manager::DOMRequest),
                [&](sys::Message *msg) -> sys::MessagePointer { return handleGetDOM(msg); });
    }

    Application::~Application() noexcept


@@ 448,6 451,25 @@ namespace app
        return msgHandled();
    }

    sys::MessagePointer Application::handleGetDOM(sys::Message *msgl)
    {
        if (windowsStack.isEmpty()) {
            LOG_ERROR("Current window is not defined - can't dump DOM");
            return msgNotHandled();
        }
        auto window = getCurrentWindow();
        if (window == nullptr) {
            LOG_ERROR("No window - can't dump DOM");
            return msgNotHandled();
        }

        auto request = static_cast<app::manager::DOMRequest *>(msgl);
        LOG_DEBUG("Get DOM for: %s", request->getSenderName().c_str());
        bus.sendUnicast(DOMResponder(GetName(), *window, std::move(request->event)).build(), request->getSenderName());

        return msgHandled();
    }

    sys::MessagePointer Application::handleAppFocusLost(sys::Message *msgl)
    {
        if (state == State::ACTIVE_FORGROUND) {

M module-apps/Application.hpp => module-apps/Application.hpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 175,6 175,7 @@ namespace app
        sys::MessagePointer handleAppClose(sys::Message *msgl);
        sys::MessagePointer handleAppRebuild(sys::Message *msgl);
        sys::MessagePointer handleAppRefresh(sys::Message *msgl);
        sys::MessagePointer handleGetDOM(sys::Message *msgl);
        sys::MessagePointer handleAppFocusLost(sys::Message *msgl);
        sys::MessagePointer handleSIMMessage(sys::Message *msgl);


M module-apps/CMakeLists.txt => module-apps/CMakeLists.txt +1 -0
@@ 17,6 17,7 @@ endif()
set( SOURCES 
    "Application.cpp"
    "GuiTimer.cpp"
    "DOMResponder.cpp"
    "WindowsFactory.cpp"
    "TopBarManager.cpp"
    "AsyncTask.cpp"

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

#include "DOMResponder.hpp"
#include "service-desktop/DeveloperModeMessage.hpp"
#include <service-appmgr/service-appmgr/messages/DOMRequest.hpp>
#include <module-gui/gui/dom/Item2JsonSerializer.hpp>
#include <memory>
#include <Item.hpp>
#include <module-utils/time/ScopedTime.hpp>
#include <service-desktop/endpoints/developerMode/event/DomRequest.hpp>

namespace app
{
    DOMResponder::DOMResponder(const std::string &name, gui::Item &item, std::unique_ptr<sdesktop::Event> event)
        : name(name), item(item), event(std::move(event))
    {}

    [[nodiscard]] auto DOMResponder::build() -> std::shared_ptr<sys::Message>
    {
        createDOM();
        return std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
    }

    void DOMResponder::createDOM()
    {
        auto t          = utils::time::Scoped("Time to build dom");
        auto serializer = gui::Item2JsonSerializer();
        serializer.traverse(item);
        auto evt = std::make_unique<sdesktop::developerMode::DomRequestEvent>(*event);
        evt->setJson(serializer.get());
        event = std::move(evt);
    }
} // namespace app

A module-apps/DOMResponder.hpp => module-apps/DOMResponder.hpp +41 -0
@@ 0,0 1,41 @@
// 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 <service-desktop/DesktopEvent.hpp>
#include <Service/MessageForward.hpp>
#include <string>

namespace gui
{
    class Item;
}

namespace sdesktop::developerMode
{
    class Event;
}

namespace app
{
    /// This class essentially hides implementation of: ServiceDesktop mechanics and DOM serialization from Application
    /// gets event data
    /// creates DOM and enapsulates in it event data
    /// builds response to be used with ServiceDesktop response type
    class DOMResponder
    {
        std::string name;
        gui::Item &item;
        std::unique_ptr<sdesktop::Event> event;
        /// uses gui::Item serializer to create DOM dump
        void createDOM();

      public:
        DOMResponder(const std::string &, gui::Item &, std::unique_ptr<sdesktop::Event> event);
        /// creates response used to inform ServiceDesktop with DOM dump encapsulated
        /// requires use of createDOM first
        [[nodiscard]] auto build() -> std::shared_ptr<sys::Message>;
    };

}; // namespace app

M module-apps/messages/AppMessage.hpp => module-apps/messages/AppMessage.hpp +2 -13
@@ 1,29 1,18 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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 "Common.hpp"
#include "MessageType.hpp"
#include "Service/Message.hpp"
#include "SwitchData.hpp"
#include "gui/input/InputEvent.hpp"
#include "BaseAppMessage.hpp"
#include <memory>
#include <string>

namespace app
{

    /*
     * @brief Template for all messages that go to application manager
     */
    class AppMessage : public sys::DataMessage
    {
      public:
        AppMessage(MessageType messageType) : sys::DataMessage(messageType){};
        AppMessage() : sys::DataMessage(MessageType::AppMessage){};
    };

    class AppActionRequest : public AppMessage
    {
      public:

A module-apps/messages/BaseAppMessage.hpp => module-apps/messages/BaseAppMessage.hpp +17 -0
@@ 0,0 1,17 @@
// 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 "MessageType.hpp"
#include "Service/Message.hpp"

namespace app
{
    class AppMessage : public sys::DataMessage
    {
      public:
        explicit AppMessage(MessageType messageType) : sys::DataMessage(messageType){};
        AppMessage() : sys::DataMessage(MessageType::AppMessage){};
    };
} // namespace app

M module-bsp/board/linux/rtc/rtc.cpp => module-bsp/board/linux/rtc/rtc.cpp +6 -1
@@ 180,7 180,12 @@ static void rtc_worker(void *pvp)

// TODO delete function if it will not be used in service
void SNVS_HP_WRAPPER_IRQHandler()
{}
{
    /// HERE on TICK set_time timer monotonic
    /// gmtime    <- based on timer monotonic
    /// localtime <- based on timer monotonic
    /// timezone  <- can be based on offset between two if one super wishes... (+1, +2 etc... )
}
/*
 *  **********************************************************************************************************************
 *  * *

M module-gui/gui/dom/Item2JsonSerializer.cpp => module-gui/gui/dom/Item2JsonSerializer.cpp +6 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Item2JsonSerializer.hpp"


@@ 69,3 69,8 @@ void Item2JsonSerializer::dump(std::ostream &stream)
{
    stream << document.dump();
}

[[nodiscard]] auto Item2JsonSerializer::get() -> json11::Json &&
{
    return std::move(document);
}

M module-gui/gui/dom/Item2JsonSerializer.hpp => module-gui/gui/dom/Item2JsonSerializer.hpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 26,5 26,6 @@ namespace gui
        /// JSON format and kept in `document`.
        void traverse(gui::Item &root);
        void dump(std::ostream &stream);
        [[nodiscard]] auto get() -> json11::Json &&;
    };
} // namespace gui

M module-services/service-appmgr/CMakeLists.txt => module-services/service-appmgr/CMakeLists.txt +3 -1
@@ 22,7 22,9 @@ set(SOURCES
    messages/SwitchBackRequest.cpp
    messages/SwitchConfirmation.cpp
    messages/SwitchRequest.cpp
    messages/UpdateInProgress.cpp)
    messages/UpdateInProgress.cpp
    messages/DOMRequest.cpp
)

add_library(${PROJECT_NAME} STATIC ${SOURCES})


M module-services/service-appmgr/messages/BaseMessage.cpp => module-services/service-appmgr/messages/BaseMessage.cpp +6 -1
@@ 1,10 1,15 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-appmgr/messages/BaseMessage.hpp>

namespace app::manager
{

    BaseMessage::BaseMessage(ApplicationName sender)
        : sys::DataMessage(MessageType::APMGeneric), senderName(std::move(sender))
    {}

    BaseMessage::BaseMessage(MessageType type, ApplicationName sender)
        : sys::DataMessage(type), senderName{std::move(sender)}
    {}

A module-services/service-appmgr/messages/DOMRequest.cpp => module-services/service-appmgr/messages/DOMRequest.cpp +18 -0
@@ 0,0 1,18 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-desktop/DeveloperModeMessage.hpp"
#include <service-appmgr/messages/DOMRequest.hpp>

namespace app::manager
{

    DOMRequest::DOMRequest(ApplicationName sender, std::unique_ptr<sdesktop::Event> event)
        : sdesktop::developerMode::DeveloperModeRequest(std::move(event)), sender(std::move(sender))
    {}

    DOMRequest::DOMRequest(const DOMRequest &dom)
        : sdesktop::developerMode::DeveloperModeRequest(std::make_unique<sdesktop::Event>(*dom.event)),
          sender(std::move(dom.sender))
    {}
} // namespace app::manager

M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +16 -0
@@ 28,6 28,8 @@
#include <module-utils/Utils.hpp>
#include <module-utils/time/DateAndTimeSettings.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <service-appmgr/messages/DOMRequest.hpp>

// Auto phone lock disabled for now till the times when it's debugged
// #define AUTO_PHONE_LOCK_ENABLED
namespace app::manager


@@ 294,6 296,8 @@ namespace app::manager
            return msgHandled();
        });

        connect(typeid(app::manager::DOMRequest), [&](sys::Message *request) { return handleDOMRequest(request); });

        auto convertibleToActionHandler = [this](sys::Message *request) { return handleMessageAsAction(request); };
        connect(typeid(CellularSimRequestPinMessage), convertibleToActionHandler);
        connect(typeid(CellularSimRequestPukMessage), convertibleToActionHandler);


@@ 843,4 847,16 @@ namespace app::manager
        }
        utils::localize.setInputLanguage(value);
    }

    auto ApplicationManager::handleDOMRequest(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>
    {
        auto app = getFocusedApplication();
        if (app != nullptr) {
            auto message = static_cast<app::manager::DOMRequest *>(request);
            LOG_INFO("DOM request for: %s", message->getSenderName().c_str());
            bus.sendUnicast(std::make_unique<app::manager::DOMRequest>(*message), app->name());
            return sys::MessageNone{};
        }
        return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
    }
} // namespace app::manager

M module-services/service-appmgr/service-appmgr/messages/BaseMessage.hpp => module-services/service-appmgr/service-appmgr/messages/BaseMessage.hpp +2 -2
@@ 1,11 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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 <Service/Message.hpp>
#include <MessageType.hpp>

#include <module-apps/Application.hpp>

namespace app::manager


@@ 14,6 13,7 @@ namespace app::manager
    {
      public:
        BaseMessage(MessageType type, ApplicationName sender);
        explicit BaseMessage(ApplicationName sender);

        [[nodiscard]] auto getSenderName() const noexcept -> const ApplicationName &;


A module-services/service-appmgr/service-appmgr/messages/DOMRequest.hpp => module-services/service-appmgr/service-appmgr/messages/DOMRequest.hpp +28 -0
@@ 0,0 1,28 @@
// 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 "BaseMessage.hpp"
#include "service-desktop/DeveloperModeMessage.hpp"
#include <json/json11.hpp>

namespace app::manager
{
    class DOMRequest : public sdesktop::developerMode::DeveloperModeRequest
    {
        ApplicationName sender;

      public:
        DOMRequest(ApplicationName sender, std::unique_ptr<sdesktop::Event> event);
        [[nodiscard]] auto getEvent()
        {
            return std::move(event);
        }
        [[nodiscard]] auto getSenderName() const
        {
            return sender;
        }
        DOMRequest(const DOMRequest &dom);
    };
} // namespace app::manager

M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +2 -0
@@ 133,6 133,8 @@ namespace app::manager
        auto handleDateFormatChange(DateFormatChangeRequest *msg) -> bool;
        auto handlePowerSavingModeInit() -> bool;
        auto handleMessageAsAction(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>;
        /// handles dom request by passing this request to application which should provide the dom
        auto handleDOMRequest(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>;

        void requestApplicationClose(ApplicationHandle &app, bool isCloseable);
        void onApplicationSwitch(ApplicationHandle &app,

A module-services/service-cellular/SMSSend.hpp => module-services/service-cellular/SMSSend.hpp +22 -0
@@ 0,0 1,22 @@
// 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 "SMSRecord.hpp"
#include "service-cellular/ServiceCellular.hpp"

namespace cellular::internal
{

    class SMSSend
    {
      protected:
        ServiceCellular &cellular;

      public:
        explicit SMSSend(ServiceCellular &p) : cellular(p)
        {}
        [[nodiscard]] auto send(SMSRecord &record) -> bool;
    };
} // namespace cellular::internal

M module-services/service-desktop/CMakeLists.txt => module-services/service-desktop/CMakeLists.txt +6 -1
@@ 12,6 12,9 @@ set(SOURCES
    endpoints/contacts/ContactsEndpoint.cpp
    endpoints/developerMode/DeveloperModeEndpoint.cpp
    endpoints/developerMode/DeveloperModeHelper.cpp
    endpoints/developerMode/Mode/BaseHelper.cpp
    endpoints/developerMode/Mode/UI_Helper.cpp
    endpoints/developerMode/event/DomRequest.cpp
    endpoints/deviceInfo/DeviceInfoEndpoint.cpp
    endpoints/factoryReset/FactoryReset.cpp
    endpoints/factoryReset/FactoryResetEndpoint.cpp


@@ 24,10 27,12 @@ set(SOURCES
    endpoints/calendarEvents/CalendarEventsHelper.cpp
    endpoints/calendarEvents/CalendarEventsEndpoint.cpp

    parser/ParserUtils.cpp
    parser/HttpEnums.cpp
    parser/ParserFSM.cpp
    parser/MessageHandler.cpp

    DesktopEvent.cpp
    DeveloperModeMessage.cpp
    DesktopMessages.cpp
    ServiceDesktop.cpp
    WorkerDesktop.cpp

A module-services/service-desktop/DesktopEvent.cpp => module-services/service-desktop/DesktopEvent.cpp +10 -0
@@ 0,0 1,10 @@
#include "service-desktop/DesktopEvent.hpp"
#include <service-desktop/parser/MessageHandler.hpp>

namespace sdesktop
{
    void Event::send()
    {
        parserFSM::MessageHandler::putToSendQueue(context.createSimpleResponse());
    }
} // namespace sdesktop

M module-services/service-desktop/DesktopMessages.cpp => module-services/service-desktop/DesktopMessages.cpp +0 -12
@@ 7,10 7,6 @@
namespace sdesktop
{
    using namespace parserFSM;
    void Event::send()
    {
        MessageHandler::putToSendQueue(context.createSimpleResponse());
    }
    namespace developerMode
    {



@@ 41,17 37,9 @@ namespace sdesktop
            context.setEndpoint(EndpointType::developerMode);
            context.setResponseBody(json11::Json::object{{json::developerMode::cellularStateInfo, stateStr}});
        }

        DeveloperModeRequest::DeveloperModeRequest(std::unique_ptr<Event> event)
            : sys::DataMessage(MessageType::DeveloperModeRequest), event(std::move(event))
        {}

        DeveloperModeRequest::DeveloperModeRequest() : sys::DataMessage(MessageType::DeveloperModeRequest)
        {}
    } // namespace developerMode
    namespace bluetooth
    {

        BluetoothStatusRequestEvent::BluetoothStatusRequestEvent(int state)
        {
            context.setResponseStatus(http::Code::OK);

A module-services/service-desktop/DeveloperModeMessage.cpp => module-services/service-desktop/DeveloperModeMessage.cpp +14 -0
@@ 0,0 1,14 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-desktop/DeveloperModeMessage.hpp>

namespace sdesktop::developerMode
{
    DeveloperModeRequest::DeveloperModeRequest(std::unique_ptr<Event> event)
        : sys::DataMessage(MessageType::DeveloperModeRequest), event(std::move(event))
    {}

    DeveloperModeRequest::DeveloperModeRequest() : sys::DataMessage(MessageType::DeveloperModeRequest)
    {}
} // namespace sdesktop::developerMode

M module-services/service-desktop/README.md => module-services/service-desktop/README.md +52 -11
@@ 95,31 95,72 @@ enum class Code

##### Example request

```#000000053{"endpoint":1, "method":1, "payload":{"test":"test"}}```
```
#000000053{"endpoint":1, "method":1, "payload":{"test":"test"}}
```

##### Example response

```#000000095{"endpoint": 1, "status": 200, "body": {"charging": true, "level": 75, "maximumCapacity": 100}}```
```
#000000095{"endpoint": 1, "status": 200, "body": {"charging": true, "level": 75, "maximumCapacity": 100}}
```

#### Sample requests
*Contacts*
get contact:
```#000000056{"endpoint":6, "method":1, "uuid":1, "body":{"count":5}}```
```
#000000056{"endpoint":6, "method":1, "uuid":1, "body":{"count":5}}
```
response:
```#000000861{"body": [{"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bolig<0xc5><0x82>owa", "blocked": false, "favourite": true, "id": 19, "numbers": ["500639802"], "priName": "Alek"}, {"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bolig<0xc5><0x82>owa", "blocked": false, "favourite": true, "id": 22, "numbers": ["500453837"], "priName": "Gra<0xc5><0xbc>yna"}, {"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bolig<0xc5><0x82>owa", "blocked": false, "favourite": true, "id": 20, "numbers": ["500545546"], "priName": "Zofia"}, {"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bubel", "blocked": false, "favourite": true, "id": 44, "numbers": ["500087699"], "priName": "Brian"}, {"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bubel", "blocked": false, "favourite": true, "id": 43, "numbers": ["500656981"], "priName": "Cezary"}], "endpoint": 6, "status": 200, "uuid": "3"}```
```
#000000861{"body": [{"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bolig<0xc5><0x82>owa", "blocked": false, "favourite": true, "id": 19, "numbers": ["500639802"], "priName": "Alek"}, {"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bolig<0xc5><0x82>owa", "blocked": false, "favourite": true, "id": 22, "numbers": ["500453837"], "priName": "Gra<0xc5><0xbc>yna"}, {"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bolig<0xc5><0x82>owa", "blocked": false, "favourite": true, "id": 20, "numbers": ["500545546"], "priName": "Zofia"}, {"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bubel", "blocked": false, "favourite": true, "id": 44, "numbers": ["500087699"], "priName": "Brian"}, {"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Bubel", "blocked": false, "favourite": true, "id": 43, "numbers": ["500656981"], "priName": "Cezary"}], "endpoint": 6, "status": 200, "uuid": "3"}
```

update contact:
```#000000203{"endpoint":6, "method":2, "uuid":123, "body":{"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Cic", "blocked": true, "favourite": true, "id": "43", "numbers": ["724842187"], "priName": "Baatek"}}```
```
#000000203{"endpoint":6, "method":2, "uuid":123, "body":{"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Cic", "blocked": true, "favourite": true, "id": "43", "numbers": ["724842187"], "priName": "Baatek"}}
```
response:
```#000000057{"body": "", "endpoint": 6, "status": 500, "uuid": "123"}/```
```#000000057{"body": "", "endpoint": 6, "status": 200, "uuid": "123"}```
```
#000000057{"body": "", "endpoint": 6, "status": 500, "uuid": "123"}/
```
```
#000000057{"body": "", "endpoint": 6, "status": 200, "uuid": "123"}
```

add contact:
```#000000191{"endpoint":6, "method":3, "uuid":123, "body":{"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Cic", "blocked": true, "favourite": true, "numbers": ["724842187"], "priName": "Baatek"}}```
```
#000000191{"endpoint":6, "method":3, "uuid":123, "body":{"address": "6 Czeczota St.\n02600 Warsaw", "altName": "Cic", "blocked": true, "favourite": true, "numbers": ["724842187"], "priName": "Baatek"}}
```
response:
```#000000057{"body": "", "endpoint": 6, "status": 200, "uuid": "123"}```
```
#000000057{"body": "", "endpoint": 6, "status": 200, "uuid": "123"}
```

remove contact:
```#000000057{"endpoint":6, "method":4, "uuid":123, "body":{"id": 23}}```
```
#000000057{"endpoint":6, "method":4, "uuid":123, "body":{"id": 23}}
```
response:
```#000000057{"body": "", "endpoint": 6, "status": 200, "uuid": "123"}```
```
#000000057{"body": "", "endpoint": 6, "status": 200, "uuid": "123"}
```

### Service documentation

#### Hi level view

![Flowchart](./doc/how_machine_works.svg)
<img src="./doc/how_machine_works.svg">

#### System asynchronous calls synchronization

Calls from outside world are REST like. This means that:
- for one request 
- there is one response

To provide synchronous response for asynchronous system calls we have special mechanism.

1. Send: `DeveloperModeRequest` message with special `Event` Data
2. Process `DeveloperModeRequest` in system, fill in `Event` Data
3. Pass `DeveloperModeRequest` back to requester

M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +1 -0
@@ 1,6 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-appmgr/service-appmgr/messages/DOMRequest.hpp"
#include "service-desktop/DesktopMessages.hpp"
#include "service-desktop/ServiceDesktop.hpp"
#include "service-desktop/WorkerDesktop.hpp"

A module-services/service-desktop/doc/how_machine_works.puml => module-services/service-desktop/doc/how_machine_works.puml +9 -0
@@ 0,0 1,9 @@
@startuml
Worker -> Worker : get data
Worker --> ServiceDesktop : pass frame
ServiceDesktop -> ServiceDesktop :  parse payload{ data request }
ServiceDesktop --> System : get {data}
System --> ServiceDesktop : responds {data}
ServiceDesktop -> ServiceDesktop : response final touch
ServiceDesktop -> Worker : push response
@enduml

A module-services/service-desktop/doc/how_machine_works.svg => module-services/service-desktop/doc/how_machine_works.svg +19 -0
@@ 0,0 1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="346px" preserveAspectRatio="none" style="width:411px;height:346px;" version="1.1" viewBox="0 0 411 346" width="411px" zoomAndPan="magnify"><defs><filter height="300%" id="f1jl8apq24479q" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="38" x2="38" y1="40.2969" y2="303.2266"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="156" x2="156" y1="40.2969" y2="303.2266"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="366" x2="366" y1="40.2969" y2="303.2266"/><rect fill="#FEFECE" filter="url(#f1jl8apq24479q)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="63" x="5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="12" y="24.9951">Worker</text><rect fill="#FEFECE" filter="url(#f1jl8apq24479q)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="63" x="5" y="302.2266"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="12" y="322.2217">Worker</text><rect fill="#FEFECE" filter="url(#f1jl8apq24479q)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="123" x="93" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="109" x="100" y="24.9951">ServiceDesktop</text><rect fill="#FEFECE" filter="url(#f1jl8apq24479q)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="123" x="93" y="302.2266"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="109" x="100" y="322.2217">ServiceDesktop</text><rect fill="#FEFECE" filter="url(#f1jl8apq24479q)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="65" x="332" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="51" x="339" y="24.9951">System</text><rect fill="#FEFECE" filter="url(#f1jl8apq24479q)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="65" x="332" y="302.2266"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="51" x="339" y="322.2217">System</text><line style="stroke:#A80036;stroke-width:1.0;" x1="38.5" x2="80.5" y1="71.4297" y2="71.4297"/><line style="stroke:#A80036;stroke-width:1.0;" x1="80.5" x2="80.5" y1="71.4297" y2="84.4297"/><line style="stroke:#A80036;stroke-width:1.0;" x1="39.5" x2="80.5" y1="84.4297" y2="84.4297"/><polygon fill="#A80036" points="49.5,80.4297,39.5,84.4297,49.5,88.4297,45.5,84.4297" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="54" x="45.5" y="66.3638">get data</text><polygon fill="#A80036" points="144.5,109.5625,154.5,113.5625,144.5,117.5625,148.5,113.5625" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:2.0,2.0;" x1="38.5" x2="150.5" y1="113.5625" y2="113.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="72" x="45.5" y="108.4966">pass frame</text><line style="stroke:#A80036;stroke-width:1.0;" x1="156.5" x2="198.5" y1="142.6953" y2="142.6953"/><line style="stroke:#A80036;stroke-width:1.0;" x1="198.5" x2="198.5" y1="142.6953" y2="155.6953"/><line style="stroke:#A80036;stroke-width:1.0;" x1="157.5" x2="198.5" y1="155.6953" y2="155.6953"/><polygon fill="#A80036" points="167.5,151.6953,157.5,155.6953,167.5,159.6953,163.5,155.6953" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="196" x="163.5" y="137.6294">parse payload{ data request }</text><polygon fill="#A80036" points="354.5,180.8281,364.5,184.8281,354.5,188.8281,358.5,184.8281" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:2.0,2.0;" x1="156.5" x2="360.5" y1="184.8281" y2="184.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="70" x="163.5" y="179.7622">get {data}</text><polygon fill="#A80036" points="167.5,209.9609,157.5,213.9609,167.5,217.9609,163.5,213.9609" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:2.0,2.0;" x1="161.5" x2="365.5" y1="213.9609" y2="213.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="108" x="173.5" y="208.895">responds {data}</text><line style="stroke:#A80036;stroke-width:1.0;" x1="156.5" x2="198.5" y1="243.0938" y2="243.0938"/><line style="stroke:#A80036;stroke-width:1.0;" x1="198.5" x2="198.5" y1="243.0938" y2="256.0938"/><line style="stroke:#A80036;stroke-width:1.0;" x1="157.5" x2="198.5" y1="256.0938" y2="256.0938"/><polygon fill="#A80036" points="167.5,252.0938,157.5,256.0938,167.5,260.0938,163.5,256.0938" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="129" x="163.5" y="238.0278">response final touch</text><polygon fill="#A80036" points="49.5,281.2266,39.5,285.2266,49.5,289.2266,45.5,285.2266" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="43.5" x2="155.5" y1="285.2266" y2="285.2266"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="94" x="55.5" y="280.1606">push response</text><!--MD5=[040fbad3755c3758adab0ffbcf4d4812]
@startuml
Worker -> Worker : get data
Worker - -> ServiceDesktop : pass frame
ServiceDesktop -> ServiceDesktop :  parse payload{ data request }
ServiceDesktop - -> System : get {data}
System - -> ServiceDesktop : responds {data}
ServiceDesktop -> ServiceDesktop : response final touch
ServiceDesktop -> Worker : push response
@enduml

PlantUML version 1.2021.00(Sun Jan 10 11:25:05 CET 2021)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Default Encoding: UTF-8
Language: en
Country: US
--></g></svg>
\ No newline at end of file

M module-services/service-desktop/endpoints/Context.hpp => module-services/service-desktop/endpoints/Context.hpp +9 -9
@@ 3,8 3,8 @@

#pragma once

#include <json/json11.hpp>
#include <module-services/service-desktop/parser/ParserUtils.hpp>
#include "ResponseContext.hpp"

namespace parserFSM
{


@@ 23,12 23,6 @@ namespace parserFSM
        inline constexpr auto entries    = "entries";
    } // namespace json

    struct endpointResponseContext
    {
        http::Code status = http::Code::OK;
        json11::Json body = json11::Json();
    };

    constexpr int invalidUuid = 0;

    class Context


@@ 38,7 32,7 @@ namespace parserFSM
        EndpointType endpoint;
        uint32_t uuid;
        http::Method method;
        endpointResponseContext responseContext;
        endpoint::ResponseContext responseContext;

        auto validate() -> void
        {


@@ 99,6 93,12 @@ namespace parserFSM
                                                             {json::body, responseContext.body}};
            return buildResponseStr(responseJson.dump().size(), responseJson.dump());
        }

        auto setResponse(endpoint::ResponseContext r)
        {
            r = responseContext;
        }

        auto setResponseStatus(http::Code status)
        {
            responseContext.status = status;


@@ 111,7 111,7 @@ namespace parserFSM
        {
            responseContext.body = respBody;
        }
        auto getBody() -> json11::Json
        auto getBody() -> const json11::Json &
        {
            return body;
        }

A module-services/service-desktop/endpoints/ResponseContext.hpp => module-services/service-desktop/endpoints/ResponseContext.hpp +16 -0
@@ 0,0 1,16 @@
// 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 <json/json11.hpp>
#include <parser/HttpEnums.hpp>

namespace parserFSM::endpoint
{
    struct ResponseContext
    {
        http::Code status = http::Code::OK;
        json11::Json body = json11::Json();
    };
} // namespace parserFSM::endpoint

M module-services/service-desktop/endpoints/backup/BackupRestore.cpp => module-services/service-desktop/endpoints/backup/BackupRestore.cpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BackupRestore.hpp"


@@ 16,6 16,7 @@
#include <memory>
#include <string>
#include <vector>
#include <vfs.hpp>

namespace sys
{

M module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp +29 -12
@@ 1,24 1,41 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "DeveloperModeEndpoint.hpp"
#include "log/log.hpp"

#include <endpoints/Context.hpp>
#include <service-desktop/parser/MessageHandler.hpp>

using namespace parserFSM;

auto DeveloperModeEndpoint::handle(Context &context) -> void
{
    switch (context.getMethod()) {
    case http::Method::get:
        helper->processGetRequest(context);
        break;
    case http::Method::post:
        break;
    case http::Method::put:
        helper->processPutRequest(context);
        break;
    case http::Method::del:
        break;
    auto &p               = helperSwitcher(context);
    auto [sent, response] = p.process(context.getMethod(), context);
    if (sent == sent::delayed) {
        LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching");
    }
    if (sent == sent::no) {
        if (not response) {
            LOG_ERROR("Response not sent & response not created : respond with error");
            context.setResponseStatus(http::Code::NotAcceptable);
        }
        else {
            context.setResponse(response.value());
        }

        MessageHandler::putToSendQueue(context.createSimpleResponse());
    }
    if (sent == sent::yes and response) {
        LOG_ERROR("Response set when we already handled response in handler");
    }
}

auto DeveloperModeEndpoint::helperSwitcher(parserFSM::Context &ctx) -> parserFSM::BaseHelper &
{
    if (ctx.getBody()["ui"] == true) {
        return *uiHelper;
    }
    return *helper;
}

M module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.hpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.hpp +10 -4
@@ 1,9 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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 "DeveloperModeHelper.hpp"
#include "Mode/UI_Helper.hpp"
#include <endpoints/Endpoint.hpp>
#include <parser/ParserUtils.hpp>



@@ 24,13 25,18 @@ namespace sys
class DeveloperModeEndpoint : public parserFSM::Endpoint
{
  private:
    std::unique_ptr<parserFSM::DeveloperModeHelper> helper;
    const std::unique_ptr<parserFSM::DeveloperModeHelper> helper;
    const std::unique_ptr<parserFSM::UI_Helper> uiHelper;

  public:
    DeveloperModeEndpoint(sys::Service *_ownerServicePtr) : Endpoint(_ownerServicePtr)
    explicit DeveloperModeEndpoint(sys::Service *_ownerServicePtr)
        : Endpoint(_ownerServicePtr), helper(std::make_unique<parserFSM::DeveloperModeHelper>(ownerServicePtr)),
          uiHelper(std::make_unique<parserFSM::UI_Helper>(ownerServicePtr))
    {
        debugName = "DeveloperModeEndpoint";
        helper    = std::make_unique<parserFSM::DeveloperModeHelper>(ownerServicePtr);
    }

    auto handle(parserFSM::Context &context) -> void override;

    [[nodiscard]] auto helperSwitcher(parserFSM::Context &ctx) -> parserFSM::BaseHelper &;
};

M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp +43 -38
@@ 5,7 5,6 @@
#include <service-desktop/DesktopMessages.hpp>
#include <parser/ParserUtils.hpp>

#include <service-desktop/parser/MessageHandler.hpp>
#include <service-evtmgr/Constants.hpp>
#include <service-cellular/CellularMessage.hpp>
#include <service-cellular/ServiceCellular.hpp>


@@ 18,6 17,7 @@

#include <service-db/DBServiceAPI.hpp>
#include <time/time_conversion.hpp>
#include <service-desktop/parser/MessageHandler.hpp>

namespace parserFSM
{


@@ 25,36 25,47 @@ namespace parserFSM
} // namespace parserFSM

using namespace parserFSM;
auto DeveloperModeHelper::processPutRequest(Context &context) -> sys::ReturnCodes

constexpr http::Code toCode(bool r)
{
    return r ? http::Code::OK : http::Code::InternalServerError;
}

auto DeveloperModeHelper::processPut(Context &context) -> ProcessResult
{
    auto body = context.getBody();
    auto code = http::Code::BadRequest;
    if (body[json::developerMode::keyPressed].is_number()) {
        auto keyValue = body[json::developerMode::keyPressed].int_value();
        auto state    = body[json::developerMode::state].int_value();
        sendKeypress(getKeyCode(keyValue), static_cast<gui::InputEvent::State>(state));
        MessageHandler::putToSendQueue(context.createSimpleResponse());
        return {sent::no, std::nullopt};
    }
    else if (body[json::developerMode::AT].is_string()) {

        auto msg     = std::make_shared<cellular::RawCommand>();
        msg->command = body[json::developerMode::AT].string_value();
        msg->timeout = 3000;
        ownerServicePtr->bus.sendUnicast(std::move(msg), ServiceCellular::serviceName);
        code         = toCode(owner->bus.sendUnicast(std::move(msg), ServiceCellular::serviceName));
        return {sent::delayed, std::nullopt};
    }
    else if (body[json::developerMode::focus].bool_value()) {
        auto event = std::make_unique<sdesktop::developerMode::AppFocusChangeEvent>();
        auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
        ownerServicePtr->bus.sendUnicast(std::move(msg), service::name::evt_manager);
        code       = toCode(owner->bus.sendUnicast(std::move(msg), service::name::evt_manager));
        return {sent::delayed, std::nullopt};
    }
    else if (body[json::developerMode::isLocked].bool_value()) {
        auto event = std::make_unique<sdesktop::developerMode::ScreenlockCheckEvent>();
        auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
        ownerServicePtr->bus.sendUnicast(std::move(msg), "ApplicationDesktop");
        code       = toCode(owner->bus.sendUnicast(std::move(msg), "ApplicationDesktop"));
        return {sent::delayed, std::nullopt};
    }
    else if (body[json::developerMode::changeSim].is_number()) {
        int simSelected = body[json::developerMode::changeSim].int_value();
        requestSimChange(simSelected);
        MessageHandler::putToSendQueue(context.createSimpleResponse());
        code = toCode(true);
        return {sent::no, std::nullopt};
    }
    else if (body[json::developerMode::changeCellularStateCmd].is_number()) {
        int cellularState = body[json::developerMode::changeCellularStateCmd].int_value();


@@ 70,47 81,40 @@ auto DeveloperModeHelper::processPutRequest(Context &context) -> sys::ReturnCode
                return prepareSMS(context);
            }
            else {
                context.setResponseStatus(http::Code::NotAcceptable);
                MessageHandler::putToSendQueue(context.createSimpleResponse());
                return {sent::no, endpoint::ResponseContext{.status = http::Code::NotAcceptable}};
            }
        }
    }
    else {
        context.setResponseStatus(http::Code::BadRequest);
        MessageHandler::putToSendQueue(context.createSimpleResponse());
    }
    return sys::ReturnCodes::Unresolved;
    return {sent::no, endpoint::ResponseContext{.status = code}};
}

auto DeveloperModeHelper::processGetRequest(Context &context) -> sys::ReturnCodes
auto DeveloperModeHelper::processGet(Context &context) -> ProcessResult
{
    auto body = context.getBody();
    if (body[json::developerMode::getInfo].is_string()) {
        auto keyValue = body[json::developerMode::getInfo].string_value();
        if (keyValue == json::developerMode::simStateInfo) {
            context.setResponseBody(json11::Json::object(
                {{json::selectedSim, std::to_string(static_cast<int>(Store::GSM::get()->selected))},
                 {json::sim, std::to_string(static_cast<int>(Store::GSM::get()->sim))},
                 {json::trayState, std::to_string(static_cast<int>(Store::GSM::get()->tray))}}));
            MessageHandler::putToSendQueue(context.createSimpleResponse());
            auto response = endpoint::ResponseContext{
                .body = json11::Json::object(
                    {{json::selectedSim, std::to_string(static_cast<int>(Store::GSM::get()->selected))},
                     {json::sim, std::to_string(static_cast<int>(Store::GSM::get()->sim))},
                     {json::trayState, std::to_string(static_cast<int>(Store::GSM::get()->tray))}})};
            response.status = http::Code::OK;
            return {sent::no, std::move(response)};
        }
        else if (keyValue == json::developerMode::cellularStateInfo) {
            if (requestServiceStateInfo(ownerServicePtr) == false) {
                context.setResponseStatus(http::Code::NotAcceptable);
                MessageHandler::putToSendQueue(context.createSimpleResponse());
            if (requestServiceStateInfo(owner) == false) {
                return {sent::no, endpoint::ResponseContext{.status = http::Code::NotAcceptable}};
            }
        }
        else {
            context.setResponseStatus(http::Code::BadRequest);
            MessageHandler::putToSendQueue(context.createSimpleResponse());
            return {sent::no, endpoint::ResponseContext{.status = http::Code::BadRequest}};
        }
    }
    else {
        context.setResponseStatus(http::Code::BadRequest);
        MessageHandler::putToSendQueue(context.createSimpleResponse());
        return {sent::no, endpoint::ResponseContext{.status = http::Code::BadRequest}};
    }

    return sys::ReturnCodes::Unresolved;
    return {sent::no, std::nullopt};
}

auto DeveloperModeHelper::getKeyCode(int val) noexcept -> bsp::KeyCodes


@@ 172,7 176,7 @@ auto DeveloperModeHelper::getKeyCode(int val) noexcept -> bsp::KeyCodes
    };
}

void DeveloperModeHelper::sendKeypress(bsp::KeyCodes keyCode, gui::InputEvent::State state)
bool DeveloperModeHelper::sendKeypress(bsp::KeyCodes keyCode, gui::InputEvent::State state)
{
    RawKey key{.state = RawKey::State::Released, .key_code = keyCode};



@@ 180,7 184,7 @@ void DeveloperModeHelper::sendKeypress(bsp::KeyCodes keyCode, gui::InputEvent::S
    LOG_INFO("Sending %s", event.str().c_str());
    auto message = std::make_shared<app::AppInputEventMessage>(std::move(event));

    ownerServicePtr->bus.sendUnicast(std::move(message), service::name::evt_manager);
    return owner->bus.sendUnicast(std::move(message), service::name::evt_manager);
}

void DeveloperModeHelper::requestSimChange(const int simSelected)


@@ 189,22 193,22 @@ void DeveloperModeHelper::requestSimChange(const int simSelected)
    if (simSelected == static_cast<int>(Store::GSM::SIM::SIM2)) {
        sim = Store::GSM::SIM::SIM2;
    }
    CellularServiceAPI::SetSimCard(ownerServicePtr, sim);
    CellularServiceAPI::SetSimCard(owner, sim);
}

bool DeveloperModeHelper::requestCellularPowerStateChange(const int cellularState)
{
    bool res = false;
    if (cellularState == 1) {
        res = CellularServiceAPI::ChangeModulePowerState(ownerServicePtr, cellular::State::PowerState::Off);
        res = CellularServiceAPI::ChangeModulePowerState(owner, cellular::State::PowerState::Off);
    }
    else if (cellularState == 2) {
        res = CellularServiceAPI::ChangeModulePowerState(ownerServicePtr, cellular::State::PowerState::On);
        res = CellularServiceAPI::ChangeModulePowerState(owner, cellular::State::PowerState::On);
    }
    else if (cellularState == 3) {
        auto event = std::make_unique<sdesktop::developerMode::CellularHotStartEvent>();
        auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
        res        = ownerServicePtr->bus.sendUnicast(std::move(msg), ServiceCellular::serviceName);
        res        = owner->bus.sendUnicast(std::move(msg), ServiceCellular::serviceName);
    }
    return res;
}


@@ 218,7 222,7 @@ auto DeveloperModeHelper::smsRecordFromJson(json11::Json msgJson) -> SMSRecord
    return record;
}

auto DeveloperModeHelper::prepareSMS(Context &context) -> sys::ReturnCodes
auto DeveloperModeHelper::prepareSMS(Context &context) -> ProcessResult
{
    SMSRecord record = smsRecordFromJson(context.getBody());



@@ 242,8 246,9 @@ auto DeveloperModeHelper::prepareSMS(Context &context) -> sys::ReturnCodes
        },
        context);

    DBServiceAPI::AddSMS(ownerServicePtr, record, std::move(listener));
    return sys::ReturnCodes::Success;
    DBServiceAPI::AddSMS(owner, record, std::move(listener));
    // actual success / fail happens in listener
    return {sent::delayed, std::nullopt};
}

bool DeveloperModeHelper::requestServiceStateInfo(sys::Service *serv)

M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.hpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.hpp +10 -7
@@ 11,6 11,7 @@
#include <bsp/keyboard/key_codes.hpp>
#include <input/InputEvent.hpp>
#include <module-db/Interface/SMSRecord.hpp>
#include "Mode/BaseHelper.hpp"

namespace sys
{


@@ 20,22 21,24 @@ namespace sys
namespace parserFSM
{

    class DeveloperModeHelper
    class DeveloperModeHelper : public BaseHelper
    {
        sys::Service *ownerServicePtr = nullptr;
        static auto getKeyCode(int val) noexcept -> bsp::KeyCodes;
        void sendKeypress(bsp::KeyCodes keyCode, gui::InputEvent::State state);
        bool sendKeypress(bsp::KeyCodes keyCode, gui::InputEvent::State state);

        void requestSimChange(const int simSelected);
        auto smsRecordFromJson(json11::Json msgJson) -> SMSRecord;
        auto prepareSMS(Context &context) -> sys::ReturnCodes;
        bool requestCellularPowerStateChange(const int simSelected);
        bool requestServiceStateInfo(sys::Service *serv);
        auto prepareSMS(Context &context) -> ProcessResult;

      public:
        DeveloperModeHelper(sys::Service *_ownerServicePtr) : ownerServicePtr(_ownerServicePtr){};
        auto processPutRequest(Context &context) -> sys::ReturnCodes;
        auto processGetRequest(Context &context) -> sys::ReturnCodes;
        explicit DeveloperModeHelper(sys::Service *p) : BaseHelper(p)
        {}

      private:
        auto processPut(Context &context) -> ProcessResult final;
        auto processGet(Context &context) -> ProcessResult final;
    };

    namespace json::developerMode

A module-services/service-desktop/endpoints/developerMode/Mode/BaseHelper.cpp => module-services/service-desktop/endpoints/developerMode/Mode/BaseHelper.cpp +51 -0
@@ 0,0 1,51 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BaseHelper.hpp"
#include <Context.hpp>

namespace parserFSM
{

    auto ret() -> BaseHelper::ProcessResult
    {
        return {sent::no, std::nullopt};
    }

    auto BaseHelper::processPut(Context &) -> ProcessResult
    {
        return ret();
    }

    auto BaseHelper::processGet(Context &) -> ProcessResult
    {
        return ret();
    }

    auto BaseHelper::processPost(Context &) -> ProcessResult
    {
        return ret();
    }

    auto BaseHelper::processDelete(Context &) -> ProcessResult
    {
        return ret();
    }

    [[nodiscard]] auto BaseHelper::process(http::Method method, Context &context) -> ProcessResult
    {
        preProcess(method, context);
        switch (method) {
        case http::Method::del:
            return processDelete(context);
        case http::Method::get:
            return processGet(context);
        case http::Method::post:
            return processPost(context);
        case http::Method::put:
            return processPut(context);
        }
        postProcess(method, context);
        return {sent::no, std::nullopt};
    }
} // namespace parserFSM

A module-services/service-desktop/endpoints/developerMode/Mode/BaseHelper.hpp => module-services/service-desktop/endpoints/developerMode/Mode/BaseHelper.hpp +67 -0
@@ 0,0 1,67 @@
// 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 <parser/HttpEnums.hpp>
#include <endpoints/ResponseContext.hpp>

namespace sys
{
    class Service;
} // namespace sys

namespace parserFSM
{
    class Context;
    enum class sent
    {
        /// response was sent from Helper class
        /// we should avoid that
        yes,
        /// response wasn't sent from Helper class
        /// we should send it from endpoint based on processing result
        no,
        /// works on global context
        /// mechanism:
        /// - Send message which is delayed
        /// - send the actual response form ServiceDesktop on `sdesktop::developerMode::DeveloperModeRequest`
        delayed,
    };

    /// base helper class to avoid copies
    class BaseHelper
    {
      public:
        using ProcessResult = std::pair<sent, std::optional<endpoint::ResponseContext>>;

      protected:
        sys::Service *owner = nullptr;
        /// by default - result = not sent
        [[nodiscard]] virtual auto processPut(Context &) -> ProcessResult;
        /// by default - result = not sent
        [[nodiscard]] virtual auto processGet(Context &) -> ProcessResult;
        /// by default - result = not sent
        [[nodiscard]] virtual auto processPost(Context &) -> ProcessResult;
        /// by default - result = not sent
        [[nodiscard]] virtual auto processDelete(Context &) -> ProcessResult;
        /// pre process action foo - in case we want to do something before processing request
        virtual void preProcess(http::Method method, Context &context){};
        /// post processing action - in case we want to do something after processing request
        virtual void postProcess(http::Method method, Context &context){};

      public:
        explicit BaseHelper(sys::Service *p) : owner(p)
        {}

        /// generall processing function
        ///
        /// we should define processing functions, not copy switch cases
        /// as we are super ambiguous how we should really handle responses
        /// here we can either:
        /// return true - to mark that we responded on this request
        /// return fale - and optionally respond that we didn't handle the request
        /// pre and post processing is available on pre/post process method override
        [[nodiscard]] auto process(http::Method method, Context &context) -> ProcessResult;
    };
}; // namespace parserFSM

A module-services/service-desktop/endpoints/developerMode/Mode/UI_Helper.cpp => module-services/service-desktop/endpoints/developerMode/Mode/UI_Helper.cpp +41 -0
@@ 0,0 1,41 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "UI_Helper.hpp"
#include "log/log.hpp"
#include "service-desktop/Constants.hpp"
#include "service-desktop/DeveloperModeMessage.hpp"
#include <variant>
#include <service-appmgr/model/ApplicationManager.hpp>
#include <service-appmgr/service-appmgr/messages/DOMRequest.hpp>

namespace parserFSM
{
    void UI_Helper::preProcess(http::Method method, Context &context)
    {
        LOG_INFO("In UI helper - requesting %d", static_cast<int>(method));
    }

    class UIEvent : public sdesktop::Event
    {
      public:
        UIEvent(Context &ctx)
        {
            context = ctx;
        }
    };

    auto UI_Helper::processGet(Context &context) -> ProcessResult
    {
        const auto &body = context.getBody();
        if (body["getWindow"] == true) {
            auto event = UIEvent(context);
            owner->bus.sendUnicast(
                std::make_shared<app::manager::DOMRequest>(service::name::service_desktop,
                                                           std::make_unique<sdesktop::Event>(std::move(event))),
                app::manager::ApplicationManager::ServiceName);
            return {sent::delayed, std::nullopt};
        }
        return {sent::no, std::nullopt};
    }
}; // namespace parserFSM

A module-services/service-desktop/endpoints/developerMode/Mode/UI_Helper.hpp => module-services/service-desktop/endpoints/developerMode/Mode/UI_Helper.hpp +24 -0
@@ 0,0 1,24 @@
// 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 <endpoints/Context.hpp>
#include <Service/Common.hpp>
#include "BaseHelper.hpp"

namespace parserFSM
{

    class UI_Helper : public BaseHelper
    {

      public:
        explicit UI_Helper(sys::Service *p) : BaseHelper(p)
        {}

        /// returns DOM async
        auto processGet(Context &context) -> ProcessResult final;
        void preProcess(http::Method method, Context &context) final;
    };
} // namespace parserFSM

A module-services/service-desktop/endpoints/developerMode/event/DomRequest.cpp => module-services/service-desktop/endpoints/developerMode/event/DomRequest.cpp +16 -0
@@ 0,0 1,16 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-desktop/endpoints/developerMode/event/DomRequest.hpp>

namespace sdesktop::developerMode
{
    DomRequestEvent::DomRequestEvent(Event &p) : Event(p)
    {}

    void DomRequestEvent::setJson(json11::Json json)
    {
        context.setResponseStatus(parserFSM::http::Code::OK);
        context.setResponseBody(json11::Json::object{{"dom", json}});
    };
} // namespace sdesktop::developerMode

A module-services/service-desktop/endpoints/developerMode/event/DomRequest.hpp => module-services/service-desktop/endpoints/developerMode/event/DomRequest.hpp +16 -0
@@ 0,0 1,16 @@
// 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 <service-desktop/DeveloperModeMessage.hpp>

namespace sdesktop::developerMode
{
    class DomRequestEvent : public sdesktop::Event
    {
      public:
        DomRequestEvent(sdesktop::Event &);
        void setJson(json11::Json json);
    };
} // namespace sdesktop::developerMode

M module-services/service-desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp => module-services/service-desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "DeviceInfoEndpoint.hpp"


@@ 14,6 14,7 @@

#include <cstdint>
#include <string>
#include <vfs.hpp>

using namespace parserFSM;


M module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp => module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 12,6 12,7 @@
#include <iosfwd>
#include <string>
#include <vector>
#include <vfs.hpp>

class ServiceDesktop;
namespace fs = std::filesystem;

R module-services/service-desktop/parser/ParserUtils.cpp => module-services/service-desktop/parser/HttpEnums.cpp +13 -15
@@ 1,22 1,20 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ParserUtils.hpp"
#include "HttpEnums.hpp"

#include <log/log.hpp>

namespace parserFSM
{
using namespace parserFSM;

    bool http::isMethodValid(uint8_t method)
    {
        if (method == static_cast<uint8_t>(http::Method::get) || method == static_cast<uint8_t>(http::Method::post) ||
            method == static_cast<uint8_t>(http::Method::put) || method == static_cast<uint8_t>(http::Method::del)) {
            return true;
        }
        else {
            LOG_ERROR("Invalid method!");
            return false;
        }
auto http::isMethodValid(uint8_t method) -> bool
{
    if (method == static_cast<uint8_t>(http::Method::get) || method == static_cast<uint8_t>(http::Method::post) ||
        method == static_cast<uint8_t>(http::Method::put) || method == static_cast<uint8_t>(http::Method::del)) {
        return true;
    }
    else {
        LOG_ERROR("Invalid method!");
        return false;
    }
} // namespace parserFSM
}

A module-services/service-desktop/parser/HttpEnums.hpp => module-services/service-desktop/parser/HttpEnums.hpp +32 -0
@@ 0,0 1,32 @@
// 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 <cstdint>

namespace parserFSM::http
{
    /*! Enum class for the HTTP status codes.
     */
    enum class Code
    {
        OK                  = 200,
        Accepted            = 202,
        BadRequest          = 400,
        NotAcceptable       = 406,
        InternalServerError = 500
    };

    /*! Enum class for the HTTP methods.
     */
    enum class Method
    {
        get = 1,
        post,
        put,
        del
    };

    [[nodiscard]] auto isMethodValid(uint8_t) -> bool;
}; // namespace parserFSM::http

M module-services/service-desktop/parser/ParserUtils.hpp => module-services/service-desktop/parser/ParserUtils.hpp +2 -28
@@ 2,12 2,12 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include <stdint.h>         // for uint8_t
#include <log/log.hpp>      // for LOG_ERROR
#include <bits/exception.h> // for exception
#include <stddef.h>         // for size_t
#include <cstddef>          // for size_t
#include <string>           // for string, allocator, basic_string, stol
#include <vector>
#include <parser/HttpEnums.hpp>

namespace parserFSM
{


@@ 76,32 76,6 @@ namespace parserFSM
        }
    } // namespace message

    namespace http
    {
        /*! Enum class for the HTTP status codes.
         */
        enum class Code
        {
            OK                  = 200,
            Accepted            = 202,
            BadRequest          = 400,
            NotAcceptable       = 406,
            InternalServerError = 500
        };

        /*! Enum class for the HTTP methods.
         */
        enum class Method
        {
            get = 1,
            post,
            put,
            del
        };

        bool isMethodValid(uint8_t);
    }; // namespace http

    namespace json
    {
        inline constexpr auto batteryLevel     = "batteryLevel";

A module-services/service-desktop/service-desktop/DesktopEvent.hpp => module-services/service-desktop/service-desktop/DesktopEvent.hpp +16 -0
@@ 0,0 1,16 @@
#pragma once

#include <service-desktop/endpoints/Context.hpp>

namespace sdesktop
{
    class Event
    {
      protected:
        parserFSM::Context context;

      public:
        void send();
        virtual ~Event() = default;
    };
} // namespace sdesktop

M module-services/service-desktop/service-desktop/DesktopMessages.hpp => module-services/service-desktop/service-desktop/DesktopMessages.hpp +3 -24
@@ 3,13 3,14 @@

#pragma once

#include <endpoints/update/UpdateMuditaOS.hpp>
#include <endpoints/developerMode/DeveloperModeEndpoint.hpp>
#include <endpoints/bluetooth/BluetoothEndpoint.hpp>
#include <endpoints/update/UpdateMuditaOS.hpp>

#include <Service/Message.hpp>
#include <MessageType.hpp>

#include <service-desktop/DeveloperModeMessage.hpp>
#include <service-desktop/DesktopEvent.hpp>

namespace sdesktop
{


@@ 66,21 67,9 @@ namespace sdesktop
        ~FactoryMessage() override = default;
    };

    class Event
    {
      protected:
        parserFSM::Context context;

      public:
        void send();
        virtual ~Event() = default;
    };

    namespace developerMode
    {



        class ATResponseEvent : public Event
        {
          public:


@@ 111,16 100,6 @@ namespace sdesktop
            ScreenlockCheckEvent() = default;
            explicit ScreenlockCheckEvent(bool isLocked);
        };


        class DeveloperModeRequest : public sys::DataMessage
        {
          public:
            std::unique_ptr<Event> event;
            DeveloperModeRequest(std::unique_ptr<Event> event);
            DeveloperModeRequest();
            ~DeveloperModeRequest() override = default;
        };
    } // namespace developerMode

    namespace bluetooth

A module-services/service-desktop/service-desktop/DeveloperModeMessage.hpp => module-services/service-desktop/service-desktop/DeveloperModeMessage.hpp +19 -0
@@ 0,0 1,19 @@
// 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 <Service/Message.hpp>
#include <service-desktop/DesktopEvent.hpp>

namespace sdesktop::developerMode
{
    class DeveloperModeRequest : public sys::DataMessage
    {
      public:
        std::unique_ptr<sdesktop::Event> event;
        explicit DeveloperModeRequest(std::unique_ptr<sdesktop::Event> event);
        DeveloperModeRequest();
        ~DeveloperModeRequest() override = default;
    };
} // namespace sdesktop::developerMode

M module-sys/Service/Common.hpp => module-sys/Service/Common.hpp +2 -14
@@ 1,9 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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 "FreeRTOSConfig.h"
#include "SystemReturnCodes.hpp"

namespace sys
{


@@ 40,19 41,6 @@ namespace sys
        SuspendToRAM,
        SuspendToNVM
    };

    enum class ReturnCodes
    {
        Success,
        Failure,
        Timeout,
        ServiceDoesntExist,
        // This is used in application's template in base class messages handler. The meaning is that
        // message that was processed by base class implementation of the DataReceivedHandler was not processed
        // and it should be handled by the class next in hierarchy.
        Unresolved
    };

} // namespace sys

inline const char *c_str(sys::ReturnCodes code)

M module-sys/Service/Message.hpp => module-sys/Service/Message.hpp +2 -6
@@ 1,10 1,11 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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 "Common.hpp"
#include "MessageType.hpp"
#include "MessageForward.hpp"

#include <cstdint>
#include <memory>


@@ 12,11 13,6 @@

namespace sys
{
    class Service;
    class Message;
    using MessagePointer = std::shared_ptr<Message>;
    using MessageNone    = std::nullptr_t;
    using SendResult     = std::pair<ReturnCodes, std::shared_ptr<Message>>;
    SendResult CreateSendResult(ReturnCodes retCode, MessagePointer msg);

    class Message

A module-sys/Service/MessageForward.hpp => module-sys/Service/MessageForward.hpp +19 -0
@@ 0,0 1,19 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

// Please do not pollute here
// This is straight forward declaration header for includes purposes

#include <memory>
#include "SystemReturnCodes.hpp"

namespace sys
{
    class Service;
    class Message;
    using MessagePointer = std::shared_ptr<Message>;
    using MessageNone    = std::nullptr_t;
    using SendResult     = std::pair<ReturnCodes, std::shared_ptr<Message>>;
} // namespace sys

A module-sys/Service/SystemReturnCodes.hpp => module-sys/Service/SystemReturnCodes.hpp +19 -0
@@ 0,0 1,19 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

namespace sys
{
    enum class ReturnCodes
    {
        Success,
        Failure,
        Timeout,
        ServiceDoesntExist,
        // This is used in application's template in base class messages handler. The meaning is that
        // message that was processed by base class implementation of the DataReceivedHandler was not processed
        // and it should be handled by the class next in hierarchy.
        Unresolved
    };
}

M module-sys/Service/Timer.cpp => module-sys/Service/Timer.cpp +1 -1
@@ 12,7 12,7 @@
#include <cstdint>

#if DEBUG_TIMER == 1
#define log(...) LOG_DEBUG(__VA_ARGS__)
#define log_debug(...) LOG_DEBUG(__VA_ARGS__)
#else
#define log_debug(...)
#endif

M source/MessageType.hpp => source/MessageType.hpp +1 -0
@@ 124,6 124,7 @@ enum class MessageType
    AudioMessage,

    // application manager
    APMGeneric,
    APMAction,          ///< Used to send an action request to application manager.
    APMCheckAppRunning, ///< check if application is running in application manager
    APMSwitch,          ///< request to switch to given application, optionally also to specified window

A test/pytest/test_dom_dump.py => test/pytest/test_dom_dump.py +9 -0
@@ 0,0 1,9 @@
from harness import log


def test_get_dom(harness):
    body = {"ui": True, "getWindow": True}
    result = harness.endpoint_request("developerMode", "get", body)
    log.info("data {}".format(result))
    assert result['body']
    assert 'Window' in result['body']['dom']