1 #pragma once
2
3 #include "configuration.hpp"
4
5 #include <boost/container/flat_map.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 boost::container::flat_map<
69 std::string,
70 std::vector<std::weak_ptr<sdbusplus::asio::dbus_interface>>>
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>
addArrayToDbus(const std::string & name,const nlohmann::json & array,sdbusplus::asio::dbus_interface * iface,sdbusplus::asio::PropertyPermission permission,nlohmann::json & systemConfiguration,const std::string & jsonPointerString)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>
addProperty(const std::string & name,const PropertyType & value,sdbusplus::asio::dbus_interface * iface,nlohmann::json & systemConfiguration,const std::string & jsonPointerString,sdbusplus::asio::PropertyPermission permission)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>
addValueToDBus(const std::string & key,const nlohmann::json & value,sdbusplus::asio::dbus_interface & iface,sdbusplus::asio::PropertyPermission permission,nlohmann::json & systemConfiguration,const std::string & path)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