blob: f83a45e6972f027395a70eba76cdc0603985cd98 [file] [log] [blame]
James Feist8fd8a582018-11-16 11:10:46 -08001#pragma once
2
Patrick Ventureca44b2f2019-10-31 11:02:26 -07003#include "Thresholds.hpp"
4
Patrick Venturefd6ba732019-10-31 14:27:39 -07005#include <limits>
6#include <memory>
James Feist8fd8a582018-11-16 11:10:46 -08007#include <sdbusplus/asio/object_server.hpp>
Patrick Venturefd6ba732019-10-31 14:27:39 -07008#include <string>
9#include <vector>
James Feist8fd8a582018-11-16 11:10:46 -080010
James Feist1169eb42018-10-31 10:08:47 -070011constexpr size_t sensorFailedPollTimeMs = 5000;
James Feista5e58722019-04-22 14:43:11 -070012
13constexpr const char* sensorValueInterface = "xyz.openbmc_project.Sensor.Value";
James Feist8fd8a582018-11-16 11:10:46 -080014struct Sensor
15{
James Feist930fcde2019-05-28 12:58:43 -070016 Sensor(const std::string& name,
James Feistd8705872019-02-08 13:26:09 -080017 std::vector<thresholds::Threshold>&& thresholdData,
18 const std::string& configurationPath, const std::string& objectType,
James Feistce3fca42018-11-21 12:58:24 -080019 const double max, const double min) :
James Feistdc6c55f2018-10-31 12:53:20 -070020 name(name),
James Feist930fcde2019-05-28 12:58:43 -070021 configurationPath(configurationPath), objectType(objectType),
James Feist9f16b4b2019-06-04 14:59:42 -070022 thresholds(std::move(thresholdData)), maxValue(max), minValue(min),
23 hysteresis((max - min) * 0.01)
James Feistdc6c55f2018-10-31 12:53:20 -070024 {
25 }
James Feist8fd8a582018-11-16 11:10:46 -080026 virtual ~Sensor() = default;
James Feistce3fca42018-11-21 12:58:24 -080027 virtual void checkThresholds(void) = 0;
James Feistdc6c55f2018-10-31 12:53:20 -070028 std::string name;
James Feistce3fca42018-11-21 12:58:24 -080029 std::string configurationPath;
30 std::string objectType;
31 double maxValue;
32 double minValue;
James Feist8fd8a582018-11-16 11:10:46 -080033 std::vector<thresholds::Threshold> thresholds;
34 std::shared_ptr<sdbusplus::asio::dbus_interface> sensorInterface;
35 std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceWarning;
36 std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceCritical;
James Feist078f2322019-03-08 11:09:05 -080037 std::shared_ptr<sdbusplus::asio::dbus_interface> association;
James Feist8fd8a582018-11-16 11:10:46 -080038 double value = std::numeric_limits<double>::quiet_NaN();
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +053039 bool overriddenState = false;
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053040 bool internalSet = false;
James Feist9f16b4b2019-06-04 14:59:42 -070041 double hysteresis;
James Feistce3fca42018-11-21 12:58:24 -080042
James Feistd8705872019-02-08 13:26:09 -080043 int setSensorValue(const double& newValue, double& oldValue)
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053044 {
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +053045 if (!internalSet)
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053046 {
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053047 oldValue = newValue;
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +053048 overriddenState = true;
49 // check thresholds for external set
50 value = newValue;
51 checkThresholds();
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053052 }
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +053053 else if (!overriddenState)
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +053054 {
55 oldValue = newValue;
56 }
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053057 return 1;
58 }
James Feistce3fca42018-11-21 12:58:24 -080059
60 void
James Feistd8705872019-02-08 13:26:09 -080061 setInitialProperties(std::shared_ptr<sdbusplus::asio::connection>& conn)
James Feistce3fca42018-11-21 12:58:24 -080062 {
James Feist82bac4c2019-03-11 11:16:53 -070063 createAssociation(association, configurationPath);
James Feistce3fca42018-11-21 12:58:24 -080064 sensorInterface->register_property("MaxValue", maxValue);
65 sensorInterface->register_property("MinValue", minValue);
66 sensorInterface->register_property(
James Feistd8705872019-02-08 13:26:09 -080067 "Value", value, [&](const double& newValue, double& oldValue) {
James Feistce3fca42018-11-21 12:58:24 -080068 return setSensorValue(newValue, oldValue);
69 });
James Feistd8705872019-02-08 13:26:09 -080070 for (auto& threshold : thresholds)
James Feistce3fca42018-11-21 12:58:24 -080071 {
72 std::shared_ptr<sdbusplus::asio::dbus_interface> iface;
73 std::string level;
74 std::string alarm;
75 if (threshold.level == thresholds::Level::CRITICAL)
76 {
77 iface = thresholdInterfaceCritical;
78 if (threshold.direction == thresholds::Direction::HIGH)
79 {
80 level = "CriticalHigh";
81 alarm = "CriticalAlarmHigh";
82 }
83 else
84 {
85 level = "CriticalLow";
86 alarm = "CriticalAlarmLow";
87 }
88 }
89 else if (threshold.level == thresholds::Level::WARNING)
90 {
91 iface = thresholdInterfaceWarning;
92 if (threshold.direction == thresholds::Direction::HIGH)
93 {
94 level = "WarningHigh";
95 alarm = "WarningAlarmHigh";
96 }
97 else
98 {
99 level = "WarningLow";
100 alarm = "WarningAlarmLow";
101 }
102 }
103 else
104 {
105 std::cerr << "Unknown threshold level" << threshold.level
106 << "\n";
107 continue;
108 }
109 if (!iface)
110 {
111 std::cout << "trying to set uninitialized interface\n";
112 continue;
113 }
114 iface->register_property(
115 level, threshold.value,
James Feistd8705872019-02-08 13:26:09 -0800116 [&](const double& request, double& oldValue) {
James Feistce3fca42018-11-21 12:58:24 -0800117 oldValue = request; // todo, just let the config do this?
118 threshold.value = request;
119 thresholds::persistThreshold(configurationPath, objectType,
James Feista222ba72019-03-01 15:57:51 -0800120 threshold, conn,
121 thresholds.size());
James Feistce3fca42018-11-21 12:58:24 -0800122 return 1;
123 });
124 iface->register_property(alarm, false);
125 }
126 if (!sensorInterface->initialize())
127 {
128 std::cerr << "error initializing value interface\n";
129 }
130 if (thresholdInterfaceWarning &&
131 !thresholdInterfaceWarning->initialize())
132 {
133 std::cerr << "error initializing warning threshold interface\n";
134 }
135
136 if (thresholdInterfaceCritical &&
137 !thresholdInterfaceCritical->initialize())
138 {
139 std::cerr << "error initializing critical threshold interface\n";
140 }
141 }
142
James Feistd8705872019-02-08 13:26:09 -0800143 void updateValue(const double& newValue)
James Feistce3fca42018-11-21 12:58:24 -0800144 {
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530145 // Ignore if overriding is enabled
146 if (!overriddenState)
147 {
148 // Indicate that it is internal set call
149 internalSet = true;
Josh Lehan432d1ed2019-10-16 12:23:31 -0700150 if (!(sensorInterface->set_property("Value", newValue)))
151 {
152 std::cerr << "error setting property to " << newValue << "\n";
153 }
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530154 internalSet = false;
James Feist52497fd2019-06-07 13:01:33 -0700155 double diff = std::abs(value - newValue);
156 if (std::isnan(diff) || diff > hysteresis)
James Feist9f16b4b2019-06-04 14:59:42 -0700157 {
158 value = newValue;
James Feist9f16b4b2019-06-04 14:59:42 -0700159 }
James Feist19cb01d2019-09-16 13:43:52 -0700160 checkThresholds();
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530161 }
James Feistce3fca42018-11-21 12:58:24 -0800162 }
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530163};