1 /* 2 // Copyright (c) 2019 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 <boost/container/flat_map.hpp> 18 #include <iostream> 19 #include <sdbusplus/asio/connection.hpp> 20 #include <sdbusplus/asio/object_server.hpp> 21 #include <variant> 22 23 constexpr const char* fatalLedPath = 24 "/xyz/openbmc_project/led/groups/status_critical"; 25 constexpr const char* criticalLedPath = 26 "/xyz/openbmc_project/led/groups/status_non_critical"; 27 constexpr const char* warningLedPath = 28 "/xyz/openbmc_project/led/groups/status_degraded"; 29 30 constexpr const char* ledIface = "xyz.openbmc_project.Led.Group"; 31 constexpr const char* ledAssertProp = "Asserted"; 32 constexpr const char* ledManagerBusname = 33 "xyz.openbmc_project.LED.GroupManager"; 34 35 std::shared_ptr<sdbusplus::asio::dbus_interface> assertedIface = nullptr; 36 37 constexpr const bool debug = false; 38 39 // final led state tracking 40 bool fatalState = false; 41 bool criticalState = false; 42 bool warnState = false; 43 44 // maps of <object-path, <property, asserted>> 45 boost::container::flat_map<std::string, 46 boost::container::flat_map<std::string, bool>> 47 fatalAssertMap; 48 boost::container::flat_map<std::string, 49 boost::container::flat_map<std::string, bool>> 50 criticalAssertMap; 51 boost::container::flat_map<std::string, 52 boost::container::flat_map<std::string, bool>> 53 warningAssertMap; 54 55 std::vector<std::string> assertedInMap( 56 const boost::container::flat_map< 57 std::string, boost::container::flat_map<std::string, bool>>& map) 58 { 59 std::vector<std::string> ret; 60 // if any of the properties are true, return true 61 for (const auto& pair : map) 62 { 63 for (const auto& item : pair.second) 64 { 65 if (item.second) 66 { 67 ret.push_back(pair.first); 68 } 69 } 70 } 71 return ret; 72 } 73 74 void updateLedStatus(std::shared_ptr<sdbusplus::asio::connection>& conn) 75 { 76 std::vector<std::pair<std::string, std::variant<bool>>> ledsToSet; 77 78 std::vector<std::string> assertedVector = assertedInMap(fatalAssertMap); 79 assertedIface->set_property("Fatal", assertedVector); 80 81 bool fatal = assertedVector.size(); 82 if (fatal != fatalState) 83 { 84 fatalState = fatal; 85 ledsToSet.push_back(std::make_pair(fatalLedPath, fatalState)); 86 } 87 88 assertedVector = assertedInMap(criticalAssertMap); 89 assertedIface->set_property("Critical", assertedVector); 90 91 bool critical = assertedVector.size(); 92 if (critical != criticalState) 93 { 94 criticalState = critical; 95 ledsToSet.push_back(std::make_pair(criticalLedPath, criticalState)); 96 } 97 98 assertedVector = assertedInMap(warningAssertMap); 99 assertedIface->set_property("Warning", assertedVector); 100 101 bool warn = assertedVector.size(); 102 if (warn != warnState) 103 { 104 warnState = warn; 105 ledsToSet.push_back(std::make_pair(warningLedPath, warnState)); 106 } 107 108 for (const auto& ledPair : ledsToSet) 109 { 110 conn->async_method_call( 111 [ledPair](const boost::system::error_code ec) { 112 if (ec) 113 { 114 std::cerr << "Cannot set " << ledPair.first << " to " 115 << std::boolalpha 116 << std::get<bool>(ledPair.second) << "\n"; 117 } 118 if constexpr (debug) 119 { 120 std::cerr << "Set " << ledPair.first << " to " 121 << std::boolalpha 122 << std::get<bool>(ledPair.second) << "\n"; 123 } 124 }, 125 ledManagerBusname, ledPair.first, "org.freedesktop.DBus.Properties", 126 "Set", ledIface, ledAssertProp, ledPair.second); 127 } 128 } 129 130 void createThresholdMatch(std::shared_ptr<sdbusplus::asio::connection>& conn) 131 { 132 static std::unique_ptr<sdbusplus::bus::match::match> match = nullptr; 133 134 std::function<void(sdbusplus::message::message&)> thresholdCallback = 135 [&conn](sdbusplus::message::message& message) { 136 std::string objectName; 137 boost::container::flat_map<std::string, std::variant<bool>> values; 138 message.read(objectName, values); 139 140 if constexpr (debug) 141 { 142 std::cerr << "Threshold callback " << message.get_path() 143 << "\n"; 144 } 145 146 auto findCriticalLow = values.find("CriticalAlarmLow"); 147 auto findCriticalHigh = values.find("CriticalAlarmHigh"); 148 149 auto findWarnLow = values.find("WarningAlarmLow"); 150 auto findWarnHigh = values.find("WarningAlarmHigh"); 151 152 if (findCriticalLow != values.end()) 153 { 154 criticalAssertMap[message.get_path()]["Low"] = 155 std::get<bool>(findCriticalLow->second); 156 } 157 if (findCriticalHigh != values.end()) 158 { 159 criticalAssertMap[message.get_path()]["High"] = 160 std::get<bool>(findCriticalHigh->second); 161 } 162 if (findWarnLow != values.end()) 163 { 164 warningAssertMap[message.get_path()]["Low"] = 165 std::get<bool>(findWarnLow->second); 166 } 167 if (findWarnHigh != values.end()) 168 { 169 warningAssertMap[message.get_path()]["High"] = 170 std::get<bool>(findWarnHigh->second); 171 } 172 updateLedStatus(conn); 173 }; 174 175 match = std::make_unique<sdbusplus::bus::match::match>( 176 static_cast<sdbusplus::bus::bus&>(*conn), 177 "type='signal',interface='org.freedesktop.DBus.Properties',path_" 178 "namespace='/xyz/openbmc_project/" 179 "sensors',arg0namespace='xyz.openbmc_project.Sensor.Threshold'", 180 thresholdCallback); 181 } 182 183 int main(int argc, char** argv) 184 { 185 boost::asio::io_service io; 186 auto conn = std::make_shared<sdbusplus::asio::connection>(io); 187 conn->request_name("xyz.openbmc_project.CallbackManager"); 188 sdbusplus::asio::object_server objServer(conn); 189 assertedIface = 190 objServer.add_interface("/xyz/openbmc_project/CallbackManager", 191 "xyz.openbmc_project.CallbackManager"); 192 assertedIface->register_property("Warning", std::vector<std::string>()); 193 assertedIface->register_property("Critical", std::vector<std::string>()); 194 assertedIface->register_property("Fatal", std::vector<std::string>()); 195 assertedIface->initialize(); 196 197 createThresholdMatch(conn); 198 199 io.run(); 200 201 return 0; 202 } 203