control: Add setFloorHold to Zone
Similar to the existing Zone::setTargetHold function, setFloorHold
allows an action to set a floor and hold it, meaning the fans are not
allowed to decrease to a value below that floor until the hold is
released. Adding this allows multiple actions to set the floor, without
worrying if one is overwriting another.
It also adds some flight recorder entries with the ID zone-floorX when
floor holds are added and removed. An example of that output is:
zone-floor0: count_state_floor-1 is setting floor hold to 7777
zone-floor0: Setting new floor to 7777
zone-floor0: mapped_floor-0 is setting floor hold to 10700
zone-floor0: Setting new floor to 10700
zone-floor0: count_state_floor-1 is removing floor hold
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I1756494e61ada60d44e58704431fb882ef7646a4
diff --git a/control/json/zone.cpp b/control/json/zone.cpp
index 6701c83..5cc0c35 100644
--- a/control/json/zone.cpp
+++ b/control/json/zone.cpp
@@ -15,6 +15,7 @@
*/
#include "zone.hpp"
+#include "../utils/flight_recorder.hpp"
#include "dbus_zone.hpp"
#include "fan.hpp"
#include "sdbusplus.hpp"
@@ -147,19 +148,19 @@
{
if (!hold)
{
- _holds.erase(ident);
+ _targetHolds.erase(ident);
}
else
{
- _holds[ident] = target;
+ _targetHolds[ident] = target;
_isActive = false;
}
- auto itHoldMax = std::max_element(_holds.begin(), _holds.end(),
+ auto itHoldMax = std::max_element(_targetHolds.begin(), _targetHolds.end(),
[](const auto& aHold, const auto& bHold) {
return aHold.second < bHold.second;
});
- if (itHoldMax == _holds.end())
+ if (itHoldMax == _targetHolds.end())
{
_isActive = true;
}
@@ -173,6 +174,71 @@
}
}
+void Zone::setFloorHold(const std::string& ident, uint64_t target, bool hold)
+{
+ using namespace std::string_literals;
+
+ if (!hold)
+ {
+ size_t removed = _floorHolds.erase(ident);
+ if (removed)
+ {
+ FlightRecorder::instance().log(
+ "zone-floor"s + getName(),
+ fmt::format("{} is removing floor hold", ident));
+ }
+ }
+ else
+ {
+ if (!((_floorHolds.find(ident) != _floorHolds.end()) &&
+ (_floorHolds[ident] == target)))
+ {
+ FlightRecorder::instance().log(
+ "zone-floor"s + getName(),
+ fmt::format("{} is setting floor hold to {}", ident, target));
+ }
+ _floorHolds[ident] = target;
+ }
+
+ if (!std::all_of(_floorChange.begin(), _floorChange.end(),
+ [](const auto& entry) { return entry.second; }))
+ {
+ return;
+ }
+
+ auto itHoldMax = std::max_element(_floorHolds.begin(), _floorHolds.end(),
+ [](const auto& aHold, const auto& bHold) {
+ return aHold.second < bHold.second;
+ });
+ if (itHoldMax == _floorHolds.end())
+ {
+ if (_floor != _defaultFloor)
+ {
+ FlightRecorder::instance().log(
+ "zone-floor"s + getName(),
+ fmt::format("No set floor exists, using default floor",
+ _defaultFloor));
+ }
+ _floor = _defaultFloor;
+ }
+ else
+ {
+ if (_floor != itHoldMax->second)
+ {
+ FlightRecorder::instance().log(
+ "zone-floor"s + getName(),
+ fmt::format("Setting new floor to {}", itHoldMax->second));
+ }
+ _floor = itHoldMax->second;
+ }
+
+ // Floor above target, update target to floor
+ if (_target < _floor)
+ {
+ requestIncrease(_floor - _target);
+ }
+}
+
void Zone::setFloor(uint64_t target)
{
// Check all entries are set to allow floor to be set
@@ -378,7 +444,8 @@
output["floor_change"] = _floorChange;
output["decrease_allowed"] = _decAllowed;
output["persisted_props"] = _propsPersisted;
- output["holds"] = _holds;
+ output["target_holds"] = _targetHolds;
+ output["floor_holds"] = _floorHolds;
return output;
}
diff --git a/control/json/zone.hpp b/control/json/zone.hpp
index fadfe13..4063bd5 100644
--- a/control/json/zone.hpp
+++ b/control/json/zone.hpp
@@ -236,6 +236,18 @@
void setFloor(uint64_t target);
/**
+ * Sets and holds the floor of the zone to the target given or releases a
+ * floor hold resulting in the fans being held at the highest remaining
+ * hold target if other floor hold targets had been requested. When no hold
+ * targets exist, the floor gets set to the default floor value.
+ *
+ * @param[in] ident - Unique identifier for a floor hold
+ * @param[in] target - Floor value
+ * @param[in] hold - Whether to hold(true) or release(false) a hold
+ */
+ void setFloorHold(const std::string& ident, uint64_t target, bool hold);
+
+ /**
* @brief Set the default floor to the given value
*
* @param[in] value - Value to set the default floor to
@@ -443,7 +455,10 @@
Timer _decTimer;
/* Map of target holds by a string identifier */
- std::unordered_map<std::string, uint64_t> _holds;
+ std::unordered_map<std::string, uint64_t> _targetHolds;
+
+ /* Map of floor holds by a string identifier */
+ std::unordered_map<std::string, uint64_t> _floorHolds;
/* Interface to property mapping of their associated set property handler
* function */