diff options
author | James Feist <james.feist@linux.intel.com> | 2019-07-10 11:59:57 -0700 |
---|---|---|
committer | Patrick Venture <venture@google.com> | 2019-07-16 14:47:18 +0000 |
commit | 5ec202704d9952674ff91e5741ac00581733f73e (patch) | |
tree | f5eec4acc7dbe357e9b221982cc7cc223c4d9d24 | |
parent | fc2e803f5d9256944e18c7c878a441606b1f121c (diff) | |
download | phosphor-pid-control-5ec202704d9952674ff91e5741ac00581733f73e.tar.gz phosphor-pid-control-5ec202704d9952674ff91e5741ac00581733f73e.zip |
Allow setting setpoint based on dynamic thresholds
As we allow dynamic thresholds in dbus-sensors to track
the t-control of dimms etc, we want to be able to set a
setpoint based on a offset from a threshold. This adds
the ability to create a "SetPointOffset" that is a
threshold of the given sensor. For instance a "SetPointOffset"
of "WarningHigh" would get the sensors "WarningHigh" value
then add the "SetPoint" value to it (commonly negative for
WarningHigh/CriticalHigh).
Tested: Turned on debug print and saw correct setpoint being
loaded into config
Change-Id: Idb9760ea5a66347f24573fb26937f8f278834a19
Signed-off-by: James Feist <james.feist@linux.intel.com>
-rw-r--r-- | dbus/dbusconfiguration.cpp | 184 | ||||
-rw-r--r-- | util.hpp | 29 |
2 files changed, 165 insertions, 48 deletions
diff --git a/dbus/dbusconfiguration.cpp b/dbus/dbusconfiguration.cpp index 7641eaf..e68c852 100644 --- a/dbus/dbusconfiguration.cpp +++ b/dbus/dbusconfiguration.cpp @@ -50,9 +50,24 @@ constexpr const char* thermalControlIface = constexpr const char* sensorInterface = "xyz.openbmc_project.Sensor.Value"; constexpr const char* pwmInterface = "xyz.openbmc_project.Control.FanPwm"; +namespace thresholds +{ +constexpr const char* warningInterface = + "xyz.openbmc_project.Sensor.Threshold.Warning"; +constexpr const char* criticalInterface = + "xyz.openbmc_project.Sensor.Threshold.Critical"; +const std::array<const char*, 4> types = {"CriticalLow", "CriticalHigh", + "WarningLow", "WarningHigh"}; + +} // namespace thresholds + namespace dbus_configuration { +using DbusVariantType = + std::variant<uint64_t, int64_t, double, std::string, + std::vector<std::string>, std::vector<double>>; + bool findSensors(const std::unordered_map<std::string, std::string>& sensors, const std::string& search, std::vector<std::pair<std::string, std::string>>& matches) @@ -276,6 +291,97 @@ void createMatches(sdbusplus::bus::bus& bus, boost::asio::steady_timer& timer) eventHandler, &timer); } +void populatePidInfo( + sdbusplus::bus::bus& bus, + const std::unordered_map<std::string, DbusVariantType>& base, + struct conf::ControllerInfo& info, const std::string* thresholdProperty) +{ + + info.type = std::get<std::string>(base.at("Class")); + + if (info.type == "fan") + { + info.setpoint = 0; + } + else + { + info.setpoint = + std::visit(VariantToDoubleVisitor(), base.at("SetPoint")); + } + + if (thresholdProperty != nullptr) + { + std::string interface; + if (*thresholdProperty == "WarningHigh" || + *thresholdProperty == "WarningLow") + { + interface = thresholds::warningInterface; + } + else + { + interface = thresholds::criticalInterface; + } + const std::string& path = sensorConfig[info.inputs.front()].readPath; + + DbusHelper helper; + std::string service = helper.getService(bus, interface, path); + double reading = 0; + try + { + helper.getProperty(bus, service, path, interface, + *thresholdProperty, reading); + } + catch (const sdbusplus::exception::SdBusError& ex) + { + // unsupported threshold, leaving reading at 0 + } + + info.setpoint += reading; + } + + info.pidInfo.ts = 1.0; // currently unused + info.pidInfo.proportionalCoeff = + std::visit(VariantToDoubleVisitor(), base.at("PCoefficient")); + info.pidInfo.integralCoeff = + std::visit(VariantToDoubleVisitor(), base.at("ICoefficient")); + info.pidInfo.feedFwdOffset = + std::visit(VariantToDoubleVisitor(), base.at("FFOffCoefficient")); + info.pidInfo.feedFwdGain = + std::visit(VariantToDoubleVisitor(), base.at("FFGainCoefficient")); + info.pidInfo.integralLimit.max = + std::visit(VariantToDoubleVisitor(), base.at("ILimitMax")); + info.pidInfo.integralLimit.min = + std::visit(VariantToDoubleVisitor(), base.at("ILimitMin")); + info.pidInfo.outLim.max = + std::visit(VariantToDoubleVisitor(), base.at("OutLimitMax")); + info.pidInfo.outLim.min = + std::visit(VariantToDoubleVisitor(), base.at("OutLimitMin")); + info.pidInfo.slewNeg = + std::visit(VariantToDoubleVisitor(), base.at("SlewNeg")); + info.pidInfo.slewPos = + std::visit(VariantToDoubleVisitor(), base.at("SlewPos")); + double negativeHysteresis = 0; + double positiveHysteresis = 0; + + auto findNeg = base.find("NegativeHysteresis"); + auto findPos = base.find("PositiveHysteresis"); + + if (findNeg != base.end()) + { + negativeHysteresis = + std::visit(VariantToDoubleVisitor(), findNeg->second); + } + + if (findPos != base.end()) + { + positiveHysteresis = + std::visit(VariantToDoubleVisitor(), findPos->second); + } + + info.pidInfo.negativeHysteresis = negativeHysteresis; + info.pidInfo.positiveHysteresis = positiveHysteresis; +} + bool init(sdbusplus::bus::bus& bus, boost::asio::steady_timer& timer) { @@ -558,61 +664,43 @@ bool init(sdbusplus::bus::bus& bus, boost::asio::steady_timer& timer) continue; } - struct conf::ControllerInfo& info = - conf[std::get<std::string>(base.at("Name"))]; - info.inputs = std::move(inputs); + std::string offsetType; - info.type = std::get<std::string>(base.at("Class")); - // todo: auto generation yaml -> c script seems to discard this - // value for fans, verify this is okay - if (info.type == "fan") - { - info.setpoint = 0; - } - else + // SetPointOffset is a threshold value to pull from the sensor + // to apply an offset. For upper thresholds this means the + // setpoint is usually negative. + auto findSetpointOffset = base.find("SetPointOffset"); + if (findSetpointOffset != base.end()) { - info.setpoint = std::visit(VariantToDoubleVisitor(), - base.at("SetPoint")); + offsetType = + std::get<std::string>(findSetpointOffset->second); + if (std::find(thresholds::types.begin(), + thresholds::types.end(), + offsetType) == thresholds::types.end()) + { + throw std::runtime_error("Unsupported type: " + + offsetType); + } } - info.pidInfo.ts = 1.0; // currently unused - info.pidInfo.proportionalCoeff = std::visit( - VariantToDoubleVisitor(), base.at("PCoefficient")); - info.pidInfo.integralCoeff = std::visit( - VariantToDoubleVisitor(), base.at("ICoefficient")); - info.pidInfo.feedFwdOffset = std::visit( - VariantToDoubleVisitor(), base.at("FFOffCoefficient")); - info.pidInfo.feedFwdGain = std::visit( - VariantToDoubleVisitor(), base.at("FFGainCoefficient")); - info.pidInfo.integralLimit.max = - std::visit(VariantToDoubleVisitor(), base.at("ILimitMax")); - info.pidInfo.integralLimit.min = - std::visit(VariantToDoubleVisitor(), base.at("ILimitMin")); - info.pidInfo.outLim.max = std::visit(VariantToDoubleVisitor(), - base.at("OutLimitMax")); - info.pidInfo.outLim.min = std::visit(VariantToDoubleVisitor(), - base.at("OutLimitMin")); - info.pidInfo.slewNeg = - std::visit(VariantToDoubleVisitor(), base.at("SlewNeg")); - info.pidInfo.slewPos = - std::visit(VariantToDoubleVisitor(), base.at("SlewPos")); - double negativeHysteresis = 0; - double positiveHysteresis = 0; - - auto findNeg = base.find("NegativeHysteresis"); - auto findPos = base.find("PositiveHysteresis"); - if (findNeg != base.end()) + + if (offsetType.empty()) { - negativeHysteresis = - std::visit(VariantToDoubleVisitor(), findNeg->second); + struct conf::ControllerInfo& info = + conf[std::get<std::string>(base.at("Name"))]; + info.inputs = std::move(inputs); + populatePidInfo(bus, base, info, nullptr); } - - if (findPos != base.end()) + else { - positiveHysteresis = - std::visit(VariantToDoubleVisitor(), findPos->second); + // we have to split up the inputs, as in practice t-control + // values will differ, making setpoints differ + for (const std::string& input : inputs) + { + struct conf::ControllerInfo& info = conf[input]; + info.inputs.emplace_back(input); + populatePidInfo(bus, base, info, &offsetType); + } } - info.pidInfo.negativeHysteresis = negativeHysteresis; - info.pidInfo.positiveHysteresis = positiveHysteresis; } } auto findStepwise = @@ -3,6 +3,7 @@ #include "pid/ec/pid.hpp" #include <limits> +#include <phosphor-logging/log.hpp> #include <sdbusplus/bus.hpp> #include <string> @@ -117,6 +118,34 @@ class DbusHelper : public DbusHelperInterface bool thresholdsAsserted(sdbusplus::bus::bus& bus, const std::string& service, const std::string& path) override; + + template <typename T> + void getProperty(sdbusplus::bus::bus& bus, const std::string& service, + const std::string& path, const std::string& interface, + const std::string& propertyName, T& prop) + { + namespace log = phosphor::logging; + + auto msg = bus.new_method_call(service.c_str(), path.c_str(), + propertiesintf.c_str(), "Get"); + + msg.append(interface, propertyName); + + std::variant<T> result; + try + { + auto valueResponseMsg = bus.call(msg); + valueResponseMsg.read(result); + } + catch (const sdbusplus::exception::SdBusError& ex) + { + log::log<log::level::ERR>("Get Property Failed", + log::entry("WHAT=%s", ex.what())); + throw; + } + + prop = std::get<T>(result); + } }; std::string getSensorPath(const std::string& type, const std::string& id); |