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