1abcc94faSVijay Khemka #include "virtualSensor.hpp"
2abcc94faSVijay Khemka 
3abcc94faSVijay Khemka #include "config.hpp"
4abcc94faSVijay Khemka 
5ddc6dcd6SMatt Spinler #include <fmt/format.h>
6ddc6dcd6SMatt Spinler 
7abcc94faSVijay Khemka #include <phosphor-logging/log.hpp>
8abcc94faSVijay Khemka #include <sdeventplus/event.hpp>
9abcc94faSVijay Khemka 
10abcc94faSVijay Khemka #include <fstream>
11abcc94faSVijay Khemka #include <iostream>
12abcc94faSVijay Khemka 
13abcc94faSVijay Khemka static constexpr bool DEBUG = false;
14abcc94faSVijay Khemka static constexpr auto busName = "xyz.openbmc_project.VirtualSensor";
15abcc94faSVijay Khemka static constexpr auto sensorDbusPath = "/xyz/openbmc_project/sensors/";
16abcc94faSVijay Khemka static constexpr uint8_t defaultHighThreshold = 100;
17abcc94faSVijay Khemka static constexpr uint8_t defaultLowThreshold = 0;
18abcc94faSVijay Khemka 
19abcc94faSVijay Khemka using namespace phosphor::logging;
20abcc94faSVijay Khemka 
2151f898e2SVijay Khemka int handleDbusSignal(sd_bus_message* msg, void* usrData, sd_bus_error*)
2251f898e2SVijay Khemka {
2351f898e2SVijay Khemka     if (usrData == nullptr)
2451f898e2SVijay Khemka     {
2551f898e2SVijay Khemka         throw std::runtime_error("Invalid match");
2651f898e2SVijay Khemka     }
2751f898e2SVijay Khemka 
2851f898e2SVijay Khemka     auto sdbpMsg = sdbusplus::message::message(msg);
2951f898e2SVijay Khemka     std::string msgIfce;
3051f898e2SVijay Khemka     std::map<std::string, std::variant<int64_t, double, bool>> msgData;
3151f898e2SVijay Khemka 
3251f898e2SVijay Khemka     sdbpMsg.read(msgIfce, msgData);
3351f898e2SVijay Khemka 
3451f898e2SVijay Khemka     if (msgData.find("Value") != msgData.end())
3551f898e2SVijay Khemka     {
3651f898e2SVijay Khemka         using namespace phosphor::virtualSensor;
3751f898e2SVijay Khemka         VirtualSensor* obj = static_cast<VirtualSensor*>(usrData);
3851f898e2SVijay Khemka         // TODO(openbmc/phosphor-virtual-sensor#1): updateVirtualSensor should
3951f898e2SVijay Khemka         // be changed to take the information we got from the signal, to avoid
4051f898e2SVijay Khemka         // having to do numerous dbus queries.
4151f898e2SVijay Khemka         obj->updateVirtualSensor();
4251f898e2SVijay Khemka     }
4351f898e2SVijay Khemka     return 0;
4451f898e2SVijay Khemka }
4551f898e2SVijay Khemka 
46abcc94faSVijay Khemka namespace phosphor
47abcc94faSVijay Khemka {
48abcc94faSVijay Khemka namespace virtualSensor
49abcc94faSVijay Khemka {
50abcc94faSVijay Khemka 
51abcc94faSVijay Khemka void printParams(const VirtualSensor::ParamMap& paramMap)
52abcc94faSVijay Khemka {
53abcc94faSVijay Khemka     for (const auto& p : paramMap)
54abcc94faSVijay Khemka     {
55abcc94faSVijay Khemka         const auto& p1 = p.first;
56abcc94faSVijay Khemka         const auto& p2 = p.second;
57abcc94faSVijay Khemka         auto val = p2->getParamValue();
58abcc94faSVijay Khemka         std::cout << p1 << " = " << val << "\n";
59abcc94faSVijay Khemka     }
60abcc94faSVijay Khemka }
61abcc94faSVijay Khemka 
62abcc94faSVijay Khemka double SensorParam::getParamValue()
63abcc94faSVijay Khemka {
64abcc94faSVijay Khemka     switch (paramType)
65abcc94faSVijay Khemka     {
66abcc94faSVijay Khemka         case constParam:
67abcc94faSVijay Khemka             return value;
68abcc94faSVijay Khemka             break;
697452a867SVijay Khemka         case dbusParam:
707452a867SVijay Khemka             return dbusSensor->getSensorValue();
717452a867SVijay Khemka             break;
72abcc94faSVijay Khemka         default:
73abcc94faSVijay Khemka             throw std::invalid_argument("param type not supported");
74abcc94faSVijay Khemka     }
75abcc94faSVijay Khemka }
76abcc94faSVijay Khemka 
77abcc94faSVijay Khemka void VirtualSensor::initVirtualSensor(const Json& sensorConfig)
78abcc94faSVijay Khemka {
79abcc94faSVijay Khemka 
80abcc94faSVijay Khemka     static const Json empty{};
81abcc94faSVijay Khemka 
82abcc94faSVijay Khemka     /* Get threshold values if defined in config */
83abcc94faSVijay Khemka     auto threshold = sensorConfig.value("Threshold", empty);
84abcc94faSVijay Khemka     if (!threshold.empty())
85abcc94faSVijay Khemka     {
86c62a5548SVijay Khemka         Threshold sensorThreshold;
87abcc94faSVijay Khemka         sensorThreshold.criticalHigh =
88abcc94faSVijay Khemka             threshold.value("CriticalHigh", defaultHighThreshold);
89abcc94faSVijay Khemka         sensorThreshold.criticalLow =
90abcc94faSVijay Khemka             threshold.value("CriticalLow", defaultLowThreshold);
91abcc94faSVijay Khemka         sensorThreshold.warningHigh =
92abcc94faSVijay Khemka             threshold.value("WarningHigh", defaultHighThreshold);
93abcc94faSVijay Khemka         sensorThreshold.warningLow =
94abcc94faSVijay Khemka             threshold.value("WarningLow", defaultLowThreshold);
95abcc94faSVijay Khemka 
96abcc94faSVijay Khemka         /* Set threshold value to dbus */
97c62a5548SVijay Khemka         setSensorThreshold(sensorThreshold);
98c62a5548SVijay Khemka     }
99abcc94faSVijay Khemka 
100abcc94faSVijay Khemka     /* Get expression string */
101abcc94faSVijay Khemka     exprStr = sensorConfig.value("Expression", "");
102abcc94faSVijay Khemka 
103abcc94faSVijay Khemka     /* Get all the parameter listed in configuration */
104abcc94faSVijay Khemka     auto params = sensorConfig.value("Params", empty);
105abcc94faSVijay Khemka 
106abcc94faSVijay Khemka     /* Check for constant parameter */
107abcc94faSVijay Khemka     const auto& consParams = params.value("ConstParam", empty);
108abcc94faSVijay Khemka     if (!consParams.empty())
109abcc94faSVijay Khemka     {
110abcc94faSVijay Khemka         for (auto& j : consParams)
111abcc94faSVijay Khemka         {
112abcc94faSVijay Khemka             if (j.find("ParamName") != j.end())
113abcc94faSVijay Khemka             {
114abcc94faSVijay Khemka                 auto paramPtr = std::make_unique<SensorParam>(j["Value"]);
1153ed9a516SVijay Khemka                 std::string name = j["ParamName"];
1163ed9a516SVijay Khemka                 symbols.create_variable(name);
1173ed9a516SVijay Khemka                 paramMap.emplace(std::move(name), std::move(paramPtr));
118abcc94faSVijay Khemka             }
119abcc94faSVijay Khemka             else
120abcc94faSVijay Khemka             {
121abcc94faSVijay Khemka                 /* Invalid configuration */
122abcc94faSVijay Khemka                 throw std::invalid_argument(
123abcc94faSVijay Khemka                     "ParamName not found in configuration");
124abcc94faSVijay Khemka             }
125abcc94faSVijay Khemka         }
126abcc94faSVijay Khemka     }
127abcc94faSVijay Khemka 
1287452a867SVijay Khemka     /* Check for dbus parameter */
1297452a867SVijay Khemka     auto dbusParams = params.value("DbusParam", empty);
1307452a867SVijay Khemka     if (!dbusParams.empty())
1317452a867SVijay Khemka     {
1327452a867SVijay Khemka         for (auto& j : dbusParams)
1337452a867SVijay Khemka         {
1347452a867SVijay Khemka             /* Get parameter dbus sensor descriptor */
1357452a867SVijay Khemka             auto desc = j.value("Desc", empty);
1367452a867SVijay Khemka             if ((!desc.empty()) && (j.find("ParamName") != j.end()))
1377452a867SVijay Khemka             {
1387452a867SVijay Khemka                 std::string sensorType = desc.value("SensorType", "");
1397452a867SVijay Khemka                 std::string name = desc.value("Name", "");
1407452a867SVijay Khemka 
1417452a867SVijay Khemka                 if (!sensorType.empty() && !name.empty())
1427452a867SVijay Khemka                 {
1437452a867SVijay Khemka                     std::string objPath(sensorDbusPath);
1447452a867SVijay Khemka                     objPath += sensorType + "/" + name;
1457452a867SVijay Khemka 
14651f898e2SVijay Khemka                     auto paramPtr =
14751f898e2SVijay Khemka                         std::make_unique<SensorParam>(bus, objPath, this);
1483ed9a516SVijay Khemka                     std::string name = j["ParamName"];
1493ed9a516SVijay Khemka                     symbols.create_variable(name);
1503ed9a516SVijay Khemka                     paramMap.emplace(std::move(name), std::move(paramPtr));
1517452a867SVijay Khemka                 }
1527452a867SVijay Khemka             }
1537452a867SVijay Khemka         }
1547452a867SVijay Khemka     }
155abcc94faSVijay Khemka 
1563ed9a516SVijay Khemka     symbols.add_constants();
1579f1ef4f5SMatt Spinler     symbols.add_package(vecopsPackage);
1583ed9a516SVijay Khemka     expression.register_symbol_table(symbols);
1593ed9a516SVijay Khemka 
1603ed9a516SVijay Khemka     /* parser from exprtk */
1613ed9a516SVijay Khemka     exprtk::parser<double> parser{};
162ddc6dcd6SMatt Spinler     if (!parser.compile(exprStr, expression))
163ddc6dcd6SMatt Spinler     {
164ddc6dcd6SMatt Spinler         log<level::ERR>("Expression compilation failed");
165ddc6dcd6SMatt Spinler 
166ddc6dcd6SMatt Spinler         for (std::size_t i = 0; i < parser.error_count(); ++i)
167ddc6dcd6SMatt Spinler         {
168ddc6dcd6SMatt Spinler             auto error = parser.get_error(i);
169ddc6dcd6SMatt Spinler 
170ddc6dcd6SMatt Spinler             log<level::ERR>(
171ddc6dcd6SMatt Spinler                 fmt::format(
172ddc6dcd6SMatt Spinler                     "Position: {} Type: {} Message: {}", error.token.position,
173ddc6dcd6SMatt Spinler                     exprtk::parser_error::to_str(error.mode), error.diagnostic)
174ddc6dcd6SMatt Spinler                     .c_str());
175ddc6dcd6SMatt Spinler         }
176ddc6dcd6SMatt Spinler         throw std::runtime_error("Expression compilation failed");
177ddc6dcd6SMatt Spinler     }
1783ed9a516SVijay Khemka 
179abcc94faSVijay Khemka     /* Print all parameters for debug purpose only */
180abcc94faSVijay Khemka     if (DEBUG)
181abcc94faSVijay Khemka         printParams(paramMap);
182abcc94faSVijay Khemka }
183abcc94faSVijay Khemka 
184abcc94faSVijay Khemka void VirtualSensor::setSensorValue(double value)
185abcc94faSVijay Khemka {
186abcc94faSVijay Khemka     ValueIface::value(value);
187abcc94faSVijay Khemka }
188abcc94faSVijay Khemka 
189c62a5548SVijay Khemka void VirtualSensor::setSensorThreshold(Threshold& sensorThreshold)
190abcc94faSVijay Khemka {
191abcc94faSVijay Khemka     CriticalInterface::criticalHigh(sensorThreshold.criticalHigh);
192abcc94faSVijay Khemka     CriticalInterface::criticalLow(sensorThreshold.criticalLow);
193abcc94faSVijay Khemka     WarningInterface::warningHigh(sensorThreshold.warningHigh);
194abcc94faSVijay Khemka     WarningInterface::warningLow(sensorThreshold.warningLow);
195abcc94faSVijay Khemka }
196abcc94faSVijay Khemka 
19732a7156bSVijay Khemka void VirtualSensor::checkSensorThreshold(const double value)
19832a7156bSVijay Khemka {
19932a7156bSVijay Khemka     auto criticalHigh = CriticalInterface::criticalHigh();
20032a7156bSVijay Khemka     auto criticalLow = CriticalInterface::criticalLow();
20132a7156bSVijay Khemka     auto warningHigh = WarningInterface::warningHigh();
20232a7156bSVijay Khemka     auto warningLow = WarningInterface::warningLow();
20332a7156bSVijay Khemka 
20426edaad4SMatt Spinler     if (value >= warningHigh)
20532a7156bSVijay Khemka     {
20632a7156bSVijay Khemka         if (!WarningInterface::warningAlarmHigh())
20732a7156bSVijay Khemka         {
20832a7156bSVijay Khemka             WarningInterface::warningAlarmHigh(true);
20932a7156bSVijay Khemka             log<level::ERR>("ASSERT: Virtual Sensor has exceeded "
21032a7156bSVijay Khemka                             "warning high threshold",
21132a7156bSVijay Khemka                             entry("NAME = %s", name.c_str()));
21232a7156bSVijay Khemka         }
21332a7156bSVijay Khemka     }
21426edaad4SMatt Spinler     else if (WarningInterface::warningAlarmHigh())
21532a7156bSVijay Khemka     {
21632a7156bSVijay Khemka         WarningInterface::warningAlarmHigh(false);
21732a7156bSVijay Khemka         log<level::INFO>("DEASSERT: Virtual Sensor is under "
21832a7156bSVijay Khemka                          "warning high threshold",
21932a7156bSVijay Khemka                          entry("NAME = %s", name.c_str()));
22032a7156bSVijay Khemka     }
22132a7156bSVijay Khemka 
22226edaad4SMatt Spinler     if (value >= criticalHigh)
22332a7156bSVijay Khemka     {
22426edaad4SMatt Spinler         if (!CriticalInterface::criticalAlarmHigh())
22532a7156bSVijay Khemka         {
22626edaad4SMatt Spinler             CriticalInterface::criticalAlarmHigh(true);
22726edaad4SMatt Spinler             log<level::ERR>("ASSERT: Virtual Sensor has exceeded "
22826edaad4SMatt Spinler                             "critical high threshold",
22932a7156bSVijay Khemka                             entry("NAME = %s", name.c_str()));
23032a7156bSVijay Khemka         }
23132a7156bSVijay Khemka     }
23226edaad4SMatt Spinler     else if (CriticalInterface::criticalAlarmHigh())
23332a7156bSVijay Khemka     {
23426edaad4SMatt Spinler         CriticalInterface::criticalAlarmHigh(false);
23526edaad4SMatt Spinler         log<level::INFO>("DEASSERT: Virtual Sensor is under "
23626edaad4SMatt Spinler                          "critical high threshold",
23732a7156bSVijay Khemka                          entry("NAME = %s", name.c_str()));
23832a7156bSVijay Khemka     }
23932a7156bSVijay Khemka 
24026edaad4SMatt Spinler     if (value <= warningLow)
24132a7156bSVijay Khemka     {
24232a7156bSVijay Khemka         if (!WarningInterface::warningAlarmLow())
24332a7156bSVijay Khemka         {
24432a7156bSVijay Khemka             WarningInterface::warningAlarmLow(true);
24532a7156bSVijay Khemka             log<level::ERR>("ASSERT: Virtual Sensor is under "
24632a7156bSVijay Khemka                             "warning low threshold",
24732a7156bSVijay Khemka                             entry("NAME = %s", name.c_str()));
24832a7156bSVijay Khemka         }
24932a7156bSVijay Khemka     }
25026edaad4SMatt Spinler     else if (WarningInterface::warningAlarmLow())
25132a7156bSVijay Khemka     {
25232a7156bSVijay Khemka         WarningInterface::warningAlarmLow(false);
25326edaad4SMatt Spinler         log<level::INFO>("DEASSERT: Virtual Sensor is above "
25432a7156bSVijay Khemka                          "warning low threshold",
25532a7156bSVijay Khemka                          entry("NAME = %s", name.c_str()));
25632a7156bSVijay Khemka     }
25726edaad4SMatt Spinler 
25826edaad4SMatt Spinler     if (value <= criticalLow)
25926edaad4SMatt Spinler     {
26026edaad4SMatt Spinler         if (!CriticalInterface::criticalAlarmLow())
26126edaad4SMatt Spinler         {
26226edaad4SMatt Spinler             CriticalInterface::criticalAlarmLow(true);
26326edaad4SMatt Spinler             log<level::ERR>("ASSERT: Virtual Sensor is under "
26426edaad4SMatt Spinler                             "critical low threshold",
26526edaad4SMatt Spinler                             entry("NAME = %s", name.c_str()));
26626edaad4SMatt Spinler         }
26726edaad4SMatt Spinler     }
26826edaad4SMatt Spinler     else if (CriticalInterface::criticalAlarmLow())
26926edaad4SMatt Spinler     {
27026edaad4SMatt Spinler         CriticalInterface::criticalAlarmLow(false);
27126edaad4SMatt Spinler         log<level::INFO>("DEASSERT: Virtual Sensor is above "
27226edaad4SMatt Spinler                          "critical low threshold",
27326edaad4SMatt Spinler                          entry("NAME = %s", name.c_str()));
27426edaad4SMatt Spinler     }
27532a7156bSVijay Khemka }
27632a7156bSVijay Khemka 
277abcc94faSVijay Khemka void VirtualSensor::updateVirtualSensor()
2783ed9a516SVijay Khemka {
2793ed9a516SVijay Khemka     for (auto& param : paramMap)
2803ed9a516SVijay Khemka     {
2813ed9a516SVijay Khemka         auto& name = param.first;
2823ed9a516SVijay Khemka         auto& data = param.second;
2833ed9a516SVijay Khemka         if (auto var = symbols.get_variable(name))
2843ed9a516SVijay Khemka         {
2853ed9a516SVijay Khemka             var->ref() = data->getParamValue();
2863ed9a516SVijay Khemka         }
2873ed9a516SVijay Khemka         else
2883ed9a516SVijay Khemka         {
2893ed9a516SVijay Khemka             /* Invalid parameter */
2903ed9a516SVijay Khemka             throw std::invalid_argument("ParamName not found in symbols");
2913ed9a516SVijay Khemka         }
2923ed9a516SVijay Khemka     }
2933ed9a516SVijay Khemka     double val = expression.value();
29432a7156bSVijay Khemka 
29532a7156bSVijay Khemka     /* Set sensor value to dbus interface */
2963ed9a516SVijay Khemka     setSensorValue(val);
29732a7156bSVijay Khemka 
2983ed9a516SVijay Khemka     if (DEBUG)
2993ed9a516SVijay Khemka         std::cout << "Sensor value is " << val << "\n";
30032a7156bSVijay Khemka 
30132a7156bSVijay Khemka     /* Check sensor threshold and log required message */
30232a7156bSVijay Khemka     checkSensorThreshold(val);
3033ed9a516SVijay Khemka }
304abcc94faSVijay Khemka 
305abcc94faSVijay Khemka /** @brief Parsing Virtual Sensor config JSON file  */
306abcc94faSVijay Khemka Json VirtualSensors::parseConfigFile(const std::string configFile)
307abcc94faSVijay Khemka {
308abcc94faSVijay Khemka     std::ifstream jsonFile(configFile);
309abcc94faSVijay Khemka     if (!jsonFile.is_open())
310abcc94faSVijay Khemka     {
311abcc94faSVijay Khemka         log<level::ERR>("config JSON file not found",
312abcc94faSVijay Khemka                         entry("FILENAME = %s", configFile.c_str()));
313abcc94faSVijay Khemka         throw std::exception{};
314abcc94faSVijay Khemka     }
315abcc94faSVijay Khemka 
316abcc94faSVijay Khemka     auto data = Json::parse(jsonFile, nullptr, false);
317abcc94faSVijay Khemka     if (data.is_discarded())
318abcc94faSVijay Khemka     {
319abcc94faSVijay Khemka         log<level::ERR>("config readings JSON parser failure",
320abcc94faSVijay Khemka                         entry("FILENAME = %s", configFile.c_str()));
321abcc94faSVijay Khemka         throw std::exception{};
322abcc94faSVijay Khemka     }
323abcc94faSVijay Khemka 
324abcc94faSVijay Khemka     return data;
325abcc94faSVijay Khemka }
326abcc94faSVijay Khemka 
327e0d371e4SVijay Khemka std::map<std::string, ValueIface::Unit> unitMap = {
328e0d371e4SVijay Khemka     {"temperature", ValueIface::Unit::DegreesC},
329e0d371e4SVijay Khemka     {"fan_tach", ValueIface::Unit::RPMS},
330e0d371e4SVijay Khemka     {"voltage", ValueIface::Unit::Volts},
331e0d371e4SVijay Khemka     {"altitude", ValueIface::Unit::Meters},
332e0d371e4SVijay Khemka     {"current", ValueIface::Unit::Amperes},
333e0d371e4SVijay Khemka     {"power", ValueIface::Unit::Watts},
334e0d371e4SVijay Khemka     {"energy", ValueIface::Unit::Joules},
335e0d371e4SVijay Khemka     {"utilization", ValueIface::Unit::Percent}};
336e0d371e4SVijay Khemka 
337abcc94faSVijay Khemka void VirtualSensors::createVirtualSensors()
338abcc94faSVijay Khemka {
339abcc94faSVijay Khemka     static const Json empty{};
340abcc94faSVijay Khemka 
341abcc94faSVijay Khemka     auto data = parseConfigFile(VIRTUAL_SENSOR_CONFIG_FILE);
342abcc94faSVijay Khemka     // print values
343abcc94faSVijay Khemka     if (DEBUG)
344abcc94faSVijay Khemka         std::cout << "Config json data:\n" << data << "\n\n";
345abcc94faSVijay Khemka 
346abcc94faSVijay Khemka     /* Get virtual sensors  config data */
347abcc94faSVijay Khemka     for (const auto& j : data)
348abcc94faSVijay Khemka     {
349abcc94faSVijay Khemka         auto desc = j.value("Desc", empty);
350abcc94faSVijay Khemka         if (!desc.empty())
351abcc94faSVijay Khemka         {
352abcc94faSVijay Khemka             std::string sensorType = desc.value("SensorType", "");
353abcc94faSVijay Khemka             std::string name = desc.value("Name", "");
354abcc94faSVijay Khemka 
355abcc94faSVijay Khemka             if (!name.empty() && !sensorType.empty())
356abcc94faSVijay Khemka             {
357e0d371e4SVijay Khemka                 if (unitMap.find(sensorType) == unitMap.end())
358e0d371e4SVijay Khemka                 {
359e0d371e4SVijay Khemka                     log<level::ERR>("Sensor type is not supported",
360e0d371e4SVijay Khemka                                     entry("TYPE = %s", sensorType.c_str()));
361e0d371e4SVijay Khemka                 }
362e0d371e4SVijay Khemka                 else
363e0d371e4SVijay Khemka                 {
364abcc94faSVijay Khemka                     std::string objPath(sensorDbusPath);
365abcc94faSVijay Khemka                     objPath += sensorType + "/" + name;
366abcc94faSVijay Khemka 
36732a7156bSVijay Khemka                     auto virtualSensorPtr = std::make_unique<VirtualSensor>(
36832a7156bSVijay Khemka                         bus, objPath.c_str(), j, name);
369abcc94faSVijay Khemka 
370abcc94faSVijay Khemka                     log<level::INFO>("Added a new virtual sensor",
371abcc94faSVijay Khemka                                      entry("NAME = %s", name.c_str()));
3723ed9a516SVijay Khemka                     virtualSensorPtr->updateVirtualSensor();
373e0d371e4SVijay Khemka 
374e0d371e4SVijay Khemka                     /* Initialize unit value for virtual sensor */
375e0d371e4SVijay Khemka                     virtualSensorPtr->ValueIface::unit(unitMap[sensorType]);
376e0d371e4SVijay Khemka 
3773ed9a516SVijay Khemka                     virtualSensorsMap.emplace(std::move(name),
3783ed9a516SVijay Khemka                                               std::move(virtualSensorPtr));
379abcc94faSVijay Khemka                 }
380e0d371e4SVijay Khemka             }
381abcc94faSVijay Khemka             else
382abcc94faSVijay Khemka             {
383abcc94faSVijay Khemka                 log<level::ERR>("Sensor type or name not found in config file");
384abcc94faSVijay Khemka             }
385abcc94faSVijay Khemka         }
386abcc94faSVijay Khemka         else
387abcc94faSVijay Khemka         {
388abcc94faSVijay Khemka             log<level::ERR>(
389abcc94faSVijay Khemka                 "Descriptor for new virtual sensor not found in config file");
390abcc94faSVijay Khemka         }
391abcc94faSVijay Khemka     }
392abcc94faSVijay Khemka }
393abcc94faSVijay Khemka 
394abcc94faSVijay Khemka } // namespace virtualSensor
395abcc94faSVijay Khemka } // namespace phosphor
396abcc94faSVijay Khemka 
397abcc94faSVijay Khemka /**
398abcc94faSVijay Khemka  * @brief Main
399abcc94faSVijay Khemka  */
400abcc94faSVijay Khemka int main()
401abcc94faSVijay Khemka {
402abcc94faSVijay Khemka 
403abcc94faSVijay Khemka     // Get a default event loop
404abcc94faSVijay Khemka     auto event = sdeventplus::Event::get_default();
405abcc94faSVijay Khemka 
406abcc94faSVijay Khemka     // Get a handle to system dbus
407abcc94faSVijay Khemka     auto bus = sdbusplus::bus::new_default();
408abcc94faSVijay Khemka 
409*6c19e7d2SMatt Spinler     // Add the ObjectManager interface
410*6c19e7d2SMatt Spinler     sdbusplus::server::manager::manager objManager(bus, "/");
411*6c19e7d2SMatt Spinler 
412abcc94faSVijay Khemka     // Create an virtual sensors object
413abcc94faSVijay Khemka     phosphor::virtualSensor::VirtualSensors virtualSensors(bus);
414abcc94faSVijay Khemka 
415abcc94faSVijay Khemka     // Request service bus name
416abcc94faSVijay Khemka     bus.request_name(busName);
417abcc94faSVijay Khemka 
418abcc94faSVijay Khemka     // Attach the bus to sd_event to service user requests
419abcc94faSVijay Khemka     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
420abcc94faSVijay Khemka     event.loop();
421abcc94faSVijay Khemka 
422abcc94faSVijay Khemka     return 0;
423abcc94faSVijay Khemka }
424