~aleteoryx/muditaos

50d0cf0be95cd23e3c860ab356e82c36f18c30e4 — Przemyslaw Brudny 5 years ago f2eace6
[EGD-5598] GuiTimer refresh window on count

Added Gui timer auto refresh window on count and additional
name based API to detach timer from window. Added
TimerIDGenerator and exception throw on creating user timer
with same name.
M module-apps/GuiTimer.cpp => module-apps/GuiTimer.cpp +6 -2
@@ 44,13 44,17 @@ namespace app
    {}

    GuiTimer::GuiTimer(const std::string &name, Application *parent, gui::ms timeout, gui::Timer::Type type)
        : sys::Timer(name, parent, timeout, toSysTimerType(type)), sysapi{*this}
        : sys::Timer(name, parent, timeout, toSysTimerType(type), sys::UserTimerIDGenerator()), sysapi{*this, parent}
    {}

    void GuiTimer::Sysapi::connect(gui::Item *item)
    {
        if (item != nullptr) {
            parent.connect([item, this](sys::Timer &timer) { item->onTimer(parent); });
            parent.connect([item, this](sys::Timer &timer) {
                if (item->onTimer(parent)) {
                    app->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
                }
            });
        }
    }
} // namespace app

M module-apps/GuiTimer.hpp => module-apps/GuiTimer.hpp +3 -2
@@ 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


@@ 49,10 49,11 @@ namespace app
        {
            friend Application;
            GuiTimer &parent;
            Application *app = nullptr;
            void connect(gui::Item *item);

          public:
            Sysapi(GuiTimer &parent) : parent(parent)
            Sysapi(GuiTimer &parent, Application *app) : parent(parent), app(app)
            {}
        } sysapi;
    };

M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +0 -1
@@ 412,7 412,6 @@ namespace gui
            updateDuration(std::chrono::system_clock::to_time_t(systemUnitDuration));
            callDuration++;
            LOG_DEBUG("Update duration timer callback - %" PRIu32, static_cast<uint32_t>(callDuration.count()));
            application->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
            return true;
        };
        timer->start();

M module-apps/application-meditation/widgets/MeditationTimer.cpp => module-apps/application-meditation/widgets/MeditationTimer.cpp +8 -12
@@ 50,6 50,11 @@ namespace gui
        timer->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        timer->setEditMode(EditMode::Browse);

        dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
            setArea({newDim.x, newDim.y, newDim.w, newDim.h});
            return true;
        };

        onReset();
    }



@@ 64,7 69,6 @@ namespace gui
    {
        updateTimer();
        progressBar->setPercentageValue(calculatePercentageValue());
        application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
    }

    void MeditationTimer::updateTimer()


@@ 76,19 80,12 @@ namespace gui
        timer->setText(remainingDuration.str(Duration::DisplayedFormat::Fixed0M0S));
    }

    auto MeditationTimer::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
    {
        setPosition(newDim.x, newDim.y);
        setSize(newDim.w, newDim.h);
        return true;
    }

    void MeditationTimer::reset(std::chrono::seconds _duration, std::chrono::seconds _intervalPeriod) noexcept
    {
        assert(_duration != std::chrono::seconds::zero()); // Pre-condition check.

        duration = _duration;
        elapsed  = std::chrono::seconds::zero();
        duration       = _duration;
        elapsed        = std::chrono::seconds::zero();
        intervalPeriod = _intervalPeriod;
        hasInterval    = _intervalPeriod != std::chrono::seconds::zero();
        onReset();


@@ 113,8 110,7 @@ namespace gui
    auto MeditationTimer::onTimerTimeout(Item &self, Timer &timerTask) -> bool
    {
        if (isStopped() || isFinished()) {
            timerTask.stop();
            detachTimer(timerTask);
            application->getTimers().detachTimer("MeditationTimer");

            if (isFinished() && timeoutCallback != nullptr) {
                timeoutCallback();

M module-apps/application-meditation/widgets/MeditationTimer.hpp => module-apps/application-meditation/widgets/MeditationTimer.hpp +0 -2
@@ 25,8 25,6 @@ namespace gui
                        app::ApplicationMeditation *app,
                        Item *_parent = nullptr);

        [[nodiscard]] auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;

        void start();
        void stop();
        void reset(std::chrono::seconds _duration, std::chrono::seconds period = std::chrono::seconds::zero()) noexcept;

M module-apps/application-meditation/windows/MeditationTimerWindow.cpp => module-apps/application-meditation/windows/MeditationTimerWindow.cpp +0 -2
@@ 68,12 68,10 @@ void MeditationTimerWindow::onBeforeShow(ShowMode mode, SwitchData *data)
        setVisibleRunning();
        auto onMeditationEnd = [&]() -> void {
            setVisibleMeditationEnd();
            application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
        };
        timer->registerTimeoutCallback(onMeditationEnd);
        timer->reset(meditationTime, meditationIntervalPeriod);
        timer->start();
        application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
    };

    timer->registerTimeoutCallback(onPreparation);

M module-apps/application-settings-new/windows/DisplayLightWindow.cpp => module-apps/application-settings-new/windows/DisplayLightWindow.cpp +5 -7
@@ 21,21 21,20 @@ namespace gui
        isDisplayLightSwitchOn = values.lightOn;
        isAutoLightSwitchOn    = values.mode == screen_light_control::ScreenLightMode::Automatic;
        brightnessValue        = values.parameters.manualModeBrightness;
        timerName              = "AmbientLightTimer";

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

        timerTask = std::make_unique<app::GuiTimer>(
            "AmbientLightTimer", application, gui::lighting::AMBIENT_LIGHT_TIMER_MS, Timer::Type::Continous);
        auto timerTask = std::make_unique<app::GuiTimer>(
            timerName, application, gui::lighting::AMBIENT_LIGHT_TIMER_MS, Timer::Type::Continous);
        timerCallback = [this](Item &it, Timer &task) { return onTimerTimeout(it, task); };
        timerTask->start();
        application->connect(std::move(timerTask), this);
    }

    DisplayLightWindow::~DisplayLightWindow()
    void DisplayLightWindow::onClose()
    {
        if (timerTask != nullptr) {
            timerTask->stop();
        }
        application->detachTimer(timerName);
    }

    auto DisplayLightWindow::onTimerTimeout(Item &self, Timer &task) -> bool


@@ 43,7 42,6 @@ namespace gui
        ambientLight = bsp::light_sensor::readout();
        refreshOptionsList();

        application->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        return true;
    }


M module-apps/application-settings-new/windows/DisplayLightWindow.hpp => module-apps/application-settings-new/windows/DisplayLightWindow.hpp +2 -2
@@ 20,7 20,7 @@ namespace gui
    {
      public:
        DisplayLightWindow(app::Application *app, app::settingsInterface::ScreenLightSettings *screenLightSettings);
        ~DisplayLightWindow();
        void onClose() override;

      private:
        auto buildOptionsList() -> std::list<Option> override;


@@ 33,7 33,7 @@ namespace gui
        std::uint8_t brightnessValue                                     = 0;
        app::settingsInterface::ScreenLightSettings *screenLightSettings = nullptr;
        float ambientLight                                               = 0.0;
        std::unique_ptr<app::GuiTimer> timerTask;
        std::string timerName;
        [[nodiscard]] auto onTimerTimeout(Item &self, Timer &task) -> bool;
    };
} // namespace gui

M module-sys/Service/Service.hpp => module-sys/Service/Service.hpp +51 -14
@@ 3,23 3,24 @@

#pragma once

#include "Timer.hpp"
#include "BusProxy.hpp"
#include "Common.hpp"  // for ReturnCodes, ServicePriority, BusChannels
#include "Mailbox.hpp" // for Mailbox
#include "Message.hpp" // for MessagePointer
#include "ServiceManifest.hpp"
#include "thread.hpp"  // for Thread
#include <algorithm>   // for find, max
#include <cstdint>     // for uint32_t, uint64_t
#include <functional>  // for function
#include <iterator>    // for end
#include <map>         // for map
#include <memory>      // for allocator, shared_ptr, enable_shared_from_this
#include <string>      // for string
#include <typeindex>   // for type_index
#include <utility>     // for pair
#include <vector>      // for vector<>::iterator, vector
#include <typeinfo>    // for connect by type
#include "thread.hpp" // for Thread
#include <algorithm>  // for find, max
#include <cstdint>    // for uint32_t, uint64_t
#include <functional> // for function
#include <iterator>   // for end
#include <map>        // for map
#include <memory>     // for allocator, shared_ptr, enable_shared_from_this
#include <string>     // for string
#include <typeindex>  // for type_index
#include <utility>    // for pair
#include <vector>     // for vector<>::iterator, vector
#include <typeinfo>   // for connect by type

namespace sys
{


@@ 124,7 125,17 @@ namespace sys

            void detach(Timer *timer)
            {
                list.erase(std::find(list.begin(), list.end(), timer));
                auto it = std::find(list.begin(), list.end(), timer);

                if (it != list.end()) {
                    list.erase(it);
                }
            }

            auto findTimer(const std::string &timerName) const
            {
                return std::find_if(
                    list.begin(), list.end(), [&, timerName](auto &el) -> bool { return el->getName() == timerName; });
            }

          public:


@@ 135,18 146,44 @@ namespace sys
                return std::find(list.begin(), list.end(), timer);
            }

            [[nodiscard]] auto timerExists(const std::string &timerName) const
            {
                return findTimer(timerName) != list.end();
            }

            void detachTimer(const std::string &timerName)
            {
                auto it = findTimer(timerName);

                if (it != list.end()) {
                    (*it)->stop();
                    detach((*it));
                }
            }

            [[nodiscard]] auto noTimer() const
            {
                return std::end(list);
            }

        } timers;

      public:
        auto getTimers() -> auto &
        [[nodiscard]] auto getTimers() -> auto &
        {
            return timers;
        }

        [[nodiscard]] auto timerExists(const std::string &timerName) -> bool
        {
            return timers.timerExists(timerName);
        }

        void detachTimer(const std::string &timerName)
        {
            timers.detachTimer(timerName);
        }

        auto TimerHandle(SystemMessage &message) -> ReturnCodes;
    };


M module-sys/Service/Timer.cpp => module-sys/Service/Timer.cpp +10 -11
@@ 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 "GuiTimer.hpp"
#include "Timer.hpp"
#include "Service.hpp"
#include "TimerMessage.hpp"


@@ 21,26 22,24 @@

namespace sys
{

    const ms Timer::timeout_infinite = std::numeric_limits<ms>().max();
    static uint32_t timer_id;

    auto toName(const std::string &val, uint32_t no) -> std::string
    {
        return val + "_" + std::to_string(no);
    }

    Timer::Timer(const std::string &name, Service *service, ms interval, Type type)
        : cpp_freertos::Timer((toName(name, timer_id)).c_str(), pdMS_TO_TICKS(interval), type == Type::Periodic),
          parent(service), type(type), interval(interval), name(toName(name, timer_id))
    Timer::Timer(const std::string &name, Service *service, ms interval, Type type, const TimerIDGenerator &generator)
        : cpp_freertos::Timer(generator.generateID(name).c_str(), pdMS_TO_TICKS(interval), type == Type::Periodic),
          parent(service), type(type), interval(interval), name(generator.generateID(name).c_str())
    {
        if (service != nullptr) {

            if (service->timerExists(name)) {
                throw std::runtime_error("Timer: " + name + " exits in service: " + service->GetName());
            }

            service->getTimers().attach(this);
            generator.incrementID();
        }
        else {
            log_error("Bad timer creation!");
        }
        ++timer_id;
        log_debug("Timer %s created %s", name.c_str(), type == Type::Periodic ? "periodic" : "singleshot");
    }


M module-sys/Service/Timer.hpp => module-sys/Service/Timer.hpp +44 -1
@@ 18,6 18,45 @@ namespace sys
{
    using ms = unsigned int;

    class TimerIDGenerator
    {
      public:
        virtual ~TimerIDGenerator() = default;

        virtual void incrementID() const                                           = 0;
        [[nodiscard]] virtual std::string generateID(const std::string &val) const = 0;
    };

    class UserTimerIDGenerator : public TimerIDGenerator
    {
      public:
        void incrementID() const override{};

        [[nodiscard]] std::string generateID(const std::string &val) const override
        {
            return val;
        }
    };
    class SystemTimerIDGenerator : public TimerIDGenerator
    {
        static uint32_t &getId() noexcept
        {
            static uint32_t timer_id = 0;
            return timer_id;
        }

      public:
        void incrementID() const override
        {
            getId()++;
        };

        [[nodiscard]] std::string generateID(const std::string &val) const override
        {
            return val + "_" + std::to_string(getId());
        }
    };

    /// Base timer for all coarse timers in system
    class Timer : private cpp_freertos::Timer
    {


@@ 34,7 73,11 @@ namespace sys
        /// @param name this will be name of timer + postfix
        /// @param parent service on which behalf timer events will be sent and received
        /// @param interval time for next timer event in
        Timer(const std::string &name, Service *parent, ms interval, Type type = Type::Periodic);
        Timer(const std::string &name,
              Service *parent,
              ms interval,
              Type type                         = Type::Periodic,
              const TimerIDGenerator &generator = SystemTimerIDGenerator());

        /// Create timer with default name `_<id_number>` and register it in parent
        /// @param parent service on which behalf timer events will be sent and received