Add support for debug card critical sensors

List of critical sensors read from json file cri_sensors.json
and its name along with current values will be displayed on
debug card screen.

Tested: verified with lcd debug card screen.

Change-Id: I1c7968b1d57efa9bf5e4cf8c7396fbeecbfbfd3a
Signed-off-by: Vijay Khemka <vijaykhemka@fb.com>
diff --git a/src/storagecommands.cpp b/src/storagecommands.cpp
index d64ebf4..d38008e 100644
--- a/src/storagecommands.cpp
+++ b/src/storagecommands.cpp
@@ -810,6 +810,56 @@
     return IPMI_CC_OK;
 }
 
+static int getSensorConnectionByName(std::string &name, std::string &connection,
+                                     std::string &path)
+{
+    if (sensorTree.empty() && !getSensorSubtree(sensorTree))
+    {
+        return -1;
+    }
+
+    for (const auto &sensor : sensorTree)
+    {
+        path = sensor.first;
+        if (path.find(name) != std::string::npos)
+        {
+            connection = sensor.second.begin()->first;
+            return 0;
+        }
+    }
+    return -1;
+}
+
+int getSensorValue(std::string &name, double &val)
+{
+    std::string connection;
+    std::string path;
+    int ret = -1;
+
+    ret = getSensorConnectionByName(name, connection, path);
+    if (ret < 0)
+    {
+        return ret;
+    }
+
+    SensorMap sensorMap;
+    if (!getSensorMap(connection, path, sensorMap))
+    {
+        return ret;
+    }
+    auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
+
+    if (sensorObject == sensorMap.end() ||
+        sensorObject->second.find("Value") == sensorObject->second.end())
+    {
+        return ret;
+    }
+    auto &valueVariant = sensorObject->second["Value"];
+    val = std::visit(VariantToDoubleVisitor(), valueVariant);
+
+    return 0;
+}
+
 void registerStorageFunctions()
 {
     // <READ FRU Data>
diff --git a/src/usb-dbg.cpp b/src/usb-dbg.cpp
index 6e3847f..dc6522e 100644
--- a/src/usb-dbg.cpp
+++ b/src/usb-dbg.cpp
@@ -22,6 +22,7 @@
 
 #include <fstream>
 #include <iostream>
+#include <sstream>
 #include <phosphor-logging/log.hpp>
 #include <appcommands.hpp>
 
@@ -30,6 +31,7 @@
 
 #define JSON_POST_DATA_FILE "/usr/share/lcd-debug/post_desc.json"
 #define JSON_GPIO_DATA_FILE "/usr/share/lcd-debug/gpio_desc.json"
+#define JSON_SENSOR_NAMES_FILE "/usr/share/lcd-debug/cri_sensors.json"
 
 #define ETH_INTF_NAME "eth0"
 
@@ -62,6 +64,12 @@
 ipmi_ret_t getNetworkData(uint8_t lan_param, char *data);
 int8_t getFruData(std::string &serial, std::string &name);
 
+/* Declare storage functions used here */
+namespace storage
+{
+int getSensorValue(std::string &, double &);
+}
+
 typedef struct _sensor_desc
 {
     char name[16];
@@ -586,7 +594,6 @@
     return -1;
 }
 
-/* Need to implement this */
 int plat_udbg_get_gpio_desc(uint8_t index, uint8_t *next, uint8_t *level,
                             uint8_t *def, uint8_t *length, uint8_t *buffer)
 {
@@ -750,13 +757,8 @@
 static int udbg_get_cri_sensor(uint8_t frame, uint8_t page, uint8_t *next,
                                uint8_t *count, uint8_t *buffer)
 {
-    char str[32], temp_val[16], temp_thresh[8], print_format[32];
-    int i, ret;
-    float fvalue;
-    sensor_desc_t *cri_sensor = NULL;
-    size_t sensor_count = 0;
-    uint8_t pos = plat_get_fru_sel();
-    uint8_t fru;
+    int ret;
+    double fvalue;
 
     if (page == 1)
     {
@@ -765,7 +767,54 @@
         // initialize and clear frame
         frame_snr.init(FRAME_BUFF_SIZE);
         snprintf(frame_snr.title, 32, "CriSensor");
-        frame_snr.append(str, 0);
+
+        nlohmann::json senObj;
+
+        /* Get critical sensor names stored in json file */
+        std::ifstream file(JSON_SENSOR_NAMES_FILE);
+        if (file)
+        {
+            file >> senObj;
+            file.close();
+        }
+        else
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Critical Sensor names file not found",
+                phosphor::logging::entry("CRI_SENSOR_NAMES_FILE=%s",
+                                         JSON_SENSOR_NAMES_FILE));
+            return -1;
+        }
+
+        /* Get sensors values for all critical sensors */
+        for (auto &j : senObj.items())
+        {
+            std::string senName = j.key();
+            auto val = j.value();
+
+            if (ipmi::storage::getSensorValue(senName, fvalue) == 0)
+            {
+                std::stringstream ss;
+                ss << fvalue;
+
+                std::string senStr;
+                if (val.find("short_name") != val.end())
+                    senStr = val["short_name"];
+                else
+                    senStr = senName;
+
+                senStr += ss.str();
+                frame_snr.append(senStr.c_str(), 0);
+            }
+            else
+            {
+                phosphor::logging::log<phosphor::logging::level::INFO>(
+                    "Critical sensor not found",
+                    phosphor::logging::entry("CRI_SENSOR_NAME=%s",
+                                             senName.c_str()));
+            }
+        }
+
     } // End of update frame
 
     if (page > frame_snr.pages)