blob: a5044daca4c4808c2ea1d43e4289092d7744cb7d [file] [log] [blame]
#pragma once
#include "types.hpp"
#include <phosphor-logging/log.hpp>
namespace phosphor
{
namespace fan
{
namespace control
{
class Zone;
using namespace phosphor::logging;
/**
* @brief Create a handler function object
*
* @param[in] handler - The handler being created
*
* @return - The created handler function object
*/
template <typename T>
auto make_handler(T&& handler)
{
return Handler(std::forward<T>(handler));
}
/**
* @brief Create an action function object
*
* @param[in] action - The action being created
*
* @return - The created action function object
*/
template <typename T>
auto make_action(T&& action)
{
return Action(std::forward<T>(action));
}
/**
* @struct Property Changed
* @brief A match filter functor for Dbus property value changed signals
*
* @tparam T - The type of the property value
* @tparam U - The type of the handler
*/
template <typename T, typename U>
struct PropertyChanged
{
PropertyChanged() = delete;
~PropertyChanged() = default;
PropertyChanged(const PropertyChanged&) = default;
PropertyChanged& operator=(const PropertyChanged&) = default;
PropertyChanged(PropertyChanged&&) = default;
PropertyChanged& operator=(PropertyChanged&&) = default;
PropertyChanged(const char* iface,
const char* property,
U&& handler) :
_iface(iface),
_property(property),
_handler(std::forward<U>(handler)) { }
/** @brief Run signal handler function
*
* Extract the property from the PropertiesChanged
* message and run the handler function.
*/
void operator()(sdbusplus::bus::bus&,
sdbusplus::message::message& msg,
Zone& zone) const
{
std::map<std::string, sdbusplus::message::variant<T>> properties;
const char* iface = nullptr;
msg.read(iface);
if (!iface || strcmp(iface, _iface))
{
return;
}
msg.read(properties);
auto it = properties.find(_property);
if (it == properties.cend())
{
log<level::ERR>("Unable to find property on interface",
entry("PROPERTY=%s", _property),
entry("INTERFACE=%s", _iface));
return;
}
_handler(zone, std::forward<T>(it->second.template get<T>()));
}
private:
const char* _iface;
const char* _property;
U _handler;
};
/**
* @brief Used to process a Dbus property changed signal event
*
* @param[in] iface - Sensor value interface
* @param[in] property - Sensor value property
* @param[in] handler - Handler function to perform
*
* @tparam T - The type of the property
* @tparam U - The type of the handler
*/
template <typename T, typename U>
auto propertySignal(const char* iface,
const char* property,
U&& handler)
{
return PropertyChanged<T, U>(iface, property, std::forward<U>(handler));
}
/**
* @struct Interface Added
* @brief A match filter functor for Dbus interface added signals
*
* @tparam T - The type of the property value
* @tparam U - The type of the handler
*/
template <typename T, typename U>
struct InterfaceAdded
{
InterfaceAdded() = delete;
~InterfaceAdded() = default;
InterfaceAdded(const InterfaceAdded&) = default;
InterfaceAdded& operator=(const InterfaceAdded&) = default;
InterfaceAdded(InterfaceAdded&&) = default;
InterfaceAdded& operator=(InterfaceAdded&&) = default;
InterfaceAdded(const char* path,
const char* iface,
const char* property,
U&& handler) :
_path(path),
_iface(iface),
_property(property),
_handler(std::forward<U>(handler)) { }
/** @brief Run signal handler function
*
* Extract the property from the InterfacesAdded
* message and run the handler function.
*/
void operator()(sdbusplus::bus::bus&,
sdbusplus::message::message& msg,
Zone& zone) const
{
std::map<std::string,
std::map<std::string,
sdbusplus::message::variant<T>>> intfProp;
sdbusplus::message::object_path op;
msg.read(op);
auto objPath = static_cast<const std::string&>(op).c_str();
if (!objPath || strcmp(objPath, _path))
{
// Object path does not match this handler's path
return;
}
msg.read(intfProp);
auto itIntf = intfProp.find(_iface);
if (itIntf == intfProp.cend())
{
// Interface not found on this handler's path
return;
}
auto itProp = itIntf->second.find(_property);
if (itProp == itIntf->second.cend())
{
// Property not found on this handler's path
return;
}
_handler(zone, std::forward<T>(itProp->second.template get<T>()));
}
private:
const char* _path;
const char* _iface;
const char* _property;
U _handler;
};
/**
* @brief Used to process a Dbus interface added signal event
*
* @param[in] path - Object path
* @param[in] iface - Object interface
* @param[in] property - Object property
* @param[in] handler - Handler function to perform
*
* @tparam T - The type of the property
* @tparam U - The type of the handler
*/
template <typename T, typename U>
auto objectSignal(const char* path,
const char* iface,
const char* property,
U&& handler)
{
return InterfaceAdded<T, U>(path,
iface,
property,
std::forward<U>(handler));
}
} // namespace control
} // namespace fan
} // namespace phosphor