xref: /openbmc/phosphor-pid-control/pid/zone.hpp (revision 6df8bb5086b29c43217596b194dda7fbc4e3ec4a)
1d8012181SPatrick Venture #pragma once
2d8012181SPatrick Venture 
3da4a5dd1SPatrick Venture #include "conf.hpp"
4da4a5dd1SPatrick Venture #include "controller.hpp"
5*6df8bb50SJames Zheng #include "failsafeloggers/failsafe_logger_utility.hpp"
622c257abSJames Feist #include "pidcontroller.hpp"
7da4a5dd1SPatrick Venture #include "sensors/manager.hpp"
8da4a5dd1SPatrick Venture #include "sensors/sensor.hpp"
9c32e3fc5SPatrick Venture #include "tuning.hpp"
101a153794SPatrick Venture #include "zone_interface.hpp"
11da4a5dd1SPatrick Venture 
12a83a3eccSPatrick Venture #include <sdbusplus/bus.hpp>
13a83a3eccSPatrick Venture #include <sdbusplus/server.hpp>
14a83a3eccSPatrick Venture #include <xyz/openbmc_project/Control/Mode/server.hpp>
1537180062SHarvey Wu #include <xyz/openbmc_project/Debug/Pid/ThermalPower/server.hpp>
16cc0232afSHarvey Wu #include <xyz/openbmc_project/Debug/Pid/Zone/server.hpp>
177c6d35d5Sykchiu #include <xyz/openbmc_project/Object/Enable/server.hpp>
18a83a3eccSPatrick Venture 
19d8012181SPatrick Venture #include <fstream>
20df1f183fSTom Tung #include <iostream>
21d8012181SPatrick Venture #include <map>
22d8012181SPatrick Venture #include <memory>
23d8012181SPatrick Venture #include <set>
24d8012181SPatrick Venture #include <string>
25d8012181SPatrick Venture #include <vector>
26d8012181SPatrick Venture 
27d8012181SPatrick Venture template <typename... T>
28b228bc30SPatrick Williams using ServerObject = typename sdbusplus::server::object_t<T...>;
29da4a5dd1SPatrick Venture using ModeInterface = sdbusplus::xyz::openbmc_project::Control::server::Mode;
30cc0232afSHarvey Wu using DebugZoneInterface =
31cc0232afSHarvey Wu     sdbusplus::xyz::openbmc_project::Debug::Pid::server::Zone;
32cc0232afSHarvey Wu using ModeObject = ServerObject<ModeInterface, DebugZoneInterface>;
337c6d35d5Sykchiu using ProcessInterface =
347c6d35d5Sykchiu     sdbusplus::xyz::openbmc_project::Object::server::Enable;
3537180062SHarvey Wu using DebugThermalPowerInterface =
3637180062SHarvey Wu     sdbusplus::xyz::openbmc_project::Debug::Pid::server::ThermalPower;
3737180062SHarvey Wu using ProcessObject =
3837180062SHarvey Wu     ServerObject<ProcessInterface, DebugThermalPowerInterface>;
39d8012181SPatrick Venture 
40a076487aSPatrick Venture namespace pid_control
41a076487aSPatrick Venture {
42a076487aSPatrick Venture 
43d8012181SPatrick Venture /*
44597ebd67SPatrick Venture  * The DbusPidZone inherits from the Mode object so that it can listen for
45597ebd67SPatrick Venture  * control mode changes.  It primarily holds all PID loops and holds the sensor
46597ebd67SPatrick Venture  * value cache that's used per iteration of the PID loops.
47d8012181SPatrick Venture  */
48597ebd67SPatrick Venture class DbusPidZone : public ZoneInterface, public ModeObject
49d8012181SPatrick Venture {
50d8012181SPatrick Venture   public:
DbusPidZone(int64_t zone,double minThermalOutput,double failSafePercent,conf::CycleTime cycleTime,const SensorManager & mgr,sdbusplus::bus_t & bus,const char * objPath,bool defer,bool accumulateSetPoint)51597ebd67SPatrick Venture     DbusPidZone(int64_t zone, double minThermalOutput, double failSafePercent,
520e8fc398SBonnie Lo                 conf::CycleTime cycleTime, const SensorManager& mgr,
539788963cSDelphine CC Chiu                 sdbusplus::bus_t& bus, const char* objPath, bool defer,
549788963cSDelphine CC Chiu                 bool accumulateSetPoint) :
55d8c5a45cSPatrick Williams         ModeObject(bus, objPath,
56d8c5a45cSPatrick Williams                    defer ? ModeObject::action::defer_emit
57d8c5a45cSPatrick Williams                          : ModeObject::action::emit_object_added),
58f7a2dd5cSPatrick Venture         _zoneId(zone), _maximumSetPoint(),
599788963cSDelphine CC Chiu         _accumulateSetPoint(accumulateSetPoint),
603484bedaSJames Feist         _minThermalOutputSetPt(minThermalOutput),
619fe3a3c7Sykchiu         _zoneFailSafePercent(failSafePercent), _cycleTime(cycleTime), _mgr(mgr)
62d8012181SPatrick Venture     {
63de79ee05SPatrick Venture         if (loggingEnabled)
64c32e3fc5SPatrick Venture         {
6589002dbdSPatrick Venture             _log.open(loggingPath + "/zone_" + std::to_string(zone) + ".log");
66c32e3fc5SPatrick Venture         }
67d8012181SPatrick Venture     }
68d8012181SPatrick Venture 
697a98c19aSPatrick Venture     bool getManualMode(void) const override;
70d8012181SPatrick Venture     /* Could put lock around this since it's accessed from two threads, but
71d8012181SPatrick Venture      * only one reader/one writer.
72d8012181SPatrick Venture      */
73a4146eb1SJosh Lehan 
74a4146eb1SJosh Lehan     bool getRedundantWrite(void) const override;
75d8012181SPatrick Venture     void setManualMode(bool mode);
76a58197cfSPatrick Venture     bool getFailSafeMode(void) const override;
773f0f7bc3SJosh Lehan     void markSensorMissing(const std::string& name);
789788963cSDelphine CC Chiu     bool getAccSetPoint(void) const override;
797a98c19aSPatrick Venture 
80c51ba919SBonnie Lo     int64_t getZoneID(void) const override;
81ccc8bb62SNirav Shah     void addSetPoint(double setPoint, const std::string& name) override;
827a98c19aSPatrick Venture     double getMaxSetPointRequest(void) const override;
83608304daSJames Feist     void addRPMCeiling(double ceiling) override;
847a98c19aSPatrick Venture     void clearSetPoints(void) override;
857a98c19aSPatrick Venture     void clearRPMCeilings(void) override;
8692f9f3c8SHarvey Wu     double getFailSafePercent(void) override;
87ccc8bb62SNirav Shah     double getMinThermalSetPoint(void) const;
880e8fc398SBonnie Lo     uint64_t getCycleIntervalTime(void) const override;
890e8fc398SBonnie Lo     uint64_t getUpdateThermalsCycle(void) const override;
90d8012181SPatrick Venture 
912d8e7851SPatrick Venture     Sensor* getSensor(const std::string& name) override;
92*6df8bb50SJames Zheng     std::vector<std::string> getSensorNames(void) override;
937a98c19aSPatrick Venture     void determineMaxSetPointRequest(void) override;
947a98c19aSPatrick Venture     void updateFanTelemetry(void) override;
957a98c19aSPatrick Venture     void updateSensors(void) override;
967a98c19aSPatrick Venture     void initializeCache(void) override;
97b300575eSJosh Lehan     void setOutputCache(std::string_view, const ValueCacheEntry&) override;
98d8012181SPatrick Venture     void dumpCache(void);
99a4146eb1SJosh Lehan 
1007a98c19aSPatrick Venture     void processFans(void) override;
1017a98c19aSPatrick Venture     void processThermals(void) override;
102d8012181SPatrick Venture 
10322c257abSJames Feist     void addFanPID(std::unique_ptr<Controller> pid);
10422c257abSJames Feist     void addThermalPID(std::unique_ptr<Controller> pid);
105a58197cfSPatrick Venture     double getCachedValue(const std::string& name) override;
106b300575eSJosh Lehan     ValueCacheEntry getCachedValues(const std::string& name) override;
107b300575eSJosh Lehan 
1083f0f7bc3SJosh Lehan     void addFanInput(const std::string& fan, bool missingAcceptable);
1093f0f7bc3SJosh Lehan     void addThermalInput(const std::string& therm, bool missingAcceptable);
110d8012181SPatrick Venture 
1117a98c19aSPatrick Venture     void initializeLog(void) override;
1127a98c19aSPatrick Venture     void writeLog(const std::string& value) override;
113d8012181SPatrick Venture 
114d8012181SPatrick Venture     /* Method for setting the manual mode over dbus */
115d8012181SPatrick Venture     bool manual(bool value) override;
116d8012181SPatrick Venture     /* Method for reading whether in fail-safe mode over dbus */
117d8012181SPatrick Venture     bool failSafe() const override;
118cc0232afSHarvey Wu     /* Method for recording the maximum SetPoint PID config name */
119cc0232afSHarvey Wu     std::string leader() const override;
1207c6d35d5Sykchiu     /* Method for control process for each loop at runtime */
12137180062SHarvey Wu     void addPidControlProcess(std::string name, std::string type,
12237180062SHarvey Wu                               double setpoint, sdbusplus::bus_t& bus,
1237c6d35d5Sykchiu                               std::string objPath, bool defer);
1247c6d35d5Sykchiu     bool isPidProcessEnabled(std::string name);
125d8012181SPatrick Venture 
12692f9f3c8SHarvey Wu     void addPidFailSafePercent(std::vector<std::string> inputs, double percent);
1279fe3a3c7Sykchiu 
12837180062SHarvey Wu     void updateThermalPowerDebugInterface(std::string pidName,
12937180062SHarvey Wu                                           std::string leader, double input,
13037180062SHarvey Wu                                           double output) override;
13137180062SHarvey Wu 
132d8012181SPatrick Venture   private:
133df1f183fSTom Tung     template <bool fanSensorLogging>
processSensorInputs(const std::vector<std::string> & sensorInputs,std::chrono::high_resolution_clock::time_point now)134df1f183fSTom Tung     void processSensorInputs(const std::vector<std::string>& sensorInputs,
135df1f183fSTom Tung                              std::chrono::high_resolution_clock::time_point now)
136df1f183fSTom Tung     {
137df1f183fSTom Tung         for (const auto& sensorInput : sensorInputs)
138df1f183fSTom Tung         {
139df1f183fSTom Tung             auto sensor = _mgr.getSensor(sensorInput);
140df1f183fSTom Tung             ReadReturn r = sensor->read();
141df1f183fSTom Tung             _cachedValuesByName[sensorInput] = {r.value, r.unscaled};
142df1f183fSTom Tung             int64_t timeout = sensor->getTimeout();
143df1f183fSTom Tung             std::chrono::high_resolution_clock::time_point then = r.updated;
144df1f183fSTom Tung 
145df1f183fSTom Tung             auto duration =
146df1f183fSTom Tung                 std::chrono::duration_cast<std::chrono::seconds>(now - then)
147df1f183fSTom Tung                     .count();
148df1f183fSTom Tung             auto period = std::chrono::seconds(timeout).count();
149df1f183fSTom Tung             /*
150df1f183fSTom Tung              * TODO(venture): We should check when these were last read.
151df1f183fSTom Tung              * However, these are the fans, so if I'm not getting updated values
152df1f183fSTom Tung              * for them... what should I do?
153df1f183fSTom Tung              */
154df1f183fSTom Tung             if constexpr (fanSensorLogging)
155df1f183fSTom Tung             {
156df1f183fSTom Tung                 if (loggingEnabled)
157df1f183fSTom Tung                 {
158df1f183fSTom Tung                     const auto& v = _cachedValuesByName[sensorInput];
159df1f183fSTom Tung                     _log << "," << v.scaled << "," << v.unscaled;
160df1f183fSTom Tung                     const auto& p = _cachedFanOutputs[sensorInput];
161df1f183fSTom Tung                     _log << "," << p.scaled << "," << p.unscaled;
162df1f183fSTom Tung                 }
163df1f183fSTom Tung             }
164df1f183fSTom Tung 
165df1f183fSTom Tung             if (debugEnabled)
166df1f183fSTom Tung             {
167df1f183fSTom Tung                 std::cerr << sensorInput << " sensor reading: " << r.value
168df1f183fSTom Tung                           << "\n";
169df1f183fSTom Tung             }
170df1f183fSTom Tung 
171df1f183fSTom Tung             // check if fan fail.
172df1f183fSTom Tung             if (sensor->getFailed())
173df1f183fSTom Tung             {
1743f0f7bc3SJosh Lehan                 markSensorMissing(sensorInput);
1753f0f7bc3SJosh Lehan 
176df1f183fSTom Tung                 if (debugEnabled)
177df1f183fSTom Tung                 {
178df1f183fSTom Tung                     std::cerr << sensorInput << " sensor get failed\n";
179df1f183fSTom Tung                 }
180df1f183fSTom Tung             }
181df1f183fSTom Tung             else if (timeout != 0 && duration >= period)
182df1f183fSTom Tung             {
1833f0f7bc3SJosh Lehan                 markSensorMissing(sensorInput);
1843f0f7bc3SJosh Lehan 
185df1f183fSTom Tung                 if (debugEnabled)
186df1f183fSTom Tung                 {
187df1f183fSTom Tung                     std::cerr << sensorInput << " sensor timeout\n";
188df1f183fSTom Tung                 }
189*6df8bb50SJames Zheng                 outputFailsafeLogWithZone(_zoneId, this->getFailSafeMode(),
190*6df8bb50SJames Zheng                                           sensorInput,
191*6df8bb50SJames Zheng                                           "The sensor has timed out.");
192df1f183fSTom Tung             }
193df1f183fSTom Tung             else
194df1f183fSTom Tung             {
195df1f183fSTom Tung                 // Check if it's in there: remove it.
196df1f183fSTom Tung                 auto kt = _failSafeSensors.find(sensorInput);
197df1f183fSTom Tung                 if (kt != _failSafeSensors.end())
198df1f183fSTom Tung                 {
199df1f183fSTom Tung                     if (debugEnabled)
200df1f183fSTom Tung                     {
201df1f183fSTom Tung                         std::cerr << sensorInput
202df1f183fSTom Tung                                   << " is erased from failsafe sensor set\n";
203df1f183fSTom Tung                     }
2043f0f7bc3SJosh Lehan 
205df1f183fSTom Tung                     _failSafeSensors.erase(kt);
206*6df8bb50SJames Zheng                     outputFailsafeLogWithZone(_zoneId, this->getFailSafeMode(),
207*6df8bb50SJames Zheng                                               sensorInput,
208*6df8bb50SJames Zheng                                               "The sensor has recovered.");
209df1f183fSTom Tung                 }
210df1f183fSTom Tung             }
211df1f183fSTom Tung         }
212df1f183fSTom Tung     }
213df1f183fSTom Tung 
214d8012181SPatrick Venture     std::ofstream _log;
215d8012181SPatrick Venture 
216d8012181SPatrick Venture     const int64_t _zoneId;
217f7a2dd5cSPatrick Venture     double _maximumSetPoint = 0;
218ccc8bb62SNirav Shah     std::string _maximumSetPointName;
219ccc8bb62SNirav Shah     std::string _maximumSetPointNamePrev;
220d8012181SPatrick Venture     bool _manualMode = false;
221a4146eb1SJosh Lehan     bool _redundantWrite = false;
2229788963cSDelphine CC Chiu     bool _accumulateSetPoint = false;
2233484bedaSJames Feist     const double _minThermalOutputSetPt;
2249fe3a3c7Sykchiu     // Zone fail safe Percent setting by configuration.
2259fe3a3c7Sykchiu     const double _zoneFailSafePercent;
2260e8fc398SBonnie Lo     const conf::CycleTime _cycleTime;
227d8012181SPatrick Venture 
22892f9f3c8SHarvey Wu     std::map<std::string, double> _failSafeSensors;
2293f0f7bc3SJosh Lehan     std::set<std::string> _missingAcceptable;
230d8012181SPatrick Venture 
2319788963cSDelphine CC Chiu     std::map<std::string, double> _SetPoints;
232608304daSJames Feist     std::vector<double> _RPMCeilings;
233d8012181SPatrick Venture     std::vector<std::string> _fanInputs;
234d8012181SPatrick Venture     std::vector<std::string> _thermalInputs;
235b300575eSJosh Lehan     std::map<std::string, ValueCacheEntry> _cachedValuesByName;
236b300575eSJosh Lehan     std::map<std::string, ValueCacheEntry> _cachedFanOutputs;
237fe75b193SPatrick Venture     const SensorManager& _mgr;
238d8012181SPatrick Venture 
23922c257abSJames Feist     std::vector<std::unique_ptr<Controller>> _fans;
24022c257abSJames Feist     std::vector<std::unique_ptr<Controller>> _thermals;
2417c6d35d5Sykchiu 
2427c6d35d5Sykchiu     std::map<std::string, std::unique_ptr<ProcessObject>> _pidsControlProcess;
2439fe3a3c7Sykchiu     /*
24492f9f3c8SHarvey Wu      * <key = sensor name, value = sensor failsafe percent>
24592f9f3c8SHarvey Wu      * sensor fail safe Percent setting by each pid controller configuration.
2469fe3a3c7Sykchiu      */
24792f9f3c8SHarvey Wu     std::map<std::string, double> _sensorFailSafePercent;
248d8012181SPatrick Venture };
249a076487aSPatrick Venture 
250a076487aSPatrick Venture } // namespace pid_control
251