blob: 13e342c95220d02ca0dc009ac1a969789ecd6ef9 [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 */
111 std::unique_ptr<CriticalObject> criticalIface;
112 /** @brief The warning threshold interface object */
113 std::unique_ptr<WarningObject> warningIface;
114 /** @brief The soft shutdown threshold interface object */
115 std::unique_ptr<SoftShutdownObject> softShutdownIface;
116 /** @brief The hard shutdown threshold interface object */
117 std::unique_ptr<HardShutdownObject> hardShutdownIface;
118
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 */
Matt Spinler8f5e6112021-01-15 10:44:32 -0600126 template <typename T>
127 void checkThresholds(double value, T* iface)
128 {
129 if (iface)
130 {
131 if (value >= Threshold<T>::high(iface))
132 {
133 if (!Threshold<T>::alarmHigh(iface))
134 {
135 Threshold<T>::alarmHigh(iface, true);
136 log<level::ERR>(fmt::format("ASSERT: {} has exceeded the "
137 "{} high threshold",
138 name, Threshold<T>::name())
139 .c_str());
140 }
141 }
142 else if (Threshold<T>::alarmHigh(iface))
143 {
144 Threshold<T>::alarmHigh(iface, false);
145 log<level::INFO>(fmt::format("DEASSERT: {} is under the "
146 "{} high threshold",
147 name, Threshold<T>::name())
148 .c_str());
149 }
150
151 if (value <= Threshold<T>::low(iface))
152 {
153 if (!Threshold<T>::alarmLow(iface))
154 {
155 Threshold<T>::alarmLow(iface, true);
156 log<level::ERR>(fmt::format("ASSERT: {} is under the "
157 "{} high threshold",
158 name, Threshold<T>::name())
159 .c_str());
160 }
161 }
162 else if (Threshold<T>::alarmLow(iface))
163 {
164 Threshold<T>::alarmLow(iface, false);
165 log<level::INFO>(fmt::format("DEASSERT: {} is above the "
166 "{} high threshold",
167 name, Threshold<T>::name())
168 .c_str());
169 }
170 }
171 }
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700172};
173
174class VirtualSensors
175{
176 public:
177 VirtualSensors() = delete;
178 virtual ~VirtualSensors() = default;
179
180 /** @brief Constructs VirtualSensors
181 *
182 * @param[in] bus - Handle to system dbus
183 */
184 explicit VirtualSensors(sdbusplus::bus::bus& bus) : bus(bus)
185 {
186 createVirtualSensors();
187 }
188
189 private:
190 /** @brief sdbusplus bus client connection. */
191 sdbusplus::bus::bus& bus;
192 /** @brief Parsing virtual sensor config JSON file */
193 Json parseConfigFile(const std::string configFile);
194
195 /** @brief Map of the object VirtualSensor */
196 std::unordered_map<std::string, std::unique_ptr<VirtualSensor>>
197 virtualSensorsMap;
198
199 /** @brief Create list of virtual sensors */
200 void createVirtualSensors();
201};
202
203} // namespace virtualSensor
204} // namespace phosphor