12474adfaSEd Tanous /* 22474adfaSEd Tanous // Copyright (c) 2018 Intel Corporation 32474adfaSEd Tanous // Copyright (c) 2018 Ampere Computing LLC 42474adfaSEd Tanous / 52474adfaSEd Tanous // Licensed under the Apache License, Version 2.0 (the "License"); 62474adfaSEd Tanous // you may not use this file except in compliance with the License. 72474adfaSEd Tanous // You may obtain a copy of the License at 82474adfaSEd Tanous // 92474adfaSEd Tanous // http://www.apache.org/licenses/LICENSE-2.0 102474adfaSEd Tanous // 112474adfaSEd Tanous // Unless required by applicable law or agreed to in writing, software 122474adfaSEd Tanous // distributed under the License is distributed on an "AS IS" BASIS, 132474adfaSEd Tanous // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 142474adfaSEd Tanous // See the License for the specific language governing permissions and 152474adfaSEd Tanous // limitations under the License. 162474adfaSEd Tanous */ 172474adfaSEd Tanous #pragma once 182474adfaSEd Tanous 192474adfaSEd Tanous #include "node.hpp" 202474adfaSEd Tanous #include "sensors.hpp" 212474adfaSEd Tanous 222474adfaSEd Tanous namespace redfish 232474adfaSEd Tanous { 242474adfaSEd Tanous 252474adfaSEd Tanous class Power : public Node 262474adfaSEd Tanous { 272474adfaSEd Tanous public: 282474adfaSEd Tanous Power(CrowApp& app) : 292474adfaSEd Tanous Node((app), "/redfish/v1/Chassis/<str>/Power/", std::string()) 302474adfaSEd Tanous { 312474adfaSEd Tanous entityPrivileges = { 322474adfaSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 332474adfaSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 346f4fd479SRichard Marian Thomaiyar {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 352474adfaSEd Tanous {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 362474adfaSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 372474adfaSEd Tanous {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 382474adfaSEd Tanous } 392474adfaSEd Tanous 402474adfaSEd Tanous private: 4185e1424fSEd Tanous std::vector<const char*> typeList = {"/xyz/openbmc_project/sensors/voltage", 42413961deSRichard Marian Thomaiyar "/xyz/openbmc_project/sensors/power"}; 432474adfaSEd Tanous void doGet(crow::Response& res, const crow::Request& req, 442474adfaSEd Tanous const std::vector<std::string>& params) override 452474adfaSEd Tanous { 462474adfaSEd Tanous if (params.size() != 1) 472474adfaSEd Tanous { 482474adfaSEd Tanous res.result(boost::beast::http::status::internal_server_error); 492474adfaSEd Tanous res.end(); 502474adfaSEd Tanous return; 512474adfaSEd Tanous } 522474adfaSEd Tanous const std::string& chassis_name = params[0]; 532474adfaSEd Tanous 54c5d03ff4SJennifer Lee res.jsonValue["PowerControl"] = nlohmann::json::array(); 55c5d03ff4SJennifer Lee 562474adfaSEd Tanous auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( 57413961deSRichard Marian Thomaiyar res, chassis_name, typeList, "Power"); 58028f7ebcSEddie James 592474adfaSEd Tanous getChassisData(sensorAsyncResp); 60028f7ebcSEddie James 61028f7ebcSEddie James // This callback verifies that the power limit is only provided for the 62028f7ebcSEddie James // chassis that implements the Chassis inventory item. This prevents 63028f7ebcSEddie James // things like power supplies providing the chassis power limit 64028f7ebcSEddie James auto chassisHandler = [sensorAsyncResp]( 65*271584abSEd Tanous const boost::system::error_code e, 66028f7ebcSEddie James const std::vector<std::string>& 67028f7ebcSEddie James chassisPaths) { 68*271584abSEd Tanous if (e) 69028f7ebcSEddie James { 70028f7ebcSEddie James BMCWEB_LOG_ERROR 71*271584abSEd Tanous << "Power Limit GetSubTreePaths handler Dbus error " << e; 72028f7ebcSEddie James return; 73028f7ebcSEddie James } 74028f7ebcSEddie James 75028f7ebcSEddie James bool found = false; 76028f7ebcSEddie James for (const std::string& chassis : chassisPaths) 77028f7ebcSEddie James { 78028f7ebcSEddie James size_t len = std::string::npos; 79028f7ebcSEddie James size_t lastPos = chassis.rfind("/"); 80028f7ebcSEddie James if (lastPos == std::string::npos) 81028f7ebcSEddie James { 82028f7ebcSEddie James continue; 83028f7ebcSEddie James } 84028f7ebcSEddie James 85028f7ebcSEddie James if (lastPos == chassis.size() - 1) 86028f7ebcSEddie James { 87028f7ebcSEddie James size_t end = lastPos; 88028f7ebcSEddie James lastPos = chassis.rfind("/", lastPos - 1); 89028f7ebcSEddie James if (lastPos == std::string::npos) 90028f7ebcSEddie James { 91028f7ebcSEddie James continue; 92028f7ebcSEddie James } 93028f7ebcSEddie James 94028f7ebcSEddie James len = end - (lastPos + 1); 95028f7ebcSEddie James } 96028f7ebcSEddie James 97028f7ebcSEddie James std::string interfaceChassisName = 98028f7ebcSEddie James chassis.substr(lastPos + 1, len); 99028f7ebcSEddie James if (!interfaceChassisName.compare(sensorAsyncResp->chassisId)) 100028f7ebcSEddie James { 101028f7ebcSEddie James found = true; 102028f7ebcSEddie James break; 103028f7ebcSEddie James } 104028f7ebcSEddie James } 105028f7ebcSEddie James 106028f7ebcSEddie James if (!found) 107028f7ebcSEddie James { 108028f7ebcSEddie James BMCWEB_LOG_DEBUG << "Power Limit not present for " 109028f7ebcSEddie James << sensorAsyncResp->chassisId; 110028f7ebcSEddie James return; 111028f7ebcSEddie James } 112028f7ebcSEddie James 113028f7ebcSEddie James auto valueHandler = 114028f7ebcSEddie James [sensorAsyncResp]( 115028f7ebcSEddie James const boost::system::error_code ec, 116028f7ebcSEddie James const std::vector<std::pair<std::string, SensorVariant>>& 117028f7ebcSEddie James properties) { 118028f7ebcSEddie James if (ec) 119028f7ebcSEddie James { 120028f7ebcSEddie James messages::internalError(sensorAsyncResp->res); 121028f7ebcSEddie James BMCWEB_LOG_ERROR 122028f7ebcSEddie James << "Power Limit GetAll handler: Dbus error " << ec; 123028f7ebcSEddie James return; 124028f7ebcSEddie James } 125028f7ebcSEddie James 126028f7ebcSEddie James nlohmann::json& tempArray = 1277ab06f49SGunnar Mills sensorAsyncResp->res.jsonValue["PowerControl"]; 128028f7ebcSEddie James 1297ab06f49SGunnar Mills // Put multiple "sensors" into a single PowerControl, 0, so 1307ab06f49SGunnar Mills // only create the first one 131028f7ebcSEddie James if (tempArray.empty()) 132028f7ebcSEddie James { 1337ab06f49SGunnar Mills // Mandatory properties odata.id and MemberId 1347ab06f49SGunnar Mills // A warning without a odata.type 1357ab06f49SGunnar Mills tempArray.push_back( 1367ab06f49SGunnar Mills {{"@odata.type", "#Power.v1_0_0.PowerControl"}, 1377ab06f49SGunnar Mills {"@odata.id", "/redfish/v1/Chassis/" + 1387ab06f49SGunnar Mills sensorAsyncResp->chassisId + 1397ab06f49SGunnar Mills "/Power#/PowerControl/0"}, 1407ab06f49SGunnar Mills {"Name", "Chassis Power Control"}, 1417ab06f49SGunnar Mills {"MemberId", "0"}}); 142028f7ebcSEddie James } 143028f7ebcSEddie James 144028f7ebcSEddie James nlohmann::json& sensorJson = tempArray.back(); 145028f7ebcSEddie James bool enabled = false; 146028f7ebcSEddie James double powerCap = 0.0; 147028f7ebcSEddie James int64_t scale = 0; 148028f7ebcSEddie James 149028f7ebcSEddie James for (const std::pair<std::string, SensorVariant>& property : 150028f7ebcSEddie James properties) 151028f7ebcSEddie James { 152028f7ebcSEddie James if (!property.first.compare("Scale")) 153028f7ebcSEddie James { 154028f7ebcSEddie James const int64_t* i = 155028f7ebcSEddie James sdbusplus::message::variant_ns::get_if<int64_t>( 156028f7ebcSEddie James &property.second); 157028f7ebcSEddie James 158028f7ebcSEddie James if (i) 159028f7ebcSEddie James { 160028f7ebcSEddie James scale = *i; 161028f7ebcSEddie James } 162028f7ebcSEddie James } 163028f7ebcSEddie James else if (!property.first.compare("PowerCap")) 164028f7ebcSEddie James { 165028f7ebcSEddie James const double* d = 166028f7ebcSEddie James sdbusplus::message::variant_ns::get_if<double>( 167028f7ebcSEddie James &property.second); 168028f7ebcSEddie James const int64_t* i = 169028f7ebcSEddie James sdbusplus::message::variant_ns::get_if<int64_t>( 170028f7ebcSEddie James &property.second); 171028f7ebcSEddie James const uint32_t* u = 172028f7ebcSEddie James sdbusplus::message::variant_ns::get_if< 173028f7ebcSEddie James uint32_t>(&property.second); 174028f7ebcSEddie James 175028f7ebcSEddie James if (d) 176028f7ebcSEddie James { 177028f7ebcSEddie James powerCap = *d; 178028f7ebcSEddie James } 179028f7ebcSEddie James else if (i) 180028f7ebcSEddie James { 181*271584abSEd Tanous powerCap = static_cast<double>(*i); 182028f7ebcSEddie James } 183028f7ebcSEddie James else if (u) 184028f7ebcSEddie James { 185028f7ebcSEddie James powerCap = *u; 186028f7ebcSEddie James } 187028f7ebcSEddie James } 188028f7ebcSEddie James else if (!property.first.compare("PowerCapEnable")) 189028f7ebcSEddie James { 190028f7ebcSEddie James const bool* b = 191028f7ebcSEddie James sdbusplus::message::variant_ns::get_if<bool>( 192028f7ebcSEddie James &property.second); 193028f7ebcSEddie James 194028f7ebcSEddie James if (b) 195028f7ebcSEddie James { 196028f7ebcSEddie James enabled = *b; 197028f7ebcSEddie James } 198028f7ebcSEddie James } 199028f7ebcSEddie James } 200028f7ebcSEddie James 2017ab06f49SGunnar Mills nlohmann::json& value = 2027ab06f49SGunnar Mills sensorJson["PowerLimit"]["LimitInWatts"]; 203028f7ebcSEddie James 204028f7ebcSEddie James if (enabled) 205028f7ebcSEddie James { 206028f7ebcSEddie James // Redfish specification indicates PowerLimit should be 207028f7ebcSEddie James // null if the limit is not enabled. 208028f7ebcSEddie James value = powerCap * std::pow(10, scale); 209028f7ebcSEddie James } 210028f7ebcSEddie James }; 211028f7ebcSEddie James 212028f7ebcSEddie James crow::connections::systemBus->async_method_call( 213028f7ebcSEddie James std::move(valueHandler), "xyz.openbmc_project.Settings", 214028f7ebcSEddie James "/xyz/openbmc_project/control/host0/power_cap", 215028f7ebcSEddie James "org.freedesktop.DBus.Properties", "GetAll", 216028f7ebcSEddie James "xyz.openbmc_project.Control.Power.Cap"); 217028f7ebcSEddie James }; 218028f7ebcSEddie James 219028f7ebcSEddie James crow::connections::systemBus->async_method_call( 220028f7ebcSEddie James std::move(chassisHandler), "xyz.openbmc_project.ObjectMapper", 221028f7ebcSEddie James "/xyz/openbmc_project/object_mapper", 222028f7ebcSEddie James "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 223*271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, 224028f7ebcSEddie James std::array<const char*, 1>{ 225028f7ebcSEddie James "xyz.openbmc_project.Inventory.Item.Chassis"}); 2262474adfaSEd Tanous } 227413961deSRichard Marian Thomaiyar void doPatch(crow::Response& res, const crow::Request& req, 228413961deSRichard Marian Thomaiyar const std::vector<std::string>& params) override 229413961deSRichard Marian Thomaiyar { 230413961deSRichard Marian Thomaiyar setSensorOverride(res, req, params, typeList, "Power"); 231413961deSRichard Marian Thomaiyar } 2322474adfaSEd Tanous }; 2332474adfaSEd Tanous 2342474adfaSEd Tanous } // namespace redfish 235