Support derivative term in PID algorithm and support to set cycle interval time from fan table

1. Support to calculate derivative term in PID algorithm.
2. Add two properties: cycleIntervalTimeMS and updateThermalsTimeMS
in fan table that could be used to decide "time interval of PID control loop"
and "time interval to update thermals' cached value".

Tested:

- PID algorithm:
    1. Check pid-control-service could calculate output PWM
       according to the fan table.

	[Test log]
        root@greatlakes:~# systemctl status phosphor-pid-control -l
        * phosphor-pid-control.service - Phosphor-Pid-Control Margin-based Fan Control Daemon
             Loaded: loaded (/lib/systemd/system/phosphor-pid-control.service; enabled; preset: enabled)
             Active: active (running) since Fri 2018-03-09 05:09:35 PST; 1min 47s ago
           Main PID: 3105 (swampd)
             CGroup: /system.slice/phosphor-pid-control.service
                     `-3105 /usr/bin/swampd -c /usr/share/entity-manager/configurations/fan-table.json
        ...
        Mar 09 05:10:29 greatlakes phosphor-pid-control[3105]: PID Zone 1 max SetPoint 3.75 requested by
        PID_NIC_SENSOR_TEMP BMC_SENSOR_FAN0_TACH BMC_SENSOR_FAN2_TACH BMC_SENSOR_FAN4_TACH BMC_SENSOR_FAN6_TACH

- Cycle interval time:
    1. Set cycleIntervalTimeMS and updateThermalsTimeMS
       to 1000 ms in fan table
    2. Check service would update thermal every second from debug log.

	[Test log]
        root@greatlakes:~# journalctl -u phosphor-pid-control --since "Mar 09 04:52:16"
        Mar 09 04:52:16 greatlakes systemd[1]: Started Phosphor-Pid-Control Margin-based Fan Control Daemon.
        ...
        Mar 09 04:53:28 greatlakes phosphor-pid-control[2795]: processThermals
        Mar 09 04:53:28 greatlakes phosphor-pid-control[2795]: processFans
        Mar 09 04:53:29 greatlakes phosphor-pid-control[2795]: processThermals
        Mar 09 04:53:29 greatlakes phosphor-pid-control[2795]: processFans
        Mar 09 04:53:30 greatlakes phosphor-pid-control[2795]: processThermals
        Mar 09 04:53:30 greatlakes phosphor-pid-control[2795]: processFans

Change-Id: I04e1b440603c3ad66a1e26c96451992785da6fe6
Signed-off-by: Bonnie Lo <Bonnie_Lo@wiwynn.com>
diff --git a/test/pid_json_unittest.cpp b/test/pid_json_unittest.cpp
index f243212..b6963cd 100644
--- a/test/pid_json_unittest.cpp
+++ b/test/pid_json_unittest.cpp
@@ -50,6 +50,7 @@
               "samplePeriod": 0.1,
               "proportionalCoeff": 0.0,
               "integralCoeff": 0.0,
+              "derivativeCoeff": 0.0,
               "feedFwdOffsetCoeff": 0.0,
               "feedFwdGainCoeff": 0.010,
               "integralLimit_min": 0.0,
@@ -95,6 +96,7 @@
               "samplePeriod": 0.1,
               "proportionalCoeff": 0.0,
               "integralCoeff": 0.0,
+              "derivativeCoeff": 0.0,
               "feedFwdOffsetCoeff": 0.0,
               "feedFwdGainCoeff": 0.010,
               "integralLimit_min": 0.0,
@@ -206,5 +208,57 @@
     EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
 }
 
+TEST(ZoneFromJson, getCycleInterval)
+{
+    // Parse a valid configuration with one zone and one PID and the zone have
+    // cycleIntervalTime and updateThermalsTime parameters.
+
+    std::map<int64_t, conf::PIDConf> pidConfig;
+    std::map<int64_t, conf::ZoneConfig> zoneConfig;
+
+    auto j2 = R"(
+      {
+        "zones" : [{
+          "id": 1,
+          "minThermalOutput": 3000.0,
+          "failsafePercent": 75.0,
+          "cycleIntervalTimeMS": 1000.0,
+          "updateThermalsTimeMS": 1000.0,
+          "pids": [{
+            "name": "fan1-5",
+            "type": "fan",
+            "inputs": ["fan1", "fan5"],
+            "setpoint": 90.0,
+            "pid": {
+              "samplePeriod": 0.1,
+              "proportionalCoeff": 0.0,
+              "integralCoeff": 0.0,
+              "derivativeCoeff": 0.0,
+              "feedFwdOffsetCoeff": 0.0,
+              "feedFwdGainCoeff": 0.010,
+              "integralLimit_min": 0.0,
+              "integralLimit_max": 0.0,
+              "outLim_min": 30.0,
+              "outLim_max": 100.0,
+              "slewNeg": 0.0,
+              "slewPos": 0.0
+            }
+          }]
+        }]
+      }
+    )"_json;
+
+    std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
+    EXPECT_EQ(pidConfig.size(), 1);
+    EXPECT_EQ(zoneConfig.size(), 1);
+
+    EXPECT_EQ(pidConfig[1]["fan1-5"].type, "fan");
+    EXPECT_EQ(zoneConfig[1].cycleTime.cycleIntervalTimeMS, 1000);
+    // updateThermalsTimeMS would be updated as updateThermalsTimeMS /
+    // cycleIntervalTimeMS
+    EXPECT_EQ(zoneConfig[1].cycleTime.updateThermalsTimeMS, 1);
+    EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
+}
+
 } // namespace
 } // namespace pid_control
diff --git a/test/pid_zone_unittest.cpp b/test/pid_zone_unittest.cpp
index 275dfe6..2c0e147 100644
--- a/test/pid_zone_unittest.cpp
+++ b/test/pid_zone_unittest.cpp
@@ -50,14 +50,15 @@
     int64_t zone = 1;
     double minThermalOutput = 1000.0;
     double failSafePercent = 0.75;
+    conf::CycleTime cycleTime;
 
     double d;
     std::vector<std::string> properties;
     SetupDbusObject(&sdbus_mock_mode, defer, objPath, modeInterface, properties,
                     &d);
 
-    DbusPidZone p(zone, minThermalOutput, failSafePercent, m, bus_mock_mode,
-                  objPath, defer);
+    DbusPidZone p(zone, minThermalOutput, failSafePercent, cycleTime, m,
+                  bus_mock_mode, objPath, defer);
     // Success.
 }
 
@@ -87,7 +88,7 @@
                         properties, &property_index);
 
         zone = std::make_unique<DbusPidZone>(zoneId, minThermalOutput,
-                                             failSafePercent, mgr,
+                                             failSafePercent, cycleTime, mgr,
                                              bus_mock_mode, objPath, defer);
     }
 
@@ -104,6 +105,7 @@
     bool defer = true;
     const char* objPath = "/path/";
     SensorManager mgr;
+    conf::CycleTime cycleTime;
 
     std::unique_ptr<DbusPidZone> zone;
 };
diff --git a/test/zone_mock.hpp b/test/zone_mock.hpp
index f2620d5..9c80a50 100644
--- a/test/zone_mock.hpp
+++ b/test/zone_mock.hpp
@@ -36,6 +36,9 @@
     MOCK_CONST_METHOD0(getFailSafeMode, bool());
     MOCK_CONST_METHOD0(getFailSafePercent, double());
 
+    MOCK_CONST_METHOD0(getCycleIntervalTime, uint64_t());
+    MOCK_CONST_METHOD0(getUpdateThermalsCycle, uint64_t());
+
     MOCK_METHOD1(getSensor, Sensor*(const std::string&));
 
     MOCK_METHOD0(initializeLog, void());