xref: /openbmc/dbus-sensors/src/Utils.cpp (revision dc6c55f3)
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 <Utils.hpp>
18 #include <boost/algorithm/string/predicate.hpp>
19 #include <experimental/filesystem>
20 #include <fstream>
21 #include <regex>
22 #include <sdbusplus/asio/connection.hpp>
23 #include <sdbusplus/bus/match.hpp>
24 
25 namespace fs = std::experimental::filesystem;
26 const static constexpr char* powerInterfaceName =
27     "xyz.openbmc_project.Chassis.Control.Power";
28 const static constexpr char* powerObjectName =
29     "/xyz/openbmc_project/Chassis/Control/Power0";
30 
31 bool getSensorConfiguration(
32     const std::string& type,
33     const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
34     ManagedObjectType& resp, bool useCache)
35 {
36     static ManagedObjectType managedObj;
37 
38     if (!useCache)
39     {
40         managedObj.clear();
41         sdbusplus::message::message getManagedObjects =
42             dbusConnection->new_method_call(
43                 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
44                 "GetManagedObjects");
45         bool err = false;
46         try
47         {
48             sdbusplus::message::message reply =
49                 dbusConnection->call(getManagedObjects);
50             reply.read(managedObj);
51         }
52         catch (const sdbusplus::exception::exception&)
53         {
54             err = true;
55         }
56 
57         if (err)
58         {
59             std::cerr << "Error communicating to entity manager\n";
60             return false;
61         }
62     }
63     for (const auto& pathPair : managedObj)
64     {
65         std::vector<boost::container::flat_map<std::string, BasicVariantType>>
66             sensorData;
67         bool correctType = false;
68         for (const auto& entry : pathPair.second)
69         {
70             if (boost::starts_with(entry.first, type))
71             {
72                 correctType = true;
73                 break;
74             }
75         }
76         if (correctType)
77         {
78             resp.emplace(pathPair);
79         }
80     }
81     return true;
82 }
83 
84 bool findFiles(const fs::path dirPath, const std::string& matchString,
85                std::vector<fs::path>& foundPaths, unsigned int symlinkDepth)
86 {
87     if (!fs::exists(dirPath))
88         return false;
89 
90     std::regex search(matchString);
91     std::smatch match;
92     for (auto& p : fs::recursive_directory_iterator(dirPath))
93     {
94         std::string path = p.path().string();
95         if (!is_directory(p))
96         {
97             if (std::regex_search(path, match, search))
98                 foundPaths.emplace_back(p.path());
99         }
100         else if (is_symlink(p) && symlinkDepth)
101         {
102             findFiles(p.path(), matchString, foundPaths, symlinkDepth - 1);
103         }
104     }
105     return true;
106 }
107 
108 // initially returns false, then sets up matches and returns status
109 // should be called once first to initialize
110 bool isPowerOn(const std::shared_ptr<sdbusplus::asio::connection>& conn)
111 {
112     static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
113     static bool powerStatusOn = false;
114 
115     if (powerMatch != nullptr)
116     {
117         return powerStatusOn;
118     }
119 
120     // create a match for powergood changes, first time do a method call to
121     // return the correct value
122     std::function<void(sdbusplus::message::message & message)> eventHandler =
123         [&powerStatusOn](sdbusplus::message::message& message) {
124             std::string objectName;
125             boost::container::flat_map<std::string,
126                                        sdbusplus::message::variant<int32_t>>
127                 values;
128             message.read(objectName, values);
129             auto findPgood = values.find("pgood");
130             if (findPgood != values.end())
131             {
132                 powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(
133                     findPgood->second);
134             }
135         };
136 
137     powerMatch = std::make_unique<sdbusplus::bus::match::match>(
138         static_cast<sdbusplus::bus::bus&>(*conn),
139         "type='signal',interface='org.freedesktop.DBus.Properties',path_"
140         "namespace='/xyz/openbmc_project/Chassis/Control/"
141         "power0',arg0='xyz.openbmc_project.Chassis.Control.Power'",
142         eventHandler);
143 
144     conn->async_method_call(
145         [&powerStatusOn](boost::system::error_code ec,
146                          const sdbusplus::message::variant<int32_t>& pgood) {
147             if (ec)
148             {
149                 std::cerr << "Error getting initial power status\n";
150                 return;
151             }
152             powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(pgood);
153         },
154         powerInterfaceName, powerObjectName, "org.freedesktop.DBus.Properties",
155         "Get", powerInterfaceName, "pgood");
156 
157     return powerStatusOn;
158 }