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 77*ce675228SMatt Spinler void VirtualSensor::initVirtualSensor(const Json& sensorConfig, 78*ce675228SMatt Spinler const std::string& objPath) 79abcc94faSVijay Khemka { 80abcc94faSVijay Khemka 81abcc94faSVijay Khemka static const Json empty{}; 82abcc94faSVijay Khemka 83abcc94faSVijay Khemka /* Get threshold values if defined in config */ 84abcc94faSVijay Khemka auto threshold = sensorConfig.value("Threshold", empty); 85abcc94faSVijay Khemka if (!threshold.empty()) 86abcc94faSVijay Khemka { 87*ce675228SMatt Spinler criticalIface = std::make_unique<CriticalObject>(bus, objPath.c_str()); 88*ce675228SMatt Spinler criticalIface->criticalHigh( 89*ce675228SMatt Spinler threshold.value("CriticalHigh", defaultHighThreshold)); 90*ce675228SMatt Spinler criticalIface->criticalLow( 91*ce675228SMatt Spinler threshold.value("CriticalLow", defaultLowThreshold)); 92abcc94faSVijay Khemka 93*ce675228SMatt Spinler warningIface = std::make_unique<WarningObject>(bus, objPath.c_str()); 94*ce675228SMatt Spinler warningIface->warningHigh( 95*ce675228SMatt Spinler threshold.value("WarningHigh", defaultHighThreshold)); 96*ce675228SMatt Spinler warningIface->warningLow( 97*ce675228SMatt Spinler threshold.value("WarningLow", defaultLowThreshold)); 98*ce675228SMatt Spinler 99*ce675228SMatt Spinler // Only create the high and low shutdown interfaces if 100*ce675228SMatt Spinler // at least one of their values is present. 101*ce675228SMatt Spinler if (threshold.contains("HardShutdownHigh") || 102*ce675228SMatt Spinler threshold.contains("HardShutdownLow")) 103*ce675228SMatt Spinler { 104*ce675228SMatt Spinler hardShutdownIface = 105*ce675228SMatt Spinler std::make_unique<HardShutdownObject>(bus, objPath.c_str()); 106*ce675228SMatt Spinler 107*ce675228SMatt Spinler hardShutdownIface->hardShutdownHigh(threshold.value( 108*ce675228SMatt Spinler "HardShutdownHigh", std::numeric_limits<double>::quiet_NaN())); 109*ce675228SMatt Spinler hardShutdownIface->hardShutdownLow(threshold.value( 110*ce675228SMatt Spinler "HardShutdownLow", std::numeric_limits<double>::quiet_NaN())); 111*ce675228SMatt Spinler } 112*ce675228SMatt Spinler 113*ce675228SMatt Spinler if (threshold.contains("SoftShutdownHigh") || 114*ce675228SMatt Spinler threshold.contains("SoftShutdownLow")) 115*ce675228SMatt Spinler { 116*ce675228SMatt Spinler softShutdownIface = 117*ce675228SMatt Spinler std::make_unique<SoftShutdownObject>(bus, objPath.c_str()); 118*ce675228SMatt Spinler 119*ce675228SMatt Spinler softShutdownIface->softShutdownHigh(threshold.value( 120*ce675228SMatt Spinler "SoftShutdownHigh", std::numeric_limits<double>::quiet_NaN())); 121*ce675228SMatt Spinler softShutdownIface->softShutdownLow(threshold.value( 122*ce675228SMatt Spinler "SoftShutdownLow", std::numeric_limits<double>::quiet_NaN())); 123*ce675228SMatt Spinler } 124c62a5548SVijay Khemka } 125abcc94faSVijay Khemka 126abcc94faSVijay Khemka /* Get expression string */ 127abcc94faSVijay Khemka exprStr = sensorConfig.value("Expression", ""); 128abcc94faSVijay Khemka 129abcc94faSVijay Khemka /* Get all the parameter listed in configuration */ 130abcc94faSVijay Khemka auto params = sensorConfig.value("Params", empty); 131abcc94faSVijay Khemka 132abcc94faSVijay Khemka /* Check for constant parameter */ 133abcc94faSVijay Khemka const auto& consParams = params.value("ConstParam", empty); 134abcc94faSVijay Khemka if (!consParams.empty()) 135abcc94faSVijay Khemka { 136abcc94faSVijay Khemka for (auto& j : consParams) 137abcc94faSVijay Khemka { 138abcc94faSVijay Khemka if (j.find("ParamName") != j.end()) 139abcc94faSVijay Khemka { 140abcc94faSVijay Khemka auto paramPtr = std::make_unique<SensorParam>(j["Value"]); 1413ed9a516SVijay Khemka std::string name = j["ParamName"]; 1423ed9a516SVijay Khemka symbols.create_variable(name); 1433ed9a516SVijay Khemka paramMap.emplace(std::move(name), std::move(paramPtr)); 144abcc94faSVijay Khemka } 145abcc94faSVijay Khemka else 146abcc94faSVijay Khemka { 147abcc94faSVijay Khemka /* Invalid configuration */ 148abcc94faSVijay Khemka throw std::invalid_argument( 149abcc94faSVijay Khemka "ParamName not found in configuration"); 150abcc94faSVijay Khemka } 151abcc94faSVijay Khemka } 152abcc94faSVijay Khemka } 153abcc94faSVijay Khemka 1547452a867SVijay Khemka /* Check for dbus parameter */ 1557452a867SVijay Khemka auto dbusParams = params.value("DbusParam", empty); 1567452a867SVijay Khemka if (!dbusParams.empty()) 1577452a867SVijay Khemka { 1587452a867SVijay Khemka for (auto& j : dbusParams) 1597452a867SVijay Khemka { 1607452a867SVijay Khemka /* Get parameter dbus sensor descriptor */ 1617452a867SVijay Khemka auto desc = j.value("Desc", empty); 1627452a867SVijay Khemka if ((!desc.empty()) && (j.find("ParamName") != j.end())) 1637452a867SVijay Khemka { 1647452a867SVijay Khemka std::string sensorType = desc.value("SensorType", ""); 1657452a867SVijay Khemka std::string name = desc.value("Name", ""); 1667452a867SVijay Khemka 1677452a867SVijay Khemka if (!sensorType.empty() && !name.empty()) 1687452a867SVijay Khemka { 1697452a867SVijay Khemka std::string objPath(sensorDbusPath); 1707452a867SVijay Khemka objPath += sensorType + "/" + name; 1717452a867SVijay Khemka 17251f898e2SVijay Khemka auto paramPtr = 17351f898e2SVijay Khemka std::make_unique<SensorParam>(bus, objPath, this); 1743ed9a516SVijay Khemka std::string name = j["ParamName"]; 1753ed9a516SVijay Khemka symbols.create_variable(name); 1763ed9a516SVijay Khemka paramMap.emplace(std::move(name), std::move(paramPtr)); 1777452a867SVijay Khemka } 1787452a867SVijay Khemka } 1797452a867SVijay Khemka } 1807452a867SVijay Khemka } 181abcc94faSVijay Khemka 1823ed9a516SVijay Khemka symbols.add_constants(); 1839f1ef4f5SMatt Spinler symbols.add_package(vecopsPackage); 1843ed9a516SVijay Khemka expression.register_symbol_table(symbols); 1853ed9a516SVijay Khemka 1863ed9a516SVijay Khemka /* parser from exprtk */ 1873ed9a516SVijay Khemka exprtk::parser<double> parser{}; 188ddc6dcd6SMatt Spinler if (!parser.compile(exprStr, expression)) 189ddc6dcd6SMatt Spinler { 190ddc6dcd6SMatt Spinler log<level::ERR>("Expression compilation failed"); 191ddc6dcd6SMatt Spinler 192ddc6dcd6SMatt Spinler for (std::size_t i = 0; i < parser.error_count(); ++i) 193ddc6dcd6SMatt Spinler { 194ddc6dcd6SMatt Spinler auto error = parser.get_error(i); 195ddc6dcd6SMatt Spinler 196ddc6dcd6SMatt Spinler log<level::ERR>( 197ddc6dcd6SMatt Spinler fmt::format( 198ddc6dcd6SMatt Spinler "Position: {} Type: {} Message: {}", error.token.position, 199ddc6dcd6SMatt Spinler exprtk::parser_error::to_str(error.mode), error.diagnostic) 200ddc6dcd6SMatt Spinler .c_str()); 201ddc6dcd6SMatt Spinler } 202ddc6dcd6SMatt Spinler throw std::runtime_error("Expression compilation failed"); 203ddc6dcd6SMatt Spinler } 2043ed9a516SVijay Khemka 205abcc94faSVijay Khemka /* Print all parameters for debug purpose only */ 206abcc94faSVijay Khemka if (DEBUG) 207abcc94faSVijay Khemka printParams(paramMap); 208abcc94faSVijay Khemka } 209abcc94faSVijay Khemka 210abcc94faSVijay Khemka void VirtualSensor::setSensorValue(double value) 211abcc94faSVijay Khemka { 212abcc94faSVijay Khemka ValueIface::value(value); 213abcc94faSVijay Khemka } 214abcc94faSVijay Khemka 21532a7156bSVijay Khemka void VirtualSensor::checkSensorThreshold(const double value) 21632a7156bSVijay Khemka { 217*ce675228SMatt Spinler if (warningIface) 21832a7156bSVijay Khemka { 219*ce675228SMatt Spinler if (value >= warningIface->warningHigh()) 22032a7156bSVijay Khemka { 221*ce675228SMatt Spinler if (!warningIface->warningAlarmHigh()) 222*ce675228SMatt Spinler { 223*ce675228SMatt Spinler warningIface->warningAlarmHigh(true); 22432a7156bSVijay Khemka log<level::ERR>("ASSERT: Virtual Sensor has exceeded " 22532a7156bSVijay Khemka "warning high threshold", 22632a7156bSVijay Khemka entry("NAME = %s", name.c_str())); 22732a7156bSVijay Khemka } 22832a7156bSVijay Khemka } 229*ce675228SMatt Spinler else if (warningIface->warningAlarmHigh()) 23032a7156bSVijay Khemka { 231*ce675228SMatt Spinler warningIface->warningAlarmHigh(false); 23232a7156bSVijay Khemka log<level::INFO>("DEASSERT: Virtual Sensor is under " 23332a7156bSVijay Khemka "warning high threshold", 23432a7156bSVijay Khemka entry("NAME = %s", name.c_str())); 23532a7156bSVijay Khemka } 23632a7156bSVijay Khemka 237*ce675228SMatt Spinler if (value <= warningIface->warningLow()) 23832a7156bSVijay Khemka { 239*ce675228SMatt Spinler if (!warningIface->warningAlarmLow()) 24032a7156bSVijay Khemka { 241*ce675228SMatt Spinler warningIface->warningAlarmLow(true); 242*ce675228SMatt Spinler log<level::ERR>("ASSERT: Virtual Sensor is under " 243*ce675228SMatt Spinler "warning low threshold", 244*ce675228SMatt Spinler entry("NAME = %s", name.c_str())); 245*ce675228SMatt Spinler } 246*ce675228SMatt Spinler } 247*ce675228SMatt Spinler else if (warningIface->warningAlarmLow()) 248*ce675228SMatt Spinler { 249*ce675228SMatt Spinler warningIface->warningAlarmLow(false); 250*ce675228SMatt Spinler log<level::INFO>("DEASSERT: Virtual Sensor is above " 251*ce675228SMatt Spinler "warning low threshold", 252*ce675228SMatt Spinler entry("NAME = %s", name.c_str())); 253*ce675228SMatt Spinler } 254*ce675228SMatt Spinler } 255*ce675228SMatt Spinler 256*ce675228SMatt Spinler if (criticalIface) 257*ce675228SMatt Spinler { 258*ce675228SMatt Spinler if (value >= criticalIface->criticalHigh()) 259*ce675228SMatt Spinler { 260*ce675228SMatt Spinler if (!criticalIface->criticalAlarmHigh()) 261*ce675228SMatt Spinler { 262*ce675228SMatt Spinler criticalIface->criticalAlarmHigh(true); 26326edaad4SMatt Spinler log<level::ERR>("ASSERT: Virtual Sensor has exceeded " 26426edaad4SMatt Spinler "critical high threshold", 26532a7156bSVijay Khemka entry("NAME = %s", name.c_str())); 26632a7156bSVijay Khemka } 26732a7156bSVijay Khemka } 268*ce675228SMatt Spinler else if (criticalIface->criticalAlarmHigh()) 26932a7156bSVijay Khemka { 270*ce675228SMatt Spinler criticalIface->criticalAlarmHigh(false); 27126edaad4SMatt Spinler log<level::INFO>("DEASSERT: Virtual Sensor is under " 27226edaad4SMatt Spinler "critical high threshold", 27332a7156bSVijay Khemka entry("NAME = %s", name.c_str())); 27432a7156bSVijay Khemka } 27532a7156bSVijay Khemka 276*ce675228SMatt Spinler if (value <= criticalIface->criticalLow()) 27732a7156bSVijay Khemka { 278*ce675228SMatt Spinler if (!criticalIface->criticalAlarmLow()) 27932a7156bSVijay Khemka { 280*ce675228SMatt Spinler criticalIface->criticalAlarmLow(true); 28132a7156bSVijay Khemka log<level::ERR>("ASSERT: Virtual Sensor is under " 282*ce675228SMatt Spinler "critical low threshold", 28332a7156bSVijay Khemka entry("NAME = %s", name.c_str())); 28432a7156bSVijay Khemka } 28532a7156bSVijay Khemka } 286*ce675228SMatt Spinler else if (criticalIface->criticalAlarmLow()) 28732a7156bSVijay Khemka { 288*ce675228SMatt Spinler criticalIface->criticalAlarmLow(false); 28926edaad4SMatt Spinler log<level::INFO>("DEASSERT: Virtual Sensor is above " 290*ce675228SMatt Spinler "critical low threshold", 291*ce675228SMatt Spinler entry("NAME = %s", name.c_str())); 292*ce675228SMatt Spinler } 293*ce675228SMatt Spinler } 294*ce675228SMatt Spinler 295*ce675228SMatt Spinler if (softShutdownIface) 296*ce675228SMatt Spinler { 297*ce675228SMatt Spinler if (value >= softShutdownIface->softShutdownHigh()) 298*ce675228SMatt Spinler { 299*ce675228SMatt Spinler if (!softShutdownIface->softShutdownAlarmHigh()) 300*ce675228SMatt Spinler { 301*ce675228SMatt Spinler softShutdownIface->softShutdownAlarmHigh(true); 302*ce675228SMatt Spinler log<level::ERR>("ASSERT: Virtual Sensor has exceeded " 303*ce675228SMatt Spinler "softShutdown high threshold", 304*ce675228SMatt Spinler entry("NAME = %s", name.c_str())); 305*ce675228SMatt Spinler } 306*ce675228SMatt Spinler } 307*ce675228SMatt Spinler else if (softShutdownIface->softShutdownAlarmHigh()) 308*ce675228SMatt Spinler { 309*ce675228SMatt Spinler softShutdownIface->softShutdownAlarmHigh(false); 310*ce675228SMatt Spinler log<level::INFO>("DEASSERT: Virtual Sensor is under " 311*ce675228SMatt Spinler "softShutdown high threshold", 31232a7156bSVijay Khemka entry("NAME = %s", name.c_str())); 31332a7156bSVijay Khemka } 31426edaad4SMatt Spinler 315*ce675228SMatt Spinler if (value <= softShutdownIface->softShutdownLow()) 31626edaad4SMatt Spinler { 317*ce675228SMatt Spinler if (!softShutdownIface->softShutdownAlarmLow()) 31826edaad4SMatt Spinler { 319*ce675228SMatt Spinler softShutdownIface->softShutdownAlarmLow(true); 32026edaad4SMatt Spinler log<level::ERR>("ASSERT: Virtual Sensor is under " 321*ce675228SMatt Spinler "softShutdown low threshold", 32226edaad4SMatt Spinler entry("NAME = %s", name.c_str())); 32326edaad4SMatt Spinler } 32426edaad4SMatt Spinler } 325*ce675228SMatt Spinler else if (softShutdownIface->softShutdownAlarmLow()) 32626edaad4SMatt Spinler { 327*ce675228SMatt Spinler softShutdownIface->softShutdownAlarmLow(false); 32826edaad4SMatt Spinler log<level::INFO>("DEASSERT: Virtual Sensor is above " 329*ce675228SMatt Spinler "softShutdown low threshold", 33026edaad4SMatt Spinler entry("NAME = %s", name.c_str())); 33126edaad4SMatt Spinler } 33232a7156bSVijay Khemka } 33332a7156bSVijay Khemka 334*ce675228SMatt Spinler if (hardShutdownIface) 335*ce675228SMatt Spinler { 336*ce675228SMatt Spinler if (value >= hardShutdownIface->hardShutdownHigh()) 337*ce675228SMatt Spinler { 338*ce675228SMatt Spinler if (!hardShutdownIface->hardShutdownAlarmHigh()) 339*ce675228SMatt Spinler { 340*ce675228SMatt Spinler hardShutdownIface->hardShutdownAlarmHigh(true); 341*ce675228SMatt Spinler log<level::ERR>("ASSERT: Virtual Sensor has exceeded " 342*ce675228SMatt Spinler "hardShutdown high threshold", 343*ce675228SMatt Spinler entry("NAME = %s", name.c_str())); 344*ce675228SMatt Spinler } 345*ce675228SMatt Spinler } 346*ce675228SMatt Spinler else if (hardShutdownIface->hardShutdownAlarmHigh()) 347*ce675228SMatt Spinler { 348*ce675228SMatt Spinler hardShutdownIface->hardShutdownAlarmHigh(false); 349*ce675228SMatt Spinler log<level::INFO>("DEASSERT: Virtual Sensor is under " 350*ce675228SMatt Spinler "hardShutdown high threshold", 351*ce675228SMatt Spinler entry("NAME = %s", name.c_str())); 352*ce675228SMatt Spinler } 353*ce675228SMatt Spinler 354*ce675228SMatt Spinler if (value <= hardShutdownIface->hardShutdownLow()) 355*ce675228SMatt Spinler { 356*ce675228SMatt Spinler if (!hardShutdownIface->hardShutdownAlarmLow()) 357*ce675228SMatt Spinler { 358*ce675228SMatt Spinler hardShutdownIface->hardShutdownAlarmLow(true); 359*ce675228SMatt Spinler log<level::ERR>("ASSERT: Virtual Sensor is under " 360*ce675228SMatt Spinler "hardShutdown low threshold", 361*ce675228SMatt Spinler entry("NAME = %s", name.c_str())); 362*ce675228SMatt Spinler } 363*ce675228SMatt Spinler } 364*ce675228SMatt Spinler else if (hardShutdownIface->hardShutdownAlarmLow()) 365*ce675228SMatt Spinler { 366*ce675228SMatt Spinler hardShutdownIface->hardShutdownAlarmLow(false); 367*ce675228SMatt Spinler log<level::INFO>("DEASSERT: Virtual Sensor is above " 368*ce675228SMatt Spinler "hardShutdown low threshold", 369*ce675228SMatt Spinler entry("NAME = %s", name.c_str())); 370*ce675228SMatt Spinler } 371*ce675228SMatt Spinler } 372*ce675228SMatt Spinler } 373*ce675228SMatt Spinler 374abcc94faSVijay Khemka void VirtualSensor::updateVirtualSensor() 3753ed9a516SVijay Khemka { 3763ed9a516SVijay Khemka for (auto& param : paramMap) 3773ed9a516SVijay Khemka { 3783ed9a516SVijay Khemka auto& name = param.first; 3793ed9a516SVijay Khemka auto& data = param.second; 3803ed9a516SVijay Khemka if (auto var = symbols.get_variable(name)) 3813ed9a516SVijay Khemka { 3823ed9a516SVijay Khemka var->ref() = data->getParamValue(); 3833ed9a516SVijay Khemka } 3843ed9a516SVijay Khemka else 3853ed9a516SVijay Khemka { 3863ed9a516SVijay Khemka /* Invalid parameter */ 3873ed9a516SVijay Khemka throw std::invalid_argument("ParamName not found in symbols"); 3883ed9a516SVijay Khemka } 3893ed9a516SVijay Khemka } 3903ed9a516SVijay Khemka double val = expression.value(); 39132a7156bSVijay Khemka 39232a7156bSVijay Khemka /* Set sensor value to dbus interface */ 3933ed9a516SVijay Khemka setSensorValue(val); 39432a7156bSVijay Khemka 3953ed9a516SVijay Khemka if (DEBUG) 3963ed9a516SVijay Khemka std::cout << "Sensor value is " << val << "\n"; 39732a7156bSVijay Khemka 39832a7156bSVijay Khemka /* Check sensor threshold and log required message */ 39932a7156bSVijay Khemka checkSensorThreshold(val); 4003ed9a516SVijay Khemka } 401abcc94faSVijay Khemka 402abcc94faSVijay Khemka /** @brief Parsing Virtual Sensor config JSON file */ 403abcc94faSVijay Khemka Json VirtualSensors::parseConfigFile(const std::string configFile) 404abcc94faSVijay Khemka { 405abcc94faSVijay Khemka std::ifstream jsonFile(configFile); 406abcc94faSVijay Khemka if (!jsonFile.is_open()) 407abcc94faSVijay Khemka { 408abcc94faSVijay Khemka log<level::ERR>("config JSON file not found", 409abcc94faSVijay Khemka entry("FILENAME = %s", configFile.c_str())); 410abcc94faSVijay Khemka throw std::exception{}; 411abcc94faSVijay Khemka } 412abcc94faSVijay Khemka 413abcc94faSVijay Khemka auto data = Json::parse(jsonFile, nullptr, false); 414abcc94faSVijay Khemka if (data.is_discarded()) 415abcc94faSVijay Khemka { 416abcc94faSVijay Khemka log<level::ERR>("config readings JSON parser failure", 417abcc94faSVijay Khemka entry("FILENAME = %s", configFile.c_str())); 418abcc94faSVijay Khemka throw std::exception{}; 419abcc94faSVijay Khemka } 420abcc94faSVijay Khemka 421abcc94faSVijay Khemka return data; 422abcc94faSVijay Khemka } 423abcc94faSVijay Khemka 424e0d371e4SVijay Khemka std::map<std::string, ValueIface::Unit> unitMap = { 425e0d371e4SVijay Khemka {"temperature", ValueIface::Unit::DegreesC}, 426e0d371e4SVijay Khemka {"fan_tach", ValueIface::Unit::RPMS}, 427e0d371e4SVijay Khemka {"voltage", ValueIface::Unit::Volts}, 428e0d371e4SVijay Khemka {"altitude", ValueIface::Unit::Meters}, 429e0d371e4SVijay Khemka {"current", ValueIface::Unit::Amperes}, 430e0d371e4SVijay Khemka {"power", ValueIface::Unit::Watts}, 431e0d371e4SVijay Khemka {"energy", ValueIface::Unit::Joules}, 432e0d371e4SVijay Khemka {"utilization", ValueIface::Unit::Percent}}; 433e0d371e4SVijay Khemka 434abcc94faSVijay Khemka void VirtualSensors::createVirtualSensors() 435abcc94faSVijay Khemka { 436abcc94faSVijay Khemka static const Json empty{}; 437abcc94faSVijay Khemka 438abcc94faSVijay Khemka auto data = parseConfigFile(VIRTUAL_SENSOR_CONFIG_FILE); 439abcc94faSVijay Khemka // print values 440abcc94faSVijay Khemka if (DEBUG) 441abcc94faSVijay Khemka std::cout << "Config json data:\n" << data << "\n\n"; 442abcc94faSVijay Khemka 443abcc94faSVijay Khemka /* Get virtual sensors config data */ 444abcc94faSVijay Khemka for (const auto& j : data) 445abcc94faSVijay Khemka { 446abcc94faSVijay Khemka auto desc = j.value("Desc", empty); 447abcc94faSVijay Khemka if (!desc.empty()) 448abcc94faSVijay Khemka { 449abcc94faSVijay Khemka std::string sensorType = desc.value("SensorType", ""); 450abcc94faSVijay Khemka std::string name = desc.value("Name", ""); 451abcc94faSVijay Khemka 452abcc94faSVijay Khemka if (!name.empty() && !sensorType.empty()) 453abcc94faSVijay Khemka { 454e0d371e4SVijay Khemka if (unitMap.find(sensorType) == unitMap.end()) 455e0d371e4SVijay Khemka { 456e0d371e4SVijay Khemka log<level::ERR>("Sensor type is not supported", 457e0d371e4SVijay Khemka entry("TYPE = %s", sensorType.c_str())); 458e0d371e4SVijay Khemka } 459e0d371e4SVijay Khemka else 460e0d371e4SVijay Khemka { 461abcc94faSVijay Khemka std::string objPath(sensorDbusPath); 462abcc94faSVijay Khemka objPath += sensorType + "/" + name; 463abcc94faSVijay Khemka 46432a7156bSVijay Khemka auto virtualSensorPtr = std::make_unique<VirtualSensor>( 46532a7156bSVijay Khemka bus, objPath.c_str(), j, name); 466abcc94faSVijay Khemka 467abcc94faSVijay Khemka log<level::INFO>("Added a new virtual sensor", 468abcc94faSVijay Khemka entry("NAME = %s", name.c_str())); 4693ed9a516SVijay Khemka virtualSensorPtr->updateVirtualSensor(); 470e0d371e4SVijay Khemka 471e0d371e4SVijay Khemka /* Initialize unit value for virtual sensor */ 472e0d371e4SVijay Khemka virtualSensorPtr->ValueIface::unit(unitMap[sensorType]); 473e0d371e4SVijay Khemka 4743ed9a516SVijay Khemka virtualSensorsMap.emplace(std::move(name), 4753ed9a516SVijay Khemka std::move(virtualSensorPtr)); 476abcc94faSVijay Khemka } 477e0d371e4SVijay Khemka } 478abcc94faSVijay Khemka else 479abcc94faSVijay Khemka { 480abcc94faSVijay Khemka log<level::ERR>("Sensor type or name not found in config file"); 481abcc94faSVijay Khemka } 482abcc94faSVijay Khemka } 483abcc94faSVijay Khemka else 484abcc94faSVijay Khemka { 485abcc94faSVijay Khemka log<level::ERR>( 486abcc94faSVijay Khemka "Descriptor for new virtual sensor not found in config file"); 487abcc94faSVijay Khemka } 488abcc94faSVijay Khemka } 489abcc94faSVijay Khemka } 490abcc94faSVijay Khemka 491abcc94faSVijay Khemka } // namespace virtualSensor 492abcc94faSVijay Khemka } // namespace phosphor 493abcc94faSVijay Khemka 494abcc94faSVijay Khemka /** 495abcc94faSVijay Khemka * @brief Main 496abcc94faSVijay Khemka */ 497abcc94faSVijay Khemka int main() 498abcc94faSVijay Khemka { 499abcc94faSVijay Khemka 500abcc94faSVijay Khemka // Get a default event loop 501abcc94faSVijay Khemka auto event = sdeventplus::Event::get_default(); 502abcc94faSVijay Khemka 503abcc94faSVijay Khemka // Get a handle to system dbus 504abcc94faSVijay Khemka auto bus = sdbusplus::bus::new_default(); 505abcc94faSVijay Khemka 5066c19e7d2SMatt Spinler // Add the ObjectManager interface 5076c19e7d2SMatt Spinler sdbusplus::server::manager::manager objManager(bus, "/"); 5086c19e7d2SMatt Spinler 509abcc94faSVijay Khemka // Create an virtual sensors object 510abcc94faSVijay Khemka phosphor::virtualSensor::VirtualSensors virtualSensors(bus); 511abcc94faSVijay Khemka 512abcc94faSVijay Khemka // Request service bus name 513abcc94faSVijay Khemka bus.request_name(busName); 514abcc94faSVijay Khemka 515abcc94faSVijay Khemka // Attach the bus to sd_event to service user requests 516abcc94faSVijay Khemka bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 517abcc94faSVijay Khemka event.loop(); 518abcc94faSVijay Khemka 519abcc94faSVijay Khemka return 0; 520abcc94faSVijay Khemka } 521