blob: d256855f6df47f1406476e4ac6b09a2c13e681a6 [file] [log] [blame]
Tomáš Pecka339bc672020-11-11 15:59:03 +01001/*
2 * Copyright (C) 2016-2020 CESNET, https://photonics.cesnet.cz/
3 *
4 * Written by Tomáš Pecka <tomas.pecka@fit.cvut.cz>
5 *
6 */
7
8#pragma once
9
10#include <functional>
11#include <map>
Jan Kundrát1c3b8812021-05-17 13:06:03 +020012#include <optional>
Tomáš Peckac0991ce2023-12-20 15:46:03 +010013#include <set>
Tomáš Pecka339bc672020-11-11 15:59:03 +010014#include <utility>
15#include "ietf-hardware/sysfs/EMMC.h"
16#include "ietf-hardware/sysfs/HWMon.h"
Tomáš Pecka4886db22023-05-10 10:46:15 +020017#include "ietf-hardware/thresholds.h"
Tomáš Pecka339bc672020-11-11 15:59:03 +010018#include "utils/log-fwd.h"
19
20using namespace std::literals;
21
22namespace velia::ietf_hardware {
23
24using DataTree = std::map<std::string, std::string>;
Tomáš Pecka4886db22023-05-10 10:46:15 +020025using ThresholdsBySensorPath = std::map<std::string, Thresholds<int64_t>>;
Tomáš Pecka339bc672020-11-11 15:59:03 +010026
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020027struct HardwareInfo {
28 DataTree dataTree;
29 std::map<std::string, State> updatedTresholdCrossing;
Tomáš Peckac0991ce2023-12-20 15:46:03 +010030 std::set<std::string> activeSensors;
31};
32
33struct SensorPollData {
34 DataTree data;
35 ThresholdsBySensorPath thresholds;
36 void merge(SensorPollData&& other);
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020037};
38
Tomáš Pecka339bc672020-11-11 15:59:03 +010039/**
40 * @brief Readout of hardware-state related data according to RFC 8348 (App. A)
41 *
42 * IETFHardware implements readout of various hardware component data and provides them as a mapping
43 * nodePath -> value, where nodePath is an XPath conforming to ietf-hardware-state module (RFC 8348, App. A).
44 *
45 * The class is designed to be modular. IETFHardware does not do much, its only capabilities are:
46 * - Register data readers responsible for readout of data for individual hardware, and
47 * - ask registered data readers to provide the data.
48 *
49 * The data readers (IETFHardware::DataReader) are simple functors with signature DataTree() (i.e., std::map<std::string, std::string>())
50 * returning parts of the tree in the form described above (i.e., mapping nodePath -> value).
51 *
52 * The IETFHardware is *not aware* of Sysrepo.
53 * However, the data readers are aware of the tree structure of the YANG module ietf-hardware-state.
54 * That is because they also create the specified parts of the resulting tree.
55 *
56 * @see IETFHardware::DataReader The data reader.
57 * @see velia::ietf_hardware::data_reader Namespace containing several predefined components.
58 */
59class IETFHardware {
60
61public:
62 /** @brief The component */
Tomáš Peckac0991ce2023-12-20 15:46:03 +010063 using DataReader = std::function<SensorPollData()>;
Tomáš Pecka339bc672020-11-11 15:59:03 +010064
65 IETFHardware();
66 ~IETFHardware();
Tomáš Pecka4886db22023-05-10 10:46:15 +020067
Tomáš Peckac0991ce2023-12-20 15:46:03 +010068 void registerDataReader(const DataReader& callable);
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020069 HardwareInfo process();
Tomáš Pecka339bc672020-11-11 15:59:03 +010070
71private:
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020072 velia::Log m_log;
73
Tomáš Pecka339bc672020-11-11 15:59:03 +010074 /** @brief registered components for individual modules */
75 std::vector<DataReader> m_callbacks;
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020076
77 /** @brief watchers for any sensor value xPath reported by data readers */
78 std::map<std::string, Watcher<int64_t>> m_thresholdsWatchers;
Tomáš Pecka339bc672020-11-11 15:59:03 +010079};
80
81/**
82 * This namespace contains several predefined data readers for IETFHardware.
83 * They are implemented as functors and fulfill the required interface -- std::function<DataTree()>
84 *
85 * 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.
86 * When IETFHardwareState fetches the data from the data reader, an operator() is invoked.
87 * The dynamic data are fetched by IETFHardware class by the use of the operator().
88 * The result of call to operator() will be merged into the static data and returned to caller (IETFHardwareState).
89 *
90 * Note that a data reader can return any number of nodes and even multiple compoments.
91 * For example, Fans data reader will create multiple components in the tree, one for each fan.
92 */
93namespace data_reader {
94
95struct DataReader {
96 /** @brief name of the module component in the tree, e.g. ne:fans:fan1 */
97 std::string m_componentName;
98
99 /** @brief name of the parent module */
100 std::optional<std::string> m_parent;
101
102 /** @brief static hw-state related data */
103 DataTree m_staticData;
104
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100105 velia::Log m_log;
106
Tomáš Pecka339bc672020-11-11 15:59:03 +0100107 DataReader(std::string propertyPrefix, std::optional<std::string> parent);
108};
109
110/** @brief Manages any component composing of static data only. The static data are provided as a DataTree in construction time. */
111struct StaticData : private DataReader {
112 StaticData(std::string propertyPrefix, std::optional<std::string> parent, DataTree tree);
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100113 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100114};
115
116/** @brief Manages fans component. Data is provided by a sysfs::HWMon object. */
117struct Fans : private DataReader {
118private:
119 std::shared_ptr<sysfs::HWMon> m_hwmon;
120 unsigned m_fanChannelsCount;
Tomáš Pecka4886db22023-05-10 10:46:15 +0200121 Thresholds<int64_t> m_thresholds;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100122
123public:
Tomáš Pecka4886db22023-05-10 10:46:15 +0200124 Fans(std::string propertyPrefix, std::optional<std::string> parent, std::shared_ptr<sysfs::HWMon> hwmon, unsigned fanChannelsCount, Thresholds<int64_t> thresholds = {});
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100125 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100126};
127
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200128enum class SensorType {
Tomáš Pecka77e09c22023-05-04 20:39:57 +0200129 Temperature,
130 Current,
131 VoltageDC,
132 VoltageAC,
133 Power
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100134
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200135};
136
137/** @brief Manages a single value from sysfs, data is provided by a sysfs::HWMon object. */
Tomáš Pecka77e09c22023-05-04 20:39:57 +0200138template <SensorType TYPE>
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200139struct SysfsValue : private DataReader {
Tomáš Pecka339bc672020-11-11 15:59:03 +0100140private:
141 std::shared_ptr<sysfs::HWMon> m_hwmon;
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200142 std::string m_sysfsFile;
Tomáš Pecka4886db22023-05-10 10:46:15 +0200143 Thresholds<int64_t> m_thresholds;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100144
145public:
Tomáš Pecka4886db22023-05-10 10:46:15 +0200146 SysfsValue(std::string propertyPrefix, std::optional<std::string> parent, std::shared_ptr<sysfs::HWMon> hwmon, int sysfsChannelNr, Thresholds<int64_t> thresholds = {});
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100147 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100148};
149
150/** @brief Manages a single eMMC block device hardware component. Data is provided by a sysfs::EMMC object. */
151struct EMMC : private DataReader {
152private:
153 std::shared_ptr<sysfs::EMMC> m_emmc;
Tomáš Pecka4886db22023-05-10 10:46:15 +0200154 Thresholds<int64_t> m_thresholds;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100155
156public:
Tomáš Pecka4886db22023-05-10 10:46:15 +0200157 EMMC(std::string propertyPrefix, std::optional<std::string> parent, std::shared_ptr<sysfs::EMMC> emmc, Thresholds<int64_t> thresholds = {});
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100158 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100159};
Tomáš Pecka2a4c9f62023-03-26 10:54:57 +0200160
Tomáš Pecka339bc672020-11-11 15:59:03 +0100161}
162}