#pragma once #include "dbusUtils.hpp" #include #include #include #include #include #include #include #include const constexpr char* entityManagerBusName = "xyz.openbmc_project.EntityManager"; namespace phosphor::virtual_sensor { template using ServerObject = typename sdbusplus::server::object_t; namespace threshold_ns = sdbusplus::xyz::openbmc_project::Sensor::Threshold::server; using Unit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit; using CriticalObject = ServerObject; using WarningObject = ServerObject; using SoftShutdownObject = ServerObject; using HardShutdownObject = ServerObject; using PerformanceLossObject = ServerObject; template struct Threshold; struct Hysteresis { double highHysteresis; double lowHysteresis; auto getHighHysteresis() { return this->highHysteresis; } auto getLowHysteresis() { return this->lowHysteresis; } auto setHighHysteresis(double value) { this->highHysteresis = value; } auto setLowHysteresis(double value) { this->lowHysteresis = value; } }; template auto tryCommit(const std::string& objPath, double value, Unit unit, double thresholdValue) -> std::optional { try { return lg2::commit( error("SENSOR_NAME", objPath, "READING_VALUE", value, "UNITS", unit, "THRESHOLD_VALUE", thresholdValue)); } catch (std::exception&) { lg2::error( "Failed creating a threshold log entry for {SENSOR} with value {VALUE}", "SENSOR", objPath, "VALUE", value); return std::nullopt; } } static inline void tryResolve( std::optional& log) { if (log) { try { lg2::resolve(*log); } catch (std::exception&) { lg2::error("Failed to resolve: {LOG}", "LOG", *log); } log.reset(); } } template <> struct Threshold : public WarningObject, public Hysteresis { static constexpr auto name = "Warning"; using WarningObject::WarningObject; using ReadingAboveUpperWarningThreshold = sdbusplus::error::xyz:: openbmc_project::sensor::Threshold::ReadingAboveUpperWarningThreshold; using ReadingBelowLowerWarningThreshold = sdbusplus::error::xyz:: openbmc_project::sensor::Threshold::ReadingBelowLowerWarningThreshold; /** @brief sdbusplus bus client connection. */ sdbusplus::bus_t& bus; std::string objPath; Unit units; /** @brief Virtual sensor path/interface in entityManagerDbus. * This 3 value is used to set thresholds */ std::string entityPath; std::string entityInterfaceHigh; std::string entityInterfaceLow; std::optional assertedHighLog; std::optional assertedLowLog; /** @brief Constructor to put object onto bus at a dbus path. * @param[in] bus - Bus to attach to. * @param[in] path - Path to attach at. * @param[in] units - units */ Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) : WarningObject(bus, path), bus(bus), objPath(std::string(path)), units(units) {} auto high() { return WarningObject::warningHigh(); } auto low() { return WarningObject::warningLow(); } template auto alarmHigh(Args... args) { return warningAlarmHigh(std::forward(args)...); } template auto alarmLow(Args... args) { return warningAlarmLow(std::forward(args)...); } template auto alarmHighSignalAsserted(V value) { assertedHighLog = tryCommit( objPath, value, units, high()); return warningHighAlarmAsserted(value); } template auto alarmHighSignalDeasserted(Args... args) { tryResolve(assertedHighLog); return warningHighAlarmDeasserted(std::forward(args)...); } template auto alarmLowSignalAsserted(V value) { assertedLowLog = tryCommit( objPath, value, units, low()); return warningLowAlarmAsserted(value); } template auto alarmLowSignalDeasserted(Args... args) { tryResolve(assertedLowLog); return warningLowAlarmDeasserted(std::forward(args)...); } /** @brief Set value of WarningHigh */ virtual double warningHigh(double value) { if (!entityPath.empty() && !entityInterfaceHigh.empty()) { // persistThreshold setDbusProperty(bus, entityManagerBusName, entityPath, entityInterfaceHigh, "Value", value); } return WarningObject::warningHigh(value); } /** @brief Set value of WarningLow */ virtual double warningLow(double value) { if (!entityPath.empty() && !entityInterfaceLow.empty()) { // persistThreshold setDbusProperty(bus, entityManagerBusName, entityPath, entityInterfaceLow, "Value", value); } return WarningObject::warningLow(value); } /** @brief Set the entitymanager interface corresponding to virtualsensor * warningLow */ void setEntityInterfaceLow(const std::string& interfaceLow) { entityInterfaceLow = interfaceLow; } /** @brief Set the entitymanager interface corresponding to virtualsensor * warningHigh */ void setEntityInterfaceHigh(const std::string& interfaceHigh) { entityInterfaceHigh = interfaceHigh; } /** @brief Set the entitymanager path corresponding to virtualsensor warning */ void setEntityPath(const std::string& path) { entityPath = path; } }; template <> struct Threshold : public CriticalObject, public Hysteresis { static constexpr auto name = "Critical"; /** @brief sdbusplus bus client connection. */ sdbusplus::bus_t& bus; std::string objPath; Unit units; /** @brief Virtual sensor path/interface in entityManagerDbus. * This 3 value is used to set thresholds */ std::string entityPath; std::string entityInterfaceHigh; std::string entityInterfaceLow; std::optional assertedHighLog; std::optional assertedLowLog; using CriticalObject::CriticalObject; using ReadingAboveUpperCriticalThreshold = sdbusplus::error::xyz:: openbmc_project::sensor::Threshold::ReadingAboveUpperCriticalThreshold; using ReadingBelowLowerCriticalThreshold = sdbusplus::error::xyz:: openbmc_project::sensor::Threshold::ReadingBelowLowerCriticalThreshold; /** @brief Constructor to put object onto bus at a dbus path. * @param[in] bus - Bus to attach to. * @param[in] path - Path to attach at. * @param[in] units - units */ Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) : CriticalObject(bus, path), bus(bus), objPath(std::string(path)), units(units) {} auto high() { return CriticalObject::criticalHigh(); } auto low() { return CriticalObject::criticalLow(); } template auto alarmHigh(Args... args) { return criticalAlarmHigh(std::forward(args)...); } template auto alarmLow(Args... args) { return criticalAlarmLow(std::forward(args)...); } template auto alarmHighSignalAsserted(V value) { assertedHighLog = tryCommit( objPath, value, units, high()); return criticalHighAlarmAsserted(value); } template auto alarmHighSignalDeasserted(Args... args) { tryResolve(assertedHighLog); return criticalHighAlarmDeasserted(std::forward(args)...); } template auto alarmLowSignalAsserted(V value) { assertedLowLog = tryCommit( objPath, value, units, low()); return criticalLowAlarmAsserted(value); } template auto alarmLowSignalDeasserted(Args... args) { tryResolve(assertedLowLog); return criticalLowAlarmDeasserted(std::forward(args)...); } /** @brief Set value of CriticalHigh */ virtual double criticalHigh(double value) { // persistThreshold if (!entityPath.empty() && !entityInterfaceHigh.empty()) { setDbusProperty(bus, entityManagerBusName, entityPath, entityInterfaceHigh, "Value", value); } return CriticalObject::criticalHigh(value); } /** @brief Set value of CriticalLow */ virtual double criticalLow(double value) { if (!entityPath.empty() && !entityInterfaceLow.empty()) { setDbusProperty(bus, entityManagerBusName, entityPath, entityInterfaceLow, "Value", value); } return CriticalObject::criticalLow(value); } /** @brief Set the entitymanager interface corresponding to virtualsensor * criticalLow */ void setEntityInterfaceLow(const std::string& interfaceLow) { entityInterfaceLow = interfaceLow; } /** @brief Set the entitymanager interface corresponding to virtualsensor * criticalLow */ void setEntityInterfaceHigh(const std::string& interfaceHigh) { entityInterfaceHigh = interfaceHigh; } /** @brief Set the entitymanager path corresponding to virtualsensor warning */ void setEntityPath(const std::string& path) { entityPath = path; } }; template <> struct Threshold : public SoftShutdownObject, public Hysteresis { static constexpr auto name = "SoftShutdown"; /** @brief sdbusplus bus client connection. */ sdbusplus::bus_t& bus; std::string objPath; Unit units; using SoftShutdownObject::SoftShutdownObject; using ReadingAboveUpperSoftShutdownThreshold = sdbusplus::error::xyz::openbmc_project::sensor::Threshold:: ReadingAboveUpperSoftShutdownThreshold; using ReadingBelowLowerSoftShutdownThreshold = sdbusplus::error::xyz::openbmc_project::sensor::Threshold:: ReadingBelowLowerSoftShutdownThreshold; std::optional assertedHighLog; std::optional assertedLowLog; /** @brief Constructor to put object onto bus at a dbus path. * @param[in] bus - Bus to attach to. * @param[in] path - Path to attach at. * @param[in] units - units */ Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) : SoftShutdownObject(bus, path), bus(bus), objPath(std::string(path)), units(units) {} auto high() { return softShutdownHigh(); } auto low() { return softShutdownLow(); } template auto alarmHigh(Args... args) { return softShutdownAlarmHigh(std::forward(args)...); } template auto alarmLow(Args... args) { return softShutdownAlarmLow(std::forward(args)...); } template auto alarmHighSignalAsserted(V value) { assertedHighLog = tryCommit( objPath, value, units, high()); return softShutdownHighAlarmAsserted(value); } template auto alarmHighSignalDeasserted(Args... args) { tryResolve(assertedHighLog); return softShutdownHighAlarmDeasserted(std::forward(args)...); } template auto alarmLowSignalAsserted(V value) { assertedLowLog = tryCommit( objPath, value, units, low()); return softShutdownLowAlarmAsserted(value); } template auto alarmLowSignalDeasserted(Args... args) { tryResolve(assertedLowLog); return softShutdownLowAlarmDeasserted(std::forward(args)...); } }; template <> struct Threshold : public HardShutdownObject, public Hysteresis { static constexpr auto name = "HardShutdown"; /** @brief sdbusplus bus client connection. */ sdbusplus::bus_t& bus; std::string objPath; Unit units; using HardShutdownObject::HardShutdownObject; using ReadingAboveUpperHardShutdownThreshold = sdbusplus::error::xyz::openbmc_project::sensor::Threshold:: ReadingAboveUpperHardShutdownThreshold; using ReadingBelowLowerHardShutdownThreshold = sdbusplus::error::xyz::openbmc_project::sensor::Threshold:: ReadingBelowLowerHardShutdownThreshold; std::optional assertedHighLog; std::optional assertedLowLog; /** @brief Constructor to put object onto bus at a dbus path. * @param[in] bus - Bus to attach to. * @param[in] path - Path to attach at. * @param[in] units - units */ Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) : HardShutdownObject(bus, path), bus(bus), objPath(std::string(path)), units(units) {} auto high() { return hardShutdownHigh(); } auto low() { return hardShutdownLow(); } template auto alarmHigh(Args... args) { return hardShutdownAlarmHigh(std::forward(args)...); } template auto alarmLow(Args... args) { return hardShutdownAlarmLow(std::forward(args)...); } template auto alarmHighSignalAsserted(V value) { assertedHighLog = tryCommit( objPath, value, units, high()); return hardShutdownHighAlarmAsserted(value); } template auto alarmHighSignalDeasserted(Args... args) { tryResolve(assertedHighLog); return hardShutdownHighAlarmDeasserted(std::forward(args)...); } template auto alarmLowSignalAsserted(V value) { assertedLowLog = tryCommit( objPath, value, units, low()); return hardShutdownLowAlarmAsserted(value); } template auto alarmLowSignalDeasserted(Args... args) { tryResolve(assertedLowLog); return hardShutdownLowAlarmDeasserted(std::forward(args)...); } }; template <> struct Threshold : public PerformanceLossObject, public Hysteresis { static constexpr auto name = "PerformanceLoss"; /** @brief sdbusplus bus client connection. */ sdbusplus::bus_t& bus; std::string objPath; Unit units; using PerformanceLossObject::PerformanceLossObject; using ReadingAboveUpperPerformanceLossThreshold = sdbusplus::error::xyz::openbmc_project::sensor::Threshold:: ReadingAboveUpperPerformanceLossThreshold; using ReadingBelowLowerPerformanceLossThreshold = sdbusplus::error::xyz::openbmc_project::sensor::Threshold:: ReadingBelowLowerPerformanceLossThreshold; double performanceLossHighHysteresis; double performanceLossLowHysteresis; std::optional assertedHighLog; std::optional assertedLowLog; /** @brief Constructor to put object onto bus at a dbus path. * @param[in] bus - Bus to attach to. * @param[in] path - Path to attach at. * @param[in] units - units */ Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) : PerformanceLossObject(bus, path), bus(bus), objPath(std::string(path)), units(units) {} auto high() { return performanceLossHigh(); } auto low() { return performanceLossLow(); } template auto alarmHigh(Args... args) { return performanceLossAlarmHigh(std::forward(args)...); } template auto alarmLow(Args... args) { return performanceLossAlarmLow(std::forward(args)...); } template auto alarmHighSignalAsserted(V value) { assertedHighLog = tryCommit( objPath, value, units, high()); return performanceLossHighAlarmAsserted(value); } template auto alarmHighSignalDeasserted(Args... args) { tryResolve(assertedHighLog); return performanceLossHighAlarmDeasserted(std::forward(args)...); } template auto alarmLowSignalAsserted(V value) { assertedLowLog = tryCommit( objPath, value, units, low()); return performanceLossLowAlarmAsserted(value); } template auto alarmLowSignalDeasserted(Args... args) { tryResolve(assertedLowLog); return performanceLossLowAlarmDeasserted(std::forward(args)...); } }; } // namespace phosphor::virtual_sensor