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 const std::string& 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(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(thresholds, triggerActions, 78 reportIds, sensors, 79 newThresholdParams); 80 oldVal = std::move(newVal); 81 return 1; 82 }, 83 [this](const auto&) { 84 return fromLabeledThresholdParam( 85 utils::transform(thresholds, [](const auto& threshold) { 86 return threshold->getThresholdParam(); 87 })); 88 }); 89 90 dbusIface.register_property_rw( 91 "Sensors", SensorsInfo{}, 92 sdbusplus::vtable::property_::emits_change, 93 [this, &triggerFactory](auto newVal, auto& oldVal) { 94 auto labeledSensorInfo = 95 triggerFactory.getLabeledSensorsInfo(newVal); 96 triggerFactory.updateSensors(sensors, labeledSensorInfo); 97 for (const auto& threshold : thresholds) 98 { 99 threshold->updateSensors(sensors); 100 } 101 oldVal = std::move(newVal); 102 return 1; 103 }, 104 [this](const auto&) { 105 return utils::fromLabeledSensorsInfo( 106 utils::transform(sensors, [](const auto& sensor) { 107 return sensor->getLabeledSensorInfo(); 108 })); 109 }); 110 111 dbusIface.register_property_rw( 112 "ReportNames", std::vector<std::string>{}, 113 sdbusplus::vtable::property_::emits_change, 114 [this](auto newVal, auto& oldVal) { 115 TriggerManager::verifyReportIds(newVal); 116 *reportIds = newVal; 117 messanger.send(messages::TriggerPresenceChangedInd{ 118 messages::Presence::Exist, id, *reportIds}); 119 oldVal = std::move(newVal); 120 return 1; 121 }, 122 [this](const auto&) { return *reportIds; }); 123 124 dbusIface.register_property_r( 125 "Discrete", false, sdbusplus::vtable::property_::const_, 126 [this](const auto& x) { 127 return !std::holds_alternative< 128 numeric::LabeledThresholdParam>( 129 thresholds.back()->getThresholdParam()); 130 }); 131 132 dbusIface.register_property_rw( 133 "Name", std::string(), 134 sdbusplus::vtable::property_::emits_change, 135 [this](auto newVal, auto& oldVal) { 136 name = oldVal = newVal; 137 return 1; 138 }, 139 [this](const auto&) { return name; }); 140 141 dbusIface.register_property_r( 142 "TriggerActions", std::vector<std::string>(), 143 sdbusplus::vtable::property_::const_, [this](const auto&) { 144 return utils::transform(triggerActions, 145 [](const auto& action) { 146 return actionToString(action); 147 }); 148 }); 149 }); 150 151 for (const auto& threshold : thresholds) 152 { 153 threshold->initialize(); 154 } 155 156 messanger.on_receive<messages::CollectTriggerIdReq>( 157 [this](const auto& msg) { 158 if (utils::contains(*reportIds, msg.reportId)) 159 { 160 messanger.send(messages::CollectTriggerIdResp{id}); 161 } 162 }); 163 164 messanger.send(messages::TriggerPresenceChangedInd{ 165 messages::Presence::Exist, id, *reportIds}); 166 } 167 168 bool Trigger::storeConfiguration() const 169 { 170 try 171 { 172 nlohmann::json data; 173 174 auto labeledThresholdParams = 175 std::visit(utils::ToLabeledThresholdParamConversion(), 176 fromLabeledThresholdParam(utils::transform( 177 thresholds, [](const auto& threshold) { 178 return threshold->getThresholdParam(); 179 }))); 180 181 data["Version"] = triggerVersion; 182 data["Id"] = id; 183 data["Name"] = name; 184 data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index(); 185 data["TriggerActions"] = 186 utils::transform(triggerActions, [](const auto& action) { 187 return actionToString(action); 188 }); 189 data["ThresholdParams"] = 190 utils::labeledThresholdParamsToJson(labeledThresholdParams); 191 data["ReportIds"] = *reportIds; 192 data["Sensors"] = utils::transform(sensors, [](const auto& sensor) { 193 return sensor->getLabeledSensorInfo(); 194 }); 195 196 triggerStorage.store(fileName, data); 197 } 198 catch (const std::exception& e) 199 { 200 phosphor::logging::log<phosphor::logging::level::ERR>( 201 "Failed to store a trigger in storage", 202 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); 203 return false; 204 } 205 return true; 206 } 207