xref: /openbmc/dbus-sensors/src/leakdetector/LeakGPIODetector.cpp (revision 15dde8641baa1cb902d17f9857effb081e384944)
1 #include "LeakGPIODetector.hpp"
2 
3 #include "LeakEvents.hpp"
4 #include "SystemdInterface.hpp"
5 
6 #include <sdbusplus/async.hpp>
7 #include <sdbusplus/message/native_types.hpp>
8 
9 #include <array>
10 #include <functional>
11 #include <string>
12 #include <string_view>
13 #include <utility>
14 
15 namespace leak
16 {
17 
18 namespace config
19 {
20 
21 /** @brief Leak level to systemd target service map */
22 static constexpr std::array<std::pair<config::DetectorLevel, std::string_view>,
23                             2>
24     leakActionTargets = {{{config::DetectorLevel::warning,
25                            "xyz.openbmc_project.leakdetector.warning@"},
26                           {config::DetectorLevel::critical,
27                            "xyz.openbmc_project.leakdetector.critical@"}}};
28 
29 } // namespace config
30 
getObjectPath(const std::string & detectorName)31 static auto getObjectPath(const std::string& detectorName)
32     -> sdbusplus::message::object_path
33 {
34     return (
35         sdbusplus::message::object_path(DetectorIntf::namespace_path::value) /
36         DetectorIntf::namespace_path::detector / detectorName);
37 }
38 
GPIODetector(sdbusplus::async::context & ctx,Events & leakEvents,const config::DetectorConfig & config)39 GPIODetector::GPIODetector(sdbusplus::async::context& ctx, Events& leakEvents,
40                            const config::DetectorConfig& config) :
41     DetectorIntf(ctx, getObjectPath(config.name).str.c_str()), ctx(ctx),
42     leakEvents(leakEvents), config(config),
43     gpioInterface(ctx, config.name, config.pinName,
44                   (config.polarity == config::PinPolarity::activeLow),
45                   std::bind_front(&GPIODetector::updateGPIOStateAsync, this))
46 {
47     pretty_name<false>(config.name);
48     type<false>(config.type);
49 
50     ctx.spawn(gpioInterface.start());
51 
52     debug("Created leak detector {NAME}", "NAME", config.name);
53 }
54 
updateGPIOStateAsync(bool gpioState)55 auto GPIODetector::updateGPIOStateAsync(bool gpioState)
56     -> sdbusplus::async::task<>
57 {
58     auto newState = gpioState ? DetectorIntf::DetectorState::Abnormal
59                               : DetectorIntf::DetectorState::Normal;
60 
61     debug("Updating detector {DETECTOR} state to {STATE}", "DETECTOR",
62           config.name, "STATE", newState);
63 
64     if (newState != state_)
65     {
66         state(newState);
67 
68         co_await leakEvents.generateLeakEvent(getObjectPath(config.name),
69                                               state_, config.level);
70         if (state_ != DetectorIntf::DetectorState::Normal)
71         {
72             for (const auto& [level, serviceSuffix] : config::leakActionTargets)
73             {
74                 if (config.level == level)
75                 {
76                     auto target = std::string(serviceSuffix) + config.name +
77                                   ".service";
78                     debug("Starting systemd target {TARGET}", "TARGET", target);
79                     co_await systemd::SystemdInterface::startUnit(ctx, target);
80                     break;
81                 }
82             }
83         }
84     }
85 
86     co_return;
87 }
88 
89 } // namespace leak
90