xref: /openbmc/dbus-sensors/src/PSUEvent.cpp (revision 2aaf7175)
158b2b53eSCheng C Yang /*
258b2b53eSCheng C Yang // Copyright (c) 2019 Intel Corporation
358b2b53eSCheng C Yang //
458b2b53eSCheng C Yang // Licensed under the Apache License, Version 2.0 (the "License");
558b2b53eSCheng C Yang // you may not use this file except in compliance with the License.
658b2b53eSCheng C Yang // You may obtain a copy of the License at
758b2b53eSCheng C Yang //
858b2b53eSCheng C Yang //      http://www.apache.org/licenses/LICENSE-2.0
958b2b53eSCheng C Yang //
1058b2b53eSCheng C Yang // Unless required by applicable law or agreed to in writing, software
1158b2b53eSCheng C Yang // distributed under the License is distributed on an "AS IS" BASIS,
1258b2b53eSCheng C Yang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1358b2b53eSCheng C Yang // See the License for the specific language governing permissions and
1458b2b53eSCheng C Yang // limitations under the License.
1558b2b53eSCheng C Yang */
1658b2b53eSCheng C Yang 
17e73bd0a1SAndrew Jeffery #include "PSUEvent.hpp"
18e73bd0a1SAndrew Jeffery 
19e73bd0a1SAndrew Jeffery #include "SensorPaths.hpp"
20eacbfdd1SEd Tanous #include "Utils.hpp"
21e73bd0a1SAndrew Jeffery 
22eacbfdd1SEd Tanous #include <boost/asio/buffer.hpp>
23eacbfdd1SEd Tanous #include <boost/asio/error.hpp>
241f978631SEd Tanous #include <boost/asio/io_context.hpp>
25eacbfdd1SEd Tanous #include <boost/asio/random_access_file.hpp>
2696e97db7SPatrick Venture #include <boost/container/flat_map.hpp>
270c42f40eSPatrick Williams #include <phosphor-logging/lg2.hpp>
2858b2b53eSCheng C Yang #include <sdbusplus/asio/connection.hpp>
2958b2b53eSCheng C Yang #include <sdbusplus/asio/object_server.hpp>
3038fb5983SJames Feist 
31eacbfdd1SEd Tanous #include <array>
32eacbfdd1SEd Tanous #include <chrono>
33eacbfdd1SEd Tanous #include <cstddef>
3438fb5983SJames Feist #include <iostream>
3538fb5983SJames Feist #include <memory>
36eacbfdd1SEd Tanous #include <set>
3796e97db7SPatrick Venture #include <stdexcept>
3896e97db7SPatrick Venture #include <string>
3996e97db7SPatrick Venture #include <utility>
4096e97db7SPatrick Venture #include <vector>
4158b2b53eSCheng C Yang 
PSUCombineEvent(sdbusplus::asio::object_server & objectServer,std::shared_ptr<sdbusplus::asio::connection> & conn,boost::asio::io_context & io,const std::string & psuName,const PowerState & powerState,EventPathList & eventPathList,GroupEventPathList & groupEventPathList,const std::string & combineEventName,double pollRate)4258b2b53eSCheng C Yang PSUCombineEvent::PSUCombineEvent(
433046a024SYong Li     sdbusplus::asio::object_server& objectServer,
443046a024SYong Li     std::shared_ptr<sdbusplus::asio::connection>& conn,
451f978631SEd Tanous     boost::asio::io_context& io, const std::string& psuName,
465b3542eaSGeorge Liu     const PowerState& powerState, EventPathList& eventPathList,
475b3542eaSGeorge Liu     GroupEventPathList& groupEventPathList, const std::string& combineEventName,
48*2aaf7175SPatrick Williams     double pollRate) : objServer(objectServer)
4958b2b53eSCheng C Yang {
506cb732a3SEd Tanous     std::string psuNameEscaped = sensor_paths::escapePathForDbus(psuName);
5158b2b53eSCheng C Yang     eventInterface = objServer.add_interface(
526cb732a3SEd Tanous         "/xyz/openbmc_project/State/Decorator/" + psuNameEscaped + "_" +
5358b2b53eSCheng C Yang             combineEventName,
5458b2b53eSCheng C Yang         "xyz.openbmc_project.State.Decorator.OperationalStatus");
55b6c0b914SJames Feist     eventInterface->register_property("functional", true);
5658b2b53eSCheng C Yang 
5758b2b53eSCheng C Yang     if (!eventInterface->initialize())
5858b2b53eSCheng C Yang     {
5958b2b53eSCheng C Yang         std::cerr << "error initializing event interface\n";
6058b2b53eSCheng C Yang     }
6158b2b53eSCheng C Yang 
6258b2b53eSCheng C Yang     std::shared_ptr<std::set<std::string>> combineEvent =
6358b2b53eSCheng C Yang         std::make_shared<std::set<std::string>>();
64b85145cfSZev Weiss     for (const auto& [eventName, paths] : eventPathList)
6558b2b53eSCheng C Yang     {
66591b1e42SYong Li         std::shared_ptr<std::set<std::string>> assert =
67591b1e42SYong Li             std::make_shared<std::set<std::string>>();
68202a1ff0SCheng C Yang         std::shared_ptr<bool> state = std::make_shared<bool>(false);
69591b1e42SYong Li 
7058b2b53eSCheng C Yang         std::string eventPSUName = eventName + psuName;
71b85145cfSZev Weiss         for (const auto& path : paths)
7258b2b53eSCheng C Yang         {
73bf8b1dadSYong Li             auto p = std::make_shared<PSUSubEvent>(
74c7a1ae6bSKonstantin Aladyshev                 eventInterface, path, conn, io, powerState, eventName,
75c7a1ae6bSKonstantin Aladyshev                 eventName, assert, combineEvent, state, psuName, pollRate);
76bf8b1dadSYong Li             p->setupRead();
77bf8b1dadSYong Li 
78bf8b1dadSYong Li             events[eventPSUName].emplace_back(p);
7958b2b53eSCheng C Yang             asserts.emplace_back(assert);
8058b2b53eSCheng C Yang             states.emplace_back(state);
8158b2b53eSCheng C Yang         }
8258b2b53eSCheng C Yang     }
83202a1ff0SCheng C Yang 
84b85145cfSZev Weiss     for (const auto& [eventName, groupEvents] : groupEventPathList)
85202a1ff0SCheng C Yang     {
86b85145cfSZev Weiss         for (const auto& [groupEventName, paths] : groupEvents)
87202a1ff0SCheng C Yang         {
88202a1ff0SCheng C Yang             std::shared_ptr<std::set<std::string>> assert =
89202a1ff0SCheng C Yang                 std::make_shared<std::set<std::string>>();
90202a1ff0SCheng C Yang             std::shared_ptr<bool> state = std::make_shared<bool>(false);
91202a1ff0SCheng C Yang 
92202a1ff0SCheng C Yang             std::string eventPSUName = groupEventName + psuName;
93b85145cfSZev Weiss             for (const auto& path : paths)
94202a1ff0SCheng C Yang             {
95bf8b1dadSYong Li                 auto p = std::make_shared<PSUSubEvent>(
96c7a1ae6bSKonstantin Aladyshev                     eventInterface, path, conn, io, powerState, groupEventName,
97b85145cfSZev Weiss                     eventName, assert, combineEvent, state, psuName, pollRate);
98bf8b1dadSYong Li                 p->setupRead();
99bf8b1dadSYong Li                 events[eventPSUName].emplace_back(p);
100bf8b1dadSYong Li 
101202a1ff0SCheng C Yang                 asserts.emplace_back(assert);
102202a1ff0SCheng C Yang                 states.emplace_back(state);
103202a1ff0SCheng C Yang             }
104202a1ff0SCheng C Yang         }
105202a1ff0SCheng C Yang     }
10658b2b53eSCheng C Yang }
10758b2b53eSCheng C Yang 
~PSUCombineEvent()10858b2b53eSCheng C Yang PSUCombineEvent::~PSUCombineEvent()
10958b2b53eSCheng C Yang {
110202a1ff0SCheng C Yang     // Clear unique_ptr first
111b85145cfSZev Weiss     for (auto& [psuName, subEvents] : events)
112202a1ff0SCheng C Yang     {
113b85145cfSZev Weiss         for (auto& subEventPtr : subEvents)
114202a1ff0SCheng C Yang         {
115202a1ff0SCheng C Yang             subEventPtr.reset();
116202a1ff0SCheng C Yang         }
117202a1ff0SCheng C Yang     }
11858b2b53eSCheng C Yang     events.clear();
11958b2b53eSCheng C Yang     objServer.remove_interface(eventInterface);
12058b2b53eSCheng C Yang }
12158b2b53eSCheng C Yang 
1229b53a628SCheng C Yang static boost::container::flat_map<std::string,
1239b53a628SCheng C Yang                                   std::pair<std::string, std::string>>
1249b53a628SCheng C Yang     logID = {
1259b53a628SCheng C Yang         {"PredictiveFailure",
1269b53a628SCheng C Yang          {"OpenBMC.0.1.PowerSupplyFailurePredicted",
1279b53a628SCheng C Yang           "OpenBMC.0.1.PowerSupplyPredictedFailureRecovered"}},
1289b53a628SCheng C Yang         {"Failure",
1299b53a628SCheng C Yang          {"OpenBMC.0.1.PowerSupplyFailed", "OpenBMC.0.1.PowerSupplyRecovered"}},
1309b53a628SCheng C Yang         {"ACLost",
131bb732ef8SCheng C Yang          {"OpenBMC.0.1.PowerSupplyPowerLost",
132bb732ef8SCheng C Yang           "OpenBMC.0.1.PowerSupplyPowerRestored"}},
1339b53a628SCheng C Yang         {"FanFault",
1349b53a628SCheng C Yang          {"OpenBMC.0.1.PowerSupplyFanFailed",
1359b53a628SCheng C Yang           "OpenBMC.0.1.PowerSupplyFanRecovered"}},
136d12f23ecSjayaprakash Mutyala         {"ConfigureError",
137d12f23ecSjayaprakash Mutyala          {"OpenBMC.0.1.PowerSupplyConfigurationError",
138d12f23ecSjayaprakash Mutyala           "OpenBMC.0.1.PowerSupplyConfigurationErrorRecovered"}}};
1395665db2bSCheng C Yang 
PSUSubEvent(std::shared_ptr<sdbusplus::asio::dbus_interface> eventInterface,const std::string & path,std::shared_ptr<sdbusplus::asio::connection> & conn,boost::asio::io_context & io,const PowerState & powerState,const std::string & groupEventName,const std::string & eventName,std::shared_ptr<std::set<std::string>> asserts,std::shared_ptr<std::set<std::string>> combineEvent,std::shared_ptr<bool> state,const std::string & psuName,double pollRate)14058b2b53eSCheng C Yang PSUSubEvent::PSUSubEvent(
14158b2b53eSCheng C Yang     std::shared_ptr<sdbusplus::asio::dbus_interface> eventInterface,
1423046a024SYong Li     const std::string& path, std::shared_ptr<sdbusplus::asio::connection>& conn,
1431f978631SEd Tanous     boost::asio::io_context& io, const PowerState& powerState,
144c7a1ae6bSKonstantin Aladyshev     const std::string& groupEventName, const std::string& eventName,
14558b2b53eSCheng C Yang     std::shared_ptr<std::set<std::string>> asserts,
14658b2b53eSCheng C Yang     std::shared_ptr<std::set<std::string>> combineEvent,
1477170a235SLei YU     std::shared_ptr<bool> state, const std::string& psuName, double pollRate) :
148*2aaf7175SPatrick Williams     eventInterface(std::move(eventInterface)), asserts(std::move(asserts)),
149*2aaf7175SPatrick Williams     combineEvent(std::move(combineEvent)), assertState(std::move(state)),
150*2aaf7175SPatrick Williams     path(path), eventName(eventName), readState(powerState), waitTimer(io),
15116966b55SEd Tanous 
15216966b55SEd Tanous     inputDev(io, path, boost::asio::random_access_file::read_only),
15316966b55SEd Tanous     psuName(psuName), groupEventName(groupEventName), systemBus(conn)
15458b2b53eSCheng C Yang {
15516966b55SEd Tanous     buffer = std::make_shared<std::array<char, 128>>();
1567170a235SLei YU     if (pollRate > 0.0)
1577170a235SLei YU     {
1587170a235SLei YU         eventPollMs = static_cast<unsigned int>(pollRate * 1000);
1597170a235SLei YU     }
16099c4409aSEd Tanous 
1615665db2bSCheng C Yang     auto found = logID.find(eventName);
1625665db2bSCheng C Yang     if (found == logID.end())
1635665db2bSCheng C Yang     {
1649b53a628SCheng C Yang         assertMessage.clear();
1659b53a628SCheng C Yang         deassertMessage.clear();
1665665db2bSCheng C Yang     }
1675665db2bSCheng C Yang     else
1685665db2bSCheng C Yang     {
1699b53a628SCheng C Yang         assertMessage = found->second.first;
1709b53a628SCheng C Yang         deassertMessage = found->second.second;
1715665db2bSCheng C Yang     }
1725665db2bSCheng C Yang 
1735665db2bSCheng C Yang     auto fanPos = path.find("fan");
1745665db2bSCheng C Yang     if (fanPos != std::string::npos)
1755665db2bSCheng C Yang     {
1765665db2bSCheng C Yang         fanName = path.substr(fanPos);
1778a57ec09SEd Tanous         auto fanNamePos = fanName.find('_');
1789b53a628SCheng C Yang         if (fanNamePos != std::string::npos)
1799b53a628SCheng C Yang         {
1809b53a628SCheng C Yang             fanName = fanName.substr(0, fanNamePos);
1819b53a628SCheng C Yang         }
1825665db2bSCheng C Yang     }
18358b2b53eSCheng C Yang }
18458b2b53eSCheng C Yang 
~PSUSubEvent()185c7a1ae6bSKonstantin Aladyshev PSUSubEvent::~PSUSubEvent()
186c7a1ae6bSKonstantin Aladyshev {
187c7a1ae6bSKonstantin Aladyshev     waitTimer.cancel();
188c7a1ae6bSKonstantin Aladyshev     inputDev.close();
189c7a1ae6bSKonstantin Aladyshev }
190c7a1ae6bSKonstantin Aladyshev 
setupRead()191201a1015SEd Tanous void PSUSubEvent::setupRead()
19258b2b53eSCheng C Yang {
193c7a1ae6bSKonstantin Aladyshev     if (!readingStateGood(readState))
194c7a1ae6bSKonstantin Aladyshev     {
195c7a1ae6bSKonstantin Aladyshev         // Deassert the event
196c7a1ae6bSKonstantin Aladyshev         updateValue(0);
197c7a1ae6bSKonstantin Aladyshev         restartRead();
198c7a1ae6bSKonstantin Aladyshev         return;
199c7a1ae6bSKonstantin Aladyshev     }
20016966b55SEd Tanous     if (!buffer)
20116966b55SEd Tanous     {
20216966b55SEd Tanous         std::cerr << "Buffer was invalid?";
20316966b55SEd Tanous         return;
20416966b55SEd Tanous     }
205c7a1ae6bSKonstantin Aladyshev 
206bf8b1dadSYong Li     std::weak_ptr<PSUSubEvent> weakRef = weak_from_this();
20716966b55SEd Tanous     inputDev.async_read_some_at(
20816966b55SEd Tanous         0, boost::asio::buffer(buffer->data(), buffer->size() - 1),
20916966b55SEd Tanous         [weakRef, buffer{buffer}](const boost::system::error_code& ec,
21016966b55SEd Tanous                                   std::size_t bytesTransferred) {
211bf8b1dadSYong Li             std::shared_ptr<PSUSubEvent> self = weakRef.lock();
212bf8b1dadSYong Li             if (self)
213bf8b1dadSYong Li             {
21416966b55SEd Tanous                 self->handleResponse(ec, bytesTransferred);
215bf8b1dadSYong Li             }
216bf8b1dadSYong Li         });
21758b2b53eSCheng C Yang }
21858b2b53eSCheng C Yang 
restartRead()219c7a1ae6bSKonstantin Aladyshev void PSUSubEvent::restartRead()
22058b2b53eSCheng C Yang {
221c7a1ae6bSKonstantin Aladyshev     std::weak_ptr<PSUSubEvent> weakRef = weak_from_this();
22283db50caSEd Tanous     waitTimer.expires_after(std::chrono::milliseconds(eventPollMs));
223c7a1ae6bSKonstantin Aladyshev     waitTimer.async_wait([weakRef](const boost::system::error_code& ec) {
224c7a1ae6bSKonstantin Aladyshev         if (ec == boost::asio::error::operation_aborted)
225c7a1ae6bSKonstantin Aladyshev         {
226c7a1ae6bSKonstantin Aladyshev             return;
227c7a1ae6bSKonstantin Aladyshev         }
228c7a1ae6bSKonstantin Aladyshev         std::shared_ptr<PSUSubEvent> self = weakRef.lock();
229c7a1ae6bSKonstantin Aladyshev         if (self)
230c7a1ae6bSKonstantin Aladyshev         {
231c7a1ae6bSKonstantin Aladyshev             self->setupRead();
232c7a1ae6bSKonstantin Aladyshev         }
233c7a1ae6bSKonstantin Aladyshev     });
23458b2b53eSCheng C Yang }
23558b2b53eSCheng C Yang 
handleResponse(const boost::system::error_code & err,size_t bytesTransferred)23616966b55SEd Tanous void PSUSubEvent::handleResponse(const boost::system::error_code& err,
23716966b55SEd Tanous                                  size_t bytesTransferred)
23858b2b53eSCheng C Yang {
23916966b55SEd Tanous     if (err == boost::asio::error::operation_aborted)
24016966b55SEd Tanous     {
24116966b55SEd Tanous         return;
24216966b55SEd Tanous     }
24316966b55SEd Tanous 
244bf8b1dadSYong Li     if ((err == boost::system::errc::bad_file_descriptor) ||
245bf8b1dadSYong Li         (err == boost::asio::error::misc_errors::not_found))
24658b2b53eSCheng C Yang     {
24758b2b53eSCheng C Yang         return;
24858b2b53eSCheng C Yang     }
24916966b55SEd Tanous     if (!buffer)
25016966b55SEd Tanous     {
25116966b55SEd Tanous         std::cerr << "Buffer was invalid?";
25216966b55SEd Tanous         return;
25316966b55SEd Tanous     }
25416966b55SEd Tanous     // null terminate the string so we don't walk off the end
25516966b55SEd Tanous     std::array<char, 128>& bufferRef = *buffer;
25616966b55SEd Tanous     bufferRef[bytesTransferred] = '\0';
25716966b55SEd Tanous 
25858b2b53eSCheng C Yang     if (!err)
25958b2b53eSCheng C Yang     {
26058b2b53eSCheng C Yang         try
26158b2b53eSCheng C Yang         {
26216966b55SEd Tanous             int nvalue = std::stoi(bufferRef.data());
26358b2b53eSCheng C Yang             updateValue(nvalue);
26458b2b53eSCheng C Yang             errCount = 0;
26558b2b53eSCheng C Yang         }
26658b2b53eSCheng C Yang         catch (const std::invalid_argument&)
26758b2b53eSCheng C Yang         {
26858b2b53eSCheng C Yang             errCount++;
26958b2b53eSCheng C Yang         }
27058b2b53eSCheng C Yang     }
27158b2b53eSCheng C Yang     else
27258b2b53eSCheng C Yang     {
27358b2b53eSCheng C Yang         errCount++;
27458b2b53eSCheng C Yang     }
27558b2b53eSCheng C Yang     if (errCount >= warnAfterErrorCount)
27658b2b53eSCheng C Yang     {
27758b2b53eSCheng C Yang         if (errCount == warnAfterErrorCount)
27858b2b53eSCheng C Yang         {
27958b2b53eSCheng C Yang             std::cerr << "Failure to read event at " << path << "\n";
28058b2b53eSCheng C Yang         }
28158b2b53eSCheng C Yang         updateValue(0);
28258b2b53eSCheng C Yang         errCount++;
28358b2b53eSCheng C Yang     }
284c7a1ae6bSKonstantin Aladyshev     restartRead();
28558b2b53eSCheng C Yang }
28658b2b53eSCheng C Yang 
28758b2b53eSCheng C Yang // Any of the sub events of one event is asserted, then the event will be
28858b2b53eSCheng C Yang // asserted. Only if none of the sub events are asserted, the event will be
28958b2b53eSCheng C Yang // deasserted.
updateValue(const int & newValue)29058b2b53eSCheng C Yang void PSUSubEvent::updateValue(const int& newValue)
29158b2b53eSCheng C Yang {
292833661aeSJosh Lehan     // Take no action if value already equal
293833661aeSJosh Lehan     // Same semantics as Sensor::updateValue(const double&)
294833661aeSJosh Lehan     if (newValue == value)
295833661aeSJosh Lehan     {
296833661aeSJosh Lehan         return;
297833661aeSJosh Lehan     }
298833661aeSJosh Lehan 
29958b2b53eSCheng C Yang     if (newValue == 0)
30058b2b53eSCheng C Yang     {
301591b1e42SYong Li         // log deassert only after all asserts are gone
302591b1e42SYong Li         if (!(*asserts).empty())
303591b1e42SYong Li         {
30458b2b53eSCheng C Yang             auto found = (*asserts).find(path);
30558b2b53eSCheng C Yang             if (found == (*asserts).end())
30658b2b53eSCheng C Yang             {
30758b2b53eSCheng C Yang                 return;
30858b2b53eSCheng C Yang             }
3099b53a628SCheng C Yang             (*asserts).erase(path);
31058b2b53eSCheng C Yang 
31158b2b53eSCheng C Yang             return;
31258b2b53eSCheng C Yang         }
3132049bd26SEd Tanous         if (*assertState)
31458b2b53eSCheng C Yang         {
31558b2b53eSCheng C Yang             *assertState = false;
316202a1ff0SCheng C Yang             auto foundCombine = (*combineEvent).find(groupEventName);
3179b53a628SCheng C Yang             if (foundCombine == (*combineEvent).end())
31858b2b53eSCheng C Yang             {
31958b2b53eSCheng C Yang                 return;
32058b2b53eSCheng C Yang             }
321202a1ff0SCheng C Yang             (*combineEvent).erase(groupEventName);
3229b53a628SCheng C Yang             if (!deassertMessage.empty())
3239b53a628SCheng C Yang             {
3249b53a628SCheng C Yang                 // Fan Failed has two args
3259b53a628SCheng C Yang                 if (deassertMessage == "OpenBMC.0.1.PowerSupplyFanRecovered")
3269b53a628SCheng C Yang                 {
3270c42f40eSPatrick Williams                     lg2::info("{EVENT} deassert", "EVENT", eventName,
3280c42f40eSPatrick Williams                               "REDFISH_MESSAGE_ID", deassertMessage,
3290c42f40eSPatrick Williams                               "REDFISH_MESSAGE_ARGS",
3300c42f40eSPatrick Williams                               (psuName + ',' + fanName));
3319b53a628SCheng C Yang                 }
3329b53a628SCheng C Yang                 else
3339b53a628SCheng C Yang                 {
3340c42f40eSPatrick Williams                     lg2::info("{EVENT} deassert", "EVENT", eventName,
3350c42f40eSPatrick Williams                               "REDFISH_MESSAGE_ID", deassertMessage,
3360c42f40eSPatrick Williams                               "REDFISH_MESSAGE_ARGS", psuName);
3379b53a628SCheng C Yang                 }
3389b53a628SCheng C Yang             }
3399b53a628SCheng C Yang 
34058b2b53eSCheng C Yang             if ((*combineEvent).empty())
34158b2b53eSCheng C Yang             {
34258b2b53eSCheng C Yang                 eventInterface->set_property("functional", true);
34358b2b53eSCheng C Yang             }
34458b2b53eSCheng C Yang         }
34558b2b53eSCheng C Yang     }
34658b2b53eSCheng C Yang     else
34758b2b53eSCheng C Yang     {
3483453354bSPaul Fertser         std::cerr << "PSUSubEvent asserted by " << path << "\n";
3493453354bSPaul Fertser 
3502049bd26SEd Tanous         if ((!*assertState) && ((*asserts).empty()))
35158b2b53eSCheng C Yang         {
35258b2b53eSCheng C Yang             *assertState = true;
3539b53a628SCheng C Yang             if (!assertMessage.empty())
3545665db2bSCheng C Yang             {
3555665db2bSCheng C Yang                 // Fan Failed has two args
3569b53a628SCheng C Yang                 if (assertMessage == "OpenBMC.0.1.PowerSupplyFanFailed")
3575665db2bSCheng C Yang                 {
3580c42f40eSPatrick Williams                     lg2::warning("{EVENT} assert", "EVENT", eventName,
3590c42f40eSPatrick Williams                                  "REDFISH_MESSAGE_ID", assertMessage,
3600c42f40eSPatrick Williams                                  "REDFISH_MESSAGE_ARGS",
3610c42f40eSPatrick Williams                                  (psuName + ',' + fanName));
3625665db2bSCheng C Yang                 }
3635665db2bSCheng C Yang                 else
3645665db2bSCheng C Yang                 {
3650c42f40eSPatrick Williams                     lg2::warning("{EVENT} assert", "EVENT", eventName,
3660c42f40eSPatrick Williams                                  "REDFISH_MESSAGE_ID", assertMessage,
3670c42f40eSPatrick Williams                                  "REDFISH_MESSAGE_ARGS", psuName);
3685665db2bSCheng C Yang                 }
3695665db2bSCheng C Yang             }
37058b2b53eSCheng C Yang             if ((*combineEvent).empty())
37158b2b53eSCheng C Yang             {
37258b2b53eSCheng C Yang                 eventInterface->set_property("functional", false);
37358b2b53eSCheng C Yang             }
374202a1ff0SCheng C Yang             (*combineEvent).emplace(groupEventName);
37558b2b53eSCheng C Yang         }
376591b1e42SYong Li         (*asserts).emplace(path);
37758b2b53eSCheng C Yang     }
37858b2b53eSCheng C Yang     value = newValue;
37958b2b53eSCheng C Yang }
380