xref: /openbmc/phosphor-fan-presence/control/gen-fan-zone-defs.py (revision c7f68beee3bbd0f17ac3c6ae4834ae14ead9d37f)
1f24d7749SMatthew Barth#!/usr/bin/env python3
2d08dbe27SMatt Spinler
3d08dbe27SMatt Spinler"""
4d08dbe27SMatt SpinlerThis script reads in fan definition and zone definition YAML
5d08dbe27SMatt Spinlerfiles and generates a set of structures for use by the fan control code.
6d08dbe27SMatt Spinler"""
7d08dbe27SMatt Spinler
8d08dbe27SMatt Spinlerimport os
9d08dbe27SMatt Spinlerimport sys
10d08dbe27SMatt Spinlerfrom argparse import ArgumentParser
11*c7f68beeSPatrick Williams
12*c7f68beeSPatrick Williamsimport yaml
13702c4a55SMatthew Barthfrom mako.lookup import TemplateLookup
14d08dbe27SMatt Spinler
1578498c94SMatt Spinler
167883f58aSMatthew Barthdef parse_cpp_type(typeName):
177883f58aSMatthew Barth    """
187883f58aSMatthew Barth    Take a list of dbus types from YAML and convert it to a recursive cpp
197883f58aSMatthew Barth    formed data structure. Each entry of the original list gets converted
207883f58aSMatthew Barth    into a tuple consisting of the type name and a list with the params
217883f58aSMatthew Barth    for this type,
227883f58aSMatthew Barth        e.g.
237883f58aSMatthew Barth            ['dict', ['string', 'dict', ['string', 'int64']]]
247883f58aSMatthew Barth        is converted to
257883f58aSMatthew Barth            [('dict', [('string', []), ('dict', [('string', []),
267883f58aSMatthew Barth             ('int64', [])]]]
277883f58aSMatthew Barth    """
287883f58aSMatthew Barth
297883f58aSMatthew Barth    if not typeName:
307883f58aSMatthew Barth        return None
317883f58aSMatthew Barth
327883f58aSMatthew Barth    # Type names are _almost_ valid YAML. Insert a , before each [
337883f58aSMatthew Barth    # and then wrap it in a [ ] and it becomes valid YAML (assuming
347883f58aSMatthew Barth    # the user gave us a valid typename).
357883f58aSMatthew Barth    typeArray = yaml.safe_load("[" + ",[".join(typeName.split("[")) + "]")
367883f58aSMatthew Barth    typeTuple = preprocess_yaml_type_array(typeArray).pop(0)
377883f58aSMatthew Barth    return get_cpp_type(typeTuple)
387883f58aSMatthew Barth
397883f58aSMatthew Barth
407883f58aSMatthew Barthdef preprocess_yaml_type_array(typeArray):
417883f58aSMatthew Barth    """
427883f58aSMatthew Barth    Flattens an array type into a tuple list that can be used to get the
437883f58aSMatthew Barth    supported cpp type from each element.
447883f58aSMatthew Barth    """
457883f58aSMatthew Barth
467883f58aSMatthew Barth    result = []
477883f58aSMatthew Barth
487883f58aSMatthew Barth    for i in range(len(typeArray)):
497883f58aSMatthew Barth        # Ignore lists because we merge them with the previous element
507883f58aSMatthew Barth        if type(typeArray[i]) is list:
517883f58aSMatthew Barth            continue
527883f58aSMatthew Barth
537883f58aSMatthew Barth        # If there is a next element and it is a list, merge it with the
547883f58aSMatthew Barth        # current element.
557883f58aSMatthew Barth        if i < len(typeArray) - 1 and type(typeArray[i + 1]) is list:
567883f58aSMatthew Barth            result.append(
570f2588f2SPatrick Williams                (typeArray[i], preprocess_yaml_type_array(typeArray[i + 1]))
580f2588f2SPatrick Williams            )
597883f58aSMatthew Barth        else:
607883f58aSMatthew Barth            result.append((typeArray[i], []))
617883f58aSMatthew Barth
627883f58aSMatthew Barth    return result
637883f58aSMatthew Barth
647883f58aSMatthew Barth
657883f58aSMatthew Barthdef get_cpp_type(typeTuple):
667883f58aSMatthew Barth    """
677883f58aSMatthew Barth    Take a list of dbus types and perform validity checking, such as:
687883f58aSMatthew Barth        [ variant [ dict [ int32, int32 ], double ] ]
697883f58aSMatthew Barth    This function then converts the type-list into a C++ type string.
707883f58aSMatthew Barth    """
717883f58aSMatthew Barth
727883f58aSMatthew Barth    propertyMap = {
730f2588f2SPatrick Williams        "byte": {"cppName": "uint8_t", "params": 0},
740f2588f2SPatrick Williams        "boolean": {"cppName": "bool", "params": 0},
750f2588f2SPatrick Williams        "int16": {"cppName": "int16_t", "params": 0},
760f2588f2SPatrick Williams        "uint16": {"cppName": "uint16_t", "params": 0},
770f2588f2SPatrick Williams        "int32": {"cppName": "int32_t", "params": 0},
780f2588f2SPatrick Williams        "uint32": {"cppName": "uint32_t", "params": 0},
790f2588f2SPatrick Williams        "int64": {"cppName": "int64_t", "params": 0},
800f2588f2SPatrick Williams        "uint64": {"cppName": "uint64_t", "params": 0},
810f2588f2SPatrick Williams        "double": {"cppName": "double", "params": 0},
820f2588f2SPatrick Williams        "string": {"cppName": "std::string", "params": 0},
830f2588f2SPatrick Williams        "array": {"cppName": "std::vector", "params": 1},
840f2588f2SPatrick Williams        "dict": {"cppName": "std::map", "params": 2},
850f2588f2SPatrick Williams    }
867883f58aSMatthew Barth
877883f58aSMatthew Barth    if len(typeTuple) != 2:
887883f58aSMatthew Barth        raise RuntimeError("Invalid typeTuple %s" % typeTuple)
897883f58aSMatthew Barth
907883f58aSMatthew Barth    first = typeTuple[0]
917883f58aSMatthew Barth    entry = propertyMap[first]
927883f58aSMatthew Barth
930f2588f2SPatrick Williams    result = entry["cppName"]
947883f58aSMatthew Barth
957883f58aSMatthew Barth    # Handle 0-entry parameter lists.
960f2588f2SPatrick Williams    if entry["params"] == 0:
970f2588f2SPatrick Williams        if len(typeTuple[1]) != 0:
987883f58aSMatthew Barth            raise RuntimeError("Invalid typeTuple %s" % typeTuple)
997883f58aSMatthew Barth        else:
1007883f58aSMatthew Barth            return result
1017883f58aSMatthew Barth
1027883f58aSMatthew Barth    # Get the parameter list
1037883f58aSMatthew Barth    rest = typeTuple[1]
1047883f58aSMatthew Barth
1057883f58aSMatthew Barth    # Confirm parameter count matches.
1060f2588f2SPatrick Williams    if (entry["params"] != -1) and (entry["params"] != len(rest)):
1070f2588f2SPatrick Williams        raise RuntimeError("Invalid entry count for %s : %s" % (first, rest))
1087883f58aSMatthew Barth
1097883f58aSMatthew Barth    # Parse each parameter entry, if appropriate, and create C++ template
1107883f58aSMatthew Barth    # syntax.
1110f2588f2SPatrick Williams    result += "<"
1120f2588f2SPatrick Williams    if entry.get("noparse"):
1137883f58aSMatthew Barth        # Do not parse the parameter list, just use the first element
1147883f58aSMatthew Barth        # of each tuple and ignore possible parameters
1157883f58aSMatthew Barth        result += ", ".join([e[0] for e in rest])
1167883f58aSMatthew Barth    else:
117867a31cfSMatthew Barth        result += ", ".join([get_cpp_type(e) for e in rest])
1180f2588f2SPatrick Williams    result += ">"
1197883f58aSMatthew Barth
1207883f58aSMatthew Barth    return result
1217883f58aSMatthew Barth
1227883f58aSMatthew Barth
123bb12c926SMatthew Barthdef convertToMap(listOfDict):
124bb12c926SMatthew Barth    """
125bb12c926SMatthew Barth    Converts a list of dictionary entries to a std::map initialization list.
126bb12c926SMatthew Barth    """
1270f2588f2SPatrick Williams    listOfDict = listOfDict.replace("'", '"')
1280f2588f2SPatrick Williams    listOfDict = listOfDict.replace("[", "{")
1290f2588f2SPatrick Williams    listOfDict = listOfDict.replace("]", "}")
1300f2588f2SPatrick Williams    listOfDict = listOfDict.replace(":", ",")
131bb12c926SMatthew Barth    return listOfDict
132bb12c926SMatthew Barth
133bb12c926SMatthew Barth
134a1aef7a1SMatthew Barthdef genEvent(event):
135a1aef7a1SMatthew Barth    """
136a1aef7a1SMatthew Barth    Generates the source code of an event and returns it as a string
137a1aef7a1SMatthew Barth    """
138a1aef7a1SMatthew Barth    e = "SetSpeedEvent{\n"
1390f2588f2SPatrick Williams    e += '"' + event["name"] + '",\n'
140a1aef7a1SMatthew Barth    e += "Group{\n"
1410f2588f2SPatrick Williams    for group in event["groups"]:
1420f2588f2SPatrick Williams        for member in group["members"]:
1430f2588f2SPatrick Williams            e += '{"' + member["object"] + '",\n'
1440f2588f2SPatrick Williams            e += '"' + member["interface"] + '",\n'
1450f2588f2SPatrick Williams            e += '"' + member["property"] + '"},\n'
146a1aef7a1SMatthew Barth    e += "},\n"
147a1aef7a1SMatthew Barth
14806fa7817SMatthew Barth    e += "ActionData{\n"
1490f2588f2SPatrick Williams    for d in event["action"]:
15006fa7817SMatthew Barth        e += "{Group{\n"
1510f2588f2SPatrick Williams        for g in d["groups"]:
1520f2588f2SPatrick Williams            for m in g["members"]:
1530f2588f2SPatrick Williams                e += '{"' + m["object"] + '",\n'
1540f2588f2SPatrick Williams                e += '"' + m["interface"] + '",\n'
1550f2588f2SPatrick Williams                e += '"' + m["property"] + '"},\n'
15606fa7817SMatthew Barth        e += "},\n"
157a1aef7a1SMatthew Barth        e += "std::vector<Action>{\n"
1580f2588f2SPatrick Williams        for a in d["actions"]:
1590f2588f2SPatrick Williams            if len(a["parameters"]) != 0:
1600f2588f2SPatrick Williams                e += "make_action(action::" + a["name"] + "(\n"
1618a697b68SMatthew Barth            else:
1620f2588f2SPatrick Williams                e += "make_action(action::" + a["name"] + "\n"
1630f2588f2SPatrick Williams            for i, p in enumerate(a["parameters"]):
1640f2588f2SPatrick Williams                if (i + 1) != len(a["parameters"]):
165a1aef7a1SMatthew Barth                    e += p + ",\n"
166a1aef7a1SMatthew Barth                else:
16706fa7817SMatthew Barth                    e += p + "\n"
1680f2588f2SPatrick Williams            if len(a["parameters"]) != 0:
16906fa7817SMatthew Barth                e += ")),\n"
1708a697b68SMatthew Barth            else:
1718a697b68SMatthew Barth                e += "),\n"
17275d97350SMatthew Barth        e += "}},\n"
17306fa7817SMatthew Barth    e += "},\n"
174a1aef7a1SMatthew Barth
1751b4de26aSMatthew Barth    e += "std::vector<Trigger>{\n"
1760f2588f2SPatrick Williams    if ("timer" in event["triggers"]) and (
1770f2588f2SPatrick Williams        event["triggers"]["timer"] is not None
1780f2588f2SPatrick Williams    ):
1791b4de26aSMatthew Barth        e += "\tmake_trigger(trigger::timer(TimerConf{\n"
1800f2588f2SPatrick Williams        e += "\t" + event["triggers"]["timer"]["interval"] + ",\n"
1810f2588f2SPatrick Williams        e += "\t" + event["triggers"]["timer"]["type"] + "\n"
182016bd24cSMatthew Barth        e += "\t})),\n"
183a1aef7a1SMatthew Barth
1840f2588f2SPatrick Williams    if ("signals" in event["triggers"]) and (
1850f2588f2SPatrick Williams        event["triggers"]["signals"] is not None
1860f2588f2SPatrick Williams    ):
1870f2588f2SPatrick Williams        for s in event["triggers"]["signals"]:
188016bd24cSMatthew Barth            e += "\tmake_trigger(trigger::signal(\n"
1890f2588f2SPatrick Williams            e += "match::" + s["match"] + "(\n"
1900f2588f2SPatrick Williams            for i, mp in enumerate(s["mparams"]["params"]):
1910f2588f2SPatrick Williams                if (i + 1) != len(s["mparams"]["params"]):
1920f2588f2SPatrick Williams                    e += "\t\t\t" + s["mparams"][mp] + ",\n"
193a1aef7a1SMatthew Barth                else:
1940f2588f2SPatrick Williams                    e += "\t\t\t" + s["mparams"][mp] + "\n"
195926df663SMatthew Barth            e += "\t\t),\n"
196926df663SMatthew Barth            e += "\t\tmake_handler<SignalHandler>(\n"
1970f2588f2SPatrick Williams            if ("type" in s["sparams"]) and (s["sparams"]["type"] is not None):
1980f2588f2SPatrick Williams                e += s["signal"] + "<" + s["sparams"]["type"] + ">(\n"
199a1aef7a1SMatthew Barth            else:
2000f2588f2SPatrick Williams                e += s["signal"] + "(\n"
2010f2588f2SPatrick Williams            for sp in s["sparams"]["params"]:
2020f2588f2SPatrick Williams                e += s["sparams"][sp] + ",\n"
2030f2588f2SPatrick Williams            if ("type" in s["hparams"]) and (s["hparams"]["type"] is not None):
2040f2588f2SPatrick Williams                e += (
2050f2588f2SPatrick Williams                    "handler::"
2060f2588f2SPatrick Williams                    + s["handler"]
2070f2588f2SPatrick Williams                    + "<"
2080f2588f2SPatrick Williams                    + s["hparams"]["type"]
2090f2588f2SPatrick Williams                    + ">(\n"
2100f2588f2SPatrick Williams                )
211a1aef7a1SMatthew Barth            else:
2120f2588f2SPatrick Williams                e += "handler::" + s["handler"] + "(\n)"
2130f2588f2SPatrick Williams            for i, hp in enumerate(s["hparams"]["params"]):
2140f2588f2SPatrick Williams                if (i + 1) != len(s["hparams"]["params"]):
2150f2588f2SPatrick Williams                    e += s["hparams"][hp] + ",\n"
216a1aef7a1SMatthew Barth                else:
2170f2588f2SPatrick Williams                    e += s["hparams"][hp] + "\n"
218a1aef7a1SMatthew Barth            e += "))\n"
219926df663SMatthew Barth            e += "\t\t)\n"
220016bd24cSMatthew Barth            e += "\t)),\n"
221016bd24cSMatthew Barth
2220f2588f2SPatrick Williams    if "init" in event["triggers"]:
2230f2588f2SPatrick Williams        for i in event["triggers"]["init"]:
224cd3bfbc1SMatthew Barth            e += "\tmake_trigger(trigger::init(\n"
2250f2588f2SPatrick Williams            if "method" in i:
226926df663SMatthew Barth                e += "\t\tmake_handler<MethodHandler>(\n"
2270f2588f2SPatrick Williams                if ("type" in i["mparams"]) and (
2280f2588f2SPatrick Williams                    i["mparams"]["type"] is not None
2290f2588f2SPatrick Williams                ):
2300f2588f2SPatrick Williams                    e += i["method"] + "<" + i["mparams"]["type"] + ">(\n"
231926df663SMatthew Barth                else:
2320f2588f2SPatrick Williams                    e += i["method"] + "(\n"
2330f2588f2SPatrick Williams                for ip in i["mparams"]["params"]:
2340f2588f2SPatrick Williams                    e += i["mparams"][ip] + ",\n"
2350f2588f2SPatrick Williams                if ("type" in i["hparams"]) and (
2360f2588f2SPatrick Williams                    i["hparams"]["type"] is not None
2370f2588f2SPatrick Williams                ):
2380f2588f2SPatrick Williams                    e += (
2390f2588f2SPatrick Williams                        "handler::"
2400f2588f2SPatrick Williams                        + i["handler"]
2410f2588f2SPatrick Williams                        + "<"
2420f2588f2SPatrick Williams                        + i["hparams"]["type"]
2430f2588f2SPatrick Williams                        + ">(\n"
2440f2588f2SPatrick Williams                    )
245cd3bfbc1SMatthew Barth                else:
2460f2588f2SPatrick Williams                    e += "handler::" + i["handler"] + "(\n)"
2470f2588f2SPatrick Williams                for i, hp in enumerate(i["hparams"]["params"]):
2480f2588f2SPatrick Williams                    if (i + 1) != len(i["hparams"]["params"]):
2490f2588f2SPatrick Williams                        e += i["hparams"][hp] + ",\n"
250cd3bfbc1SMatthew Barth                    else:
2510f2588f2SPatrick Williams                        e += i["hparams"][hp] + "\n"
252926df663SMatthew Barth                e += "))\n"
253cd3bfbc1SMatthew Barth                e += "\t\t)\n"
254cd3bfbc1SMatthew Barth            e += "\t)),\n"
255cd3bfbc1SMatthew Barth
256a1aef7a1SMatthew Barth    e += "},\n"
257a1aef7a1SMatthew Barth
258a1aef7a1SMatthew Barth    e += "}"
259a1aef7a1SMatthew Barth
260a1aef7a1SMatthew Barth    return e
261a1aef7a1SMatthew Barth
262a1aef7a1SMatthew Barth
2636c050693SMatthew Barthdef getGroups(zNum, zCond, edata, events):
2646c050693SMatthew Barth    """
2656c050693SMatthew Barth    Extract and construct the groups for the given event.
2666c050693SMatthew Barth    """
2676c050693SMatthew Barth    groups = []
2680f2588f2SPatrick Williams    if ("groups" in edata) and (edata["groups"] is not None):
2690f2588f2SPatrick Williams        for eGroups in edata["groups"]:
2700f2588f2SPatrick Williams            if ("zone_conditions" in eGroups) and (
2710f2588f2SPatrick Williams                eGroups["zone_conditions"] is not None
2720f2588f2SPatrick Williams            ):
2736c050693SMatthew Barth                # Zone conditions are optional in the events yaml but skip
2746c050693SMatthew Barth                # if this event's condition is not in this zone's conditions
2750f2588f2SPatrick Williams                if all(
2760f2588f2SPatrick Williams                    "name" in z
2770f2588f2SPatrick Williams                    and z["name"] is not None
2780f2588f2SPatrick Williams                    and not any(c["name"] == z["name"] for c in zCond)
2790f2588f2SPatrick Williams                    for z in eGroups["zone_conditions"]
2800f2588f2SPatrick Williams                ):
2816c050693SMatthew Barth                    continue
2826c050693SMatthew Barth
2836c050693SMatthew Barth                # Zone numbers are optional in the events yaml but skip if this
2846c050693SMatthew Barth                # zone's zone number is not in the event's zone numbers
2850f2588f2SPatrick Williams                if all(
2860f2588f2SPatrick Williams                    "zones" in z
2870f2588f2SPatrick Williams                    and z["zones"] is not None
2880f2588f2SPatrick Williams                    and zNum not in z["zones"]
2890f2588f2SPatrick Williams                    for z in eGroups["zone_conditions"]
2900f2588f2SPatrick Williams                ):
2916c050693SMatthew Barth                    continue
2920f2588f2SPatrick Williams            eGroup = next(
2930f2588f2SPatrick Williams                g for g in events["groups"] if g["name"] == eGroups["name"]
2940f2588f2SPatrick Williams            )
2956c050693SMatthew Barth
2966c050693SMatthew Barth            group = {}
2976c050693SMatthew Barth            members = []
2980f2588f2SPatrick Williams            group["name"] = eGroup["name"]
2990f2588f2SPatrick Williams            for m in eGroup["members"]:
3006c050693SMatthew Barth                member = {}
3010f2588f2SPatrick Williams                member["path"] = eGroup["type"]
3020f2588f2SPatrick Williams                member["object"] = eGroup["type"] + m
3030f2588f2SPatrick Williams                member["interface"] = eGroups["interface"]
3040f2588f2SPatrick Williams                member["property"] = eGroups["property"]["name"]
3050f2588f2SPatrick Williams                member["type"] = eGroups["property"]["type"]
30618c91030SMatthew Barth                # Use defined service to note member on zone object
3070f2588f2SPatrick Williams                if ("service" in eGroup) and (eGroup["service"] is not None):
3080f2588f2SPatrick Williams                    member["service"] = eGroup["service"]
3096c050693SMatthew Barth                # Add expected group member's property value if given
3100f2588f2SPatrick Williams                if ("value" in eGroups["property"]) and (
3110f2588f2SPatrick Williams                    eGroups["property"]["value"] is not None
3120f2588f2SPatrick Williams                ):
3130f2588f2SPatrick Williams                    if (
3140f2588f2SPatrick Williams                        isinstance(eGroups["property"]["value"], str)
3150f2588f2SPatrick Williams                        or "string" in str(member["type"]).lower()
3160f2588f2SPatrick Williams                    ):
3170f2588f2SPatrick Williams                        member["value"] = (
3180f2588f2SPatrick Williams                            '"' + eGroups["property"]["value"] + '"'
3190f2588f2SPatrick Williams                        )
3206c050693SMatthew Barth                    else:
3210f2588f2SPatrick Williams                        member["value"] = eGroups["property"]["value"]
3226c050693SMatthew Barth                members.append(member)
3230f2588f2SPatrick Williams            group["members"] = members
3246c050693SMatthew Barth            groups.append(group)
3256c050693SMatthew Barth    return groups
3266c050693SMatthew Barth
3276c050693SMatthew Barth
328cd3bfbc1SMatthew Barthdef getParameters(member, groups, section, events):
32973379f99SMatthew Barth    """
330cd3bfbc1SMatthew Barth    Extracts and constructs a section's parameters
33173379f99SMatthew Barth    """
332cd3bfbc1SMatthew Barth    params = {}
3330f2588f2SPatrick Williams    if ("parameters" in section) and (section["parameters"] is not None):
334cd3bfbc1SMatthew Barth        plist = []
3350f2588f2SPatrick Williams        for sp in section["parameters"]:
336cd3bfbc1SMatthew Barth            p = str(sp)
3370f2588f2SPatrick Williams            if p != "type":
338cd3bfbc1SMatthew Barth                plist.append(p)
3390f2588f2SPatrick Williams                if p != "group":
3400f2588f2SPatrick Williams                    params[p] = '"' + member[p] + '"'
34173379f99SMatthew Barth                else:
342cd3bfbc1SMatthew Barth                    params[p] = "Group\n{\n"
343cd3bfbc1SMatthew Barth                    for g in groups:
3440f2588f2SPatrick Williams                        for m in g["members"]:
345cd3bfbc1SMatthew Barth                            params[p] += (
3460f2588f2SPatrick Williams                                '{"'
3470f2588f2SPatrick Williams                                + str(m["object"])
3480f2588f2SPatrick Williams                                + '",\n'
3490f2588f2SPatrick Williams                                + '"'
3500f2588f2SPatrick Williams                                + str(m["interface"])
3510f2588f2SPatrick Williams                                + '",\n'
3520f2588f2SPatrick Williams                                + '"'
3530f2588f2SPatrick Williams                                + str(m["property"])
3540f2588f2SPatrick Williams                                + '"},\n'
3550f2588f2SPatrick Williams                            )
356cd3bfbc1SMatthew Barth                    params[p] += "}"
35773379f99SMatthew Barth            else:
358cd3bfbc1SMatthew Barth                params[p] = member[p]
3590f2588f2SPatrick Williams        params["params"] = plist
360cd3bfbc1SMatthew Barth    else:
3610f2588f2SPatrick Williams        params["params"] = []
362cd3bfbc1SMatthew Barth    return params
363cd3bfbc1SMatthew Barth
364cd3bfbc1SMatthew Barth
365cd3bfbc1SMatthew Barthdef getInit(eGrps, eTrig, events):
366cd3bfbc1SMatthew Barth    """
367cd3bfbc1SMatthew Barth    Extracts and constructs an init trigger for the event's groups
368cd3bfbc1SMatthew Barth    which are required to be of the same type.
369cd3bfbc1SMatthew Barth    """
370cd3bfbc1SMatthew Barth    method = {}
371cd3bfbc1SMatthew Barth    methods = []
3720f2588f2SPatrick Williams    if len(eGrps) > 0:
373cd3bfbc1SMatthew Barth        # Use the first group member for retrieving the type
3740f2588f2SPatrick Williams        member = eGrps[0]["members"][0]
3750f2588f2SPatrick Williams        if ("method" in eTrig) and (eTrig["method"] is not None):
376cd3bfbc1SMatthew Barth            # Add method parameters
3770f2588f2SPatrick Williams            eMethod = next(
3780f2588f2SPatrick Williams                m for m in events["methods"] if m["name"] == eTrig["method"]
3790f2588f2SPatrick Williams            )
3800f2588f2SPatrick Williams            method["method"] = eMethod["name"]
3810f2588f2SPatrick Williams            method["mparams"] = getParameters(member, eGrps, eMethod, events)
382cd3bfbc1SMatthew Barth
383cd3bfbc1SMatthew Barth            # Add handler parameters
3840f2588f2SPatrick Williams            eHandler = next(
3850f2588f2SPatrick Williams                h for h in events["handlers"] if h["name"] == eTrig["handler"]
3860f2588f2SPatrick Williams            )
3870f2588f2SPatrick Williams            method["handler"] = eHandler["name"]
3880f2588f2SPatrick Williams            method["hparams"] = getParameters(member, eGrps, eHandler, events)
389cd3bfbc1SMatthew Barth
390cd3bfbc1SMatthew Barth    methods.append(method)
391cd3bfbc1SMatthew Barth
392cd3bfbc1SMatthew Barth    return methods
39373379f99SMatthew Barth
39473379f99SMatthew Barth
395a69465a1SMatthew Barthdef getSignal(eGrps, eTrig, events):
396a69465a1SMatthew Barth    """
397a69465a1SMatthew Barth    Extracts and constructs for each group member a signal
398a69465a1SMatthew Barth    subscription of each match listed in the trigger.
399a69465a1SMatthew Barth    """
400a69465a1SMatthew Barth    signals = []
401a69465a1SMatthew Barth    for group in eGrps:
4020f2588f2SPatrick Williams        for member in group["members"]:
403a69465a1SMatthew Barth            signal = {}
404cd3bfbc1SMatthew Barth            # Add signal parameters
4050f2588f2SPatrick Williams            eSignal = next(
4060f2588f2SPatrick Williams                s for s in events["signals"] if s["name"] == eTrig["signal"]
4070f2588f2SPatrick Williams            )
4080f2588f2SPatrick Williams            signal["signal"] = eSignal["name"]
4090f2588f2SPatrick Williams            signal["sparams"] = getParameters(member, eGrps, eSignal, events)
410cd3bfbc1SMatthew Barth
411a69465a1SMatthew Barth            # If service not given, subscribe to signal match
4120f2588f2SPatrick Williams            if "service" not in member:
413cd3bfbc1SMatthew Barth                # Add signal match parameters
4140f2588f2SPatrick Williams                eMatch = next(
4150f2588f2SPatrick Williams                    m
4160f2588f2SPatrick Williams                    for m in events["matches"]
4170f2588f2SPatrick Williams                    if m["name"] == eSignal["match"]
4180f2588f2SPatrick Williams                )
4190f2588f2SPatrick Williams                signal["match"] = eMatch["name"]
4200f2588f2SPatrick Williams                signal["mparams"] = getParameters(
4210f2588f2SPatrick Williams                    member, eGrps, eMatch, events
4220f2588f2SPatrick Williams                )
42373379f99SMatthew Barth
42473379f99SMatthew Barth            # Add handler parameters
4250f2588f2SPatrick Williams            eHandler = next(
4260f2588f2SPatrick Williams                h for h in events["handlers"] if h["name"] == eTrig["handler"]
4270f2588f2SPatrick Williams            )
4280f2588f2SPatrick Williams            signal["handler"] = eHandler["name"]
4290f2588f2SPatrick Williams            signal["hparams"] = getParameters(member, eGrps, eHandler, events)
43073379f99SMatthew Barth
431a69465a1SMatthew Barth            signals.append(signal)
432cd3bfbc1SMatthew Barth
433a69465a1SMatthew Barth    return signals
434a69465a1SMatthew Barth
435a69465a1SMatthew Barth
436d0b90fc6SMatthew Barthdef getTimer(eTrig):
437d0b90fc6SMatthew Barth    """
438d0b90fc6SMatthew Barth    Extracts and constructs the required parameters for an
439d0b90fc6SMatthew Barth    event timer.
440d0b90fc6SMatthew Barth    """
441d0b90fc6SMatthew Barth    timer = {}
4420f2588f2SPatrick Williams    timer["interval"] = (
4430f2588f2SPatrick Williams        "static_cast<std::chrono::microseconds>"
4440f2588f2SPatrick Williams        + "("
4450f2588f2SPatrick Williams        + str(eTrig["interval"])
4460f2588f2SPatrick Williams        + ")"
4470f2588f2SPatrick Williams    )
4480f2588f2SPatrick Williams    timer["type"] = "TimerType::" + str(eTrig["type"])
449d0b90fc6SMatthew Barth    return timer
450d0b90fc6SMatthew Barth
451d0b90fc6SMatthew Barth
452a1aef7a1SMatthew Barthdef getActions(zNum, zCond, edata, actions, events):
4539df74750SMatthew Barth    """
4549df74750SMatthew Barth    Extracts and constructs the make_action function call for
4559df74750SMatthew Barth    all the actions within the given event.
4569df74750SMatthew Barth    """
4579df74750SMatthew Barth    action = []
4580f2588f2SPatrick Williams    for eActions in actions["actions"]:
4599df74750SMatthew Barth        actions = {}
4600f2588f2SPatrick Williams        eAction = next(
4610f2588f2SPatrick Williams            a for a in events["actions"] if a["name"] == eActions["name"]
4620f2588f2SPatrick Williams        )
4630f2588f2SPatrick Williams        actions["name"] = eAction["name"]
4640f2588f2SPatrick Williams        actions["groups"] = getGroups(zNum, zCond, eActions, events)
4659df74750SMatthew Barth        params = []
4660f2588f2SPatrick Williams        if ("parameters" in eAction) and (eAction["parameters"] is not None):
4670f2588f2SPatrick Williams            for p in eAction["parameters"]:
4689df74750SMatthew Barth                param = "static_cast<"
4699df74750SMatthew Barth                if type(eActions[p]) is not dict:
4700f2588f2SPatrick Williams                    if p == "actions":
4719df74750SMatthew Barth                        param = "std::vector<Action>{"
4720f2588f2SPatrick Williams                        pActs = getActions(
4730f2588f2SPatrick Williams                            zNum, zCond, edata, eActions, events
4740f2588f2SPatrick Williams                        )
4759df74750SMatthew Barth                        for a in pActs:
4760f2588f2SPatrick Williams                            if len(a["parameters"]) != 0:
4779df74750SMatthew Barth                                param += (
4780f2588f2SPatrick Williams                                    "make_action(action::" + a["name"] + "(\n"
4790f2588f2SPatrick Williams                                )
4800f2588f2SPatrick Williams                                for i, ap in enumerate(a["parameters"]):
4810f2588f2SPatrick Williams                                    if (i + 1) != len(a["parameters"]):
4820f2588f2SPatrick Williams                                        param += ap + ","
4839df74750SMatthew Barth                                    else:
4840f2588f2SPatrick Williams                                        param += ap + ")"
4859df74750SMatthew Barth                            else:
4860f2588f2SPatrick Williams                                param += "make_action(action::" + a["name"]
4879df74750SMatthew Barth                            param += "),"
4889df74750SMatthew Barth                        param += "}"
4890f2588f2SPatrick Williams                    elif p == "defevents" or p == "altevents" or p == "events":
490a1aef7a1SMatthew Barth                        param = "std::vector<SetSpeedEvent>{\n"
491a1aef7a1SMatthew Barth                        for i, e in enumerate(eActions[p]):
492a1aef7a1SMatthew Barth                            aEvent = getEvent(zNum, zCond, e, events)
493a1aef7a1SMatthew Barth                            if not aEvent:
494a1aef7a1SMatthew Barth                                continue
495a1aef7a1SMatthew Barth                            if (i + 1) != len(eActions[p]):
496a1aef7a1SMatthew Barth                                param += genEvent(aEvent) + ",\n"
497a1aef7a1SMatthew Barth                            else:
498a1aef7a1SMatthew Barth                                param += genEvent(aEvent) + "\n"
499a1aef7a1SMatthew Barth                        param += "\t}"
5000f2588f2SPatrick Williams                    elif p == "property":
5010f2588f2SPatrick Williams                        if (
5020f2588f2SPatrick Williams                            isinstance(eActions[p], str)
5030f2588f2SPatrick Williams                            or "string" in str(eActions[p]["type"]).lower()
5040f2588f2SPatrick Williams                        ):
5059a5b6994SMatthew Barth                            param += (
5060f2588f2SPatrick Williams                                str(eActions[p]["type"]).lower()
5070f2588f2SPatrick Williams                                + '>("'
5080f2588f2SPatrick Williams                                + str(eActions[p])
5090f2588f2SPatrick Williams                                + '")'
5100f2588f2SPatrick Williams                            )
5119a5b6994SMatthew Barth                        else:
5129df74750SMatthew Barth                            param += (
5130f2588f2SPatrick Williams                                str(eActions[p]["type"]).lower()
5140f2588f2SPatrick Williams                                + ">("
5150f2588f2SPatrick Williams                                + str(eActions[p]["value"]).lower()
5160f2588f2SPatrick Williams                                + ")"
5170f2588f2SPatrick Williams                            )
5189df74750SMatthew Barth                    else:
5199df74750SMatthew Barth                        # Default type to 'size_t' when not given
5200f2588f2SPatrick Williams                        param += "size_t>(" + str(eActions[p]).lower() + ")"
5219df74750SMatthew Barth                else:
5220f2588f2SPatrick Williams                    if p == "timer":
523d0b90fc6SMatthew Barth                        t = getTimer(eActions[p])
5249df74750SMatthew Barth                        param = (
5250f2588f2SPatrick Williams                            "TimerConf{"
5260f2588f2SPatrick Williams                            + t["interval"]
5270f2588f2SPatrick Williams                            + ","
5280f2588f2SPatrick Williams                            + t["type"]
5290f2588f2SPatrick Williams                            + "}"
5300f2588f2SPatrick Williams                        )
5319df74750SMatthew Barth                    else:
5320f2588f2SPatrick Williams                        param += str(eActions[p]["type"]).lower() + ">("
5330f2588f2SPatrick Williams                        if p != "map":
5340f2588f2SPatrick Williams                            if (
5350f2588f2SPatrick Williams                                isinstance(eActions[p]["value"], str)
5360f2588f2SPatrick Williams                                or "string" in str(eActions[p]["type"]).lower()
5370f2588f2SPatrick Williams                            ):
5380f2588f2SPatrick Williams                                param += '"' + str(eActions[p]["value"]) + '")'
5399df74750SMatthew Barth                            else:
5409df74750SMatthew Barth                                param += (
5410f2588f2SPatrick Williams                                    str(eActions[p]["value"]).lower() + ")"
5420f2588f2SPatrick Williams                                )
5430f2588f2SPatrick Williams                        else:
5440f2588f2SPatrick Williams                            param += (
5450f2588f2SPatrick Williams                                str(eActions[p]["type"]).lower()
5460f2588f2SPatrick Williams                                + convertToMap(str(eActions[p]["value"]))
5470f2588f2SPatrick Williams                                + ")"
5480f2588f2SPatrick Williams                            )
5499df74750SMatthew Barth                params.append(param)
5500f2588f2SPatrick Williams        actions["parameters"] = params
5519df74750SMatthew Barth        action.append(actions)
5529df74750SMatthew Barth    return action
5539df74750SMatthew Barth
5549df74750SMatthew Barth
5557f272fd0SMatthew Barthdef getEvent(zone_num, zone_conditions, e, events_data):
5567f272fd0SMatthew Barth    """
5577f272fd0SMatthew Barth    Parses the sections of an event and populates the properties
5587f272fd0SMatthew Barth    that construct an event within the generated source.
5597f272fd0SMatthew Barth    """
5607f272fd0SMatthew Barth    event = {}
5617f272fd0SMatthew Barth
562621a5778SMatthew Barth    # Add set speed event name
5630f2588f2SPatrick Williams    event["name"] = e["name"]
564621a5778SMatthew Barth
5656c050693SMatthew Barth    # Add set speed event groups
5660f2588f2SPatrick Williams    event["groups"] = getGroups(zone_num, zone_conditions, e, events_data)
5677f272fd0SMatthew Barth
568e3d1c4a9SMatthew Barth    # Add optional set speed actions and function parameters
5690f2588f2SPatrick Williams    event["action"] = []
5700f2588f2SPatrick Williams    if ("actions" in e) and (e["actions"] is not None):
57106fa7817SMatthew Barth        # List of dicts containing the list of groups and list of actions
57206fa7817SMatthew Barth        sseActions = []
57306fa7817SMatthew Barth        eActions = getActions(zone_num, zone_conditions, e, e, events_data)
57406fa7817SMatthew Barth        for eAction in eActions:
57506fa7817SMatthew Barth            # Skip events that have no groups defined for the event or actions
5760f2588f2SPatrick Williams            if not event["groups"] and not eAction["groups"]:
57706fa7817SMatthew Barth                continue
57806fa7817SMatthew Barth            # Find group in sseActions
57906fa7817SMatthew Barth            grpExists = False
58006fa7817SMatthew Barth            for sseDict in sseActions:
5810f2588f2SPatrick Williams                if eAction["groups"] == sseDict["groups"]:
58206fa7817SMatthew Barth                    # Extend 'actions' list
5830f2588f2SPatrick Williams                    del eAction["groups"]
5840f2588f2SPatrick Williams                    sseDict["actions"].append(eAction)
58506fa7817SMatthew Barth                    grpExists = True
58606fa7817SMatthew Barth                    break
58706fa7817SMatthew Barth            if not grpExists:
5880f2588f2SPatrick Williams                grps = eAction["groups"]
5890f2588f2SPatrick Williams                del eAction["groups"]
59006fa7817SMatthew Barth                actList = []
59106fa7817SMatthew Barth                actList.append(eAction)
5920f2588f2SPatrick Williams                sseActions.append({"groups": grps, "actions": actList})
5930f2588f2SPatrick Williams        event["action"] = sseActions
5947f272fd0SMatthew Barth
595a69465a1SMatthew Barth    # Add event triggers
5960f2588f2SPatrick Williams    event["triggers"] = {}
5970f2588f2SPatrick Williams    for trig in e["triggers"]:
598a69465a1SMatthew Barth        triggers = []
5990f2588f2SPatrick Williams        if trig["name"] == "timer":
6000f2588f2SPatrick Williams            event["triggers"]["timer"] = getTimer(trig)
6010f2588f2SPatrick Williams        elif trig["name"] == "signal":
6020f2588f2SPatrick Williams            if "signals" not in event["triggers"]:
6030f2588f2SPatrick Williams                event["triggers"]["signals"] = []
6040f2588f2SPatrick Williams            triggers = getSignal(event["groups"], trig, events_data)
6050f2588f2SPatrick Williams            event["triggers"]["signals"].extend(triggers)
6060f2588f2SPatrick Williams        elif trig["name"] == "init":
6070f2588f2SPatrick Williams            triggers = getInit(event["groups"], trig, events_data)
6080f2588f2SPatrick Williams            event["triggers"]["init"] = triggers
6097f272fd0SMatthew Barth
6107f272fd0SMatthew Barth    return event
6117f272fd0SMatthew Barth
6127f272fd0SMatthew Barth
6137f272fd0SMatthew Barthdef addPrecondition(zNum, zCond, event, events_data):
6149af190cdSMatthew Barth    """
6159af190cdSMatthew Barth    Parses the precondition section of an event and populates the necessary
6169af190cdSMatthew Barth    structures to generate a precondition for a set speed event.
6179af190cdSMatthew Barth    """
6189af190cdSMatthew Barth    precond = {}
619621a5778SMatthew Barth
620621a5778SMatthew Barth    # Add set speed event precondition name
6210f2588f2SPatrick Williams    precond["pcname"] = event["name"]
622621a5778SMatthew Barth
6239af190cdSMatthew Barth    # Add set speed event precondition group
6240f2588f2SPatrick Williams    precond["pcgrps"] = getGroups(
6250f2588f2SPatrick Williams        zNum, zCond, event["precondition"], events_data
6260f2588f2SPatrick Williams    )
6279af190cdSMatthew Barth
6287f272fd0SMatthew Barth    # Add set speed event precondition actions
6297f272fd0SMatthew Barth    pc = []
6307f272fd0SMatthew Barth    pcs = {}
6310f2588f2SPatrick Williams    pcs["name"] = event["precondition"]["name"]
6320f2588f2SPatrick Williams    epc = next(
6330f2588f2SPatrick Williams        p
6340f2588f2SPatrick Williams        for p in events_data["preconditions"]
6350f2588f2SPatrick Williams        if p["name"] == event["precondition"]["name"]
6360f2588f2SPatrick Williams    )
6379af190cdSMatthew Barth    params = []
6380f2588f2SPatrick Williams    for p in epc["parameters"] or []:
6399af190cdSMatthew Barth        param = {}
6400f2588f2SPatrick Williams        if p == "groups":
6410f2588f2SPatrick Williams            param["type"] = "std::vector<PrecondGroup>"
6420f2588f2SPatrick Williams            param["open"] = "{"
6430f2588f2SPatrick Williams            param["close"] = "}"
6449af190cdSMatthew Barth            values = []
6450f2588f2SPatrick Williams            for group in precond["pcgrps"]:
6460f2588f2SPatrick Williams                for pcgrp in group["members"]:
6479af190cdSMatthew Barth                    value = {}
6480f2588f2SPatrick Williams                    value["value"] = (
6490f2588f2SPatrick Williams                        'PrecondGroup{"'
6500f2588f2SPatrick Williams                        + str(pcgrp["object"])
6510f2588f2SPatrick Williams                        + '","'
6520f2588f2SPatrick Williams                        + str(pcgrp["interface"])
6530f2588f2SPatrick Williams                        + '","'
6540f2588f2SPatrick Williams                        + str(pcgrp["property"])
6550f2588f2SPatrick Williams                        + '",'
6560f2588f2SPatrick Williams                        + "static_cast<"
6570f2588f2SPatrick Williams                        + str(pcgrp["type"]).lower()
6580f2588f2SPatrick Williams                        + ">"
6590f2588f2SPatrick Williams                    )
6600f2588f2SPatrick Williams                    if (
6610f2588f2SPatrick Williams                        isinstance(pcgrp["value"], str)
6620f2588f2SPatrick Williams                        or "string" in str(pcgrp["type"]).lower()
6630f2588f2SPatrick Williams                    ):
6640f2588f2SPatrick Williams                        value["value"] += "(" + str(pcgrp["value"]) + ")}"
6659a5b6994SMatthew Barth                    else:
6660f2588f2SPatrick Williams                        value["value"] += (
6670f2588f2SPatrick Williams                            "(" + str(pcgrp["value"]).lower() + ")}"
6680f2588f2SPatrick Williams                        )
6699af190cdSMatthew Barth                    values.append(value)
6700f2588f2SPatrick Williams            param["values"] = values
6719af190cdSMatthew Barth        params.append(param)
6720f2588f2SPatrick Williams    pcs["params"] = params
6737f272fd0SMatthew Barth    pc.append(pcs)
6740f2588f2SPatrick Williams    precond["pcact"] = pc
6759af190cdSMatthew Barth
6767f272fd0SMatthew Barth    pcevents = []
6770f2588f2SPatrick Williams    for pce in event["precondition"]["events"]:
6787f272fd0SMatthew Barth        pcevent = getEvent(zNum, zCond, pce, events_data)
6797f272fd0SMatthew Barth        if not pcevent:
6807f272fd0SMatthew Barth            continue
6817f272fd0SMatthew Barth        pcevents.append(pcevent)
6820f2588f2SPatrick Williams    precond["pcevts"] = pcevents
6837f272fd0SMatthew Barth
684f20c321dSMatthew Barth    # Add precondition event triggers
6850f2588f2SPatrick Williams    precond["triggers"] = {}
6860f2588f2SPatrick Williams    for trig in event["precondition"]["triggers"]:
687f20c321dSMatthew Barth        triggers = []
6880f2588f2SPatrick Williams        if trig["name"] == "timer":
6890f2588f2SPatrick Williams            precond["triggers"]["pctime"] = getTimer(trig)
6900f2588f2SPatrick Williams        elif trig["name"] == "signal":
6910f2588f2SPatrick Williams            if "pcsigs" not in precond["triggers"]:
6920f2588f2SPatrick Williams                precond["triggers"]["pcsigs"] = []
6930f2588f2SPatrick Williams            triggers = getSignal(precond["pcgrps"], trig, events_data)
6940f2588f2SPatrick Williams            precond["triggers"]["pcsigs"].extend(triggers)
6950f2588f2SPatrick Williams        elif trig["name"] == "init":
6960f2588f2SPatrick Williams            triggers = getInit(precond["pcgrps"], trig, events_data)
6970f2588f2SPatrick Williams            precond["triggers"]["init"] = triggers
6989af190cdSMatthew Barth
6999af190cdSMatthew Barth    return precond
7009af190cdSMatthew Barth
7019af190cdSMatthew Barth
702b751f32dSGunnar Millsdef getEventsInZone(zone_num, zone_conditions, events_data):
703d4d0f083SMatthew Barth    """
704d4d0f083SMatthew Barth    Constructs the event entries defined for each zone using the events yaml
705d4d0f083SMatthew Barth    provided.
706d4d0f083SMatthew Barth    """
707d4d0f083SMatthew Barth    events = []
708ba102b38SMatthew Barth
7090f2588f2SPatrick Williams    if "events" in events_data:
7100f2588f2SPatrick Williams        for e in events_data["events"]:
711d4d0f083SMatthew Barth            event = {}
712621a5778SMatthew Barth
7139af190cdSMatthew Barth            # Add precondition if given
7140f2588f2SPatrick Williams            if ("precondition" in e) and (e["precondition"] is not None):
7150f2588f2SPatrick Williams                event["pc"] = addPrecondition(
7160f2588f2SPatrick Williams                    zone_num, zone_conditions, e, events_data
7170f2588f2SPatrick Williams                )
718ba102b38SMatthew Barth            else:
7197f272fd0SMatthew Barth                event = getEvent(zone_num, zone_conditions, e, events_data)
720a6f75169SMatthew Barth                # Remove empty events and events that have
721a6f75169SMatthew Barth                # no groups defined for the event or any of the actions
7220f2588f2SPatrick Williams                if not event or (
7230f2588f2SPatrick Williams                    not event["groups"]
7240f2588f2SPatrick Williams                    and all(not a["groups"] for a in event["action"])
7250f2588f2SPatrick Williams                ):
7267f272fd0SMatthew Barth                    continue
727d4d0f083SMatthew Barth            events.append(event)
728d4d0f083SMatthew Barth
729d4d0f083SMatthew Barth    return events
730d4d0f083SMatthew Barth
731d4d0f083SMatthew Barth
73278498c94SMatt Spinlerdef getFansInZone(zone_num, profiles, fan_data):
73378498c94SMatt Spinler    """
73478498c94SMatt Spinler    Parses the fan definition YAML files to find the fans
73578498c94SMatt Spinler    that match both the zone passed in and one of the
73678498c94SMatt Spinler    cooling profiles.
73778498c94SMatt Spinler    """
73878498c94SMatt Spinler
73978498c94SMatt Spinler    fans = []
74078498c94SMatt Spinler
7410f2588f2SPatrick Williams    for f in fan_data["fans"]:
7420f2588f2SPatrick Williams        if zone_num != f["cooling_zone"]:
74378498c94SMatt Spinler            continue
74478498c94SMatt Spinler
74578498c94SMatt Spinler        # 'cooling_profile' is optional (use 'all' instead)
7460f2588f2SPatrick Williams        if f.get("cooling_profile") is None:
74778498c94SMatt Spinler            profile = "all"
74878498c94SMatt Spinler        else:
7490f2588f2SPatrick Williams            profile = f["cooling_profile"]
75078498c94SMatt Spinler
75178498c94SMatt Spinler        if profile not in profiles:
75278498c94SMatt Spinler            continue
75378498c94SMatt Spinler
75478498c94SMatt Spinler        fan = {}
7550f2588f2SPatrick Williams        fan["name"] = f["inventory"]
7560f2588f2SPatrick Williams        fan["sensors"] = f["sensors"]
7570f2588f2SPatrick Williams        fan["target_interface"] = f.get(
7580f2588f2SPatrick Williams            "target_interface", "xyz.openbmc_project.Control.FanSpeed"
7590f2588f2SPatrick Williams        )
7600f2588f2SPatrick Williams        fan["target_path"] = f.get(
7610f2588f2SPatrick Williams            "target_path", "/xyz/openbmc_project/sensors/fan_tach/"
7620f2588f2SPatrick Williams        )
76378498c94SMatt Spinler        fans.append(fan)
76478498c94SMatt Spinler
76578498c94SMatt Spinler    return fans
76678498c94SMatt Spinler
76778498c94SMatt Spinler
7687883f58aSMatthew Barthdef getIfacesInZone(zone_ifaces):
7697883f58aSMatthew Barth    """
7707883f58aSMatthew Barth    Parse given interfaces for a zone for associating a zone with an interface
7717883f58aSMatthew Barth    and set any properties listed to defined values upon fan control starting
7727883f58aSMatthew Barth    on the zone.
7737883f58aSMatthew Barth    """
7747883f58aSMatthew Barth
7757883f58aSMatthew Barth    ifaces = []
7767883f58aSMatthew Barth    for i in zone_ifaces:
7777883f58aSMatthew Barth        iface = {}
7787883f58aSMatthew Barth        # Interface name not needed yet for fan zones but
7797883f58aSMatthew Barth        # may be necessary as more interfaces are extended by the zones
7800f2588f2SPatrick Williams        iface["name"] = i["name"]
7817883f58aSMatthew Barth
7820f2588f2SPatrick Williams        if ("properties" in i) and (i["properties"] is not None):
7837883f58aSMatthew Barth            props = []
7840f2588f2SPatrick Williams            for p in i["properties"]:
7857883f58aSMatthew Barth                prop = {}
7860f2588f2SPatrick Williams                prop["name"] = p["name"]
7870f2588f2SPatrick Williams                prop["func"] = str(p["name"]).lower()
7880f2588f2SPatrick Williams                prop["type"] = parse_cpp_type(p["type"])
7890f2588f2SPatrick Williams                if "persist" in p:
7900f2588f2SPatrick Williams                    persist = p["persist"]
7910f2588f2SPatrick Williams                    if persist is not None:
7920f2588f2SPatrick Williams                        if isinstance(persist, bool):
7930f2588f2SPatrick Williams                            prop["persist"] = "true" if persist else "false"
79459096e50SMatthew Barth                else:
7950f2588f2SPatrick Williams                    prop["persist"] = "false"
7967883f58aSMatthew Barth                vals = []
7970f2588f2SPatrick Williams                for v in p["values"]:
7980f2588f2SPatrick Williams                    val = v["value"]
7990f2588f2SPatrick Williams                    if val is not None:
8000f2588f2SPatrick Williams                        if isinstance(val, bool):
8017883f58aSMatthew Barth                            # Convert True/False to 'true'/'false'
8020f2588f2SPatrick Williams                            val = "true" if val else "false"
8030f2588f2SPatrick Williams                        elif isinstance(val, str):
8047883f58aSMatthew Barth                            # Wrap strings with double-quotes
8050f2588f2SPatrick Williams                            val = '"' + val + '"'
8067883f58aSMatthew Barth                        vals.append(val)
8070f2588f2SPatrick Williams                prop["values"] = vals
8087883f58aSMatthew Barth                props.append(prop)
8090f2588f2SPatrick Williams            iface["props"] = props
8107883f58aSMatthew Barth        ifaces.append(iface)
8117883f58aSMatthew Barth
8127883f58aSMatthew Barth    return ifaces
8137883f58aSMatthew Barth
8147883f58aSMatthew Barth
815ee8a2816SGunnar Millsdef getConditionInZoneConditions(zone_condition, zone_conditions_data):
816ee8a2816SGunnar Mills    """
817ee8a2816SGunnar Mills    Parses the zone conditions definition YAML files to find the condition
818ee8a2816SGunnar Mills    that match both the zone condition passed in.
819ee8a2816SGunnar Mills    """
820ee8a2816SGunnar Mills
821ee8a2816SGunnar Mills    condition = {}
822ee8a2816SGunnar Mills
8230f2588f2SPatrick Williams    for c in zone_conditions_data["conditions"]:
8240f2588f2SPatrick Williams        if zone_condition != c["name"]:
825ee8a2816SGunnar Mills            continue
8260f2588f2SPatrick Williams        condition["type"] = c["type"]
827ee8a2816SGunnar Mills        properties = []
8280f2588f2SPatrick Williams        for p in c["properties"]:
829ee8a2816SGunnar Mills            property = {}
8300f2588f2SPatrick Williams            property["property"] = p["property"]
8310f2588f2SPatrick Williams            property["interface"] = p["interface"]
8320f2588f2SPatrick Williams            property["path"] = p["path"]
8330f2588f2SPatrick Williams            property["type"] = p["type"].lower()
8340f2588f2SPatrick Williams            property["value"] = str(p["value"]).lower()
835ee8a2816SGunnar Mills            properties.append(property)
8360f2588f2SPatrick Williams        condition["properties"] = properties
837ee8a2816SGunnar Mills
838ee8a2816SGunnar Mills        return condition
839ee8a2816SGunnar Mills
840ee8a2816SGunnar Mills
841ee8a2816SGunnar Millsdef buildZoneData(zone_data, fan_data, events_data, zone_conditions_data):
84278498c94SMatt Spinler    """
84378498c94SMatt Spinler    Combines the zone definition YAML and fan
84478498c94SMatt Spinler    definition YAML to create a data structure defining
84578498c94SMatt Spinler    the fan cooling zones.
84678498c94SMatt Spinler    """
84778498c94SMatt Spinler
84878498c94SMatt Spinler    zone_groups = []
84978498c94SMatt Spinler
850005ff2ffSMatthew Barth    # Allow zone_conditions to not be in yaml (since its optional)
851005ff2ffSMatthew Barth    if not isinstance(zone_data, list) and zone_data != {}:
852005ff2ffSMatthew Barth        zone_data = [zone_data]
85378498c94SMatt Spinler    for group in zone_data:
85478498c94SMatt Spinler        conditions = []
855ee8a2816SGunnar Mills        # zone conditions are optional
8560f2588f2SPatrick Williams        if "zone_conditions" in group and group["zone_conditions"] is not None:
8570f2588f2SPatrick Williams            for c in group["zone_conditions"]:
858ee8a2816SGunnar Mills                if not zone_conditions_data:
8590f2588f2SPatrick Williams                    sys.exit(
8600f2588f2SPatrick Williams                        "No zone_conditions YAML file but "
8610f2588f2SPatrick Williams                        + "zone_conditions used in zone YAML"
8620f2588f2SPatrick Williams                    )
863ee8a2816SGunnar Mills
8640f2588f2SPatrick Williams                condition = getConditionInZoneConditions(
8650f2588f2SPatrick Williams                    c["name"], zone_conditions_data
8660f2588f2SPatrick Williams                )
867ee8a2816SGunnar Mills
868ee8a2816SGunnar Mills                if not condition:
8690f2588f2SPatrick Williams                    sys.exit("Missing zone condition " + c["name"])
870ee8a2816SGunnar Mills
871ee8a2816SGunnar Mills                conditions.append(condition)
87278498c94SMatt Spinler
87378498c94SMatt Spinler        zone_group = {}
8740f2588f2SPatrick Williams        zone_group["conditions"] = conditions
87578498c94SMatt Spinler
87678498c94SMatt Spinler        zones = []
8770f2588f2SPatrick Williams        for z in group["zones"]:
87878498c94SMatt Spinler            zone = {}
87978498c94SMatt Spinler
88078498c94SMatt Spinler            # 'zone' is required
8810f2588f2SPatrick Williams            if ("zone" not in z) or (z["zone"] is None):
8820f2588f2SPatrick Williams                sys.exit("Missing fan zone number in " + z)
88378498c94SMatt Spinler
8840f2588f2SPatrick Williams            zone["num"] = z["zone"]
88578498c94SMatt Spinler
8860f2588f2SPatrick Williams            zone["full_speed"] = z["full_speed"]
88778498c94SMatt Spinler
8880f2588f2SPatrick Williams            zone["default_floor"] = z["default_floor"]
8891de66629SMatthew Barth
890a956184bSMatthew Barth            # 'increase_delay' is optional (use 0 by default)
8910f2588f2SPatrick Williams            key = "increase_delay"
892a956184bSMatthew Barth            zone[key] = z.setdefault(key, 0)
893a956184bSMatthew Barth
894a956184bSMatthew Barth            # 'decrease_interval' is optional (use 0 by default)
8950f2588f2SPatrick Williams            key = "decrease_interval"
896a956184bSMatthew Barth            zone[key] = z.setdefault(key, 0)
897a956184bSMatthew Barth
89878498c94SMatt Spinler            # 'cooling_profiles' is optional (use 'all' instead)
8990f2588f2SPatrick Williams            if ("cooling_profiles" not in z) or (
9000f2588f2SPatrick Williams                z["cooling_profiles"] is None
9010f2588f2SPatrick Williams            ):
90278498c94SMatt Spinler                profiles = ["all"]
90378498c94SMatt Spinler            else:
9040f2588f2SPatrick Williams                profiles = z["cooling_profiles"]
90578498c94SMatt Spinler
9067883f58aSMatthew Barth            # 'interfaces' is optional (no default)
90764099cdbSMatthew Barth            ifaces = []
9080f2588f2SPatrick Williams            if ("interfaces" in z) and (z["interfaces"] is not None):
9090f2588f2SPatrick Williams                ifaces = getIfacesInZone(z["interfaces"])
9107883f58aSMatthew Barth
9110f2588f2SPatrick Williams            fans = getFansInZone(z["zone"], profiles, fan_data)
9120f2588f2SPatrick Williams            events = getEventsInZone(
9130f2588f2SPatrick Williams                z["zone"], group.get("zone_conditions", {}), events_data
9140f2588f2SPatrick Williams            )
91578498c94SMatt Spinler
91678498c94SMatt Spinler            if len(fans) == 0:
9170f2588f2SPatrick Williams                sys.exit("Didn't find any fans in zone " + str(zone["num"]))
91878498c94SMatt Spinler
9190f2588f2SPatrick Williams            if ifaces:
9200f2588f2SPatrick Williams                zone["ifaces"] = ifaces
9210f2588f2SPatrick Williams            zone["fans"] = fans
9220f2588f2SPatrick Williams            zone["events"] = events
92378498c94SMatt Spinler            zones.append(zone)
92478498c94SMatt Spinler
9250f2588f2SPatrick Williams        zone_group["zones"] = zones
92678498c94SMatt Spinler        zone_groups.append(zone_group)
92778498c94SMatt Spinler
92878498c94SMatt Spinler    return zone_groups
92978498c94SMatt Spinler
93078498c94SMatt Spinler
9310f2588f2SPatrick Williamsif __name__ == "__main__":
9320f2588f2SPatrick Williams    parser = ArgumentParser(description="Phosphor fan zone definition parser")
933d08dbe27SMatt Spinler
9340f2588f2SPatrick Williams    parser.add_argument(
9350f2588f2SPatrick Williams        "-z",
9360f2588f2SPatrick Williams        "--zone_yaml",
9370f2588f2SPatrick Williams        dest="zone_yaml",
938d08dbe27SMatt Spinler        default="example/zones.yaml",
9390f2588f2SPatrick Williams        help="fan zone definitional yaml",
9400f2588f2SPatrick Williams    )
9410f2588f2SPatrick Williams    parser.add_argument(
9420f2588f2SPatrick Williams        "-f",
9430f2588f2SPatrick Williams        "--fan_yaml",
9440f2588f2SPatrick Williams        dest="fan_yaml",
945d08dbe27SMatt Spinler        default="example/fans.yaml",
9460f2588f2SPatrick Williams        help="fan definitional yaml",
9470f2588f2SPatrick Williams    )
9480f2588f2SPatrick Williams    parser.add_argument(
9490f2588f2SPatrick Williams        "-e",
9500f2588f2SPatrick Williams        "--events_yaml",
9510f2588f2SPatrick Williams        dest="events_yaml",
9520f2588f2SPatrick Williams        help="events to set speeds yaml",
9530f2588f2SPatrick Williams    )
9540f2588f2SPatrick Williams    parser.add_argument(
9550f2588f2SPatrick Williams        "-c",
9560f2588f2SPatrick Williams        "--zone_conditions_yaml",
9570f2588f2SPatrick Williams        dest="zone_conditions_yaml",
9580f2588f2SPatrick Williams        help="conditions to determine zone yaml",
9590f2588f2SPatrick Williams    )
9600f2588f2SPatrick Williams    parser.add_argument(
9610f2588f2SPatrick Williams        "-o",
9620f2588f2SPatrick Williams        "--output_dir",
9630f2588f2SPatrick Williams        dest="output_dir",
964d08dbe27SMatt Spinler        default=".",
9650f2588f2SPatrick Williams        help="output directory",
9660f2588f2SPatrick Williams    )
967d08dbe27SMatt Spinler    args = parser.parse_args()
968d08dbe27SMatt Spinler
969d08dbe27SMatt Spinler    if not args.zone_yaml or not args.fan_yaml:
970d08dbe27SMatt Spinler        parser.print_usage()
9713e781064SWilliam A. Kennington III        sys.exit(1)
972d08dbe27SMatt Spinler
9730f2588f2SPatrick Williams    with open(args.zone_yaml, "r") as zone_input:
974d08dbe27SMatt Spinler        zone_data = yaml.safe_load(zone_input) or {}
975d08dbe27SMatt Spinler
9760f2588f2SPatrick Williams    with open(args.fan_yaml, "r") as fan_input:
977d08dbe27SMatt Spinler        fan_data = yaml.safe_load(fan_input) or {}
978d08dbe27SMatt Spinler
979d4d0f083SMatthew Barth    events_data = {}
980d4d0f083SMatthew Barth    if args.events_yaml:
9810f2588f2SPatrick Williams        with open(args.events_yaml, "r") as events_input:
982d4d0f083SMatthew Barth            events_data = yaml.safe_load(events_input) or {}
983d4d0f083SMatthew Barth
984ee8a2816SGunnar Mills    zone_conditions_data = {}
985ee8a2816SGunnar Mills    if args.zone_conditions_yaml:
9860f2588f2SPatrick Williams        with open(args.zone_conditions_yaml, "r") as zone_conditions_input:
987ee8a2816SGunnar Mills            zone_conditions_data = yaml.safe_load(zone_conditions_input) or {}
988ee8a2816SGunnar Mills
9890f2588f2SPatrick Williams    zone_config = buildZoneData(
9900f2588f2SPatrick Williams        zone_data.get("zone_configuration", {}),
9910f2588f2SPatrick Williams        fan_data,
9920f2588f2SPatrick Williams        events_data,
9930f2588f2SPatrick Williams        zone_conditions_data,
9940f2588f2SPatrick Williams    )
995ee7f6428SMatt Spinler
9960f2588f2SPatrick Williams    manager_config = zone_data.get("manager_configuration", {})
997ee7f6428SMatt Spinler
9980f2588f2SPatrick Williams    if manager_config.get("power_on_delay") is None:
9990f2588f2SPatrick Williams        manager_config["power_on_delay"] = 0
1000d08dbe27SMatt Spinler
1001702c4a55SMatthew Barth    tmpls_dir = os.path.join(
10020f2588f2SPatrick Williams        os.path.dirname(os.path.realpath(__file__)), "templates"
10030f2588f2SPatrick Williams    )
1004d08dbe27SMatt Spinler    output_file = os.path.join(args.output_dir, "fan_zone_defs.cpp")
1005702c4a55SMatthew Barth    if sys.version_info < (3, 0):
1006702c4a55SMatthew Barth        lkup = TemplateLookup(
10070f2588f2SPatrick Williams            directories=tmpls_dir.split(), disable_unicode=True
10080f2588f2SPatrick Williams        )
1009702c4a55SMatthew Barth    else:
10100f2588f2SPatrick Williams        lkup = TemplateLookup(directories=tmpls_dir.split())
10110f2588f2SPatrick Williams    tmpl = lkup.get_template("fan_zone_defs.mako.cpp")
10120f2588f2SPatrick Williams    with open(output_file, "w") as output:
10130f2588f2SPatrick Williams        output.write(tmpl.render(zones=zone_config, mgr_data=manager_config))
1014