1 #include "trigger.hpp" 2 3 #include "messages/collect_trigger_id.hpp" 4 #include "messages/trigger_presence_changed_ind.hpp" 5 #include "trigger_manager.hpp" 6 #include "types/report_types.hpp" 7 #include "types/trigger_types.hpp" 8 #include "utils/contains.hpp" 9 #include "utils/conversion_trigger.hpp" 10 #include "utils/transform.hpp" 11 12 #include <phosphor-logging/log.hpp> 13 14 Trigger::Trigger( 15 boost::asio::io_context& ioc, 16 const std::shared_ptr<sdbusplus::asio::object_server>& objServer, 17 TriggerId&& idIn, const std::string& nameIn, 18 const std::vector<TriggerAction>& triggerActionsIn, 19 const std::shared_ptr<std::vector<std::string>> reportIdsIn, 20 std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn, 21 interfaces::TriggerManager& triggerManager, 22 interfaces::JsonStorage& triggerStorageIn, 23 const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) : 24 id(std::move(idIn)), 25 name(nameIn), triggerActions(std::move(triggerActionsIn)), 26 path(triggerDir + *id), reportIds(std::move(reportIdsIn)), 27 thresholds(std::move(thresholdsIn)), 28 fileName(std::to_string(std::hash<std::string>{}(*id))), 29 triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)), 30 messanger(ioc) 31 { 32 deleteIface = objServer->add_unique_interface( 33 path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) { 34 dbusIface.register_method("Delete", [this, &ioc, &triggerManager] { 35 if (persistent) 36 { 37 triggerStorage.remove(fileName); 38 } 39 messanger.send(messages::TriggerPresenceChangedInd{ 40 messages::Presence::Removed, *id, {}}); 41 boost::asio::post(ioc, [this, &triggerManager] { 42 triggerManager.removeTrigger(this); 43 }); 44 }); 45 }); 46 47 triggerIface = objServer->add_unique_interface( 48 path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) { 49 persistent = storeConfiguration(); 50 dbusIface.register_property_rw( 51 "Persistent", persistent, 52 sdbusplus::vtable::property_::emits_change, 53 [this](bool newVal, const auto&) { 54 if (newVal == persistent) 55 { 56 return 1; 57 } 58 if (newVal) 59 { 60 persistent = storeConfiguration(); 61 } 62 else 63 { 64 triggerStorage.remove(fileName); 65 persistent = false; 66 } 67 return 1; 68 }, 69 [this](const auto&) { return persistent; }); 70 71 dbusIface.register_property_rw( 72 "Thresholds", TriggerThresholdParams{}, 73 sdbusplus::vtable::property_::emits_change, 74 [this, &triggerFactory](auto newVal, auto& oldVal) { 75 auto newThresholdParams = std::visit( 76 utils::ToLabeledThresholdParamConversion(), newVal); 77 triggerFactory.updateThresholds( 78 thresholds, *id, triggerActions, reportIds, sensors, 79 newThresholdParams); 80 oldVal = std::move(newVal); 81 return 1; 82 }, 83 [this](const auto&) { 84 return fromLabeledThresholdParam(getLabeledThresholds()); 85 }); 86 87 dbusIface.register_property_rw( 88 "Sensors", SensorsInfo{}, 89 sdbusplus::vtable::property_::emits_change, 90 [this, &triggerFactory](auto newVal, auto& oldVal) { 91 auto labeledSensorInfo = 92 triggerFactory.getLabeledSensorsInfo(newVal); 93 triggerFactory.updateSensors(sensors, labeledSensorInfo); 94 for (const auto& threshold : thresholds) 95 { 96 threshold->updateSensors(sensors); 97 } 98 oldVal = std::move(newVal); 99 return 1; 100 }, 101 [this](const auto&) { 102 return utils::fromLabeledSensorsInfo( 103 getLabeledSensorInfo()); 104 }); 105 106 dbusIface.register_property_rw( 107 "ReportNames", *reportIds, 108 sdbusplus::vtable::property_::emits_change, 109 [this](auto newVal, auto& oldVal) { 110 TriggerManager::verifyReportIds(newVal); 111 *reportIds = newVal; 112 messanger.send(messages::TriggerPresenceChangedInd{ 113 messages::Presence::Exist, *id, *reportIds}); 114 oldVal = std::move(newVal); 115 return 1; 116 }, 117 [this](const auto&) { return *reportIds; }); 118 119 dbusIface.register_property_r( 120 "Discrete", isDiscreate(), sdbusplus::vtable::property_::const_, 121 [this](const auto& x) { return isDiscreate(); }); 122 123 dbusIface.register_property_rw( 124 "Name", name, sdbusplus::vtable::property_::emits_change, 125 [this](auto newVal, auto& oldVal) { 126 name = oldVal = newVal; 127 return 1; 128 }, 129 [this](const auto&) { return name; }); 130 131 dbusIface.register_property_r( 132 "TriggerActions", std::vector<std::string>(), 133 sdbusplus::vtable::property_::const_, [this](const auto&) { 134 return utils::transform(triggerActions, 135 [](const auto& action) { 136 return actionToString(action); 137 }); 138 }); 139 }); 140 141 for (const auto& threshold : thresholds) 142 { 143 threshold->initialize(); 144 } 145 146 messanger.on_receive<messages::CollectTriggerIdReq>( 147 [this](const auto& msg) { 148 if (utils::contains(*reportIds, msg.reportId)) 149 { 150 messanger.send(messages::CollectTriggerIdResp{*id}); 151 } 152 }); 153 154 messanger.send(messages::TriggerPresenceChangedInd{ 155 messages::Presence::Exist, *id, *reportIds}); 156 } 157 158 bool Trigger::storeConfiguration() const 159 { 160 try 161 { 162 nlohmann::json data; 163 164 auto labeledThresholdParams = 165 std::visit(utils::ToLabeledThresholdParamConversion(), 166 fromLabeledThresholdParam(getLabeledThresholds())); 167 168 data["Version"] = triggerVersion; 169 data["Id"] = *id; 170 data["Name"] = name; 171 data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index(); 172 data["TriggerActions"] = 173 utils::transform(triggerActions, [](const auto& action) { 174 return actionToString(action); 175 }); 176 data["ThresholdParams"] = 177 utils::labeledThresholdParamsToJson(labeledThresholdParams); 178 data["ReportIds"] = *reportIds; 179 data["Sensors"] = getLabeledSensorInfo(); 180 181 triggerStorage.store(fileName, data); 182 } 183 catch (const std::exception& e) 184 { 185 phosphor::logging::log<phosphor::logging::level::ERR>( 186 "Failed to store a trigger in storage", 187 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); 188 return false; 189 } 190 return true; 191 } 192 193 std::vector<LabeledSensorInfo> Trigger::getLabeledSensorInfo() const 194 { 195 return utils::transform(sensors, [](const auto& sensor) { 196 return sensor->getLabeledSensorInfo(); 197 }); 198 } 199 200 std::vector<LabeledThresholdParam> Trigger::getLabeledThresholds() const 201 { 202 return utils::transform(thresholds, [](const auto& threshold) { 203 return threshold->getThresholdParam(); 204 }); 205 } 206 207 bool Trigger::isDiscreate() const 208 { 209 const auto labeledThresholds = getLabeledThresholds(); 210 211 return utils::isFirstElementOfType<std::monostate>(labeledThresholds) || 212 utils::isFirstElementOfType<discrete::LabeledThresholdParam>( 213 labeledThresholds); 214 } 215