Use exprtk expression parser

Using expression parser tool exprtk to calculate sensor value
from given expression from config file.

Signed-off-by: Vijay Khemka <vijaykhemka@fb.com>
Change-Id: Ie765748374a2c7a82ab9689b57c63fce7b015364
diff --git a/meson.build b/meson.build
index 4258e5e..6de3ea0 100644
--- a/meson.build
+++ b/meson.build
@@ -7,6 +7,17 @@
     ],
 )
 
+cpp = meson.get_compiler('cpp')
+if cpp.has_header('exprtk.hpp')
+    exprtk = declare_dependency()
+else
+    subproject('exprtk', required: false)
+    exprtk = declare_dependency(
+        include_directories: 'subprojects/exprtk'
+    )
+endif
+
+
 executable(
     'virtual-sensor',
     [
@@ -17,6 +28,7 @@
         dependency('sdbusplus'),
         dependency('phosphor-dbus-interfaces'),
         dependency('sdeventplus'),
+        exprtk,
     ],
     install: true,
     install_dir: get_option('bindir')
diff --git a/subprojects/exprtk.wrap b/subprojects/exprtk.wrap
new file mode 100644
index 0000000..4143d1f
--- /dev/null
+++ b/subprojects/exprtk.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+revision = 281c2ccc65b8f91c012ea3725ebcef406378a225
+url = https://github.com/ArashPartow/exprtk.git
diff --git a/virtualSensor.cpp b/virtualSensor.cpp
index 501d9cd..ac5e123 100644
--- a/virtualSensor.cpp
+++ b/virtualSensor.cpp
@@ -84,7 +84,9 @@
             if (j.find("ParamName") != j.end())
             {
                 auto paramPtr = std::make_unique<SensorParam>(j["Value"]);
-                paramMap.emplace(j["ParamName"], std::move(paramPtr));
+                std::string name = j["ParamName"];
+                symbols.create_variable(name);
+                paramMap.emplace(std::move(name), std::move(paramPtr));
             }
             else
             {
@@ -114,12 +116,21 @@
                     objPath += sensorType + "/" + name;
 
                     auto paramPtr = std::make_unique<SensorParam>(bus, objPath);
-                    paramMap.emplace(j["ParamName"], std::move(paramPtr));
+                    std::string name = j["ParamName"];
+                    symbols.create_variable(name);
+                    paramMap.emplace(std::move(name), std::move(paramPtr));
                 }
             }
         }
     }
 
+    symbols.add_constants();
+    expression.register_symbol_table(symbols);
+
+    /* parser from exprtk */
+    exprtk::parser<double> parser{};
+    parser.compile(exprStr, expression);
+
     /* Print all parameters for debug purpose only */
     if (DEBUG)
         printParams(paramMap);
@@ -138,9 +149,27 @@
     WarningInterface::warningLow(sensorThreshold.warningLow);
 }
 
-/* TBD */
 void VirtualSensor::updateVirtualSensor()
-{}
+{
+    for (auto& param : paramMap)
+    {
+        auto& name = param.first;
+        auto& data = param.second;
+        if (auto var = symbols.get_variable(name))
+        {
+            var->ref() = data->getParamValue();
+        }
+        else
+        {
+            /* Invalid parameter */
+            throw std::invalid_argument("ParamName not found in symbols");
+        }
+    }
+    double val = expression.value();
+    setSensorValue(val);
+    if (DEBUG)
+        std::cout << "Sensor value is " << val << "\n";
+}
 
 /** @brief Parsing Virtual Sensor config JSON file  */
 Json VirtualSensors::parseConfigFile(const std::string configFile)
@@ -189,10 +218,12 @@
 
                 auto virtualSensorPtr =
                     std::make_unique<VirtualSensor>(bus, objPath.c_str(), j);
-                virtualSensorsMap.emplace(name, std::move(virtualSensorPtr));
 
                 log<level::INFO>("Added a new virtual sensor",
                                  entry("NAME = %s", name.c_str()));
+                virtualSensorPtr->updateVirtualSensor();
+                virtualSensorsMap.emplace(std::move(name),
+                                          std::move(virtualSensorPtr));
             }
             else
             {
diff --git a/virtualSensor.hpp b/virtualSensor.hpp
index 6b11eb4..b632e15 100644
--- a/virtualSensor.hpp
+++ b/virtualSensor.hpp
@@ -1,4 +1,5 @@
 #include "dbusSensor.hpp"
+#include "exprtk.hpp"
 
 #include <nlohmann/json.hpp>
 #include <sdbusplus/bus.hpp>
@@ -95,6 +96,8 @@
 
     /** @brief Set sensor value */
     void setSensorValue(double value);
+    /** @brief Update sensor at regular intrval */
+    void updateVirtualSensor();
 
     /** @brief Map of list of parameters */
     using ParamMap =
@@ -108,6 +111,10 @@
     std::string exprStr;
     /** @brief Sensor Threshold config values */
     struct Threshold sensorThreshold;
+    /** @brief symbol table from exprtk */
+    exprtk::symbol_table<double> symbols{};
+    /** @brief expression from exprtk to calculate sensor value */
+    exprtk::expression<double> expression{};
 
     /** @brief Read config from json object and initialize sensor data
      * for each virtual sensor
@@ -115,8 +122,6 @@
     void initVirtualSensor(const Json& sensorConfig);
     /** @brief Set Sensor Threshold to D-bus at beginning */
     void setSensorThreshold();
-    /** @brief Update sensor at regular intrval */
-    void updateVirtualSensor();
 };
 
 class VirtualSensors