control: Complete zone configuration parsing
Zone configurations include the ability to configure any properties that
are served by interfaces on each zone object configured. These
properties can optionally be set to values provided within the JSON
configuration per zone along with whether they should be persisted or
not.
Tested:
Zone objects created for each entry in "zones.json"
A "zones.json" configuration is required
Each supported attribute is parsed and stored on each zone object
Zone interfaces/properties are parse and stored per zone object
Change-Id: I2220f3b0a37d166bfff5c1c17acaedc9552a54a0
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/zone.cpp b/control/json/zone.cpp
index 24dceee..84f9c82 100644
--- a/control/json/zone.cpp
+++ b/control/json/zone.cpp
@@ -19,12 +19,23 @@
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
+#include <any>
+#include <iterator>
+#include <map>
+#include <numeric>
+#include <tuple>
+#include <utility>
+
namespace phosphor::fan::control::json
{
using json = nlohmann::json;
using namespace phosphor::logging;
+const std::map<std::string, propertyHandler> Zone::_props = {
+ {"Supported", zone::property::supported},
+ {"Current", zone::property::current}};
+
Zone::Zone(sdbusplus::bus::bus& bus, const json& jsonObj) :
ConfigBase(jsonObj), _incDelay(0)
{
@@ -43,6 +54,11 @@
setFullSpeed(jsonObj);
setDefaultFloor(jsonObj);
setDecInterval(jsonObj);
+ // Setting properties on interfaces to be served are optional
+ if (jsonObj.contains("interfaces"))
+ {
+ setInterfaces(jsonObj);
+ }
}
void Zone::setFullSpeed(const json& jsonObj)
@@ -78,4 +94,85 @@
_decInterval = jsonObj["decrease_interval"].get<uint64_t>();
}
+void Zone::setInterfaces(const json& jsonObj)
+{
+ for (const auto& interface : jsonObj["interfaces"])
+ {
+ if (!interface.contains("name") || !interface.contains("properties"))
+ {
+ log<level::ERR>("Missing required zone interface attributes",
+ entry("JSON=%s", interface.dump().c_str()));
+ throw std::runtime_error(
+ "Missing required zone interface attributes");
+ }
+ std::map<std::string, std::tuple<std::any, bool>> props;
+ for (const auto& property : interface["properties"])
+ {
+ if (!property.contains("name"))
+ {
+ log<level::ERR>(
+ "Missing required interface property attributes",
+ entry("JSON=%s", property.dump().c_str()));
+ throw std::runtime_error(
+ "Missing required interface property attributes");
+ }
+ // Attribute "persist" is optional, defaults to `false`
+ auto persist = false;
+ if (property.contains("persist"))
+ {
+ persist = property["persist"].get<bool>();
+ }
+ // Property name from JSON must exactly match supported
+ // index names to functions in property namespace
+ auto prop = property["name"].get<std::string>();
+ auto propFunc = _props.find(prop);
+ if (propFunc != _props.end())
+ {
+ auto value = propFunc->second(property);
+ props.emplace(prop, std::make_tuple(value, persist));
+ }
+ else
+ {
+ // Construct list of available properties
+ auto props = std::accumulate(
+ std::next(_props.begin()), _props.end(),
+ _props.begin()->first, [](auto list, auto prop) {
+ return std::move(list) + ", " + prop.first;
+ });
+ log<level::ERR>("Configured property function not available",
+ entry("JSON=%s", property.dump().c_str()),
+ entry("AVAILABLE_PROPS=%s", props.c_str()));
+ throw std::runtime_error(
+ "Configured property function not available");
+ }
+ }
+ _interfaces.emplace(interface["name"].get<std::string>(), props);
+ }
+}
+
+/**
+ * Properties of interfaces supported by the zone configuration
+ */
+namespace zone::property
+{
+// Get an any object for the configured value of the "Supported" property
+std::any supported(const json& jsonObj)
+{
+ std::vector<std::string> values;
+ for (const auto& value : jsonObj["values"])
+ {
+ values.emplace_back(value["value"].get<std::string>());
+ }
+
+ return std::make_any<std::vector<std::string>>(values);
+}
+
+// Get an any object for the configured value of the "Current" property
+std::any current(const json& jsonObj)
+{
+ auto value = jsonObj["value"].get<std::string>();
+ return std::make_any<std::string>(value);
+}
+} // namespace zone::property
+
} // namespace phosphor::fan::control::json