1 /* 2 // Copyright (c) 2017 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 17 #include "filesystem.hpp" 18 19 #include <Utils.hpp> 20 #include <boost/algorithm/string/predicate.hpp> 21 #include <fstream> 22 #include <regex> 23 #include <sdbusplus/asio/connection.hpp> 24 #include <sdbusplus/bus/match.hpp> 25 26 namespace fs = std::filesystem; 27 const static constexpr char* powerInterfaceName = 28 "xyz.openbmc_project.Chassis.Control.Power"; 29 const static constexpr char* powerObjectName = 30 "/xyz/openbmc_project/Chassis/Control/Power0"; 31 32 static bool powerStatusOn = false; 33 static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr; 34 35 bool getSensorConfiguration( 36 const std::string& type, 37 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection, 38 ManagedObjectType& resp, bool useCache) 39 { 40 static ManagedObjectType managedObj; 41 42 if (!useCache) 43 { 44 managedObj.clear(); 45 sdbusplus::message::message getManagedObjects = 46 dbusConnection->new_method_call( 47 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager", 48 "GetManagedObjects"); 49 bool err = false; 50 try 51 { 52 sdbusplus::message::message reply = 53 dbusConnection->call(getManagedObjects); 54 reply.read(managedObj); 55 } 56 catch (const sdbusplus::exception::exception&) 57 { 58 err = true; 59 } 60 61 if (err) 62 { 63 std::cerr << "Error communicating to entity manager\n"; 64 return false; 65 } 66 } 67 for (const auto& pathPair : managedObj) 68 { 69 std::vector<boost::container::flat_map<std::string, BasicVariantType>> 70 sensorData; 71 bool correctType = false; 72 for (const auto& entry : pathPair.second) 73 { 74 if (boost::starts_with(entry.first, type)) 75 { 76 correctType = true; 77 break; 78 } 79 } 80 if (correctType) 81 { 82 resp.emplace(pathPair); 83 } 84 } 85 return true; 86 } 87 88 bool findFiles(const fs::path dirPath, const std::string& matchString, 89 std::vector<fs::path>& foundPaths, unsigned int symlinkDepth) 90 { 91 if (!fs::exists(dirPath)) 92 return false; 93 94 std::regex search(matchString); 95 std::smatch match; 96 for (auto& p : fs::recursive_directory_iterator(dirPath)) 97 { 98 std::string path = p.path().string(); 99 if (!is_directory(p)) 100 { 101 if (std::regex_search(path, match, search)) 102 foundPaths.emplace_back(p.path()); 103 } 104 else if (is_symlink(p) && symlinkDepth) 105 { 106 findFiles(p.path(), matchString, foundPaths, symlinkDepth - 1); 107 } 108 } 109 return true; 110 } 111 112 bool isPowerOn(void) 113 { 114 if (!powerMatch) 115 { 116 throw std::runtime_error("Power Match Not Created"); 117 } 118 return powerStatusOn; 119 } 120 121 void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn) 122 { 123 124 // create a match for powergood changes, first time do a method call to 125 // cache the correct value 126 std::function<void(sdbusplus::message::message & message)> eventHandler = 127 [](sdbusplus::message::message& message) { 128 std::string objectName; 129 boost::container::flat_map<std::string, 130 sdbusplus::message::variant<int32_t>> 131 values; 132 message.read(objectName, values); 133 auto findPgood = values.find("pgood"); 134 if (findPgood != values.end()) 135 { 136 powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>( 137 findPgood->second); 138 } 139 }; 140 141 powerMatch = std::make_unique<sdbusplus::bus::match::match>( 142 static_cast<sdbusplus::bus::bus&>(*conn), 143 "type='signal',interface='org.freedesktop.DBus.Properties',path_" 144 "namespace='/xyz/openbmc_project/Chassis/Control/" 145 "power0',arg0='xyz.openbmc_project.Chassis.Control.Power'", 146 eventHandler); 147 148 conn->async_method_call( 149 [](boost::system::error_code ec, 150 const sdbusplus::message::variant<int32_t>& pgood) { 151 if (ec) 152 { 153 std::cerr << "Error getting initial power status\n"; 154 return; 155 } 156 powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(pgood); 157 }, 158 powerInterfaceName, powerObjectName, "org.freedesktop.DBus.Properties", 159 "Get", powerInterfaceName, "pgood"); 160 } 161 162 // replaces limits if MinReading and MaxReading are found. 163 void findLimits(std::pair<double, double>& limits, 164 const SensorBaseConfiguration* data) 165 { 166 if (!data) 167 { 168 return; 169 } 170 auto maxFind = data->second.find("MaxReading"); 171 auto minFind = data->second.find("MinReading"); 172 173 if (minFind != data->second.end()) 174 { 175 limits.first = sdbusplus::message::variant_ns::visit( 176 VariantToDoubleVisitor(), minFind->second); 177 } 178 if (maxFind != data->second.end()) 179 { 180 limits.second = sdbusplus::message::variant_ns::visit( 181 VariantToDoubleVisitor(), maxFind->second); 182 } 183 }