xref: /openbmc/bmcweb/features/redfish/lib/sensors.hpp (revision 43b761d0c8f5c4c39199093ee4bcd60698e77138)
108777fb0SLewanczyk, Dawid /*
208777fb0SLewanczyk, Dawid // Copyright (c) 2018 Intel Corporation
308777fb0SLewanczyk, Dawid //
408777fb0SLewanczyk, Dawid // Licensed under the Apache License, Version 2.0 (the "License");
508777fb0SLewanczyk, Dawid // you may not use this file except in compliance with the License.
608777fb0SLewanczyk, Dawid // You may obtain a copy of the License at
708777fb0SLewanczyk, Dawid //
808777fb0SLewanczyk, Dawid //      http://www.apache.org/licenses/LICENSE-2.0
908777fb0SLewanczyk, Dawid //
1008777fb0SLewanczyk, Dawid // Unless required by applicable law or agreed to in writing, software
1108777fb0SLewanczyk, Dawid // distributed under the License is distributed on an "AS IS" BASIS,
1208777fb0SLewanczyk, Dawid // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308777fb0SLewanczyk, Dawid // See the License for the specific language governing permissions and
1408777fb0SLewanczyk, Dawid // limitations under the License.
1508777fb0SLewanczyk, Dawid */
1608777fb0SLewanczyk, Dawid #pragma once
1708777fb0SLewanczyk, Dawid 
1808777fb0SLewanczyk, Dawid #include <math.h>
191abe55efSEd Tanous 
2008777fb0SLewanczyk, Dawid #include <boost/algorithm/string/predicate.hpp>
2108777fb0SLewanczyk, Dawid #include <boost/algorithm/string/split.hpp>
2208777fb0SLewanczyk, Dawid #include <boost/container/flat_map.hpp>
2308777fb0SLewanczyk, Dawid #include <boost/range/algorithm/replace_copy_if.hpp>
241abe55efSEd Tanous #include <dbus_singleton.hpp>
25abf2add6SEd Tanous #include <variant>
2608777fb0SLewanczyk, Dawid 
271abe55efSEd Tanous namespace redfish
281abe55efSEd Tanous {
2908777fb0SLewanczyk, Dawid 
30d76323e5SEd Tanous constexpr const char* dbusSensorPrefix = "/xyz/openbmc_project/sensors/";
3108777fb0SLewanczyk, Dawid 
3208777fb0SLewanczyk, Dawid using GetSubTreeType = std::vector<
3308777fb0SLewanczyk, Dawid     std::pair<std::string,
3408777fb0SLewanczyk, Dawid               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
3508777fb0SLewanczyk, Dawid 
36abf2add6SEd Tanous using SensorVariant = std::variant<int64_t, double>;
37aa2e59c1SEd Tanous 
3808777fb0SLewanczyk, Dawid using ManagedObjectsVectorType = std::vector<std::pair<
39aa2e59c1SEd Tanous     sdbusplus::message::object_path,
4008777fb0SLewanczyk, Dawid     boost::container::flat_map<
41aa2e59c1SEd Tanous         std::string, boost::container::flat_map<std::string, SensorVariant>>>>;
4208777fb0SLewanczyk, Dawid 
4308777fb0SLewanczyk, Dawid /**
44588c3f0dSKowalski, Kamil  * SensorsAsyncResp
4508777fb0SLewanczyk, Dawid  * Gathers data needed for response processing after async calls are done
4608777fb0SLewanczyk, Dawid  */
471abe55efSEd Tanous class SensorsAsyncResp
481abe55efSEd Tanous {
4908777fb0SLewanczyk, Dawid   public:
5055c7b7a2SEd Tanous     SensorsAsyncResp(crow::Response& response, const std::string& chassisId,
512474adfaSEd Tanous                      const std::initializer_list<const char*> types,
522474adfaSEd Tanous                      const std::string& subNode) :
53*43b761d0SEd Tanous         res(response),
54*43b761d0SEd Tanous         chassisId(chassisId), types(types), chassisSubNode(subNode)
551abe55efSEd Tanous     {
5655c7b7a2SEd Tanous         res.jsonValue["@odata.id"] =
5708777fb0SLewanczyk, Dawid             "/redfish/v1/Chassis/" + chassisId + "/Thermal";
5808777fb0SLewanczyk, Dawid     }
5908777fb0SLewanczyk, Dawid 
601abe55efSEd Tanous     ~SensorsAsyncResp()
611abe55efSEd Tanous     {
621abe55efSEd Tanous         if (res.result() == boost::beast::http::status::internal_server_error)
631abe55efSEd Tanous         {
641abe55efSEd Tanous             // Reset the json object to clear out any data that made it in
651abe55efSEd Tanous             // before the error happened todo(ed) handle error condition with
661abe55efSEd Tanous             // proper code
6755c7b7a2SEd Tanous             res.jsonValue = nlohmann::json::object();
6808777fb0SLewanczyk, Dawid         }
6908777fb0SLewanczyk, Dawid         res.end();
7008777fb0SLewanczyk, Dawid     }
71588c3f0dSKowalski, Kamil 
7255c7b7a2SEd Tanous     crow::Response& res;
73588c3f0dSKowalski, Kamil     std::string chassisId{};
7408777fb0SLewanczyk, Dawid     const std::vector<const char*> types;
752474adfaSEd Tanous     std::string chassisSubNode{};
7608777fb0SLewanczyk, Dawid };
7708777fb0SLewanczyk, Dawid 
7808777fb0SLewanczyk, Dawid /**
7908777fb0SLewanczyk, Dawid  * @brief Creates connections necessary for chassis sensors
80588c3f0dSKowalski, Kamil  * @param SensorsAsyncResp Pointer to object holding response data
8108777fb0SLewanczyk, Dawid  * @param sensorNames Sensors retrieved from chassis
8208777fb0SLewanczyk, Dawid  * @param callback Callback for processing gathered connections
8308777fb0SLewanczyk, Dawid  */
8408777fb0SLewanczyk, Dawid template <typename Callback>
85588c3f0dSKowalski, Kamil void getConnections(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
8608777fb0SLewanczyk, Dawid                     const boost::container::flat_set<std::string>& sensorNames,
871abe55efSEd Tanous                     Callback&& callback)
881abe55efSEd Tanous {
8955c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getConnections enter";
9003b5bae3SJames Feist     const std::string path = "/xyz/openbmc_project/sensors";
9108777fb0SLewanczyk, Dawid     const std::array<std::string, 1> interfaces = {
9208777fb0SLewanczyk, Dawid         "xyz.openbmc_project.Sensor.Value"};
9308777fb0SLewanczyk, Dawid 
9408777fb0SLewanczyk, Dawid     // Response handler for parsing objects subtree
951abe55efSEd Tanous     auto respHandler = [callback{std::move(callback)}, SensorsAsyncResp,
961abe55efSEd Tanous                         sensorNames](const boost::system::error_code ec,
971abe55efSEd Tanous                                      const GetSubTreeType& subtree) {
9855c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getConnections resp_handler enter";
991abe55efSEd Tanous         if (ec)
1001abe55efSEd Tanous         {
1015f7d88c4SEd Tanous             messages::internalError(SensorsAsyncResp->res);
1021abe55efSEd Tanous             BMCWEB_LOG_ERROR << "getConnections resp_handler: Dbus error "
1031abe55efSEd Tanous                              << ec;
10408777fb0SLewanczyk, Dawid             return;
10508777fb0SLewanczyk, Dawid         }
10608777fb0SLewanczyk, Dawid 
10755c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "Found " << subtree.size() << " subtrees";
10808777fb0SLewanczyk, Dawid 
10908777fb0SLewanczyk, Dawid         // Make unique list of connections only for requested sensor types and
11008777fb0SLewanczyk, Dawid         // found in the chassis
11108777fb0SLewanczyk, Dawid         boost::container::flat_set<std::string> connections;
1121abe55efSEd Tanous         // Intrinsic to avoid malloc.  Most systems will have < 8 sensor
1131abe55efSEd Tanous         // producers
11408777fb0SLewanczyk, Dawid         connections.reserve(8);
11508777fb0SLewanczyk, Dawid 
11655c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "sensorNames list count: " << sensorNames.size();
1171abe55efSEd Tanous         for (const std::string& tsensor : sensorNames)
1181abe55efSEd Tanous         {
11955c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "Sensor to find: " << tsensor;
12008777fb0SLewanczyk, Dawid         }
12108777fb0SLewanczyk, Dawid 
12208777fb0SLewanczyk, Dawid         for (const std::pair<
12308777fb0SLewanczyk, Dawid                  std::string,
12408777fb0SLewanczyk, Dawid                  std::vector<std::pair<std::string, std::vector<std::string>>>>&
1251abe55efSEd Tanous                  object : subtree)
1261abe55efSEd Tanous         {
1271abe55efSEd Tanous             for (const char* type : SensorsAsyncResp->types)
1281abe55efSEd Tanous             {
1291abe55efSEd Tanous                 if (boost::starts_with(object.first, type))
1301abe55efSEd Tanous                 {
13108777fb0SLewanczyk, Dawid                     auto lastPos = object.first.rfind('/');
1321abe55efSEd Tanous                     if (lastPos != std::string::npos)
1331abe55efSEd Tanous                     {
1341abe55efSEd Tanous                         std::string sensorName =
1351abe55efSEd Tanous                             object.first.substr(lastPos + 1);
13608777fb0SLewanczyk, Dawid 
1371abe55efSEd Tanous                         if (sensorNames.find(sensorName) != sensorNames.end())
1381abe55efSEd Tanous                         {
13955c7b7a2SEd Tanous                             // For each Connection name
1401abe55efSEd Tanous                             for (const std::pair<std::string,
1411abe55efSEd Tanous                                                  std::vector<std::string>>&
1421abe55efSEd Tanous                                      objData : object.second)
1431abe55efSEd Tanous                             {
1441abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG << "Adding connection: "
1451abe55efSEd Tanous                                                  << objData.first;
14608777fb0SLewanczyk, Dawid                                 connections.insert(objData.first);
14708777fb0SLewanczyk, Dawid                             }
14808777fb0SLewanczyk, Dawid                         }
14908777fb0SLewanczyk, Dawid                     }
15008777fb0SLewanczyk, Dawid                     break;
15108777fb0SLewanczyk, Dawid                 }
15208777fb0SLewanczyk, Dawid             }
15308777fb0SLewanczyk, Dawid         }
15455c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "Found " << connections.size() << " connections";
15508777fb0SLewanczyk, Dawid         callback(std::move(connections));
15655c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getConnections resp_handler exit";
15708777fb0SLewanczyk, Dawid     };
15808777fb0SLewanczyk, Dawid 
15908777fb0SLewanczyk, Dawid     // Make call to ObjectMapper to find all sensors objects
16055c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
16155c7b7a2SEd Tanous         std::move(respHandler), "xyz.openbmc_project.ObjectMapper",
1621abe55efSEd Tanous         "/xyz/openbmc_project/object_mapper",
1631abe55efSEd Tanous         "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, 2, interfaces);
16455c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getConnections exit";
16508777fb0SLewanczyk, Dawid }
16608777fb0SLewanczyk, Dawid 
16708777fb0SLewanczyk, Dawid /**
16808777fb0SLewanczyk, Dawid  * @brief Retrieves requested chassis sensors and redundancy data from DBus .
169588c3f0dSKowalski, Kamil  * @param SensorsAsyncResp   Pointer to object holding response data
17008777fb0SLewanczyk, Dawid  * @param callback  Callback for next step in gathered sensor processing
17108777fb0SLewanczyk, Dawid  */
17208777fb0SLewanczyk, Dawid template <typename Callback>
173588c3f0dSKowalski, Kamil void getChassis(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
1741abe55efSEd Tanous                 Callback&& callback)
1751abe55efSEd Tanous {
17655c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassis enter";
17708777fb0SLewanczyk, Dawid     // Process response from EntityManager and extract chassis data
1781abe55efSEd Tanous     auto respHandler = [callback{std::move(callback)},
1791abe55efSEd Tanous                         SensorsAsyncResp](const boost::system::error_code ec,
1801abe55efSEd Tanous                                           ManagedObjectsVectorType& resp) {
18155c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassis respHandler enter";
1821abe55efSEd Tanous         if (ec)
1831abe55efSEd Tanous         {
18455c7b7a2SEd Tanous             BMCWEB_LOG_ERROR << "getChassis respHandler DBUS error: " << ec;
1855f7d88c4SEd Tanous             messages::internalError(SensorsAsyncResp->res);
18608777fb0SLewanczyk, Dawid             return;
18708777fb0SLewanczyk, Dawid         }
18808777fb0SLewanczyk, Dawid         boost::container::flat_set<std::string> sensorNames;
18908777fb0SLewanczyk, Dawid 
190588c3f0dSKowalski, Kamil         //   SensorsAsyncResp->chassisId
191daf36e2eSEd Tanous         bool foundChassis = false;
192daf36e2eSEd Tanous         std::vector<std::string> split;
193daf36e2eSEd Tanous         // Reserve space for
194daf36e2eSEd Tanous         // /xyz/openbmc_project/inventory/<name>/<subname> + 3 subnames
195daf36e2eSEd Tanous         split.reserve(8);
196daf36e2eSEd Tanous 
1971abe55efSEd Tanous         for (const auto& objDictEntry : resp)
1981abe55efSEd Tanous         {
199daf36e2eSEd Tanous             const std::string& objectPath =
200daf36e2eSEd Tanous                 static_cast<const std::string&>(objDictEntry.first);
201daf36e2eSEd Tanous             boost::algorithm::split(split, objectPath, boost::is_any_of("/"));
2021abe55efSEd Tanous             if (split.size() < 2)
2031abe55efSEd Tanous             {
2041abe55efSEd Tanous                 BMCWEB_LOG_ERROR << "Got path that isn't long enough "
2051abe55efSEd Tanous                                  << objectPath;
206daf36e2eSEd Tanous                 split.clear();
207daf36e2eSEd Tanous                 continue;
208daf36e2eSEd Tanous             }
209daf36e2eSEd Tanous             const std::string& sensorName = split.end()[-1];
210daf36e2eSEd Tanous             const std::string& chassisName = split.end()[-2];
211daf36e2eSEd Tanous 
2121abe55efSEd Tanous             if (chassisName != SensorsAsyncResp->chassisId)
2131abe55efSEd Tanous             {
214daf36e2eSEd Tanous                 split.clear();
215daf36e2eSEd Tanous                 continue;
216daf36e2eSEd Tanous             }
21755c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "New sensor: " << sensorName;
218daf36e2eSEd Tanous             foundChassis = true;
21908777fb0SLewanczyk, Dawid             sensorNames.emplace(sensorName);
220daf36e2eSEd Tanous             split.clear();
22108777fb0SLewanczyk, Dawid         };
22255c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "Found " << sensorNames.size() << " Sensor names";
22308777fb0SLewanczyk, Dawid 
2241abe55efSEd Tanous         if (!foundChassis)
2251abe55efSEd Tanous         {
22655c7b7a2SEd Tanous             BMCWEB_LOG_INFO << "Unable to find chassis named "
227588c3f0dSKowalski, Kamil                             << SensorsAsyncResp->chassisId;
228f12894f8SJason M. Bills             messages::resourceNotFound(SensorsAsyncResp->res, "Chassis",
229f12894f8SJason M. Bills                                        SensorsAsyncResp->chassisId);
2301abe55efSEd Tanous         }
2311abe55efSEd Tanous         else
2321abe55efSEd Tanous         {
23308777fb0SLewanczyk, Dawid             callback(sensorNames);
23408777fb0SLewanczyk, Dawid         }
23555c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassis respHandler exit";
23608777fb0SLewanczyk, Dawid     };
23708777fb0SLewanczyk, Dawid 
23808777fb0SLewanczyk, Dawid     // Make call to EntityManager to find all chassis objects
23955c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
24055c7b7a2SEd Tanous         respHandler, "xyz.openbmc_project.EntityManager", "/",
2417885954aSLewanczyk, Dawid         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
24255c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassis exit";
24308777fb0SLewanczyk, Dawid }
24408777fb0SLewanczyk, Dawid 
24508777fb0SLewanczyk, Dawid /**
24608777fb0SLewanczyk, Dawid  * @brief Builds a json sensor representation of a sensor.
24708777fb0SLewanczyk, Dawid  * @param sensorName  The name of the sensor to be built
248274fad5aSGunnar Mills  * @param sensorType  The type (temperature, fan_tach, etc) of the sensor to
24908777fb0SLewanczyk, Dawid  * build
25008777fb0SLewanczyk, Dawid  * @param interfacesDict  A dictionary of the interfaces and properties of said
25108777fb0SLewanczyk, Dawid  * interfaces to be built from
25208777fb0SLewanczyk, Dawid  * @param sensor_json  The json object to fill
25308777fb0SLewanczyk, Dawid  */
25408777fb0SLewanczyk, Dawid void objectInterfacesToJson(
25508777fb0SLewanczyk, Dawid     const std::string& sensorName, const std::string& sensorType,
25608777fb0SLewanczyk, Dawid     const boost::container::flat_map<
257aa2e59c1SEd Tanous         std::string, boost::container::flat_map<std::string, SensorVariant>>&
25808777fb0SLewanczyk, Dawid         interfacesDict,
2591abe55efSEd Tanous     nlohmann::json& sensor_json)
2601abe55efSEd Tanous {
26108777fb0SLewanczyk, Dawid     // We need a value interface before we can do anything with it
26255c7b7a2SEd Tanous     auto valueIt = interfacesDict.find("xyz.openbmc_project.Sensor.Value");
2631abe55efSEd Tanous     if (valueIt == interfacesDict.end())
2641abe55efSEd Tanous     {
26555c7b7a2SEd Tanous         BMCWEB_LOG_ERROR << "Sensor doesn't have a value interface";
26608777fb0SLewanczyk, Dawid         return;
26708777fb0SLewanczyk, Dawid     }
26808777fb0SLewanczyk, Dawid 
26908777fb0SLewanczyk, Dawid     // Assume values exist as is (10^0 == 1) if no scale exists
27008777fb0SLewanczyk, Dawid     int64_t scaleMultiplier = 0;
27108777fb0SLewanczyk, Dawid 
27255c7b7a2SEd Tanous     auto scaleIt = valueIt->second.find("Scale");
27308777fb0SLewanczyk, Dawid     // If a scale exists, pull value as int64, and use the scaling.
2741abe55efSEd Tanous     if (scaleIt != valueIt->second.end())
2751abe55efSEd Tanous     {
276abf2add6SEd Tanous         const int64_t* int64Value = std::get_if<int64_t>(&scaleIt->second);
2771abe55efSEd Tanous         if (int64Value != nullptr)
2781abe55efSEd Tanous         {
27908777fb0SLewanczyk, Dawid             scaleMultiplier = *int64Value;
28008777fb0SLewanczyk, Dawid         }
28108777fb0SLewanczyk, Dawid     }
28208777fb0SLewanczyk, Dawid 
28308777fb0SLewanczyk, Dawid     sensor_json["MemberId"] = sensorName;
28408777fb0SLewanczyk, Dawid     sensor_json["Name"] = sensorName;
28508777fb0SLewanczyk, Dawid     sensor_json["Status"]["State"] = "Enabled";
28608777fb0SLewanczyk, Dawid     sensor_json["Status"]["Health"] = "OK";
28708777fb0SLewanczyk, Dawid 
28808777fb0SLewanczyk, Dawid     // Parameter to set to override the type we get from dbus, and force it to
28908777fb0SLewanczyk, Dawid     // int, regardless of what is available.  This is used for schemas like fan,
29008777fb0SLewanczyk, Dawid     // that require integers, not floats.
29108777fb0SLewanczyk, Dawid     bool forceToInt = false;
29208777fb0SLewanczyk, Dawid 
29308777fb0SLewanczyk, Dawid     const char* unit = "Reading";
2941abe55efSEd Tanous     if (sensorType == "temperature")
2951abe55efSEd Tanous     {
29608777fb0SLewanczyk, Dawid         unit = "ReadingCelsius";
2977885954aSLewanczyk, Dawid         sensor_json["@odata.type"] = "#Thermal.v1_3_0.Temperature";
29808777fb0SLewanczyk, Dawid         // TODO(ed) Documentation says that path should be type fan_tach,
29908777fb0SLewanczyk, Dawid         // implementation seems to implement fan
3001abe55efSEd Tanous     }
3011abe55efSEd Tanous     else if (sensorType == "fan" || sensorType == "fan_tach")
3021abe55efSEd Tanous     {
30308777fb0SLewanczyk, Dawid         unit = "Reading";
30408777fb0SLewanczyk, Dawid         sensor_json["ReadingUnits"] = "RPM";
3057885954aSLewanczyk, Dawid         sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
30608777fb0SLewanczyk, Dawid         forceToInt = true;
3071abe55efSEd Tanous     }
3086f6d0d32SEd Tanous     else if (sensorType == "fan_pwm")
3096f6d0d32SEd Tanous     {
3106f6d0d32SEd Tanous         unit = "Reading";
3116f6d0d32SEd Tanous         sensor_json["ReadingUnits"] = "Percent";
3126f6d0d32SEd Tanous         sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
3136f6d0d32SEd Tanous         forceToInt = true;
3146f6d0d32SEd Tanous     }
3151abe55efSEd Tanous     else if (sensorType == "voltage")
3161abe55efSEd Tanous     {
31708777fb0SLewanczyk, Dawid         unit = "ReadingVolts";
3187885954aSLewanczyk, Dawid         sensor_json["@odata.type"] = "#Power.v1_0_0.Voltage";
3191abe55efSEd Tanous     }
3202474adfaSEd Tanous     else if (sensorType == "power")
3212474adfaSEd Tanous     {
3222474adfaSEd Tanous         unit = "LastPowerOutputWatts";
3232474adfaSEd Tanous     }
3241abe55efSEd Tanous     else
3251abe55efSEd Tanous     {
32655c7b7a2SEd Tanous         BMCWEB_LOG_ERROR << "Redfish cannot map object type for " << sensorName;
32708777fb0SLewanczyk, Dawid         return;
32808777fb0SLewanczyk, Dawid     }
32908777fb0SLewanczyk, Dawid     // Map of dbus interface name, dbus property name and redfish property_name
33008777fb0SLewanczyk, Dawid     std::vector<std::tuple<const char*, const char*, const char*>> properties;
33108777fb0SLewanczyk, Dawid     properties.reserve(7);
33208777fb0SLewanczyk, Dawid 
33308777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Value", "Value", unit);
33408777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
33508777fb0SLewanczyk, Dawid                             "WarningHigh", "UpperThresholdNonCritical");
33608777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
33708777fb0SLewanczyk, Dawid                             "WarningLow", "LowerThresholdNonCritical");
33808777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
33908777fb0SLewanczyk, Dawid                             "CriticalHigh", "UpperThresholdCritical");
34008777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
34108777fb0SLewanczyk, Dawid                             "CriticalLow", "LowerThresholdCritical");
34208777fb0SLewanczyk, Dawid 
3432474adfaSEd Tanous     // TODO Need to get UpperThresholdFatal and LowerThresholdFatal
3442474adfaSEd Tanous 
3451abe55efSEd Tanous     if (sensorType == "temperature")
3461abe55efSEd Tanous     {
34708777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
34808777fb0SLewanczyk, Dawid                                 "MinReadingRangeTemp");
34908777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
35008777fb0SLewanczyk, Dawid                                 "MaxReadingRangeTemp");
3511abe55efSEd Tanous     }
3521abe55efSEd Tanous     else
3531abe55efSEd Tanous     {
35408777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
35508777fb0SLewanczyk, Dawid                                 "MinReadingRange");
35608777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
35708777fb0SLewanczyk, Dawid                                 "MaxReadingRange");
35808777fb0SLewanczyk, Dawid     }
35908777fb0SLewanczyk, Dawid 
36008777fb0SLewanczyk, Dawid     for (const std::tuple<const char*, const char*, const char*>& p :
3611abe55efSEd Tanous          properties)
3621abe55efSEd Tanous     {
36308777fb0SLewanczyk, Dawid         auto interfaceProperties = interfacesDict.find(std::get<0>(p));
3641abe55efSEd Tanous         if (interfaceProperties != interfacesDict.end())
3651abe55efSEd Tanous         {
36655c7b7a2SEd Tanous             auto valueIt = interfaceProperties->second.find(std::get<1>(p));
3671abe55efSEd Tanous             if (valueIt != interfaceProperties->second.end())
3681abe55efSEd Tanous             {
36955c7b7a2SEd Tanous                 const SensorVariant& valueVariant = valueIt->second;
37055c7b7a2SEd Tanous                 nlohmann::json& valueIt = sensor_json[std::get<2>(p)];
37108777fb0SLewanczyk, Dawid                 // Attempt to pull the int64 directly
372abf2add6SEd Tanous                 const int64_t* int64Value = std::get_if<int64_t>(&valueVariant);
37308777fb0SLewanczyk, Dawid 
374abf2add6SEd Tanous                 const double* doubleValue = std::get_if<double>(&valueVariant);
3756f6d0d32SEd Tanous                 double temp = 0.0;
3766f6d0d32SEd Tanous                 if (int64Value != nullptr)
3771abe55efSEd Tanous                 {
3786f6d0d32SEd Tanous                     temp = *int64Value;
3796f6d0d32SEd Tanous                 }
3806f6d0d32SEd Tanous                 else if (doubleValue != nullptr)
3811abe55efSEd Tanous                 {
3826f6d0d32SEd Tanous                     temp = *doubleValue;
3831abe55efSEd Tanous                 }
3841abe55efSEd Tanous                 else
3851abe55efSEd Tanous                 {
3866f6d0d32SEd Tanous                     BMCWEB_LOG_ERROR
3876f6d0d32SEd Tanous                         << "Got value interface that wasn't int or double";
3886f6d0d32SEd Tanous                     continue;
38908777fb0SLewanczyk, Dawid                 }
3906f6d0d32SEd Tanous                 temp = temp * std::pow(10, scaleMultiplier);
3916f6d0d32SEd Tanous                 if (forceToInt)
3926f6d0d32SEd Tanous                 {
3936f6d0d32SEd Tanous                     valueIt = static_cast<int64_t>(temp);
3946f6d0d32SEd Tanous                 }
3956f6d0d32SEd Tanous                 else
3966f6d0d32SEd Tanous                 {
3976f6d0d32SEd Tanous                     valueIt = temp;
39808777fb0SLewanczyk, Dawid                 }
39908777fb0SLewanczyk, Dawid             }
40008777fb0SLewanczyk, Dawid         }
40108777fb0SLewanczyk, Dawid     }
40255c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "Added sensor " << sensorName;
40308777fb0SLewanczyk, Dawid }
40408777fb0SLewanczyk, Dawid 
40508777fb0SLewanczyk, Dawid /**
40608777fb0SLewanczyk, Dawid  * @brief Entry point for retrieving sensors data related to requested
40708777fb0SLewanczyk, Dawid  *        chassis.
408588c3f0dSKowalski, Kamil  * @param SensorsAsyncResp   Pointer to object holding response data
40908777fb0SLewanczyk, Dawid  */
4101abe55efSEd Tanous void getChassisData(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp)
4111abe55efSEd Tanous {
41255c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassisData enter";
413588c3f0dSKowalski, Kamil     auto getChassisCb = [&, SensorsAsyncResp](
414588c3f0dSKowalski, Kamil                             boost::container::flat_set<std::string>&
41508777fb0SLewanczyk, Dawid                                 sensorNames) {
41655c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassisCb enter";
417588c3f0dSKowalski, Kamil         auto getConnectionCb =
418588c3f0dSKowalski, Kamil             [&, SensorsAsyncResp, sensorNames](
419588c3f0dSKowalski, Kamil                 const boost::container::flat_set<std::string>& connections) {
42055c7b7a2SEd Tanous                 BMCWEB_LOG_DEBUG << "getConnectionCb enter";
42108777fb0SLewanczyk, Dawid                 // Get managed objects from all services exposing sensors
4221abe55efSEd Tanous                 for (const std::string& connection : connections)
4231abe55efSEd Tanous                 {
42408777fb0SLewanczyk, Dawid                     // Response handler to process managed objects
4251abe55efSEd Tanous                     auto getManagedObjectsCb =
4261abe55efSEd Tanous                         [&, SensorsAsyncResp,
4271abe55efSEd Tanous                          sensorNames](const boost::system::error_code ec,
42808777fb0SLewanczyk, Dawid                                       ManagedObjectsVectorType& resp) {
42955c7b7a2SEd Tanous                             BMCWEB_LOG_DEBUG << "getManagedObjectsCb enter";
4301abe55efSEd Tanous                             if (ec)
4311abe55efSEd Tanous                             {
4321abe55efSEd Tanous                                 BMCWEB_LOG_ERROR
4331abe55efSEd Tanous                                     << "getManagedObjectsCb DBUS error: " << ec;
4345f7d88c4SEd Tanous                                 messages::internalError(SensorsAsyncResp->res);
4357885954aSLewanczyk, Dawid                                 return;
4367885954aSLewanczyk, Dawid                             }
43708777fb0SLewanczyk, Dawid                             // Go through all objects and update response with
43808777fb0SLewanczyk, Dawid                             // sensor data
4391abe55efSEd Tanous                             for (const auto& objDictEntry : resp)
4401abe55efSEd Tanous                             {
441aa2e59c1SEd Tanous                                 const std::string& objPath =
4421abe55efSEd Tanous                                     static_cast<const std::string&>(
4431abe55efSEd Tanous                                         objDictEntry.first);
4441abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
4451abe55efSEd Tanous                                     << "getManagedObjectsCb parsing object "
446588c3f0dSKowalski, Kamil                                     << objPath;
447e0d918bcSEd Tanous 
44808777fb0SLewanczyk, Dawid                                 std::vector<std::string> split;
44908777fb0SLewanczyk, Dawid                                 // Reserve space for
45003b5bae3SJames Feist                                 // /xyz/openbmc_project/sensors/<name>/<subname>
45108777fb0SLewanczyk, Dawid                                 split.reserve(6);
4521abe55efSEd Tanous                                 boost::algorithm::split(split, objPath,
4531abe55efSEd Tanous                                                         boost::is_any_of("/"));
4541abe55efSEd Tanous                                 if (split.size() < 6)
4551abe55efSEd Tanous                                 {
4561abe55efSEd Tanous                                     BMCWEB_LOG_ERROR
4571abe55efSEd Tanous                                         << "Got path that isn't long enough "
458588c3f0dSKowalski, Kamil                                         << objPath;
45908777fb0SLewanczyk, Dawid                                     continue;
46008777fb0SLewanczyk, Dawid                                 }
4611abe55efSEd Tanous                                 // These indexes aren't intuitive, as
4621abe55efSEd Tanous                                 // boost::split puts an empty string at the
4631abe55efSEd Tanous                                 // beggining
46408777fb0SLewanczyk, Dawid                                 const std::string& sensorType = split[4];
46508777fb0SLewanczyk, Dawid                                 const std::string& sensorName = split[5];
46655c7b7a2SEd Tanous                                 BMCWEB_LOG_DEBUG << "sensorName " << sensorName
4671abe55efSEd Tanous                                                  << " sensorType "
4681abe55efSEd Tanous                                                  << sensorType;
4691abe55efSEd Tanous                                 if (sensorNames.find(sensorName) ==
4701abe55efSEd Tanous                                     sensorNames.end())
4711abe55efSEd Tanous                                 {
4721abe55efSEd Tanous                                     BMCWEB_LOG_ERROR << sensorName
4731abe55efSEd Tanous                                                      << " not in sensor list ";
47408777fb0SLewanczyk, Dawid                                     continue;
47508777fb0SLewanczyk, Dawid                                 }
47608777fb0SLewanczyk, Dawid 
47708777fb0SLewanczyk, Dawid                                 const char* fieldName = nullptr;
4781abe55efSEd Tanous                                 if (sensorType == "temperature")
4791abe55efSEd Tanous                                 {
48008777fb0SLewanczyk, Dawid                                     fieldName = "Temperatures";
4811abe55efSEd Tanous                                 }
4821abe55efSEd Tanous                                 else if (sensorType == "fan" ||
4836f6d0d32SEd Tanous                                          sensorType == "fan_tach" ||
4846f6d0d32SEd Tanous                                          sensorType == "fan_pwm")
4851abe55efSEd Tanous                                 {
48608777fb0SLewanczyk, Dawid                                     fieldName = "Fans";
4871abe55efSEd Tanous                                 }
4881abe55efSEd Tanous                                 else if (sensorType == "voltage")
4891abe55efSEd Tanous                                 {
49008777fb0SLewanczyk, Dawid                                     fieldName = "Voltages";
4911abe55efSEd Tanous                                 }
4921abe55efSEd Tanous                                 else if (sensorType == "current")
4931abe55efSEd Tanous                                 {
49408777fb0SLewanczyk, Dawid                                     fieldName = "PowerSupply";
4951abe55efSEd Tanous                                 }
4961abe55efSEd Tanous                                 else if (sensorType == "power")
4971abe55efSEd Tanous                                 {
49808777fb0SLewanczyk, Dawid                                     fieldName = "PowerSupply";
4991abe55efSEd Tanous                                 }
5001abe55efSEd Tanous                                 else
5011abe55efSEd Tanous                                 {
5021abe55efSEd Tanous                                     BMCWEB_LOG_ERROR
5031abe55efSEd Tanous                                         << "Unsure how to handle sensorType "
50408777fb0SLewanczyk, Dawid                                         << sensorType;
50508777fb0SLewanczyk, Dawid                                     continue;
50608777fb0SLewanczyk, Dawid                                 }
50708777fb0SLewanczyk, Dawid 
50855c7b7a2SEd Tanous                                 nlohmann::json& tempArray =
50955c7b7a2SEd Tanous                                     SensorsAsyncResp->res.jsonValue[fieldName];
51008777fb0SLewanczyk, Dawid 
51155c7b7a2SEd Tanous                                 tempArray.push_back(
5121abe55efSEd Tanous                                     {{"@odata.id",
5131abe55efSEd Tanous                                       "/redfish/v1/Chassis/" +
5142474adfaSEd Tanous                                           SensorsAsyncResp->chassisId + "/" +
5152474adfaSEd Tanous                                           SensorsAsyncResp->chassisSubNode +
5162474adfaSEd Tanous                                           "#/" + fieldName + "/" +
5176f6d0d32SEd Tanous                                           std::to_string(tempArray.size())}});
51855c7b7a2SEd Tanous                                 nlohmann::json& sensorJson = tempArray.back();
5196f6d0d32SEd Tanous 
520588c3f0dSKowalski, Kamil                                 objectInterfacesToJson(sensorName, sensorType,
5211abe55efSEd Tanous                                                        objDictEntry.second,
5221abe55efSEd Tanous                                                        sensorJson);
52308777fb0SLewanczyk, Dawid                             }
52455c7b7a2SEd Tanous                             BMCWEB_LOG_DEBUG << "getManagedObjectsCb exit";
52508777fb0SLewanczyk, Dawid                         };
52655c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
5277885954aSLewanczyk, Dawid                         getManagedObjectsCb, connection, "/",
5281abe55efSEd Tanous                         "org.freedesktop.DBus.ObjectManager",
5291abe55efSEd Tanous                         "GetManagedObjects");
53008777fb0SLewanczyk, Dawid                 };
53155c7b7a2SEd Tanous                 BMCWEB_LOG_DEBUG << "getConnectionCb exit";
53208777fb0SLewanczyk, Dawid             };
53355c7b7a2SEd Tanous         // get connections and then pass it to get sensors
5341abe55efSEd Tanous         getConnections(SensorsAsyncResp, sensorNames,
5351abe55efSEd Tanous                        std::move(getConnectionCb));
53655c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassisCb exit";
53708777fb0SLewanczyk, Dawid     };
53808777fb0SLewanczyk, Dawid 
53955c7b7a2SEd Tanous     // get chassis information related to sensors
540588c3f0dSKowalski, Kamil     getChassis(SensorsAsyncResp, std::move(getChassisCb));
54155c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassisData exit";
54208777fb0SLewanczyk, Dawid };
54308777fb0SLewanczyk, Dawid 
54408777fb0SLewanczyk, Dawid } // namespace redfish
545