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 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 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 116 inline void logFanRedundancyLost() 117 { 118 const auto* msg = "OpenBMC.0.1.FanRedundancyLost"; 119 lg2::error("Fan Inserted", "REDFISH_MESSAGE_ID", msg); 120 } 121 122 inline void logFanRedundancyRestored() 123 { 124 const auto* msg = "OpenBMC.0.1.FanRedundancyRegained"; 125 lg2::error("Fan Removed", "REDFISH_MESSAGE_ID", msg); 126 } 127