xref: /openbmc/entity-manager/src/entity_manager/dbus_interface.hpp (revision 7d5f205fc506952c7413940aed33db52babf9ddd)
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