blob: 4a7b4ff7d5aa2ce24d089b01629d0bc15178f3a3 [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áš Pecka26b38212024-01-16 17:23:31 +010027struct SideLoadedAlarm {
28 std::string alarmTypeId;
29 std::string resource;
30 std::string severity;
31 std::string text;
32
33 auto operator<=>(const SideLoadedAlarm&) const = default;
34};
35
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020036struct HardwareInfo {
37 DataTree dataTree;
38 std::map<std::string, State> updatedTresholdCrossing;
Tomáš Peckac0991ce2023-12-20 15:46:03 +010039 std::set<std::string> activeSensors;
Tomáš Pecka26b38212024-01-16 17:23:31 +010040 std::set<SideLoadedAlarm> sideLoadedAlarms;
Tomáš Peckac0991ce2023-12-20 15:46:03 +010041};
42
43struct SensorPollData {
44 DataTree data;
45 ThresholdsBySensorPath thresholds;
Tomáš Pecka26b38212024-01-16 17:23:31 +010046 std::set<SideLoadedAlarm> sideLoadedAlarms;
Tomáš Peckac0991ce2023-12-20 15:46:03 +010047 void merge(SensorPollData&& other);
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020048};
49
Tomáš Pecka339bc672020-11-11 15:59:03 +010050/**
51 * @brief Readout of hardware-state related data according to RFC 8348 (App. A)
52 *
53 * IETFHardware implements readout of various hardware component data and provides them as a mapping
54 * nodePath -> value, where nodePath is an XPath conforming to ietf-hardware-state module (RFC 8348, App. A).
55 *
56 * The class is designed to be modular. IETFHardware does not do much, its only capabilities are:
57 * - Register data readers responsible for readout of data for individual hardware, and
58 * - ask registered data readers to provide the data.
59 *
60 * The data readers (IETFHardware::DataReader) are simple functors with signature DataTree() (i.e., std::map<std::string, std::string>())
61 * returning parts of the tree in the form described above (i.e., mapping nodePath -> value).
62 *
63 * The IETFHardware is *not aware* of Sysrepo.
64 * However, the data readers are aware of the tree structure of the YANG module ietf-hardware-state.
65 * That is because they also create the specified parts of the resulting tree.
66 *
67 * @see IETFHardware::DataReader The data reader.
68 * @see velia::ietf_hardware::data_reader Namespace containing several predefined components.
69 */
70class IETFHardware {
71
72public:
73 /** @brief The component */
Tomáš Peckac0991ce2023-12-20 15:46:03 +010074 using DataReader = std::function<SensorPollData()>;
Tomáš Pecka339bc672020-11-11 15:59:03 +010075
76 IETFHardware();
77 ~IETFHardware();
Tomáš Pecka4886db22023-05-10 10:46:15 +020078
Tomáš Peckac0991ce2023-12-20 15:46:03 +010079 void registerDataReader(const DataReader& callable);
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020080 HardwareInfo process();
Tomáš Pecka339bc672020-11-11 15:59:03 +010081
82private:
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020083 velia::Log m_log;
84
Tomáš Pecka339bc672020-11-11 15:59:03 +010085 /** @brief registered components for individual modules */
86 std::vector<DataReader> m_callbacks;
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020087
88 /** @brief watchers for any sensor value xPath reported by data readers */
89 std::map<std::string, Watcher<int64_t>> m_thresholdsWatchers;
Tomáš Pecka339bc672020-11-11 15:59:03 +010090};
91
92/**
93 * This namespace contains several predefined data readers for IETFHardware.
94 * They are implemented as functors and fulfill the required interface -- std::function<DataTree()>
95 *
96 * 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.
97 * When IETFHardwareState fetches the data from the data reader, an operator() is invoked.
98 * The dynamic data are fetched by IETFHardware class by the use of the operator().
99 * The result of call to operator() will be merged into the static data and returned to caller (IETFHardwareState).
100 *
101 * Note that a data reader can return any number of nodes and even multiple compoments.
102 * For example, Fans data reader will create multiple components in the tree, one for each fan.
103 */
104namespace data_reader {
105
106struct DataReader {
107 /** @brief name of the module component in the tree, e.g. ne:fans:fan1 */
108 std::string m_componentName;
109
110 /** @brief name of the parent module */
111 std::optional<std::string> m_parent;
112
113 /** @brief static hw-state related data */
114 DataTree m_staticData;
115
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100116 velia::Log m_log;
117
Tomáš Pecka339bc672020-11-11 15:59:03 +0100118 DataReader(std::string propertyPrefix, std::optional<std::string> parent);
119};
120
121/** @brief Manages any component composing of static data only. The static data are provided as a DataTree in construction time. */
122struct StaticData : private DataReader {
123 StaticData(std::string propertyPrefix, std::optional<std::string> parent, DataTree tree);
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100124 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100125};
126
127/** @brief Manages fans component. Data is provided by a sysfs::HWMon object. */
128struct Fans : private DataReader {
129private:
130 std::shared_ptr<sysfs::HWMon> m_hwmon;
131 unsigned m_fanChannelsCount;
Tomáš Pecka4886db22023-05-10 10:46:15 +0200132 Thresholds<int64_t> m_thresholds;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100133
134public:
Tomáš Pecka4886db22023-05-10 10:46:15 +0200135 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 +0100136 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100137};
138
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200139enum class SensorType {
Tomáš Pecka77e09c22023-05-04 20:39:57 +0200140 Temperature,
141 Current,
142 VoltageDC,
143 VoltageAC,
144 Power
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100145
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200146};
147
148/** @brief Manages a single value from sysfs, data is provided by a sysfs::HWMon object. */
Tomáš Pecka77e09c22023-05-04 20:39:57 +0200149template <SensorType TYPE>
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200150struct SysfsValue : private DataReader {
Tomáš Pecka339bc672020-11-11 15:59:03 +0100151private:
152 std::shared_ptr<sysfs::HWMon> m_hwmon;
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200153 std::string m_sysfsFile;
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 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 +0100158 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100159};
160
161/** @brief Manages a single eMMC block device hardware component. Data is provided by a sysfs::EMMC object. */
162struct EMMC : private DataReader {
163private:
164 std::shared_ptr<sysfs::EMMC> m_emmc;
Tomáš Pecka4886db22023-05-10 10:46:15 +0200165 Thresholds<int64_t> m_thresholds;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100166
167public:
Tomáš Pecka4886db22023-05-10 10:46:15 +0200168 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 +0100169 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100170};
Tomáš Pecka2a4c9f62023-03-26 10:54:57 +0200171
Tomáš Pecka339bc672020-11-11 15:59:03 +0100172}
173}