blob: 62042d87259c248aa310d87ffd8b4461497d7a90 [file] [log] [blame]
Vijay Khemka7452a862020-08-11 16:01:23 -07001#include "dbusSensor.hpp"
Vijay Khemka92d648b2020-08-21 18:55:07 -07002#include "exprtkTools.hpp"
Matt Spinler8f5e6112021-01-15 10:44:32 -06003#include "thresholds.hpp"
4
5#include <fmt/format.h>
Vijay Khemka7452a862020-08-11 16:01:23 -07006
Vijay Khemkaabcc94f2020-08-11 15:27:44 -07007#include <nlohmann/json.hpp>
8#include <sdbusplus/bus.hpp>
Vijay Khemkaabcc94f2020-08-11 15:27:44 -07009#include <xyz/openbmc_project/Sensor/Value/server.hpp>
10
11#include <map>
12#include <string>
13
14namespace phosphor
15{
16namespace virtualSensor
17{
18
19using Json = nlohmann::json;
Matt Spinlerce675222021-01-14 16:38:09 -060020
21template <typename... T>
22using ServerObject = typename sdbusplus::server::object::object<T...>;
23
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070024using ValueIface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
Matt Spinlerce675222021-01-14 16:38:09 -060025using ValueObject = ServerObject<ValueIface>;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070026
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070027class SensorParam
28{
29 public:
30 SensorParam() = delete;
31 virtual ~SensorParam() = default;
32
33 enum ParamType
34 {
35 constParam,
36 dbusParam
37 };
38
39 /** @brief Constructs SensorParam (type = constParam)
40 *
41 * @param[in] value - Value of constant parameter
42 */
43 explicit SensorParam(double value) : value(value), paramType(constParam)
44 {}
45
Vijay Khemka7452a862020-08-11 16:01:23 -070046 /** @brief Constructs SensorParam (type = dbusParam)
47 *
48 * @param[in] bus - Handle to system dbus
49 * @param[in] path - The Dbus path of sensor
Vijay Khemka51f898e2020-09-09 22:24:18 -070050 * @param[in] ctx - sensor context for update
Vijay Khemka7452a862020-08-11 16:01:23 -070051 */
Vijay Khemka51f898e2020-09-09 22:24:18 -070052 SensorParam(sdbusplus::bus::bus& bus, std::string path, void* ctx) :
53 dbusSensor(std::make_unique<DbusSensor>(bus, path, ctx)),
Vijay Khemka7452a862020-08-11 16:01:23 -070054 paramType(dbusParam)
55 {}
56
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070057 /** @brief Get sensor value property from D-bus interface */
58 double getParamValue();
59
60 private:
Vijay Khemka7452a862020-08-11 16:01:23 -070061 std::unique_ptr<DbusSensor> dbusSensor = nullptr;
62 double value = 0;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070063 ParamType paramType;
64};
65
Matt Spinlerce675222021-01-14 16:38:09 -060066class VirtualSensor : public ValueObject
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070067{
68 public:
69 VirtualSensor() = delete;
70 virtual ~VirtualSensor() = default;
71
72 /** @brief Constructs VirtualSensor
73 *
74 * @param[in] bus - Handle to system dbus
75 * @param[in] objPath - The Dbus path of sensor
76 * @param[in] sensorConfig - Json object for sensor config
77 */
78 VirtualSensor(sdbusplus::bus::bus& bus, const char* objPath,
Vijay Khemka32a71562020-09-10 15:29:18 -070079 const Json& sensorConfig, const std::string& name) :
Matt Spinlerce675222021-01-14 16:38:09 -060080 ValueObject(bus, objPath),
Vijay Khemka32a71562020-09-10 15:29:18 -070081 bus(bus), name(name)
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070082 {
Matt Spinlerce675222021-01-14 16:38:09 -060083 initVirtualSensor(sensorConfig, objPath);
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070084 }
85
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070086 /** @brief Set sensor value */
87 void setSensorValue(double value);
Vijay Khemka3ed9a512020-08-21 16:13:05 -070088 /** @brief Update sensor at regular intrval */
89 void updateVirtualSensor();
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070090
91 /** @brief Map of list of parameters */
92 using ParamMap =
93 std::unordered_map<std::string, std::unique_ptr<SensorParam>>;
94 ParamMap paramMap;
95
96 private:
97 /** @brief sdbusplus bus client connection. */
98 sdbusplus::bus::bus& bus;
Vijay Khemka32a71562020-09-10 15:29:18 -070099 /** @brief name of sensor */
100 std::string name;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700101 /** @brief Expression string for virtual sensor value calculations */
102 std::string exprStr;
Vijay Khemka3ed9a512020-08-21 16:13:05 -0700103 /** @brief symbol table from exprtk */
104 exprtk::symbol_table<double> symbols{};
105 /** @brief expression from exprtk to calculate sensor value */
106 exprtk::expression<double> expression{};
Matt Spinler9f1ef4f2020-11-09 15:59:11 -0600107 /** @brief The vecops package so the expression can use vectors */
108 exprtk::rtl::vecops::package<double> vecopsPackage;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700109
Matt Spinlerce675222021-01-14 16:38:09 -0600110 /** @brief The critical threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600111 std::unique_ptr<Threshold<CriticalObject>> criticalIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600112 /** @brief The warning threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600113 std::unique_ptr<Threshold<WarningObject>> warningIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600114 /** @brief The soft shutdown threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600115 std::unique_ptr<Threshold<SoftShutdownObject>> softShutdownIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600116 /** @brief The hard shutdown threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600117 std::unique_ptr<Threshold<HardShutdownObject>> hardShutdownIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600118
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700119 /** @brief Read config from json object and initialize sensor data
120 * for each virtual sensor
121 */
Matt Spinlerce675222021-01-14 16:38:09 -0600122 void initVirtualSensor(const Json& sensorConfig,
123 const std::string& objPath);
124
Vijay Khemka32a71562020-09-10 15:29:18 -0700125 /** @brief Check Sensor threshold and update alarm and log */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600126 template <typename V, typename T>
127 void checkThresholds(V value, T& threshold)
Matt Spinler8f5e6112021-01-15 10:44:32 -0600128 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600129 if (!threshold)
130 return;
Matt Spinler8f5e6112021-01-15 10:44:32 -0600131
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600132 static constexpr auto tname = T::element_type::name;
133
134 auto alarmHigh = threshold->alarmHigh();
135 if ((!alarmHigh && value >= threshold->high()) || alarmHigh)
136 {
137 if (!alarmHigh)
Matt Spinler8f5e6112021-01-15 10:44:32 -0600138 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600139 constexpr auto msg =
140 "ASSERT: {} has exceeded the {} high threshold";
141 log<level::ERR>(fmt::format(msg, name, tname).c_str());
Matt Spinler8f5e6112021-01-15 10:44:32 -0600142 }
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600143 else
Matt Spinler8f5e6112021-01-15 10:44:32 -0600144 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600145 constexpr auto msg =
146 "DEASSERT: {} is under the {} high threshold";
147 log<level::INFO>(fmt::format(msg, name, tname).c_str());
Matt Spinler8f5e6112021-01-15 10:44:32 -0600148 }
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600149 threshold->alarmHigh(!alarmHigh);
150 }
151
152 auto alarmLow = threshold->alarmLow();
153 if ((!alarmLow && value <= threshold->low()) || alarmLow)
154 {
155 if (!alarmLow)
156 {
157 constexpr auto msg = "ASSERT: {} is under the {} low threshold";
158 log<level::ERR>(fmt::format(msg, name, tname).c_str());
159 }
160 else
161 {
162 constexpr auto msg =
163 "DEASSERT: {} is above the {} low threshold";
164 log<level::INFO>(fmt::format(msg, name, tname).c_str());
165 }
166 threshold->alarmLow(!alarmLow);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600167 }
168 }
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700169};
170
171class VirtualSensors
172{
173 public:
174 VirtualSensors() = delete;
175 virtual ~VirtualSensors() = default;
176
177 /** @brief Constructs VirtualSensors
178 *
179 * @param[in] bus - Handle to system dbus
180 */
181 explicit VirtualSensors(sdbusplus::bus::bus& bus) : bus(bus)
182 {
183 createVirtualSensors();
184 }
185
186 private:
187 /** @brief sdbusplus bus client connection. */
188 sdbusplus::bus::bus& bus;
189 /** @brief Parsing virtual sensor config JSON file */
190 Json parseConfigFile(const std::string configFile);
191
192 /** @brief Map of the object VirtualSensor */
193 std::unordered_map<std::string, std::unique_ptr<VirtualSensor>>
194 virtualSensorsMap;
195
196 /** @brief Create list of virtual sensors */
197 void createVirtualSensors();
198};
199
200} // namespace virtualSensor
201} // namespace phosphor