Generate selected match strings and signals

The available matches and their associated signals are now listed
within the events yaml and can be added to the list of matches to
register for per event.

Change-Id: I65f657038afe7c68a421adb4820ea09e275be06d
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/example/events.yaml b/control/example/events.yaml
index d413633..4bd5bfb 100644
--- a/control/example/events.yaml
+++ b/control/example/events.yaml
@@ -7,6 +7,19 @@
 #      members:
 #          [List of object paths under the path extension]
 #
+#matches:
+#    - name: [The name associated with a supported match string function]
+#      description: [A user description of what this match string represents]
+#      parameters:
+#          [List of required parameters for the match string function]
+#      signal: [Signal function name used with this match string]
+#
+#signals:
+#    - name: [The name associated with a supported signal function]
+#      description: [A user description of what this signal does]
+#      parameters:
+#          [List of required parameters for the signal function]
+#
 #preconditions:
 #    - name: [Name associated with a supported precondition]
 #      description: [A user description of the precondition's use]
@@ -70,6 +83,39 @@
 #          - /temperature/dimm3_temp
 #          - /temperature/dimm4_temp
 #
+#signals:
+#    - name: propertiesChanged
+#      description: >
+#          A property changed signal
+#      parameters:
+#          - object
+#          - interface
+#      handler: propertySignal
+#    - name: interfacesAdded
+#      description: >
+#          An interfaces added signal
+#      parameters:
+#          - object
+#      handler: objectSignal
+#
+#handlers:
+#    - name: propertySignal
+#      description: >
+#          Handle property signals
+#      parameters:
+#          - type
+#          - object
+#          - interface
+#          - property
+#    - name: objectSignal
+#      description: >
+#          Handle object signals
+#      parameters:
+#          - type
+#          - object
+#          - interface
+#          - property
+#
 #preconditions:
 #    - name: property_states_match
 #      description: >
@@ -121,6 +167,9 @@
 #      property:
 #          name: Present
 #          type: bool
+#      signals:
+#          - name: interfacesAdded
+#          - name: propertiesChanged
 #      actions:
 #          - name: count_state_before_speed
 #            count: 1
@@ -138,6 +187,8 @@
 #      property:
 #          name: Value
 #          type: int64_t
+#      signals:
+#          - name: propertiesChanged
 #      actions:
 #          - name: set_floor_from_average_sensor_value
 #            map:
@@ -163,6 +214,8 @@
 #      property:
 #          name: Value
 #          type: int64_t
+#      signals:
+#          - name: propertiesChanged
 #      actions:
 #          - name: set_floor_from_average_sensor_value
 #            map:
@@ -191,6 +244,8 @@
 #      property:
 #          name: Value
 #          type: int64_t
+#      signals:
+#          - name: propertiesChanged
 #      actions:
 #          - name: set_net_increase_speed
 #            property: 85000
@@ -226,6 +281,9 @@
 #                    name: OccActive
 #                    type: bool
 #                    value: true
+#          signals:
+#              - name: interfacesAdded
+#              - name: propertiesChanged
 #          events:
 #              - name: speed_changes_based_on_dimm_temps
 #                zone_conditions:
@@ -240,6 +298,9 @@
 #                property:
 #                    name: Value
 #                    type: int64_t
+#                signals:
+#                    - name: interfacesAdded
+#                    - name: propertiesChanged
 #                actions:
 #                    - name: set_net_increase_speed
 #                      property: 64000
diff --git a/control/gen-fan-zone-defs.py b/control/gen-fan-zone-defs.py
index d11ff35..6d04bbd 100755
--- a/control/gen-fan-zone-defs.py
+++ b/control/gen-fan-zone-defs.py
@@ -20,7 +20,7 @@
 Group{
 %for member in event['group']:
 {
-    "${member['name']}",
+    "${member['object']}",
     {"${member['interface']}",
      "${member['property']}"}
 },
@@ -46,30 +46,32 @@
 Timer{
     ${event['timer']['interval']}
 },
-std::vector<PropertyChange>{
-%for s in event['signal']:
-    PropertyChange{
-        interfacesAdded("${s['obj_path']}"),
-        make_handler(objectSignal<${s['type']}>(
-            "${s['path']}",
-            "${s['interface']}",
-            "${s['property']}",
+std::vector<Signal>{
+%for s in event['signals']:
+    Signal{
+        ${s['match']}(
+        %for i, mp in enumerate(s['mparams']):
+        %if (i+1) != len(s['mparams']):
+        "${mp}",
+        %else:
+        "${mp}"
+        %endif
+        %endfor
+        ),
+        make_handler(
+            %if ('type' in s['sparams']) and \
+                (s['sparams']['type'] is not None):
+            ${s['signal']}<${s['sparams']['type']}>(
+            %else:
+            ${s['signal']}(
+            %endif
+            %for spk, spv in s['sparams'].iteritems():
+            %if spk != 'type':
+            "${spv}",
+            %endif
+            %endfor
             handler::setProperty<${s['type']}>(
-                "${s['path']}",
-                "${s['interface']}",
-                "${s['property']}"
-            )
-        ))
-    },
-    PropertyChange{
-        propertiesChanged(
-            "${s['path']}",
-            "${s['interface']}"),
-        make_handler(propertySignal<${s['type']}>(
-            "${s['interface']}",
-            "${s['property']}",
-            handler::setProperty<${s['type']}>(
-                "${s['path']}",
+                "${s['object']}",
                 "${s['interface']}",
                 "${s['property']}"
             )
@@ -140,7 +142,7 @@
                         Group{
                         %for member in event['pc']['pcgrp']:
                         {
-                            "${member['name']}",
+                            "${member['object']}",
                             {"${member['interface']}",
                              "${member['property']}"}
                         },
@@ -195,30 +197,32 @@
                         Timer{
                             ${event['pc']['pctime']['interval']}
                         },
-                        std::vector<PropertyChange>{
-                        %for s in event['pc']['pcsig']:
-                            PropertyChange{
-                                interfacesAdded("${s['obj_path']}"),
-                                make_handler(objectSignal<${s['type']}>(
-                                    "${s['path']}",
-                                    "${s['interface']}",
-                                    "${s['property']}",
+                        std::vector<Signal>{
+                        %for s in event['pc']['pcsigs']:
+                            Signal{
+                                ${s['match']}(
+                                %for i, mp in enumerate(s['mparams']):
+                                %if (i+1) != len(s['mparams']):
+                                "${mp}",
+                                %else:
+                                "${mp}"
+                                %endif
+                                %endfor
+                                ),
+                                make_handler(
+                                    %if ('type' in s['sparams']) and \
+                                        (s['sparams']['type'] is not None):
+                                    ${s['signal']}<${s['sparams']['type']}>(
+                                    %else:
+                                    ${s['signal']}(
+                                    %endif
+                                    %for spk, spv in s['sparams'].iteritems():
+                                    %if spk != 'type':
+                                    "${spv}",
+                                    %endif
+                                    %endfor
                                     handler::setProperty<${s['type']}>(
-                                        "${s['path']}",
-                                        "${s['interface']}",
-                                        "${s['property']}"
-                                    )
-                                ))
-                            },
-                            PropertyChange{
-                                propertiesChanged(
-                                    "${s['path']}",
-                                    "${s['interface']}"),
-                                make_handler(propertySignal<${s['type']}>(
-                                    "${s['interface']}",
-                                    "${s['property']}",
-                                    handler::setProperty<${s['type']}>(
-                                        "${s['path']}",
+                                        "${s['object']}",
                                         "${s['interface']}",
                                         "${s['property']}"
                                     )
@@ -276,11 +280,11 @@
                   if g['name'] == e['group'])
     for member in groups['members']:
         members = {}
-        members['obj_path'] = groups['type']
-        members['name'] = (groups['type'] +
-                           member)
+        members['object'] = (groups['type'] +
+                             member)
         members['interface'] = e['interface']
         members['property'] = e['property']['name']
+        members['type'] = e['property']['type']
         group.append(members)
     event['group'] = group
 
@@ -319,17 +323,36 @@
         action.append(actions)
     event['action'] = action
 
-    # Add property change signal handler
-    signal = []
-    for path in group:
-        signals = {}
-        signals['obj_path'] = path['obj_path']
-        signals['path'] = path['name']
-        signals['interface'] = e['interface']
-        signals['property'] = e['property']['name']
-        signals['type'] = e['property']['type']
-        signal.append(signals)
-    event['signal'] = signal
+    # Add signal handlers
+    signals = []
+    for member in group:
+        for eMatches in e['matches']:
+            signal = {}
+            eMatch = next(m for m in events_data['matches']
+                          if m['name'] == eMatches['name'])
+            signal['match'] = eMatch['name']
+            params = []
+            if ('parameters' in eMatch) and \
+               (eMatch['parameters'] is not None):
+                for p in eMatch['parameters']:
+                    params.append(member[str(p)])
+            signal['mparams'] = params
+            eSignal = next(s for s in events_data['signals']
+                           if s['name'] == eMatch['signal'])
+            signal['signal'] = eSignal['name']
+            sparams = {}
+            if ('parameters' in eSignal) and \
+               (eSignal['parameters'] is not None):
+                for p in eSignal['parameters']:
+                    sparams[str(p)] = member[str(p)]
+            signal['sparams'] = sparams
+            # Add member attributes
+            signal['object'] = member['object']
+            signal['interface'] = member['interface']
+            signal['property'] = member['property']
+            signal['type'] = member['type']
+            signals.append(signal)
+    event['signals'] = signals
 
     # Add optional action call timer
     timer = {}
@@ -361,9 +384,8 @@
                       if g['name'] == grp['name'])
         for member in groups['members']:
             members = {}
-            members['obj_path'] = groups['type']
-            members['name'] = (groups['type'] +
-                               member)
+            members['object'] = (groups['type'] +
+                                 member)
             members['interface'] = grp['interface']
             members['property'] = grp['property']['name']
             members['type'] = grp['property']['type']
@@ -389,7 +411,7 @@
                 value = {}
                 value['value'] = (
                     "PrecondGroup{\"" +
-                    str(pcgrp['name']) + "\",\"" +
+                    str(pcgrp['object']) + "\",\"" +
                     str(pcgrp['interface']) + "\",\"" +
                     str(pcgrp['property']) + "\"," +
                     "static_cast<" +
@@ -410,17 +432,36 @@
         pcevents.append(pcevent)
     precond['pcevts'] = pcevents
 
-    # Add precondition property change signal handler
-    signal = []
+    # Add precondition signal handlers
+    signals = []
     for member in group:
-        signals = {}
-        signals['obj_path'] = member['obj_path']
-        signals['path'] = member['name']
-        signals['interface'] = member['interface']
-        signals['property'] = member['property']
-        signals['type'] = member['type']
-        signal.append(signals)
-    precond['pcsig'] = signal
+        for eMatches in event['precondition']['matches']:
+            signal = {}
+            eMatch = next(m for m in events_data['matches']
+                          if m['name'] == eMatches['name'])
+            signal['match'] = eMatch['name']
+            params = []
+            if ('parameters' in eMatch) and \
+               (eMatch['parameters'] is not None):
+                for p in eMatch['parameters']:
+                    params.append(member[str(p)])
+            signal['mparams'] = params
+            eSignal = next(s for s in events_data['signals']
+                           if s['name'] == eMatch['signal'])
+            signal['signal'] = eSignal['name']
+            sparams = {}
+            if ('parameters' in eSignal) and \
+               (eSignal['parameters'] is not None):
+                for p in eSignal['parameters']:
+                    sparams[str(p)] = member[str(p)]
+            signal['sparams'] = sparams
+            # Add member attributes
+            signal['object'] = member['object']
+            signal['interface'] = member['interface']
+            signal['property'] = member['property']
+            signal['type'] = member['type']
+            signals.append(signal)
+    precond['pcsigs'] = signals
 
     # Add optional action call timer
     timer = {}
diff --git a/control/types.hpp b/control/types.hpp
index a670810..f6b2b60 100644
--- a/control/types.hpp
+++ b/control/types.hpp
@@ -58,16 +58,16 @@
 
 constexpr auto signaturePos = 0;
 constexpr auto handlerObjPos = 1;
-using PropertyChange = std::tuple<std::string, Handler>;
+using Signal = std::tuple<std::string, Handler>;
 
 constexpr auto groupPos = 0;
 constexpr auto actionsPos = 1;
 constexpr auto timerPos = 2;
-constexpr auto propChangeListPos = 3;
+constexpr auto signalsPos = 3;
 using SetSpeedEvent = std::tuple<Group,
                                  std::vector<Action>,
                                  Timer,
-                                 std::vector<PropertyChange>>;
+                                 std::vector<Signal>>;
 
 constexpr auto eventGroupPos = 0;
 constexpr auto eventHandlerPos = 1;
diff --git a/control/zone.cpp b/control/zone.cpp
index 88cdc86..fa426e6 100644
--- a/control/zone.cpp
+++ b/control/zone.cpp
@@ -213,22 +213,22 @@
                 entry("PROPERTY=%s", std::get<propPos>(group.second).c_str()));
         }
     }
-    // Setup signal matches for property change events
-    for (auto& prop : std::get<propChangeListPos>(event))
+    // Setup signal matches for events
+    for (auto& sig : std::get<signalsPos>(event))
     {
         std::unique_ptr<EventData> eventData =
             std::make_unique<EventData>(
                 EventData
                 {
                     std::get<groupPos>(event),
-                    std::get<handlerObjPos>(prop),
+                    std::get<handlerObjPos>(sig),
                     std::get<actionsPos>(event)
                 }
             );
         std::unique_ptr<sdbusplus::server::match::match> match =
             std::make_unique<sdbusplus::server::match::match>(
                 _bus,
-                std::get<signaturePos>(prop).c_str(),
+                std::get<signaturePos>(sig).c_str(),
                 std::bind(std::mem_fn(&Zone::handleEvent),
                           this,
                           std::placeholders::_1,