utils: Add setProperty support

Signed-off-by: Lei YU <yulei.sh@bytedance.com>
Change-Id: Iac2c5b90a4a8ed07210a564dbd6048c37b5e34c3
diff --git a/src/utils.cpp b/src/utils.cpp
index 70a4e61..f745a26 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -91,4 +91,24 @@
     }
 }
 
+void Utils::setPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
+                            const char* path, const char* interface,
+                            const char* propertyName, ValueType&& value) const
+{
+    auto method = bus.new_method_call(service, path,
+                                      "org.freedesktop.DBus.Properties", "Set");
+    method.append(interface, propertyName, value);
+    try
+    {
+        bus.call_noreply(method);
+    }
+    catch (const sdbusplus::exception::SdBusError& ex)
+    {
+        log<level::ERR>("SetProperty call failed", entry("PATH=%s", path),
+                        entry("INTERFACE=%s", interface),
+                        entry("PROPERTY=%s", propertyName));
+        throw std::runtime_error("SetProperty call failed");
+    }
+}
+
 } // namespace utils
diff --git a/src/utils.hpp b/src/utils.hpp
index d382bf9..fafd646 100644
--- a/src/utils.hpp
+++ b/src/utils.hpp
@@ -17,6 +17,9 @@
 using std::experimental::any;
 using std::experimental::any_cast;
 
+using ValueType =
+    std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
+                 uint64_t, double, std::string>;
 /**
  * @brief Get the implementation of UtilsInterface
  */
@@ -58,6 +61,11 @@
 T getProperty(sdbusplus::bus::bus& bus, const char* service, const char* path,
               const char* interface, const char* propertyName);
 
+template <typename T>
+void setProperty(sdbusplus::bus::bus& bus, const char* service,
+                 const char* path, const char* interface,
+                 const char* propertyName, const T& value);
+
 /**
  * @brief The interface for utils
  */
@@ -80,6 +88,11 @@
                                 const char* path, const char* interface,
                                 const char* propertyName) const = 0;
 
+    virtual void setPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
+                                 const char* path, const char* interface,
+                                 const char* propertyName,
+                                 ValueType&& value) const = 0;
+
     template <typename T>
     T getProperty(sdbusplus::bus::bus& bus, const char* service,
                   const char* path, const char* interface,
@@ -90,6 +103,16 @@
         auto value = any_cast<PropertyType>(result);
         return std::get<T>(value);
     }
+
+    template <typename T>
+    void setProperty(sdbusplus::bus::bus& bus, const char* service,
+                     const char* path, const char* interface,
+                     const char* propertyName, const T& value) const
+    {
+        ValueType v(value);
+        setPropertyImpl(bus, service, path, interface, propertyName,
+                        std::move(v));
+    }
 };
 
 class Utils : public UtilsInterface
@@ -105,6 +128,11 @@
     any getPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
                         const char* path, const char* interface,
                         const char* propertyName) const override;
+
+    void setPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
+                         const char* path, const char* interface,
+                         const char* propertyName,
+                         ValueType&& value) const override;
 };
 
 inline std::string getService(sdbusplus::bus::bus& bus, const char* path,
@@ -128,4 +156,13 @@
                                      propertyName);
 }
 
+template <typename T>
+void setProperty(sdbusplus::bus::bus& bus, const char* service,
+                 const char* path, const char* interface,
+                 const char* propertyName, const T& value)
+{
+    return getUtils().setProperty<T>(bus, service, path, interface,
+                                     propertyName, value);
+}
+
 } // namespace utils