blob: cdf1d974d1561d1d9673c4b2549c92b63671e75b [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
Vijay Khemkaabcc94f2020-08-11 15:27:44 -07005#include <nlohmann/json.hpp>
Patrick Williams82b39c62021-07-28 16:22:27 -05006#include <phosphor-logging/lg2.hpp>
Vijay Khemkaabcc94f2020-08-11 15:27:44 -07007#include <sdbusplus/bus.hpp>
Lei YU0fcf0e12021-06-04 11:14:17 +08008#include <xyz/openbmc_project/Association/Definitions/server.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
Patrick Williams82b39c62021-07-28 16:22:27 -050019PHOSPHOR_LOG2_USING_WITH_FLAGS;
20
Rashmica Guptae7efe132021-07-27 19:42:11 +100021using BasicVariantType =
22 std::variant<std::string, int64_t, uint64_t, double, int32_t, uint32_t,
23 int16_t, uint16_t, uint8_t, bool, std::vector<std::string>>;
24
25using PropertyMap = std::map<std::string, BasicVariantType>;
26
27using InterfaceMap = std::map<std::string, PropertyMap>;
28
29using ManagedObjectType =
30 std::map<sdbusplus::message::object_path, InterfaceMap>;
31
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070032using Json = nlohmann::json;
Matt Spinlerce675222021-01-14 16:38:09 -060033
34template <typename... T>
35using ServerObject = typename sdbusplus::server::object::object<T...>;
36
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070037using ValueIface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
Matt Spinlerce675222021-01-14 16:38:09 -060038using ValueObject = ServerObject<ValueIface>;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070039
Lei YU0fcf0e12021-06-04 11:14:17 +080040using AssociationIface =
41 sdbusplus::xyz::openbmc_project::Association::server::Definitions;
42using AssociationObject = ServerObject<AssociationIface>;
43
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070044class SensorParam
45{
46 public:
47 SensorParam() = delete;
48 virtual ~SensorParam() = default;
49
50 enum ParamType
51 {
52 constParam,
53 dbusParam
54 };
55
56 /** @brief Constructs SensorParam (type = constParam)
57 *
58 * @param[in] value - Value of constant parameter
59 */
60 explicit SensorParam(double value) : value(value), paramType(constParam)
61 {}
62
Vijay Khemka7452a862020-08-11 16:01:23 -070063 /** @brief Constructs SensorParam (type = dbusParam)
64 *
65 * @param[in] bus - Handle to system dbus
66 * @param[in] path - The Dbus path of sensor
Vijay Khemka51f898e2020-09-09 22:24:18 -070067 * @param[in] ctx - sensor context for update
Vijay Khemka7452a862020-08-11 16:01:23 -070068 */
Vijay Khemka51f898e2020-09-09 22:24:18 -070069 SensorParam(sdbusplus::bus::bus& bus, std::string path, void* ctx) :
70 dbusSensor(std::make_unique<DbusSensor>(bus, path, ctx)),
Vijay Khemka7452a862020-08-11 16:01:23 -070071 paramType(dbusParam)
72 {}
73
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070074 /** @brief Get sensor value property from D-bus interface */
75 double getParamValue();
76
77 private:
Vijay Khemka7452a862020-08-11 16:01:23 -070078 std::unique_ptr<DbusSensor> dbusSensor = nullptr;
79 double value = 0;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070080 ParamType paramType;
81};
82
Matt Spinlerce675222021-01-14 16:38:09 -060083class VirtualSensor : public ValueObject
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070084{
85 public:
86 VirtualSensor() = delete;
87 virtual ~VirtualSensor() = default;
88
89 /** @brief Constructs VirtualSensor
90 *
91 * @param[in] bus - Handle to system dbus
92 * @param[in] objPath - The Dbus path of sensor
93 * @param[in] sensorConfig - Json object for sensor config
94 */
95 VirtualSensor(sdbusplus::bus::bus& bus, const char* objPath,
Vijay Khemka32a71562020-09-10 15:29:18 -070096 const Json& sensorConfig, const std::string& name) :
Rashmica Guptaa2fa63a2021-08-06 12:21:13 +100097 ValueObject(bus, objPath, action::defer_emit),
Vijay Khemka32a71562020-09-10 15:29:18 -070098 bus(bus), name(name)
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070099 {
Matt Spinlerce675222021-01-14 16:38:09 -0600100 initVirtualSensor(sensorConfig, objPath);
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700101 }
102
Rashmica Guptae7efe132021-07-27 19:42:11 +1000103 /** @brief Constructs VirtualSensor
104 *
105 * @param[in] bus - Handle to system dbus
106 * @param[in] objPath - The Dbus path of sensor
107 * @param[in] ifacemap - All the sensor information
108 * @param[in] name - Virtual sensor name
109 * @param[in] type - Virtual sensor type/unit
110 * @param[in] calcType - Calculation used to calculate sensor value
111 *
112 */
113 VirtualSensor(sdbusplus::bus::bus& bus, const char* objPath,
114 const InterfaceMap& ifacemap, const std::string& name,
115 const std::string& type, const std::string& calculationType) :
116 ValueObject(bus, objPath, action::defer_emit),
117 bus(bus), name(name)
118 {
119 initVirtualSensor(ifacemap, objPath, type, calculationType);
120 }
121
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700122 /** @brief Set sensor value */
123 void setSensorValue(double value);
Vijay Khemka3ed9a512020-08-21 16:13:05 -0700124 /** @brief Update sensor at regular intrval */
125 void updateVirtualSensor();
Rashmica Gupta304fd0e2021-08-10 16:50:44 +1000126 /** @brief Check if sensor value is in valid range */
127 bool sensorInRange(double value);
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700128
129 /** @brief Map of list of parameters */
130 using ParamMap =
131 std::unordered_map<std::string, std::unique_ptr<SensorParam>>;
132 ParamMap paramMap;
133
134 private:
135 /** @brief sdbusplus bus client connection. */
136 sdbusplus::bus::bus& bus;
Vijay Khemka32a71562020-09-10 15:29:18 -0700137 /** @brief name of sensor */
138 std::string name;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700139 /** @brief Expression string for virtual sensor value calculations */
140 std::string exprStr;
Vijay Khemka3ed9a512020-08-21 16:13:05 -0700141 /** @brief symbol table from exprtk */
142 exprtk::symbol_table<double> symbols{};
143 /** @brief expression from exprtk to calculate sensor value */
144 exprtk::expression<double> expression{};
Matt Spinler9f1ef4f2020-11-09 15:59:11 -0600145 /** @brief The vecops package so the expression can use vectors */
146 exprtk::rtl::vecops::package<double> vecopsPackage;
Rashmica Guptae7efe132021-07-27 19:42:11 +1000147 /** @brief The maximum valid value for an input sensor **/
148 double maxValidInput = std::numeric_limits<double>::infinity();
149 /** @brief The minimum valid value for an input sensor **/
150 double minValidInput = -std::numeric_limits<double>::infinity();
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700151
Matt Spinlerce675222021-01-14 16:38:09 -0600152 /** @brief The critical threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600153 std::unique_ptr<Threshold<CriticalObject>> criticalIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600154 /** @brief The warning threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600155 std::unique_ptr<Threshold<WarningObject>> warningIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600156 /** @brief The soft shutdown threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600157 std::unique_ptr<Threshold<SoftShutdownObject>> softShutdownIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600158 /** @brief The hard shutdown threshold interface object */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600159 std::unique_ptr<Threshold<HardShutdownObject>> hardShutdownIface;
Matt Spinlerb306b032021-02-01 10:05:46 -0600160 /** @brief The performance loss threshold interface object */
161 std::unique_ptr<Threshold<PerformanceLossObject>> perfLossIface;
Matt Spinlerce675222021-01-14 16:38:09 -0600162
Lei YU0fcf0e12021-06-04 11:14:17 +0800163 /** @brief The association interface object */
164 std::unique_ptr<AssociationObject> associationIface;
165
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700166 /** @brief Read config from json object and initialize sensor data
167 * for each virtual sensor
168 */
Matt Spinlerce675222021-01-14 16:38:09 -0600169 void initVirtualSensor(const Json& sensorConfig,
170 const std::string& objPath);
171
Rashmica Guptae7efe132021-07-27 19:42:11 +1000172 /** @brief Read config from interface map and initialize sensor data
173 * for each virtual sensor
174 */
175 void initVirtualSensor(const InterfaceMap& interfaceMap,
176 const std::string& objPath,
177 const std::string& sensorType,
178 const std::string& calculationType);
179
180 /** @brief Returns which calculation function or expression to use */
Rashmica Gupta304fd0e2021-08-10 16:50:44 +1000181 double calculateValue(const std::string& sensortype,
182 const VirtualSensor::ParamMap& paramMap);
183 /** @brief Calculate median value from sensors */
184 double
185 calculateModifiedMedianValue(const VirtualSensor::ParamMap& paramMap);
Rashmica Gupta3e999192021-06-09 16:17:04 +1000186 /** @brief create threshold objects from json config */
187 void createThresholds(const Json& threshold, const std::string& objPath);
Rashmica Guptae7efe132021-07-27 19:42:11 +1000188 /** @brief parse config from entity manager **/
189 void parseConfigInterface(const PropertyMap& propertyMap,
190 const std::string& sensorType,
191 const std::string& interface);
Rashmica Gupta3e999192021-06-09 16:17:04 +1000192
Vijay Khemka32a71562020-09-10 15:29:18 -0700193 /** @brief Check Sensor threshold and update alarm and log */
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600194 template <typename V, typename T>
195 void checkThresholds(V value, T& threshold)
Matt Spinler8f5e6112021-01-15 10:44:32 -0600196 {
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600197 if (!threshold)
198 return;
Matt Spinler8f5e6112021-01-15 10:44:32 -0600199
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600200 static constexpr auto tname = T::element_type::name;
201
202 auto alarmHigh = threshold->alarmHigh();
Rashmica Gupta1dff7dc2021-07-27 19:43:31 +1000203 auto highHysteresis = threshold->getHighHysteresis();
Matt Spinlera4fe6652021-01-28 14:02:59 -0600204 if ((!alarmHigh && value >= threshold->high()) ||
Rashmica Gupta1dff7dc2021-07-27 19:43:31 +1000205 (alarmHigh && value < (threshold->high() - highHysteresis)))
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600206 {
207 if (!alarmHigh)
Matt Spinler8f5e6112021-01-15 10:44:32 -0600208 {
Patrick Williams82b39c62021-07-28 16:22:27 -0500209 error("ASSERT: sensor {SENSOR} is above the upper threshold "
210 "{THRESHOLD}.",
211 "SENSOR", name, "THRESHOLD", tname);
George Hung4294e6d2021-04-14 20:58:21 +0800212 threshold->alarmHighSignalAsserted(value);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600213 }
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600214 else
Matt Spinler8f5e6112021-01-15 10:44:32 -0600215 {
Patrick Williams82b39c62021-07-28 16:22:27 -0500216 info("DEASSERT: sensor {SENSOR} is under the upper threshold "
217 "{THRESHOLD}.",
218 "SENSOR", name, "THRESHOLD", tname);
George Hung4294e6d2021-04-14 20:58:21 +0800219 threshold->alarmHighSignalDeasserted(value);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600220 }
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600221 threshold->alarmHigh(!alarmHigh);
222 }
223
224 auto alarmLow = threshold->alarmLow();
Rashmica Gupta1dff7dc2021-07-27 19:43:31 +1000225 auto lowHysteresis = threshold->getLowHysteresis();
Matt Spinlera4fe6652021-01-28 14:02:59 -0600226 if ((!alarmLow && value <= threshold->low()) ||
Rashmica Gupta1dff7dc2021-07-27 19:43:31 +1000227 (alarmLow && value > (threshold->low() + lowHysteresis)))
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600228 {
229 if (!alarmLow)
230 {
Patrick Williams82b39c62021-07-28 16:22:27 -0500231 error("ASSERT: sensor {SENSOR} is below the lower threshold "
232 "{THRESHOLD}.",
233 "SENSOR", name, "THRESHOLD", tname);
George Hung4294e6d2021-04-14 20:58:21 +0800234 threshold->alarmLowSignalAsserted(value);
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600235 }
236 else
237 {
Patrick Williams82b39c62021-07-28 16:22:27 -0500238 info("DEASSERT: sensor {SENSOR} is above the lower threshold "
239 "{THRESHOLD}.",
240 "SENSOR", name, "THRESHOLD", tname);
George Hung4294e6d2021-04-14 20:58:21 +0800241 threshold->alarmLowSignalDeasserted(value);
Patrick Williamsfdb826d2021-01-20 14:37:53 -0600242 }
243 threshold->alarmLow(!alarmLow);
Matt Spinler8f5e6112021-01-15 10:44:32 -0600244 }
245 }
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700246};
247
248class VirtualSensors
249{
250 public:
251 VirtualSensors() = delete;
252 virtual ~VirtualSensors() = default;
253
254 /** @brief Constructs VirtualSensors
255 *
256 * @param[in] bus - Handle to system dbus
257 */
258 explicit VirtualSensors(sdbusplus::bus::bus& bus) : bus(bus)
259 {
260 createVirtualSensors();
261 }
Rashmica Guptae7efe132021-07-27 19:42:11 +1000262 /** @brief Calls createVirtualSensor when interface added */
263 void propertiesChanged(sdbusplus::message::message& msg);
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700264
265 private:
266 /** @brief sdbusplus bus client connection. */
267 sdbusplus::bus::bus& bus;
Rashmica Guptae7efe132021-07-27 19:42:11 +1000268 /** @brief Get virual sensor config from DBus**/
269 ManagedObjectType getObjectsFromDBus();
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700270 /** @brief Parsing virtual sensor config JSON file */
271 Json parseConfigFile(const std::string configFile);
272
Rashmica Guptae7efe132021-07-27 19:42:11 +1000273 /** @brief Matches for virtual sensors */
274 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700275 /** @brief Map of the object VirtualSensor */
276 std::unordered_map<std::string, std::unique_ptr<VirtualSensor>>
277 virtualSensorsMap;
278
Rashmica Guptae7efe132021-07-27 19:42:11 +1000279 /** @brief Create list of virtual sensors from JSON config*/
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700280 void createVirtualSensors();
Rashmica Guptae7efe132021-07-27 19:42:11 +1000281 /** @brief Create list of virtual sensors from DBus config */
282 void createVirtualSensorsFromDBus(const std::string& calculationType);
283 /** @brief Setup matches for virtual sensors */
284 void setupMatches();
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700285};
286
287} // namespace virtualSensor
288} // namespace phosphor