control: mapped_floor: Add default floors
Add support for two optional default floor values in the mapped floor
action. The first is action wide, and the second is key value wide.
These would be chosen in certain situations when a normal floor can't be
calculated.
Default floor at action level:
{
"name": "mapped_floor",
"key_group": "ambient_temp",
"default_floor": 2000, <---
...
}
Default floor at key value level:
{
"key": 27,
"default_floor": 3000, <---
"floors": [
...
]
}
The key level default floor would be selected when no other floor value
could be found within that that key's tables.
The action level default floor would be used when a key table couldn't
be found based on the actual key value, or when a key level default
floor would have been used but it wasn't supplied.
The default floor from the zone will be used when no other default floor
is provided at the key level or action level.
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I740220a97477e9a4fb16cdc54c91f86c99c8b461
diff --git a/control/json/actions/mapped_floor.cpp b/control/json/actions/mapped_floor.cpp
index b84de15..34cbfac 100644
--- a/control/json/actions/mapped_floor.cpp
+++ b/control/json/actions/mapped_floor.cpp
@@ -58,6 +58,7 @@
{
setKeyGroup(jsonObj);
setFloorTable(jsonObj);
+ setDefaultFloor(jsonObj);
}
const Group* MappedFloor::getGroup(const std::string& name)
@@ -86,6 +87,14 @@
_keyGroup = getGroup(jsonObj["key_group"].get<std::string>());
}
+void MappedFloor::setDefaultFloor(const json& jsonObj)
+{
+ if (jsonObj.contains("default_floor"))
+ {
+ _defaultFloor = jsonObj["default_floor"].get<uint64_t>();
+ }
+}
+
void MappedFloor::setFloorTable(const json& jsonObj)
{
if (!jsonObj.contains("fan_floors"))
@@ -114,6 +123,11 @@
floors["floor_offset_parameter"].get<std::string>();
}
+ if (floors.contains("default_floor"))
+ {
+ ff.defaultFloor = floors["default_floor"].get<uint64_t>();
+ }
+
for (const auto& groupEntry : floors["floors"])
{
if ((!groupEntry.contains("group") &&
@@ -196,7 +210,8 @@
member, group.getInterface(), group.getProperty());
// Only allow a group to have multiple members if it's numeric.
- // Unlike std::is_arithmetic, bools are not considered numeric here.
+ // Unlike std::is_arithmetic, bools are not considered numeric
+ // here.
if (!checked && (group.getMembers().size() > 1))
{
std::visit(
@@ -242,13 +257,13 @@
void MappedFloor::run(Zone& zone)
{
std::optional<uint64_t> newFloor;
- bool missingGroupProperty = false;
auto& manager = *zone.getManager();
auto keyValue = getMaxGroupValue(*_keyGroup, manager);
if (!keyValue)
{
- zone.setFloor(zone.getDefaultFloor());
+ auto floor = _defaultFloor ? *_defaultFloor : zone.getDefaultFloor();
+ zone.setFloorHold(getUniqueName(), floor, true);
return;
}
@@ -301,51 +316,63 @@
*std::get<const Group*>(groupOrParameter), manager);
}
- if (!propertyValue)
- {
- // Couldn't successfully get a value. Results in default floor.
- missingGroupProperty = true;
- break;
- }
-
- // Do either a <= or an == check depending on the data type to get
- // the floor value based on this group.
std::optional<uint64_t> floor;
- for (const auto& [tableValue, tableFloor] : floorGroups)
+ if (propertyValue)
{
- PropertyVariantType value{tableValue};
- tryConvertToDouble(value);
-
- if (std::holds_alternative<double>(*propertyValue))
+ // Do either a <= or an == check depending on the data type
+ // to get the floor value based on this group.
+ for (const auto& [tableValue, tableFloor] : floorGroups)
{
- if (*propertyValue <= value)
+ PropertyVariantType value{tableValue};
+ tryConvertToDouble(value);
+
+ if (std::holds_alternative<double>(*propertyValue))
+ {
+ if (*propertyValue <= value)
+ {
+ floor = tableFloor;
+ break;
+ }
+ }
+ else if (*propertyValue == value)
{
floor = tableFloor;
break;
}
}
- else if (*propertyValue == value)
+ }
+
+ // No floor found in this group, use a default floor for now but
+ // let keep going in case it finds a higher one.
+ if (!floor)
+ {
+ if (floorTable.defaultFloor)
{
- floor = tableFloor;
- break;
+ floor = *floorTable.defaultFloor;
+ }
+ else if (_defaultFloor)
+ {
+ floor = *_defaultFloor;
+ }
+ else
+ {
+ floor = zone.getDefaultFloor();
}
}
// Keep track of the highest floor value found across all
// entries/groups
- if (floor)
+ if ((newFloor && (floor > *newFloor)) || !newFloor)
{
- if ((newFloor && (floor > *newFloor)) || !newFloor)
- {
- newFloor = floor;
- }
+ newFloor = floor;
}
- else
- {
- // No match found in this group's table.
- // Results in default floor.
- missingGroupProperty = true;
- }
+ }
+
+ // if still no floor, use the default one from the floor table if
+ // there
+ if (!newFloor && floorTable.defaultFloor)
+ {
+ newFloor = floorTable.defaultFloor.value();
}
if (newFloor)
@@ -357,14 +384,12 @@
break;
}
- if (newFloor && !missingGroupProperty)
+ if (!newFloor)
{
- zone.setFloorHold(getUniqueName(), *newFloor, true);
+ newFloor = _defaultFloor ? *_defaultFloor : zone.getDefaultFloor();
}
- else
- {
- zone.setFloorHold(getUniqueName(), zone.getDefaultFloor(), true);
- }
+
+ zone.setFloorHold(getUniqueName(), *newFloor, true);
}
uint64_t MappedFloor::applyFloorOffset(uint64_t floor,
diff --git a/control/json/actions/mapped_floor.hpp b/control/json/actions/mapped_floor.hpp
index fa0e302..6866250 100644
--- a/control/json/actions/mapped_floor.hpp
+++ b/control/json/actions/mapped_floor.hpp
@@ -34,10 +34,12 @@
* {
* "name": "mapped_floor",
* "key_group": "ambient_temp",
+ * "default_floor": 2000,
* "fan_floors": [
* {
* "key": 27,
* "floor_offset_parameter": "floor_27_offset",
+ * "default_floor": 3000,
* "floors": [
* {
* "group": "altitude",
@@ -89,12 +91,15 @@
* - If any group check results doesn't end in a match being found, then
* the default floor will be set.
*
- * Cases where the default floor will be set:
- * - A table entry can't be found based on a key group's value.
- * - A table entry can't be found based on a group's value.
- * - A value can't be obtained for the 'key_group' D-Bus property group.
- * - A value can't be obtained for any of the 'group' property groups.
- * - A value is NaN, as no <, <=, or == checks would succeed.
+ * There are up to 3 default value values that may be used when a regular
+ * floor value can't be calculated:
+ * 1. Optional default floor at the key group level
+ * - Chosen when a floor wasn't found in any floor groups
+ * 2. Optional default floor at the action level
+ * - Chosen when there isn't a key table found for the key value,
+ * or 1. above occurred but that default floor wasn't supplied.
+ * 3. The default floor in the zone config
+ * - Chosen when when 2. would be used, but it wasn't supplied
*
* Other notes:
* - If a group has multiple members, they must be numeric or else
@@ -146,6 +151,13 @@
void setKeyGroup(const json& jsonObj);
/**
+ * @brief Parse and set the default floor value
+ *
+ * @param[in] jsonObj - JSON object for the action
+ */
+ void setDefaultFloor(const json& jsonObj);
+
+ /**
* @brief Parses and sets the floor group data members
*
* @param[in] jsonObj - JSON object for the action
@@ -201,6 +213,9 @@
/* Key group pointer */
const Group* _keyGroup;
+ /* Optional default floor value for the action */
+ std::optional<uint64_t> _defaultFloor;
+
using FloorEntry = std::tuple<PropertyVariantType, uint64_t>;
struct FloorGroup
@@ -213,6 +228,7 @@
{
PropertyVariantType keyValue;
std::string offsetParameter;
+ std::optional<uint64_t> defaultFloor;
std::vector<FloorGroup> floorGroups;
};