blob: 9223264d497a022a4aa0948ff4982a67faf9fbb0 [file] [log] [blame]
Ed Tanous828c5a62024-02-09 16:59:22 -08001#include "IpmbSDRSensor.hpp"
2#include "IpmbSensor.hpp"
3#include "Utils.hpp"
4
5#include <boost/asio/error.hpp>
6#include <boost/asio/io_context.hpp>
7#include <boost/asio/post.hpp>
8#include <boost/asio/steady_timer.hpp>
9#include <boost/container/flat_map.hpp>
10#include <sdbusplus/asio/connection.hpp>
11#include <sdbusplus/asio/object_server.hpp>
12#include <sdbusplus/bus.hpp>
13#include <sdbusplus/bus/match.hpp>
14#include <sdbusplus/message.hpp>
15
16#include <array>
17#include <chrono>
18#include <cstddef>
19#include <cstdint>
20#include <functional>
21#include <iostream>
22#include <memory>
23#include <string>
24#include <variant>
25#include <vector>
26
27std::unique_ptr<boost::asio::steady_timer> initCmdTimer;
28boost::container::flat_map<std::string, std::shared_ptr<IpmbSensor>> sensors;
29boost::container::flat_map<uint8_t, std::shared_ptr<IpmbSDRDevice>> sdrsensor;
30
31void sdrHandler(
32 boost::container::flat_map<uint8_t, std::shared_ptr<IpmbSDRDevice>>
33 sdrsensor,
34 sdbusplus::message_t& message,
35 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
36{
37 std::string objectName;
38 SensorBaseConfigMap values;
39 message.read(objectName, values);
40
41 auto findBus = values.find("Bus");
42 if (findBus == values.end())
43 {
44 return;
45 }
46
47 uint8_t busIndex = loadVariant<uint8_t>(values, "Bus");
48
49 auto& sdrsen = sdrsensor[busIndex];
50 sdrsen = nullptr;
51 sdrsen = std::make_shared<IpmbSDRDevice>(dbusConnection, busIndex);
52 sdrsen->getSDRRepositoryInfo();
53}
54
55void reinitSensors(sdbusplus::message_t& message)
56{
57 constexpr const size_t reinitWaitSeconds = 2;
58 std::string objectName;
59 boost::container::flat_map<std::string, std::variant<std::string>> values;
60 message.read(objectName, values);
61
62 auto findStatus = values.find(power::property);
63 if (findStatus != values.end())
64 {
65 bool powerStatus =
66 std::get<std::string>(findStatus->second).ends_with(".Running");
67 if (powerStatus)
68 {
69 if (!initCmdTimer)
70 {
71 // this should be impossible
72 return;
73 }
74 // we seem to send this command too fast sometimes, wait before
75 // sending
76 initCmdTimer->expires_after(
77 std::chrono::seconds(reinitWaitSeconds));
78
79 initCmdTimer->async_wait([](const boost::system::error_code ec) {
80 if (ec == boost::asio::error::operation_aborted)
81 {
82 return; // we're being canceled
83 }
84
85 for (const auto& [name, sensor] : sensors)
86 {
87 if (sensor)
88 {
89 sensor->runInitCmd();
90 }
91 }
92 });
93 }
94 }
95}
96
97int main()
98{
99 boost::asio::io_context io;
100 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
101 sdbusplus::asio::object_server objectServer(systemBus, true);
102 objectServer.add_manager("/xyz/openbmc_project/sensors");
103 systemBus->request_name("xyz.openbmc_project.IpmbSensor");
104
105 initCmdTimer = std::make_unique<boost::asio::steady_timer>(io);
106
107 boost::asio::post(
108 io, [&]() { createSensors(io, objectServer, sensors, systemBus); });
109
110 boost::asio::steady_timer configTimer(io);
111
112 std::function<void(sdbusplus::message_t&)> eventHandler =
113 [&](sdbusplus::message_t&) {
114 configTimer.expires_after(std::chrono::seconds(1));
115 // create a timer because normally multiple properties change
116 configTimer.async_wait([&](const boost::system::error_code& ec) {
117 if (ec == boost::asio::error::operation_aborted)
118 {
119 return; // we're being canceled
120 }
121 createSensors(io, objectServer, sensors, systemBus);
122 if (sensors.empty())
123 {
124 std::cout << "Configuration not detected\n";
125 }
126 });
127 };
128
129 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
130 setupPropertiesChangedMatches(
131 *systemBus, std::to_array<const char*>({sensorType}), eventHandler);
132
133 sdbusplus::bus::match_t powerChangeMatch(
134 static_cast<sdbusplus::bus_t&>(*systemBus),
135 "type='signal',interface='" + std::string(properties::interface) +
136 "',path='" + std::string(power::path) + "',arg0='" +
137 std::string(power::interface) + "'",
138 reinitSensors);
139
140 auto matchSignal = std::make_shared<sdbusplus::bus::match_t>(
141 static_cast<sdbusplus::bus_t&>(*systemBus),
142 "type='signal',member='PropertiesChanged',path_namespace='" +
143 std::string(inventoryPath) + "',arg0namespace='" +
144 configInterfaceName(sdrInterface) + "'",
145 [&systemBus](sdbusplus::message_t& msg) {
146 sdrHandler(sdrsensor, msg, systemBus);
147 });
148
149 // Watch for entity-manager to remove configuration interfaces
150 // so the corresponding sensors can be removed.
151 auto ifaceRemovedMatch = std::make_shared<sdbusplus::bus::match_t>(
152 static_cast<sdbusplus::bus_t&>(*systemBus),
153 "type='signal',member='InterfacesRemoved',arg0path='" +
154 std::string(inventoryPath) + "/'",
155 [](sdbusplus::message_t& msg) { interfaceRemoved(msg, sensors); });
156
157 setupManufacturingModeMatch(*systemBus);
158 io.run();
159 return 0;
160}