blob: 15681378a1225f0555bd4f93f9da3095879d903a [file] [log] [blame]
Matt Spinlerd08dbe22017-04-11 13:52:54 -05001#!/usr/bin/env python
2
3"""
4This script reads in fan definition and zone definition YAML
5files and generates a set of structures for use by the fan control code.
6"""
7
8import os
9import sys
10import yaml
11from argparse import ArgumentParser
12from mako.template import Template
13
Matthew Barth336f18a2017-09-26 09:15:56 -050014tmpl = '''\
Matthew Barth7f272fd2017-09-12 16:16:56 -050015<%!
16def indent(str, depth):
17 return ''.join(4*' '*depth+line for line in str.splitlines(True))
Matthew Barth336f18a2017-09-26 09:15:56 -050018%>\
Matthew Barth9f964bf2017-10-02 15:07:00 -050019<%def name="genHandler(sig)" buffered="True">
20%if ('type' in sig['sparams']) and \
21 (sig['sparams']['type'] is not None):
22${sig['signal']}<${sig['sparams']['type']}>(
23%else:
24${sig['signal']}(
25%endif
26%for spk in sig['sparams']['params']:
27${sig['sparams'][spk]},
28%endfor
29%if ('type' in sig['hparams']) and \
30 (sig['hparams']['type'] is not None):
31handler::${sig['handler']}<${sig['hparams']['type']}>(
32%else:
33handler::${sig['handler']}(
34%endif
35%for i, hpk in enumerate(sig['hparams']['params']):
36 %if (i+1) != len(sig['hparams']['params']):
37 ${sig['hparams'][hpk]},
38 %else:
39 ${sig['hparams'][hpk]}
40 %endif
41%endfor
42))
43</%def>\
Matthew Barth7f272fd2017-09-12 16:16:56 -050044<%def name="genSSE(event)" buffered="True">
45Group{
46%for member in event['group']:
47{
Matthew Barth67967f92017-09-22 12:43:57 -050048 "${member['object']}",
Matthew Barth7f272fd2017-09-12 16:16:56 -050049 {"${member['interface']}",
50 "${member['property']}"}
51},
52%endfor
53},
54std::vector<Action>{
55%for a in event['action']:
Matthew Barth4c04a012017-09-15 13:05:30 -050056%if len(a['parameters']) != 0:
Matthew Barth7f272fd2017-09-12 16:16:56 -050057make_action(action::${a['name']}(
Matthew Barth4c04a012017-09-15 13:05:30 -050058%else:
59make_action(action::${a['name']}
60%endif
Matthew Barth7f272fd2017-09-12 16:16:56 -050061%for i, p in enumerate(a['parameters']):
62%if (i+1) != len(a['parameters']):
Matthew Barth6c997d72017-10-10 15:32:09 -050063 ${p},
Matthew Barth7f272fd2017-09-12 16:16:56 -050064%else:
Matthew Barth6c997d72017-10-10 15:32:09 -050065 ${p})
Matthew Barth7f272fd2017-09-12 16:16:56 -050066%endif
67%endfor
Matthew Barth4c04a012017-09-15 13:05:30 -050068),
Matthew Barth7f272fd2017-09-12 16:16:56 -050069%endfor
70},
71Timer{
Matthew Barth7b7ceb82017-10-04 12:59:50 -050072 ${event['timer']['interval']},
73 ${event['timer']['type']}
Matthew Barth7f272fd2017-09-12 16:16:56 -050074},
Matthew Barth67967f92017-09-22 12:43:57 -050075std::vector<Signal>{
76%for s in event['signals']:
77 Signal{
Matthew Barth336f18a2017-09-26 09:15:56 -050078 match::${s['match']}(
Matthew Barth67967f92017-09-22 12:43:57 -050079 %for i, mp in enumerate(s['mparams']):
80 %if (i+1) != len(s['mparams']):
81 "${mp}",
82 %else:
83 "${mp}"
84 %endif
85 %endfor
86 ),
Matthew Barth9f964bf2017-10-02 15:07:00 -050087 make_handler(\
88 ${indent(genHandler(sig=s), 3)}\
89 )
Matthew Barth7f272fd2017-09-12 16:16:56 -050090 },
91%endfor
92}
Matthew Barth336f18a2017-09-26 09:15:56 -050093</%def>\
Matthew Barth7f272fd2017-09-12 16:16:56 -050094/* This is a generated file. */
Matt Spinlerd08dbe22017-04-11 13:52:54 -050095#include "manager.hpp"
Matthew Barthba102b32017-05-16 16:13:56 -050096#include "functor.hpp"
97#include "actions.hpp"
Matthew Barth7e527c12017-05-17 10:14:15 -050098#include "handlers.hpp"
Matthew Barth9af190c2017-08-08 14:20:43 -050099#include "preconditions.hpp"
Matthew Barth336f18a2017-09-26 09:15:56 -0500100#include "matches.hpp"
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500101
102using namespace phosphor::fan::control;
103
Matt Spinleree7f6422017-05-09 11:03:14 -0500104const unsigned int Manager::_powerOnDelay{${mgr_data['power_on_delay']}};
105
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500106const std::vector<ZoneGroup> Manager::_zoneLayouts
107{
108%for zone_group in zones:
Matthew Barth9c726672017-05-18 13:44:46 -0500109 ZoneGroup{
Gunnar Millsee8a2812017-06-02 14:26:47 -0500110 std::vector<Condition>{
111 %for condition in zone_group['conditions']:
112 Condition{
113 "${condition['type']}",
114 std::vector<ConditionProperty>{
115 %for property in condition['properties']:
116 ConditionProperty{
117 "${property['property']}",
118 "${property['interface']}",
119 "${property['path']}",
120 static_cast<${property['type']}>(${property['value']}),
121 },
122 %endfor
123 },
124 },
125 %endfor
126 },
Matthew Barth9c726672017-05-18 13:44:46 -0500127 std::vector<ZoneDefinition>{
128 %for zone in zone_group['zones']:
129 ZoneDefinition{
130 ${zone['num']},
131 ${zone['full_speed']},
Matthew Barth1de66622017-06-12 13:13:02 -0500132 ${zone['default_floor']},
Matthew Bartha9561842017-06-29 11:43:45 -0500133 ${zone['increase_delay']},
134 ${zone['decrease_interval']},
Matthew Barth9c726672017-05-18 13:44:46 -0500135 std::vector<FanDefinition>{
136 %for fan in zone['fans']:
137 FanDefinition{
138 "${fan['name']}",
139 std::vector<std::string>{
140 %for sensor in fan['sensors']:
141 "${sensor}",
142 %endfor
143 }
144 },
145 %endfor
146 },
147 std::vector<SetSpeedEvent>{
148 %for event in zone['events']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500149 %if ('pc' in event) and \
150 (event['pc'] is not None):
151 SetSpeedEvent{
152 Group{
153 %for member in event['pc']['pcgrp']:
154 {
Matthew Barth67967f92017-09-22 12:43:57 -0500155 "${member['object']}",
Matthew Barth9af190c2017-08-08 14:20:43 -0500156 {"${member['interface']}",
157 "${member['property']}"}
158 },
159 %endfor
160 },
Matthew Barth7f272fd2017-09-12 16:16:56 -0500161 std::vector<Action>{
162 %for i, a in enumerate(event['pc']['pcact']):
Matthew Barth4c04a012017-09-15 13:05:30 -0500163 %if len(a['params']) != 0:
Matthew Barth9af190c2017-08-08 14:20:43 -0500164 make_action(
Matthew Barth7f272fd2017-09-12 16:16:56 -0500165 precondition::${a['name']}(
Matthew Barth4c04a012017-09-15 13:05:30 -0500166 %else:
167 make_action(
168 precondition::${a['name']}
169 %endif
Matthew Barth7f272fd2017-09-12 16:16:56 -0500170 %for p in a['params']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500171 ${p['type']}${p['open']}
172 %for j, v in enumerate(p['values']):
173 %if (j+1) != len(p['values']):
174 ${v['value']},
175 %else:
176 ${v['value']}
177 %endif
178 %endfor
179 ${p['close']},
180 %endfor
Matthew Barth7f272fd2017-09-12 16:16:56 -0500181 %if (i+1) != len(event['pc']['pcact']):
Matthew Barth4c04a012017-09-15 13:05:30 -0500182 %if len(a['params']) != 0:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500183 )),
Matthew Barth4c04a012017-09-15 13:05:30 -0500184 %else:
185 ),
186 %endif
Matthew Barth9c726672017-05-18 13:44:46 -0500187 %endif
188 %endfor
Matthew Barth7f272fd2017-09-12 16:16:56 -0500189 std::vector<SetSpeedEvent>{
190 %for pcevt in event['pc']['pcevts']:
191 SetSpeedEvent{\
192 ${indent(genSSE(event=pcevt), 6)}\
193 },
194 %endfor
195 %else:
196 SetSpeedEvent{\
197 ${indent(genSSE(event=event), 6)}
198 %endif
Matthew Barth9af190c2017-08-08 14:20:43 -0500199 %if ('pc' in event) and (event['pc'] is not None):
200 }
Matthew Barth4c04a012017-09-15 13:05:30 -0500201 %if len(event['pc']['pcact'][-1]['params']) != 0:
Matthew Barth9af190c2017-08-08 14:20:43 -0500202 )),
Matthew Barth4c04a012017-09-15 13:05:30 -0500203 %else:
204 ),
205 %endif
Matthew Barth7f272fd2017-09-12 16:16:56 -0500206 },
Matthew Barth90149802017-08-15 10:51:37 -0500207 Timer{
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500208 ${event['pc']['pctime']['interval']},
209 ${event['pc']['pctime']['type']}
Matthew Barth90149802017-08-15 10:51:37 -0500210 },
Matthew Barth67967f92017-09-22 12:43:57 -0500211 std::vector<Signal>{
212 %for s in event['pc']['pcsigs']:
213 Signal{
Matthew Barth336f18a2017-09-26 09:15:56 -0500214 match::${s['match']}(
Matthew Barth67967f92017-09-22 12:43:57 -0500215 %for i, mp in enumerate(s['mparams']):
216 %if (i+1) != len(s['mparams']):
217 "${mp}",
218 %else:
219 "${mp}"
220 %endif
221 %endfor
222 ),
Matthew Barth9f964bf2017-10-02 15:07:00 -0500223 make_handler(\
224 ${indent(genHandler(sig=s), 9)}\
225 )
Matthew Barth9af190c2017-08-08 14:20:43 -0500226 },
227 %endfor
228 }
229 %endif
Matthew Barth9c726672017-05-18 13:44:46 -0500230 },
231 %endfor
232 }
233 },
234 %endfor
235 }
Matt Spinler78498c92017-04-11 13:59:46 -0500236 },
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500237%endfor
238};
239'''
240
Matt Spinler78498c92017-04-11 13:59:46 -0500241
Matthew Barthbb12c922017-06-13 13:57:40 -0500242def convertToMap(listOfDict):
243 """
244 Converts a list of dictionary entries to a std::map initialization list.
245 """
Matthew Barth9a5b6992018-01-23 15:32:26 -0600246 listOfDict = listOfDict.replace('\'', '\"')
Matthew Barthbb12c922017-06-13 13:57:40 -0500247 listOfDict = listOfDict.replace('[', '{')
248 listOfDict = listOfDict.replace(']', '}')
249 listOfDict = listOfDict.replace(':', ',')
250 return listOfDict
251
252
Matthew Barth9df74752017-10-11 14:39:31 -0500253def getActions(edata, actions, events):
254 """
255 Extracts and constructs the make_action function call for
256 all the actions within the given event.
257 """
258 action = []
259 for eActions in actions['actions']:
260 actions = {}
261 eAction = next(a for a in events['actions']
262 if a['name'] == eActions['name'])
263 actions['name'] = eAction['name']
264 params = []
265 if ('parameters' in eAction) and \
266 (eAction['parameters'] is not None):
267 for p in eAction['parameters']:
268 param = "static_cast<"
269 if type(eActions[p]) is not dict:
270 if p == 'actions':
271 param = "std::vector<Action>{"
272 pActs = getActions(edata, eActions, events)
273 for a in pActs:
274 if (len(a['parameters']) != 0):
275 param += (
276 "make_action(action::" +
277 a['name'] +
278 "(\n")
279 for i, ap in enumerate(a['parameters']):
280 if (i+1) != len(a['parameters']):
281 param += (ap + ",")
282 else:
283 param += (ap + ")")
284 else:
285 param += ("make_action(action::" + a['name'])
286 param += "),"
287 param += "}"
288 elif p == 'property':
Matthew Barth9a5b6992018-01-23 15:32:26 -0600289 if isinstance(eActions[p], str) or \
290 "string" in str(edata['property']['type']).lower():
291 param += (
292 str(edata['property']['type']).lower() +
293 ">(\"" + str(eActions[p]) + "\")")
294 else:
295 param += (
296 str(edata['property']['type']).lower() +
297 ">(" + str(eActions[p]).lower() + ")")
Matthew Barth9df74752017-10-11 14:39:31 -0500298 else:
299 # Default type to 'size_t' when not given
300 param += ("size_t>(" + str(eActions[p]).lower() + ")")
301 else:
302 if p == 'timer':
303 param = (
304 "Timer{static_cast<std::chrono::seconds>(" +
305 str(eActions[p]['delay']) + "), " +
306 "util::Timer::TimerType::" +
307 str(eActions[p]['type']) + "}")
308 else:
309 param += (str(eActions[p]['type']).lower() + ">(")
310 if p != 'map':
Matthew Barth9a5b6992018-01-23 15:32:26 -0600311 if isinstance(eActions[p]['value'], str) or \
312 "string" in str(eActions[p]['type']).lower():
313 param += \
314 "\"" + str(eActions[p]['value']) + "\")"
315 else:
316 param += \
317 str(eActions[p]['value']).lower() + ")"
Matthew Barth9df74752017-10-11 14:39:31 -0500318 else:
319 param += (
320 str(eActions[p]['type']).lower() +
321 convertToMap(str(eActions[p]['value'])) + ")")
322 params.append(param)
323 actions['parameters'] = params
324 action.append(actions)
325 return action
326
327
Matthew Barth7f272fd2017-09-12 16:16:56 -0500328def getEvent(zone_num, zone_conditions, e, events_data):
329 """
330 Parses the sections of an event and populates the properties
331 that construct an event within the generated source.
332 """
333 event = {}
334 # Zone numbers are optional in the events yaml but skip if this
335 # zone's zone number is not in the event's zone numbers
336 if all('zones' in z and
337 z['zones'] is not None and
338 zone_num not in z['zones']
339 for z in e['zone_conditions']):
340 return
341
342 # Zone conditions are optional in the events yaml but skip
343 # if this event's condition is not in this zone's conditions
344 if all('name' in z and z['name'] is not None and
345 not any(c['name'] == z['name'] for c in zone_conditions)
346 for z in e['zone_conditions']):
347 return
348
349 # Add set speed event group
350 group = []
351 groups = next(g for g in events_data['groups']
352 if g['name'] == e['group'])
353 for member in groups['members']:
354 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500355 members['object'] = (groups['type'] +
356 member)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500357 members['interface'] = e['interface']
358 members['property'] = e['property']['name']
Matthew Barth67967f92017-09-22 12:43:57 -0500359 members['type'] = e['property']['type']
Matthew Barth7f272fd2017-09-12 16:16:56 -0500360 group.append(members)
361 event['group'] = group
362
363 # Add set speed actions and function parameters
Matthew Barth9df74752017-10-11 14:39:31 -0500364 event['action'] = getActions(e, e, events_data)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500365
Matthew Barth67967f92017-09-22 12:43:57 -0500366 # Add signal handlers
367 signals = []
368 for member in group:
369 for eMatches in e['matches']:
370 signal = {}
371 eMatch = next(m for m in events_data['matches']
372 if m['name'] == eMatches['name'])
373 signal['match'] = eMatch['name']
374 params = []
375 if ('parameters' in eMatch) and \
376 (eMatch['parameters'] is not None):
377 for p in eMatch['parameters']:
378 params.append(member[str(p)])
379 signal['mparams'] = params
380 eSignal = next(s for s in events_data['signals']
381 if s['name'] == eMatch['signal'])
382 signal['signal'] = eSignal['name']
383 sparams = {}
384 if ('parameters' in eSignal) and \
385 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500386 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500387 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500388 sp = str(p)
389 if (sp != 'type'):
390 splist.append(sp)
391 if (sp != 'group'):
392 sparams[sp] = "\"" + member[sp] + "\""
393 else:
394 sparams[sp] = "Group{\n"
395 for m in group:
396 sparams[sp] += (
397 "{\n" +
398 "\"" + str(m['object']) + "\",\n" +
399 "{\"" + str(m['interface']) + "\"," +
400 "\"" + str(m['property']) + "\"}\n" +
401 "},\n")
402 sparams[sp] += "}"
403 else:
404 sparams[sp] = member[sp]
405 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500406 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500407 # Add signal handler
408 eHandler = next(h for h in events_data['handlers']
409 if h['name'] == eSignal['handler'])
410 signal['handler'] = eHandler['name']
411 hparams = {}
412 if ('parameters' in eHandler) and \
413 (eHandler['parameters'] is not None):
414 hplist = []
415 for p in eHandler['parameters']:
416 hp = str(p)
417 if (hp != 'type'):
418 hplist.append(hp)
419 if (hp != 'group'):
420 hparams[hp] = "\"" + member[hp] + "\""
421 else:
422 hparams[hp] = "Group{\n"
423 for m in group:
424 hparams[hp] += (
425 "{\n" +
426 "\"" + str(m['object']) + "\",\n" +
427 "{\"" + str(m['interface']) + "\"," +
428 "\"" + str(m['property']) + "\"}\n" +
429 "},\n")
430 hparams[hp] += "}"
431 else:
432 hparams[hp] = member[hp]
433 hparams['params'] = hplist
434 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500435 signals.append(signal)
436 event['signals'] = signals
Matthew Barth7f272fd2017-09-12 16:16:56 -0500437
438 # Add optional action call timer
439 timer = {}
440 interval = "static_cast<std::chrono::seconds>"
441 if ('timer' in e) and \
442 (e['timer'] is not None):
443 timer['interval'] = (interval +
444 "(" +
445 str(e['timer']['interval']) +
446 ")")
447 else:
448 timer['interval'] = (interval +
449 "(" + str(0) + ")")
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500450 timer['type'] = "util::Timer::TimerType::repeating"
Matthew Barth7f272fd2017-09-12 16:16:56 -0500451 event['timer'] = timer
452
453 return event
454
455
456def addPrecondition(zNum, zCond, event, events_data):
Matthew Barth9af190c2017-08-08 14:20:43 -0500457 """
458 Parses the precondition section of an event and populates the necessary
459 structures to generate a precondition for a set speed event.
460 """
461 precond = {}
462 # Add set speed event precondition group
463 group = []
464 for grp in event['precondition']['groups']:
465 groups = next(g for g in events_data['groups']
466 if g['name'] == grp['name'])
467 for member in groups['members']:
468 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500469 members['object'] = (groups['type'] +
470 member)
Matthew Barth9af190c2017-08-08 14:20:43 -0500471 members['interface'] = grp['interface']
472 members['property'] = grp['property']['name']
473 members['type'] = grp['property']['type']
Matthew Barth9a5b6992018-01-23 15:32:26 -0600474 if isinstance(grp['property']['value'], str) or \
475 "string" in str(members['type']).lower():
476 members['value'] = "\"" + grp['property']['value'] + "\""
477 else:
478 members['value'] = grp['property']['value']
Matthew Barth9af190c2017-08-08 14:20:43 -0500479 group.append(members)
480 precond['pcgrp'] = group
481
Matthew Barth7f272fd2017-09-12 16:16:56 -0500482 # Add set speed event precondition actions
483 pc = []
484 pcs = {}
485 pcs['name'] = event['precondition']['name']
486 epc = next(p for p in events_data['preconditions']
Matthew Barth9af190c2017-08-08 14:20:43 -0500487 if p['name'] == event['precondition']['name'])
488 params = []
Matthew Barth7f272fd2017-09-12 16:16:56 -0500489 for p in epc['parameters']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500490 param = {}
491 if p == 'groups':
492 param['type'] = "std::vector<PrecondGroup>"
493 param['open'] = "{"
494 param['close'] = "}"
495 values = []
496 for pcgrp in group:
497 value = {}
498 value['value'] = (
499 "PrecondGroup{\"" +
Matthew Barth67967f92017-09-22 12:43:57 -0500500 str(pcgrp['object']) + "\",\"" +
Matthew Barth9af190c2017-08-08 14:20:43 -0500501 str(pcgrp['interface']) + "\",\"" +
502 str(pcgrp['property']) + "\"," +
503 "static_cast<" +
Matthew Barth9a5b6992018-01-23 15:32:26 -0600504 str(pcgrp['type']).lower() + ">")
505 if isinstance(pcgrp['value'], str) or \
506 "string" in str(pcgrp['type']).lower():
507 value['value'] += ("(" + str(pcgrp['value']) + ")}")
508 else:
509 value['value'] += \
510 ("(" + str(pcgrp['value']).lower() + ")}")
Matthew Barth9af190c2017-08-08 14:20:43 -0500511 values.append(value)
512 param['values'] = values
513 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500514 pcs['params'] = params
515 pc.append(pcs)
Matthew Barth9af190c2017-08-08 14:20:43 -0500516 precond['pcact'] = pc
517
Matthew Barth7f272fd2017-09-12 16:16:56 -0500518 pcevents = []
519 for pce in event['precondition']['events']:
520 pcevent = getEvent(zNum, zCond, pce, events_data)
521 if not pcevent:
522 continue
523 pcevents.append(pcevent)
524 precond['pcevts'] = pcevents
525
Matthew Barth67967f92017-09-22 12:43:57 -0500526 # Add precondition signal handlers
527 signals = []
Matthew Barth9af190c2017-08-08 14:20:43 -0500528 for member in group:
Matthew Barth67967f92017-09-22 12:43:57 -0500529 for eMatches in event['precondition']['matches']:
530 signal = {}
531 eMatch = next(m for m in events_data['matches']
532 if m['name'] == eMatches['name'])
533 signal['match'] = eMatch['name']
534 params = []
535 if ('parameters' in eMatch) and \
536 (eMatch['parameters'] is not None):
537 for p in eMatch['parameters']:
538 params.append(member[str(p)])
539 signal['mparams'] = params
540 eSignal = next(s for s in events_data['signals']
541 if s['name'] == eMatch['signal'])
542 signal['signal'] = eSignal['name']
543 sparams = {}
544 if ('parameters' in eSignal) and \
545 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500546 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500547 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500548 sp = str(p)
549 if (sp != 'type'):
550 splist.append(sp)
551 if (sp != 'group'):
552 sparams[sp] = "\"" + member[sp] + "\""
553 else:
554 sparams[sp] = "Group{\n"
555 for m in group:
556 sparams[sp] += (
557 "{\n" +
558 "\"" + str(m['object']) + "\",\n" +
559 "{\"" + str(m['interface']) + "\"," +
560 "\"" + str(m['property']) + "\"}\n" +
561 "},\n")
562 sparams[sp] += "}"
563 else:
564 sparams[sp] = member[sp]
565 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500566 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500567 # Add signal handler
568 eHandler = next(h for h in events_data['handlers']
569 if h['name'] == eSignal['handler'])
570 signal['handler'] = eHandler['name']
571 hparams = {}
572 if ('parameters' in eHandler) and \
573 (eHandler['parameters'] is not None):
574 hplist = []
575 for p in eHandler['parameters']:
576 hp = str(p)
577 if (hp != 'type'):
578 hplist.append(hp)
579 if (hp != 'group'):
580 hparams[hp] = "\"" + member[hp] + "\""
581 else:
582 hparams[hp] = "Group{\n"
583 for m in group:
584 hparams[hp] += (
585 "{\n" +
586 "\"" + str(m['object']) + "\",\n" +
587 "{\"" + str(m['interface']) + "\"," +
588 "\"" + str(m['property']) + "\"}\n" +
589 "},\n")
590 hparams[hp] += "}"
591 else:
592 hparams[hp] = member[hp]
593 hparams['params'] = hplist
594 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500595 signals.append(signal)
596 precond['pcsigs'] = signals
Matthew Barth9af190c2017-08-08 14:20:43 -0500597
Matthew Barth90149802017-08-15 10:51:37 -0500598 # Add optional action call timer
599 timer = {}
600 interval = "static_cast<std::chrono::seconds>"
601 if ('timer' in event['precondition']) and \
602 (event['precondition']['timer'] is not None):
603 timer['interval'] = (interval +
604 "(" +
605 str(event['precondition']['timer']['interval']) +
606 ")")
607 else:
608 timer['interval'] = (interval +
609 "(" + str(0) + ")")
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500610 timer['type'] = "util::Timer::TimerType::repeating"
Matthew Barth90149802017-08-15 10:51:37 -0500611 precond['pctime'] = timer
612
Matthew Barth9af190c2017-08-08 14:20:43 -0500613 return precond
614
615
Gunnar Millsb751f322017-06-06 15:14:11 -0500616def getEventsInZone(zone_num, zone_conditions, events_data):
Matthew Barthd4d0f082017-05-16 13:51:10 -0500617 """
618 Constructs the event entries defined for each zone using the events yaml
619 provided.
620 """
621 events = []
Matthew Barthba102b32017-05-16 16:13:56 -0500622
Matthew Barthd4d0f082017-05-16 13:51:10 -0500623 if 'events' in events_data:
624 for e in events_data['events']:
Matthew Barthd4d0f082017-05-16 13:51:10 -0500625 event = {}
Matthew Barth9af190c2017-08-08 14:20:43 -0500626 # Add precondition if given
627 if ('precondition' in e) and \
628 (e['precondition'] is not None):
Matthew Barth7f272fd2017-09-12 16:16:56 -0500629 event['pc'] = addPrecondition(zone_num,
630 zone_conditions,
631 e,
632 events_data)
Matthew Barth90149802017-08-15 10:51:37 -0500633 else:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500634 event = getEvent(zone_num, zone_conditions, e, events_data)
635 if not event:
636 continue
Matthew Barthd4d0f082017-05-16 13:51:10 -0500637 events.append(event)
638
639 return events
640
641
Matt Spinler78498c92017-04-11 13:59:46 -0500642def getFansInZone(zone_num, profiles, fan_data):
643 """
644 Parses the fan definition YAML files to find the fans
645 that match both the zone passed in and one of the
646 cooling profiles.
647 """
648
649 fans = []
650
651 for f in fan_data['fans']:
652
653 if zone_num != f['cooling_zone']:
654 continue
655
Gunnar Mills67e95512017-06-02 14:35:18 -0500656 # 'cooling_profile' is optional (use 'all' instead)
Matt Spinler78498c92017-04-11 13:59:46 -0500657 if f.get('cooling_profile') is None:
658 profile = "all"
659 else:
660 profile = f['cooling_profile']
661
662 if profile not in profiles:
663 continue
664
665 fan = {}
666 fan['name'] = f['inventory']
667 fan['sensors'] = f['sensors']
668 fans.append(fan)
669
670 return fans
671
672
Gunnar Millsee8a2812017-06-02 14:26:47 -0500673def getConditionInZoneConditions(zone_condition, zone_conditions_data):
674 """
675 Parses the zone conditions definition YAML files to find the condition
676 that match both the zone condition passed in.
677 """
678
679 condition = {}
680
681 for c in zone_conditions_data['conditions']:
682
683 if zone_condition != c['name']:
684 continue
685 condition['type'] = c['type']
686 properties = []
687 for p in c['properties']:
688 property = {}
689 property['property'] = p['property']
690 property['interface'] = p['interface']
691 property['path'] = p['path']
692 property['type'] = p['type'].lower()
693 property['value'] = str(p['value']).lower()
694 properties.append(property)
695 condition['properties'] = properties
696
697 return condition
698
699
700def buildZoneData(zone_data, fan_data, events_data, zone_conditions_data):
Matt Spinler78498c92017-04-11 13:59:46 -0500701 """
702 Combines the zone definition YAML and fan
703 definition YAML to create a data structure defining
704 the fan cooling zones.
705 """
706
707 zone_groups = []
708
709 for group in zone_data:
710 conditions = []
Gunnar Millsee8a2812017-06-02 14:26:47 -0500711 # zone conditions are optional
712 if 'zone_conditions' in group and group['zone_conditions'] is not None:
713 for c in group['zone_conditions']:
714
715 if not zone_conditions_data:
Gunnar Millsb751f322017-06-06 15:14:11 -0500716 sys.exit("No zone_conditions YAML file but " +
Gunnar Millsee8a2812017-06-02 14:26:47 -0500717 "zone_conditions used in zone YAML")
718
719 condition = getConditionInZoneConditions(c['name'],
720 zone_conditions_data)
721
722 if not condition:
723 sys.exit("Missing zone condition " + c['name'])
724
725 conditions.append(condition)
Matt Spinler78498c92017-04-11 13:59:46 -0500726
727 zone_group = {}
728 zone_group['conditions'] = conditions
729
730 zones = []
731 for z in group['zones']:
732 zone = {}
733
Gunnar Mills67e95512017-06-02 14:35:18 -0500734 # 'zone' is required
735 if ('zone' not in z) or (z['zone'] is None):
Matt Spinler78498c92017-04-11 13:59:46 -0500736 sys.exit("Missing fan zone number in " + zone_yaml)
737
738 zone['num'] = z['zone']
739
740 zone['full_speed'] = z['full_speed']
741
Matthew Barth1de66622017-06-12 13:13:02 -0500742 zone['default_floor'] = z['default_floor']
743
Matthew Bartha9561842017-06-29 11:43:45 -0500744 # 'increase_delay' is optional (use 0 by default)
745 key = 'increase_delay'
746 zone[key] = z.setdefault(key, 0)
747
748 # 'decrease_interval' is optional (use 0 by default)
749 key = 'decrease_interval'
750 zone[key] = z.setdefault(key, 0)
751
Gunnar Mills67e95512017-06-02 14:35:18 -0500752 # 'cooling_profiles' is optional (use 'all' instead)
753 if ('cooling_profiles' not in z) or \
Matt Spinler78498c92017-04-11 13:59:46 -0500754 (z['cooling_profiles'] is None):
755 profiles = ["all"]
756 else:
757 profiles = z['cooling_profiles']
758
759 fans = getFansInZone(z['zone'], profiles, fan_data)
Gunnar Millsb751f322017-06-06 15:14:11 -0500760 events = getEventsInZone(z['zone'], group['zone_conditions'],
761 events_data)
Matt Spinler78498c92017-04-11 13:59:46 -0500762
763 if len(fans) == 0:
764 sys.exit("Didn't find any fans in zone " + str(zone['num']))
765
766 zone['fans'] = fans
Matthew Barthd4d0f082017-05-16 13:51:10 -0500767 zone['events'] = events
Matt Spinler78498c92017-04-11 13:59:46 -0500768 zones.append(zone)
769
770 zone_group['zones'] = zones
771 zone_groups.append(zone_group)
772
773 return zone_groups
774
775
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500776if __name__ == '__main__':
777 parser = ArgumentParser(
778 description="Phosphor fan zone definition parser")
779
780 parser.add_argument('-z', '--zone_yaml', dest='zone_yaml',
781 default="example/zones.yaml",
782 help='fan zone definitional yaml')
783 parser.add_argument('-f', '--fan_yaml', dest='fan_yaml',
784 default="example/fans.yaml",
785 help='fan definitional yaml')
Matthew Barthd4d0f082017-05-16 13:51:10 -0500786 parser.add_argument('-e', '--events_yaml', dest='events_yaml',
787 help='events to set speeds yaml')
Gunnar Millsee8a2812017-06-02 14:26:47 -0500788 parser.add_argument('-c', '--zone_conditions_yaml',
789 dest='zone_conditions_yaml',
790 help='conditions to determine zone yaml')
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500791 parser.add_argument('-o', '--output_dir', dest='output_dir',
792 default=".",
793 help='output directory')
794 args = parser.parse_args()
795
796 if not args.zone_yaml or not args.fan_yaml:
797 parser.print_usage()
798 sys.exit(-1)
799
800 with open(args.zone_yaml, 'r') as zone_input:
801 zone_data = yaml.safe_load(zone_input) or {}
802
803 with open(args.fan_yaml, 'r') as fan_input:
804 fan_data = yaml.safe_load(fan_input) or {}
805
Matthew Barthd4d0f082017-05-16 13:51:10 -0500806 events_data = {}
807 if args.events_yaml:
808 with open(args.events_yaml, 'r') as events_input:
809 events_data = yaml.safe_load(events_input) or {}
810
Gunnar Millsee8a2812017-06-02 14:26:47 -0500811 zone_conditions_data = {}
812 if args.zone_conditions_yaml:
813 with open(args.zone_conditions_yaml, 'r') as zone_conditions_input:
814 zone_conditions_data = yaml.safe_load(zone_conditions_input) or {}
815
Matt Spinleree7f6422017-05-09 11:03:14 -0500816 zone_config = buildZoneData(zone_data.get('zone_configuration', {}),
Gunnar Millsee8a2812017-06-02 14:26:47 -0500817 fan_data, events_data, zone_conditions_data)
Matt Spinleree7f6422017-05-09 11:03:14 -0500818
819 manager_config = zone_data.get('manager_configuration', {})
820
821 if manager_config.get('power_on_delay') is None:
822 manager_config['power_on_delay'] = 0
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500823
824 output_file = os.path.join(args.output_dir, "fan_zone_defs.cpp")
825 with open(output_file, 'w') as output:
Matt Spinleree7f6422017-05-09 11:03:14 -0500826 output.write(Template(tmpl).render(zones=zone_config,
827 mgr_data=manager_config))