blob: 58d7e2dd46aed9ecb0832d94a6e9a4af2b220191 [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
82void updateLedStatus(std::shared_ptr<sdbusplus::asio::connection>& conn)
83{
James Feist03a02ad2019-02-06 12:38:50 -080084 std::vector<std::string> assertedVector = assertedInMap(fatalAssertMap);
85 assertedIface->set_property("Fatal", assertedVector);
James Feist03a02ad2019-02-06 12:38:50 -080086 bool fatal = assertedVector.size();
James Feist03a02ad2019-02-06 12:38:50 -080087
88 assertedVector = assertedInMap(criticalAssertMap);
89 assertedIface->set_property("Critical", assertedVector);
James Feist03a02ad2019-02-06 12:38:50 -080090 bool critical = assertedVector.size();
James Feist03a02ad2019-02-06 12:38:50 -080091
92 assertedVector = assertedInMap(warningAssertMap);
93 assertedIface->set_property("Warning", assertedVector);
94
95 bool warn = assertedVector.size();
James Feiste409fc72019-03-05 12:19:43 -080096
97 StatusSetting last = currentPriority;
98
99 if (fatal)
James Feist03a02ad2019-02-06 12:38:50 -0800100 {
James Feiste409fc72019-03-05 12:19:43 -0800101 currentPriority = StatusSetting::fatal;
102 }
103 else if (critical)
104 {
105 currentPriority = StatusSetting::critical;
106 }
107 else if (warn)
108 {
109 currentPriority = StatusSetting::warn;
110 }
111 else
112 {
113 currentPriority = StatusSetting::ok;
114 }
115
116 std::vector<std::pair<std::string, std::variant<bool>>> ledsToSet;
117
118 if (last != currentPriority)
119 {
120 switch (currentPriority)
121 {
122 case (StatusSetting::fatal):
123 {
124 ledsToSet.push_back(std::make_pair(fatalLedPath, true));
125 ledsToSet.push_back(std::make_pair(criticalLedPath, false));
126 ledsToSet.push_back(std::make_pair(warningLedPath, false));
127 ledsToSet.push_back(std::make_pair(okLedPath, false));
128 break;
129 }
130 case (StatusSetting::critical):
131 {
132 ledsToSet.push_back(std::make_pair(fatalLedPath, false));
133 ledsToSet.push_back(std::make_pair(criticalLedPath, true));
134 ledsToSet.push_back(std::make_pair(warningLedPath, false));
135 ledsToSet.push_back(std::make_pair(okLedPath, false));
136 break;
137 }
138 case (StatusSetting::warn):
139 {
140 ledsToSet.push_back(std::make_pair(fatalLedPath, false));
141 ledsToSet.push_back(std::make_pair(criticalLedPath, false));
142 ledsToSet.push_back(std::make_pair(warningLedPath, true));
143 ledsToSet.push_back(std::make_pair(okLedPath, false));
144 break;
145 }
146 case (StatusSetting::ok):
147 {
148 ledsToSet.push_back(std::make_pair(fatalLedPath, false));
149 ledsToSet.push_back(std::make_pair(criticalLedPath, false));
150 ledsToSet.push_back(std::make_pair(warningLedPath, false));
151 ledsToSet.push_back(std::make_pair(okLedPath, true));
152 break;
153 }
154 }
James Feist03a02ad2019-02-06 12:38:50 -0800155 }
156
157 for (const auto& ledPair : ledsToSet)
158 {
159 conn->async_method_call(
160 [ledPair](const boost::system::error_code ec) {
161 if (ec)
162 {
163 std::cerr << "Cannot set " << ledPair.first << " to "
164 << std::boolalpha
165 << std::get<bool>(ledPair.second) << "\n";
166 }
167 if constexpr (debug)
168 {
169 std::cerr << "Set " << ledPair.first << " to "
170 << std::boolalpha
171 << std::get<bool>(ledPair.second) << "\n";
172 }
173 },
174 ledManagerBusname, ledPair.first, "org.freedesktop.DBus.Properties",
175 "Set", ledIface, ledAssertProp, ledPair.second);
176 }
177}
178
179void createThresholdMatch(std::shared_ptr<sdbusplus::asio::connection>& conn)
180{
181 static std::unique_ptr<sdbusplus::bus::match::match> match = nullptr;
182
183 std::function<void(sdbusplus::message::message&)> thresholdCallback =
184 [&conn](sdbusplus::message::message& message) {
185 std::string objectName;
186 boost::container::flat_map<std::string, std::variant<bool>> values;
187 message.read(objectName, values);
188
189 if constexpr (debug)
190 {
191 std::cerr << "Threshold callback " << message.get_path()
192 << "\n";
193 }
194
195 auto findCriticalLow = values.find("CriticalAlarmLow");
196 auto findCriticalHigh = values.find("CriticalAlarmHigh");
197
198 auto findWarnLow = values.find("WarningAlarmLow");
199 auto findWarnHigh = values.find("WarningAlarmHigh");
200
201 if (findCriticalLow != values.end())
202 {
203 criticalAssertMap[message.get_path()]["Low"] =
204 std::get<bool>(findCriticalLow->second);
205 }
206 if (findCriticalHigh != values.end())
207 {
208 criticalAssertMap[message.get_path()]["High"] =
209 std::get<bool>(findCriticalHigh->second);
210 }
211 if (findWarnLow != values.end())
212 {
213 warningAssertMap[message.get_path()]["Low"] =
214 std::get<bool>(findWarnLow->second);
215 }
216 if (findWarnHigh != values.end())
217 {
218 warningAssertMap[message.get_path()]["High"] =
219 std::get<bool>(findWarnHigh->second);
220 }
221 updateLedStatus(conn);
222 };
223
224 match = std::make_unique<sdbusplus::bus::match::match>(
225 static_cast<sdbusplus::bus::bus&>(*conn),
James Feiste409fc72019-03-05 12:19:43 -0800226 "type='signal',interface='org.freedesktop.DBus.Properties',"
227 "path_"
James Feist03a02ad2019-02-06 12:38:50 -0800228 "namespace='/xyz/openbmc_project/"
229 "sensors',arg0namespace='xyz.openbmc_project.Sensor.Threshold'",
230 thresholdCallback);
231}
232
233int main(int argc, char** argv)
234{
235 boost::asio::io_service io;
236 auto conn = std::make_shared<sdbusplus::asio::connection>(io);
237 conn->request_name("xyz.openbmc_project.CallbackManager");
238 sdbusplus::asio::object_server objServer(conn);
239 assertedIface =
240 objServer.add_interface("/xyz/openbmc_project/CallbackManager",
241 "xyz.openbmc_project.CallbackManager");
242 assertedIface->register_property("Warning", std::vector<std::string>());
243 assertedIface->register_property("Critical", std::vector<std::string>());
244 assertedIface->register_property("Fatal", std::vector<std::string>());
245 assertedIface->initialize();
246
247 createThresholdMatch(conn);
James Feiste409fc72019-03-05 12:19:43 -0800248 updateLedStatus(conn);
James Feist03a02ad2019-02-06 12:38:50 -0800249
250 io.run();
251
252 return 0;
253}