control: Add all fan functionality to JSON fan object
In transitioning to JSON based configuration support, the objects
created based on the JSON will eventually replace the similar objects
used for YAML based configurations. This adds all the functionality from
the current fan class used for YAML configs to the fan class used for
JSON configs.
Change-Id: I50bdd218fc964a4b75126643727f1c3f4d27966b
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/fan.cpp b/control/json/fan.cpp
index 7a65da1..008bca5 100644
--- a/control/json/fan.cpp
+++ b/control/json/fan.cpp
@@ -15,6 +15,10 @@
*/
#include "fan.hpp"
+#include "sdbusplus.hpp"
+
+#include <fmt/format.h>
+
#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
@@ -25,7 +29,11 @@
using json = nlohmann::json;
using namespace phosphor::logging;
-Fan::Fan(sdbusplus::bus::bus& bus, const json& jsonObj) : ConfigBase(jsonObj)
+constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
+constexpr auto FAN_TARGET_PROPERTY = "Target";
+
+Fan::Fan(sdbusplus::bus::bus& bus, const json& jsonObj) :
+ ConfigBase(jsonObj), _bus(bus)
{
if (jsonObj.contains("profiles"))
{
@@ -34,9 +42,45 @@
_profiles.emplace_back(profile.get<std::string>());
}
}
- setZone(jsonObj);
- setSensors(jsonObj);
setInterface(jsonObj);
+ setSensors(jsonObj);
+ setZone(jsonObj);
+}
+
+void Fan::setInterface(const json& jsonObj)
+{
+ if (!jsonObj.contains("target_interface"))
+ {
+ log<level::ERR>("Missing required fan sensor target interface",
+ entry("JSON=%s", jsonObj.dump().c_str()));
+ throw std::runtime_error(
+ "Missing required fan sensor target interface");
+ }
+ _interface = jsonObj["target_interface"].get<std::string>();
+}
+
+void Fan::setSensors(const json& jsonObj)
+{
+ if (!jsonObj.contains("sensors"))
+ {
+ log<level::ERR>("Missing required fan sensors list",
+ entry("JSON=%s", jsonObj.dump().c_str()));
+ throw std::runtime_error("Missing required fan sensors list");
+ }
+ std::string path;
+ for (const auto& sensor : jsonObj["sensors"])
+ {
+ path = FAN_SENSOR_PATH + sensor.get<std::string>();
+ auto service = util::SDBusPlus::getService(_bus, path, _interface);
+ _sensors[path] = service;
+ }
+ // All sensors associated with this fan are set to the same target speed,
+ // so only need to read target property from one of them
+ if (!path.empty())
+ {
+ _target = util::SDBusPlus::getProperty<uint64_t>(
+ _bus, _sensors.at(path), path, _interface, FAN_TARGET_PROPERTY);
+ }
}
void Fan::setZone(const json& jsonObj)
@@ -50,30 +94,25 @@
_zone = jsonObj["zone"].get<std::string>();
}
-void Fan::setSensors(const json& jsonObj)
+void Fan::setTarget(uint64_t target)
{
- if (!jsonObj.contains("sensors"))
+ for (const auto& sensor : _sensors)
{
- log<level::ERR>("Missing required fan sensors list",
- entry("JSON=%s", jsonObj.dump().c_str()));
- throw std::runtime_error("Missing required fan sensors list");
+ auto value = target;
+ try
+ {
+ util::SDBusPlus::setProperty<uint64_t>(
+ _bus, sensor.second, sensor.first, _interface,
+ FAN_TARGET_PROPERTY, std::move(value));
+ }
+ catch (const sdbusplus::exception::SdBusError&)
+ {
+ throw util::DBusPropertyError{
+ fmt::format("Failed to set target for fan {}", _name).c_str(),
+ sensor.second, sensor.first, _interface, FAN_TARGET_PROPERTY};
+ }
}
- for (const auto& sensor : jsonObj["sensors"])
- {
- _sensors.emplace_back(sensor.get<std::string>());
- }
-}
-
-void Fan::setInterface(const json& jsonObj)
-{
- if (!jsonObj.contains("target_interface"))
- {
- log<level::ERR>("Missing required fan sensor target interface",
- entry("JSON=%s", jsonObj.dump().c_str()));
- throw std::runtime_error(
- "Missing required fan sensor target interface");
- }
- _interface = jsonObj["target_interface"].get<std::string>();
+ _target = target;
}
} // namespace phosphor::fan::control::json