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 17abcc94faSVijay Khemka using namespace phosphor::logging; 18abcc94faSVijay Khemka 1951f898e2SVijay Khemka int handleDbusSignal(sd_bus_message* msg, void* usrData, sd_bus_error*) 2051f898e2SVijay Khemka { 2151f898e2SVijay Khemka if (usrData == nullptr) 2251f898e2SVijay Khemka { 2351f898e2SVijay Khemka throw std::runtime_error("Invalid match"); 2451f898e2SVijay Khemka } 2551f898e2SVijay Khemka 2651f898e2SVijay Khemka auto sdbpMsg = sdbusplus::message::message(msg); 2751f898e2SVijay Khemka std::string msgIfce; 2851f898e2SVijay Khemka std::map<std::string, std::variant<int64_t, double, bool>> msgData; 2951f898e2SVijay Khemka 3051f898e2SVijay Khemka sdbpMsg.read(msgIfce, msgData); 3151f898e2SVijay Khemka 3251f898e2SVijay Khemka if (msgData.find("Value") != msgData.end()) 3351f898e2SVijay Khemka { 3451f898e2SVijay Khemka using namespace phosphor::virtualSensor; 3551f898e2SVijay Khemka VirtualSensor* obj = static_cast<VirtualSensor*>(usrData); 3651f898e2SVijay Khemka // TODO(openbmc/phosphor-virtual-sensor#1): updateVirtualSensor should 3751f898e2SVijay Khemka // be changed to take the information we got from the signal, to avoid 3851f898e2SVijay Khemka // having to do numerous dbus queries. 3951f898e2SVijay Khemka obj->updateVirtualSensor(); 4051f898e2SVijay Khemka } 4151f898e2SVijay Khemka return 0; 4251f898e2SVijay Khemka } 4351f898e2SVijay Khemka 44abcc94faSVijay Khemka namespace phosphor 45abcc94faSVijay Khemka { 46abcc94faSVijay Khemka namespace virtualSensor 47abcc94faSVijay Khemka { 48abcc94faSVijay Khemka 49abcc94faSVijay Khemka void printParams(const VirtualSensor::ParamMap& paramMap) 50abcc94faSVijay Khemka { 51abcc94faSVijay Khemka for (const auto& p : paramMap) 52abcc94faSVijay Khemka { 53abcc94faSVijay Khemka const auto& p1 = p.first; 54abcc94faSVijay Khemka const auto& p2 = p.second; 55abcc94faSVijay Khemka auto val = p2->getParamValue(); 56abcc94faSVijay Khemka std::cout << p1 << " = " << val << "\n"; 57abcc94faSVijay Khemka } 58abcc94faSVijay Khemka } 59abcc94faSVijay Khemka 60abcc94faSVijay Khemka double SensorParam::getParamValue() 61abcc94faSVijay Khemka { 62abcc94faSVijay Khemka switch (paramType) 63abcc94faSVijay Khemka { 64abcc94faSVijay Khemka case constParam: 65abcc94faSVijay Khemka return value; 66abcc94faSVijay Khemka break; 677452a867SVijay Khemka case dbusParam: 687452a867SVijay Khemka return dbusSensor->getSensorValue(); 697452a867SVijay Khemka break; 70abcc94faSVijay Khemka default: 71abcc94faSVijay Khemka throw std::invalid_argument("param type not supported"); 72abcc94faSVijay Khemka } 73abcc94faSVijay Khemka } 74abcc94faSVijay Khemka 750fcf0e1cSLei YU using AssociationList = 760fcf0e1cSLei YU std::vector<std::tuple<std::string, std::string, std::string>>; 770fcf0e1cSLei YU 780fcf0e1cSLei YU AssociationList getAssociationsFromJson(const Json& j) 790fcf0e1cSLei YU { 800fcf0e1cSLei YU AssociationList assocs{}; 810fcf0e1cSLei YU try 820fcf0e1cSLei YU { 830fcf0e1cSLei YU j.get_to(assocs); 840fcf0e1cSLei YU } 850fcf0e1cSLei YU catch (const std::exception& ex) 860fcf0e1cSLei YU { 870fcf0e1cSLei YU log<level::ERR>("Failed to parse association", 880fcf0e1cSLei YU entry("EX=%s", ex.what())); 890fcf0e1cSLei YU } 900fcf0e1cSLei YU return assocs; 910fcf0e1cSLei YU } 920fcf0e1cSLei YU 93ce675228SMatt Spinler void VirtualSensor::initVirtualSensor(const Json& sensorConfig, 94ce675228SMatt Spinler const std::string& objPath) 95abcc94faSVijay Khemka { 96abcc94faSVijay Khemka 97abcc94faSVijay Khemka static const Json empty{}; 98abcc94faSVijay Khemka 99abcc94faSVijay Khemka /* Get threshold values if defined in config */ 100abcc94faSVijay Khemka auto threshold = sensorConfig.value("Threshold", empty); 101f15189e3SMatt Spinler 1023e99919bSRashmica Gupta createThresholds(threshold, objPath); 103abcc94faSVijay Khemka 104f6443742SHarvey Wu /* Get MaxValue, MinValue setting if defined in config */ 105f6443742SHarvey Wu auto confDesc = sensorConfig.value("Desc", empty); 106f6443742SHarvey Wu if (auto maxConf = confDesc.find("MaxValue"); 107f6443742SHarvey Wu maxConf != confDesc.end() && maxConf->is_number()) 108f6443742SHarvey Wu { 109f6443742SHarvey Wu ValueIface::maxValue(maxConf->get<double>()); 110f6443742SHarvey Wu } 111f6443742SHarvey Wu if (auto minConf = confDesc.find("MinValue"); 112f6443742SHarvey Wu minConf != confDesc.end() && minConf->is_number()) 113f6443742SHarvey Wu { 114f6443742SHarvey Wu ValueIface::minValue(minConf->get<double>()); 115f6443742SHarvey Wu } 116f6443742SHarvey Wu 1170fcf0e1cSLei YU /* Get optional association */ 1180fcf0e1cSLei YU auto assocJson = sensorConfig.value("Associations", empty); 1190fcf0e1cSLei YU if (!assocJson.empty()) 1200fcf0e1cSLei YU { 1210fcf0e1cSLei YU auto assocs = getAssociationsFromJson(assocJson); 1220fcf0e1cSLei YU if (!assocs.empty()) 1230fcf0e1cSLei YU { 1240fcf0e1cSLei YU associationIface = 1250fcf0e1cSLei YU std::make_unique<AssociationObject>(bus, objPath.c_str()); 1260fcf0e1cSLei YU associationIface->associations(assocs); 1270fcf0e1cSLei YU } 1280fcf0e1cSLei YU } 1290fcf0e1cSLei YU 130abcc94faSVijay Khemka /* Get expression string */ 131abcc94faSVijay Khemka exprStr = sensorConfig.value("Expression", ""); 132abcc94faSVijay Khemka 133abcc94faSVijay Khemka /* Get all the parameter listed in configuration */ 134abcc94faSVijay Khemka auto params = sensorConfig.value("Params", empty); 135abcc94faSVijay Khemka 136abcc94faSVijay Khemka /* Check for constant parameter */ 137abcc94faSVijay Khemka const auto& consParams = params.value("ConstParam", empty); 138abcc94faSVijay Khemka if (!consParams.empty()) 139abcc94faSVijay Khemka { 140abcc94faSVijay Khemka for (auto& j : consParams) 141abcc94faSVijay Khemka { 142abcc94faSVijay Khemka if (j.find("ParamName") != j.end()) 143abcc94faSVijay Khemka { 144abcc94faSVijay Khemka auto paramPtr = std::make_unique<SensorParam>(j["Value"]); 1453ed9a516SVijay Khemka std::string name = j["ParamName"]; 1463ed9a516SVijay Khemka symbols.create_variable(name); 1473ed9a516SVijay Khemka paramMap.emplace(std::move(name), std::move(paramPtr)); 148abcc94faSVijay Khemka } 149abcc94faSVijay Khemka else 150abcc94faSVijay Khemka { 151abcc94faSVijay Khemka /* Invalid configuration */ 152abcc94faSVijay Khemka throw std::invalid_argument( 153abcc94faSVijay Khemka "ParamName not found in configuration"); 154abcc94faSVijay Khemka } 155abcc94faSVijay Khemka } 156abcc94faSVijay Khemka } 157abcc94faSVijay Khemka 1587452a867SVijay Khemka /* Check for dbus parameter */ 1597452a867SVijay Khemka auto dbusParams = params.value("DbusParam", empty); 1607452a867SVijay Khemka if (!dbusParams.empty()) 1617452a867SVijay Khemka { 1627452a867SVijay Khemka for (auto& j : dbusParams) 1637452a867SVijay Khemka { 1647452a867SVijay Khemka /* Get parameter dbus sensor descriptor */ 1657452a867SVijay Khemka auto desc = j.value("Desc", empty); 1667452a867SVijay Khemka if ((!desc.empty()) && (j.find("ParamName") != j.end())) 1677452a867SVijay Khemka { 1687452a867SVijay Khemka std::string sensorType = desc.value("SensorType", ""); 1697452a867SVijay Khemka std::string name = desc.value("Name", ""); 1707452a867SVijay Khemka 1717452a867SVijay Khemka if (!sensorType.empty() && !name.empty()) 1727452a867SVijay Khemka { 1737452a867SVijay Khemka std::string objPath(sensorDbusPath); 1747452a867SVijay Khemka objPath += sensorType + "/" + name; 1757452a867SVijay Khemka 17651f898e2SVijay Khemka auto paramPtr = 17751f898e2SVijay Khemka std::make_unique<SensorParam>(bus, objPath, this); 1783ed9a516SVijay Khemka std::string name = j["ParamName"]; 1793ed9a516SVijay Khemka symbols.create_variable(name); 1803ed9a516SVijay Khemka paramMap.emplace(std::move(name), std::move(paramPtr)); 1817452a867SVijay Khemka } 1827452a867SVijay Khemka } 1837452a867SVijay Khemka } 1847452a867SVijay Khemka } 185abcc94faSVijay Khemka 1863ed9a516SVijay Khemka symbols.add_constants(); 1879f1ef4f5SMatt Spinler symbols.add_package(vecopsPackage); 1883ed9a516SVijay Khemka expression.register_symbol_table(symbols); 1893ed9a516SVijay Khemka 1903ed9a516SVijay Khemka /* parser from exprtk */ 1913ed9a516SVijay Khemka exprtk::parser<double> parser{}; 192ddc6dcd6SMatt Spinler if (!parser.compile(exprStr, expression)) 193ddc6dcd6SMatt Spinler { 194ddc6dcd6SMatt Spinler log<level::ERR>("Expression compilation failed"); 195ddc6dcd6SMatt Spinler 196ddc6dcd6SMatt Spinler for (std::size_t i = 0; i < parser.error_count(); ++i) 197ddc6dcd6SMatt Spinler { 198ddc6dcd6SMatt Spinler auto error = parser.get_error(i); 199ddc6dcd6SMatt Spinler 200ddc6dcd6SMatt Spinler log<level::ERR>( 201ddc6dcd6SMatt Spinler fmt::format( 202ddc6dcd6SMatt Spinler "Position: {} Type: {} Message: {}", error.token.position, 203ddc6dcd6SMatt Spinler exprtk::parser_error::to_str(error.mode), error.diagnostic) 204ddc6dcd6SMatt Spinler .c_str()); 205ddc6dcd6SMatt Spinler } 206ddc6dcd6SMatt Spinler throw std::runtime_error("Expression compilation failed"); 207ddc6dcd6SMatt Spinler } 2083ed9a516SVijay Khemka 209abcc94faSVijay Khemka /* Print all parameters for debug purpose only */ 210abcc94faSVijay Khemka if (DEBUG) 211abcc94faSVijay Khemka printParams(paramMap); 212abcc94faSVijay Khemka } 213abcc94faSVijay Khemka 214abcc94faSVijay Khemka void VirtualSensor::setSensorValue(double value) 215abcc94faSVijay Khemka { 216543bf668SPatrick Williams value = std::clamp(value, ValueIface::minValue(), ValueIface::maxValue()); 217abcc94faSVijay Khemka ValueIface::value(value); 218abcc94faSVijay Khemka } 219abcc94faSVijay Khemka 220abcc94faSVijay Khemka void VirtualSensor::updateVirtualSensor() 2213ed9a516SVijay Khemka { 2223ed9a516SVijay Khemka for (auto& param : paramMap) 2233ed9a516SVijay Khemka { 2243ed9a516SVijay Khemka auto& name = param.first; 2253ed9a516SVijay Khemka auto& data = param.second; 2263ed9a516SVijay Khemka if (auto var = symbols.get_variable(name)) 2273ed9a516SVijay Khemka { 2283ed9a516SVijay Khemka var->ref() = data->getParamValue(); 2293ed9a516SVijay Khemka } 2303ed9a516SVijay Khemka else 2313ed9a516SVijay Khemka { 2323ed9a516SVijay Khemka /* Invalid parameter */ 2333ed9a516SVijay Khemka throw std::invalid_argument("ParamName not found in symbols"); 2343ed9a516SVijay Khemka } 2353ed9a516SVijay Khemka } 2363ed9a516SVijay Khemka double val = expression.value(); 23732a7156bSVijay Khemka 23832a7156bSVijay Khemka /* Set sensor value to dbus interface */ 2393ed9a516SVijay Khemka setSensorValue(val); 24032a7156bSVijay Khemka 2413ed9a516SVijay Khemka if (DEBUG) 2423ed9a516SVijay Khemka std::cout << "Sensor value is " << val << "\n"; 24332a7156bSVijay Khemka 2448f5e6119SMatt Spinler /* Check sensor thresholds and log required message */ 245b306b03dSMatt Spinler checkThresholds(val, perfLossIface); 246fdb826d5SPatrick Williams checkThresholds(val, warningIface); 247fdb826d5SPatrick Williams checkThresholds(val, criticalIface); 248fdb826d5SPatrick Williams checkThresholds(val, softShutdownIface); 249fdb826d5SPatrick Williams checkThresholds(val, hardShutdownIface); 2503ed9a516SVijay Khemka } 251abcc94faSVijay Khemka 2523e99919bSRashmica Gupta void VirtualSensor::createThresholds(const Json& threshold, 2533e99919bSRashmica Gupta const std::string& objPath) 2543e99919bSRashmica Gupta { 2553e99919bSRashmica Gupta if (threshold.empty()) 2563e99919bSRashmica Gupta { 2573e99919bSRashmica Gupta return; 2583e99919bSRashmica Gupta } 2593e99919bSRashmica Gupta // Only create the threshold interfaces if 2603e99919bSRashmica Gupta // at least one of their values is present. 2613e99919bSRashmica Gupta if (threshold.contains("CriticalHigh") || threshold.contains("CriticalLow")) 2623e99919bSRashmica Gupta { 2633e99919bSRashmica Gupta criticalIface = 2643e99919bSRashmica Gupta std::make_unique<Threshold<CriticalObject>>(bus, objPath.c_str()); 2653e99919bSRashmica Gupta 2663e99919bSRashmica Gupta criticalIface->criticalHigh(threshold.value( 2673e99919bSRashmica Gupta "CriticalHigh", std::numeric_limits<double>::quiet_NaN())); 2683e99919bSRashmica Gupta criticalIface->criticalLow(threshold.value( 2693e99919bSRashmica Gupta "CriticalLow", std::numeric_limits<double>::quiet_NaN())); 2703e99919bSRashmica Gupta } 2713e99919bSRashmica Gupta 2723e99919bSRashmica Gupta if (threshold.contains("WarningHigh") || threshold.contains("WarningLow")) 2733e99919bSRashmica Gupta { 2743e99919bSRashmica Gupta warningIface = 2753e99919bSRashmica Gupta std::make_unique<Threshold<WarningObject>>(bus, objPath.c_str()); 2763e99919bSRashmica Gupta 2773e99919bSRashmica Gupta warningIface->warningHigh(threshold.value( 2783e99919bSRashmica Gupta "WarningHigh", std::numeric_limits<double>::quiet_NaN())); 2793e99919bSRashmica Gupta warningIface->warningLow(threshold.value( 2803e99919bSRashmica Gupta "WarningLow", std::numeric_limits<double>::quiet_NaN())); 2813e99919bSRashmica Gupta } 2823e99919bSRashmica Gupta 2833e99919bSRashmica Gupta if (threshold.contains("HardShutdownHigh") || 2843e99919bSRashmica Gupta threshold.contains("HardShutdownLow")) 2853e99919bSRashmica Gupta { 2863e99919bSRashmica Gupta hardShutdownIface = std::make_unique<Threshold<HardShutdownObject>>( 2873e99919bSRashmica Gupta bus, objPath.c_str()); 2883e99919bSRashmica Gupta 2893e99919bSRashmica Gupta hardShutdownIface->hardShutdownHigh(threshold.value( 2903e99919bSRashmica Gupta "HardShutdownHigh", std::numeric_limits<double>::quiet_NaN())); 2913e99919bSRashmica Gupta hardShutdownIface->hardShutdownLow(threshold.value( 2923e99919bSRashmica Gupta "HardShutdownLow", std::numeric_limits<double>::quiet_NaN())); 2933e99919bSRashmica Gupta } 2943e99919bSRashmica Gupta 2953e99919bSRashmica Gupta if (threshold.contains("SoftShutdownHigh") || 2963e99919bSRashmica Gupta threshold.contains("SoftShutdownLow")) 2973e99919bSRashmica Gupta { 2983e99919bSRashmica Gupta softShutdownIface = std::make_unique<Threshold<SoftShutdownObject>>( 2993e99919bSRashmica Gupta bus, objPath.c_str()); 3003e99919bSRashmica Gupta 3013e99919bSRashmica Gupta softShutdownIface->softShutdownHigh(threshold.value( 3023e99919bSRashmica Gupta "SoftShutdownHigh", std::numeric_limits<double>::quiet_NaN())); 3033e99919bSRashmica Gupta softShutdownIface->softShutdownLow(threshold.value( 3043e99919bSRashmica Gupta "SoftShutdownLow", std::numeric_limits<double>::quiet_NaN())); 3053e99919bSRashmica Gupta } 3063e99919bSRashmica Gupta 3073e99919bSRashmica Gupta if (threshold.contains("PerformanceLossHigh") || 3083e99919bSRashmica Gupta threshold.contains("PerformanceLossLow")) 3093e99919bSRashmica Gupta { 3103e99919bSRashmica Gupta perfLossIface = std::make_unique<Threshold<PerformanceLossObject>>( 3113e99919bSRashmica Gupta bus, objPath.c_str()); 3123e99919bSRashmica Gupta 3133e99919bSRashmica Gupta perfLossIface->performanceLossHigh(threshold.value( 3143e99919bSRashmica Gupta "PerformanceLossHigh", std::numeric_limits<double>::quiet_NaN())); 3153e99919bSRashmica Gupta perfLossIface->performanceLossLow(threshold.value( 3163e99919bSRashmica Gupta "PerformanceLossLow", std::numeric_limits<double>::quiet_NaN())); 3173e99919bSRashmica Gupta } 3183e99919bSRashmica Gupta } 3193e99919bSRashmica Gupta 320abcc94faSVijay Khemka /** @brief Parsing Virtual Sensor config JSON file */ 321abcc94faSVijay Khemka Json VirtualSensors::parseConfigFile(const std::string configFile) 322abcc94faSVijay Khemka { 323abcc94faSVijay Khemka std::ifstream jsonFile(configFile); 324abcc94faSVijay Khemka if (!jsonFile.is_open()) 325abcc94faSVijay Khemka { 326abcc94faSVijay Khemka log<level::ERR>("config JSON file not found", 327abcc94faSVijay Khemka entry("FILENAME=%s", configFile.c_str())); 328abcc94faSVijay Khemka throw std::exception{}; 329abcc94faSVijay Khemka } 330abcc94faSVijay Khemka 331abcc94faSVijay Khemka auto data = Json::parse(jsonFile, nullptr, false); 332abcc94faSVijay Khemka if (data.is_discarded()) 333abcc94faSVijay Khemka { 334abcc94faSVijay Khemka log<level::ERR>("config readings JSON parser failure", 335abcc94faSVijay Khemka entry("FILENAME=%s", configFile.c_str())); 336abcc94faSVijay Khemka throw std::exception{}; 337abcc94faSVijay Khemka } 338abcc94faSVijay Khemka 339abcc94faSVijay Khemka return data; 340abcc94faSVijay Khemka } 341abcc94faSVijay Khemka 342e0d371e4SVijay Khemka std::map<std::string, ValueIface::Unit> unitMap = { 343e0d371e4SVijay Khemka {"temperature", ValueIface::Unit::DegreesC}, 344e0d371e4SVijay Khemka {"fan_tach", ValueIface::Unit::RPMS}, 345e0d371e4SVijay Khemka {"voltage", ValueIface::Unit::Volts}, 346e0d371e4SVijay Khemka {"altitude", ValueIface::Unit::Meters}, 347e0d371e4SVijay Khemka {"current", ValueIface::Unit::Amperes}, 348e0d371e4SVijay Khemka {"power", ValueIface::Unit::Watts}, 349e0d371e4SVijay Khemka {"energy", ValueIface::Unit::Joules}, 3502b56ddb3SKumar Thangavel {"utilization", ValueIface::Unit::Percent}, 3514ac7a7f2SRashmica Gupta {"airflow", ValueIface::Unit::CFM}, 3524ac7a7f2SRashmica Gupta {"pressure", ValueIface::Unit::Pascals}}; 353e0d371e4SVijay Khemka 354abcc94faSVijay Khemka void VirtualSensors::createVirtualSensors() 355abcc94faSVijay Khemka { 356abcc94faSVijay Khemka static const Json empty{}; 357abcc94faSVijay Khemka 358abcc94faSVijay Khemka auto data = parseConfigFile(VIRTUAL_SENSOR_CONFIG_FILE); 359abcc94faSVijay Khemka // print values 360abcc94faSVijay Khemka if (DEBUG) 361abcc94faSVijay Khemka std::cout << "Config json data:\n" << data << "\n\n"; 362abcc94faSVijay Khemka 363abcc94faSVijay Khemka /* Get virtual sensors config data */ 364abcc94faSVijay Khemka for (const auto& j : data) 365abcc94faSVijay Khemka { 366abcc94faSVijay Khemka auto desc = j.value("Desc", empty); 367abcc94faSVijay Khemka if (!desc.empty()) 368abcc94faSVijay Khemka { 369abcc94faSVijay Khemka std::string sensorType = desc.value("SensorType", ""); 370abcc94faSVijay Khemka std::string name = desc.value("Name", ""); 371665a0a29SRashmica Gupta std::replace(name.begin(), name.end(), ' ', '_'); 372abcc94faSVijay Khemka 373abcc94faSVijay Khemka if (!name.empty() && !sensorType.empty()) 374abcc94faSVijay Khemka { 375e0d371e4SVijay Khemka if (unitMap.find(sensorType) == unitMap.end()) 376e0d371e4SVijay Khemka { 377e0d371e4SVijay Khemka log<level::ERR>("Sensor type is not supported", 378e0d371e4SVijay Khemka entry("TYPE=%s", sensorType.c_str())); 379e0d371e4SVijay Khemka } 380e0d371e4SVijay Khemka else 381e0d371e4SVijay Khemka { 38267d8b9d2SRashmica Gupta if (virtualSensorsMap.find(name) != virtualSensorsMap.end()) 38367d8b9d2SRashmica Gupta { 38467d8b9d2SRashmica Gupta log<level::ERR>( 38567d8b9d2SRashmica Gupta "A virtual sensor with this name already exists", 38667d8b9d2SRashmica Gupta entry("TYPE=%s", name.c_str())); 38767d8b9d2SRashmica Gupta continue; 38867d8b9d2SRashmica Gupta } 389abcc94faSVijay Khemka std::string objPath(sensorDbusPath); 390abcc94faSVijay Khemka objPath += sensorType + "/" + name; 391abcc94faSVijay Khemka 39232a7156bSVijay Khemka auto virtualSensorPtr = std::make_unique<VirtualSensor>( 39332a7156bSVijay Khemka bus, objPath.c_str(), j, name); 394abcc94faSVijay Khemka 395abcc94faSVijay Khemka log<level::INFO>("Added a new virtual sensor", 396abcc94faSVijay Khemka entry("NAME=%s", name.c_str())); 3973ed9a516SVijay Khemka virtualSensorPtr->updateVirtualSensor(); 398e0d371e4SVijay Khemka 399e0d371e4SVijay Khemka /* Initialize unit value for virtual sensor */ 400e0d371e4SVijay Khemka virtualSensorPtr->ValueIface::unit(unitMap[sensorType]); 401*a2fa63a6SRashmica Gupta virtualSensorPtr->emit_object_added(); 402e0d371e4SVijay Khemka 4033ed9a516SVijay Khemka virtualSensorsMap.emplace(std::move(name), 4043ed9a516SVijay Khemka std::move(virtualSensorPtr)); 405abcc94faSVijay Khemka } 406e0d371e4SVijay Khemka } 407abcc94faSVijay Khemka else 408abcc94faSVijay Khemka { 409abcc94faSVijay Khemka log<level::ERR>("Sensor type or name not found in config file"); 410abcc94faSVijay Khemka } 411abcc94faSVijay Khemka } 412abcc94faSVijay Khemka else 413abcc94faSVijay Khemka { 414abcc94faSVijay Khemka log<level::ERR>( 415abcc94faSVijay Khemka "Descriptor for new virtual sensor not found in config file"); 416abcc94faSVijay Khemka } 417abcc94faSVijay Khemka } 418abcc94faSVijay Khemka } 419abcc94faSVijay Khemka 420abcc94faSVijay Khemka } // namespace virtualSensor 421abcc94faSVijay Khemka } // namespace phosphor 422abcc94faSVijay Khemka 423abcc94faSVijay Khemka /** 424abcc94faSVijay Khemka * @brief Main 425abcc94faSVijay Khemka */ 426abcc94faSVijay Khemka int main() 427abcc94faSVijay Khemka { 428abcc94faSVijay Khemka 429abcc94faSVijay Khemka // Get a default event loop 430abcc94faSVijay Khemka auto event = sdeventplus::Event::get_default(); 431abcc94faSVijay Khemka 432abcc94faSVijay Khemka // Get a handle to system dbus 433abcc94faSVijay Khemka auto bus = sdbusplus::bus::new_default(); 434abcc94faSVijay Khemka 4356c19e7d2SMatt Spinler // Add the ObjectManager interface 4366c19e7d2SMatt Spinler sdbusplus::server::manager::manager objManager(bus, "/"); 4376c19e7d2SMatt Spinler 438abcc94faSVijay Khemka // Create an virtual sensors object 439abcc94faSVijay Khemka phosphor::virtualSensor::VirtualSensors virtualSensors(bus); 440abcc94faSVijay Khemka 441abcc94faSVijay Khemka // Request service bus name 442abcc94faSVijay Khemka bus.request_name(busName); 443abcc94faSVijay Khemka 444abcc94faSVijay Khemka // Attach the bus to sd_event to service user requests 445abcc94faSVijay Khemka bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 446abcc94faSVijay Khemka event.loop(); 447abcc94faSVijay Khemka 448abcc94faSVijay Khemka return 0; 449abcc94faSVijay Khemka } 450