blob: 34506d90be02c2c7b251555539343611b04b5f48 [file] [log] [blame]
James Feist03a02ad2019-02-06 12:38:50 -08001/*
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
23constexpr const char* fatalLedPath =
24 "/xyz/openbmc_project/led/groups/status_critical";
25constexpr const char* criticalLedPath =
26 "/xyz/openbmc_project/led/groups/status_non_critical";
27constexpr const char* warningLedPath =
28 "/xyz/openbmc_project/led/groups/status_degraded";
James Feiste409fc72019-03-05 12:19:43 -080029constexpr const char* okLedPath = "/xyz/openbmc_project/led/groups/status_ok";
James Feist03a02ad2019-02-06 12:38:50 -080030
31constexpr const char* ledIface = "xyz.openbmc_project.Led.Group";
32constexpr const char* ledAssertProp = "Asserted";
33constexpr const char* ledManagerBusname =
34 "xyz.openbmc_project.LED.GroupManager";
35
James Feiste409fc72019-03-05 12:19:43 -080036enum class StatusSetting
37{
38 none,
39 ok,
40 warn,
41 critical,
42 fatal
43};
44
James Feist03a02ad2019-02-06 12:38:50 -080045std::shared_ptr<sdbusplus::asio::dbus_interface> assertedIface = nullptr;
46
47constexpr const bool debug = false;
48
49// final led state tracking
James Feiste409fc72019-03-05 12:19:43 -080050StatusSetting currentPriority = StatusSetting::none;
James Feist03a02ad2019-02-06 12:38:50 -080051
52// maps of <object-path, <property, asserted>>
53boost::container::flat_map<std::string,
54 boost::container::flat_map<std::string, bool>>
55 fatalAssertMap;
56boost::container::flat_map<std::string,
57 boost::container::flat_map<std::string, bool>>
58 criticalAssertMap;
59boost::container::flat_map<std::string,
60 boost::container::flat_map<std::string, bool>>
61 warningAssertMap;
62
63std::vector<std::string> assertedInMap(
64 const boost::container::flat_map<
65 std::string, boost::container::flat_map<std::string, bool>>& map)
66{
67 std::vector<std::string> ret;
68 // if any of the properties are true, return true
69 for (const auto& pair : map)
70 {
71 for (const auto& item : pair.second)
72 {
73 if (item.second)
74 {
75 ret.push_back(pair.first);
76 }
77 }
78 }
79 return ret;
80}
81
Richard Marian Thomaiyar28161212019-04-13 21:11:23 +053082void updateLedStatus(std::shared_ptr<sdbusplus::asio::connection>& conn,
83 bool forceRefresh = false)
James Feist03a02ad2019-02-06 12:38:50 -080084{
James Feist03a02ad2019-02-06 12:38:50 -080085 std::vector<std::string> assertedVector = assertedInMap(fatalAssertMap);
86 assertedIface->set_property("Fatal", assertedVector);
James Feist03a02ad2019-02-06 12:38:50 -080087 bool fatal = assertedVector.size();
James Feist03a02ad2019-02-06 12:38:50 -080088
89 assertedVector = assertedInMap(criticalAssertMap);
90 assertedIface->set_property("Critical", assertedVector);
James Feist03a02ad2019-02-06 12:38:50 -080091 bool critical = assertedVector.size();
James Feist03a02ad2019-02-06 12:38:50 -080092
93 assertedVector = assertedInMap(warningAssertMap);
94 assertedIface->set_property("Warning", assertedVector);
95
96 bool warn = assertedVector.size();
James Feiste409fc72019-03-05 12:19:43 -080097
98 StatusSetting last = currentPriority;
99
100 if (fatal)
James Feist03a02ad2019-02-06 12:38:50 -0800101 {
James Feiste409fc72019-03-05 12:19:43 -0800102 currentPriority = StatusSetting::fatal;
103 }
104 else if (critical)
105 {
106 currentPriority = StatusSetting::critical;
107 }
108 else if (warn)
109 {
110 currentPriority = StatusSetting::warn;
111 }
112 else
113 {
114 currentPriority = StatusSetting::ok;
115 }
116
117 std::vector<std::pair<std::string, std::variant<bool>>> ledsToSet;
118
Richard Marian Thomaiyar28161212019-04-13 21:11:23 +0530119 if (last != currentPriority || forceRefresh)
James Feiste409fc72019-03-05 12:19:43 -0800120 {
121 switch (currentPriority)
122 {
123 case (StatusSetting::fatal):
124 {
125 ledsToSet.push_back(std::make_pair(fatalLedPath, true));
126 ledsToSet.push_back(std::make_pair(criticalLedPath, false));
127 ledsToSet.push_back(std::make_pair(warningLedPath, false));
128 ledsToSet.push_back(std::make_pair(okLedPath, false));
129 break;
130 }
131 case (StatusSetting::critical):
132 {
133 ledsToSet.push_back(std::make_pair(fatalLedPath, false));
134 ledsToSet.push_back(std::make_pair(criticalLedPath, true));
135 ledsToSet.push_back(std::make_pair(warningLedPath, false));
136 ledsToSet.push_back(std::make_pair(okLedPath, false));
137 break;
138 }
139 case (StatusSetting::warn):
140 {
141 ledsToSet.push_back(std::make_pair(fatalLedPath, false));
142 ledsToSet.push_back(std::make_pair(criticalLedPath, false));
143 ledsToSet.push_back(std::make_pair(warningLedPath, true));
144 ledsToSet.push_back(std::make_pair(okLedPath, false));
145 break;
146 }
147 case (StatusSetting::ok):
148 {
149 ledsToSet.push_back(std::make_pair(fatalLedPath, false));
150 ledsToSet.push_back(std::make_pair(criticalLedPath, false));
151 ledsToSet.push_back(std::make_pair(warningLedPath, false));
152 ledsToSet.push_back(std::make_pair(okLedPath, true));
153 break;
154 }
155 }
James Feist03a02ad2019-02-06 12:38:50 -0800156 }
157
158 for (const auto& ledPair : ledsToSet)
159 {
160 conn->async_method_call(
161 [ledPair](const boost::system::error_code ec) {
162 if (ec)
163 {
164 std::cerr << "Cannot set " << ledPair.first << " to "
165 << std::boolalpha
166 << std::get<bool>(ledPair.second) << "\n";
167 }
168 if constexpr (debug)
169 {
170 std::cerr << "Set " << ledPair.first << " to "
171 << std::boolalpha
172 << std::get<bool>(ledPair.second) << "\n";
173 }
174 },
175 ledManagerBusname, ledPair.first, "org.freedesktop.DBus.Properties",
176 "Set", ledIface, ledAssertProp, ledPair.second);
177 }
178}
179
180void createThresholdMatch(std::shared_ptr<sdbusplus::asio::connection>& conn)
181{
182 static std::unique_ptr<sdbusplus::bus::match::match> match = nullptr;
183
184 std::function<void(sdbusplus::message::message&)> thresholdCallback =
185 [&conn](sdbusplus::message::message& message) {
186 std::string objectName;
187 boost::container::flat_map<std::string, std::variant<bool>> values;
188 message.read(objectName, values);
189
190 if constexpr (debug)
191 {
192 std::cerr << "Threshold callback " << message.get_path()
193 << "\n";
194 }
195
196 auto findCriticalLow = values.find("CriticalAlarmLow");
197 auto findCriticalHigh = values.find("CriticalAlarmHigh");
198
199 auto findWarnLow = values.find("WarningAlarmLow");
200 auto findWarnHigh = values.find("WarningAlarmHigh");
201
202 if (findCriticalLow != values.end())
203 {
204 criticalAssertMap[message.get_path()]["Low"] =
205 std::get<bool>(findCriticalLow->second);
206 }
207 if (findCriticalHigh != values.end())
208 {
209 criticalAssertMap[message.get_path()]["High"] =
210 std::get<bool>(findCriticalHigh->second);
211 }
212 if (findWarnLow != values.end())
213 {
214 warningAssertMap[message.get_path()]["Low"] =
215 std::get<bool>(findWarnLow->second);
216 }
217 if (findWarnHigh != values.end())
218 {
219 warningAssertMap[message.get_path()]["High"] =
220 std::get<bool>(findWarnHigh->second);
221 }
222 updateLedStatus(conn);
223 };
224
225 match = std::make_unique<sdbusplus::bus::match::match>(
226 static_cast<sdbusplus::bus::bus&>(*conn),
James Feiste409fc72019-03-05 12:19:43 -0800227 "type='signal',interface='org.freedesktop.DBus.Properties',"
228 "path_"
James Feist03a02ad2019-02-06 12:38:50 -0800229 "namespace='/xyz/openbmc_project/"
230 "sensors',arg0namespace='xyz.openbmc_project.Sensor.Threshold'",
231 thresholdCallback);
232}
233
234int main(int argc, char** argv)
235{
236 boost::asio::io_service io;
237 auto conn = std::make_shared<sdbusplus::asio::connection>(io);
238 conn->request_name("xyz.openbmc_project.CallbackManager");
239 sdbusplus::asio::object_server objServer(conn);
240 assertedIface =
241 objServer.add_interface("/xyz/openbmc_project/CallbackManager",
242 "xyz.openbmc_project.CallbackManager");
243 assertedIface->register_property("Warning", std::vector<std::string>());
244 assertedIface->register_property("Critical", std::vector<std::string>());
245 assertedIface->register_property("Fatal", std::vector<std::string>());
Richard Marian Thomaiyar28161212019-04-13 21:11:23 +0530246 assertedIface->register_method("RetriggerLEDUpdate",
247 [&conn]() { updateLedStatus(conn, true); });
James Feist03a02ad2019-02-06 12:38:50 -0800248 assertedIface->initialize();
249
250 createThresholdMatch(conn);
James Feiste409fc72019-03-05 12:19:43 -0800251 updateLedStatus(conn);
James Feist03a02ad2019-02-06 12:38:50 -0800252
253 io.run();
254
255 return 0;
256}