1 #pragma once 2 3 #include "configuration.hpp" 4 5 #include <boost/asio/io_context.hpp> 6 #include <nlohmann/json.hpp> 7 #include <phosphor-logging/lg2.hpp> 8 #include <sdbusplus/asio/connection.hpp> 9 #include <sdbusplus/asio/object_server.hpp> 10 11 #include <flat_map> 12 #include <vector> 13 14 namespace dbus_interface 15 { 16 17 using JsonVariantType = 18 std::variant<std::vector<std::string>, std::vector<double>, std::string, 19 int64_t, uint64_t, double, int32_t, uint32_t, int16_t, 20 uint16_t, uint8_t, bool>; 21 22 class EMDBusInterface 23 { 24 public: 25 EMDBusInterface(boost::asio::io_context& io, 26 sdbusplus::asio::object_server& objServer, 27 const std::filesystem::path& schemaDirectory); 28 29 std::shared_ptr<sdbusplus::asio::dbus_interface> createInterface( 30 const std::string& path, const std::string& interface, 31 const std::string& parent, bool checkNull = false); 32 33 std::vector<std::weak_ptr<sdbusplus::asio::dbus_interface>>& 34 getDeviceInterfaces(const nlohmann::json& device); 35 36 void createAddObjectMethod(const std::string& jsonPointerPath, 37 const std::string& path, 38 nlohmann::json& systemConfiguration, 39 const std::string& board); 40 41 void populateInterfaceFromJson( 42 nlohmann::json& systemConfiguration, const std::string& jsonPointerPath, 43 std::shared_ptr<sdbusplus::asio::dbus_interface>& iface, 44 nlohmann::json& dict, 45 sdbusplus::asio::PropertyPermission permission = 46 sdbusplus::asio::PropertyPermission::readOnly); 47 48 void createDeleteObjectMethod( 49 const std::string& jsonPointerPath, 50 const std::shared_ptr<sdbusplus::asio::dbus_interface>& iface, 51 nlohmann::json& systemConfiguration); 52 53 private: 54 void addObject( 55 const std::flat_map<std::string, JsonVariantType, std::less<>>& data, 56 nlohmann::json& systemConfiguration, const std::string& jsonPointerPath, 57 const std::string& path, const std::string& board); 58 59 // @brief: same as 'addObject', but operates on json 60 void addObjectJson(nlohmann::json& newData, 61 nlohmann::json& systemConfiguration, 62 const std::string& jsonPointerPath, 63 const std::string& path, const std::string& board); 64 65 boost::asio::io_context& io; 66 sdbusplus::asio::object_server& objServer; 67 68 std::flat_map<std::string, 69 std::vector<std::weak_ptr<sdbusplus::asio::dbus_interface>>, 70 std::less<>> 71 inventory; 72 73 const std::filesystem::path schemaDirectory; 74 }; 75 76 void tryIfaceInitialize( 77 std::shared_ptr<sdbusplus::asio::dbus_interface>& iface); 78 79 template <typename PropertyType> 80 void addArrayToDbus(const std::string& name, const nlohmann::json& array, 81 sdbusplus::asio::dbus_interface* iface, 82 sdbusplus::asio::PropertyPermission permission, 83 nlohmann::json& systemConfiguration, 84 const std::string& jsonPointerString) 85 { 86 std::vector<PropertyType> values; 87 for (const auto& property : array) 88 { 89 auto ptr = property.get_ptr<const PropertyType*>(); 90 if (ptr != nullptr) 91 { 92 values.emplace_back(*ptr); 93 } 94 } 95 96 if (permission == sdbusplus::asio::PropertyPermission::readOnly) 97 { 98 iface->register_property(name, values); 99 } 100 else 101 { 102 iface->register_property( 103 name, values, 104 [&systemConfiguration, 105 jsonPointerString{std::string(jsonPointerString)}]( 106 const std::vector<PropertyType>& newVal, 107 std::vector<PropertyType>& val) { 108 val = newVal; 109 if (!setJsonFromPointer(jsonPointerString, val, 110 systemConfiguration)) 111 { 112 lg2::error("error setting json field"); 113 return -1; 114 } 115 if (!writeJsonFiles(systemConfiguration)) 116 { 117 lg2::error("error setting json file"); 118 return -1; 119 } 120 return 1; 121 }); 122 } 123 } 124 125 template <typename PropertyType> 126 void addProperty(const std::string& name, const PropertyType& value, 127 sdbusplus::asio::dbus_interface* iface, 128 nlohmann::json& systemConfiguration, 129 const std::string& jsonPointerString, 130 sdbusplus::asio::PropertyPermission permission) 131 { 132 if (permission == sdbusplus::asio::PropertyPermission::readOnly) 133 { 134 iface->register_property(name, value); 135 return; 136 } 137 iface->register_property( 138 name, value, 139 [&systemConfiguration, 140 jsonPointerString{std::string(jsonPointerString)}]( 141 const PropertyType& newVal, PropertyType& val) { 142 val = newVal; 143 if (!setJsonFromPointer(jsonPointerString, val, 144 systemConfiguration)) 145 { 146 lg2::error("error setting json field"); 147 return -1; 148 } 149 if (!writeJsonFiles(systemConfiguration)) 150 { 151 lg2::error("error setting json file"); 152 return -1; 153 } 154 return 1; 155 }); 156 } 157 158 template <typename PropertyType> 159 void addValueToDBus(const std::string& key, const nlohmann::json& value, 160 sdbusplus::asio::dbus_interface& iface, 161 sdbusplus::asio::PropertyPermission permission, 162 nlohmann::json& systemConfiguration, 163 const std::string& path) 164 { 165 if (value.is_array()) 166 { 167 addArrayToDbus<PropertyType>(key, value, &iface, permission, 168 systemConfiguration, path); 169 } 170 else 171 { 172 addProperty(key, value.get<PropertyType>(), &iface, systemConfiguration, 173 path, sdbusplus::asio::PropertyPermission::readOnly); 174 } 175 } 176 177 } // namespace dbus_interface 178