Advertisement
Guest User

Untitled

a guest
Mar 10th, 2022
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.16 KB | None | 0 0
  1. #include <boost/algorithm/string/predicate.hpp>
  2. #include <boost/asio.hpp>
  3. #include <phosphor-logging/lg2.hpp>
  4. #include <sdbusplus/asio/connection.hpp>
  5. #include <sdbusplus/asio/property.hpp>
  6. #include <sdbusplus/bus/match.hpp>
  7.  
  8. constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";   // NOLINT
  9. constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";    // NOLINT
  10. constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; // NOLINT
  11. constexpr auto hostBusname = "xyz.openbmc_project.State.Host";
  12. constexpr auto hostInterface = "xyz.openbmc_project.State.Host";
  13. constexpr auto hostPath = "/xyz/openbmc_project/state/host0";
  14. constexpr auto hostProperty = "CurrentHostState";
  15.  
  16.  
  17. PHOSPHOR_LOG2_USING;
  18.  
  19. constexpr size_t numOfSensors = 14;
  20. using SensorValues = std::array<uint8_t, numOfSensors>;
  21.  
  22. constexpr auto sensorValueInterface = "xyz.openbmc_project.Sensor.Value";
  23. constexpr auto propertyValue = "Value";
  24. constexpr std::array<const char*, numOfSensors> sensorObjects = {
  25.     "/xyz/openbmc_project/sensors/temperature/Inlet0_Temp",
  26.     "/xyz/openbmc_project/sensors/temperature/Inlet1_Temp",
  27.     "/xyz/openbmc_project/sensors/temperature/Outlet0_Temp",
  28.     "/xyz/openbmc_project/sensors/temperature/Outlet1_Temp",
  29.     "/xyz/openbmc_project/sensors/temperature/CPU_Temp",
  30.     "/xyz/openbmc_project/sensors/temperature/DIMM_Temp",
  31.     "/xyz/openbmc_project/sensors/temperature/CPU_VR_Temp",
  32.     "/xyz/openbmc_project/sensors/temperature/Mdot2_Temp",
  33.     "/xyz/openbmc_project/sensors/temperature/DRAM0_Temp",
  34.     "/xyz/openbmc_project/sensors/temperature/DRAM1_Temp",
  35.     "/xyz/openbmc_project/sensors/temperature/DRAM2_Temp",
  36.     "/xyz/openbmc_project/sensors/temperature/FPGA_Temp",
  37.     "/xyz/openbmc_project/sensors/temperature/DSPF_Temp",
  38.     "/xyz/openbmc_project/sensors/temperature/FPGA_VR_Temp",
  39. };
  40.  
  41. std::array<std::optional<std::string>, numOfSensors> sensorServices;
  42. SensorValues sensorValues;
  43.  
  44. std::string getService(sdbusplus::bus::bus& bus, const char* path,
  45.                               const char* interface)
  46. {
  47.     auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
  48.                                       MAPPER_INTERFACE, "GetObject");
  49.  
  50.     mapper.append(path, std::vector<std::string>({interface}));
  51.     try
  52.     {
  53.         auto mapperResponseMsg = bus.call(mapper);
  54.  
  55.         std::vector<std::pair<std::string, std::vector<std::string>>>
  56.             mapperResponse;
  57.         mapperResponseMsg.read(mapperResponse);
  58.         if (mapperResponse.empty())
  59.         {
  60.             throw std::runtime_error("Error reading mapper response");
  61.         }
  62.         std::vector<std::string> ret;
  63.         ret.reserve(mapperResponse.size());
  64.         for (const auto& i : mapperResponse)
  65.         {
  66.             ret.emplace_back(i.first);
  67.         }
  68.         return ret[0];
  69.     }
  70.     catch (const sdbusplus::exception::SdBusError& ex)
  71.     {
  72.         throw std::runtime_error("GetObject call failed");
  73.     }
  74. }
  75.  
  76.  
  77. using PropertyType = std::variant<std::string, bool, double>;
  78. template <typename T>
  79. T getProperty(sdbusplus::bus::bus& bus, const char* service,
  80.               const char* path, const char* interface,
  81.               const char* propertyName)
  82. {
  83.     auto method = bus.new_method_call(service, path,
  84.                                       "org.freedesktop.DBus.Properties", "Get");
  85.     method.append(interface, propertyName);
  86.     try
  87.     {
  88.         PropertyType value{};
  89.         auto reply = bus.call(method);
  90.         reply.read(value);
  91.         auto ret = std::get<T>(value);
  92.         return ret;
  93.     }
  94.     catch (const sdbusplus::exception::SdBusError& ex)
  95.     {
  96.         throw std::runtime_error("GetProperty call failed");
  97.     }
  98. }
  99. void getSensors(sdbusplus::bus::bus& bus)
  100. {
  101.     // Read the sensors multiple times to make the issue more reproducible
  102.     for (int j = 0; j < 10; ++j)
  103.     {
  104.         for (size_t i = 0; i < numOfSensors; ++i)
  105.         {
  106.             try
  107.             {
  108.                 const auto& sensor = sensorObjects[i];
  109.                 auto& service = sensorServices[i];
  110.                 if (!service)
  111.                 {
  112.                     service = getService(bus, sensor, sensorValueInterface);
  113.                 }
  114.                 auto value =
  115.                     getProperty<double>(bus, service->c_str(), sensor,
  116.                                                sensorValueInterface, propertyValue);
  117.                 sensorValues[i] = static_cast<uint32_t>(value);
  118.             }
  119.             catch (const std::runtime_error& ex)
  120.             {
  121.                 sensorServices[i].reset();
  122.                 sensorValues[i] = 0;
  123.                 continue;
  124.             }
  125.         }
  126.     }
  127. }
  128.  
  129. void timerHandler(const boost::system::error_code& ec, sdbusplus::bus::bus& bus,
  130.                   boost::asio::steady_timer& t)
  131. {
  132.     if (ec)
  133.     {
  134.         lg2::error("Error occurs");
  135.         return;
  136.     }
  137.  
  138.     getSensors(bus);
  139.     t.expires_from_now(std::chrono::seconds(1));
  140.     t.async_wait([&](const boost::system::error_code& ec) {
  141.         timerHandler(ec, std::ref(bus), std::ref(t));
  142.     });
  143. }
  144.  
  145. int main(int /*argc*/, char** /*argv*/)
  146. {
  147.     boost::asio::io_context io;
  148.     boost::asio::steady_timer t(io, std::chrono::seconds(1));
  149.     auto bus = std::make_shared<sdbusplus::asio::connection>(io);
  150.  
  151.     t.async_wait([&](const boost::system::error_code& ec) {
  152.         timerHandler(ec, std::ref(static_cast<sdbusplus::bus::bus&>(*bus)),
  153.                      std::ref(t));
  154.     });
  155.  
  156.     // Match for host power monitor
  157.     namespace rules = sdbusplus::bus::match::rules;
  158.     sdbusplus::bus::match::match m(
  159.         static_cast<sdbusplus::bus::bus&>(*bus),
  160.         rules::propertiesChanged(hostPath, hostInterface),
  161.         [](sdbusplus::message::message& message) {
  162.             std::string objectName;
  163.             std::map<std::string, std::variant<std::string>> values;
  164.             message.read(objectName, values);
  165.             for (const auto& it : values)
  166.             {
  167.                 auto v = std::get<std::string>(it.second);
  168.                 lg2::info("aiso callback, property: {PROP}, value: {VALUE}", "PROP", it.first, "VALUE", v);
  169.             }
  170.         });
  171.  
  172.     io.run();
  173.     return 0;
  174. }
  175.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement