~aleteoryx/muditaos

9645fbc278597e0827e948b9c81c24a17fe72269 — Przemyslaw Brudny 5 years ago 8370b97
[EDG-4717] Add screen for brightness control

Window for manual and automatic screen brightness control.
34 files changed, 775 insertions(+), 302 deletions(-)

M module-apps/Application.cpp
M module-apps/application-settings-new/ApplicationSettings.cpp
M module-apps/application-settings-new/ApplicationSettings.hpp
M module-apps/application-settings-new/CMakeLists.txt
A module-apps/application-settings-new/widgets/OptionSetting.hpp
A module-apps/application-settings-new/widgets/SpinBox.cpp
A module-apps/application-settings-new/widgets/SpinBox.hpp
A module-apps/application-settings-new/widgets/SpinBoxOptionSetting.cpp
M module-apps/application-settings-new/windows/BaseSettingsWindow.cpp
M module-apps/application-settings-new/windows/BaseSettingsWindow.hpp
M module-apps/application-settings-new/windows/DisplayLightWindow.cpp
M module-apps/application-settings-new/windows/DisplayLightWindow.hpp
M module-apps/application-settings/windows/SimSelectWindow.hpp
M module-apps/options/type/OptionSetting.hpp
M module-apps/widgets/BarGraph.cpp
M module-apps/widgets/BarGraph.hpp
M module-apps/windows/OptionWindow.cpp
M module-apps/windows/OptionWindow.hpp
M module-gui/gui/widgets/ProgressBar.cpp
M module-gui/gui/widgets/ProgressBar.hpp
M module-services/service-db/agents/settings/SystemSettings.hpp
M module-services/service-evtmgr/CMakeLists.txt
M module-services/service-evtmgr/EventManager.cpp
M module-services/service-evtmgr/WorkerEvent.cpp
M module-services/service-evtmgr/doc/screen_light_control.md
M module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp
M module-services/service-evtmgr/screen-light-control/ControlFunctions.hpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp
M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp
M module-services/service-evtmgr/service-evtmgr/EventManager.hpp
A module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp
M module-services/service-evtmgr/tests/test-ScreenLightControlFunctions.cpp
M source/MessageType.hpp
M module-apps/Application.cpp => module-apps/Application.cpp +21 -22
@@ 2,31 2,31 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Application.hpp"
#include "Common.hpp"                                    // for RefreshModes
#include "GuiTimer.hpp"                                  // for GuiTimer
#include "Item.hpp"                                      // for Item
#include "MessageType.hpp"                               // for MessageType
#include "Service/Timer.hpp"                             // for Timer
#include "Timer.hpp"                                     // for Timer
#include "Translator.hpp"                                // for KeyInputSim...
#include "common_data/EventStore.hpp"                    // for Battery
#include "common_data/RawKey.hpp"                        // for RawKey, key...
#include "gui/input/InputEvent.hpp"                      // for InputEvent
#include "log/debug.hpp"                                 // for DEBUG_APPLI...
#include "log/log.hpp"                                   // for LOG_INFO
#include "messages/AppMessage.hpp"                       // for AppSwitchMe...
#include "service-appmgr/Controller.hpp"                 // for Controller
#include "Common.hpp"                    // for RefreshModes
#include "GuiTimer.hpp"                  // for GuiTimer
#include "Item.hpp"                      // for Item
#include "MessageType.hpp"               // for MessageType
#include "Service/Timer.hpp"             // for Timer
#include "Timer.hpp"                     // for Timer
#include "Translator.hpp"                // for KeyInputSim...
#include "common_data/EventStore.hpp"    // for Battery
#include "common_data/RawKey.hpp"        // for RawKey, key...
#include "gui/input/InputEvent.hpp"      // for InputEvent
#include "log/debug.hpp"                 // for DEBUG_APPLI...
#include "log/log.hpp"                   // for LOG_INFO
#include "messages/AppMessage.hpp"       // for AppSwitchMe...
#include "service-appmgr/Controller.hpp" // for Controller
#include <service-cellular/CellularMessage.hpp>
#include <service-evtmgr/BatteryMessages.hpp>
#include <service-evtmgr/Constants.hpp>
#include <service-evtmgr/EVMessages.hpp>
#include "service-gui/messages/DrawMessage.hpp"          // for DrawMessage
#include "task.h"                                        // for xTaskGetTic...
#include "windows/AppWindow.hpp"                         // for AppWindow
#include <Text.hpp>                                      // for Text
#include <algorithm>                                     // for find
#include <iterator>                                      // for distance, next
#include <type_traits>                                   // for add_const<>...
#include "service-gui/messages/DrawMessage.hpp" // for DrawMessage
#include "task.h"                               // for xTaskGetTic...
#include "windows/AppWindow.hpp"                // for AppWindow
#include <Text.hpp>                             // for Text
#include <algorithm>                            // for find
#include <iterator>                             // for distance, next
#include <type_traits>                          // for add_const<>...
#include <WindowsFactory.hpp>
#include <service-gui/Common.hpp>
#include <module-utils/Utils.hpp>


@@ 104,7 104,6 @@ namespace app
        state = st;
    }


    void Application::longPressTimerCallback()
    {
        // TODO if(check widget type long press trigger)

M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +56 -4
@@ 30,16 30,21 @@
#include "Dialog.hpp"

#include <service-evtmgr/EventManagerServiceAPI.hpp>
#include <service-bluetooth/BluetoothMessage.hpp>
#include <service-cellular/CellularServiceAPI.hpp>
#include <service-db/Settings.hpp>
#include <module-services/service-bluetooth/service-bluetooth/messages/Status.hpp>
#include <service-bluetooth/BluetoothMessage.hpp>
#include <service-bluetooth/service-bluetooth/messages/Status.hpp>
#include <service-bluetooth/messages/BondedDevices.hpp>
#include <service-bluetooth/messages/DeviceName.hpp>
#include <application-settings-new/data/BondedDevicesData.hpp>
#include <application-settings-new/data/PhoneNameData.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
#include <application-settings-new/data/PhoneNameData.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <service-db/Settings.hpp>

#include <i18n/i18n.hpp>
#include <module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp>
#include <module-services/service-evtmgr/service-evtmgr/Constants.hpp>

namespace app
{


@@ 188,7 193,7 @@ namespace app
            return std::make_unique<gui::FontSizeWindow>(app);
        });
        windowsFactory.attach(gui::window::name::display_light, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DisplayLightWindow>(app);
            return std::make_unique<gui::DisplayLightWindow>(app, static_cast<ApplicationSettingsNew *>(app));
        });
        windowsFactory.attach(gui::window::name::apps_and_tools, [](Application *app, const std::string &name) {
            return std::make_unique<gui::AppsAndToolsWindow>(app);


@@ 292,4 297,51 @@ namespace app
        lockPassHash = value;
        settings->setValue(::settings::SystemProperties::lockPassHash, std::to_string(value));
    }

    auto ApplicationSettingsNew::getCurrentValues() -> settingsInterface::ScreenLightSettings::Values
    {
        constexpr int timeout = pdMS_TO_TICKS(1500);

        auto response = sys::Bus::SendUnicast(
            std::make_shared<sevm::ScreenLightControlRequestParameters>(), service::name::evt_manager, this, timeout);

        if (response.first == sys::ReturnCodes::Success) {
            auto msgState = dynamic_cast<sevm::ScreenLightControlParametersResponse *>(response.second.get());
            if (msgState == nullptr) {
                return {};
            }

            return {msgState->lightOn, msgState->mode, msgState->parameters};
        }

        return {};
    }

    void ApplicationSettingsNew::setBrightness(bsp::eink_frontlight::BrightnessPercentage value)
    {
        screen_light_control::Parameters parameters{value};
        sys::Bus::SendUnicast(std::make_shared<sevm::ScreenLightControlMessage>(
                                  screen_light_control::Action::setManualModeBrightness, parameters),
                              service::name::evt_manager,
                              this);
    }

    void ApplicationSettingsNew::setMode(bool isAutoLightSwitchOn)
    {
        sys::Bus::SendUnicast(std::make_shared<sevm::ScreenLightControlMessage>(
                                  isAutoLightSwitchOn ? screen_light_control::Action::enableAutomaticMode
                                                      : screen_light_control::Action::disableAutomaticMode),
                              service::name::evt_manager,
                              this);
    }

    void ApplicationSettingsNew::setStatus(bool isDisplayLightSwitchOn)
    {
        sys::Bus::SendUnicast(
            std::make_shared<sevm::ScreenLightControlMessage>(
                isDisplayLightSwitchOn ? screen_light_control::Action::turnOn : screen_light_control::Action::turnOff),
            service::name::evt_manager,
            this);
    }

} /* namespace app */

M module-apps/application-settings-new/ApplicationSettings.hpp => module-apps/application-settings-new/ApplicationSettings.hpp +24 -1
@@ 6,6 6,7 @@
#include "Application.hpp"

#include <bsp/common.hpp>
#include <module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp>

namespace gui::window::name
{


@@ 69,11 70,28 @@ namespace app
            virtual void setVoLTEOn(bool value)                        = 0;
            [[nodiscard]] virtual bool getVoLTEOn() const noexcept     = 0;
        };
        class ScreenLightSettings
        {
          public:
            struct Values
            {
                bool lightOn;
                screen_light_control::ScreenLightMode mode;
                screen_light_control::Parameters parameters;
            };

            virtual ~ScreenLightSettings()                      = default;
            virtual auto getCurrentValues() -> Values           = 0;
            virtual void setBrightness(float brigtnessValue)    = 0;
            virtual void setMode(bool isAutoLightSwitchOn)      = 0;
            virtual void setStatus(bool isDisplayLightSwitchOn) = 0;
        };
    }; // namespace settingsInterface

    class ApplicationSettingsNew : public app::Application,
                                   public settingsInterface::SimParams,
                                   public settingsInterface::OperatorsSettings
                                   public settingsInterface::OperatorsSettings,
                                   public settingsInterface::ScreenLightSettings
    {
      public:
        ApplicationSettingsNew(std::string name                    = name_settings_new,


@@ 106,6 124,11 @@ namespace app
        }
        void setLockPassHash(unsigned int value);

        ScreenLightSettings::Values getCurrentValues() override;
        void setBrightness(float brigtnessValue) override;
        void setMode(bool isAutoLightSwitchOn) override;
        void setStatus(bool isDisplayLightSwitchOn) override;

      private:
        Store::GSM::SIM selectedSim   = Store::GSM::get()->selected;
        std::string selectedSimNumber = {};

M module-apps/application-settings-new/CMakeLists.txt => module-apps/application-settings-new/CMakeLists.txt +2 -1
@@ 41,6 41,8 @@ target_sources( ${PROJECT_NAME}
        windows/QuotesAddWindow.cpp
        windows/SecurityMainWindow.cpp
        windows/ChangePasscodeWindow.cpp
        widgets/SpinBox.cpp
        widgets/SpinBoxOptionSetting.cpp

    PUBLIC
        ApplicationSettings.hpp


@@ 66,5 68,4 @@ add_dependencies(${PROJECT_NAME} version)
target_link_libraries(${PROJECT_NAME}
    PUBLIC
        service-bluetooth
        service-evtmgr
)

A module-apps/application-settings-new/widgets/OptionSetting.hpp => module-apps/application-settings-new/widgets/OptionSetting.hpp +30 -0
@@ 0,0 1,30 @@
// 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 "SpinBox.hpp"
#include "OptionWindow.hpp"
#include "Application.hpp"

#include <module-apps/options/type/OptionSetting.hpp>

namespace gui
{
    class SpinBoxOptionSettings : public option::OptionSettings
    {
      public:
        SpinBoxOptionSettings(UTF8 text,
                              uint8_t value,
                              uint8_t maxValue,
                              std::function<bool(uint8_t)> updateCallback,
                              std::function<bool(Item &)> focusChangedCallback = nullptr);

        [[nodiscard]] auto build() const -> ListItem * override;

      private:
        std::function<bool(uint8_t)> updateCallback;
        std::uint8_t maxValue;
        std::uint8_t value;
    };
} // namespace gui

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

#include "SpinBox.hpp"
#include "widgets/BarGraph.hpp"

#include <InputEvent.hpp>
#include <Label.hpp>
#include <Image.hpp>
#include <utf8/UTF8.hpp>
#include <utility>

namespace gui
{
    SpinBox::SpinBox(
        Item *parent, const std::string &title, UpdateCallback updateCallback, uint8_t maxValue, uint8_t startValue)
        : HBox(parent, style::window::default_left_margin), updateBarCallback(std::move(updateCallback))
    {
        setMinimumSize(style::window::default_body_width, style::window::label::big_h);
        setPenWidth(style::window::default_border_no_focus_w);
        setPenFocusWidth(style::window::default_border_focus_w);
        setEdges(gui::RectangleEdge::Top | gui::RectangleEdge::Bottom);

        titleLabel = addTitle(this, title);
        leftArrow  = addArrow(this, "arrow_left", Alignment::Horizontal::Left, false);
        rightArrow = addArrow(this, "arrow_right", Alignment::Horizontal::Right, false);
        bar        = addBarGraph(this, maxValue, startValue);

        focusChangedCallback = [this](Item &item) {
            leftArrow->setVisible(item.focus);
            rightArrow->setVisible(item.focus);
            resizeItems();
            return true;
        };

        inputCallback = [this](gui::Item &item, const gui::InputEvent &event) {
            if (!event.isShortPress()) {
                return false;
            }

            int update = 0;
            if (event.is(KeyCode::KEY_LEFT)) {
                update = -1;
            }
            else if (event.is(KeyCode::KEY_RIGHT)) {
                update = 1;
            }

            if (update != 0 && bar->update(update)) {
                updateBarCallback(bar->getValue());
                return true;
            }

            return false;
        };
    }

    Image *SpinBox::addArrow(Item *parent, const std::string &arrowName, Alignment::Horizontal aligment, bool visible)
    {
        auto arrow = new Image(parent, 0, 0, 0, 0);
        arrow->setAlignment(Alignment(aligment, Alignment::Vertical::Center));
        arrow->setMargins(Margins(0, 0, style::margins::big, 0));
        arrow->set(arrowName);
        arrow->setVisible(visible);

        return arrow;
    }

    Label *SpinBox::addTitle(Item *parent, const std::string &text)
    {
        auto label = new Label(parent);
        label->setMinimumHeight(style::window::label::default_h);
        label->setMaximumWidth(style::window::default_body_width);

        label->setEdges(RectangleEdge::None);
        label->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
        label->setFont(style::window::font::big);
        label->setText(text);
        label->activeItem = false;

        return label;
    }

    HBarGraph *SpinBox::addBarGraph(Item *parent, uint8_t maxValue, uint8_t startValue)
    {
        auto barGraph = new HBarGraph(parent, 0, 0, maxValue);
        barGraph->setAlignment(Alignment(gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Center));
        barGraph->setValue(startValue);
        barGraph->activeItem = false;

        return barGraph;
    }
} // namespace gui

A module-apps/application-settings-new/widgets/SpinBox.hpp => module-apps/application-settings-new/widgets/SpinBox.hpp +43 -0
@@ 0,0 1,43 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

// 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 "widgets/BarGraph.hpp"

namespace style::settings::brightness
{
    inline constexpr auto max_value = 6;
};

class UTF8;

namespace gui
{
    class Image;
    class SpinBox : public HBox
    {
      public:
        using UpdateCallback = std::function<bool(uint8_t)>;

        SpinBox(Item *parent,
                const std::string &title,
                UpdateCallback updateCallback,
                std::uint8_t maxValue   = style::settings::brightness::max_value,
                std::uint8_t startValue = 0);

      private:
        auto addArrow(Item *parent, const std::string &arrowName, Alignment::Horizontal aligment, bool visible)
            -> Image *;
        auto addBarGraph(Item *parent, uint8_t maxValue, uint8_t startValue) -> HBarGraph *;
        auto addTitle(Item *parent, const std::string &text) -> Label *;

        HBarGraph *bar;
        Label *titleLabel;
        Image *leftArrow;
        Image *rightArrow;
        UpdateCallback updateBarCallback;
    };
} // namespace gui

A module-apps/application-settings-new/widgets/SpinBoxOptionSetting.cpp => module-apps/application-settings-new/widgets/SpinBoxOptionSetting.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 "OptionSetting.hpp"

#include <utility>
#include "SpinBox.hpp"

namespace gui
{
    SpinBoxOptionSettings::SpinBoxOptionSettings(UTF8 text,
                                                 std::uint8_t value,
                                                 std::uint8_t maxValue,
                                                 std::function<bool(uint8_t)> updateCallback,
                                                 std::function<bool(Item &)> focusChangedCallback)
        : option::OptionSettings(text, nullptr, focusChangedCallback, nullptr),
          updateCallback(std::move(updateCallback)), maxValue(maxValue), value(value)
    {}

    auto SpinBoxOptionSettings::build() const -> ListItem *
    {
        auto spinBox = new SpinBox(nullptr, text, updateCallback, maxValue, value);

        auto optionItem = new gui::ListItem();
        optionItem->setMinimumSize(style::window::default_body_width, style::window::label::big_h);
        optionItem->inputCallback        = spinBox->inputCallback;
        optionItem->focusChangedCallback = [spinBox, this](Item &item) {
            spinBox->focusChangedCallback(item);
            return focusChangedCallback(item);
        };
        optionItem->dimensionChangedCallback = [spinBox](gui::Item &, const BoundingBox &newDim) -> bool {
            spinBox->setPosition(0, 0);
            spinBox->setSize(newDim.w, newDim.h);
            return true;
        };

        optionItem->addWidget(spinBox);

        return optionItem;
    }
} // namespace gui

M module-apps/application-settings-new/windows/BaseSettingsWindow.cpp => module-apps/application-settings-new/windows/BaseSettingsWindow.cpp +0 -1
@@ 2,7 2,6 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BaseSettingsWindow.hpp"

#include <i18n/i18n.hpp>

namespace gui

M module-apps/application-settings-new/windows/BaseSettingsWindow.hpp => module-apps/application-settings-new/windows/BaseSettingsWindow.hpp +1 -0
@@ 6,6 6,7 @@
#include "Application.hpp"
#include "windows/AppWindow.hpp"
#include "windows/OptionWindow.hpp"
#include <service-db/Settings.hpp>

namespace gui
{

M module-apps/application-settings-new/windows/DisplayLightWindow.cpp => module-apps/application-settings-new/windows/DisplayLightWindow.cpp +51 -14
@@ 2,23 2,38 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "DisplayLightWindow.hpp"

#include "application-settings-new/widgets/OptionSetting.hpp"
#include "OptionSetting.hpp"
#include "application-settings-new/ApplicationSettings.hpp"
#include "OptionSetting.hpp"

#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <i18n/i18n.hpp>
#include <Service/Bus.hpp>

namespace gui
{
    DisplayLightWindow::DisplayLightWindow(app::Application *app) : BaseSettingsWindow(app, window::name::display_light)

    DisplayLightWindow::DisplayLightWindow(app::Application *app, app::settingsInterface::ScreenLightSettings *settings)
        : BaseSettingsWindow(app, window::name::display_light), screenLightSettings(settings)
    {
        auto values = screenLightSettings->getCurrentValues();

        isDisplayLightSwitchOn = values.lightOn;
        isAutoLightSwitchOn    = values.mode;
        brightnessValue        = values.parameters.manualModeBrightness;

        setTitle(utils::localize.get("app_settings_display_display_light"));
    }

    void DisplayLightWindow::switchHandler(bool &onOffSwitch)
    {
        onOffSwitch = !onOffSwitch;

        rebuildOptionList();

        screenLightSettings->setStatus(isDisplayLightSwitchOn);
        screenLightSettings->setMode(isAutoLightSwitchOn);
    }

    auto DisplayLightWindow::buildOptionsList() -> std::list<gui::Option>


@@ 49,21 64,43 @@ namespace gui
        }

        if (isDisplayLightSwitchOn && !isAutoLightSwitchOn) {
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                utils::translateI18("app_settings_display_light_brightness"),
                [=](gui::Item &item) { return true; },
                [=](gui::Item &item) {
                    if (item.focus) {
                        this->setBottomBarText(utils::translateI18(style::strings::common::set),
                                               BottomBar::Side::CENTER);
                    }
                    return true;
                },
                this,
                gui::option::SettingRightItem::ArrowWhite));
            addBrightnessOption(optionsList);
        }

        return optionsList;
    }

    auto DisplayLightWindow::createBrightnessOption(int brightnessStep) -> std::unique_ptr<SpinBoxOptionSettings>
    {
        auto setBrightness = [this, brightnessStep](uint8_t value) {
            screenLightSettings->setBrightness(value * brightnessStep);
            return true;
        };

        auto setBottomBarOnSpinnerFocus = [&](gui::Item &item) {
            if (item.focus) {
                setBottomBarText(utils::translateI18(style::strings::common::set), BottomBar::Side::CENTER);
            }
            return true;
        };

        auto spinner = std::make_unique<gui::SpinBoxOptionSettings>(
            utils::translateI18("app_settings_display_light_brightness") + " " + std::to_string(brightnessStep),
            brightnessValue * brightnessStep,
            std::ceil(screen_light_control::Parameters::MAX_BRIGHTNESS / brightnessStep),
            setBrightness,
            setBottomBarOnSpinnerFocus);

        return spinner;
    }

    void DisplayLightWindow::addBrightnessOption(std::list<gui::Option> &options)
    {
        /*
         * We are adding 4 brightness widgets to easily check what is the best step for setting screen brightness.
         */
        for (auto step : {10, 15, 20, 25}) {
            options.emplace_back(createBrightnessOption(step));
        }
    }
} // namespace gui

M module-apps/application-settings-new/windows/DisplayLightWindow.hpp => module-apps/application-settings-new/windows/DisplayLightWindow.hpp +13 -5
@@ 3,21 3,29 @@

#pragma once

#include <module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <module-apps/application-settings-new/widgets/SpinBox.hpp>
#include <module-apps/application-settings-new/ApplicationSettings.hpp>
#include <module-apps/application-settings-new/widgets/OptionSetting.hpp>
#include "BaseSettingsWindow.hpp"

namespace gui
{

    class DisplayLightWindow : public BaseSettingsWindow
    {
      public:
        DisplayLightWindow(app::Application *app);
        DisplayLightWindow(app::Application *app, app::settingsInterface::ScreenLightSettings *screenLightSettings);

      private:
        void switchHandler(bool &onOffSwitch);
        auto buildOptionsList() -> std::list<Option> override;
        void switchHandler(bool &onOffSwitch);

        void addBrightnessOption(std::list<Option> &);
        auto createBrightnessOption(int step) -> std::unique_ptr<SpinBoxOptionSettings>;

        bool isDisplayLightSwitchOn = false;
        bool isAutoLightSwitchOn    = false;
        bool isDisplayLightSwitchOn                                      = false;
        bool isAutoLightSwitchOn                                         = false;
        std::uint8_t brightnessValue                                     = 0;
        app::settingsInterface::ScreenLightSettings *screenLightSettings = nullptr;
    };
} // namespace gui

M module-apps/application-settings/windows/SimSelectWindow.hpp => module-apps/application-settings/windows/SimSelectWindow.hpp +1 -1
@@ 10,4 10,4 @@ namespace app
    class SimSetter;
} // namespace app

std::list<gui::Option> simSelectWindow(app::Application *app, app::SimSetter *setter);
std::list<gui::Option> simSelectWindow(app::Application *app, app::SimSetter *setter);
\ No newline at end of file

M module-apps/options/type/OptionSetting.hpp => module-apps/options/type/OptionSetting.hpp +1 -1
@@ 10,7 10,7 @@ namespace gui::option
{
    class OptionSettings : public option::Base
    {
      private:
      protected:
        UTF8 text;
        std::function<bool(Item &)> activatedCallback    = nullptr;
        std::function<bool(Item &)> focusChangedCallback = nullptr;

M module-apps/widgets/BarGraph.cpp => module-apps/widgets/BarGraph.cpp +59 -100
@@ 18,104 18,111 @@ namespace gui
        setValue(absoluteValue);
    }

    Rect *BarGraph::createRectangle(uint32_t width, uint32_t height)
    auto BarGraph::createRectangle(uint32_t width, uint32_t height) const -> Rect *
    {
        auto rectangle = new Rect(nullptr, 0, 0, width, height);
        rectangle->setFillColor(ColorFullBlack);
        rectangle->setBorderColor(ColorFullBlack);
        rectangle->setFilled(true);
        rectangle->setFilled(false);
        rectangle->setRadius(style::bargraph::radius);
        rectangle->setPenWidth(style::window::default_border_focus_w);
        return rectangle;
    }

    Rect *BarGraph::createSpace(uint32_t width, uint32_t height)
    auto BarGraph::createSpace(uint32_t width, uint32_t height) const -> Rect *
    {
        auto space = new Rect(nullptr, 0, 0, width, height);
        space->setEdges(RectangleEdge::None);
        return space;
    }

    VBarGraph::VBarGraph(Item *parent, Position x, Position y, uint32_t numberOfRectangles)
        : VBox(parent, x, y, style::bargraph::rect_axis_length_lrg, rectAxisLenghtFrom(numberOfRectangles))
    auto BarGraph::incrementWith(uint32_t levels) -> bool
    {
        setRadius(style::bargraph::radius);
        setEdges(RectangleEdge::None);
        setMaximum(numberOfRectangles);
        std::reverse(std::begin(rectangles), std::end(rectangles));
        if ((currentLevel + levels) <= numberOfRectangles) {
            for (uint32_t i = 0; i < levels; ++i) {
                rectangles[currentLevel]->setFillColor(ColorFullBlack);
                rectangles[currentLevel]->setBorderColor(ColorFullBlack);
                ++currentLevel;
            }
            return true;
        }
        else {
            LOG_ERROR("bargraph incremented out of size");
            return false;
        }
    }

    void VBarGraph::setMaximum(unsigned int value)
    auto BarGraph::decrementWith(uint32_t levels) -> bool
    {
        numberOfRectangles = value;
        setSize(rectAxisLenghtFrom(numberOfRectangles), Axis::Y);
        if (currentLevel > numberOfRectangles) {
            currentLevel = numberOfRectangles;
        }
        if (!rectangles.empty()) {
            erase();
            rectangles.clear();
        if (currentLevel >= levels) {
            for (uint32_t i = levels; i > 0; --i) {
                --currentLevel;
                rectangles[currentLevel]->setFillColor(ColorFullWhite);
                rectangles[currentLevel]->setBorderColor(ColorFullBlack);
            }
            return true;
        }
        for (uint32_t i = 0; i < numberOfRectangles; ++i) {
            auto rectangle =
                createRectangle(style::bargraph::rect_axis_length_lrg, style::bargraph::rect_axis_length_sml);
            addWidget(rectangle);
            rectangles.push_back(rectangle);
            addWidget(createSpace(style::bargraph::rect_axis_length_lrg, style::bargraph::spacing));
        else {
            LOG_ERROR("bargraph incremented out of size");
            return false;
        }
    }

    void VBarGraph::update(int value)
    auto BarGraph::update(int value) -> bool
    {
        if (value > 0) {
            incrementWith(value);
            return incrementWith(value);
        }
        else if (value < 0) {
            decrementWith((-value));
            return decrementWith((-value));
        }

        return false;
    }

    void VBarGraph::setValue(unsigned int value)
    bool BarGraph::setValue(unsigned int value)
    {
        if (const auto levels = static_cast<int>(value) - static_cast<int>(currentLevel); levels > 0) {
            incrementWith(levels);
            return incrementWith(levels);
        }
        else if (levels < 0) {
            decrementWith(-levels);
            return decrementWith(-levels);
        }
        return false;
    }

    void VBarGraph::incrementWith(uint32_t levels)
    VBarGraph::VBarGraph(Item *parent, Position x, Position y, uint32_t numberOfRectangles)
        : VBox(parent, x, y, style::bargraph::rect_axis_length_lrg, rectAxisLenghtFrom(numberOfRectangles))
    {
        if ((currentLevel + levels) <= numberOfRectangles) {
            for (uint32_t i = 0; i < levels; ++i) {
                rectangles[currentLevel]->setFillColor(ColorFullBlack);
                rectangles[currentLevel]->setBorderColor(ColorFullBlack);
                ++currentLevel;
            }
        }
        else {
            LOG_ERROR("bargraph incremented out of size");
        }
        setRadius(style::bargraph::radius);
        setEdges(RectangleEdge::None);
        setMaximum(numberOfRectangles);
        std::reverse(std::begin(rectangles), std::end(rectangles));
    }

    void VBarGraph::decrementWith(uint32_t levels)
    void VBarGraph::setMaximum(unsigned int value)
    {
        if (currentLevel >= levels) {
            for (uint32_t i = levels; i > 0; --i) {
                --currentLevel;
                rectangles[currentLevel]->setFillColor(ColorTray);
                rectangles[currentLevel]->setBorderColor(ColorTray);
            }
        numberOfRectangles = value;
        setSize(rectAxisLenghtFrom(numberOfRectangles), Axis::Y);
        if (currentLevel > numberOfRectangles) {
            currentLevel = numberOfRectangles;
        }
        else {
            LOG_ERROR("bargraph incremented out of size");
        if (!rectangles.empty()) {
            erase();
            rectangles.clear();
        }
        for (uint32_t i = 0; i < numberOfRectangles; ++i) {
            auto rectangle =
                createRectangle(style::bargraph::rect_axis_length_lrg, style::bargraph::rect_axis_length_sml);
            addWidget(rectangle);
            rectangles.push_back(rectangle);
            addWidget(createSpace(style::bargraph::rect_axis_length_lrg, style::bargraph::spacing));
        }
    }

    HBarGraph::HBarGraph(Item *parent, Position x, Position y, uint32_t numberOfRectangles)
        : HBox(parent, x, y, rectAxisLenghtFrom(numberOfRectangles), style::bargraph::rect_axis_length_lrg)
    HBarGraph::HBarGraph(Item *parent, Position x, Position y, uint32_t numberOfRectangles) : HBox(parent)
    {
        setMinimumSize(rectAxisLenghtFrom(numberOfRectangles), style::bargraph::rect_axis_length_lrg);
        setRadius(style::bargraph::radius);
        setEdges(RectangleEdge::None);
        setMaximum(numberOfRectangles);


@@ 141,52 148,4 @@ namespace gui
        }
    }

    void HBarGraph::update(int value)
    {
        if (value > 0) {
            incrementWith(value);
        }
        else if (value < 0) {
            decrementWith(-value);
        }
    }

    void HBarGraph::setValue(unsigned int value)
    {
        if (const auto levels = static_cast<int>(value) - static_cast<int>(currentLevel); levels > 0) {
            incrementWith(levels);
        }
        else if (levels < 0) {
            decrementWith(levels * -1);
        }
    }

    void HBarGraph::incrementWith(uint32_t levels)
    {
        if ((currentLevel + levels) <= numberOfRectangles) {
            for (uint32_t i = 0; i < levels; ++i) {
                rectangles[currentLevel]->setFillColor(ColorFullBlack);
                rectangles[currentLevel]->setBorderColor(ColorFullBlack);
                ++currentLevel;
            }
        }
        else {
            LOG_ERROR("bargraph incremented out of size");
        }
    }

    void HBarGraph::decrementWith(uint32_t levels)
    {
        if (currentLevel >= levels) {
            for (uint32_t i = levels; i > 0; --i) {
                --currentLevel;
                rectangles[currentLevel]->setFillColor(ColorFullWhite);
                rectangles[currentLevel]->setBorderColor(ColorFullBlack);
            }
        }
        else {
            LOG_ERROR("bargraph incremented out of size");
        }
    }

} /* namespace gui */

M module-apps/widgets/BarGraph.hpp => module-apps/widgets/BarGraph.hpp +13 -13
@@ 23,36 23,36 @@ namespace gui
        uint32_t numberOfRectangles;
        uint32_t currentLevel = 0;

      public:
        Rect *createRectangle(uint32_t width, uint32_t height);
        [[nodiscard]] auto createRectangle(uint32_t width, uint32_t height) const -> Rect *;
        [[nodiscard]] auto createSpace(uint32_t width, uint32_t height) const -> Rect *;

        Rect *createSpace(uint32_t width, uint32_t height);
        auto incrementWith(uint32_t levels) -> bool;
        auto decrementWith(uint32_t levels) -> bool;

      public:
        void setPercentageValue(unsigned int value) override;

        [[nodiscard]] auto getValue() const -> uint32_t
        {
            return currentLevel;
        }
        auto update(int value = 1) -> bool final;

        auto setValue(unsigned int value) -> bool override;
    };

    class VBarGraph : public VBox, public BarGraph
    {
        void incrementWith(uint32_t levels);
        void decrementWith(uint32_t levels);

      public:
        VBarGraph(Item *parent = nullptr, Position x = 0, Position y = 0, uint32_t numberOfRectangles = 0);
        void setMaximum(unsigned int value) final;
        void setValue(unsigned int value) final;
        void update(int value = 1) final;
    };

    class HBarGraph : public HBox, public BarGraph
    {
        void incrementWith(uint32_t levels);
        void decrementWith(uint32_t levels);

      public:
        HBarGraph(Item *parent = nullptr, Position x = 0, Position y = 0, uint32_t numberOfRectangles = 0);
        void setMaximum(unsigned int value) final;
        void setValue(unsigned int value) final;
        void update(int value = 1) final;
    };

} /* namespace gui */

M module-apps/windows/OptionWindow.cpp => module-apps/windows/OptionWindow.cpp +1 -0
@@ 97,4 97,5 @@ namespace gui
            resetOptions(message->takeOptions());
        }
    }

} /* namespace gui */

M module-apps/windows/OptionWindow.hpp => module-apps/windows/OptionWindow.hpp +0 -1
@@ 19,7 19,6 @@ namespace gui

    class OptionWindow : public AppWindow
    {

      protected:
        std::shared_ptr<OptionsModel> optionsModel = nullptr;
        ListView *optionsList                      = nullptr;

M module-gui/gui/widgets/ProgressBar.cpp => module-gui/gui/widgets/ProgressBar.cpp +8 -6
@@ 35,14 35,15 @@ namespace gui
        }
    }

    void ProgressBar::setValue(unsigned int value) noexcept
    bool ProgressBar::setValue(unsigned int value) noexcept
    {
        currentValue = std::clamp(value, 0U, maxValue);
        return currentValue == value;
    }

    void ProgressBar::update(int value) noexcept
    bool ProgressBar::update(int value) noexcept
    {
        setValue(currentValue + value);
        return setValue(currentValue + value);
    }

    void ProgressBar::setPercentageValue(unsigned int value) noexcept


@@ 110,14 111,15 @@ namespace gui
        }
    }

    void CircularProgressBar::setValue(unsigned int value) noexcept
    bool CircularProgressBar::setValue(unsigned int value) noexcept
    {
        currentValue = std::clamp(value, 0U, maxValue);
        return value == currentValue;
    }

    void CircularProgressBar::update(int value) noexcept
    bool CircularProgressBar::update(int value) noexcept
    {
        setValue(currentValue + value);
        return setValue(currentValue + value);
    }

    void CircularProgressBar::setPercentageValue(unsigned int value) noexcept

M module-gui/gui/widgets/ProgressBar.hpp => module-gui/gui/widgets/ProgressBar.hpp +6 -6
@@ 17,8 17,8 @@ namespace gui
        virtual ~Progress() noexcept = default;

        virtual void setMaximum(unsigned int value)         = 0;
        virtual void setValue(unsigned int value)           = 0;
        virtual void update(int value = 1)                  = 0;
        virtual auto setValue(unsigned int value) -> bool   = 0;
        virtual auto update(int value = 1) -> bool          = 0;
        virtual void setPercentageValue(unsigned int value) = 0;
    };



@@ 28,8 28,8 @@ namespace gui
        ProgressBar(Item *parent, std::uint32_t x, std::uint32_t y, std::uint32_t w, std::uint32_t h);

        void setMaximum(unsigned int value) noexcept override;
        void setValue(unsigned int value) noexcept override;
        void update(int value = 1) noexcept override;
        auto setValue(unsigned int value) noexcept -> bool override;
        auto update(int value = 1) noexcept -> bool override;
        void setPercentageValue(unsigned int value) noexcept override;

        void buildDrawListImplementation(std::list<Command> &commands) override;


@@ 49,8 49,8 @@ namespace gui
        CircularProgressBar(Item *parent, const Circle::ShapeParams &shape);

        void setMaximum(unsigned int value) noexcept override;
        void setValue(unsigned int value) noexcept override;
        void update(int value = 1) noexcept override;
        auto setValue(unsigned int value) noexcept -> bool override;
        auto update(int value = 1) noexcept -> bool override;
        void setPercentageValue(unsigned int value) noexcept override;

        void buildDrawListImplementation(std::list<Command> &commands) override;

M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +7 -0
@@ 24,6 24,13 @@ namespace settings
        constexpr inline auto bondedDevices    = "bt_bonded_devices";
        constexpr inline auto btKeys           = "bt_keys";
    } // namespace Bluetooth
    namespace Brightness
    {
        constexpr inline auto state           = "br_state";
        constexpr inline auto brightnessLevel = "br_level";
        constexpr inline auto gammaFactor     = "br_gamma_Factor";
        constexpr inline auto autoMode        = "br_auto_mode";
    } // namespace Brightness

    namespace Cellular
    {

M module-services/service-evtmgr/CMakeLists.txt => module-services/service-evtmgr/CMakeLists.txt +2 -2
@@ 7,9 7,9 @@ set(SOURCES
        alarm/EventManagerAlarm.cpp
        api/EventManagerServiceAPI.cpp
        messages/Message.cpp
        screen-light-control/ScreenLightControl.cpp
        screen-light-control/ControlFunctions.cpp
        battery-level-check/BatteryLevelCheck.cpp
        screen-light-control/ControlFunctions.cpp
        screen-light-control/ScreenLightControl.cpp
)

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

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +20 -13
@@ 2,13 2,15 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-evtmgr/BatteryMessages.hpp"
#include "service-evtmgr/Constants.hpp"
#include "service-evtmgr/EVMessages.hpp"
#include "service-evtmgr/EventManager.hpp"
#include "service-evtmgr/KbdMessage.hpp"
#include "service-evtmgr/ScreenLightControlMessage.hpp"
#include "service-evtmgr/Constants.hpp"
#include "service-evtmgr/EventManager.hpp"
#include "service-evtmgr/WorkerEvent.hpp"
#include "screen-light-control/ScreenLightControl.hpp"

#include "battery-level-check/BatteryLevelCheck.hpp"
#include "screen-light-control/ScreenLightControl.hpp"

#include <BaseInterface.hpp>
#include <MessageType.hpp>


@@ 39,7 41,8 @@
#include <module-apps/messages/AppMessage.hpp>
#include <SystemManager/messages/CpuFrequencyMessage.hpp>

EventManager::EventManager(const std::string &name) : sys::Service(name)
EventManager::EventManager(const std::string &name)
    : sys::Service(name), screenLightControl(std::make_unique<screen_light_control::ScreenLightControl>(this))
{
    LOG_INFO("[%s] Initializing", name.c_str());
    alarmTimestamp = 0;


@@ 261,12 264,6 @@ sys::ReturnCodes EventManager::InitHandler()
        return response;
    });

    connect(sevm::ScreenLightControlMessage(sevm::screen_light_control::Action::turnOff), [&](sys::Message *msgl) {
        auto request = static_cast<sevm::ScreenLightControlMessage *>(msgl);
        sevm::screen_light_control::processRequest(request->action, request->parameters);
        return std::make_shared<sys::ResponseMessage>();
    });

    connect(sevm::BatterySetCriticalLevel(0), [&](sys::Message *msgl) {
        auto request = static_cast<sevm::BatterySetCriticalLevel *>(msgl);
        battery_level_check::setBatteryCriticalLevel(request->criticalLevel);


@@ 278,6 275,19 @@ sys::ReturnCodes EventManager::InitHandler()
        return std::make_shared<sys::ResponseMessage>();
    });

    connect(sevm::ScreenLightControlMessage(), [&](sys::Message *msgl) {
        auto *m = dynamic_cast<sevm::ScreenLightControlMessage *>(msgl);
        screenLightControl->processRequest(m->action, m->parameters);
        return std::make_shared<sys::ResponseMessage>();
    });

    connect(sevm::ScreenLightControlRequestParameters(), [&](sys::Message *msgl) {
        screen_light_control::Parameters params = {screenLightControl->getBrightnessValue()};
        auto msg                                = std::make_shared<sevm::ScreenLightControlParametersResponse>(
            screenLightControl->getLightState(), screenLightControl->getAutoModeState(), params);
        return msg;
    });

    // initialize keyboard worker
    EventWorker = std::make_unique<WorkerEvent>(this);



@@ 312,14 322,12 @@ sys::ReturnCodes EventManager::InitHandler()

    EventWorker->init(list);
    EventWorker->run();
    sevm::screen_light_control::init(this);

    return sys::ReturnCodes::Success;
}

sys::ReturnCodes EventManager::DeinitHandler()
{
    sevm::screen_light_control::deinit();
    EventWorker->close();
    EventWorker.reset();
    EventWorker = nullptr;


@@ 344,7 352,6 @@ sys::ReturnCodes EventManager::SwitchPowerModeHandler(const sys::ServicePowerMod

bool EventManager::messageSetApplication(sys::Service *sender, const std::string &applicationName)
{

    auto msg = std::make_shared<sevm::EVMFocusApplication>(applicationName);
    return sys::Bus::SendUnicast(msg, service::name::evt_manager, sender);
}

M module-services/service-evtmgr/WorkerEvent.cpp => module-services/service-evtmgr/WorkerEvent.cpp +2 -2
@@ 2,9 2,9 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-evtmgr/BatteryMessages.hpp"
#include "service-evtmgr/Constants.hpp"
#include "service-evtmgr/EVMessages.hpp"
#include "service-evtmgr/KbdMessage.hpp"
#include "service-evtmgr/Constants.hpp"
#include "service-evtmgr/WorkerEvent.hpp"
#include "battery-level-check/BatteryLevelCheck.hpp"



@@ 78,7 78,7 @@ bool WorkerEvent::handleMessage(uint32_t queueID)
        }

        if (bsp::headset::Handler(notification) == true) {
            bool state = bsp::headset::IsInserted();
            bool state   = bsp::headset::IsInserted();
            auto message = std::make_shared<AudioEventRequest>(audio::EventType::JackState,
                                                               state ? audio::Event::DeviceState::Connected
                                                                     : audio::Event::DeviceState::Disconnected);

M module-services/service-evtmgr/doc/screen_light_control.md => module-services/service-evtmgr/doc/screen_light_control.md +2 -1
@@ 54,6 54,7 @@ Default value of &gamma; is 2.5 . For leds this factor could be in range 2.2-2.8

## Message API

`sevm::ScreenLightControlMessage` is used to control the module. It takes action and data structure as parameters. Set of actions is described in `sevm::screen_light_control::Action`.
`screen_light_control::ScreenLightControlMessage` is used to control the module. It takes action and data structure as parameters. Set of actions is described in `sevm::screen_light_control::Action`.
`screen_light_control::ScreenLightControlRequestParameters` us ised to request currently setup parameters for display light and sensor.

![](light_control_message_flow.svg "Message to light control")
\ No newline at end of file

M module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp => module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp +2 -2
@@ 4,7 4,7 @@
#include "ControlFunctions.hpp"
#include <cmath>

namespace sevm::screen_light_control::functions
namespace screen_light_control::functions
{
    namespace
    {


@@ 95,4 95,4 @@ namespace sevm::screen_light_control::functions
        }
    }

} // namespace sevm::screen_light_control::functions
} // namespace screen_light_control::functions

M module-services/service-evtmgr/screen-light-control/ControlFunctions.hpp => module-services/service-evtmgr/screen-light-control/ControlFunctions.hpp +2 -2
@@ 8,7 8,7 @@
#include <vector>
#include <memory>

namespace sevm::screen_light_control::functions
namespace screen_light_control::functions
{
    using BrightnessFunction =
        std::vector<std::pair<bsp::light_sensor::IlluminanceLux, bsp::eink_frontlight::BrightnessPercentage>>;


@@ 23,4 23,4 @@ namespace sevm::screen_light_control::functions

    void setFunctionFromPoints(const BrightnessFunction &points);

} // namespace sevm::screen_light_control::functions
} // namespace screen_light_control::functions

M module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp +143 -75
@@ 3,119 3,99 @@

#include "ScreenLightControl.hpp"

namespace sevm::screen_light_control
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
#include <agents/settings/SystemSettings.hpp>

namespace screen_light_control
{
    namespace
    {
        constexpr inline auto CONTROL_TIMER_MS = 25;
        constexpr inline auto READOUT_TIMER_MS = 500;
        std::unique_ptr<sys::Timer> controlTimer;
        std::unique_ptr<sys::Timer> readoutTimer;

        bool automaticMode = false;
        bool lightOn       = false;

        void enableTimers()
        {
            controlTimer->connect([&](sys::Timer &) { controlTimerCallback(); });
            readoutTimer->connect([&](sys::Timer &) { readoutTimerCallback(); });
            controlTimer->start();
            readoutTimer->start();
        }

        void disableTimers()
        auto from_string(const std::string &str, bool def) -> bool
        {
            controlTimer->stop();
            readoutTimer->stop();
        }

        void setAutomaticModeParameters(const Parameters &params)
        {
            if (lightOn && automaticMode) {
                disableTimers();
            try {
                return std::stoi(str) == 0;
            }

            functions::setRampStep(100.0f *
                                   (static_cast<float>(CONTROL_TIMER_MS) / static_cast<float>(params.rampTimeMS)));
            functions::setHysteresis(params.brightnessHysteresis);
            functions::setFunctionFromPoints(params.functionPoints);

            if (lightOn && automaticMode) {
                enableTimers();
            catch (std::exception &) {
                return def;
            }
        }

        void turnOff()
        auto from_string(const std::string &str, float def) -> float
        {
            bsp::eink_frontlight::turnOff();
            bsp::light_sensor::standby();
            controlTimer->stop();
            readoutTimer->stop();
            lightOn = false;
        }

        void turnOn()
        {
            bsp::eink_frontlight::turnOn();
            bsp::light_sensor::wakeup();
            if (automaticMode) {
                enableTimers();
            try {
                return std::stof(str);
            }
            lightOn = true;
        }

        void enableAutomaticMode()
        {
            if (lightOn) {
                enableTimers();
            catch (std::exception &) {
                return def;
            }
            automaticMode = true;
        }

        void disableAutomaticMode()
        {
            disableTimers();
            automaticMode = false;
        }

    } // namespace

    void init(sys::Service *parent)
    ScreenLightControl::ScreenLightControl(sys::Service *parent)
        : settings(std::make_unique<settings::Settings>(parent))
    {
        controlTimer = std::make_unique<sys::Timer>("LightControlTimer", parent, CONTROL_TIMER_MS);
        readoutTimer = std::make_unique<sys::Timer>("LightSensorReadoutTimer", parent, READOUT_TIMER_MS);

        Parameters defaultParams;
        setAutomaticModeParameters(defaultParams);
        initFromSettings();
    }

    void deinit()
    ScreenLightControl::~ScreenLightControl()
    {
        disableTimers();
        controlTimer.reset();
        readoutTimer.reset();
    }

    void processRequest(Action action, const Parameters &params)
    void ScreenLightControl::initFromSettings()
    {
        settings->registerValueChange(settings::Brightness::brightnessLevel,
                                      [&](const std::string &value) { setBrightnessLevel(from_string(value, 0.0f)); });

        settings->registerValueChange(settings::Brightness::autoMode, [&](const std::string &value) {
            if (from_string(value, false)) {
                enableAutomaticMode();
            }
            else {
                disableAutomaticMode();
            }
        });

        settings->registerValueChange(settings::Brightness::autoMode, [&](const std::string &value) {
            if (from_string(value, false)) {
                turnOn();
            }
            else {
                turnOff();
            }
        });
    }

    void ScreenLightControl::processRequest(Action action, const Parameters &params)
    {
        switch (action) {
        case Action::turnOff:
            turnOff();
            setScreenLightSettings(settings::Brightness::state, lightOn);
            break;
        case Action::turnOn:
            turnOn();
            setScreenLightSettings(settings::Brightness::state, lightOn);
            break;
        case Action::enableAutomaticMode:
            enableAutomaticMode();
            setScreenLightSettings(settings::Brightness::autoMode, automaticMode);
            break;
        case Action::disableAutomaticMode:
            disableAutomaticMode();
            setScreenLightSettings(settings::Brightness::autoMode, automaticMode);
            break;
        case Action::setManualModeBrightness:
            bsp::eink_frontlight::setBrightness(params.manualModeBrightness);
            setBrightnessLevel(params.manualModeBrightness);
            setScreenLightSettings(settings::Brightness::brightnessLevel, params.manualModeBrightness);
            break;
        case Action::setGammaCorrectionFactor:
            bsp::eink_frontlight::setGammaFactor(params.gammaFactor);
            setGammaFactor(params.gammaFactor);
            break;
        case Action::setAutomaticModeParameters:
            setAutomaticModeParameters(params);


@@ 123,14 103,102 @@ namespace sevm::screen_light_control
        }
    }

    void controlTimerCallback()
    void ScreenLightControl::controlTimerCallback()
    {
        bsp::eink_frontlight::setBrightness(functions::brightnessRampOut());
    }

    void readoutTimerCallback()
    void ScreenLightControl::readoutTimerCallback()
    {
        functions::calculateBrightness(bsp::light_sensor::readout());
    }

} // namespace sevm::screen_light_control
    auto ScreenLightControl::getAutoModeState() const noexcept -> ScreenLightMode
    {
        return automaticMode;
    }

    auto ScreenLightControl::getLightState() const noexcept -> bool
    {
        return lightOn;
    }

    auto ScreenLightControl::getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage
    {
        return brightnessValue;
    }

    void ScreenLightControl::enableTimers()
    {
        controlTimer->connect([&](sys::Timer &) { controlTimerCallback(); });
        readoutTimer->connect([&](sys::Timer &) { readoutTimerCallback(); });
        controlTimer->start();
        readoutTimer->start();
    }

    void ScreenLightControl::disableTimers()
    {
        controlTimer->stop();
        readoutTimer->stop();
    }

    void ScreenLightControl::setAutomaticModeParameters(const Parameters &params)
    {
        if (lightOn && automaticMode == ScreenLightMode::Automatic) {
            disableTimers();
        }

        functions::setRampStep(100.0f * (static_cast<float>(CONTROL_TIMER_MS) / static_cast<float>(params.rampTimeMS)));
        functions::setHysteresis(params.brightnessHysteresis);
        functions::setFunctionFromPoints(params.functionPoints);

        if (lightOn && automaticMode == ScreenLightMode::Automatic) {
            enableTimers();
        }
    }

    void ScreenLightControl::enableAutomaticMode()
    {
        if (lightOn) {
            enableTimers();
        }
        automaticMode = ScreenLightMode::Automatic;
    }

    void ScreenLightControl::disableAutomaticMode()
    {
        disableTimers();
        automaticMode = ScreenLightMode::Manual;
    }

    void ScreenLightControl::turnOn()
    {
        bsp::eink_frontlight::turnOn();
        bsp::light_sensor::wakeup();
        if (automaticMode) {
            enableTimers();
        }
        lightOn = true;
    }

    void ScreenLightControl::setBrightnessLevel(bsp::eink_frontlight::BrightnessPercentage brightnessPercentage)
    {
        bsp::eink_frontlight::setBrightness(brightnessPercentage);
        brightnessValue = brightnessPercentage;
    }

    void ScreenLightControl::setGammaFactor(float gammaFactor)
    {
        bsp::eink_frontlight::setGammaFactor(gammaFactor);
        setScreenLightSettings(settings::Brightness::gammaFactor, gammaFactor);
    }

    void ScreenLightControl::turnOff()
    {
        bsp::eink_frontlight::turnOff();
        bsp::light_sensor::standby();
        controlTimer->stop();
        readoutTimer->stop();
        lightOn = false;
    }
} // namespace screen_light_control

M module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp +63 -10
@@ 3,13 3,27 @@

#pragma once

#include <service-db/service-db/Settings.hpp>
#include "ControlFunctions.hpp"
#include <Service/Timer.hpp>

#include <sstream>

namespace sys
{
    class Timer;
}

/// Screen light control algorithm. Automatic/Manual mode of operation.
/// Processing of ambient light sensor input to screen brightness output.
namespace sevm::screen_light_control
namespace screen_light_control
{
    /// Modes in which front light can operate
    enum ScreenLightMode
    {
        Automatic, /// Automally sets screen brightness based on sensor data
        Manual     /// Manually set brightness level
    };

    /// Set of actions to control the screen light
    enum class Action
    {


@@ 24,6 38,8 @@ namespace sevm::screen_light_control

    struct Parameters
    {
        static constexpr auto MAX_BRIGHTNESS = 100.0;

        /// Screen brightness 0-100% in manual mode
        bsp::eink_frontlight::BrightnessPercentage manualModeBrightness = 50.0f;
        /// Vector of points for screen brightness [%] in relation to ambient light [Lux] function. Points have to be in


@@ 37,16 53,53 @@ namespace sevm::screen_light_control
        float gammaFactor = 2.5f;
    };

    /// Initialization of screen light control
    /// @param 'parent' - pointer to parent sys::Service class
    void init(sys::Service *parent);
    /// Control screen light and keeps it's current state
    class ScreenLightControl
    {
      public:
        explicit ScreenLightControl(sys::Service *parent);
        ~ScreenLightControl();

        void processRequest(Action action, const Parameters &params);

    void deinit();
        [[nodiscard]] auto getLightState() const noexcept -> bool;
        [[nodiscard]] auto getAutoModeState() const noexcept -> ScreenLightMode;
        [[nodiscard]] auto getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage;

    void processRequest(Action action, const Parameters &params);
      private:
        void controlTimerCallback();
        void readoutTimerCallback();

    void controlTimerCallback();
        void enableTimers();
        void disableTimers();

    void readoutTimerCallback();
        void setAutomaticModeParameters(const Parameters &params);
        void setBrightnessLevel(bsp::eink_frontlight::BrightnessPercentage brightnessPercentage);
        void setGammaFactor(float gammaFactor);

        void turnOff();
        void turnOn();

        void enableAutomaticMode();
        void disableAutomaticMode();

        template <class T> void setScreenLightSettings(const std::string &varName, T value)
        {
            settings->setValue(varName, std::to_string(value));
        }
        void initFromSettings();

        static constexpr inline auto CONTROL_TIMER_MS = 25;
        static constexpr inline auto READOUT_TIMER_MS = 500;

        std::unique_ptr<sys::Timer> controlTimer;
        std::unique_ptr<sys::Timer> readoutTimer;

        bool lightOn                                               = false;
        screen_light_control::ScreenLightMode automaticMode        = ScreenLightMode::Manual;
        bsp::eink_frontlight::BrightnessPercentage brightnessValue = 0.0;

        std::unique_ptr<settings::Settings> settings;
    };

} // namespace sevm::screen_light_control
} // namespace screen_light_control

M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp => module-services/service-evtmgr/service-evtmgr/EVMessages.hpp +0 -13
@@ 5,7 5,6 @@

#include "KbdMessage.hpp"
#include "BatteryMessages.hpp"
#include <screen-light-control/ScreenLightControl.hpp>

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


@@ 143,16 142,4 @@ namespace sevm
        bool success;
    };

    class ScreenLightControlMessage : public Message
    {
      public:
        ScreenLightControlMessage(screen_light_control::Action act,
                                  screen_light_control::Parameters params = screen_light_control::Parameters())
            : Message(MessageType::EVMScreenLightControlMessage), action(act), parameters(params)
        {}

        screen_light_control::Action action;
        screen_light_control::Parameters parameters;
    };

} /* namespace sevm*/

M module-services/service-evtmgr/service-evtmgr/EventManager.hpp => module-services/service-evtmgr/service-evtmgr/EventManager.hpp +3 -0
@@ 11,6 11,7 @@
#include <bsp/common.hpp>
#include <bsp/keyboard/key_codes.hpp>
#include <bsp/keypad_backlight/keypad_backlight.hpp>
#include <screen-light-control/ScreenLightControl.hpp>

#include <cstdint>
#include <memory>


@@ 40,6 41,8 @@ class EventManager : public sys::Service
    // flag set when there is alarm to handle
    bool alarmIsValid = false;

    std::unique_ptr<screen_light_control::ScreenLightControl> screenLightControl;

  public:
    EventManager(const std::string &name);
    ~EventManager();

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

// 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-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp"

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

namespace sevm
{
    class ScreenLightControlMessage : public sys::DataMessage
    {
      public:
        ScreenLightControlMessage() : sys::DataMessage(MessageType::ScreenLightControlAction)
        {}
        ScreenLightControlMessage(screen_light_control::Action act,
                                  screen_light_control::Parameters params = screen_light_control::Parameters())
            : sys::DataMessage(MessageType::ScreenLightControlAction), action(act), parameters(std::move(params))
        {}

        screen_light_control::Action action;
        screen_light_control::Parameters parameters;
    };

    class ScreenLightControlRequestParameters : public sys::DataMessage
    {
      public:
        ScreenLightControlRequestParameters() : sys::DataMessage(MessageType::ScreenLightControlParameters)
        {}
    };

    class ScreenLightControlParametersResponse : public sys::DataMessage
    {
      public:
        ScreenLightControlParametersResponse() : sys::DataMessage(MessageType::ScreenLightControlParametersResponse)
        {}

        ScreenLightControlParametersResponse(bool lightOn,
                                             screen_light_control::ScreenLightMode mode,
                                             screen_light_control::Parameters params)
            : sys::DataMessage(MessageType::ScreenLightControlParametersResponse), lightOn(lightOn), mode(mode),
              parameters(std::move(params))
        {}

        bool lightOn;
        screen_light_control::ScreenLightMode mode;
        screen_light_control::Parameters parameters;
    };
} // namespace sevm

M module-services/service-evtmgr/tests/test-ScreenLightControlFunctions.cpp => module-services/service-evtmgr/tests/test-ScreenLightControlFunctions.cpp +4 -3
@@ 6,7 6,7 @@

TEST_CASE("ScreenLightControlFunctions")
{
    using namespace sevm::screen_light_control::functions;
    using namespace screen_light_control::functions;
    constexpr auto controlTimerMS = 25;

    SECTION("Ramp an hysteresis test")


@@ 14,8 14,9 @@ TEST_CASE("ScreenLightControlFunctions")
        INFO("Setup");
        const unsigned int testRampTime                          = 500;
        const bsp::eink_frontlight::BrightnessPercentage testVal = 100.0f;
        BrightnessFunction functionPoints = BrightnessFunction({{0.0f, testVal}, {100.0f, 0.0f}});
        const float hysteresis            = 10.0f;
        screen_light_control::functions::BrightnessFunction functionPoints =
            BrightnessFunction({{0.0f, testVal}, {100.0f, 0.0f}});
        const float hysteresis = 10.0f;

        setRampStep(100.0f * (static_cast<float>(controlTimerMS) / static_cast<float>(testRampTime)));
        setHysteresis(hysteresis);

M source/MessageType.hpp => source/MessageType.hpp +6 -3
@@ 177,8 177,6 @@ enum class MessageType
    EVMTorchStateMessage,
    // Keypad backlight control messages
    EVMKeypadBacklightMessage,
    // Screen frontlight control messages
    EVMScreenLightControlMessage,

    // cellular messages
    EVMGetBoard,


@@ 238,7 236,12 @@ enum class MessageType
    AntennaLockNotification,
    Settings,
    FileContentModified,
    FileIndexer
    FileIndexer,

    // Screen frontlight control messages
    ScreenLightControlAction,
    ScreenLightControlParameters,
    ScreenLightControlParametersResponse,
};

#endif /* SOURCE_MESSAGETYPE_HPP_ */