xref: /openbmc/bmcweb/features/redfish/lib/sensors.hpp (revision 413961de57624a9eb35f46f143ba44f99f40b7ac)
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>
25*413961deSRichard Marian Thomaiyar #include <utils/json_utils.hpp>
26abf2add6SEd Tanous #include <variant>
2708777fb0SLewanczyk, Dawid 
281abe55efSEd Tanous namespace redfish
291abe55efSEd Tanous {
3008777fb0SLewanczyk, Dawid 
31d76323e5SEd Tanous constexpr const char* dbusSensorPrefix = "/xyz/openbmc_project/sensors/";
3208777fb0SLewanczyk, Dawid 
3308777fb0SLewanczyk, Dawid using GetSubTreeType = std::vector<
3408777fb0SLewanczyk, Dawid     std::pair<std::string,
3508777fb0SLewanczyk, Dawid               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
3608777fb0SLewanczyk, Dawid 
37abf2add6SEd Tanous using SensorVariant = std::variant<int64_t, double>;
38aa2e59c1SEd Tanous 
3908777fb0SLewanczyk, Dawid using ManagedObjectsVectorType = std::vector<std::pair<
40aa2e59c1SEd Tanous     sdbusplus::message::object_path,
4108777fb0SLewanczyk, Dawid     boost::container::flat_map<
42aa2e59c1SEd Tanous         std::string, boost::container::flat_map<std::string, SensorVariant>>>>;
4308777fb0SLewanczyk, Dawid 
4408777fb0SLewanczyk, Dawid /**
45588c3f0dSKowalski, Kamil  * SensorsAsyncResp
4608777fb0SLewanczyk, Dawid  * Gathers data needed for response processing after async calls are done
4708777fb0SLewanczyk, Dawid  */
481abe55efSEd Tanous class SensorsAsyncResp
491abe55efSEd Tanous {
5008777fb0SLewanczyk, Dawid   public:
5155c7b7a2SEd Tanous     SensorsAsyncResp(crow::Response& response, const std::string& chassisId,
522474adfaSEd Tanous                      const std::initializer_list<const char*> types,
532474adfaSEd Tanous                      const std::string& subNode) :
5443b761d0SEd Tanous         res(response),
5543b761d0SEd Tanous         chassisId(chassisId), types(types), chassisSubNode(subNode)
561abe55efSEd Tanous     {
5755c7b7a2SEd Tanous         res.jsonValue["@odata.id"] =
58*413961deSRichard Marian Thomaiyar             "/redfish/v1/Chassis/" + chassisId + "/" + subNode;
5908777fb0SLewanczyk, Dawid     }
6008777fb0SLewanczyk, Dawid 
611abe55efSEd Tanous     ~SensorsAsyncResp()
621abe55efSEd Tanous     {
631abe55efSEd Tanous         if (res.result() == boost::beast::http::status::internal_server_error)
641abe55efSEd Tanous         {
651abe55efSEd Tanous             // Reset the json object to clear out any data that made it in
661abe55efSEd Tanous             // before the error happened todo(ed) handle error condition with
671abe55efSEd Tanous             // proper code
6855c7b7a2SEd Tanous             res.jsonValue = nlohmann::json::object();
6908777fb0SLewanczyk, Dawid         }
7008777fb0SLewanczyk, Dawid         res.end();
7108777fb0SLewanczyk, Dawid     }
72588c3f0dSKowalski, Kamil 
7355c7b7a2SEd Tanous     crow::Response& res;
74588c3f0dSKowalski, Kamil     std::string chassisId{};
7508777fb0SLewanczyk, Dawid     const std::vector<const char*> types;
762474adfaSEd Tanous     std::string chassisSubNode{};
7708777fb0SLewanczyk, Dawid };
7808777fb0SLewanczyk, Dawid 
7908777fb0SLewanczyk, Dawid /**
80*413961deSRichard Marian Thomaiyar  * @brief Get objects with connection necessary for sensors
81588c3f0dSKowalski, Kamil  * @param SensorsAsyncResp Pointer to object holding response data
8208777fb0SLewanczyk, Dawid  * @param sensorNames Sensors retrieved from chassis
8308777fb0SLewanczyk, Dawid  * @param callback Callback for processing gathered connections
8408777fb0SLewanczyk, Dawid  */
8508777fb0SLewanczyk, Dawid template <typename Callback>
86*413961deSRichard Marian Thomaiyar void getObjectsWithConnection(
87*413961deSRichard Marian Thomaiyar     std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
8808777fb0SLewanczyk, Dawid     const boost::container::flat_set<std::string>& sensorNames,
891abe55efSEd Tanous     Callback&& callback)
901abe55efSEd Tanous {
91*413961deSRichard Marian Thomaiyar     BMCWEB_LOG_DEBUG << "getObjectsWithConnection 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) {
100*413961deSRichard Marian Thomaiyar         BMCWEB_LOG_DEBUG << "getObjectsWithConnection resp_handler enter";
1011abe55efSEd Tanous         if (ec)
1021abe55efSEd Tanous         {
1035f7d88c4SEd Tanous             messages::internalError(SensorsAsyncResp->res);
104*413961deSRichard Marian Thomaiyar             BMCWEB_LOG_ERROR
105*413961deSRichard Marian Thomaiyar                 << "getObjectsWithConnection resp_handler: Dbus error " << 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;
114*413961deSRichard Marian Thomaiyar         std::set<std::pair<std::string, std::string>> objectsWithConnection;
1151abe55efSEd Tanous         // Intrinsic to avoid malloc.  Most systems will have < 8 sensor
1161abe55efSEd Tanous         // producers
11708777fb0SLewanczyk, Dawid         connections.reserve(8);
11808777fb0SLewanczyk, Dawid 
11955c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "sensorNames list count: " << sensorNames.size();
1201abe55efSEd Tanous         for (const std::string& tsensor : sensorNames)
1211abe55efSEd Tanous         {
12255c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "Sensor to find: " << tsensor;
12308777fb0SLewanczyk, Dawid         }
12408777fb0SLewanczyk, Dawid 
12508777fb0SLewanczyk, Dawid         for (const std::pair<
12608777fb0SLewanczyk, Dawid                  std::string,
12708777fb0SLewanczyk, Dawid                  std::vector<std::pair<std::string, std::vector<std::string>>>>&
1281abe55efSEd Tanous                  object : subtree)
1291abe55efSEd Tanous         {
1301abe55efSEd Tanous             for (const char* type : SensorsAsyncResp->types)
1311abe55efSEd Tanous             {
1321abe55efSEd Tanous                 if (boost::starts_with(object.first, type))
1331abe55efSEd Tanous                 {
13408777fb0SLewanczyk, Dawid                     auto lastPos = object.first.rfind('/');
1351abe55efSEd Tanous                     if (lastPos != std::string::npos)
1361abe55efSEd Tanous                     {
1371abe55efSEd Tanous                         std::string sensorName =
1381abe55efSEd Tanous                             object.first.substr(lastPos + 1);
13908777fb0SLewanczyk, Dawid 
1401abe55efSEd Tanous                         if (sensorNames.find(sensorName) != sensorNames.end())
1411abe55efSEd Tanous                         {
14255c7b7a2SEd Tanous                             // For each Connection name
1431abe55efSEd Tanous                             for (const std::pair<std::string,
1441abe55efSEd Tanous                                                  std::vector<std::string>>&
1451abe55efSEd Tanous                                      objData : object.second)
1461abe55efSEd Tanous                             {
1471abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG << "Adding connection: "
1481abe55efSEd Tanous                                                  << objData.first;
14908777fb0SLewanczyk, Dawid                                 connections.insert(objData.first);
150*413961deSRichard Marian Thomaiyar                                 objectsWithConnection.insert(std::make_pair(
151*413961deSRichard Marian Thomaiyar                                     object.first, objData.first));
15208777fb0SLewanczyk, Dawid                             }
15308777fb0SLewanczyk, Dawid                         }
15408777fb0SLewanczyk, Dawid                     }
15508777fb0SLewanczyk, Dawid                     break;
15608777fb0SLewanczyk, Dawid                 }
15708777fb0SLewanczyk, Dawid             }
15808777fb0SLewanczyk, Dawid         }
15955c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "Found " << connections.size() << " connections";
160*413961deSRichard Marian Thomaiyar         callback(std::move(connections), std::move(objectsWithConnection));
161*413961deSRichard Marian Thomaiyar         BMCWEB_LOG_DEBUG << "getObjectsWithConnection resp_handler exit";
16208777fb0SLewanczyk, Dawid     };
16308777fb0SLewanczyk, Dawid     // Make call to ObjectMapper to find all sensors objects
16455c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
16555c7b7a2SEd Tanous         std::move(respHandler), "xyz.openbmc_project.ObjectMapper",
1661abe55efSEd Tanous         "/xyz/openbmc_project/object_mapper",
1671abe55efSEd Tanous         "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, 2, interfaces);
168*413961deSRichard Marian Thomaiyar     BMCWEB_LOG_DEBUG << "getObjectsWithConnection exit";
169*413961deSRichard Marian Thomaiyar }
170*413961deSRichard Marian Thomaiyar 
171*413961deSRichard Marian Thomaiyar /**
172*413961deSRichard Marian Thomaiyar  * @brief Create connections necessary for sensors
173*413961deSRichard Marian Thomaiyar  * @param SensorsAsyncResp Pointer to object holding response data
174*413961deSRichard Marian Thomaiyar  * @param sensorNames Sensors retrieved from chassis
175*413961deSRichard Marian Thomaiyar  * @param callback Callback for processing gathered connections
176*413961deSRichard Marian Thomaiyar  */
177*413961deSRichard Marian Thomaiyar template <typename Callback>
178*413961deSRichard Marian Thomaiyar void getConnections(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
179*413961deSRichard Marian Thomaiyar                     const boost::container::flat_set<std::string>& sensorNames,
180*413961deSRichard Marian Thomaiyar                     Callback&& callback)
181*413961deSRichard Marian Thomaiyar {
182*413961deSRichard Marian Thomaiyar     auto objectsWithConnectionCb =
183*413961deSRichard Marian Thomaiyar         [callback](const boost::container::flat_set<std::string>& connections,
184*413961deSRichard Marian Thomaiyar                    const std::set<std::pair<std::string, std::string>>&
185*413961deSRichard Marian Thomaiyar                        objectsWithConnection) {
186*413961deSRichard Marian Thomaiyar             callback(std::move(connections));
187*413961deSRichard Marian Thomaiyar         };
188*413961deSRichard Marian Thomaiyar     getObjectsWithConnection(SensorsAsyncResp, sensorNames,
189*413961deSRichard Marian Thomaiyar                              std::move(objectsWithConnectionCb));
19008777fb0SLewanczyk, Dawid }
19108777fb0SLewanczyk, Dawid 
19208777fb0SLewanczyk, Dawid /**
19308777fb0SLewanczyk, Dawid  * @brief Retrieves requested chassis sensors and redundancy data from DBus .
194588c3f0dSKowalski, Kamil  * @param SensorsAsyncResp   Pointer to object holding response data
19508777fb0SLewanczyk, Dawid  * @param callback  Callback for next step in gathered sensor processing
19608777fb0SLewanczyk, Dawid  */
19708777fb0SLewanczyk, Dawid template <typename Callback>
198588c3f0dSKowalski, Kamil void getChassis(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
1991abe55efSEd Tanous                 Callback&& callback)
2001abe55efSEd Tanous {
20155c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassis enter";
20208777fb0SLewanczyk, Dawid     // Process response from EntityManager and extract chassis data
2031abe55efSEd Tanous     auto respHandler = [callback{std::move(callback)},
2041abe55efSEd Tanous                         SensorsAsyncResp](const boost::system::error_code ec,
2051abe55efSEd Tanous                                           ManagedObjectsVectorType& resp) {
20655c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassis respHandler enter";
2071abe55efSEd Tanous         if (ec)
2081abe55efSEd Tanous         {
20955c7b7a2SEd Tanous             BMCWEB_LOG_ERROR << "getChassis respHandler DBUS error: " << ec;
2105f7d88c4SEd Tanous             messages::internalError(SensorsAsyncResp->res);
21108777fb0SLewanczyk, Dawid             return;
21208777fb0SLewanczyk, Dawid         }
21308777fb0SLewanczyk, Dawid         boost::container::flat_set<std::string> sensorNames;
21408777fb0SLewanczyk, Dawid 
215588c3f0dSKowalski, Kamil         //   SensorsAsyncResp->chassisId
216daf36e2eSEd Tanous         bool foundChassis = false;
217daf36e2eSEd Tanous         std::vector<std::string> split;
218daf36e2eSEd Tanous         // Reserve space for
219daf36e2eSEd Tanous         // /xyz/openbmc_project/inventory/<name>/<subname> + 3 subnames
220daf36e2eSEd Tanous         split.reserve(8);
221daf36e2eSEd Tanous 
2221abe55efSEd Tanous         for (const auto& objDictEntry : resp)
2231abe55efSEd Tanous         {
224daf36e2eSEd Tanous             const std::string& objectPath =
225daf36e2eSEd Tanous                 static_cast<const std::string&>(objDictEntry.first);
226daf36e2eSEd Tanous             boost::algorithm::split(split, objectPath, boost::is_any_of("/"));
2271abe55efSEd Tanous             if (split.size() < 2)
2281abe55efSEd Tanous             {
2291abe55efSEd Tanous                 BMCWEB_LOG_ERROR << "Got path that isn't long enough "
2301abe55efSEd Tanous                                  << objectPath;
231daf36e2eSEd Tanous                 split.clear();
232daf36e2eSEd Tanous                 continue;
233daf36e2eSEd Tanous             }
234daf36e2eSEd Tanous             const std::string& sensorName = split.end()[-1];
235daf36e2eSEd Tanous             const std::string& chassisName = split.end()[-2];
236daf36e2eSEd Tanous 
2371abe55efSEd Tanous             if (chassisName != SensorsAsyncResp->chassisId)
2381abe55efSEd Tanous             {
239daf36e2eSEd Tanous                 split.clear();
240daf36e2eSEd Tanous                 continue;
241daf36e2eSEd Tanous             }
24255c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "New sensor: " << sensorName;
243daf36e2eSEd Tanous             foundChassis = true;
24408777fb0SLewanczyk, Dawid             sensorNames.emplace(sensorName);
245daf36e2eSEd Tanous             split.clear();
24608777fb0SLewanczyk, Dawid         };
24755c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "Found " << sensorNames.size() << " Sensor names";
24808777fb0SLewanczyk, Dawid 
2491abe55efSEd Tanous         if (!foundChassis)
2501abe55efSEd Tanous         {
25155c7b7a2SEd Tanous             BMCWEB_LOG_INFO << "Unable to find chassis named "
252588c3f0dSKowalski, Kamil                             << SensorsAsyncResp->chassisId;
253f12894f8SJason M. Bills             messages::resourceNotFound(SensorsAsyncResp->res, "Chassis",
254f12894f8SJason M. Bills                                        SensorsAsyncResp->chassisId);
2551abe55efSEd Tanous         }
2561abe55efSEd Tanous         else
2571abe55efSEd Tanous         {
25808777fb0SLewanczyk, Dawid             callback(sensorNames);
25908777fb0SLewanczyk, Dawid         }
26055c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassis respHandler exit";
26108777fb0SLewanczyk, Dawid     };
26208777fb0SLewanczyk, Dawid 
26308777fb0SLewanczyk, Dawid     // Make call to EntityManager to find all chassis objects
26455c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
26555c7b7a2SEd Tanous         respHandler, "xyz.openbmc_project.EntityManager", "/",
2667885954aSLewanczyk, Dawid         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
26755c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassis exit";
26808777fb0SLewanczyk, Dawid }
26908777fb0SLewanczyk, Dawid 
27008777fb0SLewanczyk, Dawid /**
27108777fb0SLewanczyk, Dawid  * @brief Builds a json sensor representation of a sensor.
27208777fb0SLewanczyk, Dawid  * @param sensorName  The name of the sensor to be built
273274fad5aSGunnar Mills  * @param sensorType  The type (temperature, fan_tach, etc) of the sensor to
27408777fb0SLewanczyk, Dawid  * build
27508777fb0SLewanczyk, Dawid  * @param interfacesDict  A dictionary of the interfaces and properties of said
27608777fb0SLewanczyk, Dawid  * interfaces to be built from
27708777fb0SLewanczyk, Dawid  * @param sensor_json  The json object to fill
27808777fb0SLewanczyk, Dawid  */
27908777fb0SLewanczyk, Dawid void objectInterfacesToJson(
28008777fb0SLewanczyk, Dawid     const std::string& sensorName, const std::string& sensorType,
28108777fb0SLewanczyk, Dawid     const boost::container::flat_map<
282aa2e59c1SEd Tanous         std::string, boost::container::flat_map<std::string, SensorVariant>>&
28308777fb0SLewanczyk, Dawid         interfacesDict,
2841abe55efSEd Tanous     nlohmann::json& sensor_json)
2851abe55efSEd Tanous {
28608777fb0SLewanczyk, Dawid     // We need a value interface before we can do anything with it
28755c7b7a2SEd Tanous     auto valueIt = interfacesDict.find("xyz.openbmc_project.Sensor.Value");
2881abe55efSEd Tanous     if (valueIt == interfacesDict.end())
2891abe55efSEd Tanous     {
29055c7b7a2SEd Tanous         BMCWEB_LOG_ERROR << "Sensor doesn't have a value interface";
29108777fb0SLewanczyk, Dawid         return;
29208777fb0SLewanczyk, Dawid     }
29308777fb0SLewanczyk, Dawid 
29408777fb0SLewanczyk, Dawid     // Assume values exist as is (10^0 == 1) if no scale exists
29508777fb0SLewanczyk, Dawid     int64_t scaleMultiplier = 0;
29608777fb0SLewanczyk, Dawid 
29755c7b7a2SEd Tanous     auto scaleIt = valueIt->second.find("Scale");
29808777fb0SLewanczyk, Dawid     // If a scale exists, pull value as int64, and use the scaling.
2991abe55efSEd Tanous     if (scaleIt != valueIt->second.end())
3001abe55efSEd Tanous     {
301abf2add6SEd Tanous         const int64_t* int64Value = std::get_if<int64_t>(&scaleIt->second);
3021abe55efSEd Tanous         if (int64Value != nullptr)
3031abe55efSEd Tanous         {
30408777fb0SLewanczyk, Dawid             scaleMultiplier = *int64Value;
30508777fb0SLewanczyk, Dawid         }
30608777fb0SLewanczyk, Dawid     }
30708777fb0SLewanczyk, Dawid 
30808777fb0SLewanczyk, Dawid     sensor_json["MemberId"] = sensorName;
30908777fb0SLewanczyk, Dawid     sensor_json["Name"] = sensorName;
31008777fb0SLewanczyk, Dawid     sensor_json["Status"]["State"] = "Enabled";
31108777fb0SLewanczyk, Dawid     sensor_json["Status"]["Health"] = "OK";
31208777fb0SLewanczyk, Dawid 
31308777fb0SLewanczyk, Dawid     // Parameter to set to override the type we get from dbus, and force it to
31408777fb0SLewanczyk, Dawid     // int, regardless of what is available.  This is used for schemas like fan,
31508777fb0SLewanczyk, Dawid     // that require integers, not floats.
31608777fb0SLewanczyk, Dawid     bool forceToInt = false;
31708777fb0SLewanczyk, Dawid 
31808777fb0SLewanczyk, Dawid     const char* unit = "Reading";
3191abe55efSEd Tanous     if (sensorType == "temperature")
3201abe55efSEd Tanous     {
32108777fb0SLewanczyk, Dawid         unit = "ReadingCelsius";
3227885954aSLewanczyk, Dawid         sensor_json["@odata.type"] = "#Thermal.v1_3_0.Temperature";
32308777fb0SLewanczyk, Dawid         // TODO(ed) Documentation says that path should be type fan_tach,
32408777fb0SLewanczyk, Dawid         // implementation seems to implement fan
3251abe55efSEd Tanous     }
3261abe55efSEd Tanous     else if (sensorType == "fan" || sensorType == "fan_tach")
3271abe55efSEd Tanous     {
32808777fb0SLewanczyk, Dawid         unit = "Reading";
32908777fb0SLewanczyk, Dawid         sensor_json["ReadingUnits"] = "RPM";
3307885954aSLewanczyk, Dawid         sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
33108777fb0SLewanczyk, Dawid         forceToInt = true;
3321abe55efSEd Tanous     }
3336f6d0d32SEd Tanous     else if (sensorType == "fan_pwm")
3346f6d0d32SEd Tanous     {
3356f6d0d32SEd Tanous         unit = "Reading";
3366f6d0d32SEd Tanous         sensor_json["ReadingUnits"] = "Percent";
3376f6d0d32SEd Tanous         sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
3386f6d0d32SEd Tanous         forceToInt = true;
3396f6d0d32SEd Tanous     }
3401abe55efSEd Tanous     else if (sensorType == "voltage")
3411abe55efSEd Tanous     {
34208777fb0SLewanczyk, Dawid         unit = "ReadingVolts";
3437885954aSLewanczyk, Dawid         sensor_json["@odata.type"] = "#Power.v1_0_0.Voltage";
3441abe55efSEd Tanous     }
3452474adfaSEd Tanous     else if (sensorType == "power")
3462474adfaSEd Tanous     {
3472474adfaSEd Tanous         unit = "LastPowerOutputWatts";
3482474adfaSEd Tanous     }
3491abe55efSEd Tanous     else
3501abe55efSEd Tanous     {
35155c7b7a2SEd Tanous         BMCWEB_LOG_ERROR << "Redfish cannot map object type for " << sensorName;
35208777fb0SLewanczyk, Dawid         return;
35308777fb0SLewanczyk, Dawid     }
35408777fb0SLewanczyk, Dawid     // Map of dbus interface name, dbus property name and redfish property_name
35508777fb0SLewanczyk, Dawid     std::vector<std::tuple<const char*, const char*, const char*>> properties;
35608777fb0SLewanczyk, Dawid     properties.reserve(7);
35708777fb0SLewanczyk, Dawid 
35808777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Value", "Value", unit);
35908777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
36008777fb0SLewanczyk, Dawid                             "WarningHigh", "UpperThresholdNonCritical");
36108777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
36208777fb0SLewanczyk, Dawid                             "WarningLow", "LowerThresholdNonCritical");
36308777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
36408777fb0SLewanczyk, Dawid                             "CriticalHigh", "UpperThresholdCritical");
36508777fb0SLewanczyk, Dawid     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
36608777fb0SLewanczyk, Dawid                             "CriticalLow", "LowerThresholdCritical");
36708777fb0SLewanczyk, Dawid 
3682474adfaSEd Tanous     // TODO Need to get UpperThresholdFatal and LowerThresholdFatal
3692474adfaSEd Tanous 
3701abe55efSEd Tanous     if (sensorType == "temperature")
3711abe55efSEd Tanous     {
37208777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
37308777fb0SLewanczyk, Dawid                                 "MinReadingRangeTemp");
37408777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
37508777fb0SLewanczyk, Dawid                                 "MaxReadingRangeTemp");
3761abe55efSEd Tanous     }
3771abe55efSEd Tanous     else
3781abe55efSEd Tanous     {
37908777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
38008777fb0SLewanczyk, Dawid                                 "MinReadingRange");
38108777fb0SLewanczyk, Dawid         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
38208777fb0SLewanczyk, Dawid                                 "MaxReadingRange");
38308777fb0SLewanczyk, Dawid     }
38408777fb0SLewanczyk, Dawid 
38508777fb0SLewanczyk, Dawid     for (const std::tuple<const char*, const char*, const char*>& p :
3861abe55efSEd Tanous          properties)
3871abe55efSEd Tanous     {
38808777fb0SLewanczyk, Dawid         auto interfaceProperties = interfacesDict.find(std::get<0>(p));
3891abe55efSEd Tanous         if (interfaceProperties != interfacesDict.end())
3901abe55efSEd Tanous         {
39155c7b7a2SEd Tanous             auto valueIt = interfaceProperties->second.find(std::get<1>(p));
3921abe55efSEd Tanous             if (valueIt != interfaceProperties->second.end())
3931abe55efSEd Tanous             {
39455c7b7a2SEd Tanous                 const SensorVariant& valueVariant = valueIt->second;
39555c7b7a2SEd Tanous                 nlohmann::json& valueIt = sensor_json[std::get<2>(p)];
39608777fb0SLewanczyk, Dawid                 // Attempt to pull the int64 directly
397abf2add6SEd Tanous                 const int64_t* int64Value = std::get_if<int64_t>(&valueVariant);
39808777fb0SLewanczyk, Dawid 
399abf2add6SEd Tanous                 const double* doubleValue = std::get_if<double>(&valueVariant);
4006f6d0d32SEd Tanous                 double temp = 0.0;
4016f6d0d32SEd Tanous                 if (int64Value != nullptr)
4021abe55efSEd Tanous                 {
4036f6d0d32SEd Tanous                     temp = *int64Value;
4046f6d0d32SEd Tanous                 }
4056f6d0d32SEd Tanous                 else if (doubleValue != nullptr)
4061abe55efSEd Tanous                 {
4076f6d0d32SEd Tanous                     temp = *doubleValue;
4081abe55efSEd Tanous                 }
4091abe55efSEd Tanous                 else
4101abe55efSEd Tanous                 {
4116f6d0d32SEd Tanous                     BMCWEB_LOG_ERROR
4126f6d0d32SEd Tanous                         << "Got value interface that wasn't int or double";
4136f6d0d32SEd Tanous                     continue;
41408777fb0SLewanczyk, Dawid                 }
4156f6d0d32SEd Tanous                 temp = temp * std::pow(10, scaleMultiplier);
4166f6d0d32SEd Tanous                 if (forceToInt)
4176f6d0d32SEd Tanous                 {
4186f6d0d32SEd Tanous                     valueIt = static_cast<int64_t>(temp);
4196f6d0d32SEd Tanous                 }
4206f6d0d32SEd Tanous                 else
4216f6d0d32SEd Tanous                 {
4226f6d0d32SEd Tanous                     valueIt = temp;
42308777fb0SLewanczyk, Dawid                 }
42408777fb0SLewanczyk, Dawid             }
42508777fb0SLewanczyk, Dawid         }
42608777fb0SLewanczyk, Dawid     }
42755c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "Added sensor " << sensorName;
42808777fb0SLewanczyk, Dawid }
42908777fb0SLewanczyk, Dawid 
43008777fb0SLewanczyk, Dawid /**
43108777fb0SLewanczyk, Dawid  * @brief Entry point for retrieving sensors data related to requested
43208777fb0SLewanczyk, Dawid  *        chassis.
433588c3f0dSKowalski, Kamil  * @param SensorsAsyncResp   Pointer to object holding response data
43408777fb0SLewanczyk, Dawid  */
4351abe55efSEd Tanous void getChassisData(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp)
4361abe55efSEd Tanous {
43755c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassisData enter";
438588c3f0dSKowalski, Kamil     auto getChassisCb = [&, SensorsAsyncResp](
439588c3f0dSKowalski, Kamil                             boost::container::flat_set<std::string>&
44008777fb0SLewanczyk, Dawid                                 sensorNames) {
44155c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassisCb enter";
442588c3f0dSKowalski, Kamil         auto getConnectionCb =
443588c3f0dSKowalski, Kamil             [&, SensorsAsyncResp, sensorNames](
444588c3f0dSKowalski, Kamil                 const boost::container::flat_set<std::string>& connections) {
44555c7b7a2SEd Tanous                 BMCWEB_LOG_DEBUG << "getConnectionCb enter";
44608777fb0SLewanczyk, Dawid                 // Get managed objects from all services exposing sensors
4471abe55efSEd Tanous                 for (const std::string& connection : connections)
4481abe55efSEd Tanous                 {
44908777fb0SLewanczyk, Dawid                     // Response handler to process managed objects
4501abe55efSEd Tanous                     auto getManagedObjectsCb =
4511abe55efSEd Tanous                         [&, SensorsAsyncResp,
4521abe55efSEd Tanous                          sensorNames](const boost::system::error_code ec,
45308777fb0SLewanczyk, Dawid                                       ManagedObjectsVectorType& resp) {
45455c7b7a2SEd Tanous                             BMCWEB_LOG_DEBUG << "getManagedObjectsCb enter";
4551abe55efSEd Tanous                             if (ec)
4561abe55efSEd Tanous                             {
4571abe55efSEd Tanous                                 BMCWEB_LOG_ERROR
4581abe55efSEd Tanous                                     << "getManagedObjectsCb DBUS error: " << ec;
4595f7d88c4SEd Tanous                                 messages::internalError(SensorsAsyncResp->res);
4607885954aSLewanczyk, Dawid                                 return;
4617885954aSLewanczyk, Dawid                             }
46208777fb0SLewanczyk, Dawid                             // Go through all objects and update response with
46308777fb0SLewanczyk, Dawid                             // sensor data
4641abe55efSEd Tanous                             for (const auto& objDictEntry : resp)
4651abe55efSEd Tanous                             {
466aa2e59c1SEd Tanous                                 const std::string& objPath =
4671abe55efSEd Tanous                                     static_cast<const std::string&>(
4681abe55efSEd Tanous                                         objDictEntry.first);
4691abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
4701abe55efSEd Tanous                                     << "getManagedObjectsCb parsing object "
471588c3f0dSKowalski, Kamil                                     << objPath;
472e0d918bcSEd Tanous 
47308777fb0SLewanczyk, Dawid                                 std::vector<std::string> split;
47408777fb0SLewanczyk, Dawid                                 // Reserve space for
47503b5bae3SJames Feist                                 // /xyz/openbmc_project/sensors/<name>/<subname>
47608777fb0SLewanczyk, Dawid                                 split.reserve(6);
4771abe55efSEd Tanous                                 boost::algorithm::split(split, objPath,
4781abe55efSEd Tanous                                                         boost::is_any_of("/"));
4791abe55efSEd Tanous                                 if (split.size() < 6)
4801abe55efSEd Tanous                                 {
4811abe55efSEd Tanous                                     BMCWEB_LOG_ERROR
4821abe55efSEd Tanous                                         << "Got path that isn't long enough "
483588c3f0dSKowalski, Kamil                                         << objPath;
48408777fb0SLewanczyk, Dawid                                     continue;
48508777fb0SLewanczyk, Dawid                                 }
4861abe55efSEd Tanous                                 // These indexes aren't intuitive, as
4871abe55efSEd Tanous                                 // boost::split puts an empty string at the
4881abe55efSEd Tanous                                 // beggining
48908777fb0SLewanczyk, Dawid                                 const std::string& sensorType = split[4];
49008777fb0SLewanczyk, Dawid                                 const std::string& sensorName = split[5];
49155c7b7a2SEd Tanous                                 BMCWEB_LOG_DEBUG << "sensorName " << sensorName
4921abe55efSEd Tanous                                                  << " sensorType "
4931abe55efSEd Tanous                                                  << sensorType;
4941abe55efSEd Tanous                                 if (sensorNames.find(sensorName) ==
4951abe55efSEd Tanous                                     sensorNames.end())
4961abe55efSEd Tanous                                 {
4971abe55efSEd Tanous                                     BMCWEB_LOG_ERROR << sensorName
4981abe55efSEd Tanous                                                      << " not in sensor list ";
49908777fb0SLewanczyk, Dawid                                     continue;
50008777fb0SLewanczyk, Dawid                                 }
50108777fb0SLewanczyk, Dawid 
50208777fb0SLewanczyk, Dawid                                 const char* fieldName = nullptr;
5031abe55efSEd Tanous                                 if (sensorType == "temperature")
5041abe55efSEd Tanous                                 {
50508777fb0SLewanczyk, Dawid                                     fieldName = "Temperatures";
5061abe55efSEd Tanous                                 }
5071abe55efSEd Tanous                                 else if (sensorType == "fan" ||
5086f6d0d32SEd Tanous                                          sensorType == "fan_tach" ||
5096f6d0d32SEd Tanous                                          sensorType == "fan_pwm")
5101abe55efSEd Tanous                                 {
51108777fb0SLewanczyk, Dawid                                     fieldName = "Fans";
5121abe55efSEd Tanous                                 }
5131abe55efSEd Tanous                                 else if (sensorType == "voltage")
5141abe55efSEd Tanous                                 {
51508777fb0SLewanczyk, Dawid                                     fieldName = "Voltages";
5161abe55efSEd Tanous                                 }
5171abe55efSEd Tanous                                 else if (sensorType == "current")
5181abe55efSEd Tanous                                 {
51908777fb0SLewanczyk, Dawid                                     fieldName = "PowerSupply";
5201abe55efSEd Tanous                                 }
5211abe55efSEd Tanous                                 else if (sensorType == "power")
5221abe55efSEd Tanous                                 {
52308777fb0SLewanczyk, Dawid                                     fieldName = "PowerSupply";
5241abe55efSEd Tanous                                 }
5251abe55efSEd Tanous                                 else
5261abe55efSEd Tanous                                 {
5271abe55efSEd Tanous                                     BMCWEB_LOG_ERROR
5281abe55efSEd Tanous                                         << "Unsure how to handle sensorType "
52908777fb0SLewanczyk, Dawid                                         << sensorType;
53008777fb0SLewanczyk, Dawid                                     continue;
53108777fb0SLewanczyk, Dawid                                 }
53208777fb0SLewanczyk, Dawid 
53355c7b7a2SEd Tanous                                 nlohmann::json& tempArray =
53455c7b7a2SEd Tanous                                     SensorsAsyncResp->res.jsonValue[fieldName];
53508777fb0SLewanczyk, Dawid 
53655c7b7a2SEd Tanous                                 tempArray.push_back(
5371abe55efSEd Tanous                                     {{"@odata.id",
5381abe55efSEd Tanous                                       "/redfish/v1/Chassis/" +
5392474adfaSEd Tanous                                           SensorsAsyncResp->chassisId + "/" +
5402474adfaSEd Tanous                                           SensorsAsyncResp->chassisSubNode +
5412474adfaSEd Tanous                                           "#/" + fieldName + "/" +
5426f6d0d32SEd Tanous                                           std::to_string(tempArray.size())}});
54355c7b7a2SEd Tanous                                 nlohmann::json& sensorJson = tempArray.back();
5446f6d0d32SEd Tanous 
545588c3f0dSKowalski, Kamil                                 objectInterfacesToJson(sensorName, sensorType,
5461abe55efSEd Tanous                                                        objDictEntry.second,
5471abe55efSEd Tanous                                                        sensorJson);
54808777fb0SLewanczyk, Dawid                             }
54955c7b7a2SEd Tanous                             BMCWEB_LOG_DEBUG << "getManagedObjectsCb exit";
55008777fb0SLewanczyk, Dawid                         };
55155c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
5527885954aSLewanczyk, Dawid                         getManagedObjectsCb, connection, "/",
5531abe55efSEd Tanous                         "org.freedesktop.DBus.ObjectManager",
5541abe55efSEd Tanous                         "GetManagedObjects");
55508777fb0SLewanczyk, Dawid                 };
55655c7b7a2SEd Tanous                 BMCWEB_LOG_DEBUG << "getConnectionCb exit";
55708777fb0SLewanczyk, Dawid             };
55855c7b7a2SEd Tanous         // get connections and then pass it to get sensors
5591abe55efSEd Tanous         getConnections(SensorsAsyncResp, sensorNames,
5601abe55efSEd Tanous                        std::move(getConnectionCb));
56155c7b7a2SEd Tanous         BMCWEB_LOG_DEBUG << "getChassisCb exit";
56208777fb0SLewanczyk, Dawid     };
56308777fb0SLewanczyk, Dawid 
56455c7b7a2SEd Tanous     // get chassis information related to sensors
565588c3f0dSKowalski, Kamil     getChassis(SensorsAsyncResp, std::move(getChassisCb));
56655c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "getChassisData exit";
56708777fb0SLewanczyk, Dawid };
56808777fb0SLewanczyk, Dawid 
569*413961deSRichard Marian Thomaiyar /**
570*413961deSRichard Marian Thomaiyar  * @brief Entry point for overriding sensor values of given sensor
571*413961deSRichard Marian Thomaiyar  *
572*413961deSRichard Marian Thomaiyar  * @param res   response object
573*413961deSRichard Marian Thomaiyar  * @param req   request object
574*413961deSRichard Marian Thomaiyar  * @param params   parameter passed for CRUD
575*413961deSRichard Marian Thomaiyar  * @param typeList   TypeList of sensors for the resource queried
576*413961deSRichard Marian Thomaiyar  * @param chassisSubNode   Chassis Node for which the query has to happen
577*413961deSRichard Marian Thomaiyar  */
578*413961deSRichard Marian Thomaiyar void setSensorOverride(crow::Response& res, const crow::Request& req,
579*413961deSRichard Marian Thomaiyar                        const std::vector<std::string>& params,
580*413961deSRichard Marian Thomaiyar                        const std::initializer_list<const char*> typeList,
581*413961deSRichard Marian Thomaiyar                        const std::string& chassisSubNode)
582*413961deSRichard Marian Thomaiyar {
583*413961deSRichard Marian Thomaiyar 
584*413961deSRichard Marian Thomaiyar     // TODO: Need to figure out dynamic way to restrict patch (Set Sensor
585*413961deSRichard Marian Thomaiyar     // override) based on another d-bus announcement to be more generic.
586*413961deSRichard Marian Thomaiyar     if (params.size() != 1)
587*413961deSRichard Marian Thomaiyar     {
588*413961deSRichard Marian Thomaiyar         messages::internalError(res);
589*413961deSRichard Marian Thomaiyar         res.end();
590*413961deSRichard Marian Thomaiyar         return;
591*413961deSRichard Marian Thomaiyar     }
592*413961deSRichard Marian Thomaiyar     const char* collectionName;
593*413961deSRichard Marian Thomaiyar     const char* propertyValueName;
594*413961deSRichard Marian Thomaiyar     if (chassisSubNode == "Thermal")
595*413961deSRichard Marian Thomaiyar     {
596*413961deSRichard Marian Thomaiyar         collectionName = "Temperatures";
597*413961deSRichard Marian Thomaiyar         propertyValueName = "ReadingCelsius";
598*413961deSRichard Marian Thomaiyar     }
599*413961deSRichard Marian Thomaiyar     else if (chassisSubNode == "Power")
600*413961deSRichard Marian Thomaiyar     {
601*413961deSRichard Marian Thomaiyar         collectionName = "Voltages";
602*413961deSRichard Marian Thomaiyar         propertyValueName = "ReadingVolts";
603*413961deSRichard Marian Thomaiyar     }
604*413961deSRichard Marian Thomaiyar     else
605*413961deSRichard Marian Thomaiyar     {
606*413961deSRichard Marian Thomaiyar         res.result(boost::beast::http::status::not_found);
607*413961deSRichard Marian Thomaiyar         res.end();
608*413961deSRichard Marian Thomaiyar         return;
609*413961deSRichard Marian Thomaiyar     }
610*413961deSRichard Marian Thomaiyar     std::vector<nlohmann::json> collections;
611*413961deSRichard Marian Thomaiyar     if (!json_util::readJson(req, res, collectionName, collections))
612*413961deSRichard Marian Thomaiyar     {
613*413961deSRichard Marian Thomaiyar         return;
614*413961deSRichard Marian Thomaiyar     }
615*413961deSRichard Marian Thomaiyar     if (collections.size() != 1)
616*413961deSRichard Marian Thomaiyar     {
617*413961deSRichard Marian Thomaiyar         messages::malformedJSON(res);
618*413961deSRichard Marian Thomaiyar         res.end();
619*413961deSRichard Marian Thomaiyar         return;
620*413961deSRichard Marian Thomaiyar     }
621*413961deSRichard Marian Thomaiyar 
622*413961deSRichard Marian Thomaiyar     std::string memberId;
623*413961deSRichard Marian Thomaiyar     double value;
624*413961deSRichard Marian Thomaiyar     if (!json_util::readJson(collections[0], res, "MemberId", memberId,
625*413961deSRichard Marian Thomaiyar                              propertyValueName, value))
626*413961deSRichard Marian Thomaiyar     {
627*413961deSRichard Marian Thomaiyar         return;
628*413961deSRichard Marian Thomaiyar     }
629*413961deSRichard Marian Thomaiyar     const std::string& chassisName = params[0];
630*413961deSRichard Marian Thomaiyar     auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
631*413961deSRichard Marian Thomaiyar         res, chassisName, typeList, chassisSubNode);
632*413961deSRichard Marian Thomaiyar     BMCWEB_LOG_INFO << "setSensorOverride for " << memberId
633*413961deSRichard Marian Thomaiyar                     << "with value: " << value << "\n";
634*413961deSRichard Marian Thomaiyar     // first check for valid chassis id & sensor in requested chassis.
635*413961deSRichard Marian Thomaiyar     auto getChassisSensorListCb =
636*413961deSRichard Marian Thomaiyar         [sensorAsyncResp, memberId,
637*413961deSRichard Marian Thomaiyar          value](const boost::container::flat_set<std::string>& sensorLists) {
638*413961deSRichard Marian Thomaiyar             if (sensorLists.find(memberId) == sensorLists.end())
639*413961deSRichard Marian Thomaiyar             {
640*413961deSRichard Marian Thomaiyar                 BMCWEB_LOG_INFO << "Unable to find memberId " << memberId;
641*413961deSRichard Marian Thomaiyar                 messages::resourceNotFound(sensorAsyncResp->res,
642*413961deSRichard Marian Thomaiyar                                            sensorAsyncResp->chassisSubNode ==
643*413961deSRichard Marian Thomaiyar                                                    "Thermal"
644*413961deSRichard Marian Thomaiyar                                                ? "Temperatures"
645*413961deSRichard Marian Thomaiyar                                                : "Voltages",
646*413961deSRichard Marian Thomaiyar                                            memberId);
647*413961deSRichard Marian Thomaiyar                 return;
648*413961deSRichard Marian Thomaiyar             }
649*413961deSRichard Marian Thomaiyar             boost::container::flat_set<std::string> sensorNames;
650*413961deSRichard Marian Thomaiyar             sensorNames.emplace(memberId);
651*413961deSRichard Marian Thomaiyar             // Get the connection to which the memberId belongs
652*413961deSRichard Marian Thomaiyar             auto getObjectsWithConnectionCb =
653*413961deSRichard Marian Thomaiyar                 [sensorAsyncResp, memberId, value](
654*413961deSRichard Marian Thomaiyar                     const boost::container::flat_set<std::string>& connections,
655*413961deSRichard Marian Thomaiyar                     const std::set<std::pair<std::string, std::string>>&
656*413961deSRichard Marian Thomaiyar                         objectsWithConnection) {
657*413961deSRichard Marian Thomaiyar                     if (objectsWithConnection.size() != 1)
658*413961deSRichard Marian Thomaiyar                     {
659*413961deSRichard Marian Thomaiyar                         BMCWEB_LOG_INFO
660*413961deSRichard Marian Thomaiyar                             << "Unable to find object with proper connection "
661*413961deSRichard Marian Thomaiyar                             << objectsWithConnection.size() << "\n";
662*413961deSRichard Marian Thomaiyar                         messages::resourceNotFound(
663*413961deSRichard Marian Thomaiyar                             sensorAsyncResp->res,
664*413961deSRichard Marian Thomaiyar                             sensorAsyncResp->chassisSubNode == "Thermal"
665*413961deSRichard Marian Thomaiyar                                 ? "Temperatures"
666*413961deSRichard Marian Thomaiyar                                 : "Voltages",
667*413961deSRichard Marian Thomaiyar                             memberId);
668*413961deSRichard Marian Thomaiyar                         return;
669*413961deSRichard Marian Thomaiyar                     }
670*413961deSRichard Marian Thomaiyar                     crow::connections::systemBus->async_method_call(
671*413961deSRichard Marian Thomaiyar                         [sensorAsyncResp, memberId,
672*413961deSRichard Marian Thomaiyar                          value](const boost::system::error_code ec) {
673*413961deSRichard Marian Thomaiyar                             if (ec)
674*413961deSRichard Marian Thomaiyar                             {
675*413961deSRichard Marian Thomaiyar                                 BMCWEB_LOG_DEBUG
676*413961deSRichard Marian Thomaiyar                                     << "getOverrideValueStatus DBUS error: "
677*413961deSRichard Marian Thomaiyar                                     << ec;
678*413961deSRichard Marian Thomaiyar                                 messages::internalError(sensorAsyncResp->res);
679*413961deSRichard Marian Thomaiyar                                 return;
680*413961deSRichard Marian Thomaiyar                             }
681*413961deSRichard Marian Thomaiyar                         },
682*413961deSRichard Marian Thomaiyar                         objectsWithConnection.begin()->second,
683*413961deSRichard Marian Thomaiyar                         objectsWithConnection.begin()->first,
684*413961deSRichard Marian Thomaiyar                         "org.freedesktop.DBus.Properties", "Set",
685*413961deSRichard Marian Thomaiyar                         "xyz.openbmc_project.Sensor.Value", "Value",
686*413961deSRichard Marian Thomaiyar                         sdbusplus::message::variant<double>(value));
687*413961deSRichard Marian Thomaiyar                 };
688*413961deSRichard Marian Thomaiyar             // Get object with connection for the given sensor name
689*413961deSRichard Marian Thomaiyar             getObjectsWithConnection(sensorAsyncResp, sensorNames,
690*413961deSRichard Marian Thomaiyar                                      std::move(getObjectsWithConnectionCb));
691*413961deSRichard Marian Thomaiyar         };
692*413961deSRichard Marian Thomaiyar     // get full sensor list for the given chassisId and cross verify the sensor.
693*413961deSRichard Marian Thomaiyar     getChassis(sensorAsyncResp, std::move(getChassisSensorListCb));
694*413961deSRichard Marian Thomaiyar }
695*413961deSRichard Marian Thomaiyar 
69608777fb0SLewanczyk, Dawid } // namespace redfish
697