xref: /openbmc/dbus-sensors/src/TachSensor.hpp (revision 201a1015)
1 #pragma once
2 
3 #include "Thresholds.hpp"
4 #include "sensor.hpp"
5 
6 #include <boost/asio/random_access_file.hpp>
7 #include <boost/container/flat_map.hpp>
8 #include <boost/container/flat_set.hpp>
9 #include <gpiod.hpp>
10 #include <phosphor-logging/lg2.hpp>
11 #include <sdbusplus/asio/object_server.hpp>
12 
13 #include <memory>
14 #include <optional>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 class PresenceSensor
20 {
21   public:
22     PresenceSensor(const std::string& gpioName, bool inverted,
23                    boost::asio::io_context& io, const std::string& name);
24     ~PresenceSensor();
25 
26     void monitorPresence();
27     void read();
28     bool getValue() const;
29 
30   private:
31     bool status = true;
32     gpiod::line gpioLine;
33     boost::asio::posix::stream_descriptor gpioFd;
34     std::string name;
35 };
36 
37 namespace redundancy
38 {
39 constexpr const char* full = "Full";
40 constexpr const char* degraded = "Degraded";
41 constexpr const char* failed = "Failed";
42 } // namespace redundancy
43 
44 class RedundancySensor
45 {
46   public:
47     RedundancySensor(size_t count, const std::vector<std::string>& children,
48                      sdbusplus::asio::object_server& objectServer,
49                      const std::string& sensorConfiguration);
50     ~RedundancySensor();
51 
52     void update(const std::string& name, bool failed);
53 
54   private:
55     size_t count;
56     std::string state = redundancy::full;
57     std::shared_ptr<sdbusplus::asio::dbus_interface> iface;
58     std::shared_ptr<sdbusplus::asio::dbus_interface> association;
59     sdbusplus::asio::object_server& objectServer;
60     boost::container::flat_map<std::string, bool> statuses;
61 };
62 
63 class TachSensor :
64     public Sensor,
65     public std::enable_shared_from_this<TachSensor>
66 {
67   public:
68     TachSensor(const std::string& path, const std::string& objectType,
69                sdbusplus::asio::object_server& objectServer,
70                std::shared_ptr<sdbusplus::asio::connection>& conn,
71                std::unique_ptr<PresenceSensor>&& presence,
72                std::optional<RedundancySensor>* redundancy,
73                boost::asio::io_context& io, const std::string& fanName,
74                std::vector<thresholds::Threshold>&& thresholds,
75                const std::string& sensorConfiguration,
76                const std::pair<double, double>& limits,
77                const PowerState& powerState,
78                const std::optional<std::string>& led);
79     ~TachSensor() override;
80     void setupRead();
81 
82   private:
83     // Ordering is important here; readBuf is first so that it's not destroyed
84     // while async operations from other member fields might still be using it.
85     std::array<char, 128> readBuf{};
86     sdbusplus::asio::object_server& objServer;
87     std::optional<RedundancySensor>* redundancy;
88     std::unique_ptr<PresenceSensor> presence;
89     std::shared_ptr<sdbusplus::asio::dbus_interface> itemIface;
90     std::shared_ptr<sdbusplus::asio::dbus_interface> itemAssoc;
91     boost::asio::random_access_file inputDev;
92     boost::asio::steady_timer waitTimer;
93     std::string path;
94     std::optional<std::string> led;
95     bool ledState = false;
96 
97     void handleResponse(const boost::system::error_code& err, size_t bytesRead);
98     void restartRead(size_t pollTime);
99     void checkThresholds() override;
100 };
101 
logFanInserted(const std::string & device)102 inline void logFanInserted(const std::string& device)
103 {
104     const auto* msg = "OpenBMC.0.1.FanInserted";
105     lg2::error("Fan Inserted", "REDFISH_MESSAGE_ID", msg,
106                "REDFISH_MESSAGE_ARGS", device);
107 }
108 
logFanRemoved(const std::string & device)109 inline void logFanRemoved(const std::string& device)
110 {
111     const auto* msg = "OpenBMC.0.1.FanRemoved";
112     lg2::error("Fan Removed", "REDFISH_MESSAGE_ID", msg, "REDFISH_MESSAGE_ARGS",
113                device);
114 }
115 
logFanRedundancyLost()116 inline void logFanRedundancyLost()
117 {
118     const auto* msg = "OpenBMC.0.1.FanRedundancyLost";
119     lg2::error("Fan Inserted", "REDFISH_MESSAGE_ID", msg);
120 }
121 
logFanRedundancyRestored()122 inline void logFanRedundancyRestored()
123 {
124     const auto* msg = "OpenBMC.0.1.FanRedundancyRegained";
125     lg2::error("Fan Removed", "REDFISH_MESSAGE_ID", msg);
126 }
127