blob: f097e9b2394b6aadea8ce5a95bacd9bd7a77d333 [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;
Tomáš Pecka61212852024-09-30 14:36:50 +020038 std::map<std::string, ThresholdUpdate<int64_t>> 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/**
Jan Kundrátc98da382024-10-08 16:47:04 +020093 * @brief Read a range of bytes from an EEPROM in hex
94 */
95std::optional<std::string> hexEEPROM(const std::string& sysfsPrefix, const uint8_t bus, const uint8_t address, const uint32_t totalSize, const uint32_t offset, const uint32_t length);
96
97/**
Tomáš Pecka339bc672020-11-11 15:59:03 +010098 * This namespace contains several predefined data readers for IETFHardware.
99 * They are implemented as functors and fulfill the required interface -- std::function<DataTree()>
100 *
101 * 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.
102 * When IETFHardwareState fetches the data from the data reader, an operator() is invoked.
103 * The dynamic data are fetched by IETFHardware class by the use of the operator().
104 * The result of call to operator() will be merged into the static data and returned to caller (IETFHardwareState).
105 *
106 * Note that a data reader can return any number of nodes and even multiple compoments.
107 * For example, Fans data reader will create multiple components in the tree, one for each fan.
108 */
109namespace data_reader {
110
111struct DataReader {
112 /** @brief name of the module component in the tree, e.g. ne:fans:fan1 */
113 std::string m_componentName;
114
115 /** @brief name of the parent module */
116 std::optional<std::string> m_parent;
117
118 /** @brief static hw-state related data */
119 DataTree m_staticData;
120
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100121 velia::Log m_log;
122
Tomáš Pecka339bc672020-11-11 15:59:03 +0100123 DataReader(std::string propertyPrefix, std::optional<std::string> parent);
124};
125
126/** @brief Manages any component composing of static data only. The static data are provided as a DataTree in construction time. */
127struct StaticData : private DataReader {
128 StaticData(std::string propertyPrefix, std::optional<std::string> parent, DataTree tree);
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100129 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100130};
131
132/** @brief Manages fans component. Data is provided by a sysfs::HWMon object. */
133struct Fans : private DataReader {
134private:
135 std::shared_ptr<sysfs::HWMon> m_hwmon;
136 unsigned m_fanChannelsCount;
Tomáš Pecka4886db22023-05-10 10:46:15 +0200137 Thresholds<int64_t> m_thresholds;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100138
139public:
Tomáš Pecka4886db22023-05-10 10:46:15 +0200140 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 +0100141 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100142};
143
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200144enum class SensorType {
Tomáš Pecka77e09c22023-05-04 20:39:57 +0200145 Temperature,
146 Current,
147 VoltageDC,
148 VoltageAC,
149 Power
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100150
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200151};
152
153/** @brief Manages a single value from sysfs, data is provided by a sysfs::HWMon object. */
Tomáš Pecka77e09c22023-05-04 20:39:57 +0200154template <SensorType TYPE>
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200155struct SysfsValue : private DataReader {
Tomáš Pecka339bc672020-11-11 15:59:03 +0100156private:
157 std::shared_ptr<sysfs::HWMon> m_hwmon;
Václav Kubernát6c17d0a2021-03-29 04:55:31 +0200158 std::string m_sysfsFile;
Tomáš Pecka4886db22023-05-10 10:46:15 +0200159 Thresholds<int64_t> m_thresholds;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100160
161public:
Tomáš Pecka4886db22023-05-10 10:46:15 +0200162 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 +0100163 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100164};
165
166/** @brief Manages a single eMMC block device hardware component. Data is provided by a sysfs::EMMC object. */
167struct EMMC : private DataReader {
168private:
169 std::shared_ptr<sysfs::EMMC> m_emmc;
Tomáš Pecka4886db22023-05-10 10:46:15 +0200170 Thresholds<int64_t> m_thresholds;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100171
172public:
Tomáš Pecka4886db22023-05-10 10:46:15 +0200173 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 +0100174 SensorPollData operator()() const;
Tomáš Pecka339bc672020-11-11 15:59:03 +0100175};
Tomáš Pecka2a4c9f62023-03-26 10:54:57 +0200176
Jan Kundrátc98da382024-10-08 16:47:04 +0200177/** brief Static data and a serial number read from the trailing part of the EEPROM */
178struct EepromWithUid : private DataReader {
179 EepromWithUid(std::string componentName, std::optional<std::string> parent, const std::string& sysfsPrefix, const uint8_t bus, const uint8_t address, const uint32_t totalSize, const uint32_t offset, const uint32_t length);
180 SensorPollData operator()() const;
181};
182
Tomáš Pecka339bc672020-11-11 15:59:03 +0100183}
184}