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