sensor-cache: Implement reading data
Implement reading data in property changed callback.
With sensor-cache, the sensor's property is returned by the
callback of propertiesChanged match, parse the property from the message
and generate the sensor's response.
Tested: Verify the sensors using `readingData` have valid values in
QEMU, e.g.
Inlet_Temp | 20.000 | degrees C | ok | na | 0.000 | 5.000 | 38.000 | 43.000 | na
Signed-off-by: Lei YU <yulei.sh@bytedance.com>
Change-Id: I2c6328cb6001d0daf2045d17e73773dccf55d521
diff --git a/sensordatahandler.hpp b/sensordatahandler.hpp
index 91654af..2704146 100644
--- a/sensordatahandler.hpp
+++ b/sensordatahandler.hpp
@@ -12,6 +12,10 @@
#include <phosphor-logging/log.hpp>
#include <sdbusplus/message/types.hpp>
+#ifdef FEATURE_SENSORS_CACHE
+extern ipmi::sensor::SensorCacheMap sensorCacheMap;
+#endif
+
namespace ipmi
{
namespace sensor
@@ -334,10 +338,6 @@
#else
-using SensorCacheMap =
- std::map<uint8_t, std::optional<ipmi::sensor::GetSensorResponse>>;
-extern SensorCacheMap sensorCacheMap;
-
/**
* @brief Map the Dbus info to sensor's assertion status in the Get sensor
* reading command response.
@@ -397,8 +397,102 @@
std::optional<GetSensorResponse> readingData(uint8_t id, const Info& sensorInfo,
sdbusplus::message::message& msg)
{
- // TODO
- return {};
+ std::string interfaceName;
+ std::map<std::string, ipmi::Value> properties;
+ msg.read(interfaceName);
+
+ if (interfaceName ==
+ "xyz.openbmc_project.State.Decorator.OperationalStatus")
+ {
+ msg.read(properties);
+ auto val = properties.find("Functional");
+ if (val != properties.end())
+ {
+ sensorCacheMap[id]->functional = std::get<bool>(val->second);
+ }
+ return {};
+ }
+ if (interfaceName == "xyz.openbmc_project.State.Decorator.Availability")
+ {
+ msg.read(properties);
+ auto val = properties.find("Available");
+ if (val != properties.end())
+ {
+ sensorCacheMap[id]->available = std::get<bool>(val->second);
+ }
+ return {};
+ }
+
+ if (interfaceName != sensorInfo.sensorInterface)
+ {
+ // Not the interface we need
+ return {};
+ }
+
+#ifdef UPDATE_FUNCTIONAL_ON_FAIL
+ if (sensorCacheMap[id])
+ {
+ if (!sensorCacheMap[id]->functional)
+ {
+ throw SensorFunctionalError();
+ }
+ }
+#endif
+
+ GetSensorResponse response{};
+
+ enableScanning(&response);
+
+ msg.read(properties);
+
+ auto iter = properties.find(
+ sensorInfo.propertyInterfaces.begin()->second.begin()->first);
+ if (iter == properties.end())
+ {
+ return {};
+ }
+
+ double value = std::get<T>(iter->second) *
+ std::pow(10, sensorInfo.scale - sensorInfo.exponentR);
+ int32_t rawData =
+ (value - sensorInfo.scaledOffset) / sensorInfo.coefficientM;
+
+ constexpr uint8_t sensorUnitsSignedBits = 2 << 6;
+ constexpr uint8_t signedDataFormat = 0x80;
+ // if sensorUnits1 [7:6] = 10b, sensor is signed
+ if ((sensorInfo.sensorUnits1 & sensorUnitsSignedBits) == signedDataFormat)
+ {
+ if (rawData > std::numeric_limits<int8_t>::max() ||
+ rawData < std::numeric_limits<int8_t>::lowest())
+ {
+ log<level::ERR>("Value out of range");
+ throw std::out_of_range("Value out of range");
+ }
+ setReading(static_cast<int8_t>(rawData), &response);
+ }
+ else
+ {
+ if (rawData > std::numeric_limits<uint8_t>::max() ||
+ rawData < std::numeric_limits<uint8_t>::lowest())
+ {
+ log<level::ERR>("Value out of range");
+ throw std::out_of_range("Value out of range");
+ }
+ setReading(static_cast<uint8_t>(rawData), &response);
+ }
+
+ if (!std::isfinite(value))
+ {
+ response.readingOrStateUnavailable = 1;
+ }
+
+ if (!sensorCacheMap[id].has_value())
+ {
+ sensorCacheMap[id] = SensorData{};
+ }
+ sensorCacheMap[id]->response = response;
+
+ return response;
}
#endif // FEATURE_SENSORS_CACHE