blob: d807fe8f9308d376c65c147550482b18e0dea254 [file] [log] [blame]
/*
* Copyright (C) 2016-2020 CESNET, https://photonics.cesnet.cz/
*
* Written by Tomáš Pecka <tomas.pecka@fit.cvut.cz>
*
*/
#pragma once
#include <functional>
#include <map>
#include <optional>
#include <utility>
#include "ietf-hardware/sysfs/EMMC.h"
#include "ietf-hardware/sysfs/HWMon.h"
#include "utils/log-fwd.h"
using namespace std::literals;
namespace velia::ietf_hardware {
using DataTree = std::map<std::string, std::string>;
/**
* @brief Readout of hardware-state related data according to RFC 8348 (App. A)
*
* IETFHardware implements readout of various hardware component data and provides them as a mapping
* nodePath -> value, where nodePath is an XPath conforming to ietf-hardware-state module (RFC 8348, App. A).
*
* The class is designed to be modular. IETFHardware does not do much, its only capabilities are:
* - Register data readers responsible for readout of data for individual hardware, and
* - ask registered data readers to provide the data.
*
* The data readers (IETFHardware::DataReader) are simple functors with signature DataTree() (i.e., std::map<std::string, std::string>())
* returning parts of the tree in the form described above (i.e., mapping nodePath -> value).
*
* The IETFHardware is *not aware* of Sysrepo.
* However, the data readers are aware of the tree structure of the YANG module ietf-hardware-state.
* That is because they also create the specified parts of the resulting tree.
*
* @see IETFHardware::DataReader The data reader.
* @see velia::ietf_hardware::data_reader Namespace containing several predefined components.
*/
class IETFHardware {
public:
/** @brief The component */
using DataReader = std::function<DataTree()>;
IETFHardware();
~IETFHardware();
void registerDataReader(const DataReader& callable);
DataTree process();
private:
/** @brief registered components for individual modules */
std::vector<DataReader> m_callbacks;
};
/**
* This namespace contains several predefined data readers for IETFHardware.
* They are implemented as functors and fulfill the required interface -- std::function<DataTree()>
*
* The philosophy here is to initialize Component::m_staticData DataTree when constructing the object so the tree does not have to be completely reconstructed every time.
* When IETFHardwareState fetches the data from the data reader, an operator() is invoked.
* The dynamic data are fetched by IETFHardware class by the use of the operator().
* The result of call to operator() will be merged into the static data and returned to caller (IETFHardwareState).
*
* Note that a data reader can return any number of nodes and even multiple compoments.
* For example, Fans data reader will create multiple components in the tree, one for each fan.
*/
namespace data_reader {
struct DataReader {
/** @brief name of the module component in the tree, e.g. ne:fans:fan1 */
std::string m_componentName;
/** @brief name of the parent module */
std::optional<std::string> m_parent;
/** @brief static hw-state related data */
DataTree m_staticData;
DataReader(std::string propertyPrefix, std::optional<std::string> parent);
};
/** @brief Manages any component composing of static data only. The static data are provided as a DataTree in construction time. */
struct StaticData : private DataReader {
StaticData(std::string propertyPrefix, std::optional<std::string> parent, DataTree tree);
DataTree operator()() const;
};
/** @brief Manages fans component. Data is provided by a sysfs::HWMon object. */
struct Fans : private DataReader {
private:
std::shared_ptr<sysfs::HWMon> m_hwmon;
unsigned m_fanChannelsCount;
public:
Fans(std::string propertyPrefix, std::optional<std::string> parent, std::shared_ptr<sysfs::HWMon> hwmon, unsigned fanChannelsCount);
DataTree operator()() const;
};
enum class SensorType {
Temperature,
Current,
VoltageDC,
VoltageAC,
Power
};
/** @brief Manages a single value from sysfs, data is provided by a sysfs::HWMon object. */
template <SensorType TYPE>
struct SysfsValue : private DataReader {
private:
std::shared_ptr<sysfs::HWMon> m_hwmon;
std::string m_sysfsFile;
public:
SysfsValue(std::string propertyPrefix, std::optional<std::string> parent, std::shared_ptr<sysfs::HWMon> hwmon, int sysfsChannelNr);
DataTree operator()() const;
};
/** @brief Manages a single eMMC block device hardware component. Data is provided by a sysfs::EMMC object. */
struct EMMC : private DataReader {
private:
std::shared_ptr<sysfs::EMMC> m_emmc;
public:
EMMC(std::string propertyPrefix, std::optional<std::string> parent, std::shared_ptr<sysfs::EMMC> emmc);
DataTree operator()() const;
};
/** @brief Use this when you want to wrap reading several properties in one go and still use it as a single DataReader instance (e.g. in on thread)
*/
struct Group {
private:
std::vector<IETFHardware::DataReader> m_readers;
public:
void registerDataReader(const IETFHardware::DataReader& callable);
DataTree operator()() const;
};
}
}