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