blob: aad85480d1ba701ffa8ba595e58bbd1505c4ee26 [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
James Feist8fd8a582018-11-16 11:10:46 -08005#include <sdbusplus/asio/object_server.hpp>
6
James Feist1169eb42018-10-31 10:08:47 -07007constexpr size_t sensorFailedPollTimeMs = 5000;
James Feista5e58722019-04-22 14:43:11 -07008
9constexpr const char* sensorValueInterface = "xyz.openbmc_project.Sensor.Value";
James Feist8fd8a582018-11-16 11:10:46 -080010struct Sensor
11{
James Feist930fcde2019-05-28 12:58:43 -070012 Sensor(const std::string& name,
James Feistd8705872019-02-08 13:26:09 -080013 std::vector<thresholds::Threshold>&& thresholdData,
14 const std::string& configurationPath, const std::string& objectType,
James Feistce3fca42018-11-21 12:58:24 -080015 const double max, const double min) :
James Feistdc6c55f2018-10-31 12:53:20 -070016 name(name),
James Feist930fcde2019-05-28 12:58:43 -070017 configurationPath(configurationPath), objectType(objectType),
James Feist9f16b4b2019-06-04 14:59:42 -070018 thresholds(std::move(thresholdData)), maxValue(max), minValue(min),
19 hysteresis((max - min) * 0.01)
James Feistdc6c55f2018-10-31 12:53:20 -070020 {
21 }
James Feist8fd8a582018-11-16 11:10:46 -080022 virtual ~Sensor() = default;
James Feistce3fca42018-11-21 12:58:24 -080023 virtual void checkThresholds(void) = 0;
James Feistdc6c55f2018-10-31 12:53:20 -070024 std::string name;
James Feistce3fca42018-11-21 12:58:24 -080025 std::string configurationPath;
26 std::string objectType;
27 double maxValue;
28 double minValue;
James Feist8fd8a582018-11-16 11:10:46 -080029 std::vector<thresholds::Threshold> thresholds;
30 std::shared_ptr<sdbusplus::asio::dbus_interface> sensorInterface;
31 std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceWarning;
32 std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceCritical;
James Feist078f2322019-03-08 11:09:05 -080033 std::shared_ptr<sdbusplus::asio::dbus_interface> association;
James Feist8fd8a582018-11-16 11:10:46 -080034 double value = std::numeric_limits<double>::quiet_NaN();
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +053035 bool overriddenState = false;
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053036 bool internalSet = false;
James Feist9f16b4b2019-06-04 14:59:42 -070037 double hysteresis;
James Feistce3fca42018-11-21 12:58:24 -080038
James Feistd8705872019-02-08 13:26:09 -080039 int setSensorValue(const double& newValue, double& oldValue)
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053040 {
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +053041 if (!internalSet)
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053042 {
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053043 oldValue = newValue;
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +053044 overriddenState = true;
45 // check thresholds for external set
46 value = newValue;
47 checkThresholds();
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053048 }
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +053049 else if (!overriddenState)
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +053050 {
51 oldValue = newValue;
52 }
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053053 return 1;
54 }
James Feistce3fca42018-11-21 12:58:24 -080055
56 void
James Feistd8705872019-02-08 13:26:09 -080057 setInitialProperties(std::shared_ptr<sdbusplus::asio::connection>& conn)
James Feistce3fca42018-11-21 12:58:24 -080058 {
James Feist82bac4c2019-03-11 11:16:53 -070059 createAssociation(association, configurationPath);
James Feistce3fca42018-11-21 12:58:24 -080060 sensorInterface->register_property("MaxValue", maxValue);
61 sensorInterface->register_property("MinValue", minValue);
62 sensorInterface->register_property(
James Feistd8705872019-02-08 13:26:09 -080063 "Value", value, [&](const double& newValue, double& oldValue) {
James Feistce3fca42018-11-21 12:58:24 -080064 return setSensorValue(newValue, oldValue);
65 });
James Feistd8705872019-02-08 13:26:09 -080066 for (auto& threshold : thresholds)
James Feistce3fca42018-11-21 12:58:24 -080067 {
68 std::shared_ptr<sdbusplus::asio::dbus_interface> iface;
69 std::string level;
70 std::string alarm;
71 if (threshold.level == thresholds::Level::CRITICAL)
72 {
73 iface = thresholdInterfaceCritical;
74 if (threshold.direction == thresholds::Direction::HIGH)
75 {
76 level = "CriticalHigh";
77 alarm = "CriticalAlarmHigh";
78 }
79 else
80 {
81 level = "CriticalLow";
82 alarm = "CriticalAlarmLow";
83 }
84 }
85 else if (threshold.level == thresholds::Level::WARNING)
86 {
87 iface = thresholdInterfaceWarning;
88 if (threshold.direction == thresholds::Direction::HIGH)
89 {
90 level = "WarningHigh";
91 alarm = "WarningAlarmHigh";
92 }
93 else
94 {
95 level = "WarningLow";
96 alarm = "WarningAlarmLow";
97 }
98 }
99 else
100 {
101 std::cerr << "Unknown threshold level" << threshold.level
102 << "\n";
103 continue;
104 }
105 if (!iface)
106 {
107 std::cout << "trying to set uninitialized interface\n";
108 continue;
109 }
110 iface->register_property(
111 level, threshold.value,
James Feistd8705872019-02-08 13:26:09 -0800112 [&](const double& request, double& oldValue) {
James Feistce3fca42018-11-21 12:58:24 -0800113 oldValue = request; // todo, just let the config do this?
114 threshold.value = request;
115 thresholds::persistThreshold(configurationPath, objectType,
James Feista222ba72019-03-01 15:57:51 -0800116 threshold, conn,
117 thresholds.size());
James Feistce3fca42018-11-21 12:58:24 -0800118 return 1;
119 });
120 iface->register_property(alarm, false);
121 }
122 if (!sensorInterface->initialize())
123 {
124 std::cerr << "error initializing value interface\n";
125 }
126 if (thresholdInterfaceWarning &&
127 !thresholdInterfaceWarning->initialize())
128 {
129 std::cerr << "error initializing warning threshold interface\n";
130 }
131
132 if (thresholdInterfaceCritical &&
133 !thresholdInterfaceCritical->initialize())
134 {
135 std::cerr << "error initializing critical threshold interface\n";
136 }
137 }
138
James Feistd8705872019-02-08 13:26:09 -0800139 void updateValue(const double& newValue)
James Feistce3fca42018-11-21 12:58:24 -0800140 {
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530141 // Ignore if overriding is enabled
142 if (!overriddenState)
143 {
144 // Indicate that it is internal set call
145 internalSet = true;
Josh Lehan432d1ed2019-10-16 12:23:31 -0700146 if (!(sensorInterface->set_property("Value", newValue)))
147 {
148 std::cerr << "error setting property to " << newValue << "\n";
149 }
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530150 internalSet = false;
James Feist52497fd2019-06-07 13:01:33 -0700151 double diff = std::abs(value - newValue);
152 if (std::isnan(diff) || diff > hysteresis)
James Feist9f16b4b2019-06-04 14:59:42 -0700153 {
154 value = newValue;
James Feist9f16b4b2019-06-04 14:59:42 -0700155 }
James Feist19cb01d2019-09-16 13:43:52 -0700156 checkThresholds();
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530157 }
James Feistce3fca42018-11-21 12:58:24 -0800158 }
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530159};