Expose power cap min/max on dbus
The min and max power cap values will be read from sysfs files and then
the data will be put on the dbus. This will allow users to know the
valid range of power cap available.
The PowerCap object was moved from Manager to Status.
Change-Id: I5196cc8645f84c31a5282cf844109bae47b09bf7
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/occ_device.hpp b/occ_device.hpp
index 106604e..97bdceb 100644
--- a/occ_device.hpp
+++ b/occ_device.hpp
@@ -11,6 +11,7 @@
#include <filesystem>
#include <fstream>
+#include <regex>
namespace open_power
{
@@ -274,6 +275,25 @@
* @param[in] error - True if an error is reported, false otherwise
*/
void throttleMemTempCallback(bool error);
+
+ /** @brief Get the pathname for a file based on a regular expression
+ *
+ * @param[in] basePath - The path where the files will be checked
+ * @param[in] expr - Regular expression describing the target file
+ *
+ * @return path to the file or empty path if not found
+ */
+ fs::path getFilenameByRegex(fs::path basePath, const std::regex& expr) const
+ {
+ for (auto& file : fs::directory_iterator(basePath))
+ {
+ if (std::regex_search(file.path().string(), expr))
+ {
+ return file;
+ }
+ }
+ return fs::path{};
+ }
};
} // namespace occ
diff --git a/occ_manager.cpp b/occ_manager.cpp
index 26950fd..ea02cf3 100644
--- a/occ_manager.cpp
+++ b/occ_manager.cpp
@@ -151,7 +151,7 @@
if (!pmode)
{
// Create the power mode object
- pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
+ pmode = std::make_unique<powermode::PowerMode>(
*this, powermode::PMODE_PATH, powermode::PIPS_PATH);
}
#endif
@@ -178,13 +178,6 @@
.c_str());
_pollTimer->setEnabled(false);
- // Create the power cap monitor object for master OCC
- if (!pcap)
- {
- pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
- *statusObjects.back());
- }
-
#ifdef POWER10
// Set the master OCC on the PowerMode object
pmode->setMasterOcc(path);
@@ -295,7 +288,6 @@
static_assert(sizeof(DEV_PATH) != 0);
auto deviceNames = i2c_occ::getOccHwmonDevices(DEV_PATH);
- auto occMasterName = deviceNames.front();
for (auto& name : deviceNames)
{
i2c_occ::i2cToDbus(name);
@@ -304,13 +296,9 @@
statusObjects.emplace_back(
std::make_unique<Status>(event, path.c_str(), *this));
}
- // The first device is master occ
- pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
- *statusObjects.front(), occMasterName);
#ifdef POWER10
- pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
- *this, open_power::occ::powermode::PMODE_PATH,
- open_power::occ::powermode::PIPS_PATH);
+ pmode = std::make_unique<powermode::PowerMode>(*this, powermode::PMODE_PATH,
+ powermode::PIPS_PATH);
// Set the master OCC on the PowerMode object
pmode->setMasterOcc(path);
#endif
@@ -496,13 +484,11 @@
for (auto& obj : statusObjects)
{
-#ifdef READ_OCC_SENSORS
- auto id = obj->getOccInstanceID();
-#endif
if (!obj->occActive())
{
// OCC is not running yet
#ifdef READ_OCC_SENSORS
+ auto id = obj->getOccInstanceID();
setSensorValueToNaN(id);
#endif
continue;
@@ -513,7 +499,7 @@
#ifdef READ_OCC_SENSORS
// Read occ sensor values
- getSensorValues(id, obj->isMasterOcc());
+ getSensorValues(obj);
#endif
}
@@ -683,11 +669,11 @@
if (faultValue != 0)
{
- open_power::occ::dbus::OccDBusSensors::getOccDBus().setValue(
+ dbus::OccDBusSensors::getOccDBus().setValue(
sensorPath, std::numeric_limits<double>::quiet_NaN());
- open_power::occ::dbus::OccDBusSensors::getOccDBus()
- .setOperationalStatus(sensorPath, false);
+ dbus::OccDBusSensors::getOccDBus().setOperationalStatus(sensorPath,
+ false);
continue;
}
@@ -707,17 +693,17 @@
continue;
}
- open_power::occ::dbus::OccDBusSensors::getOccDBus().setValue(
+ dbus::OccDBusSensors::getOccDBus().setValue(
sensorPath, tempValue * std::pow(10, -3));
- open_power::occ::dbus::OccDBusSensors::getOccDBus()
- .setOperationalStatus(sensorPath, true);
+ dbus::OccDBusSensors::getOccDBus().setOperationalStatus(sensorPath,
+ true);
// At this point, the sensor will be created for sure.
if (existingSensors.find(sensorPath) == existingSensors.end())
{
- open_power::occ::dbus::OccDBusSensors::getOccDBus()
- .setChassisAssociation(sensorPath);
+ dbus::OccDBusSensors::getOccDBus().setChassisAssociation(
+ sensorPath);
}
existingSensors[sensorPath] = id;
@@ -805,25 +791,25 @@
catch (const std::system_error& e)
{
log<level::DEBUG>(
- fmt::format("readTempSensors: Failed reading {}, errno = {}",
+ fmt::format("readPowerSensors: Failed reading {}, errno = {}",
filePathString + inputSuffix, e.code().value())
.c_str());
continue;
}
- open_power::occ::dbus::OccDBusSensors::getOccDBus().setUnit(
+ dbus::OccDBusSensors::getOccDBus().setUnit(
sensorPath, "xyz.openbmc_project.Sensor.Value.Unit.Watts");
- open_power::occ::dbus::OccDBusSensors::getOccDBus().setValue(
+ dbus::OccDBusSensors::getOccDBus().setValue(
sensorPath, tempValue * std::pow(10, -3) * std::pow(10, -3));
- open_power::occ::dbus::OccDBusSensors::getOccDBus()
- .setOperationalStatus(sensorPath, true);
+ dbus::OccDBusSensors::getOccDBus().setOperationalStatus(sensorPath,
+ true);
if (existingSensors.find(sensorPath) == existingSensors.end())
{
- open_power::occ::dbus::OccDBusSensors::getOccDBus()
- .setChassisAssociation(sensorPath);
+ dbus::OccDBusSensors::getOccDBus().setChassisAssociation(
+ sensorPath);
}
existingSensors[sensorPath] = id;
@@ -837,29 +823,22 @@
{
if (occId == id)
{
- open_power::occ::dbus::OccDBusSensors::getOccDBus().setValue(
+ dbus::OccDBusSensors::getOccDBus().setValue(
sensorPath, std::numeric_limits<double>::quiet_NaN());
}
}
return;
}
-void Manager::getSensorValues(uint32_t id, bool masterOcc)
+void Manager::getSensorValues(std::unique_ptr<Status>& occ)
{
- const auto occ = std::string("occ-hwmon.") + std::to_string(id + 1);
-
- fs::path fileName{OCC_HWMON_PATH + occ + "/hwmon/"};
-
- // Need to get the hwmonXX directory name, there better only be 1 dir
- assert(std::distance(fs::directory_iterator(fileName),
- fs::directory_iterator{}) == 1);
- // Now set our path to this full path, including this hwmonXX directory
- fileName = fs::path(*fs::directory_iterator(fileName));
+ const fs::path fileName = occ->getHwmonPath();
+ const uint32_t id = occ->getOccInstanceID();
// Read temperature sensors
readTempSensors(fileName, id);
- if (masterOcc)
+ if (occ->isMasterOcc())
{
// Read power sensors
readPowerSensors(fileName, id);
@@ -1026,9 +1005,10 @@
int masterInstance = -1;
for (auto& obj : statusObjects)
{
- obj->addPresenceWatchMaster();
if (obj->isMasterOcc())
{
+ obj->addPresenceWatchMaster();
+
if (masterInstance == -1)
{
masterInstance = obj->getOccInstanceID();
diff --git a/occ_manager.hpp b/occ_manager.hpp
index 9a29b8f..fa340b7 100644
--- a/occ_manager.hpp
+++ b/occ_manager.hpp
@@ -7,7 +7,6 @@
#include <libphal.H>
#endif
-#include "powercap.hpp"
#include "utils.hpp"
#ifdef POWER10
#include "powermode.hpp"
@@ -184,9 +183,6 @@
/** @brief OCC Status objects */
std::vector<std::unique_ptr<Status>> statusObjects;
- /** @brief Power cap monitor and occ notification object */
- std::unique_ptr<open_power::occ::powercap::PowerCap> pcap;
-
#ifdef POWER10
/** @brief Power mode monitor and notification object */
std::unique_ptr<open_power::occ::powermode::PowerMode> pmode;
@@ -327,10 +323,9 @@
#ifdef READ_OCC_SENSORS
/**
* @brief Gets the occ sensor values.
- * @param[in] id - Id of the OCC.
- * @param[in] masterOcc - Is this OCC the master OCC.
+ * @param[in] occ - pointer to OCCs Status object
* */
- void getSensorValues(uint32_t id, bool masterOcc);
+ void getSensorValues(std::unique_ptr<Status>& occ);
/**
* @brief Trigger OCC driver to read the temperature sensors.
diff --git a/occ_status.cpp b/occ_status.cpp
index 5abf6dd..ff44c9d 100644
--- a/occ_status.cpp
+++ b/occ_status.cpp
@@ -38,6 +38,17 @@
// Reset last OCC state
lastState = 0;
+ if (device.master())
+ {
+ if (!pcap)
+ {
+ // Create the power cap monitor object for master OCC
+ pcap = std::make_unique<powercap::PowerCap>(*this);
+ }
+ // Update powercap bounds from OCC
+ pcap->updatePcapBounds();
+ }
+
// Call into Manager to let know that we have bound
if (this->managerCallBack)
{
@@ -202,6 +213,13 @@
fmt::format("Status::readOccState: OCC{} state 0x{:02X}",
instance, state)
.c_str());
+ if (state & 0xFFFFFFF8)
+ {
+ log<level::ERR>(
+ fmt::format("Status::readOccState: INVALID STATE from {}!!",
+ filename.c_str())
+ .c_str());
+ }
lastState = state;
#ifdef POWER10
@@ -372,5 +390,19 @@
}
#endif // POWER10
+fs::path Status::getHwmonPath() const
+{
+ using namespace std::literals::string_literals;
+
+ // Build the base HWMON path
+ fs::path prefixPath = fs::path{OCC_HWMON_PATH + "occ-hwmon."s +
+ std::to_string(instance + 1) + "/hwmon/"s};
+ // Get the hwmonXX directory name, there better only be 1 dir
+ assert(std::distance(fs::directory_iterator(prefixPath),
+ fs::directory_iterator{}) == 1);
+
+ return *fs::directory_iterator(prefixPath);
+}
+
} // namespace occ
} // namespace open_power
diff --git a/occ_status.hpp b/occ_status.hpp
index 6dab7dd..0d22c49 100644
--- a/occ_status.hpp
+++ b/occ_status.hpp
@@ -5,6 +5,7 @@
#include "occ_command.hpp"
#include "occ_device.hpp"
#include "occ_events.hpp"
+#include "powercap.hpp"
#include "powermode.hpp"
#include "utils.hpp"
@@ -76,7 +77,7 @@
*/
Status(EventPtr& event, const char* path, Manager& managerRef,
#ifdef POWER10
- std::unique_ptr<open_power::occ::powermode::PowerMode>& powerModeRef,
+ std::unique_ptr<powermode::PowerMode>& powerModeRef,
#endif
std::function<void(bool)> callBack = nullptr
#ifdef PLDM
@@ -199,6 +200,12 @@
const uint16_t altitude = 0xFFFF);
#endif // POWER10
+ /** @brief Return the HWMON path for this OCC
+ *
+ * @return path or empty path if not found
+ */
+ fs::path getHwmonPath() const;
+
private:
/** @brief OCC dbus object path */
std::string path;
@@ -220,9 +227,12 @@
/** @brief OCC manager object */
const Manager& manager;
+ /** @brief Power cap monitor and occ notification object */
+ std::unique_ptr<powercap::PowerCap> pcap;
+
#ifdef POWER10
/** @brief OCC PowerMode object */
- std::unique_ptr<open_power::occ::powermode::PowerMode>& pmode;
+ std::unique_ptr<powermode::PowerMode>& pmode;
#endif
/** @brief OCC device object to do bind and unbind */
diff --git a/powercap.cpp b/powercap.cpp
index 2555d95..cd11059 100644
--- a/powercap.cpp
+++ b/powercap.cpp
@@ -1,10 +1,11 @@
+#include "occ_status.hpp"
+
#include <fmt/core.h>
#include <phosphor-logging/log.hpp>
#include <powercap.hpp>
#include <cassert>
-#include <regex>
namespace open_power
{
@@ -18,10 +19,77 @@
constexpr auto POWER_CAP_PROP = "PowerCap";
constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable";
+constexpr auto POWER_CAP_SOFT_MIN = "MinSoftPowerCapValue";
+constexpr auto POWER_CAP_HARD_MIN = "MinPowerCapValue";
+constexpr auto POWER_CAP_MAX = "MaxPowerCapValue";
using namespace phosphor::logging;
namespace fs = std::filesystem;
+void PowerCap::updatePcapBounds()
+{
+ // Build the hwmon string to write the power cap bounds
+ fs::path minName = getPcapFilename(std::regex{"power\\d+_cap_min$"});
+ fs::path softMinName =
+ getPcapFilename(std::regex{"power\\d+_cap_min_soft$"});
+ fs::path maxName = getPcapFilename(std::regex{"power\\d+_cap_max$"});
+
+ // Read the power cap bounds from sysfs files
+ uint64_t cap;
+ uint32_t capSoftMin = 0, capHardMin = 0, capMax = INT_MAX;
+ std::ifstream softMinFile(softMinName, std::ios::in);
+ if (softMinFile)
+ {
+ softMinFile >> cap;
+ softMinFile.close();
+ // Convert to Watts
+ capSoftMin = cap / 1000000;
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format(
+ "updatePcapBounds: unable to find pcap_min_soft file: {} (errno={})",
+ pcapBasePathname.c_str(), errno)
+ .c_str());
+ }
+ std::ifstream minFile(minName, std::ios::in);
+ if (minFile)
+ {
+ minFile >> cap;
+ minFile.close();
+ // Convert to Watts
+ capHardMin = cap / 1000000;
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format(
+ "updatePcapBounds: unable to find cap_min file: {} (errno={})",
+ pcapBasePathname.c_str(), errno)
+ .c_str());
+ }
+ std::ifstream maxFile(maxName, std::ios::in);
+ if (maxFile)
+ {
+ maxFile >> cap;
+ maxFile.close();
+ // Convert to Watts
+ capMax = cap / 1000000;
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format(
+ "updatePcapBounds: unable to find cap_max file: {} (errno={})",
+ pcapBasePathname.c_str(), errno)
+ .c_str());
+ }
+
+ // Save the bounds to dbus
+ updateDbusPcap(capSoftMin, capHardMin, capMax);
+}
+
uint32_t PowerCap::getOccInput(uint32_t pcap, bool pcapEnabled)
{
if (!pcapEnabled)
@@ -74,56 +142,65 @@
}
}
-std::string PowerCap::getPcapFilename(const fs::path& path)
+fs::path PowerCap::getPcapFilename(const std::regex& expr)
{
- std::regex expr{"power\\d+_cap_user$"};
- for (auto& file : fs::directory_iterator(path))
+ if (pcapBasePathname.empty())
+ {
+ static bool tracedError = false;
+ pcapBasePathname = occStatus.getHwmonPath();
+ if (!fs::exists(pcapBasePathname) && !tracedError)
+ {
+ log<level::ERR>(fmt::format("Power Cap base filename not found: {}",
+ pcapBasePathname.c_str())
+ .c_str());
+ tracedError = true;
+ }
+ }
+ for (auto& file : fs::directory_iterator(pcapBasePathname))
{
if (std::regex_search(file.path().string(), expr))
{
- return file.path().filename();
+ return file;
}
}
- return std::string{};
+ // return empty path
+ return fs::path{};
}
void PowerCap::writeOcc(uint32_t pcapValue)
{
- // Create path out to master occ hwmon entry
- std::unique_ptr<fs::path> fileName =
- std::make_unique<fs::path>(OCC_HWMON_PATH);
- *fileName /= occMasterName;
- *fileName /= "hwmon";
-
- // Need to get the hwmonXX directory name, there better only be 1 dir
- assert(std::distance(fs::directory_iterator(*fileName),
- fs::directory_iterator{}) == 1);
- // Now set our path to this full path, including this hwmonXX directory
- fileName = std::make_unique<fs::path>(*fs::directory_iterator(*fileName));
- // Append on the hwmon string where we write the user power cap
-
- auto baseName = getPcapFilename(*fileName);
- if (baseName.empty())
+ // Build the hwmon string to write the user power cap
+ fs::path fileName = getPcapFilename(std::regex{"power\\d+_cap_user$"});
+ if (fileName.empty())
{
log<level::ERR>(
fmt::format("Could not find a power cap file to write to: {})",
- fileName->c_str())
+ pcapBasePathname.c_str())
.c_str());
return;
}
- *fileName /= baseName;
uint64_t microWatts = pcapValue * 1000000ull;
auto pcapString{std::to_string(microWatts)};
- log<level::INFO>("Writing pcap value to hwmon",
- entry("PCAP_PATH=%s", fileName->c_str()),
- entry("PCAP_VALUE=%s", pcapString.c_str()));
// Open the hwmon file and write the power cap
- std::ofstream file(*fileName, std::ios::out);
- file << pcapString;
- file.close();
+ std::ofstream file(fileName, std::ios::out);
+ if (file)
+ {
+ log<level::INFO>(fmt::format("Writing {}uW to {}", pcapString.c_str(),
+ fileName.c_str())
+ .c_str());
+ file << pcapString;
+ file.close();
+ }
+ else
+ {
+ log<level::ERR>(fmt::format("Failed writing {}uW to {} (errno={})",
+ microWatts, fileName.c_str(), errno)
+ .c_str());
+ }
+
return;
}
@@ -131,7 +208,7 @@
{
if (!occStatus.occActive())
{
- // Nothing to do
+ // Nothing to do
return;
}
@@ -142,43 +219,102 @@
std::map<std::string, std::variant<uint32_t, bool>> msgData;
msg.read(msgSensor, msgData);
- // Retrieve which property changed via the msg and read the other one
- auto valPropMap = msgData.find(POWER_CAP_PROP);
- if (valPropMap != msgData.end())
+ bool changeFound = false;
+ for (const auto& [prop, value] : msgData)
{
- pcap = std::get<uint32_t>(valPropMap->second);
- pcapEnabled = getPcapEnabled();
- }
- else
- {
- valPropMap = msgData.find(POWER_CAP_ENABLE_PROP);
- if (valPropMap != msgData.end())
+ if (prop == POWER_CAP_PROP)
{
- pcapEnabled = std::get<bool>(valPropMap->second);
+ pcap = std::get<uint32_t>(value);
+ pcapEnabled = getPcapEnabled();
+ changeFound = true;
+ }
+ else if (prop == POWER_CAP_ENABLE_PROP)
+ {
+ pcapEnabled = std::get<bool>(value);
pcap = getPcap();
+ changeFound = true;
}
else
{
- log<level::INFO>("Unknown power cap property changed");
- return;
+ // Ignore other properties
+ log<level::DEBUG>(
+ fmt::format(
+ "pcapChanged: Unknown power cap property changed {} to {}",
+ prop.c_str(), std::get<uint32_t>(value))
+ .c_str());
}
}
- log<level::INFO>(
- fmt::format("Power Cap Property Change (cap={}W (input), enabled={})",
- pcap, pcapEnabled ? 'y' : 'n')
- .c_str());
+ if (changeFound)
+ {
+ log<level::INFO>(
+ fmt::format(
+ "Power Cap Property Change (cap={}W (input), enabled={})", pcap,
+ pcapEnabled ? 'y' : 'n')
+ .c_str());
- // Determine desired action to write to occ
+ // Determine desired action to write to occ
- auto occInput = getOccInput(pcap, pcapEnabled);
+ auto occInput = getOccInput(pcap, pcapEnabled);
- // Write action to occ
- writeOcc(occInput);
+ // Write action to occ
+ writeOcc(occInput);
+ }
return;
}
+// Update the Power Cap bounds on DBus
+bool PowerCap::updateDbusPcap(uint32_t softMin, uint32_t hardMin, uint32_t max)
+{
+ bool complete = true;
+
+ try
+ {
+ utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_SOFT_MIN,
+ softMin);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "updateDbusPcap: Failed to set SOFT PCAP to {}W due to {}",
+ softMin, e.what())
+ .c_str());
+ complete = false;
+ }
+
+ try
+ {
+ utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_HARD_MIN,
+ hardMin);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "updateDbusPcap: Failed to set HARD PCAP to {}W due to {}",
+ hardMin, e.what())
+ .c_str());
+ complete = false;
+ }
+
+ try
+ {
+ utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_MAX, max);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "updateDbusPcap: Failed to set MAX PCAP to {}W due to {}", max,
+ e.what())
+ .c_str());
+ complete = false;
+ }
+
+ return complete;
+}
} // namespace powercap
} // namespace occ
diff --git a/powercap.hpp b/powercap.hpp
index 6dab352..34df45f 100644
--- a/powercap.hpp
+++ b/powercap.hpp
@@ -2,22 +2,25 @@
#include "config.h"
-#include "occ_status.hpp"
#include "utils.hpp"
#include <sdbusplus/bus.hpp>
#include <sdbusplus/bus/match.hpp>
#include <filesystem>
+#include <regex>
namespace open_power
{
namespace occ
{
+class Status;
+
namespace powercap
{
namespace sdbusRule = sdbusplus::bus::match::rules;
+namespace fs = std::filesystem;
/** @class PowerCap
* @brief Monitors for changes to the power cap and notifies occ
@@ -38,9 +41,7 @@
*
* @param[in] occStatus - The occ status object
*/
- explicit PowerCap(Status& occStatus,
- const std::string& occMasterName = OCC_MASTER_NAME) :
- occMasterName(occMasterName),
+ explicit PowerCap(Status& occStatus) :
occStatus(occStatus),
pcapMatch(
utils::getBus(),
@@ -61,6 +62,9 @@
*/
uint32_t getOccInput(uint32_t pcap, bool pcapEnabled);
+ /** @brief Read the power cap bounds from sysfs and update DBus */
+ void updatePcapBounds();
+
private:
/** @brief Callback for pcap setting changes
*
@@ -95,20 +99,30 @@
* The file is of the form "powerX_cap_user", where X is any
* number.
*
- * @param[in] path - The directory to look for the file in
+ * @param[in] expr - Regular expression of file to find
*
- * @return std::string - The filename, or empty string if not found.
+ * @return full path/filename, or empty path if not found.
*/
- std::string getPcapFilename(const std::filesystem::path& path);
-
- /** @brief The master occ name */
- std::string occMasterName;
+ fs::path getPcapFilename(const std::regex& expr);
/* @brief OCC Status object */
Status& occStatus;
/** @brief Used to subscribe to dbus pcap property changes **/
sdbusplus::bus::match_t pcapMatch;
+
+ /** @brief Path to the sysfs files holding the cap properties **/
+ fs::path pcapBasePathname;
+
+ /** @brief Update the power cap bounds on DBus
+ *
+ * @param[in] softMin - soft minimum power cap in Watts
+ * @param[in] hardMin - hard minimum power cap in Watts
+ * @param[in] pcapMax - maximum power cap in Watts
+ *
+ * @return true if all parms were written successfully
+ */
+ bool updateDbusPcap(uint32_t softMin, uint32_t hardMin, uint32_t pcapMax);
};
} // namespace powercap
diff --git a/utils.cpp b/utils.cpp
index e9ccc88..e79bc5a 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -78,10 +78,10 @@
* @param[in] value - Property value
*/
void setProperty(const std::string& objectPath, const std::string& interface,
- const std::string& propertyName, std::string&& value)
+ const std::string& propertyName, PropertyValue&& value)
{
using namespace std::literals::string_literals;
- std::variant<std::string> varValue(std::forward<std::string>(value));
+ PropertyValue varValue(std::forward<PropertyValue>(value));
try
{
diff --git a/utils.hpp b/utils.hpp
index 2b4b897..5033222 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -19,7 +19,7 @@
constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
// The value of the property(type: variant, contains some basic types)
-using PropertyValue = std::variant<uint32_t, bool, double>;
+using PropertyValue = std::variant<uint32_t, bool, double, std::string>;
/** @brief Get the bus connection. */
static auto& getBus()
@@ -63,7 +63,7 @@
* @param[in] value - Property value
*/
void setProperty(const std::string& objectPath, const std::string& interface,
- const std::string& propertyName, std::string&& value);
+ const std::string& propertyName, PropertyValue&& value);
/** @brief Get subtree paths
*