// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "BatteryLevelCheck.hpp" #include "service-evtmgr/BatteryMessages.hpp" #include "system/Constants.hpp" #include #include #include #define BOOST_SML_CFG_DISABLE_MIN_SIZE // GCC10 fix #include namespace battery_level_check { namespace { unsigned int batteryLevelCritical = 10; constexpr auto batteryShutdownLevel = 5; sys::Service *parentService = nullptr; std::shared_ptr settings = nullptr; namespace sml = boost::sml; // events struct initialLevelCheck {}; struct criticalLevelCheck {}; // guards struct isNormal { bool operator()() const { return Store::Battery::get().level >= batteryLevelCritical; } } isNormal; struct isCriticalNotCharging { bool operator()() const { return Store::Battery::get().level < batteryLevelCritical && Store::Battery::get().state != Store::Battery::State::Charging && Store::Battery::get().state != Store::Battery::State::ChargingDone; } } isCriticalNotCharging; struct isCriticalCharging { bool operator()() const { return Store::Battery::get().level < batteryLevelCritical && (Store::Battery::get().state == Store::Battery::State::Charging || Store::Battery::get().state == Store::Battery::State::ChargingDone); } } isCriticalCharging; struct isShutdown { bool operator()() const { return Store::Battery::get().level < batteryShutdownLevel; } } isShutdown; // actions struct setCriticalNotCharging { void operator()() { Store::Battery::modify().levelState = Store::Battery::LevelState::CriticalNotCharging; } } setCriticalNotCharging; struct setCriticalCharging { void operator()() { Store::Battery::modify().levelState = Store::Battery::LevelState::CriticalCharging; } } setCriticalCharging; struct setNormal { void operator()() { Store::Battery::modify().levelState = Store::Battery::LevelState::Normal; } } setNormal; struct setShutdown { void operator()() { Store::Battery::modify().levelState = Store::Battery::LevelState::Shutdown; } } setShutdown; struct sendStateChange { void operator()() { auto stateChangeMessage = std::make_shared(); parentService->bus.sendUnicast(std::move(stateChangeMessage), service::name::system_manager); } } sendStateChange; struct StateMachine { auto operator()() const { using namespace sml; // clang-format off return make_transition_table( *"InitialCheck"_s + event [ isCriticalNotCharging && !isShutdown ] / setCriticalNotCharging = "LevelCriticalNotCharging"_s, "InitialCheck"_s + event [ isCriticalNotCharging && isShutdown ] / setShutdown = "Shutdown"_s, "InitialCheck"_s + event [ isCriticalCharging ] / setCriticalCharging = "LevelCriticalCharging"_s, "InitialCheck"_s + event [ isNormal ] / setNormal = "LevelNormal"_s, "LevelNormal"_s + event [ isCriticalNotCharging && !isShutdown ] / (setCriticalNotCharging, sendStateChange) = "LevelCriticalNotCharging"_s, "LevelNormal"_s + event [ isCriticalNotCharging && isShutdown ] / (setShutdown, sendStateChange) = "Shutdown"_s, "LevelNormal"_s + event [ isCriticalCharging ] / (setCriticalCharging, sendStateChange) = "LevelCriticalCharging"_s, "LevelCriticalNotCharging"_s + event [ isNormal ] / (setNormal, sendStateChange) = "LevelNormal"_s, "LevelCriticalNotCharging"_s + event [ isCriticalCharging ] / (setCriticalCharging, sendStateChange) = "LevelCriticalCharging"_s, "LevelCriticalNotCharging"_s + event [ isShutdown ] / (setShutdown, sendStateChange) = "Shutdown"_s, "LevelCriticalCharging"_s + event [ isCriticalNotCharging && !isShutdown ] / (setCriticalNotCharging, sendStateChange) = "LevelCriticalNotCharging"_s, "LevelCriticalCharging"_s + event [ isNormal ] / (setNormal, sendStateChange) = "LevelNormal"_s, "LevelCriticalCharging"_s + event [ isCriticalNotCharging && isShutdown ] / (setShutdown, sendStateChange) = "Shutdown"_s ); // clang-format on } }; std::unique_ptr> sm; } // namespace void init(sys::Service *service, std::shared_ptr &setts) { sm = std::make_unique>(); parentService = service; settings = setts; settings->registerValueChange( settings::Battery::batteryCriticalLevel, [&](const std::string &value) { batteryLevelCritical = utils::getNumericValue(value); }, settings::SettingsScope::Global); sm->process_event(initialLevelCheck{}); } void deinit() { settings->unregisterValueChange(settings::Battery::batteryCriticalLevel, settings::SettingsScope::Global); settings.reset(); sm.reset(); } void checkBatteryLevel() { sm->process_event(criticalLevelCheck{}); } void setBatteryCriticalLevel(unsigned int level) { batteryLevelCritical = level; settings->setValue( settings::Battery::batteryCriticalLevel, utils::to_string(level), settings::SettingsScope::Global); checkBatteryLevel(); } } // namespace battery_level_check