blob: 706c607ed460b5f7e8de2cd53318fa7816d7e272 [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";
29
30constexpr const char* ledIface = "xyz.openbmc_project.Led.Group";
31constexpr const char* ledAssertProp = "Asserted";
32constexpr const char* ledManagerBusname =
33 "xyz.openbmc_project.LED.GroupManager";
34
35std::shared_ptr<sdbusplus::asio::dbus_interface> assertedIface = nullptr;
36
37constexpr const bool debug = false;
38
39// final led state tracking
40bool fatalState = false;
41bool criticalState = false;
42bool warnState = false;
43
44// maps of <object-path, <property, asserted>>
45boost::container::flat_map<std::string,
46 boost::container::flat_map<std::string, bool>>
47 fatalAssertMap;
48boost::container::flat_map<std::string,
49 boost::container::flat_map<std::string, bool>>
50 criticalAssertMap;
51boost::container::flat_map<std::string,
52 boost::container::flat_map<std::string, bool>>
53 warningAssertMap;
54
55std::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
74void 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
130void 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
183int 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}