blob: 19c37335ef4c67977897f4f42e6d87ca27e19aeb [file] [log] [blame]
#pragma once
#include <Thresholds.hpp>
#include <sdbusplus/asio/object_server.hpp>
constexpr size_t sensorFailedPollTimeMs = 5000;
constexpr const char* sensorValueInterface = "xyz.openbmc_project.Sensor.Value";
struct Sensor
{
Sensor(const std::string& name, const std::string& path,
std::vector<thresholds::Threshold>&& thresholdData,
const std::string& configurationPath, const std::string& objectType,
const double max, const double min) :
name(name),
path(path), configurationPath(configurationPath),
objectType(objectType), thresholds(std::move(thresholdData)),
maxValue(max), minValue(min)
{
}
virtual ~Sensor() = default;
virtual void checkThresholds(void) = 0;
std::string name;
std::string path;
std::string configurationPath;
std::string objectType;
double maxValue;
double minValue;
std::vector<thresholds::Threshold> thresholds;
std::shared_ptr<sdbusplus::asio::dbus_interface> sensorInterface;
std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceWarning;
std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceCritical;
std::shared_ptr<sdbusplus::asio::dbus_interface> association;
double value = std::numeric_limits<double>::quiet_NaN();
bool overriddenState = false;
bool internalSet = false;
int setSensorValue(const double& newValue, double& oldValue)
{
if (!internalSet)
{
oldValue = newValue;
overriddenState = true;
// check thresholds for external set
value = newValue;
checkThresholds();
}
else if (!overriddenState)
{
oldValue = newValue;
}
return 1;
}
void
setInitialProperties(std::shared_ptr<sdbusplus::asio::connection>& conn)
{
createAssociation(association, configurationPath);
sensorInterface->register_property("MaxValue", maxValue);
sensorInterface->register_property("MinValue", minValue);
sensorInterface->register_property(
"Value", value, [&](const double& newValue, double& oldValue) {
return setSensorValue(newValue, oldValue);
});
for (auto& threshold : thresholds)
{
std::shared_ptr<sdbusplus::asio::dbus_interface> iface;
std::string level;
std::string alarm;
if (threshold.level == thresholds::Level::CRITICAL)
{
iface = thresholdInterfaceCritical;
if (threshold.direction == thresholds::Direction::HIGH)
{
level = "CriticalHigh";
alarm = "CriticalAlarmHigh";
}
else
{
level = "CriticalLow";
alarm = "CriticalAlarmLow";
}
}
else if (threshold.level == thresholds::Level::WARNING)
{
iface = thresholdInterfaceWarning;
if (threshold.direction == thresholds::Direction::HIGH)
{
level = "WarningHigh";
alarm = "WarningAlarmHigh";
}
else
{
level = "WarningLow";
alarm = "WarningAlarmLow";
}
}
else
{
std::cerr << "Unknown threshold level" << threshold.level
<< "\n";
continue;
}
if (!iface)
{
std::cout << "trying to set uninitialized interface\n";
continue;
}
iface->register_property(
level, threshold.value,
[&](const double& request, double& oldValue) {
oldValue = request; // todo, just let the config do this?
threshold.value = request;
thresholds::persistThreshold(configurationPath, objectType,
threshold, conn,
thresholds.size());
return 1;
});
iface->register_property(alarm, false);
}
if (!sensorInterface->initialize())
{
std::cerr << "error initializing value interface\n";
}
if (thresholdInterfaceWarning &&
!thresholdInterfaceWarning->initialize())
{
std::cerr << "error initializing warning threshold interface\n";
}
if (thresholdInterfaceCritical &&
!thresholdInterfaceCritical->initialize())
{
std::cerr << "error initializing critical threshold interface\n";
}
}
void updateValue(const double& newValue)
{
// Ignore if overriding is enabled
if (!overriddenState)
{
// Indicate that it is internal set call
internalSet = true;
sensorInterface->set_property("Value", newValue);
internalSet = false;
value = newValue;
checkThresholds();
}
}
};