xref: /openbmc/phosphor-power/power-supply/record_manager.hpp (revision 48781aef031d0fcf7d947ceea1848b9dd1047485)
1d7abf367SMatt Spinler #pragma once
2d7abf367SMatt Spinler 
3c60b9751SAndrew Geissler #include <cstdint>
4d7abf367SMatt Spinler #include <deque>
501779a6aSAndrew Geissler #include <stdexcept>
6d7abf367SMatt Spinler #include <tuple>
7d7abf367SMatt Spinler #include <vector>
8d7abf367SMatt Spinler 
9ab093328SLei YU namespace phosphor
10d7abf367SMatt Spinler {
11d7abf367SMatt Spinler namespace power
12d7abf367SMatt Spinler {
13d7abf367SMatt Spinler namespace history
14d7abf367SMatt Spinler {
15d7abf367SMatt Spinler 
16d7abf367SMatt Spinler static constexpr auto recIDPos = 0;
17d7abf367SMatt Spinler static constexpr auto recTimePos = 1;
18d7abf367SMatt Spinler static constexpr auto recAvgPos = 2;
19d7abf367SMatt Spinler static constexpr auto recMaxPos = 3;
20d7abf367SMatt Spinler using Record = std::tuple<size_t, int64_t, int64_t, int64_t>;
21d7abf367SMatt Spinler 
22d7abf367SMatt Spinler /**
2328fa1b6bSMatt Spinler  * @class InvalidRecordException
2428fa1b6bSMatt Spinler  *
2528fa1b6bSMatt Spinler  * The exception that is thrown when a raw history record
2628fa1b6bSMatt Spinler  * cannot be parsed.
2728fa1b6bSMatt Spinler  */
2828fa1b6bSMatt Spinler class InvalidRecordException : public std::runtime_error
2928fa1b6bSMatt Spinler {
3028fa1b6bSMatt Spinler   public:
InvalidRecordException()31*48781aefSPatrick Williams     InvalidRecordException() : std::runtime_error("Invalid history record") {}
3228fa1b6bSMatt Spinler };
3328fa1b6bSMatt Spinler 
3428fa1b6bSMatt Spinler /**
35d7abf367SMatt Spinler  * @class RecordManager
36d7abf367SMatt Spinler  *
37d7abf367SMatt Spinler  * This class manages the records for the input power history of
38d7abf367SMatt Spinler  * a power supply.
39d7abf367SMatt Spinler  *
40d7abf367SMatt Spinler  * The history is the average and maximum power values across 30s
41d7abf367SMatt Spinler  * intervals.  Every 30s, a new record will be available from the
42d7abf367SMatt Spinler  * PS.  This class takes that raw PS data and converts it into
43cab48342SGunnar Mills  * something usable by D-Bus.  It ensures the readings are always
44d7abf367SMatt Spinler  * sorted newest to oldest, and prunes out the oldest entries when
45d7abf367SMatt Spinler  * necessary.  If there is a problem with the ordering IDs coming
46d7abf367SMatt Spinler  * from the PS, it will clear out the old records and start over.
47d7abf367SMatt Spinler  */
48d7abf367SMatt Spinler class RecordManager
49d7abf367SMatt Spinler {
50d7abf367SMatt Spinler   public:
5128fa1b6bSMatt Spinler     static constexpr auto RAW_RECORD_SIZE = 5;
5228fa1b6bSMatt Spinler     static constexpr auto RAW_RECORD_ID_OFFSET = 0;
538168d280SMatt Spinler     static constexpr auto FIRST_SEQUENCE_ID = 0;
54d7abf367SMatt Spinler     static constexpr auto LAST_SEQUENCE_ID = 0xFF;
55d7abf367SMatt Spinler 
56d7abf367SMatt Spinler     using DBusRecord = std::tuple<uint64_t, int64_t>;
57d7abf367SMatt Spinler     using DBusRecordList = std::vector<DBusRecord>;
58d7abf367SMatt Spinler 
59d7abf367SMatt Spinler     RecordManager() = delete;
60d7abf367SMatt Spinler     ~RecordManager() = default;
61d7abf367SMatt Spinler     RecordManager(const RecordManager&) = default;
62d7abf367SMatt Spinler     RecordManager& operator=(const RecordManager&) = default;
63d7abf367SMatt Spinler     RecordManager(RecordManager&&) = default;
64d7abf367SMatt Spinler     RecordManager& operator=(RecordManager&&) = default;
65d7abf367SMatt Spinler 
66d7abf367SMatt Spinler     /**
67d7abf367SMatt Spinler      * @brief Constructor
68d7abf367SMatt Spinler      *
69d7abf367SMatt Spinler      * @param[in] maxRec - the maximum number of history
70d7abf367SMatt Spinler      *                     records to keep at a time
71d7abf367SMatt Spinler      */
RecordManager(size_t maxRec)7286433ae8SGeorge Liu     explicit RecordManager(size_t maxRec) :
7386433ae8SGeorge Liu         RecordManager(maxRec, LAST_SEQUENCE_ID)
740c9a33d6SAdriana Kobylak     {}
75d7abf367SMatt Spinler 
76d7abf367SMatt Spinler     /**
77d7abf367SMatt Spinler      * @brief Constructor
78d7abf367SMatt Spinler      *
79d7abf367SMatt Spinler      * @param[in] maxRec - the maximum number of history
80d7abf367SMatt Spinler      *                     records to keep at a time
81d7abf367SMatt Spinler      * @param[in] lastSequenceID - the last sequence ID the power supply
82d7abf367SMatt Spinler      *                             will use before starting over
83d7abf367SMatt Spinler      */
RecordManager(size_t maxRec,size_t lastSequenceID)84d7abf367SMatt Spinler     RecordManager(size_t maxRec, size_t lastSequenceID) :
85f0f02b9aSMatt Spinler         maxRecords(maxRec), lastSequenceID(lastSequenceID)
860c9a33d6SAdriana Kobylak     {}
87d7abf367SMatt Spinler 
88d7abf367SMatt Spinler     /**
898168d280SMatt Spinler      * @brief Adds a new entry to the history
908168d280SMatt Spinler      *
918168d280SMatt Spinler      * Also checks to see if the old history should be
928168d280SMatt Spinler      * cleared, such as when there is an invalid record
938168d280SMatt Spinler      * sequence ID or if there was no data from the PS.
948168d280SMatt Spinler      *
958168d280SMatt Spinler      * @param[in] rawRecord - the record data straight
968168d280SMatt Spinler      *                    from the power supply
978168d280SMatt Spinler      *
988168d280SMatt Spinler      * @return bool - If there has been a change to the
998168d280SMatt Spinler      *                history records that needs to be
1008168d280SMatt Spinler      *                reflected in D-Bus.
1018168d280SMatt Spinler      */
1028168d280SMatt Spinler     bool add(const std::vector<uint8_t>& rawRecord);
1038168d280SMatt Spinler 
1048168d280SMatt Spinler     /**
105c3414388SMatt Spinler      * @brief Returns the history of average input power
106c3414388SMatt Spinler      *        in a representation used by D-Bus.
107c3414388SMatt Spinler      *
108c3414388SMatt Spinler      * @return DBusRecordList - A list of averages with
109c3414388SMatt Spinler      *         a timestamp for each entry.
110c3414388SMatt Spinler      */
111c3414388SMatt Spinler     DBusRecordList getAverageRecords();
112c3414388SMatt Spinler 
113c3414388SMatt Spinler     /**
114c3414388SMatt Spinler      * @brief Returns the history of maximum input power
115c3414388SMatt Spinler      *        in a representation used by D-Bus.
116c3414388SMatt Spinler      *
117c3414388SMatt Spinler      * @return DBusRecordList - A list of maximums with
118c3414388SMatt Spinler      *         a timestamp for each entry.
119c3414388SMatt Spinler      */
120c3414388SMatt Spinler     DBusRecordList getMaximumRecords();
121c3414388SMatt Spinler 
122c3414388SMatt Spinler     /**
123e710d189SMatt Spinler      * @brief Converts a Linear Format power number to an integer
124e710d189SMatt Spinler      *
125e710d189SMatt Spinler      * The PMBus spec describes a 2 byte Linear Format
126e710d189SMatt Spinler      * number that is composed of an exponent and mantissa
127e710d189SMatt Spinler      * in two's complement notation.
128e710d189SMatt Spinler      *
129e710d189SMatt Spinler      * Value = Mantissa * 2**Exponent
130e710d189SMatt Spinler      *
131e710d189SMatt Spinler      * @return int64_t the converted value
132e710d189SMatt Spinler      */
133e710d189SMatt Spinler     static int64_t linearToInteger(uint16_t data);
134e710d189SMatt Spinler 
135e710d189SMatt Spinler     /**
136d7abf367SMatt Spinler      * @brief Returns the number of records
137d7abf367SMatt Spinler      *
138d7abf367SMatt Spinler      * @return size_t - the number of records
139d7abf367SMatt Spinler      *
140d7abf367SMatt Spinler      */
getNumRecords() const141d7abf367SMatt Spinler     inline size_t getNumRecords() const
142d7abf367SMatt Spinler     {
143d7abf367SMatt Spinler         return records.size();
144d7abf367SMatt Spinler     }
145d7abf367SMatt Spinler 
146d7abf367SMatt Spinler     /**
147d7abf367SMatt Spinler      * @brief Deletes all records
148d7abf367SMatt Spinler      */
clear()149d7abf367SMatt Spinler     inline void clear()
150d7abf367SMatt Spinler     {
151d7abf367SMatt Spinler         records.clear();
152d7abf367SMatt Spinler     }
153d7abf367SMatt Spinler 
154d7abf367SMatt Spinler   private:
155d7abf367SMatt Spinler     /**
15628fa1b6bSMatt Spinler      * @brief returns the sequence ID from a raw history record
15728fa1b6bSMatt Spinler      *
15828fa1b6bSMatt Spinler      * Throws InvalidRecordException if the data is the wrong length.
15928fa1b6bSMatt Spinler      *
16028fa1b6bSMatt Spinler      * @param[in] data - the raw record data as the PS returns it
16128fa1b6bSMatt Spinler      *
16228fa1b6bSMatt Spinler      * @return size_t - the ID from byte 0
16328fa1b6bSMatt Spinler      */
16428fa1b6bSMatt Spinler     size_t getRawRecordID(const std::vector<uint8_t>& data) const;
16528fa1b6bSMatt Spinler 
16628fa1b6bSMatt Spinler     /**
16728fa1b6bSMatt Spinler      * @brief Creates an instance of a Record from the raw PS data
16828fa1b6bSMatt Spinler      *
16928fa1b6bSMatt Spinler      * @param[in] data - the raw record data as the PS returns it
17028fa1b6bSMatt Spinler      *
17128fa1b6bSMatt Spinler      * @return Record - A filled in Record instance
17228fa1b6bSMatt Spinler      */
17328fa1b6bSMatt Spinler     Record createRecord(const std::vector<uint8_t>& data);
17428fa1b6bSMatt Spinler 
17528fa1b6bSMatt Spinler     /**
176d7abf367SMatt Spinler      * @brief The maximum number of entries to keep in the history.
177d7abf367SMatt Spinler      *
178d7abf367SMatt Spinler      * When a new record is added, the oldest one will be removed.
179d7abf367SMatt Spinler      */
180d7abf367SMatt Spinler     const size_t maxRecords;
181d7abf367SMatt Spinler 
182d7abf367SMatt Spinler     /**
183d7abf367SMatt Spinler      * @brief The last ID the power supply returns before rolling over
184d7abf367SMatt Spinler      *        back to the first ID of 0.
185d7abf367SMatt Spinler      */
186d7abf367SMatt Spinler     const size_t lastSequenceID;
187d7abf367SMatt Spinler 
188d7abf367SMatt Spinler     /**
189d7abf367SMatt Spinler      * @brief The list of timestamp/average/maximum records.
190d7abf367SMatt Spinler      *        Newer records are added to the front, and older ones
191d7abf367SMatt Spinler      *        removed from the back.
192d7abf367SMatt Spinler      */
193d7abf367SMatt Spinler     std::deque<Record> records;
194d7abf367SMatt Spinler };
195d7abf367SMatt Spinler 
196f0f02b9aSMatt Spinler } // namespace history
197f0f02b9aSMatt Spinler } // namespace power
198ab093328SLei YU } // namespace phosphor
199