control: Support `member` signal triggers

`member` signals are signals that a dbus object could send out on dbus
that acts as a notification that does not contain any other data. This
adds support to fan control events that can be triggered by this type of
signal on dbus to essentially run a set of actions. The configuration of
this trigger is contained within the JSON configuration of the trigger
on the event and not against the event's group(s).

i.e.)
"triggers": [
  {
    "class": "signal",
    "signal": "member",
    "member":
      {
        "name": "Pressed",
        "path": "/xyz/openbmc_project/Chassis/Buttons/Power0",
        "interface": "xyz.openbmc_project.Chassis.Buttons.Power"
      }
  }
]

Change-Id: Ie7924174333c604fb54c8f18560a890bf6a7c489
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/triggers/signal.cpp b/control/json/triggers/signal.cpp
index fa6d32b..5786049 100644
--- a/control/json/triggers/signal.cpp
+++ b/control/json/triggers/signal.cpp
@@ -214,6 +214,31 @@
     }
 }
 
+void member(Manager* mgr, std::unique_ptr<ActionBase>& action,
+            const json& jsonObj)
+{
+    if (!jsonObj.contains("member") || !jsonObj["member"].contains("name") ||
+        !jsonObj["member"].contains("path") ||
+        !jsonObj["member"].contains("interface"))
+    {
+        log<level::ERR>("Missing required member trigger attributes",
+                        entry("JSON=%s", jsonObj.dump().c_str()));
+        throw std::runtime_error("Missing required member trigger attributes");
+    }
+    const auto match =
+        rules::type::signal() +
+        rules::member(jsonObj["member"]["name"].get<std::string>()) +
+        rules::path(jsonObj["member"]["path"].get<std::string>()) +
+        rules::interface(jsonObj["member"]["interface"].get<std::string>());
+    // No SignalObject required to associate to this signal
+    SignalPkg signalPkg = {Handlers::member, SignalObject(),
+                           SignalActions({action})};
+    // If signal match already exists, then the member signal will be the
+    // same so add action to be run
+    auto isSameSig = [](SignalPkg& pkg) { return true; };
+    subscribe(match, std::move(signalPkg), isSameSig, mgr);
+}
+
 enableTrigger triggerSignal(const json& jsonObj, const std::string& eventName,
                             std::vector<std::unique_ptr<ActionBase>>& actions)
 {