~aleteoryx/muditaos

121879f4ec9b37516529d5b349b525cea7e8f31a — Lefucjusz 2 years ago cfc39c9
[MOS-220] Changed signal strength refresh mechanism

Modified signal strength update mechanism
to avoid unnecessary screen refreshes in
case new signal strength value is equal
to the previous one.
Minor cleanups.
M module-apps/apps-common/ApplicationCommon.cpp => module-apps/apps-common/ApplicationCommon.cpp +21 -28
@@ 352,52 352,45 @@ namespace app
                return handleNetworkAccessTechnologyUpdate(msgl);
            }
        }
        else if (msgl->messageType == MessageType::AppInputEvent) {

        switch (msgl->messageType) {
        case MessageType::AppInputEvent:
            return handleInputEvent(msgl);
        }
        else if (msgl->messageType == MessageType::KBDKeyEvent) {
        case MessageType::KBDKeyEvent:
            return handleKBDKeyEvent(msgl);
        }
        else if (msgl->messageType == MessageType::EVMMinuteUpdated) {
        case MessageType::EVMMinuteUpdated:
            return handleMinuteUpdated(msgl);
        }
        else if (msgl->messageType == MessageType::AppAction) {
        case MessageType::AppAction:
            return handleAction(msgl);
        }
        else if (msgl->messageType == MessageType::AppSwitch) {
        case MessageType::AppSwitch:
            return handleApplicationSwitch(msgl);
        }
        else if (msgl->messageType == MessageType::AppSwitchBack) {
        case MessageType::AppSwitchBack:
            returnToPreviousWindow();
            return sys::msgHandled();
        }
        else if (msgl->messageType == MessageType::AppSwitchWindow) {
        case MessageType::AppSwitchWindow:
            return handleSwitchWindow(msgl);
        }
        else if (msgl->messageType == MessageType::AppClose) {
        case MessageType::AppClose:
            return handleAppClose(msgl);
        }
        else if (msgl->messageType == MessageType::AppRebuild) {
        case MessageType::AppRebuild:
            return handleAppRebuild(msg);
        }
        else if (msgl->messageType == MessageType::AppFocusLost) {
        case MessageType::AppFocusLost:
            return handleAppFocusLost(msgl);
        default:
            return sys::msgNotHandled();
        }
        return sys::msgNotHandled();
    }

    sys::MessagePointer ApplicationCommon::handleAsyncResponse(sys::ResponseMessage *resp)
    {
        if (resp != nullptr) {
            if (auto command = callbackStorage->getCallback(resp); command->execute()) {
                refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
                checkBlockingRequests();
            }
            return std::make_shared<sys::ResponseMessage>();
        }
        else {
        if (resp == nullptr) {
            return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
        }

        if (const auto command = callbackStorage->getCallback(resp); command->execute()) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
            checkBlockingRequests();
        }
        return std::make_shared<sys::ResponseMessage>();
    }

    sys::MessagePointer ApplicationCommon::handleSignalStrengthUpdate([[maybe_unused]] sys::Message *msgl)

M module-apps/apps-common/windows/AppWindow.cpp => module-apps/apps-common/windows/AppWindow.cpp +2 -2
@@ 167,7 167,7 @@ namespace gui
        return header->getTitle();
    }

    bool AppWindow::onDatabaseMessage(sys::Message *msg)
    bool AppWindow::onDatabaseMessage([[maybe_unused]] sys::Message *msg)
    {
        return false;
    }


@@ 309,7 309,7 @@ namespace gui
        return application->GetName() + separator + getName();
    }

    void AppWindow::startInputModeRestoreTimer(std::function<void()> inputModeRestoreFunction)
    void AppWindow::startInputModeRestoreTimer(const std::function<void()> &inputModeRestoreFunction)
    {
        if (inputModeRestoreFunction == nullptr) {
            return;

M module-apps/apps-common/windows/AppWindow.hpp => module-apps/apps-common/windows/AppWindow.hpp +1 -1
@@ 119,7 119,7 @@ namespace gui
        /// but it would mean not insignificant refactor
        BoundingBox bodySize();

        void startInputModeRestoreTimer(std::function<void()> inputModeRestoreFunction = nullptr);
        void startInputModeRestoreTimer(const std::function<void()> &inputModeRestoreFunction = nullptr);
    };

} /* namespace gui */

M module-gui/gui/widgets/StatusBar.cpp => module-gui/gui/widgets/StatusBar.cpp +22 -18
@@ 2,8 2,6 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <iomanip>
#include "Label.hpp"
#include "Image.hpp"
#include "BoxLayout.hpp"
#include "StatusBar.hpp"
#include "status-bar/Style.hpp"


@@ 268,7 266,7 @@ namespace gui::status_bar

    void StatusBar::setIndicatorModifier(Indicator indicator, StatusBarVisitor &modifier)
    {
        if (indicator == Indicator::SimCard && sim != nullptr) {
        if ((indicator == Indicator::SimCard) && (sim != nullptr)) {
            sim->acceptStatusBarVisitor(modifier);
        }
    }


@@ 283,6 281,7 @@ namespace gui::status_bar

    bool StatusBar::showBattery(bool enabled)
    {
        const auto stateChanged      = battery->update(Store::Battery::get());
        const auto visibilityChanged = (battery->isVisible() != enabled);
        if (enabled) {
            battery->show();


@@ 290,14 289,12 @@ namespace gui::status_bar
        else {
            battery->hide();
        }
        const auto stateChanged    = battery->update(Store::Battery::get());
        const auto refreshRequired = stateChanged || visibilityChanged;
        return refreshRequired;
        return (stateChanged || visibilityChanged);
    }

    void StatusBar::showBluetooth(bool enabled)
    {
        if (enabled && configuration.getBluetoothMode() != sys::bluetooth::BluetoothMode::Disabled) {
        if (enabled && (configuration.getBluetoothMode() != sys::bluetooth::BluetoothMode::Disabled)) {
            bluetooth->show();
        }
        else {


@@ 331,7 328,7 @@ namespace gui::status_bar

    bool StatusBar::updateBluetooth(sys::bluetooth::BluetoothMode mode)
    {
        if (bluetooth == nullptr || !configuration.isEnabled(Indicator::Bluetooth)) {
        if ((bluetooth == nullptr) || !configuration.isEnabled(Indicator::Bluetooth)) {
            return false;
        }
        configuration.setBluetoothMode(mode);


@@ 342,7 339,7 @@ namespace gui::status_bar

    bool StatusBar::updateAlarmClock(bool status)
    {
        if (alarmClock == nullptr || !configuration.isEnabled(Indicator::AlarmClock)) {
        if ((alarmClock == nullptr) || !configuration.isEnabled(Indicator::AlarmClock)) {
            return false;
        }
        configuration.setAlarmClockStatus(status);


@@ 360,13 357,22 @@ namespace gui::status_bar
        return true;
    }

    void StatusBar::showSignalStrength(bool enabled)
    bool StatusBar::showSignalStrength(bool enabled)
    {
        const auto signalStrength = Store::GSM::get()->getSignalStrength();
        const auto networkStatus  = Store::GSM::get()->getNetwork().status;
        const auto tethering      = Store::GSM::get()->getTethering();
        signal->update(signalStrength, networkStatus, tethering);
        enabled ? signal->show() : signal->hide();
        const auto currentSignalStrength = Store::GSM::get()->getSignalStrength();
        const auto currentNetworkStatus  = Store::GSM::get()->getNetwork().status;
        const auto currentTethering      = Store::GSM::get()->getTethering();
        const auto stateChanged      = signal->update(currentSignalStrength, currentNetworkStatus, currentTethering);
        const auto visibilityChanged = (signal->isVisible() != enabled);
        if (visibilityChanged) {
            if (enabled) {
                signal->show();
            }
            else {
                signal->hide();
            }
        }
        return (stateChanged || visibilityChanged);
    }

    bool StatusBar::updateSignalStrength()


@@ 374,8 380,7 @@ namespace gui::status_bar
        if (signal == nullptr) {
            return false;
        }
        showSignalStrength(configuration.isEnabled(Indicator::Signal));
        return true;
        return showSignalStrength(configuration.isEnabled(Indicator::Signal));
    }

    bool StatusBar::updatePhoneMode()


@@ 468,7 473,6 @@ namespace gui::status_bar
        configuration.setTetheringState(state);
        showTethering(configuration.isEnabled(Indicator::Tethering));
        leftBox->resizeItems();

        return true;
    }


M module-gui/gui/widgets/StatusBar.hpp => module-gui/gui/widgets/StatusBar.hpp +2 -1
@@ 243,7 243,8 @@ namespace gui::status_bar

        /// Show/hide signal strenght widget
        /// @param enabled true to show false to hide the widget
        void showSignalStrength(bool enabled);
        /// @return true if screen refresh is required, false if not required
        bool showSignalStrength(bool enabled);

        /// Show/hide phone mode widget
        /// @param enabled true to show false to hide the widget

M module-gui/gui/widgets/status-bar/SignalStrengthBar.cpp => module-gui/gui/widgets/status-bar/SignalStrengthBar.cpp +20 -3
@@ 6,6 6,7 @@
#include <string>
#include <Image.hpp>
#include <map>
#include <magic_enum.hpp>

namespace gui::status_bar
{


@@ 47,31 48,47 @@ namespace gui::status_bar
        setMinimumSize(img->getWidth(), style::status_bar::height);
    }

    void SignalStrengthBar::update(const Store::SignalStrength &signal,
    bool SignalStrengthBar::update(const Store::SignalStrength &signal,
                                   const Store::Network::Status &status,
                                   const Store::Tethering &tethering)
    {
        try {
            if (img == nullptr) {
                LOG_ERROR("SignalStrength image nullptr");
                return;
                LOG_ERROR("SignalStrength image is nullptr");
                return false;
            }

            /* Skip update if nothing has changed */
            if ((currentTethering == tethering) && (currentStatus == status) && (currentRssiBar == signal.rssiBar)) {
                return false;
            }

            if (tethering == Store::Tethering::On) {
                img->set(signal_none, style::status_bar::imageTypeSpecifier);
                currentTethering = tethering;
            }
            else if (status == Store::Network::Status::RegisteredRoaming) {
                img->set(signalMapRoaming.at(signal.rssiBar), style::status_bar::imageTypeSpecifier);
                currentStatus  = status;
                currentRssiBar = signal.rssiBar;
            }
            else if (status == Store::Network::Status::RegisteredHomeNetwork) {
                img->set(signalMapHomeCon.at(signal.rssiBar), style::status_bar::imageTypeSpecifier);
                currentStatus  = status;
                currentRssiBar = signal.rssiBar;
            }
            else {
                img->set(signal_none, style::status_bar::imageTypeSpecifier);
                currentTethering = tethering;
                currentStatus    = status;
                currentRssiBar   = signal.rssiBar;
            }
            return true;
        }
        catch (const std::exception &exception) {
            LOG_ERROR("Exception while updating signal image: %s", exception.what());
        }

        return false;
    }
} // namespace gui::status_bar

M module-gui/gui/widgets/status-bar/SignalStrengthBar.hpp => module-gui/gui/widgets/status-bar/SignalStrengthBar.hpp +8 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 9,17 9,21 @@ namespace gui
{
    class Image;
}

namespace gui::status_bar
{
    class SignalStrengthBar : public SignalStrengthBase
    {
      public:
        SignalStrengthBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
        void update(const Store::SignalStrength &signal,
                    const Store::Network::Status &status,
                    const Store::Tethering &tethering) override;
        [[nodiscard]] bool update(const Store::SignalStrength &signal,
                                  const Store::Network::Status &status,
                                  const Store::Tethering &tethering) override;

      private:
        Image *img = nullptr;
        Store::RssiBar currentRssiBar        = Store::RssiBar::zero;
        Store::Network::Status currentStatus = Store::Network::Status::NotRegistered;
        Store::Tethering currentTethering    = Store::Tethering::Off;
    };
} // namespace gui::status_bar

M module-gui/gui/widgets/status-bar/SignalStrengthBase.cpp => module-gui/gui/widgets/status-bar/SignalStrengthBase.cpp +3 -2
@@ 1,11 1,12 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "SignalStrengthBase.hpp"

namespace gui::status_bar
{
    SignalStrengthBase::SignalStrengthBase(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
    SignalStrengthBase::SignalStrengthBase(
        Item *parent, std::uint32_t x, std::uint32_t y, std::uint32_t w, std::uint32_t h)
        : StatusBarWidgetBase(parent, x, y, w, h)
    {
        setEdges(RectangleEdge::None);

M module-gui/gui/widgets/status-bar/SignalStrengthBase.hpp => module-gui/gui/widgets/status-bar/SignalStrengthBase.hpp +5 -5
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 12,9 12,9 @@ namespace gui::status_bar
    class SignalStrengthBase : public StatusBarWidgetBase<HBox>
    {
      public:
        SignalStrengthBase(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
        virtual void update(const Store::SignalStrength &signal,
                            const Store::Network::Status &status,
                            const Store::Tethering &tethering) = 0;
        SignalStrengthBase(Item *parent, std::uint32_t x, std::uint32_t y, std::uint32_t w, std::uint32_t h);
        [[nodiscard]] virtual bool update(const Store::SignalStrength &signal,
                                          const Store::Network::Status &status,
                                          const Store::Tethering &tethering) = 0;
    };
} // namespace gui::status_bar

M module-gui/gui/widgets/status-bar/SignalStrengthText.cpp => module-gui/gui/widgets/status-bar/SignalStrengthText.cpp +11 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "SignalStrengthText.hpp"


@@ 9,7 9,8 @@

namespace gui::status_bar
{
    SignalStrengthText::SignalStrengthText(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
    SignalStrengthText::SignalStrengthText(
        Item *parent, std::uint32_t x, std::uint32_t y, std::uint32_t w, std::uint32_t h)
        : SignalStrengthBase(parent, x, y, w, h)
    {
        label = new Label(this, 0, 0, 0, 0);


@@ 22,11 23,17 @@ namespace gui::status_bar
        label->setMaximumSize(style::status_bar::signal::maxX, style::status_bar::height);
    }

    void SignalStrengthText::update(const Store::SignalStrength &signal,
    bool SignalStrengthText::update(const Store::SignalStrength &signal,
                                    [[maybe_unused]] const Store::Network::Status &status,
                                    [[maybe_unused]] const Store::Tethering &tethering)
    {
        /* Skip update if nothing has changed */
        if (currentRssidBm == signal.rssidBm) {
            return false;
        }

        label->setText(utils::to_string(signal.rssidBm) + " dBm");
        currentRssidBm = signal.rssidBm;
        return true;
    }

} // namespace gui::status_bar

M module-gui/gui/widgets/status-bar/SignalStrengthText.hpp => module-gui/gui/widgets/status-bar/SignalStrengthText.hpp +6 -5
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 15,12 15,13 @@ namespace gui::status_bar
    class SignalStrengthText : public SignalStrengthBase
    {
      public:
        SignalStrengthText(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
        void update(const Store::SignalStrength &signal,
                    [[maybe_unused]] const Store::Network::Status &status,
                    [[maybe_unused]] const Store::Tethering &tethering) override;
        SignalStrengthText(Item *parent, std::uint32_t x, std::uint32_t y, std::uint32_t w, std::uint32_t h);
        [[nodiscard]] bool update(const Store::SignalStrength &signal,
                                  [[maybe_unused]] const Store::Network::Status &status,
                                  [[maybe_unused]] const Store::Tethering &tethering) override;

      private:
        Label *label = nullptr;
        signed currentRssidBm = 0;
    };
} // namespace gui::status_bar

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +6 -5
@@ 50,7 50,7 @@
#include <at/UrcCtze.hpp>
#include <at/UrcCusd.hpp>
#include <at/UrcQind.hpp>
#include <at/UrcCpin.hpp> // for Cpin
#include <at/UrcCpin.hpp>
#include <at/response.hpp>
#include <bsp/cellular/bsp_cellular.hpp>
#include <EventStore.hpp>


@@ 156,10 156,11 @@ ServiceCellular::ServiceCellular()
    simTimer = sys::TimerFactory::createSingleShotTimer(
        this, "simTimer", std::chrono::milliseconds{6000}, [this](sys::Timer &) { priv->simCard->handleSimTimer(); });

    csqTimer = sys::TimerFactory::createPeriodicTimer(this, "csqTimer", std::chrono::minutes{15}, [this](sys::Timer &) {
        priv->csqHandler->handleTimerTick();
        csqCounter.clearCounter();
    });
    csqTimer =
        sys::TimerFactory::createPeriodicTimer(this, "csqPollingTimer", std::chrono::minutes{15}, [this](sys::Timer &) {
            priv->csqHandler->handleTimerTick();
            csqCounter.clearCounter();
        });

    priv->ussdHandler->setTimerStartCallback([this]() { ussdTimer.start(); });
    priv->ussdHandler->setTimerStopCallback([this]() { ussdTimer.stop(); });

M module-services/service-cellular/src/CSQHandler.cpp => module-services/service-cellular/src/CSQHandler.cpp +40 -33
@@ 8,56 8,64 @@
#include <ticks.hpp>
#include <chrono>

namespace cellular::service
namespace
{
    constexpr auto urcThreshold     = 4;
    constexpr auto pollModeDuration = std::chrono::minutes{60};

    bool isRssiValid(std::uint32_t csq)
    {
        constexpr auto invalidRssiLow  = 99;
        constexpr auto invalidRssiHigh = 199;
        return ((csq != invalidRssiLow) && (csq != invalidRssiHigh));
    }
} // namespace

namespace cellular::service
{
    void CSQHandler::handleTimerTick()
    {
        if (currentMode == CSQMode::HybridPolling) {
            if (isPollModeTimeElapsed()) {
                LOG_INFO("CSQ poll mode time elapsed.");
                LOG_INFO("CSQ poll mode timer elapsed");
                switchToHybridReportMode();
                return;
            }

            getCSQ();
        }
    }

    void CSQHandler::handleURCCounterMessage(const uint32_t counter)
    void CSQHandler::handleURCCounterMessage(std::uint32_t counter)
    {
        urcCounter = counter;
        if (isTooManyURC() && currentMode == CSQMode::HybridReporting) {
        if (isTooManyURCs() && (currentMode == CSQMode::HybridReporting)) {
            switchToHybridPollMode();
        }
    }

    auto CSQHandler::isTooManyURC() -> bool
    auto CSQHandler::isTooManyURCs() -> bool
    {
        return urcCounter > urcThreshold;
        return (urcCounter > urcThreshold);
    }

    auto CSQHandler::isPollModeTimeElapsed() -> bool
    {
        auto currentTime = cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks());
        auto timeSpentInPollMode =
            currentTime >= switchToPollModeTimestamp
                ? currentTime - switchToPollModeTimestamp
                : std::numeric_limits<TickType_t>::max() - switchToPollModeTimestamp + currentTime;
        return timeSpentInPollMode > std::chrono::duration_cast<std::chrono::milliseconds>(pollTime).count();
        const auto currentTime         = cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks());
        const auto timeSpentInPollMode = utils::computeIncrease(currentTime, switchToPollModeTimestamp);
        return (timeSpentInPollMode >= std::chrono::duration_cast<std::chrono::milliseconds>(pollModeDuration).count());
    }

    void CSQHandler::checkConditionToChangeMode()
    {
        if (currentMode != CSQMode::PermanentReporting) {
            if (not isPhoneLocked || isBluetoothCarKitConnected ||
                Store::Battery::get().state != Store::Battery::State::Discharging) {
            if (!isPhoneLocked || isBluetoothCarKitConnected ||
                (Store::Battery::get().state != Store::Battery::State::Discharging)) {
                switchToPermanentReportMode();
            }
        }
        else {
            if (isPhoneLocked && not isBluetoothCarKitConnected &&
                Store::Battery::get().state == Store::Battery::State::Discharging) {
            if (isPhoneLocked && !isBluetoothCarKitConnected &&
                (Store::Battery::get().state == Store::Battery::State::Discharging)) {
                switchToHybridReportMode();
            }
        }


@@ 65,13 73,13 @@ namespace cellular::service

    bool CSQHandler::switchToPermanentReportMode()
    {
        if (onEnableCsqReporting != nullptr && onEnableCsqReporting()) {
        if ((onEnableCsqReporting != nullptr) && onEnableCsqReporting()) {
            currentMode = CSQMode::PermanentReporting;
            LOG_INFO("Switch to permanent report mode.");
            LOG_INFO("Switch to permanent report mode");
            return true;
        }

        LOG_ERROR("Failed to switch to CSQ permanent report mode! Retry!");
        LOG_ERROR("Failed to switch to CSQ permanent report mode, retrying");
        if (onRetrySwitchMode != nullptr) {
            onRetrySwitchMode(CSQMode::PermanentReporting);
        }


@@ 80,13 88,13 @@ namespace cellular::service

    bool CSQHandler::switchToHybridReportMode()
    {
        if (onEnableCsqReporting != nullptr && onEnableCsqReporting()) {
        if ((onEnableCsqReporting != nullptr) && onEnableCsqReporting()) {
            currentMode = CSQMode::HybridReporting;
            LOG_INFO("Switch to hybrid report mode.");
            LOG_INFO("Switching to hybrid report mode");
            return true;
        }

        LOG_ERROR("Failed to switch to CSQ hybrid report mode! Retry!");
        LOG_ERROR("Failed to switch to CSQ hybrid report mode, retrying");
        if (onRetrySwitchMode != nullptr) {
            onRetrySwitchMode(CSQMode::HybridReporting);
        }


@@ 95,14 103,14 @@ namespace cellular::service

    bool CSQHandler::switchToHybridPollMode()
    {
        if (onDisableCsqReporting != nullptr && onDisableCsqReporting()) {
        if ((onDisableCsqReporting != nullptr) && onDisableCsqReporting()) {
            currentMode               = CSQMode::HybridPolling;
            switchToPollModeTimestamp = cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks());
            LOG_INFO("Too many signal strength updates, switch to hybrid poll mode.");
            LOG_INFO("Too many signal strength updates, switching to hybrid poll mode");
            return true;
        }

        LOG_ERROR("Failed to switch to CSQ hybrid poll mode! Retry!");
        LOG_ERROR("Failed to switch to CSQ hybrid poll mode, retrying");
        if (onRetrySwitchMode != nullptr) {
            onRetrySwitchMode(CSQMode::HybridPolling);
        }


@@ 112,17 120,17 @@ namespace cellular::service
    bool CSQHandler::getCSQ()
    {
        if (onGetCsq != nullptr) {
            if (auto result = onGetCsq(); result.has_value()) {
                auto csq = result.value();
                if (csq.csq != invalid_rssi_low && csq.csq != invalid_rssi_high) {
                    LOG_INFO("Propagate valid CSQ");
            if (const auto &result = onGetCsq(); result.has_value()) {
                const auto &csq = result.value();
                if (isRssiValid(csq.csq)) {
                    LOG_INFO("Propagating valid CSQ");
                    if (onPropagateCSQ != nullptr) {
                        onPropagateCSQ(csq.csq);
                        return true;
                    }
                }
                else {
                    LOG_INFO("Invalid CSQ, notify service antenna");
                    LOG_INFO("Invalid CSQ, notifying service antenna");
                    if (onInvalidCSQ != nullptr) {
                        onInvalidCSQ();
                        return true;


@@ 131,7 139,7 @@ namespace cellular::service
            }
        }

        LOG_ERROR("Failed to get CSQ! Retry!");
        LOG_ERROR("Failed to get CSQ, retrying");
        if (onRetryGetCSQ != nullptr) {
            onRetryGetCSQ();
        }


@@ 157,5 165,4 @@ namespace cellular::service
    {
        isBluetoothCarKitConnected = false;
    }

} // namespace cellular::service

M module-services/service-cellular/src/CSQHandler.hpp => module-services/service-cellular/src/CSQHandler.hpp +5 -12
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 12,13 12,6 @@

namespace cellular::service
{

    constexpr auto urcThreshold = 4;
    constexpr auto pollTime     = std::chrono::minutes{60};

    static const auto invalid_rssi_low  = 99;
    static const auto invalid_rssi_high = 199;

    enum class CSQMode
    {
        PermanentReporting,


@@ 30,12 23,12 @@ namespace cellular::service
    {
      public:
        void handleTimerTick();
        void handleURCCounterMessage(const uint32_t counter);
        void handleURCCounterMessage(std::uint32_t counter);

        std::function<bool()> onEnableCsqReporting;
        std::function<bool()> onDisableCsqReporting;
        std::function<std::optional<at::result::CSQ>()> onGetCsq;
        std::function<void(uint32_t)> onPropagateCSQ;
        std::function<void(std::uint32_t)> onPropagateCSQ;
        std::function<void()> onInvalidCSQ;

        std::function<void(CSQMode)> onRetrySwitchMode;


@@ 52,7 45,7 @@ namespace cellular::service
        bool getCSQ();

      private:
        uint32_t urcCounter = 0;
        std::uint32_t urcCounter = 0;
        CSQMode currentMode = CSQMode::HybridReporting;
        TickType_t switchToPollModeTimestamp{0};



@@ 61,6 54,6 @@ namespace cellular::service
        bool isBluetoothCarKitConnected{false};

        auto isPollModeTimeElapsed() -> bool;
        auto isTooManyURC() -> bool;
        auto isTooManyURCs() -> bool;
    };
} // namespace cellular::service

M module-utils/utility/Utils.hpp => module-utils/utility/Utils.hpp +1 -3
@@ 271,9 271,7 @@ namespace utils
        if (currentCount >= lastCount) {
            return currentCount - lastCount;
        }
        else {
            return std::numeric_limits<T>::max() - lastCount + currentCount;
        }
        return std::numeric_limits<T>::max() - lastCount + currentCount;
    }

    static inline void findAndReplaceAll(std::string &data,

M pure_changelog.md => pure_changelog.md +1 -0
@@ 11,6 11,7 @@
* Disabled USB MTP protocol
* Changed UI flow on discharged device window.
* Changed VoLTE label from 'beta' to 'experimental'.
* Changed signal strength update mechanism to avoid unnecessary screen refreshes.

### Fixed