xref: /openbmc/dbus-sensors/src/Utils.cpp (revision e5a1af55)
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* POWER_INTERFACE_NAME =
27     "xyz.openbmc_project.Chassis.Control.Power";
28 const static constexpr char* POWER_OBJECT_NAME =
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                 ENTITY_MANAGER_NAME, "/", "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 find_files(const fs::path dir_path, const std::string& match_string,
85                 std::vector<fs::path>& found_paths, unsigned int symlink_depth)
86 {
87     if (!fs::exists(dir_path))
88         return false;
89 
90     fs::directory_iterator end_itr;
91     std::regex search(match_string);
92     std::smatch match;
93     for (auto& p : fs::recursive_directory_iterator(dir_path))
94     {
95         std::string path = p.path().string();
96         if (!is_directory(p))
97         {
98             if (std::regex_search(path, match, search))
99                 found_paths.emplace_back(p.path());
100         }
101         else if (is_symlink(p) && symlink_depth)
102         {
103             find_files(p.path(), match_string, found_paths, symlink_depth - 1);
104         }
105     }
106     return true;
107 }
108 
109 // initially returns false, then sets up matches and returns status
110 // should be called once first to initialize
111 bool isPowerOn(const std::shared_ptr<sdbusplus::asio::connection>& conn)
112 {
113     static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
114     static bool powerStatusOn = false;
115 
116     if (powerMatch != nullptr)
117     {
118         return powerStatusOn;
119     }
120 
121     // create a match for powergood changes, first time do a method call to
122     // return the correct value
123     std::function<void(sdbusplus::message::message & message)> eventHandler =
124         [&powerStatusOn](sdbusplus::message::message& message) {
125             std::string objectName;
126             boost::container::flat_map<std::string,
127                                        sdbusplus::message::variant<int32_t>>
128                 values;
129             message.read(objectName, values);
130             auto findPgood = values.find("pgood");
131             if (findPgood != values.end())
132             {
133                 powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(
134                     findPgood->second);
135             }
136         };
137 
138     powerMatch = std::make_unique<sdbusplus::bus::match::match>(
139         static_cast<sdbusplus::bus::bus&>(*conn),
140         "type='signal',interface='org.freedesktop.DBus.Properties',path_"
141         "namespace='/xyz/openbmc_project/Chassis/Control/"
142         "power0',arg0='xyz.openbmc_project.Chassis.Control.Power'",
143         eventHandler);
144 
145     conn->async_method_call(
146         [&powerStatusOn](boost::system::error_code ec,
147                          const sdbusplus::message::variant<int32_t>& pgood) {
148             if (ec)
149             {
150                 std::cerr << "Error getting initial power status\n";
151                 return;
152             }
153             powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(pgood);
154         },
155         POWER_INTERFACE_NAME, POWER_OBJECT_NAME,
156         "org.freedesktop.DBus.Properties", "Get", "pgood");
157 
158     return powerStatusOn;
159 }