blob: 71a66ca929af3e11cd15e9dcaea385e4993a0fe3 [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>
Lei YU0fcf0e12021-06-04 11:14:17 +08009#include <xyz/openbmc_project/Association/Definitions/server.hpp>
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070010#include <xyz/openbmc_project/Sensor/Value/server.hpp>
11
12#include <map>
13#include <string>
14
15namespace phosphor
16{
17namespace virtualSensor
18{
19
20using Json = nlohmann::json;
Matt Spinlerce675222021-01-14 16:38:09 -060021
22template <typename... T>
23using ServerObject = typename sdbusplus::server::object::object<T...>;
24
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070025using ValueIface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
Matt Spinlerce675222021-01-14 16:38:09 -060026using ValueObject = ServerObject<ValueIface>;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070027
Lei YU0fcf0e12021-06-04 11:14:17 +080028using AssociationIface =
29 sdbusplus::xyz::openbmc_project::Association::server::Definitions;
30using AssociationObject = ServerObject<AssociationIface>;
31
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070032class SensorParam
33{
34 public:
35 SensorParam() = delete;
36 virtual ~SensorParam() = default;
37
38 enum ParamType
39 {
40 constParam,
41 dbusParam
42 };
43
44 /** @brief Constructs SensorParam (type = constParam)
45 *
46 * @param[in] value - Value of constant parameter
47 */
48 explicit SensorParam(double value) : value(value), paramType(constParam)
49 {}
50
Vijay Khemka7452a862020-08-11 16:01:23 -070051 /** @brief Constructs SensorParam (type = dbusParam)
52 *
53 * @param[in] bus - Handle to system dbus
54 * @param[in] path - The Dbus path of sensor
Vijay Khemka51f898e2020-09-09 22:24:18 -070055 * @param[in] ctx - sensor context for update
Vijay Khemka7452a862020-08-11 16:01:23 -070056 */
Vijay Khemka51f898e2020-09-09 22:24:18 -070057 SensorParam(sdbusplus::bus::bus& bus, std::string path, void* ctx) :
58 dbusSensor(std::make_unique<DbusSensor>(bus, path, ctx)),
Vijay Khemka7452a862020-08-11 16:01:23 -070059 paramType(dbusParam)
60 {}
61
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070062 /** @brief Get sensor value property from D-bus interface */
63 double getParamValue();
64
65 private:
Vijay Khemka7452a862020-08-11 16:01:23 -070066 std::unique_ptr<DbusSensor> dbusSensor = nullptr;
67 double value = 0;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070068 ParamType paramType;
69};
70
Matt Spinlerce675222021-01-14 16:38:09 -060071class VirtualSensor : public ValueObject
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070072{
73 public:
74 VirtualSensor() = delete;
75 virtual ~VirtualSensor() = default;
76
77 /** @brief Constructs VirtualSensor
78 *
79 * @param[in] bus - Handle to system dbus
80 * @param[in] objPath - The Dbus path of sensor
81 * @param[in] sensorConfig - Json object for sensor config
82 */
83 VirtualSensor(sdbusplus::bus::bus& bus, const char* objPath,
Vijay Khemka32a71562020-09-10 15:29:18 -070084 const Json& sensorConfig, const std::string& name) :
Matt Spinlerce675222021-01-14 16:38:09 -060085 ValueObject(bus, objPath),
Vijay Khemka32a71562020-09-10 15:29:18 -070086 bus(bus), name(name)
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070087 {
Matt Spinlerce675222021-01-14 16:38:09 -060088 initVirtualSensor(sensorConfig, objPath);
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070089 }
90
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070091 /** @brief Set sensor value */
92 void setSensorValue(double value);
Vijay Khemka3ed9a512020-08-21 16:13:05 -070093 /** @brief Update sensor at regular intrval */
94 void updateVirtualSensor();
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070095
96 /** @brief Map of list of parameters */
97 using ParamMap =
98 std::unordered_map<std::string, std::unique_ptr<SensorParam>>;
99 ParamMap paramMap;
100
101 private:
102 /** @brief sdbusplus bus client connection. */
103 sdbusplus::bus::bus& bus;
Vijay Khemka32a71562020-09-10 15:29:18 -0700104 /** @brief name of sensor */
105 std::string name;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700106 /** @brief Expression string for virtual sensor value calculations */
107 std::string exprStr;
Vijay Khemka3ed9a512020-08-21 16:13:05 -0700108 /** @brief symbol table from exprtk */
109 exprtk::symbol_table<double> symbols{};
110 /** @brief expression from exprtk to calculate sensor value */
111 exprtk::expression<double> expression{};
Matt Spinler9f1ef4f2020-11-09 15:59:11 -0600112 /** @brief The vecops package so the expression can use vectors */
113 exprtk::rtl::vecops::package<double> vecopsPackage;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700114
Matt Spinlerce675222021-01-14 16:38:09 -0600115 /** @brief The critical threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600116 std::unique_ptr<Threshold<CriticalObject>> criticalIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600117 /** @brief The warning threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600118 std::unique_ptr<Threshold<WarningObject>> warningIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600119 /** @brief The soft shutdown threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600120 std::unique_ptr<Threshold<SoftShutdownObject>> softShutdownIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600121 /** @brief The hard shutdown threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600122 std::unique_ptr<Threshold<HardShutdownObject>> hardShutdownIface;
Matt Spinlerb306b032021-02-01 10:05:46 -0600123 /** @brief The performance loss threshold interface object */
124 std::unique_ptr<Threshold<PerformanceLossObject>> perfLossIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600125
Lei YU0fcf0e12021-06-04 11:14:17 +0800126 /** @brief The association interface object */
127 std::unique_ptr<AssociationObject> associationIface;
128
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700129 /** @brief Read config from json object and initialize sensor data
130 * for each virtual sensor
131 */
Matt Spinlerce675222021-01-14 16:38:09 -0600132 void initVirtualSensor(const Json& sensorConfig,
133 const std::string& objPath);
134
Vijay Khemka32a71562020-09-10 15:29:18 -0700135 /** @brief Check Sensor threshold and update alarm and log */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600136 template <typename V, typename T>
137 void checkThresholds(V value, T& threshold)
Matt Spinler8f5e6112021-01-15 10:44:32 -0600138 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600139 if (!threshold)
140 return;
Matt Spinler8f5e6112021-01-15 10:44:32 -0600141
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600142 static constexpr auto tname = T::element_type::name;
143
144 auto alarmHigh = threshold->alarmHigh();
Matt Spinlera4fe6652021-01-28 14:02:59 -0600145 if ((!alarmHigh && value >= threshold->high()) ||
146 (alarmHigh && value < threshold->high()))
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600147 {
148 if (!alarmHigh)
Matt Spinler8f5e6112021-01-15 10:44:32 -0600149 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600150 constexpr auto msg =
151 "ASSERT: {} has exceeded the {} high threshold";
152 log<level::ERR>(fmt::format(msg, name, tname).c_str());
George Hung4294e6d2021-04-14 20:58:21 +0800153 threshold->alarmHighSignalAsserted(value);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600154 }
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600155 else
Matt Spinler8f5e6112021-01-15 10:44:32 -0600156 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600157 constexpr auto msg =
158 "DEASSERT: {} is under the {} high threshold";
159 log<level::INFO>(fmt::format(msg, name, tname).c_str());
George Hung4294e6d2021-04-14 20:58:21 +0800160 threshold->alarmHighSignalDeasserted(value);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600161 }
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600162 threshold->alarmHigh(!alarmHigh);
163 }
164
165 auto alarmLow = threshold->alarmLow();
Matt Spinlera4fe6652021-01-28 14:02:59 -0600166 if ((!alarmLow && value <= threshold->low()) ||
167 (alarmLow && value > threshold->low()))
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600168 {
169 if (!alarmLow)
170 {
171 constexpr auto msg = "ASSERT: {} is under the {} low threshold";
172 log<level::ERR>(fmt::format(msg, name, tname).c_str());
George Hung4294e6d2021-04-14 20:58:21 +0800173 threshold->alarmLowSignalAsserted(value);
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600174 }
175 else
176 {
177 constexpr auto msg =
178 "DEASSERT: {} is above the {} low threshold";
179 log<level::INFO>(fmt::format(msg, name, tname).c_str());
George Hung4294e6d2021-04-14 20:58:21 +0800180 threshold->alarmLowSignalDeasserted(value);
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600181 }
182 threshold->alarmLow(!alarmLow);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600183 }
184 }
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700185};
186
187class VirtualSensors
188{
189 public:
190 VirtualSensors() = delete;
191 virtual ~VirtualSensors() = default;
192
193 /** @brief Constructs VirtualSensors
194 *
195 * @param[in] bus - Handle to system dbus
196 */
197 explicit VirtualSensors(sdbusplus::bus::bus& bus) : bus(bus)
198 {
199 createVirtualSensors();
200 }
201
202 private:
203 /** @brief sdbusplus bus client connection. */
204 sdbusplus::bus::bus& bus;
205 /** @brief Parsing virtual sensor config JSON file */
206 Json parseConfigFile(const std::string configFile);
207
208 /** @brief Map of the object VirtualSensor */
209 std::unordered_map<std::string, std::unique_ptr<VirtualSensor>>
210 virtualSensorsMap;
211
212 /** @brief Create list of virtual sensors */
213 void createVirtualSensors();
214};
215
216} // namespace virtualSensor
217} // namespace phosphor