Add debug mode

Description:
    1. Could enable debug mode by adding file: /etc/thermal.d/debugging.
        $ mkdir /etc/thermal.d
        $ touch /etc/thermal.d/debugging
        $ systemctl restart phosphor-pid-control

    2. Could record fans output PWM, chosen temperature, PID/stepwise output PWM in debug mode.

Design:
    1. Create debugging file and restart service to enable debug mode.

    2. Check if debug mode is enabled to output fans output PWM, chosen temperature,
       PID/stepwise output PWM, and so on.

Test Case:
    1. Enable debug mode and check logs: pass

Change-Id: I8527ebcb81e723298ba7e786b4501f986ebd439e
Signed-off-by: Bonnie Lo <Bonnie_Lo@wiwynn.com>
diff --git a/main.cpp b/main.cpp
index 796c066..8ae6be5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -244,6 +244,7 @@
     loggingPath = "";
     loggingEnabled = false;
     tuningEnabled = false;
+    debugEnabled = false;
 
     CLI::App app{"OpenBMC Fan Control Daemon"};
 
@@ -254,11 +255,13 @@
                    "Optional parameter to specify logging folder")
         ->check(CLI::ExistingDirectory);
     app.add_flag("-t,--tuning", tuningEnabled, "Enable or disable tuning");
+    app.add_flag("-d,--debug", debugEnabled, "Enable or disable debug mode");
 
     CLI11_PARSE(app, argc, argv);
 
     static constexpr auto loggingEnablePath = "/etc/thermal.d/logging";
     static constexpr auto tuningEnablePath = "/etc/thermal.d/tuning";
+    static constexpr auto debugEnablePath = "/etc/thermal.d/debugging";
 
     // Set up default logging path, preferring command line if it was given
     std::string defLoggingPath(loggingPath);
@@ -306,6 +309,17 @@
         std::cerr << "Tuning enabled\n";
     }
 
+    // If this file exists, enable debug mode at runtime
+    if (std::filesystem::exists(debugEnablePath))
+    {
+        debugEnabled = true;
+    }
+
+    if (debugEnabled)
+    {
+        std::cerr << "Debug mode enabled\n";
+    }
+
     static constexpr auto modeRoot = "/xyz/openbmc_project/settings/fanctrl";
     // Create a manager for the ModeBus because we own it.
     sdbusplus::server::manager_t(static_cast<sdbusplus::bus_t&>(modeControlBus),
diff --git a/pid/fancontroller.cpp b/pid/fancontroller.cpp
index 57902ab..7d4a92d 100644
--- a/pid/fancontroller.cpp
+++ b/pid/fancontroller.cpp
@@ -145,8 +145,24 @@
             {
                 percent = failsafePercent;
             }
+
+            if (failsafePrint || debugEnabled)
+            {
+                std::cerr << "Zone " << _owner->getZoneID()
+                          << " fans output failsafe pwm: " << percent << "\n";
+                failsafePrint = false;
+            }
 #endif
         }
+        else
+        {
+            failsafePrint = true;
+            if (debugEnabled)
+            {
+                std::cerr << "Zone " << _owner->getZoneID()
+                          << " fans output pwm: " << percent << "\n";
+            }
+        }
     }
 
     // value and kFanFailSafeDutyCycle are 10 for 10% so let's fix that.
diff --git a/pid/fancontroller.hpp b/pid/fancontroller.hpp
index 25eebad..89b3d5e 100644
--- a/pid/fancontroller.hpp
+++ b/pid/fancontroller.hpp
@@ -47,6 +47,7 @@
   private:
     std::vector<std::string> _inputs;
     FanSpeedDirection _direction;
+    bool failsafePrint = true;
 };
 
 } // namespace pid_control
diff --git a/pid/stepwisecontroller.cpp b/pid/stepwisecontroller.cpp
index 5c36778..d141f87 100644
--- a/pid/stepwisecontroller.cpp
+++ b/pid/stepwisecontroller.cpp
@@ -18,6 +18,7 @@
 
 #include "ec/stepwise.hpp"
 #include "errors/exception.hpp"
+#include "tuning.hpp"
 #include "util.hpp"
 #include "zone.hpp"
 
@@ -90,6 +91,13 @@
     {
         value = std::max(value, _owner->getCachedValue(in));
     }
+
+    if (debugEnabled)
+    {
+        std::cerr << getID()
+                  << " choose the maximum temperature value: " << value << "\n";
+    }
+
     return value;
 }
 
@@ -102,6 +110,10 @@
     else
     {
         _owner->addSetPoint(value, _id);
+        if (debugEnabled)
+        {
+            std::cerr << getID() << " stepwise output pwm: " << value << "\n";
+        }
     }
     return;
 }
diff --git a/pid/thermalcontroller.cpp b/pid/thermalcontroller.cpp
index 71374a1..8778719 100644
--- a/pid/thermalcontroller.cpp
+++ b/pid/thermalcontroller.cpp
@@ -17,6 +17,7 @@
 #include "thermalcontroller.hpp"
 
 #include "errors/exception.hpp"
+#include "tuning.hpp"
 #include "util.hpp"
 #include "zone.hpp"
 
@@ -98,6 +99,12 @@
         value = 0;
     }
 
+    if (debugEnabled)
+    {
+        std::cerr << getID() << " choose the temperature value: " << value
+                  << "\n";
+    }
+
     return value;
 }
 
@@ -125,6 +132,11 @@
 {
     _owner->addSetPoint(value, _id);
 
+    if (debugEnabled)
+    {
+        std::cerr << getID() << " pid output pwm: " << value << "\n";
+    }
+
     return;
 }
 
diff --git a/pid/tuning.cpp b/pid/tuning.cpp
index 3422e34..38fa07b 100644
--- a/pid/tuning.cpp
+++ b/pid/tuning.cpp
@@ -20,3 +20,5 @@
 
 std::string loggingPath;
 bool loggingEnabled = false;
+
+bool debugEnabled = false;
diff --git a/pid/tuning.hpp b/pid/tuning.hpp
index ba4ec32..7f1cb63 100644
--- a/pid/tuning.hpp
+++ b/pid/tuning.hpp
@@ -11,3 +11,8 @@
 extern std::string loggingPath;
 /** Boolean variable whether loggingPath is non-empty. */
 extern bool loggingEnabled;
+
+/** Boolean variable controlling whether debug mode is enabled
+ * during this run.
+ */
+extern bool debugEnabled;
diff --git a/pid/zone.cpp b/pid/zone.cpp
index cac4577..69464e1 100644
--- a/pid/zone.cpp
+++ b/pid/zone.cpp
@@ -383,14 +383,27 @@
             _log << "," << p.scaled << "," << p.unscaled;
         }
 
+        if (debugEnabled)
+        {
+            std::cerr << f << " fan sensor reading: " << r.value << "\n";
+        }
+
         // check if fan fail.
         if (sensor->getFailed())
         {
             _failSafeSensors.insert(f);
+            if (debugEnabled)
+            {
+                std::cerr << f << " fan sensor get failed\n";
+            }
         }
         else if (timeout != 0 && duration >= period)
         {
             _failSafeSensors.insert(f);
+            if (debugEnabled)
+            {
+                std::cerr << f << " fan sensor timeout\n";
+            }
         }
         else
         {
@@ -398,6 +411,10 @@
             auto kt = _failSafeSensors.find(f);
             if (kt != _failSafeSensors.end())
             {
+                if (debugEnabled)
+                {
+                    std::cerr << f << " is erased from failsafe sensor set\n";
+                }
                 _failSafeSensors.erase(kt);
             }
         }
@@ -433,14 +450,28 @@
         auto duration = duration_cast<std::chrono::seconds>(now - then).count();
         auto period = std::chrono::seconds(timeout).count();
 
+        if (debugEnabled)
+        {
+            std::cerr << t << " temperature sensor reading: " << r.value
+                      << "\n";
+        }
+
         if (sensor->getFailed())
         {
             _failSafeSensors.insert(t);
+            if (debugEnabled)
+            {
+                std::cerr << t << " temperature sensor get failed\n";
+            }
         }
         else if (timeout != 0 && duration >= period)
         {
             // std::cerr << "Entering fail safe mode.\n";
             _failSafeSensors.insert(t);
+            if (debugEnabled)
+            {
+                std::cerr << t << " temperature sensor get timeout\n";
+            }
         }
         else
         {
@@ -448,6 +479,10 @@
             auto kt = _failSafeSensors.find(t);
             if (kt != _failSafeSensors.end())
             {
+                if (debugEnabled)
+                {
+                    std::cerr << t << " is erased from failsafe sensor set\n";
+                }
                 _failSafeSensors.erase(kt);
             }
         }
diff --git a/pid/zone.hpp b/pid/zone.hpp
index 41514a7..0504a6d 100644
--- a/pid/zone.hpp
+++ b/pid/zone.hpp
@@ -60,7 +60,7 @@
     void setManualMode(bool mode);
     bool getFailSafeMode(void) const override;
 
-    int64_t getZoneID(void) const;
+    int64_t getZoneID(void) const override;
     void addSetPoint(double setPoint, const std::string& name) override;
     double getMaxSetPointRequest(void) const override;
     void addRPMCeiling(double ceiling) override;
diff --git a/pid/zone_interface.hpp b/pid/zone_interface.hpp
index d7f73b4..179c856 100644
--- a/pid/zone_interface.hpp
+++ b/pid/zone_interface.hpp
@@ -16,6 +16,9 @@
   public:
     virtual ~ZoneInterface() = default;
 
+    /** Get Current Zone ID */
+    virtual int64_t getZoneID(void) const = 0;
+
     /** If the zone implementation supports logging, initialize the log. */
     virtual void initializeLog(void) = 0;
     /** If the zone implementation supports logging, write string to log. */
diff --git a/test/Makefile.am b/test/Makefile.am
index f978fa2..86493c6 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -50,11 +50,12 @@
 pid_thermalcontroller_unittest_SOURCES = pid_thermalcontroller_unittest.cpp
 pid_thermalcontroller_unittest_LDADD = $(top_builddir)/pid/ec/pid.o \
  $(top_builddir)/pid/util.o $(top_builddir)/pid/pidcontroller.o \
- $(top_builddir)/pid/thermalcontroller.o
+ $(top_builddir)/pid/thermalcontroller.o $(top_builddir)/pid/tuning.o
 
 pid_stepwisecontroller_unittest_SOURCES = pid_stepwisecontroller_unittest.cpp
 pid_stepwisecontroller_unittest_LDADD = $(top_builddir)/pid/ec/stepwise.o \
- $(top_builddir)/pid/util.o $(top_builddir)/pid/stepwisecontroller.o
+ $(top_builddir)/pid/util.o $(top_builddir)/pid/stepwisecontroller.o \
+ $(top_builddir)/pid/tuning.o
 
 pid_fancontroller_unittest_SOURCES = pid_fancontroller_unittest.cpp
 pid_fancontroller_unittest_LDADD = $(top_builddir)/pid/ec/pid.o \
diff --git a/test/zone_mock.hpp b/test/zone_mock.hpp
index 9c80a50..b63408f 100644
--- a/test/zone_mock.hpp
+++ b/test/zone_mock.hpp
@@ -35,6 +35,7 @@
     MOCK_CONST_METHOD0(getManualMode, bool());
     MOCK_CONST_METHOD0(getFailSafeMode, bool());
     MOCK_CONST_METHOD0(getFailSafePercent, double());
+    MOCK_CONST_METHOD0(getZoneID, int64_t());
 
     MOCK_CONST_METHOD0(getCycleIntervalTime, uint64_t());
     MOCK_CONST_METHOD0(getUpdateThermalsCycle, uint64_t());