xref: /openbmc/entity-manager/src/entity_manager/dbus_interface.hpp (revision a182cb7c338c70e65bf6f8a828cb7176ffde152d)
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     boost::asio::io_context& io;
59     sdbusplus::asio::object_server& objServer;
60 
61     boost::container::flat_map<
62         std::string,
63         std::vector<std::weak_ptr<sdbusplus::asio::dbus_interface>>>
64         inventory;
65 };
66 
67 void tryIfaceInitialize(
68     std::shared_ptr<sdbusplus::asio::dbus_interface>& iface);
69 
70 template <typename PropertyType>
71 void addArrayToDbus(const std::string& name, const nlohmann::json& array,
72                     sdbusplus::asio::dbus_interface* iface,
73                     sdbusplus::asio::PropertyPermission permission,
74                     nlohmann::json& systemConfiguration,
75                     const std::string& jsonPointerString)
76 {
77     std::vector<PropertyType> values;
78     for (const auto& property : array)
79     {
80         auto ptr = property.get_ptr<const PropertyType*>();
81         if (ptr != nullptr)
82         {
83             values.emplace_back(*ptr);
84         }
85     }
86 
87     if (permission == sdbusplus::asio::PropertyPermission::readOnly)
88     {
89         iface->register_property(name, values);
90     }
91     else
92     {
93         iface->register_property(
94             name, values,
95             [&systemConfiguration,
96              jsonPointerString{std::string(jsonPointerString)}](
97                 const std::vector<PropertyType>& newVal,
98                 std::vector<PropertyType>& val) {
99                 val = newVal;
100                 if (!setJsonFromPointer(jsonPointerString, val,
101                                         systemConfiguration))
102                 {
103                     lg2::error("error setting json field");
104                     return -1;
105                 }
106                 if (!writeJsonFiles(systemConfiguration))
107                 {
108                     lg2::error("error setting json file");
109                     return -1;
110                 }
111                 return 1;
112             });
113     }
114 }
115 
116 template <typename PropertyType>
117 void addProperty(const std::string& name, const PropertyType& value,
118                  sdbusplus::asio::dbus_interface* iface,
119                  nlohmann::json& systemConfiguration,
120                  const std::string& jsonPointerString,
121                  sdbusplus::asio::PropertyPermission permission)
122 {
123     if (permission == sdbusplus::asio::PropertyPermission::readOnly)
124     {
125         iface->register_property(name, value);
126         return;
127     }
128     iface->register_property(
129         name, value,
130         [&systemConfiguration,
131          jsonPointerString{std::string(jsonPointerString)}](
132             const PropertyType& newVal, PropertyType& val) {
133             val = newVal;
134             if (!setJsonFromPointer(jsonPointerString, val,
135                                     systemConfiguration))
136             {
137                 lg2::error("error setting json field");
138                 return -1;
139             }
140             if (!writeJsonFiles(systemConfiguration))
141             {
142                 lg2::error("error setting json file");
143                 return -1;
144             }
145             return 1;
146         });
147 }
148 
149 template <typename PropertyType>
150 void addValueToDBus(const std::string& key, const nlohmann::json& value,
151                     sdbusplus::asio::dbus_interface& iface,
152                     sdbusplus::asio::PropertyPermission permission,
153                     nlohmann::json& systemConfiguration,
154                     const std::string& path)
155 {
156     if (value.is_array())
157     {
158         addArrayToDbus<PropertyType>(key, value, &iface, permission,
159                                      systemConfiguration, path);
160     }
161     else
162     {
163         addProperty(key, value.get<PropertyType>(), &iface, systemConfiguration,
164                     path, sdbusplus::asio::PropertyPermission::readOnly);
165     }
166 }
167 
168 } // namespace dbus_interface
169