1 #pragma once 2 3 #include "types.hpp" 4 #include <phosphor-logging/log.hpp> 5 6 namespace phosphor 7 { 8 namespace fan 9 { 10 namespace control 11 { 12 class Zone; 13 14 using namespace phosphor::logging; 15 16 /** 17 * @brief Create a handler function object 18 * 19 * @param[in] handler - The handler being created 20 * 21 * @return - The created handler function object 22 */ 23 template <typename T> 24 auto make_handler(T&& handler) 25 { 26 return Handler(std::forward<T>(handler)); 27 } 28 29 /** 30 * @brief Create an action function object 31 * 32 * @param[in] action - The action being created 33 * 34 * @return - The created action function object 35 */ 36 template <typename T> 37 auto make_action(T&& action) 38 { 39 return Action(std::forward<T>(action)); 40 } 41 42 /** 43 * @struct Property Changed 44 * @brief A match filter functor for Dbus property value changed signals 45 * 46 * @tparam T - The type of the property value 47 * @tparam U - The type of the handler 48 */ 49 template <typename T, typename U> 50 struct PropertyChanged 51 { 52 PropertyChanged() = delete; 53 ~PropertyChanged() = default; 54 PropertyChanged(const PropertyChanged&) = default; 55 PropertyChanged& operator=(const PropertyChanged&) = default; 56 PropertyChanged(PropertyChanged&&) = default; 57 PropertyChanged& operator=(PropertyChanged&&) = default; 58 PropertyChanged(const char* iface, 59 const char* property, 60 U&& handler) : 61 _iface(iface), 62 _property(property), 63 _handler(std::forward<U>(handler)) { } 64 65 /** @brief Run signal handler function 66 * 67 * Extract the property from the PropertiesChanged 68 * message and run the handler function. 69 */ 70 void operator()(sdbusplus::bus::bus&, 71 sdbusplus::message::message& msg, 72 Zone& zone) const 73 { 74 std::map<std::string, sdbusplus::message::variant<T>> properties; 75 const char* iface = nullptr; 76 77 msg.read(iface); 78 if (!iface || strcmp(iface, _iface)) 79 { 80 return; 81 } 82 83 msg.read(properties); 84 auto it = properties.find(_property); 85 if (it == properties.cend()) 86 { 87 log<level::ERR>("Unable to find property on interface", 88 entry("PROPERTY=%s", _property), 89 entry("INTERFACE=%s", _iface)); 90 return; 91 } 92 93 _handler(zone, std::forward<T>(it->second.template get<T>())); 94 } 95 96 private: 97 const char* _iface; 98 const char* _property; 99 U _handler; 100 }; 101 102 /** 103 * @brief Used to process a Dbus property changed signal event 104 * 105 * @param[in] iface - Sensor value interface 106 * @param[in] property - Sensor value property 107 * @param[in] handler - Handler function to perform 108 * 109 * @tparam T - The type of the property 110 * @tparam U - The type of the handler 111 */ 112 template <typename T, typename U> 113 auto propertySignal(const char* iface, 114 const char* property, 115 U&& handler) 116 { 117 return PropertyChanged<T, U>(iface, property, std::forward<U>(handler)); 118 } 119 120 } // namespace control 121 } // namespace fan 122 } // namespace phosphor 123