blob: 1d72f1eddfd6a97938e1fa7133808392da442400 [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 Spinlerb306b032021-02-01 10:05:46 -0600118 /** @brief The performance loss threshold interface object */
119 std::unique_ptr<Threshold<PerformanceLossObject>> perfLossIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600120
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700121 /** @brief Read config from json object and initialize sensor data
122 * for each virtual sensor
123 */
Matt Spinlerce675222021-01-14 16:38:09 -0600124 void initVirtualSensor(const Json& sensorConfig,
125 const std::string& objPath);
126
Vijay Khemka32a71562020-09-10 15:29:18 -0700127 /** @brief Check Sensor threshold and update alarm and log */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600128 template <typename V, typename T>
129 void checkThresholds(V value, T& threshold)
Matt Spinler8f5e6112021-01-15 10:44:32 -0600130 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600131 if (!threshold)
132 return;
Matt Spinler8f5e6112021-01-15 10:44:32 -0600133
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600134 static constexpr auto tname = T::element_type::name;
135
136 auto alarmHigh = threshold->alarmHigh();
Matt Spinlera4fe6652021-01-28 14:02:59 -0600137 if ((!alarmHigh && value >= threshold->high()) ||
138 (alarmHigh && value < threshold->high()))
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600139 {
140 if (!alarmHigh)
Matt Spinler8f5e6112021-01-15 10:44:32 -0600141 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600142 constexpr auto msg =
143 "ASSERT: {} has exceeded the {} high threshold";
144 log<level::ERR>(fmt::format(msg, name, tname).c_str());
George Hung4294e6d2021-04-14 20:58:21 +0800145 threshold->alarmHighSignalAsserted(value);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600146 }
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600147 else
Matt Spinler8f5e6112021-01-15 10:44:32 -0600148 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600149 constexpr auto msg =
150 "DEASSERT: {} is under the {} high threshold";
151 log<level::INFO>(fmt::format(msg, name, tname).c_str());
George Hung4294e6d2021-04-14 20:58:21 +0800152 threshold->alarmHighSignalDeasserted(value);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600153 }
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600154 threshold->alarmHigh(!alarmHigh);
155 }
156
157 auto alarmLow = threshold->alarmLow();
Matt Spinlera4fe6652021-01-28 14:02:59 -0600158 if ((!alarmLow && value <= threshold->low()) ||
159 (alarmLow && value > threshold->low()))
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600160 {
161 if (!alarmLow)
162 {
163 constexpr auto msg = "ASSERT: {} is under the {} low threshold";
164 log<level::ERR>(fmt::format(msg, name, tname).c_str());
George Hung4294e6d2021-04-14 20:58:21 +0800165 threshold->alarmLowSignalAsserted(value);
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600166 }
167 else
168 {
169 constexpr auto msg =
170 "DEASSERT: {} is above the {} low threshold";
171 log<level::INFO>(fmt::format(msg, name, tname).c_str());
George Hung4294e6d2021-04-14 20:58:21 +0800172 threshold->alarmLowSignalDeasserted(value);
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600173 }
174 threshold->alarmLow(!alarmLow);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600175 }
176 }
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700177};
178
179class VirtualSensors
180{
181 public:
182 VirtualSensors() = delete;
183 virtual ~VirtualSensors() = default;
184
185 /** @brief Constructs VirtualSensors
186 *
187 * @param[in] bus - Handle to system dbus
188 */
189 explicit VirtualSensors(sdbusplus::bus::bus& bus) : bus(bus)
190 {
191 createVirtualSensors();
192 }
193
194 private:
195 /** @brief sdbusplus bus client connection. */
196 sdbusplus::bus::bus& bus;
197 /** @brief Parsing virtual sensor config JSON file */
198 Json parseConfigFile(const std::string configFile);
199
200 /** @brief Map of the object VirtualSensor */
201 std::unordered_map<std::string, std::unique_ptr<VirtualSensor>>
202 virtualSensorsMap;
203
204 /** @brief Create list of virtual sensors */
205 void createVirtualSensors();
206};
207
208} // namespace virtualSensor
209} // namespace phosphor