1 #include "virtualSensor.hpp" 2 3 #include "config.hpp" 4 5 #include <phosphor-logging/log.hpp> 6 #include <sdeventplus/event.hpp> 7 8 #include <fstream> 9 #include <iostream> 10 11 static constexpr bool DEBUG = false; 12 static constexpr auto busName = "xyz.openbmc_project.VirtualSensor"; 13 static constexpr auto sensorDbusPath = "/xyz/openbmc_project/sensors/"; 14 static constexpr uint8_t defaultHighThreshold = 100; 15 static constexpr uint8_t defaultLowThreshold = 0; 16 17 using namespace phosphor::logging; 18 19 namespace phosphor 20 { 21 namespace virtualSensor 22 { 23 24 void printParams(const VirtualSensor::ParamMap& paramMap) 25 { 26 for (const auto& p : paramMap) 27 { 28 const auto& p1 = p.first; 29 const auto& p2 = p.second; 30 auto val = p2->getParamValue(); 31 std::cout << p1 << " = " << val << "\n"; 32 } 33 } 34 35 double SensorParam::getParamValue() 36 { 37 switch (paramType) 38 { 39 case constParam: 40 return value; 41 break; 42 case dbusParam: 43 return dbusSensor->getSensorValue(); 44 break; 45 default: 46 throw std::invalid_argument("param type not supported"); 47 } 48 } 49 50 void VirtualSensor::initVirtualSensor(const Json& sensorConfig) 51 { 52 53 static const Json empty{}; 54 55 /* Get threshold values if defined in config */ 56 auto threshold = sensorConfig.value("Threshold", empty); 57 if (!threshold.empty()) 58 { 59 sensorThreshold.criticalHigh = 60 threshold.value("CriticalHigh", defaultHighThreshold); 61 sensorThreshold.criticalLow = 62 threshold.value("CriticalLow", defaultLowThreshold); 63 sensorThreshold.warningHigh = 64 threshold.value("WarningHigh", defaultHighThreshold); 65 sensorThreshold.warningLow = 66 threshold.value("WarningLow", defaultLowThreshold); 67 } 68 69 /* Set threshold value to dbus */ 70 setSensorThreshold(); 71 72 /* Get expression string */ 73 exprStr = sensorConfig.value("Expression", ""); 74 75 /* Get all the parameter listed in configuration */ 76 auto params = sensorConfig.value("Params", empty); 77 78 /* Check for constant parameter */ 79 const auto& consParams = params.value("ConstParam", empty); 80 if (!consParams.empty()) 81 { 82 for (auto& j : consParams) 83 { 84 if (j.find("ParamName") != j.end()) 85 { 86 auto paramPtr = std::make_unique<SensorParam>(j["Value"]); 87 std::string name = j["ParamName"]; 88 symbols.create_variable(name); 89 paramMap.emplace(std::move(name), std::move(paramPtr)); 90 } 91 else 92 { 93 /* Invalid configuration */ 94 throw std::invalid_argument( 95 "ParamName not found in configuration"); 96 } 97 } 98 } 99 100 /* Check for dbus parameter */ 101 auto dbusParams = params.value("DbusParam", empty); 102 if (!dbusParams.empty()) 103 { 104 for (auto& j : dbusParams) 105 { 106 /* Get parameter dbus sensor descriptor */ 107 auto desc = j.value("Desc", empty); 108 if ((!desc.empty()) && (j.find("ParamName") != j.end())) 109 { 110 std::string sensorType = desc.value("SensorType", ""); 111 std::string name = desc.value("Name", ""); 112 113 if (!sensorType.empty() && !name.empty()) 114 { 115 std::string objPath(sensorDbusPath); 116 objPath += sensorType + "/" + name; 117 118 auto paramPtr = std::make_unique<SensorParam>(bus, objPath); 119 std::string name = j["ParamName"]; 120 symbols.create_variable(name); 121 paramMap.emplace(std::move(name), std::move(paramPtr)); 122 } 123 } 124 } 125 } 126 127 symbols.add_constants(); 128 expression.register_symbol_table(symbols); 129 130 /* parser from exprtk */ 131 exprtk::parser<double> parser{}; 132 parser.compile(exprStr, expression); 133 134 /* Print all parameters for debug purpose only */ 135 if (DEBUG) 136 printParams(paramMap); 137 } 138 139 void VirtualSensor::setSensorValue(double value) 140 { 141 ValueIface::value(value); 142 } 143 144 void VirtualSensor::setSensorThreshold() 145 { 146 CriticalInterface::criticalHigh(sensorThreshold.criticalHigh); 147 CriticalInterface::criticalLow(sensorThreshold.criticalLow); 148 WarningInterface::warningHigh(sensorThreshold.warningHigh); 149 WarningInterface::warningLow(sensorThreshold.warningLow); 150 } 151 152 void VirtualSensor::updateVirtualSensor() 153 { 154 for (auto& param : paramMap) 155 { 156 auto& name = param.first; 157 auto& data = param.second; 158 if (auto var = symbols.get_variable(name)) 159 { 160 var->ref() = data->getParamValue(); 161 } 162 else 163 { 164 /* Invalid parameter */ 165 throw std::invalid_argument("ParamName not found in symbols"); 166 } 167 } 168 double val = expression.value(); 169 setSensorValue(val); 170 if (DEBUG) 171 std::cout << "Sensor value is " << val << "\n"; 172 } 173 174 /** @brief Parsing Virtual Sensor config JSON file */ 175 Json VirtualSensors::parseConfigFile(const std::string configFile) 176 { 177 std::ifstream jsonFile(configFile); 178 if (!jsonFile.is_open()) 179 { 180 log<level::ERR>("config JSON file not found", 181 entry("FILENAME = %s", configFile.c_str())); 182 throw std::exception{}; 183 } 184 185 auto data = Json::parse(jsonFile, nullptr, false); 186 if (data.is_discarded()) 187 { 188 log<level::ERR>("config readings JSON parser failure", 189 entry("FILENAME = %s", configFile.c_str())); 190 throw std::exception{}; 191 } 192 193 return data; 194 } 195 196 void VirtualSensors::createVirtualSensors() 197 { 198 static const Json empty{}; 199 200 auto data = parseConfigFile(VIRTUAL_SENSOR_CONFIG_FILE); 201 // print values 202 if (DEBUG) 203 std::cout << "Config json data:\n" << data << "\n\n"; 204 205 /* Get virtual sensors config data */ 206 for (const auto& j : data) 207 { 208 auto desc = j.value("Desc", empty); 209 if (!desc.empty()) 210 { 211 std::string sensorType = desc.value("SensorType", ""); 212 std::string name = desc.value("Name", ""); 213 214 if (!name.empty() && !sensorType.empty()) 215 { 216 std::string objPath(sensorDbusPath); 217 objPath += sensorType + "/" + name; 218 219 auto virtualSensorPtr = 220 std::make_unique<VirtualSensor>(bus, objPath.c_str(), j); 221 222 log<level::INFO>("Added a new virtual sensor", 223 entry("NAME = %s", name.c_str())); 224 virtualSensorPtr->updateVirtualSensor(); 225 virtualSensorsMap.emplace(std::move(name), 226 std::move(virtualSensorPtr)); 227 } 228 else 229 { 230 log<level::ERR>("Sensor type or name not found in config file"); 231 } 232 } 233 else 234 { 235 log<level::ERR>( 236 "Descriptor for new virtual sensor not found in config file"); 237 } 238 } 239 } 240 241 } // namespace virtualSensor 242 } // namespace phosphor 243 244 /** 245 * @brief Main 246 */ 247 int main() 248 { 249 250 // Get a default event loop 251 auto event = sdeventplus::Event::get_default(); 252 253 // Get a handle to system dbus 254 auto bus = sdbusplus::bus::new_default(); 255 256 // Create an virtual sensors object 257 phosphor::virtualSensor::VirtualSensors virtualSensors(bus); 258 259 // Request service bus name 260 bus.request_name(busName); 261 262 // Attach the bus to sd_event to service user requests 263 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 264 event.loop(); 265 266 return 0; 267 } 268