xref: /openbmc/bmcweb/features/redfish/lib/sensors.hpp (revision 6f6d0d32f282477558ab3235f1d162d6207e2c58)
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>
2508777fb0SLewanczyk, Dawid 
261abe55efSEd Tanous namespace redfish
271abe55efSEd Tanous {
2808777fb0SLewanczyk, Dawid 
29d76323e5SEd Tanous constexpr const char* dbusSensorPrefix = "/xyz/openbmc_project/sensors/";
3008777fb0SLewanczyk, Dawid 
3108777fb0SLewanczyk, Dawid using GetSubTreeType = std::vector<
3208777fb0SLewanczyk, Dawid     std::pair<std::string,
3308777fb0SLewanczyk, Dawid               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
3408777fb0SLewanczyk, Dawid 
35aa2e59c1SEd Tanous using SensorVariant = sdbusplus::message::variant<int64_t, double>;
36aa2e59c1SEd Tanous 
3708777fb0SLewanczyk, Dawid using ManagedObjectsVectorType = std::vector<std::pair<
38aa2e59c1SEd Tanous     sdbusplus::message::object_path,
3908777fb0SLewanczyk, Dawid     boost::container::flat_map<
40aa2e59c1SEd Tanous         std::string, boost::container::flat_map<std::string, SensorVariant>>>>;
4108777fb0SLewanczyk, Dawid 
4208777fb0SLewanczyk, Dawid /**
43588c3f0dSKowalski, Kamil  * SensorsAsyncResp
4408777fb0SLewanczyk, Dawid  * Gathers data needed for response processing after async calls are done
4508777fb0SLewanczyk, Dawid  */
461abe55efSEd Tanous class SensorsAsyncResp
471abe55efSEd Tanous {
4808777fb0SLewanczyk, Dawid   public:
4955c7b7a2SEd Tanous     SensorsAsyncResp(crow::Response& response, const std::string& chassisId,
501abe55efSEd Tanous                      const std::initializer_list<const char*> types) :
511abe55efSEd Tanous         res(response),
521abe55efSEd Tanous         chassisId(chassisId), types(types)
531abe55efSEd Tanous     {
5455c7b7a2SEd Tanous         res.jsonValue["@odata.id"] =
5508777fb0SLewanczyk, Dawid             "/redfish/v1/Chassis/" + chassisId + "/Thermal";
5608777fb0SLewanczyk, Dawid     }
5708777fb0SLewanczyk, Dawid 
581abe55efSEd Tanous     ~SensorsAsyncResp()
591abe55efSEd Tanous     {
601abe55efSEd Tanous         if (res.result() == boost::beast::http::status::internal_server_error)
611abe55efSEd Tanous         {
621abe55efSEd Tanous             // Reset the json object to clear out any data that made it in
631abe55efSEd Tanous             // before the error happened todo(ed) handle error condition with
641abe55efSEd Tanous             // proper code
6555c7b7a2SEd Tanous             res.jsonValue = nlohmann::json::object();
6608777fb0SLewanczyk, Dawid         }
6708777fb0SLewanczyk, Dawid         res.end();
6808777fb0SLewanczyk, Dawid     }
69588c3f0dSKowalski, Kamil 
701abe55efSEd Tanous     void setErrorStatus()
711abe55efSEd Tanous     {
72e0d918bcSEd Tanous         res.result(boost::beast::http::status::internal_server_error);
7308777fb0SLewanczyk, Dawid     }
7408777fb0SLewanczyk, Dawid 
7555c7b7a2SEd Tanous     crow::Response& res;
76588c3f0dSKowalski, Kamil     std::string chassisId{};
7708777fb0SLewanczyk, Dawid     const std::vector<const char*> types;
7808777fb0SLewanczyk, Dawid };
7908777fb0SLewanczyk, Dawid 
8008777fb0SLewanczyk, Dawid /**
8108777fb0SLewanczyk, Dawid  * @brief Creates connections necessary for chassis sensors
82588c3f0dSKowalski, Kamil  * @param SensorsAsyncResp Pointer to object holding response data
8308777fb0SLewanczyk, Dawid  * @param sensorNames Sensors retrieved from chassis
8408777fb0SLewanczyk, Dawid  * @param callback Callback for processing gathered connections
8508777fb0SLewanczyk, Dawid  */
8608777fb0SLewanczyk, Dawid template <typename Callback>
87588c3f0dSKowalski, Kamil void getConnections(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
8808777fb0SLewanczyk, Dawid                     const boost::container::flat_set<std::string>& sensorNames,
891abe55efSEd Tanous                     Callback&& callback)
901abe55efSEd Tanous {
9155c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getConnections enter";
9203b5bae3SJames Feist     const std::string path = "/xyz/openbmc_project/sensors";
9308777fb0SLewanczyk, Dawid     const std::array<std::string, 1> interfaces = {
9408777fb0SLewanczyk, Dawid         "xyz.openbmc_project.Sensor.Value"};
9508777fb0SLewanczyk, Dawid 
9608777fb0SLewanczyk, Dawid     // Response handler for parsing objects subtree
971abe55efSEd Tanous     auto respHandler = [callback{std::move(callback)}, SensorsAsyncResp,
981abe55efSEd Tanous                         sensorNames](const boost::system::error_code ec,
991abe55efSEd Tanous                                      const GetSubTreeType& subtree) {
10055c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getConnections resp_handler enter";
1011abe55efSEd Tanous         if (ec)
1021abe55efSEd Tanous         {
103588c3f0dSKowalski, Kamil             SensorsAsyncResp->setErrorStatus();
1041abe55efSEd Tanous             BMCWEB_LOG_ERROR << "getConnections resp_handler: Dbus error "
1051abe55efSEd Tanous                              << ec;
10608777fb0SLewanczyk, Dawid             return;
10708777fb0SLewanczyk, Dawid         }
10808777fb0SLewanczyk, Dawid 
10955c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "Found " << subtree.size() << " subtrees";
11008777fb0SLewanczyk, Dawid 
11108777fb0SLewanczyk, Dawid         // Make unique list of connections only for requested sensor types and
11208777fb0SLewanczyk, Dawid         // found in the chassis
11308777fb0SLewanczyk, Dawid         boost::container::flat_set<std::string> connections;
1141abe55efSEd Tanous         // Intrinsic to avoid malloc.  Most systems will have < 8 sensor
1151abe55efSEd Tanous         // producers
11608777fb0SLewanczyk, Dawid         connections.reserve(8);
11708777fb0SLewanczyk, Dawid 
11855c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "sensorNames list count: " << sensorNames.size();
1191abe55efSEd Tanous         for (const std::string& tsensor : sensorNames)
1201abe55efSEd Tanous         {
12155c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "Sensor to find: " << tsensor;
12208777fb0SLewanczyk, Dawid         }
12308777fb0SLewanczyk, Dawid 
12408777fb0SLewanczyk, Dawid         for (const std::pair<
12508777fb0SLewanczyk, Dawid                  std::string,
12608777fb0SLewanczyk, Dawid                  std::vector<std::pair<std::string, std::vector<std::string>>>>&
1271abe55efSEd Tanous                  object : subtree)
1281abe55efSEd Tanous         {
1291abe55efSEd Tanous             for (const char* type : SensorsAsyncResp->types)
1301abe55efSEd Tanous             {
1311abe55efSEd Tanous                 if (boost::starts_with(object.first, type))
1321abe55efSEd Tanous                 {
13308777fb0SLewanczyk, Dawid                     auto lastPos = object.first.rfind('/');
1341abe55efSEd Tanous                     if (lastPos != std::string::npos)
1351abe55efSEd Tanous                     {
1361abe55efSEd Tanous                         std::string sensorName =
1371abe55efSEd Tanous                             object.first.substr(lastPos + 1);
13808777fb0SLewanczyk, Dawid 
1391abe55efSEd Tanous                         if (sensorNames.find(sensorName) != sensorNames.end())
1401abe55efSEd Tanous                         {
14155c7b7a2SEd Tanous                             // For each Connection name
1421abe55efSEd Tanous                             for (const std::pair<std::string,
1431abe55efSEd Tanous                                                  std::vector<std::string>>&
1441abe55efSEd Tanous                                      objData : object.second)
1451abe55efSEd Tanous                             {
1461abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG << "Adding connection: "
1471abe55efSEd Tanous                                                  << objData.first;
14808777fb0SLewanczyk, Dawid                                 connections.insert(objData.first);
14908777fb0SLewanczyk, Dawid                             }
15008777fb0SLewanczyk, Dawid                         }
15108777fb0SLewanczyk, Dawid                     }
15208777fb0SLewanczyk, Dawid                     break;
15308777fb0SLewanczyk, Dawid                 }
15408777fb0SLewanczyk, Dawid             }
15508777fb0SLewanczyk, Dawid         }
15655c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "Found " << connections.size() << " connections";
15708777fb0SLewanczyk, Dawid         callback(std::move(connections));
15855c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getConnections resp_handler exit";
15908777fb0SLewanczyk, Dawid     };
16008777fb0SLewanczyk, Dawid 
16108777fb0SLewanczyk, Dawid     // Make call to ObjectMapper to find all sensors objects
16255c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
16355c7b7a2SEd Tanous         std::move(respHandler), "xyz.openbmc_project.ObjectMapper",
1641abe55efSEd Tanous         "/xyz/openbmc_project/object_mapper",
1651abe55efSEd Tanous         "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, 2, interfaces);
16655c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getConnections exit";
16708777fb0SLewanczyk, Dawid }
16808777fb0SLewanczyk, Dawid 
16908777fb0SLewanczyk, Dawid /**
17008777fb0SLewanczyk, Dawid  * @brief Retrieves requested chassis sensors and redundancy data from DBus .
171588c3f0dSKowalski, Kamil  * @param SensorsAsyncResp   Pointer to object holding response data
17208777fb0SLewanczyk, Dawid  * @param callback  Callback for next step in gathered sensor processing
17308777fb0SLewanczyk, Dawid  */
17408777fb0SLewanczyk, Dawid template <typename Callback>
175588c3f0dSKowalski, Kamil void getChassis(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
1761abe55efSEd Tanous                 Callback&& callback)
1771abe55efSEd Tanous {
17855c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassis enter";
17908777fb0SLewanczyk, Dawid     // Process response from EntityManager and extract chassis data
1801abe55efSEd Tanous     auto respHandler = [callback{std::move(callback)},
1811abe55efSEd Tanous                         SensorsAsyncResp](const boost::system::error_code ec,
1821abe55efSEd Tanous                                           ManagedObjectsVectorType& resp) {
18355c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassis respHandler enter";
1841abe55efSEd Tanous         if (ec)
1851abe55efSEd Tanous         {
18655c7b7a2SEd Tanous             BMCWEB_LOG_ERROR << "getChassis respHandler DBUS error: " << ec;
187588c3f0dSKowalski, Kamil             SensorsAsyncResp->setErrorStatus();
18808777fb0SLewanczyk, Dawid             return;
18908777fb0SLewanczyk, Dawid         }
19008777fb0SLewanczyk, Dawid         boost::container::flat_set<std::string> sensorNames;
19108777fb0SLewanczyk, Dawid 
192588c3f0dSKowalski, Kamil         //   SensorsAsyncResp->chassisId
193daf36e2eSEd Tanous         bool foundChassis = false;
194daf36e2eSEd Tanous         std::vector<std::string> split;
195daf36e2eSEd Tanous         // Reserve space for
196daf36e2eSEd Tanous         // /xyz/openbmc_project/inventory/<name>/<subname> + 3 subnames
197daf36e2eSEd Tanous         split.reserve(8);
198daf36e2eSEd Tanous 
1991abe55efSEd Tanous         for (const auto& objDictEntry : resp)
2001abe55efSEd Tanous         {
201daf36e2eSEd Tanous             const std::string& objectPath =
202daf36e2eSEd Tanous                 static_cast<const std::string&>(objDictEntry.first);
203daf36e2eSEd Tanous             boost::algorithm::split(split, objectPath, boost::is_any_of("/"));
2041abe55efSEd Tanous             if (split.size() < 2)
2051abe55efSEd Tanous             {
2061abe55efSEd Tanous                 BMCWEB_LOG_ERROR << "Got path that isn't long enough "
2071abe55efSEd Tanous                                  << objectPath;
208daf36e2eSEd Tanous                 split.clear();
209daf36e2eSEd Tanous                 continue;
210daf36e2eSEd Tanous             }
211daf36e2eSEd Tanous             const std::string& sensorName = split.end()[-1];
212daf36e2eSEd Tanous             const std::string& chassisName = split.end()[-2];
213daf36e2eSEd Tanous 
2141abe55efSEd Tanous             if (chassisName != SensorsAsyncResp->chassisId)
2151abe55efSEd Tanous             {
216daf36e2eSEd Tanous                 split.clear();
217daf36e2eSEd Tanous                 continue;
218daf36e2eSEd Tanous             }
21955c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "New sensor: " << sensorName;
220daf36e2eSEd Tanous             foundChassis = true;
22108777fb0SLewanczyk, Dawid             sensorNames.emplace(sensorName);
222daf36e2eSEd Tanous             split.clear();
22308777fb0SLewanczyk, Dawid         };
22455c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "Found " << sensorNames.size() << " Sensor names";
22508777fb0SLewanczyk, Dawid 
2261abe55efSEd Tanous         if (!foundChassis)
2271abe55efSEd Tanous         {
22855c7b7a2SEd Tanous             BMCWEB_LOG_INFO << "Unable to find chassis named "
229588c3f0dSKowalski, Kamil                             << SensorsAsyncResp->chassisId;
230588c3f0dSKowalski, Kamil             SensorsAsyncResp->res.result(boost::beast::http::status::not_found);
2311abe55efSEd Tanous         }
2321abe55efSEd Tanous         else
2331abe55efSEd Tanous         {
23408777fb0SLewanczyk, Dawid             callback(sensorNames);
23508777fb0SLewanczyk, Dawid         }
23655c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassis respHandler exit";
23708777fb0SLewanczyk, Dawid     };
23808777fb0SLewanczyk, Dawid 
23908777fb0SLewanczyk, Dawid     // Make call to EntityManager to find all chassis objects
24055c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
24155c7b7a2SEd Tanous         respHandler, "xyz.openbmc_project.EntityManager", "/",
2427885954aSLewanczyk, Dawid         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
24355c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassis exit";
24408777fb0SLewanczyk, Dawid }
24508777fb0SLewanczyk, Dawid 
24608777fb0SLewanczyk, Dawid /**
24708777fb0SLewanczyk, Dawid  * @brief Builds a json sensor representation of a sensor.
24808777fb0SLewanczyk, Dawid  * @param sensorName  The name of the sensor to be built
249274fad5aSGunnar Mills  * @param sensorType  The type (temperature, fan_tach, etc) of the sensor to
25008777fb0SLewanczyk, Dawid  * build
25108777fb0SLewanczyk, Dawid  * @param interfacesDict  A dictionary of the interfaces and properties of said
25208777fb0SLewanczyk, Dawid  * interfaces to be built from
25308777fb0SLewanczyk, Dawid  * @param sensor_json  The json object to fill
25408777fb0SLewanczyk, Dawid  */
25508777fb0SLewanczyk, Dawid void objectInterfacesToJson(
25608777fb0SLewanczyk, Dawid     const std::string& sensorName, const std::string& sensorType,
25708777fb0SLewanczyk, Dawid     const boost::container::flat_map<
258aa2e59c1SEd Tanous         std::string, boost::container::flat_map<std::string, SensorVariant>>&
25908777fb0SLewanczyk, Dawid         interfacesDict,
2601abe55efSEd Tanous     nlohmann::json& sensor_json)
2611abe55efSEd Tanous {
26208777fb0SLewanczyk, Dawid     // We need a value interface before we can do anything with it
26355c7b7a2SEd Tanous     auto valueIt = interfacesDict.find("xyz.openbmc_project.Sensor.Value");
2641abe55efSEd Tanous     if (valueIt == interfacesDict.end())
2651abe55efSEd Tanous     {
26655c7b7a2SEd Tanous         BMCWEB_LOG_ERROR << "Sensor doesn't have a value interface";
26708777fb0SLewanczyk, Dawid         return;
26808777fb0SLewanczyk, Dawid     }
26908777fb0SLewanczyk, Dawid 
27008777fb0SLewanczyk, Dawid     // Assume values exist as is (10^0 == 1) if no scale exists
27108777fb0SLewanczyk, Dawid     int64_t scaleMultiplier = 0;
27208777fb0SLewanczyk, Dawid 
27355c7b7a2SEd Tanous     auto scaleIt = valueIt->second.find("Scale");
27408777fb0SLewanczyk, Dawid     // If a scale exists, pull value as int64, and use the scaling.
2751abe55efSEd Tanous     if (scaleIt != valueIt->second.end())
2761abe55efSEd Tanous     {
2771abe55efSEd Tanous         const int64_t* int64Value =
2781abe55efSEd Tanous             mapbox::getPtr<const int64_t>(scaleIt->second);
2791abe55efSEd Tanous         if (int64Value != nullptr)
2801abe55efSEd Tanous         {
28108777fb0SLewanczyk, Dawid             scaleMultiplier = *int64Value;
28208777fb0SLewanczyk, Dawid         }
28308777fb0SLewanczyk, Dawid     }
28408777fb0SLewanczyk, Dawid 
28508777fb0SLewanczyk, Dawid     sensor_json["MemberId"] = sensorName;
28608777fb0SLewanczyk, Dawid     sensor_json["Name"] = sensorName;
28708777fb0SLewanczyk, Dawid     sensor_json["Status"]["State"] = "Enabled";
28808777fb0SLewanczyk, Dawid     sensor_json["Status"]["Health"] = "OK";
28908777fb0SLewanczyk, Dawid 
29008777fb0SLewanczyk, Dawid     // Parameter to set to override the type we get from dbus, and force it to
29108777fb0SLewanczyk, Dawid     // int, regardless of what is available.  This is used for schemas like fan,
29208777fb0SLewanczyk, Dawid     // that require integers, not floats.
29308777fb0SLewanczyk, Dawid     bool forceToInt = false;
29408777fb0SLewanczyk, Dawid 
29508777fb0SLewanczyk, Dawid     const char* unit = "Reading";
2961abe55efSEd Tanous     if (sensorType == "temperature")
2971abe55efSEd Tanous     {
29808777fb0SLewanczyk, Dawid         unit = "ReadingCelsius";
2997885954aSLewanczyk, Dawid         sensor_json["@odata.type"] = "#Thermal.v1_3_0.Temperature";
30008777fb0SLewanczyk, Dawid         // TODO(ed) Documentation says that path should be type fan_tach,
30108777fb0SLewanczyk, Dawid         // implementation seems to implement fan
3021abe55efSEd Tanous     }
3031abe55efSEd Tanous     else if (sensorType == "fan" || sensorType == "fan_tach")
3041abe55efSEd Tanous     {
30508777fb0SLewanczyk, Dawid         unit = "Reading";
30608777fb0SLewanczyk, Dawid         sensor_json["ReadingUnits"] = "RPM";
3077885954aSLewanczyk, Dawid         sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
30808777fb0SLewanczyk, Dawid         forceToInt = true;
3091abe55efSEd Tanous     }
310*6f6d0d32SEd Tanous     else if (sensorType == "fan_pwm")
311*6f6d0d32SEd Tanous     {
312*6f6d0d32SEd Tanous         unit = "Reading";
313*6f6d0d32SEd Tanous         sensor_json["ReadingUnits"] = "Percent";
314*6f6d0d32SEd Tanous         sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
315*6f6d0d32SEd Tanous         forceToInt = true;
316*6f6d0d32SEd Tanous     }
3171abe55efSEd Tanous     else if (sensorType == "voltage")
3181abe55efSEd Tanous     {
31908777fb0SLewanczyk, Dawid         unit = "ReadingVolts";
3207885954aSLewanczyk, Dawid         sensor_json["@odata.type"] = "#Power.v1_0_0.Voltage";
3211abe55efSEd Tanous     }
3221abe55efSEd Tanous     else
3231abe55efSEd Tanous     {
32455c7b7a2SEd Tanous         BMCWEB_LOG_ERROR << "Redfish cannot map object type for " << sensorName;
32508777fb0SLewanczyk, Dawid         return;
32608777fb0SLewanczyk, Dawid     }
32708777fb0SLewanczyk, Dawid     // Map of dbus interface name, dbus property name and redfish property_name
32808777fb0SLewanczyk, Dawid     std::vector<std::tuple<const char*, const char*, const char*>> properties;
32908777fb0SLewanczyk, Dawid     properties.reserve(7);
33008777fb0SLewanczyk, Dawid 
33108777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Value", "Value", unit);
33208777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
33308777fb0SLewanczyk, Dawid                             "WarningHigh", "UpperThresholdNonCritical");
33408777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
33508777fb0SLewanczyk, Dawid                             "WarningLow", "LowerThresholdNonCritical");
33608777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
33708777fb0SLewanczyk, Dawid                             "CriticalHigh", "UpperThresholdCritical");
33808777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
33908777fb0SLewanczyk, Dawid                             "CriticalLow", "LowerThresholdCritical");
34008777fb0SLewanczyk, Dawid 
3411abe55efSEd Tanous     if (sensorType == "temperature")
3421abe55efSEd Tanous     {
34308777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
34408777fb0SLewanczyk, Dawid                                 "MinReadingRangeTemp");
34508777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
34608777fb0SLewanczyk, Dawid                                 "MaxReadingRangeTemp");
3471abe55efSEd Tanous     }
3481abe55efSEd Tanous     else
3491abe55efSEd Tanous     {
35008777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
35108777fb0SLewanczyk, Dawid                                 "MinReadingRange");
35208777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
35308777fb0SLewanczyk, Dawid                                 "MaxReadingRange");
35408777fb0SLewanczyk, Dawid     }
35508777fb0SLewanczyk, Dawid 
35608777fb0SLewanczyk, Dawid     for (const std::tuple<const char*, const char*, const char*>& p :
3571abe55efSEd Tanous          properties)
3581abe55efSEd Tanous     {
35908777fb0SLewanczyk, Dawid         auto interfaceProperties = interfacesDict.find(std::get<0>(p));
3601abe55efSEd Tanous         if (interfaceProperties != interfacesDict.end())
3611abe55efSEd Tanous         {
36255c7b7a2SEd Tanous             auto valueIt = interfaceProperties->second.find(std::get<1>(p));
3631abe55efSEd Tanous             if (valueIt != interfaceProperties->second.end())
3641abe55efSEd Tanous             {
36555c7b7a2SEd Tanous                 const SensorVariant& valueVariant = valueIt->second;
36655c7b7a2SEd Tanous                 nlohmann::json& valueIt = sensor_json[std::get<2>(p)];
36708777fb0SLewanczyk, Dawid                 // Attempt to pull the int64 directly
3681abe55efSEd Tanous                 const int64_t* int64Value =
3691abe55efSEd Tanous                     mapbox::getPtr<const int64_t>(valueVariant);
37008777fb0SLewanczyk, Dawid 
3711abe55efSEd Tanous                 const double* doubleValue =
3721abe55efSEd Tanous                     mapbox::getPtr<const double>(valueVariant);
373*6f6d0d32SEd Tanous                 double temp = 0.0;
374*6f6d0d32SEd Tanous                 if (int64Value != nullptr)
3751abe55efSEd Tanous                 {
376*6f6d0d32SEd Tanous                     temp = *int64Value;
377*6f6d0d32SEd Tanous                 }
378*6f6d0d32SEd Tanous                 else if (doubleValue != nullptr)
3791abe55efSEd Tanous                 {
380*6f6d0d32SEd Tanous                     temp = *doubleValue;
3811abe55efSEd Tanous                 }
3821abe55efSEd Tanous                 else
3831abe55efSEd Tanous                 {
384*6f6d0d32SEd Tanous                     BMCWEB_LOG_ERROR
385*6f6d0d32SEd Tanous                         << "Got value interface that wasn't int or double";
386*6f6d0d32SEd Tanous                     continue;
38708777fb0SLewanczyk, Dawid                 }
388*6f6d0d32SEd Tanous                 temp = temp * std::pow(10, scaleMultiplier);
389*6f6d0d32SEd Tanous                 if (forceToInt)
390*6f6d0d32SEd Tanous                 {
391*6f6d0d32SEd Tanous                     valueIt = static_cast<int64_t>(temp);
392*6f6d0d32SEd Tanous                 }
393*6f6d0d32SEd Tanous                 else
394*6f6d0d32SEd Tanous                 {
395*6f6d0d32SEd Tanous                     valueIt = temp;
39608777fb0SLewanczyk, Dawid                 }
39708777fb0SLewanczyk, Dawid             }
39808777fb0SLewanczyk, Dawid         }
39908777fb0SLewanczyk, Dawid     }
40055c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "Added sensor " << sensorName;
40108777fb0SLewanczyk, Dawid }
40208777fb0SLewanczyk, Dawid 
40308777fb0SLewanczyk, Dawid /**
40408777fb0SLewanczyk, Dawid  * @brief Entry point for retrieving sensors data related to requested
40508777fb0SLewanczyk, Dawid  *        chassis.
406588c3f0dSKowalski, Kamil  * @param SensorsAsyncResp   Pointer to object holding response data
40708777fb0SLewanczyk, Dawid  */
4081abe55efSEd Tanous void getChassisData(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp)
4091abe55efSEd Tanous {
41055c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassisData enter";
411588c3f0dSKowalski, Kamil     auto getChassisCb = [&, SensorsAsyncResp](
412588c3f0dSKowalski, Kamil                             boost::container::flat_set<std::string>&
41308777fb0SLewanczyk, Dawid                                 sensorNames) {
41455c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassisCb enter";
415588c3f0dSKowalski, Kamil         auto getConnectionCb =
416588c3f0dSKowalski, Kamil             [&, SensorsAsyncResp, sensorNames](
417588c3f0dSKowalski, Kamil                 const boost::container::flat_set<std::string>& connections) {
41855c7b7a2SEd Tanous                 BMCWEB_LOG_DEBUG << "getConnectionCb enter";
41908777fb0SLewanczyk, Dawid                 // Get managed objects from all services exposing sensors
4201abe55efSEd Tanous                 for (const std::string& connection : connections)
4211abe55efSEd Tanous                 {
42208777fb0SLewanczyk, Dawid                     // Response handler to process managed objects
4231abe55efSEd Tanous                     auto getManagedObjectsCb =
4241abe55efSEd Tanous                         [&, SensorsAsyncResp,
4251abe55efSEd Tanous                          sensorNames](const boost::system::error_code ec,
42608777fb0SLewanczyk, Dawid                                       ManagedObjectsVectorType& resp) {
42755c7b7a2SEd Tanous                             BMCWEB_LOG_DEBUG << "getManagedObjectsCb enter";
4281abe55efSEd Tanous                             if (ec)
4291abe55efSEd Tanous                             {
4301abe55efSEd Tanous                                 BMCWEB_LOG_ERROR
4311abe55efSEd Tanous                                     << "getManagedObjectsCb DBUS error: " << ec;
4327885954aSLewanczyk, Dawid                                 SensorsAsyncResp->setErrorStatus();
4337885954aSLewanczyk, Dawid                                 return;
4347885954aSLewanczyk, Dawid                             }
43508777fb0SLewanczyk, Dawid                             // Go through all objects and update response with
43608777fb0SLewanczyk, Dawid                             // sensor data
4371abe55efSEd Tanous                             for (const auto& objDictEntry : resp)
4381abe55efSEd Tanous                             {
439aa2e59c1SEd Tanous                                 const std::string& objPath =
4401abe55efSEd Tanous                                     static_cast<const std::string&>(
4411abe55efSEd Tanous                                         objDictEntry.first);
4421abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
4431abe55efSEd Tanous                                     << "getManagedObjectsCb parsing object "
444588c3f0dSKowalski, Kamil                                     << objPath;
445e0d918bcSEd Tanous 
44608777fb0SLewanczyk, Dawid                                 std::vector<std::string> split;
44708777fb0SLewanczyk, Dawid                                 // Reserve space for
44803b5bae3SJames Feist                                 // /xyz/openbmc_project/sensors/<name>/<subname>
44908777fb0SLewanczyk, Dawid                                 split.reserve(6);
4501abe55efSEd Tanous                                 boost::algorithm::split(split, objPath,
4511abe55efSEd Tanous                                                         boost::is_any_of("/"));
4521abe55efSEd Tanous                                 if (split.size() < 6)
4531abe55efSEd Tanous                                 {
4541abe55efSEd Tanous                                     BMCWEB_LOG_ERROR
4551abe55efSEd Tanous                                         << "Got path that isn't long enough "
456588c3f0dSKowalski, Kamil                                         << objPath;
45708777fb0SLewanczyk, Dawid                                     continue;
45808777fb0SLewanczyk, Dawid                                 }
4591abe55efSEd Tanous                                 // These indexes aren't intuitive, as
4601abe55efSEd Tanous                                 // boost::split puts an empty string at the
4611abe55efSEd Tanous                                 // beggining
46208777fb0SLewanczyk, Dawid                                 const std::string& sensorType = split[4];
46308777fb0SLewanczyk, Dawid                                 const std::string& sensorName = split[5];
46455c7b7a2SEd Tanous                                 BMCWEB_LOG_DEBUG << "sensorName " << sensorName
4651abe55efSEd Tanous                                                  << " sensorType "
4661abe55efSEd Tanous                                                  << sensorType;
4671abe55efSEd Tanous                                 if (sensorNames.find(sensorName) ==
4681abe55efSEd Tanous                                     sensorNames.end())
4691abe55efSEd Tanous                                 {
4701abe55efSEd Tanous                                     BMCWEB_LOG_ERROR << sensorName
4711abe55efSEd Tanous                                                      << " not in sensor list ";
47208777fb0SLewanczyk, Dawid                                     continue;
47308777fb0SLewanczyk, Dawid                                 }
47408777fb0SLewanczyk, Dawid 
47508777fb0SLewanczyk, Dawid                                 const char* fieldName = nullptr;
4761abe55efSEd Tanous                                 if (sensorType == "temperature")
4771abe55efSEd Tanous                                 {
47808777fb0SLewanczyk, Dawid                                     fieldName = "Temperatures";
4791abe55efSEd Tanous                                 }
4801abe55efSEd Tanous                                 else if (sensorType == "fan" ||
481*6f6d0d32SEd Tanous                                          sensorType == "fan_tach" ||
482*6f6d0d32SEd Tanous                                          sensorType == "fan_pwm")
4831abe55efSEd Tanous                                 {
48408777fb0SLewanczyk, Dawid                                     fieldName = "Fans";
4851abe55efSEd Tanous                                 }
4861abe55efSEd Tanous                                 else if (sensorType == "voltage")
4871abe55efSEd Tanous                                 {
48808777fb0SLewanczyk, Dawid                                     fieldName = "Voltages";
4891abe55efSEd Tanous                                 }
4901abe55efSEd Tanous                                 else if (sensorType == "current")
4911abe55efSEd Tanous                                 {
49208777fb0SLewanczyk, Dawid                                     fieldName = "PowerSupply";
4931abe55efSEd Tanous                                 }
4941abe55efSEd Tanous                                 else if (sensorType == "power")
4951abe55efSEd Tanous                                 {
49608777fb0SLewanczyk, Dawid                                     fieldName = "PowerSupply";
4971abe55efSEd Tanous                                 }
4981abe55efSEd Tanous                                 else
4991abe55efSEd Tanous                                 {
5001abe55efSEd Tanous                                     BMCWEB_LOG_ERROR
5011abe55efSEd Tanous                                         << "Unsure how to handle sensorType "
50208777fb0SLewanczyk, Dawid                                         << sensorType;
50308777fb0SLewanczyk, Dawid                                     continue;
50408777fb0SLewanczyk, Dawid                                 }
50508777fb0SLewanczyk, Dawid 
50655c7b7a2SEd Tanous                                 nlohmann::json& tempArray =
50755c7b7a2SEd Tanous                                     SensorsAsyncResp->res.jsonValue[fieldName];
50808777fb0SLewanczyk, Dawid 
50955c7b7a2SEd Tanous                                 tempArray.push_back(
5101abe55efSEd Tanous                                     {{"@odata.id",
5111abe55efSEd Tanous                                       "/redfish/v1/Chassis/" +
512588c3f0dSKowalski, Kamil                                           SensorsAsyncResp->chassisId +
513*6f6d0d32SEd Tanous                                           "/Thermal#/" + fieldName + "/" +
514*6f6d0d32SEd Tanous                                           std::to_string(tempArray.size())}});
51555c7b7a2SEd Tanous                                 nlohmann::json& sensorJson = tempArray.back();
516*6f6d0d32SEd Tanous 
517588c3f0dSKowalski, Kamil                                 objectInterfacesToJson(sensorName, sensorType,
5181abe55efSEd Tanous                                                        objDictEntry.second,
5191abe55efSEd Tanous                                                        sensorJson);
52008777fb0SLewanczyk, Dawid                             }
52155c7b7a2SEd Tanous                             BMCWEB_LOG_DEBUG << "getManagedObjectsCb exit";
52208777fb0SLewanczyk, Dawid                         };
52355c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
5247885954aSLewanczyk, Dawid                         getManagedObjectsCb, connection, "/",
5251abe55efSEd Tanous                         "org.freedesktop.DBus.ObjectManager",
5261abe55efSEd Tanous                         "GetManagedObjects");
52708777fb0SLewanczyk, Dawid                 };
52855c7b7a2SEd Tanous                 BMCWEB_LOG_DEBUG << "getConnectionCb exit";
52908777fb0SLewanczyk, Dawid             };
53055c7b7a2SEd Tanous         // get connections and then pass it to get sensors
5311abe55efSEd Tanous         getConnections(SensorsAsyncResp, sensorNames,
5321abe55efSEd Tanous                        std::move(getConnectionCb));
53355c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassisCb exit";
53408777fb0SLewanczyk, Dawid     };
53508777fb0SLewanczyk, Dawid 
53655c7b7a2SEd Tanous     // get chassis information related to sensors
537588c3f0dSKowalski, Kamil     getChassis(SensorsAsyncResp, std::move(getChassisCb));
53855c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassisData exit";
53908777fb0SLewanczyk, Dawid };
54008777fb0SLewanczyk, Dawid 
54108777fb0SLewanczyk, Dawid } // namespace redfish
542