xref: /openbmc/phosphor-pid-control/util.hpp (revision cdd61349)
1 #pragma once
2 
3 #include "pid/ec/pid.hpp"
4 
5 #include <phosphor-logging/log.hpp>
6 #include <sdbusplus/bus.hpp>
7 
8 #include <limits>
9 #include <string>
10 
11 void tryRestartControlLoops(void);
12 
13 /*
14  * Given a configuration structure, fill out the information we use within the
15  * PID loop.
16  */
17 void initializePIDStruct(ec::pid_info_t* info, const ec::pidinfo& initial);
18 
19 void dumpPIDStruct(ec::pid_info_t* info);
20 
21 struct SensorProperties
22 {
23     int64_t scale;
24     double value;
25     double min;
26     double max;
27     std::string unit;
28 };
29 
30 struct SensorThresholds
31 {
32     double lowerThreshold = std::numeric_limits<double>::quiet_NaN();
33     double upperThreshold = std::numeric_limits<double>::quiet_NaN();
34 };
35 
36 const std::string sensorintf = "xyz.openbmc_project.Sensor.Value";
37 const std::string criticalThreshInf =
38     "xyz.openbmc_project.Sensor.Threshold.Critical";
39 const std::string propertiesintf = "org.freedesktop.DBus.Properties";
40 
41 class DbusHelperInterface
42 {
43   public:
44     virtual ~DbusHelperInterface() = default;
45 
46     /** @brief Get the service providing the interface for the path.
47      *
48      * @warning Throws exception on dbus failure.
49      */
50     virtual std::string getService(sdbusplus::bus::bus& bus,
51                                    const std::string& intf,
52                                    const std::string& path) = 0;
53 
54     /** @brief Get all Sensor.Value properties for a service and path.
55      *
56      * @param[in] bus - A bus to use for the call.
57      * @param[in] service - The service providing the interface.
58      * @param[in] path - The dbus path.
59      * @param[out] prop - A pointer to a properties struct to fill out.
60      *
61      * @warning Throws exception on dbus failure.
62      */
63     virtual void getProperties(sdbusplus::bus::bus& bus,
64                                const std::string& service,
65                                const std::string& path,
66                                struct SensorProperties* prop) = 0;
67 
68     /** @brief Get Critical Threshold current assert status
69      *
70      * @param[in] bus - A bus to use for the call.
71      * @param[in] service - The service providing the interface.
72      * @param[in] path - The dbus path.
73      */
74     virtual bool thresholdsAsserted(sdbusplus::bus::bus& bus,
75                                     const std::string& service,
76                                     const std::string& path) = 0;
77 };
78 
79 class DbusHelper : public DbusHelperInterface
80 {
81   public:
82     DbusHelper() = default;
83     ~DbusHelper() = default;
84     DbusHelper(const DbusHelper&) = default;
85     DbusHelper& operator=(const DbusHelper&) = default;
86     DbusHelper(DbusHelper&&) = default;
87     DbusHelper& operator=(DbusHelper&&) = default;
88 
89     std::string getService(sdbusplus::bus::bus& bus, const std::string& intf,
90                            const std::string& path) override;
91 
92     void getProperties(sdbusplus::bus::bus& bus, const std::string& service,
93                        const std::string& path,
94                        struct SensorProperties* prop) override;
95 
96     bool thresholdsAsserted(sdbusplus::bus::bus& bus,
97                             const std::string& service,
98                             const std::string& path) override;
99 
100     template <typename T>
101     void getProperty(sdbusplus::bus::bus& bus, const std::string& service,
102                      const std::string& path, const std::string& interface,
103                      const std::string& propertyName, T& prop)
104     {
105         namespace log = phosphor::logging;
106 
107         auto msg = bus.new_method_call(service.c_str(), path.c_str(),
108                                        propertiesintf.c_str(), "Get");
109 
110         msg.append(interface, propertyName);
111 
112         std::variant<T> result;
113         try
114         {
115             auto valueResponseMsg = bus.call(msg);
116             valueResponseMsg.read(result);
117         }
118         catch (const sdbusplus::exception::SdBusError& ex)
119         {
120             log::log<log::level::ERR>("Get Property Failed",
121                                       log::entry("WHAT=%s", ex.what()));
122             throw;
123         }
124 
125         prop = std::get<T>(result);
126     }
127 };
128 
129 std::string getSensorPath(const std::string& type, const std::string& id);
130 std::string getMatch(const std::string& type, const std::string& id);
131 void scaleSensorReading(const double min, const double max, double& value);
132 bool validType(const std::string& type);
133 
134 struct VariantToDoubleVisitor
135 {
136     template <typename T>
137     std::enable_if_t<std::is_arithmetic<T>::value, double>
138         operator()(const T& t) const
139     {
140         return static_cast<double>(t);
141     }
142 
143     template <typename T>
144     std::enable_if_t<!std::is_arithmetic<T>::value, double>
145         operator()(const T& t) const
146     {
147         throw std::invalid_argument("Cannot translate type to double");
148     }
149 };
150 
151 /*
152  * Given a path that optionally has a glob portion, fill it out.
153  */
154 std::string FixupPath(std::string original);
155