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