Send high/low alarm signal when sensor reading exceeds threshold

The change to the xyz.openbmc_project.Sensor.Threshold.Warning and
xyz.openbmc_project.Sensor.Threshold.Critical interface that add
the new signals WarningHighAlarmAsserted, WarningHighAlarmDeasserted,
WarningLowAlarmAsserted, WarningLowAlarmDeasserted,
CriticalHighAlarmAsserted, CriticalHighAlarmDeasserted,
CriticalLowAlarmAsserted and CriticalLowAlarmDeasserted.

When sensor reading exceeds the threshold, hwmon would send the signal
with the sensor reading value at that time.

Tested:
Use dbus-monitor command to check the signal is captured, when hwmon
send signals.

Signed-off-by: Duke Du <Duke.Du@quantatw.com>
Change-Id: Ibf050b8bcff128cf77fd103c6d2bd1f30700b27b
diff --git a/mainloop.cpp b/mainloop.cpp
index 3e7e0bf..ecceee5 100644
--- a/mainloop.cpp
+++ b/mainloop.cpp
@@ -59,6 +59,22 @@
 decltype(
     Thresholds<WarningObject>::alarmHi) Thresholds<WarningObject>::alarmHi =
     &WarningObject::warningAlarmHigh;
+decltype(Thresholds<WarningObject>::getAlarmLow)
+    Thresholds<WarningObject>::getAlarmLow = &WarningObject::warningAlarmLow;
+decltype(Thresholds<WarningObject>::getAlarmHigh)
+    Thresholds<WarningObject>::getAlarmHigh = &WarningObject::warningAlarmHigh;
+decltype(Thresholds<WarningObject>::assertLowSignal)
+    Thresholds<WarningObject>::assertLowSignal =
+        &WarningObject::warningLowAlarmAsserted;
+decltype(Thresholds<WarningObject>::assertHighSignal)
+    Thresholds<WarningObject>::assertHighSignal =
+        &WarningObject::warningHighAlarmAsserted;
+decltype(Thresholds<WarningObject>::deassertLowSignal)
+    Thresholds<WarningObject>::deassertLowSignal =
+        &WarningObject::warningLowAlarmDeasserted;
+decltype(Thresholds<WarningObject>::deassertHighSignal)
+    Thresholds<WarningObject>::deassertHighSignal =
+        &WarningObject::warningHighAlarmDeasserted;
 
 // Initialization for Critical Objects
 decltype(Thresholds<CriticalObject>::setLo) Thresholds<CriticalObject>::setLo =
@@ -75,6 +91,23 @@
 decltype(
     Thresholds<CriticalObject>::alarmHi) Thresholds<CriticalObject>::alarmHi =
     &CriticalObject::criticalAlarmHigh;
+decltype(Thresholds<CriticalObject>::getAlarmLow)
+    Thresholds<CriticalObject>::getAlarmLow = &CriticalObject::criticalAlarmLow;
+decltype(Thresholds<CriticalObject>::getAlarmHigh)
+    Thresholds<CriticalObject>::getAlarmHigh =
+        &CriticalObject::criticalAlarmHigh;
+decltype(Thresholds<CriticalObject>::assertLowSignal)
+    Thresholds<CriticalObject>::assertLowSignal =
+        &CriticalObject::criticalLowAlarmAsserted;
+decltype(Thresholds<CriticalObject>::assertHighSignal)
+    Thresholds<CriticalObject>::assertHighSignal =
+        &CriticalObject::criticalHighAlarmAsserted;
+decltype(Thresholds<CriticalObject>::deassertLowSignal)
+    Thresholds<CriticalObject>::deassertLowSignal =
+        &CriticalObject::criticalLowAlarmDeasserted;
+decltype(Thresholds<CriticalObject>::deassertHighSignal)
+    Thresholds<CriticalObject>::deassertHighSignal =
+        &CriticalObject::criticalHighAlarmDeasserted;
 
 void updateSensorInterfaces(InterfaceMap& ifaces, SensorValueType value)
 {
diff --git a/thresholds.hpp b/thresholds.hpp
index 4d2fcff..8d557fc 100644
--- a/thresholds.hpp
+++ b/thresholds.hpp
@@ -32,6 +32,12 @@
     static SensorValueType (WarningObject::*const getHi)() const;
     static bool (WarningObject::*const alarmLo)(bool);
     static bool (WarningObject::*const alarmHi)(bool);
+    static bool (WarningObject::*const getAlarmLow)() const;
+    static bool (WarningObject::*const getAlarmHigh)() const;
+    static void (WarningObject::*const assertLowSignal)(SensorValueType);
+    static void (WarningObject::*const assertHighSignal)(SensorValueType);
+    static void (WarningObject::*const deassertLowSignal)(SensorValueType);
+    static void (WarningObject::*const deassertHighSignal)(SensorValueType);
 };
 
 /**@brief Thresholds specialization for critical thresholds. */
@@ -47,6 +53,12 @@
     static SensorValueType (CriticalObject::*const getHi)() const;
     static bool (CriticalObject::*const alarmLo)(bool);
     static bool (CriticalObject::*const alarmHi)(bool);
+    static bool (CriticalObject::*const getAlarmLow)() const;
+    static bool (CriticalObject::*const getAlarmHigh)() const;
+    static void (CriticalObject::*const assertLowSignal)(SensorValueType);
+    static void (CriticalObject::*const assertHighSignal)(SensorValueType);
+    static void (CriticalObject::*const deassertLowSignal)(SensorValueType);
+    static void (CriticalObject::*const deassertHighSignal)(SensorValueType);
 };
 
 /** @brief checkThresholds
@@ -65,8 +77,32 @@
     auto realIface = std::any_cast<std::shared_ptr<T>>(iface);
     auto lo = (*realIface.*Thresholds<T>::getLo)();
     auto hi = (*realIface.*Thresholds<T>::getHi)();
+    auto alarmLowState = (*realIface.*Thresholds<T>::getAlarmLow)();
+    auto alarmHighState = (*realIface.*Thresholds<T>::getAlarmHigh)();
     (*realIface.*Thresholds<T>::alarmLo)(value <= lo);
     (*realIface.*Thresholds<T>::alarmHi)(value >= hi);
+    if (alarmLowState != (value <= lo))
+    {
+        if (value <= lo)
+        {
+            (*realIface.*Thresholds<T>::assertLowSignal)(value);
+        }
+        else
+        {
+            (*realIface.*Thresholds<T>::deassertLowSignal)(value);
+        }
+    }
+    if (alarmHighState != (value >= hi))
+    {
+        if (value >= hi)
+        {
+            (*realIface.*Thresholds<T>::assertHighSignal)(value);
+        }
+        else
+        {
+            (*realIface.*Thresholds<T>::deassertHighSignal)(value);
+        }
+    }
 }
 
 /** @brief addThreshold
@@ -83,7 +119,7 @@
  */
 template <typename T>
 auto addThreshold(const std::string& sensorType, const std::string& sensorID,
-                  int64_t value, ObjectInfo& info, int64_t scale)
+                  SensorValueType value, ObjectInfo& info, int64_t scale)
 {
     auto& objPath = std::get<std::string>(info);
     auto& obj = std::get<InterfaceMap>(info);
@@ -101,8 +137,32 @@
         auto hi = stod(tHi) * std::pow(10, scale);
         (*iface.*Thresholds<T>::setLo)(lo);
         (*iface.*Thresholds<T>::setHi)(hi);
+        auto alarmLowState = (*iface.*Thresholds<T>::getAlarmLow)();
+        auto alarmHighState = (*iface.*Thresholds<T>::getAlarmHigh)();
         (*iface.*Thresholds<T>::alarmLo)(value <= lo);
         (*iface.*Thresholds<T>::alarmHi)(value >= hi);
+        if (alarmLowState != (value <= lo))
+        {
+            if (value <= lo)
+            {
+                (*iface.*Thresholds<T>::assertLowSignal)(value);
+            }
+            else
+            {
+                (*iface.*Thresholds<T>::deassertLowSignal)(value);
+            }
+        }
+        if (alarmHighState != (value >= hi))
+        {
+            if (value >= hi)
+            {
+                (*iface.*Thresholds<T>::assertHighSignal)(value);
+            }
+            else
+            {
+                (*iface.*Thresholds<T>::deassertHighSignal)(value);
+            }
+        }
         auto type = Thresholds<T>::type;
         obj[type] = iface;
     }