1 /**
2  * Copyright © 2021 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "dbus_sensors.hpp"
18 
19 #include <utility>
20 
21 namespace phosphor::power::regulators
22 {
23 
24 void DBusSensors::enable()
25 {
26     // Currently nothing to do here.  The next monitoring cycle will set the
27     // values of all sensors, and that will set them to the enabled state.
28 }
29 
30 void DBusSensors::endCycle()
31 {
32     // Delete any sensors that were not updated during this monitoring cycle.
33     // This can happen if the hardware device producing the sensors was removed
34     // or replaced with a different version.
35     auto it = sensors.begin();
36     while (it != sensors.end())
37     {
38         // Increment iterator before potentially deleting the sensor.
39         // map::erase() invalidates iterators/references to the erased element.
40         auto& [sensorName, sensor] = *it;
41         ++it;
42 
43         // Check if last update time for sensor is before cycle start time
44         if (sensor->getLastUpdateTime() < cycleStartTime)
45         {
46             sensors.erase(sensorName);
47         }
48     }
49 }
50 
51 void DBusSensors::endRail(bool errorOccurred)
52 {
53     // If an error occurred, set all sensors for current rail to the error state
54     if (errorOccurred)
55     {
56         for (auto& [sensorName, sensor] : sensors)
57         {
58             if (sensor->getRail() == rail)
59             {
60                 sensor->setToErrorState();
61             }
62         }
63     }
64 
65     // Clear current rail information
66     rail.clear();
67     deviceInventoryPath.clear();
68     chassisInventoryPath.clear();
69 }
70 
71 void DBusSensors::disable()
72 {
73     // Disable all sensors
74     for (auto& [sensorName, sensor] : sensors)
75     {
76         sensor->disable();
77     }
78 }
79 
80 void DBusSensors::setValue(SensorType type, double value)
81 {
82     // Build unique sensor name based on rail and sensor type
83     std::string sensorName{rail + '_' + sensors::toString(type)};
84 
85     // Check to see if the sensor already exists
86     auto it = sensors.find(sensorName);
87     if (it != sensors.end())
88     {
89         // Sensor exists; update value
90         it->second->setValue(value);
91     }
92     else
93     {
94         // Sensor doesn't exist; create it and add it to the map
95         auto sensor = std::make_unique<DBusSensor>(bus, sensorName, type, value,
96                                                    rail, deviceInventoryPath,
97                                                    chassisInventoryPath);
98         sensors.emplace(sensorName, std::move(sensor));
99     }
100 }
101 
102 void DBusSensors::startCycle()
103 {
104     // Store the time when this monitoring cycle started.  This is used to
105     // detect sensors that were not updated during this cycle.
106     cycleStartTime = std::chrono::system_clock::now();
107 }
108 
109 void DBusSensors::startRail(const std::string& rail,
110                             const std::string& deviceInventoryPath,
111                             const std::string& chassisInventoryPath)
112 {
113     // Store current rail information; used later by setValue() and endRail()
114     this->rail = rail;
115     this->deviceInventoryPath = deviceInventoryPath;
116     this->chassisInventoryPath = chassisInventoryPath;
117 }
118 
119 } // namespace phosphor::power::regulators
120