dbus-sdr: support Get Temperature Readings command
This commit support Get Temperature Readings command in the
dynamicsensor library.
The design follows teps:
- Get the list of sensors based on Entity Id
- Sort the list of sensors.
- Loop all of sensors in the list, if its Entity Instance is greater
than the Instance Start then read the temperature via object path.
Tested:
1. Request to read Temperature of sensors
"ipmitool dcmi get_temp_reading"
2. Display Entity Id, Entity Instance, Temperature of sensors
Change-Id: Iaa7d65a763dacb50c1488d2a161b180fed49899b
Signed-off-by: Thang Tran <thuutran@amperecomputing.com>
diff --git a/dbus-sdr/sensorcommands.cpp b/dbus-sdr/sensorcommands.cpp
index 8c9d686..55ba6d9 100644
--- a/dbus-sdr/sensorcommands.cpp
+++ b/dbus-sdr/sensorcommands.cpp
@@ -2601,6 +2601,54 @@
return std::make_tuple(totalInstSensor, sensorList);
}
+std::tuple<bool, // Reading result
+ uint7_t, // Temp value
+ bool> // Sign bit
+ readTemp(ipmi::Context::ptr ctx, const std::string& objectPath)
+{
+ std::string service{};
+ boost::system::error_code ec =
+ ipmi::getService(ctx, sensor::sensorInterface, objectPath, service);
+ if (ec.value())
+ {
+ return std::make_tuple(false, 0, false);
+ }
+
+ ipmi::PropertyMap properties{};
+ ec = ipmi::getAllDbusProperties(ctx, service, objectPath,
+ sensor::sensorInterface, properties);
+ if (ec.value())
+ {
+ return std::make_tuple(false, 0, false);
+ }
+
+ auto scaleIt = properties.find("Scale");
+ double scaleVal = 0.0;
+ if (scaleIt != properties.end())
+ {
+ scaleVal = std::visit(ipmi::VariantToDoubleVisitor(), scaleIt->second);
+ }
+
+ auto tempValIt = properties.find("Value");
+ double tempVal = 0.0;
+ if (tempValIt == properties.end())
+ {
+ return std::make_tuple(false, 0, false);
+ }
+
+ const double maxTemp = 127;
+ double absTempVal = 0.0;
+ bool signBit = false;
+
+ tempVal = std::visit(ipmi::VariantToDoubleVisitor(), tempValIt->second);
+ tempVal = std::pow(10, scaleVal) * tempVal;
+ absTempVal = std::abs(tempVal);
+ absTempVal = std::min(absTempVal, maxTemp);
+ signBit = (tempVal < 0) ? true : false;
+
+ return std::make_tuple(true, static_cast<uint7_t>(absTempVal), signBit);
+}
+
ipmi::RspType<uint8_t, // No of instances for requested id
uint8_t, // No of record ids in the response
std::vector<uint16_t> // SDR Record ID corresponding to the Entity
@@ -2654,6 +2702,73 @@
return ipmi::responseSuccess(
totalSensorInst, static_cast<uint8_t>(sensorRec.size()), sensorRec);
}
+
+ipmi::RspType<uint8_t, // No of instances for requested id
+ uint8_t, // No of record ids in the response
+ std::vector< // Temperature Data
+ std::tuple<uint7_t, // Temperature value
+ bool, // Sign bit
+ uint8_t // Entity Instance of sensor
+ >>>
+ getTempReadings(ipmi::Context::ptr ctx, uint8_t sensorType,
+ uint8_t entityId, uint8_t entityInstance,
+ uint8_t instanceStart)
+{
+ auto match = ipmi::dcmi::validEntityId.find(entityId);
+ if (match == ipmi::dcmi::validEntityId.end())
+ {
+ log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", entityId));
+
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+ if (sensorType != ipmi::dcmi::temperatureSensorType)
+ {
+ log<level::ERR>("Invalid sensor type",
+ entry("SENSOR_TYPE=%d", sensorType));
+
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+ std::vector<std::tuple<uint7_t, bool, uint8_t>> tempReadingVal{};
+ const auto& [totalSensorInst, sensorList] =
+ getSensorsByEntityId(ctx, entityId, entityInstance, instanceStart);
+
+ if (sensorList.empty())
+ {
+ return ipmi::responseSuccess(totalSensorInst, 0, tempReadingVal);
+ }
+
+ /*
+ * As DCMI specification, the maximum number of Record Ids of response data
+ * is 1 if Entity Instance paramter is not 0. Else the maximum number of
+ * Record Ids of response data is 8. Therefore, not all of sensors are shown
+ * in response data.
+ */
+ uint8_t numOfRec = (entityInstance != 0) ? 1 : ipmi::dcmi::maxRecords;
+
+ for (const auto& sensor : sensorList)
+ {
+ const auto& [readResult, tempVal,
+ signBit] = readTemp(ctx, sensor.objectPath);
+
+ if (readResult)
+ {
+ tempReadingVal.emplace_back(
+ std::make_tuple(tempVal, signBit, sensor.entityInstance));
+
+ if (tempReadingVal.size() >= numOfRec)
+ {
+ break;
+ }
+ }
+ }
+
+ return ipmi::responseSuccess(totalSensorInst,
+ static_cast<uint8_t>(tempReadingVal.size()),
+ tempReadingVal);
+}
+
} // namespace dcmi
/* end storage commands */
@@ -2738,5 +2853,10 @@
ipmi::dcmi::cmdGetDcmiSensorInfo,
ipmi::Privilege::Operator,
ipmi::dcmi::getSensorInfo);
+ // <Get Temperature Readings>
+ ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
+ ipmi::dcmi::cmdGetTemperatureReadings,
+ ipmi::Privilege::User,
+ ipmi::dcmi::getTempReadings);
}
} // namespace ipmi
diff --git a/dcmihandler.cpp b/dcmihandler.cpp
index 07f1b63..da6fced 100644
--- a/dcmihandler.cpp
+++ b/dcmihandler.cpp
@@ -1193,11 +1193,6 @@
ipmi::dcmi::cmdGetDcmiCapabilitiesInfo,
ipmi::Privilege::User, getDCMICapabilities);
- // <Get Temperature Readings>
- registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
- ipmi::dcmi::cmdGetTemperatureReadings,
- ipmi::Privilege::User, getTempReadings);
-
// <Get Power Reading>
registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
ipmi::dcmi::cmdGetPowerReading, ipmi::Privilege::User,
@@ -1210,6 +1205,11 @@
registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
ipmi::dcmi::cmdGetDcmiSensorInfo,
ipmi::Privilege::Operator, getSensorInfo);
+
+ // <Get Temperature Readings>
+ registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
+ ipmi::dcmi::cmdGetTemperatureReadings,
+ ipmi::Privilege::User, getTempReadings);
#endif
// <Get DCMI Configuration Parameters>
registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,