#include <CLI/App.hpp> #include <CLI/Config.hpp> #include <CLI/Formatter.hpp> #include <boost/asio/steady_timer.hpp> #include <chrono> #include <functional> #include <iostream> #include <memory> #include <sdbusplus/asio/connection.hpp> #include <sdbusplus/asio/object_server.hpp> boost::asio::io_context io; std::vector<std::shared_ptr<sdbusplus::asio::dbus_interface>> sensorInterfaces; int update_interval_seconds = 1; size_t reads = 0; void on_loop(boost::asio::steady_timer *timer, const boost::system::error_code &error) { if (error) { return; } std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); static double value = -100.0; for (auto &sensor : sensorInterfaces) { if (!sensor->set_property("Value", value)) { std::cout << "Can't set property for sensor\n"; } value += 10.0; if (value >= 100.0) { value = -100.0; } } if (!sensorInterfaces.empty()) { std::cout << sensorInterfaces.size() << " updates took " << std::chrono::duration_cast<std::chrono::duration<float>>( std::chrono::steady_clock::now() - start) .count() << " seconds\n"; } if (reads > 0) { std::cout << "Read " << reads << " sensor updates\n"; reads = 0; } timer->expires_from_now(std::chrono::seconds(update_interval_seconds)); timer->async_wait(std::bind_front(on_loop, timer)); }; int main(int argc, const char **argv) { CLI::App app{"dbus performance test application"}; size_t number_of_sensors = 0; app.add_option("-n", number_of_sensors, "Number of sensors to create"); bool watch_sensor_updates = false; app.add_flag("-w", watch_sensor_updates, "Watch for all sensor values from dbus"); CLI11_PARSE(app, argc, argv); if (number_of_sensors == 0 && watch_sensor_updates == false) { std::cout << "Nothing to do\n"; app.exit(CLI::CallForHelp()); return -1; } std::shared_ptr<sdbusplus::asio::connection> connection = std::make_shared<sdbusplus::asio::connection>(io); sdbusplus::asio::object_server objectServer(connection); std::string name = "foobar"; sensorInterfaces.reserve(number_of_sensors); for (size_t sensorIndex = 0; sensorIndex < number_of_sensors; sensorIndex++) { sdbusplus::message::object_path path( "/xyz/openbmc_project/sensors/temperature/"); path /= name + std::to_string(sensorIndex); std::shared_ptr<sdbusplus::asio::dbus_interface> sensorInterface = objectServer.add_interface(path.str, "xyz.openbmc_project.Sensor.Value"); sensorInterface->register_property<std::string>( "Unit", "xyz.openbmc_project.Sensor.Unit.DegreesC"); sensorInterface->register_property<double>("MaxValue", 100); sensorInterface->register_property<double>("MinValue", -100); sensorInterface->register_property<double>("Value", 42); sensorInterface->initialize(); sensorInterfaces.emplace_back(sensorInterface); } std::cout << "Done initializing\n"; boost::asio::steady_timer timer(io); timer.expires_from_now(std::chrono::seconds(update_interval_seconds)); timer.async_wait(std::bind_front(on_loop, &timer)); std::optional<sdbusplus::bus::match_t> match; if (watch_sensor_updates) { std::string expr = "type='signal',member='PropertiesChanged',path_" "namespace='/xyz/openbmc_project/sensors'"; match.emplace( static_cast<sdbusplus::bus_t &>(*connection), expr, [](sdbusplus::message_t &message) { std::string objectName; std::vector<std::pair<std::string, std::variant<double>>> result; try { message.read(objectName, result); } catch (const sdbusplus::exception_t &) { std::cerr << "Error reading match data\n"; return; } for (auto &property : result) { if (property.first == "Value") { reads++; } } }); } io.run(); return 0; }