| #include "trigger.hpp" |
| |
| #include "messages/collect_trigger_id.hpp" |
| #include "messages/trigger_presence_changed_ind.hpp" |
| #include "trigger_manager.hpp" |
| #include "types/report_types.hpp" |
| #include "types/trigger_types.hpp" |
| #include "utils/contains.hpp" |
| #include "utils/conversion_trigger.hpp" |
| #include "utils/dbus_path_utils.hpp" |
| #include "utils/transform.hpp" |
| |
| #include <phosphor-logging/log.hpp> |
| |
| Trigger::Trigger( |
| boost::asio::io_context& ioc, |
| const std::shared_ptr<sdbusplus::asio::object_server>& objServer, |
| TriggerId&& idIn, const std::string& nameIn, |
| const std::vector<TriggerAction>& triggerActionsIn, |
| const std::shared_ptr<std::vector<std::string>> reportIdsIn, |
| std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn, |
| interfaces::TriggerManager& triggerManager, |
| interfaces::JsonStorage& triggerStorageIn, |
| const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) : |
| id(std::move(idIn)), |
| path(utils::pathAppend(utils::constants::triggerDirPath, *id)), |
| name(nameIn), triggerActions(std::move(triggerActionsIn)), |
| reportIds(std::move(reportIdsIn)), thresholds(std::move(thresholdsIn)), |
| fileName(std::to_string(std::hash<std::string>{}(*id))), |
| triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)), |
| messanger(ioc) |
| { |
| deleteIface = objServer->add_unique_interface( |
| path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) { |
| dbusIface.register_method("Delete", [this, &ioc, &triggerManager] { |
| if (persistent) |
| { |
| triggerStorage.remove(fileName); |
| } |
| messanger.send(messages::TriggerPresenceChangedInd{ |
| messages::Presence::Removed, *id, {}}); |
| boost::asio::post(ioc, [this, &triggerManager] { |
| triggerManager.removeTrigger(this); |
| }); |
| }); |
| }); |
| |
| triggerIface = objServer->add_unique_interface( |
| path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) { |
| persistent = storeConfiguration(); |
| dbusIface.register_property_rw( |
| "Persistent", persistent, |
| sdbusplus::vtable::property_::emits_change, |
| [this](bool newVal, const auto&) { |
| if (newVal == persistent) |
| { |
| return 1; |
| } |
| if (newVal) |
| { |
| persistent = storeConfiguration(); |
| } |
| else |
| { |
| triggerStorage.remove(fileName); |
| persistent = false; |
| } |
| return 1; |
| }, [this](const auto&) { return persistent; }); |
| |
| dbusIface.register_property_rw( |
| "Thresholds", TriggerThresholdParams{}, |
| sdbusplus::vtable::property_::emits_change, |
| [this, &triggerFactory](auto newVal, auto& oldVal) { |
| auto newThresholdParams = |
| std::visit(utils::ToLabeledThresholdParamConversion(), newVal); |
| TriggerManager::verifyThresholdParams(newThresholdParams); |
| triggerFactory.updateThresholds(thresholds, *id, triggerActions, |
| reportIds, sensors, |
| newThresholdParams); |
| oldVal = std::move(newVal); |
| return 1; |
| }, [this](const auto&) { |
| return fromLabeledThresholdParam(getLabeledThresholds()); |
| }); |
| |
| dbusIface.register_property_rw( |
| "Sensors", SensorsInfo{}, |
| sdbusplus::vtable::property_::emits_change, |
| [this, &triggerFactory](auto newVal, auto& oldVal) { |
| auto labeledSensorInfo = |
| triggerFactory.getLabeledSensorsInfo(newVal); |
| triggerFactory.updateSensors(sensors, labeledSensorInfo); |
| for (const auto& threshold : thresholds) |
| { |
| threshold->updateSensors(sensors); |
| } |
| oldVal = std::move(newVal); |
| return 1; |
| }, [this](const auto&) { |
| return utils::fromLabeledSensorsInfo(getLabeledSensorInfo()); |
| }); |
| |
| dbusIface.register_property_rw( |
| "Reports", std::vector<sdbusplus::message::object_path>(), |
| sdbusplus::vtable::property_::emits_change, |
| [this](auto newVal, auto& oldVal) { |
| auto newReportIds = utils::transform<std::vector>( |
| newVal, |
| [](const auto& path) { return utils::reportPathToId(path); }); |
| TriggerManager::verifyReportIds(newReportIds); |
| *reportIds = newReportIds; |
| messanger.send(messages::TriggerPresenceChangedInd{ |
| messages::Presence::Exist, *id, *reportIds}); |
| oldVal = std::move(newVal); |
| return 1; |
| }, [this](const auto&) { |
| return utils::transform<std::vector>(*reportIds, |
| [](const auto& id) { |
| return utils::pathAppend(utils::constants::reportDirPath, id); |
| }); |
| }); |
| |
| dbusIface.register_property_r( |
| "Discrete", isDiscreate(), sdbusplus::vtable::property_::const_, |
| [this](const auto& x) { return isDiscreate(); }); |
| |
| dbusIface.register_property_rw( |
| "Name", name, sdbusplus::vtable::property_::emits_change, |
| [this](auto newVal, auto& oldVal) { |
| if (newVal.length() > utils::constants::maxIdNameLength) |
| { |
| throw errors::InvalidArgument("Name", "Name is too long."); |
| } |
| name = oldVal = newVal; |
| return 1; |
| }, [this](const auto&) { return name; }); |
| |
| dbusIface.register_property_r( |
| "TriggerActions", std::vector<std::string>(), |
| sdbusplus::vtable::property_::const_, [this](const auto&) { |
| return utils::transform(triggerActions, [](const auto& action) { |
| return actionToString(action); |
| }); |
| }); |
| }); |
| |
| for (const auto& threshold : thresholds) |
| { |
| threshold->initialize(); |
| } |
| |
| messanger.on_receive<messages::CollectTriggerIdReq>( |
| [this](const auto& msg) { |
| if (utils::contains(*reportIds, msg.reportId)) |
| { |
| messanger.send(messages::CollectTriggerIdResp{*id}); |
| } |
| }); |
| |
| messanger.send(messages::TriggerPresenceChangedInd{ |
| messages::Presence::Exist, *id, *reportIds}); |
| } |
| |
| bool Trigger::storeConfiguration() const |
| { |
| try |
| { |
| nlohmann::json data; |
| |
| auto labeledThresholdParams = |
| std::visit(utils::ToLabeledThresholdParamConversion(), |
| fromLabeledThresholdParam(getLabeledThresholds())); |
| |
| data["Version"] = triggerVersion; |
| data["Id"] = *id; |
| data["Name"] = name; |
| data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index(); |
| data["TriggerActions"] = utils::transform( |
| triggerActions, |
| [](const auto& action) { return actionToString(action); }); |
| data["ThresholdParams"] = |
| utils::labeledThresholdParamsToJson(labeledThresholdParams); |
| data["ReportIds"] = *reportIds; |
| data["Sensors"] = getLabeledSensorInfo(); |
| |
| triggerStorage.store(fileName, data); |
| } |
| catch (const std::exception& e) |
| { |
| phosphor::logging::log<phosphor::logging::level::ERR>( |
| "Failed to store a trigger in storage", |
| phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); |
| return false; |
| } |
| return true; |
| } |
| |
| std::vector<LabeledSensorInfo> Trigger::getLabeledSensorInfo() const |
| { |
| return utils::transform(sensors, [](const auto& sensor) { |
| return sensor->getLabeledSensorInfo(); |
| }); |
| } |
| |
| std::vector<LabeledThresholdParam> Trigger::getLabeledThresholds() const |
| { |
| return utils::transform(thresholds, [](const auto& threshold) { |
| return threshold->getThresholdParam(); |
| }); |
| } |
| |
| bool Trigger::isDiscreate() const |
| { |
| const auto labeledThresholds = getLabeledThresholds(); |
| |
| return utils::isFirstElementOfType<std::monostate>(labeledThresholds) || |
| utils::isFirstElementOfType<discrete::LabeledThresholdParam>( |
| labeledThresholds); |
| } |