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: 41b01bf299SEd Tanous std::initializer_list<const char*> typeList = { 42b01bf299SEd Tanous "/xyz/openbmc_project/sensors/voltage", 43413961deSRichard Marian Thomaiyar "/xyz/openbmc_project/sensors/power"}; 442474adfaSEd Tanous void doGet(crow::Response& res, const crow::Request& req, 452474adfaSEd Tanous const std::vector<std::string>& params) override 462474adfaSEd Tanous { 472474adfaSEd Tanous if (params.size() != 1) 482474adfaSEd Tanous { 492474adfaSEd Tanous res.result(boost::beast::http::status::internal_server_error); 502474adfaSEd Tanous res.end(); 512474adfaSEd Tanous return; 522474adfaSEd Tanous } 532474adfaSEd Tanous const std::string& chassis_name = params[0]; 542474adfaSEd Tanous 552474adfaSEd Tanous auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( 56413961deSRichard Marian Thomaiyar res, chassis_name, typeList, "Power"); 57*028f7ebcSEddie James 582474adfaSEd Tanous getChassisData(sensorAsyncResp); 59*028f7ebcSEddie James 60*028f7ebcSEddie James // This callback verifies that the power limit is only provided for the 61*028f7ebcSEddie James // chassis that implements the Chassis inventory item. This prevents 62*028f7ebcSEddie James // things like power supplies providing the chassis power limit 63*028f7ebcSEddie James auto chassisHandler = [sensorAsyncResp]( 64*028f7ebcSEddie James const boost::system::error_code ec, 65*028f7ebcSEddie James const std::vector<std::string>& 66*028f7ebcSEddie James chassisPaths) { 67*028f7ebcSEddie James if (ec) 68*028f7ebcSEddie James { 69*028f7ebcSEddie James BMCWEB_LOG_ERROR 70*028f7ebcSEddie James << "Power Limit GetSubTreePaths handler Dbus error " << ec; 71*028f7ebcSEddie James return; 72*028f7ebcSEddie James } 73*028f7ebcSEddie James 74*028f7ebcSEddie James bool found = false; 75*028f7ebcSEddie James for (const std::string& chassis : chassisPaths) 76*028f7ebcSEddie James { 77*028f7ebcSEddie James size_t len = std::string::npos; 78*028f7ebcSEddie James size_t lastPos = chassis.rfind("/"); 79*028f7ebcSEddie James if (lastPos == std::string::npos) 80*028f7ebcSEddie James { 81*028f7ebcSEddie James continue; 82*028f7ebcSEddie James } 83*028f7ebcSEddie James 84*028f7ebcSEddie James if (lastPos == chassis.size() - 1) 85*028f7ebcSEddie James { 86*028f7ebcSEddie James size_t end = lastPos; 87*028f7ebcSEddie James lastPos = chassis.rfind("/", lastPos - 1); 88*028f7ebcSEddie James if (lastPos == std::string::npos) 89*028f7ebcSEddie James { 90*028f7ebcSEddie James continue; 91*028f7ebcSEddie James } 92*028f7ebcSEddie James 93*028f7ebcSEddie James len = end - (lastPos + 1); 94*028f7ebcSEddie James } 95*028f7ebcSEddie James 96*028f7ebcSEddie James std::string interfaceChassisName = 97*028f7ebcSEddie James chassis.substr(lastPos + 1, len); 98*028f7ebcSEddie James if (!interfaceChassisName.compare(sensorAsyncResp->chassisId)) 99*028f7ebcSEddie James { 100*028f7ebcSEddie James found = true; 101*028f7ebcSEddie James break; 102*028f7ebcSEddie James } 103*028f7ebcSEddie James } 104*028f7ebcSEddie James 105*028f7ebcSEddie James if (!found) 106*028f7ebcSEddie James { 107*028f7ebcSEddie James BMCWEB_LOG_DEBUG << "Power Limit not present for " 108*028f7ebcSEddie James << sensorAsyncResp->chassisId; 109*028f7ebcSEddie James return; 110*028f7ebcSEddie James } 111*028f7ebcSEddie James 112*028f7ebcSEddie James auto valueHandler = 113*028f7ebcSEddie James [sensorAsyncResp]( 114*028f7ebcSEddie James const boost::system::error_code ec, 115*028f7ebcSEddie James const std::vector<std::pair<std::string, SensorVariant>>& 116*028f7ebcSEddie James properties) { 117*028f7ebcSEddie James if (ec) 118*028f7ebcSEddie James { 119*028f7ebcSEddie James messages::internalError(sensorAsyncResp->res); 120*028f7ebcSEddie James BMCWEB_LOG_ERROR 121*028f7ebcSEddie James << "Power Limit GetAll handler: Dbus error " << ec; 122*028f7ebcSEddie James return; 123*028f7ebcSEddie James } 124*028f7ebcSEddie James 125*028f7ebcSEddie James nlohmann::json& tempArray = 126*028f7ebcSEddie James sensorAsyncResp->res.jsonValue["PowerLimit"]; 127*028f7ebcSEddie James 128*028f7ebcSEddie James if (tempArray.empty()) 129*028f7ebcSEddie James { 130*028f7ebcSEddie James tempArray.push_back({}); 131*028f7ebcSEddie James } 132*028f7ebcSEddie James 133*028f7ebcSEddie James nlohmann::json& sensorJson = tempArray.back(); 134*028f7ebcSEddie James bool enabled = false; 135*028f7ebcSEddie James double powerCap = 0.0; 136*028f7ebcSEddie James int64_t scale = 0; 137*028f7ebcSEddie James 138*028f7ebcSEddie James for (const std::pair<std::string, SensorVariant>& property : 139*028f7ebcSEddie James properties) 140*028f7ebcSEddie James { 141*028f7ebcSEddie James if (!property.first.compare("Scale")) 142*028f7ebcSEddie James { 143*028f7ebcSEddie James const int64_t* i = 144*028f7ebcSEddie James sdbusplus::message::variant_ns::get_if<int64_t>( 145*028f7ebcSEddie James &property.second); 146*028f7ebcSEddie James 147*028f7ebcSEddie James if (i) 148*028f7ebcSEddie James { 149*028f7ebcSEddie James scale = *i; 150*028f7ebcSEddie James } 151*028f7ebcSEddie James } 152*028f7ebcSEddie James else if (!property.first.compare("PowerCap")) 153*028f7ebcSEddie James { 154*028f7ebcSEddie James const double* d = 155*028f7ebcSEddie James sdbusplus::message::variant_ns::get_if<double>( 156*028f7ebcSEddie James &property.second); 157*028f7ebcSEddie James const int64_t* i = 158*028f7ebcSEddie James sdbusplus::message::variant_ns::get_if<int64_t>( 159*028f7ebcSEddie James &property.second); 160*028f7ebcSEddie James const uint32_t* u = 161*028f7ebcSEddie James sdbusplus::message::variant_ns::get_if< 162*028f7ebcSEddie James uint32_t>(&property.second); 163*028f7ebcSEddie James 164*028f7ebcSEddie James if (d) 165*028f7ebcSEddie James { 166*028f7ebcSEddie James powerCap = *d; 167*028f7ebcSEddie James } 168*028f7ebcSEddie James else if (i) 169*028f7ebcSEddie James { 170*028f7ebcSEddie James powerCap = *i; 171*028f7ebcSEddie James } 172*028f7ebcSEddie James else if (u) 173*028f7ebcSEddie James { 174*028f7ebcSEddie James powerCap = *u; 175*028f7ebcSEddie James } 176*028f7ebcSEddie James } 177*028f7ebcSEddie James else if (!property.first.compare("PowerCapEnable")) 178*028f7ebcSEddie James { 179*028f7ebcSEddie James const bool* b = 180*028f7ebcSEddie James sdbusplus::message::variant_ns::get_if<bool>( 181*028f7ebcSEddie James &property.second); 182*028f7ebcSEddie James 183*028f7ebcSEddie James if (b) 184*028f7ebcSEddie James { 185*028f7ebcSEddie James enabled = *b; 186*028f7ebcSEddie James } 187*028f7ebcSEddie James } 188*028f7ebcSEddie James } 189*028f7ebcSEddie James 190*028f7ebcSEddie James nlohmann::json& value = sensorJson["LimitInWatts"]; 191*028f7ebcSEddie James 192*028f7ebcSEddie James if (enabled) 193*028f7ebcSEddie James { 194*028f7ebcSEddie James // Redfish specification indicates PowerLimit should be 195*028f7ebcSEddie James // null if the limit is not enabled. 196*028f7ebcSEddie James value = powerCap * std::pow(10, scale); 197*028f7ebcSEddie James } 198*028f7ebcSEddie James }; 199*028f7ebcSEddie James 200*028f7ebcSEddie James crow::connections::systemBus->async_method_call( 201*028f7ebcSEddie James std::move(valueHandler), "xyz.openbmc_project.Settings", 202*028f7ebcSEddie James "/xyz/openbmc_project/control/host0/power_cap", 203*028f7ebcSEddie James "org.freedesktop.DBus.Properties", "GetAll", 204*028f7ebcSEddie James "xyz.openbmc_project.Control.Power.Cap"); 205*028f7ebcSEddie James }; 206*028f7ebcSEddie James 207*028f7ebcSEddie James crow::connections::systemBus->async_method_call( 208*028f7ebcSEddie James std::move(chassisHandler), "xyz.openbmc_project.ObjectMapper", 209*028f7ebcSEddie James "/xyz/openbmc_project/object_mapper", 210*028f7ebcSEddie James "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 211*028f7ebcSEddie James "/xyz/openbmc_project/inventory", int32_t(0), 212*028f7ebcSEddie James std::array<const char*, 1>{ 213*028f7ebcSEddie James "xyz.openbmc_project.Inventory.Item.Chassis"}); 2142474adfaSEd Tanous } 215413961deSRichard Marian Thomaiyar void doPatch(crow::Response& res, const crow::Request& req, 216413961deSRichard Marian Thomaiyar const std::vector<std::string>& params) override 217413961deSRichard Marian Thomaiyar { 218413961deSRichard Marian Thomaiyar setSensorOverride(res, req, params, typeList, "Power"); 219413961deSRichard Marian Thomaiyar } 2202474adfaSEd Tanous }; 2212474adfaSEd Tanous 2222474adfaSEd Tanous } // namespace redfish 223