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