blob: ba593060470ca538b4ceedd92d6f942468ff78c0 [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
James Feistdc7bbdc2019-05-16 15:33:06 -070017#include "callback_manager.hpp"
18
James Feist03a02ad2019-02-06 12:38:50 -080019#include <boost/container/flat_map.hpp>
James Feist03a02ad2019-02-06 12:38:50 -080020#include <sdbusplus/asio/connection.hpp>
21#include <sdbusplus/asio/object_server.hpp>
22#include <variant>
23
24constexpr const char* fatalLedPath =
25 "/xyz/openbmc_project/led/groups/status_critical";
26constexpr const char* criticalLedPath =
27 "/xyz/openbmc_project/led/groups/status_non_critical";
28constexpr const char* warningLedPath =
29 "/xyz/openbmc_project/led/groups/status_degraded";
James Feiste409fc72019-03-05 12:19:43 -080030constexpr const char* okLedPath = "/xyz/openbmc_project/led/groups/status_ok";
James Feist03a02ad2019-02-06 12:38:50 -080031
32constexpr const char* ledIface = "xyz.openbmc_project.Led.Group";
33constexpr const char* ledAssertProp = "Asserted";
34constexpr const char* ledManagerBusname =
35 "xyz.openbmc_project.LED.GroupManager";
36
James Feistdc7bbdc2019-05-16 15:33:06 -070037std::unique_ptr<AssociationManager> associationManager;
38
James Feiste409fc72019-03-05 12:19:43 -080039enum class StatusSetting
40{
41 none,
42 ok,
43 warn,
44 critical,
45 fatal
46};
47
James Feist03a02ad2019-02-06 12:38:50 -080048constexpr const bool debug = false;
49
50// final led state tracking
James Feiste409fc72019-03-05 12:19:43 -080051StatusSetting currentPriority = StatusSetting::none;
James Feist03a02ad2019-02-06 12:38:50 -080052
53// maps of <object-path, <property, asserted>>
54boost::container::flat_map<std::string,
55 boost::container::flat_map<std::string, bool>>
56 fatalAssertMap;
57boost::container::flat_map<std::string,
58 boost::container::flat_map<std::string, bool>>
59 criticalAssertMap;
60boost::container::flat_map<std::string,
61 boost::container::flat_map<std::string, bool>>
62 warningAssertMap;
63
64std::vector<std::string> assertedInMap(
65 const boost::container::flat_map<
66 std::string, boost::container::flat_map<std::string, bool>>& map)
67{
68 std::vector<std::string> ret;
69 // if any of the properties are true, return true
70 for (const auto& pair : map)
71 {
72 for (const auto& item : pair.second)
73 {
74 if (item.second)
75 {
76 ret.push_back(pair.first);
77 }
78 }
79 }
80 return ret;
81}
82
Richard Marian Thomaiyar28161212019-04-13 21:11:23 +053083void updateLedStatus(std::shared_ptr<sdbusplus::asio::connection>& conn,
84 bool forceRefresh = false)
James Feist03a02ad2019-02-06 12:38:50 -080085{
James Feistdc7bbdc2019-05-16 15:33:06 -070086 std::vector<std::string> fatalVector = assertedInMap(fatalAssertMap);
87 bool fatal = fatalVector.size();
James Feist03a02ad2019-02-06 12:38:50 -080088
James Feistdc7bbdc2019-05-16 15:33:06 -070089 std::vector<std::string> criticalVector = assertedInMap(criticalAssertMap);
90 bool critical = criticalVector.size();
James Feist03a02ad2019-02-06 12:38:50 -080091
James Feistdc7bbdc2019-05-16 15:33:06 -070092 std::vector<std::string> warningVector = assertedInMap(warningAssertMap);
93 bool warn = warningVector.size();
James Feist03a02ad2019-02-06 12:38:50 -080094
James Feistdc7bbdc2019-05-16 15:33:06 -070095 associationManager->setLocalAssociations(fatalVector, criticalVector,
96 warningVector);
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);
James Feistdc7bbdc2019-05-16 15:33:06 -0700240 std::shared_ptr<sdbusplus::asio::dbus_interface> rootIface =
241 objServer.add_interface(rootPath,
James Feist03a02ad2019-02-06 12:38:50 -0800242 "xyz.openbmc_project.CallbackManager");
James Feistdc7bbdc2019-05-16 15:33:06 -0700243 rootIface->register_method("RetriggerLEDUpdate",
244 [&conn]() { updateLedStatus(conn, true); });
245 rootIface->initialize();
246
247 std::shared_ptr<sdbusplus::asio::dbus_interface> inventoryIface =
248 objServer.add_interface(rootPath, globalInventoryIface);
249 inventoryIface->initialize();
250
251 associationManager = std::make_unique<AssociationManager>(objServer, conn);
James Feist03a02ad2019-02-06 12:38:50 -0800252
253 createThresholdMatch(conn);
James Feiste409fc72019-03-05 12:19:43 -0800254 updateLedStatus(conn);
James Feist03a02ad2019-02-06 12:38:50 -0800255
256 io.run();
257
258 return 0;
259}