blob: c071aea43a4d67df9e91c1349681d1f72bf39020 [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 """
246 listOfDict = listOfDict.replace('[', '{')
247 listOfDict = listOfDict.replace(']', '}')
248 listOfDict = listOfDict.replace(':', ',')
249 return listOfDict
250
251
Matthew Barth9df74752017-10-11 14:39:31 -0500252def getActions(edata, actions, events):
253 """
254 Extracts and constructs the make_action function call for
255 all the actions within the given event.
256 """
257 action = []
258 for eActions in actions['actions']:
259 actions = {}
260 eAction = next(a for a in events['actions']
261 if a['name'] == eActions['name'])
262 actions['name'] = eAction['name']
263 params = []
264 if ('parameters' in eAction) and \
265 (eAction['parameters'] is not None):
266 for p in eAction['parameters']:
267 param = "static_cast<"
268 if type(eActions[p]) is not dict:
269 if p == 'actions':
270 param = "std::vector<Action>{"
271 pActs = getActions(edata, eActions, events)
272 for a in pActs:
273 if (len(a['parameters']) != 0):
274 param += (
275 "make_action(action::" +
276 a['name'] +
277 "(\n")
278 for i, ap in enumerate(a['parameters']):
279 if (i+1) != len(a['parameters']):
280 param += (ap + ",")
281 else:
282 param += (ap + ")")
283 else:
284 param += ("make_action(action::" + a['name'])
285 param += "),"
286 param += "}"
287 elif p == 'property':
288 param += (
289 str(edata['property']['type']).lower() +
290 ">(" + str(eActions[p]).lower() + ")")
291 else:
292 # Default type to 'size_t' when not given
293 param += ("size_t>(" + str(eActions[p]).lower() + ")")
294 else:
295 if p == 'timer':
296 param = (
297 "Timer{static_cast<std::chrono::seconds>(" +
298 str(eActions[p]['delay']) + "), " +
299 "util::Timer::TimerType::" +
300 str(eActions[p]['type']) + "}")
301 else:
302 param += (str(eActions[p]['type']).lower() + ">(")
303 if p != 'map':
304 param += str(eActions[p]['value']).lower() + ")"
305 else:
306 param += (
307 str(eActions[p]['type']).lower() +
308 convertToMap(str(eActions[p]['value'])) + ")")
309 params.append(param)
310 actions['parameters'] = params
311 action.append(actions)
312 return action
313
314
Matthew Barth7f272fd2017-09-12 16:16:56 -0500315def getEvent(zone_num, zone_conditions, e, events_data):
316 """
317 Parses the sections of an event and populates the properties
318 that construct an event within the generated source.
319 """
320 event = {}
321 # Zone numbers are optional in the events yaml but skip if this
322 # zone's zone number is not in the event's zone numbers
323 if all('zones' in z and
324 z['zones'] is not None and
325 zone_num not in z['zones']
326 for z in e['zone_conditions']):
327 return
328
329 # Zone conditions are optional in the events yaml but skip
330 # if this event's condition is not in this zone's conditions
331 if all('name' in z and z['name'] is not None and
332 not any(c['name'] == z['name'] for c in zone_conditions)
333 for z in e['zone_conditions']):
334 return
335
336 # Add set speed event group
337 group = []
338 groups = next(g for g in events_data['groups']
339 if g['name'] == e['group'])
340 for member in groups['members']:
341 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500342 members['object'] = (groups['type'] +
343 member)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500344 members['interface'] = e['interface']
345 members['property'] = e['property']['name']
Matthew Barth67967f92017-09-22 12:43:57 -0500346 members['type'] = e['property']['type']
Matthew Barth7f272fd2017-09-12 16:16:56 -0500347 group.append(members)
348 event['group'] = group
349
350 # Add set speed actions and function parameters
Matthew Barth9df74752017-10-11 14:39:31 -0500351 event['action'] = getActions(e, e, events_data)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500352
Matthew Barth67967f92017-09-22 12:43:57 -0500353 # Add signal handlers
354 signals = []
355 for member in group:
356 for eMatches in e['matches']:
357 signal = {}
358 eMatch = next(m for m in events_data['matches']
359 if m['name'] == eMatches['name'])
360 signal['match'] = eMatch['name']
361 params = []
362 if ('parameters' in eMatch) and \
363 (eMatch['parameters'] is not None):
364 for p in eMatch['parameters']:
365 params.append(member[str(p)])
366 signal['mparams'] = params
367 eSignal = next(s for s in events_data['signals']
368 if s['name'] == eMatch['signal'])
369 signal['signal'] = eSignal['name']
370 sparams = {}
371 if ('parameters' in eSignal) and \
372 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500373 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500374 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500375 sp = str(p)
376 if (sp != 'type'):
377 splist.append(sp)
378 if (sp != 'group'):
379 sparams[sp] = "\"" + member[sp] + "\""
380 else:
381 sparams[sp] = "Group{\n"
382 for m in group:
383 sparams[sp] += (
384 "{\n" +
385 "\"" + str(m['object']) + "\",\n" +
386 "{\"" + str(m['interface']) + "\"," +
387 "\"" + str(m['property']) + "\"}\n" +
388 "},\n")
389 sparams[sp] += "}"
390 else:
391 sparams[sp] = member[sp]
392 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500393 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500394 # Add signal handler
395 eHandler = next(h for h in events_data['handlers']
396 if h['name'] == eSignal['handler'])
397 signal['handler'] = eHandler['name']
398 hparams = {}
399 if ('parameters' in eHandler) and \
400 (eHandler['parameters'] is not None):
401 hplist = []
402 for p in eHandler['parameters']:
403 hp = str(p)
404 if (hp != 'type'):
405 hplist.append(hp)
406 if (hp != 'group'):
407 hparams[hp] = "\"" + member[hp] + "\""
408 else:
409 hparams[hp] = "Group{\n"
410 for m in group:
411 hparams[hp] += (
412 "{\n" +
413 "\"" + str(m['object']) + "\",\n" +
414 "{\"" + str(m['interface']) + "\"," +
415 "\"" + str(m['property']) + "\"}\n" +
416 "},\n")
417 hparams[hp] += "}"
418 else:
419 hparams[hp] = member[hp]
420 hparams['params'] = hplist
421 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500422 signals.append(signal)
423 event['signals'] = signals
Matthew Barth7f272fd2017-09-12 16:16:56 -0500424
425 # Add optional action call timer
426 timer = {}
427 interval = "static_cast<std::chrono::seconds>"
428 if ('timer' in e) and \
429 (e['timer'] is not None):
430 timer['interval'] = (interval +
431 "(" +
432 str(e['timer']['interval']) +
433 ")")
434 else:
435 timer['interval'] = (interval +
436 "(" + str(0) + ")")
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500437 timer['type'] = "util::Timer::TimerType::repeating"
Matthew Barth7f272fd2017-09-12 16:16:56 -0500438 event['timer'] = timer
439
440 return event
441
442
443def addPrecondition(zNum, zCond, event, events_data):
Matthew Barth9af190c2017-08-08 14:20:43 -0500444 """
445 Parses the precondition section of an event and populates the necessary
446 structures to generate a precondition for a set speed event.
447 """
448 precond = {}
449 # Add set speed event precondition group
450 group = []
451 for grp in event['precondition']['groups']:
452 groups = next(g for g in events_data['groups']
453 if g['name'] == grp['name'])
454 for member in groups['members']:
455 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500456 members['object'] = (groups['type'] +
457 member)
Matthew Barth9af190c2017-08-08 14:20:43 -0500458 members['interface'] = grp['interface']
459 members['property'] = grp['property']['name']
460 members['type'] = grp['property']['type']
461 members['value'] = grp['property']['value']
462 group.append(members)
463 precond['pcgrp'] = group
464
Matthew Barth7f272fd2017-09-12 16:16:56 -0500465 # Add set speed event precondition actions
466 pc = []
467 pcs = {}
468 pcs['name'] = event['precondition']['name']
469 epc = next(p for p in events_data['preconditions']
Matthew Barth9af190c2017-08-08 14:20:43 -0500470 if p['name'] == event['precondition']['name'])
471 params = []
Matthew Barth7f272fd2017-09-12 16:16:56 -0500472 for p in epc['parameters']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500473 param = {}
474 if p == 'groups':
475 param['type'] = "std::vector<PrecondGroup>"
476 param['open'] = "{"
477 param['close'] = "}"
478 values = []
479 for pcgrp in group:
480 value = {}
481 value['value'] = (
482 "PrecondGroup{\"" +
Matthew Barth67967f92017-09-22 12:43:57 -0500483 str(pcgrp['object']) + "\",\"" +
Matthew Barth9af190c2017-08-08 14:20:43 -0500484 str(pcgrp['interface']) + "\",\"" +
485 str(pcgrp['property']) + "\"," +
486 "static_cast<" +
487 str(pcgrp['type']).lower() + ">" +
488 "(" + str(pcgrp['value']).lower() + ")}")
489 values.append(value)
490 param['values'] = values
491 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500492 pcs['params'] = params
493 pc.append(pcs)
Matthew Barth9af190c2017-08-08 14:20:43 -0500494 precond['pcact'] = pc
495
Matthew Barth7f272fd2017-09-12 16:16:56 -0500496 pcevents = []
497 for pce in event['precondition']['events']:
498 pcevent = getEvent(zNum, zCond, pce, events_data)
499 if not pcevent:
500 continue
501 pcevents.append(pcevent)
502 precond['pcevts'] = pcevents
503
Matthew Barth67967f92017-09-22 12:43:57 -0500504 # Add precondition signal handlers
505 signals = []
Matthew Barth9af190c2017-08-08 14:20:43 -0500506 for member in group:
Matthew Barth67967f92017-09-22 12:43:57 -0500507 for eMatches in event['precondition']['matches']:
508 signal = {}
509 eMatch = next(m for m in events_data['matches']
510 if m['name'] == eMatches['name'])
511 signal['match'] = eMatch['name']
512 params = []
513 if ('parameters' in eMatch) and \
514 (eMatch['parameters'] is not None):
515 for p in eMatch['parameters']:
516 params.append(member[str(p)])
517 signal['mparams'] = params
518 eSignal = next(s for s in events_data['signals']
519 if s['name'] == eMatch['signal'])
520 signal['signal'] = eSignal['name']
521 sparams = {}
522 if ('parameters' in eSignal) and \
523 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500524 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500525 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500526 sp = str(p)
527 if (sp != 'type'):
528 splist.append(sp)
529 if (sp != 'group'):
530 sparams[sp] = "\"" + member[sp] + "\""
531 else:
532 sparams[sp] = "Group{\n"
533 for m in group:
534 sparams[sp] += (
535 "{\n" +
536 "\"" + str(m['object']) + "\",\n" +
537 "{\"" + str(m['interface']) + "\"," +
538 "\"" + str(m['property']) + "\"}\n" +
539 "},\n")
540 sparams[sp] += "}"
541 else:
542 sparams[sp] = member[sp]
543 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500544 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500545 # Add signal handler
546 eHandler = next(h for h in events_data['handlers']
547 if h['name'] == eSignal['handler'])
548 signal['handler'] = eHandler['name']
549 hparams = {}
550 if ('parameters' in eHandler) and \
551 (eHandler['parameters'] is not None):
552 hplist = []
553 for p in eHandler['parameters']:
554 hp = str(p)
555 if (hp != 'type'):
556 hplist.append(hp)
557 if (hp != 'group'):
558 hparams[hp] = "\"" + member[hp] + "\""
559 else:
560 hparams[hp] = "Group{\n"
561 for m in group:
562 hparams[hp] += (
563 "{\n" +
564 "\"" + str(m['object']) + "\",\n" +
565 "{\"" + str(m['interface']) + "\"," +
566 "\"" + str(m['property']) + "\"}\n" +
567 "},\n")
568 hparams[hp] += "}"
569 else:
570 hparams[hp] = member[hp]
571 hparams['params'] = hplist
572 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500573 signals.append(signal)
574 precond['pcsigs'] = signals
Matthew Barth9af190c2017-08-08 14:20:43 -0500575
Matthew Barth90149802017-08-15 10:51:37 -0500576 # Add optional action call timer
577 timer = {}
578 interval = "static_cast<std::chrono::seconds>"
579 if ('timer' in event['precondition']) and \
580 (event['precondition']['timer'] is not None):
581 timer['interval'] = (interval +
582 "(" +
583 str(event['precondition']['timer']['interval']) +
584 ")")
585 else:
586 timer['interval'] = (interval +
587 "(" + str(0) + ")")
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500588 timer['type'] = "util::Timer::TimerType::repeating"
Matthew Barth90149802017-08-15 10:51:37 -0500589 precond['pctime'] = timer
590
Matthew Barth9af190c2017-08-08 14:20:43 -0500591 return precond
592
593
Gunnar Millsb751f322017-06-06 15:14:11 -0500594def getEventsInZone(zone_num, zone_conditions, events_data):
Matthew Barthd4d0f082017-05-16 13:51:10 -0500595 """
596 Constructs the event entries defined for each zone using the events yaml
597 provided.
598 """
599 events = []
Matthew Barthba102b32017-05-16 16:13:56 -0500600
Matthew Barthd4d0f082017-05-16 13:51:10 -0500601 if 'events' in events_data:
602 for e in events_data['events']:
Matthew Barthd4d0f082017-05-16 13:51:10 -0500603 event = {}
Matthew Barth9af190c2017-08-08 14:20:43 -0500604 # Add precondition if given
605 if ('precondition' in e) and \
606 (e['precondition'] is not None):
Matthew Barth7f272fd2017-09-12 16:16:56 -0500607 event['pc'] = addPrecondition(zone_num,
608 zone_conditions,
609 e,
610 events_data)
Matthew Barth90149802017-08-15 10:51:37 -0500611 else:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500612 event = getEvent(zone_num, zone_conditions, e, events_data)
613 if not event:
614 continue
Matthew Barthd4d0f082017-05-16 13:51:10 -0500615 events.append(event)
616
617 return events
618
619
Matt Spinler78498c92017-04-11 13:59:46 -0500620def getFansInZone(zone_num, profiles, fan_data):
621 """
622 Parses the fan definition YAML files to find the fans
623 that match both the zone passed in and one of the
624 cooling profiles.
625 """
626
627 fans = []
628
629 for f in fan_data['fans']:
630
631 if zone_num != f['cooling_zone']:
632 continue
633
Gunnar Mills67e95512017-06-02 14:35:18 -0500634 # 'cooling_profile' is optional (use 'all' instead)
Matt Spinler78498c92017-04-11 13:59:46 -0500635 if f.get('cooling_profile') is None:
636 profile = "all"
637 else:
638 profile = f['cooling_profile']
639
640 if profile not in profiles:
641 continue
642
643 fan = {}
644 fan['name'] = f['inventory']
645 fan['sensors'] = f['sensors']
646 fans.append(fan)
647
648 return fans
649
650
Gunnar Millsee8a2812017-06-02 14:26:47 -0500651def getConditionInZoneConditions(zone_condition, zone_conditions_data):
652 """
653 Parses the zone conditions definition YAML files to find the condition
654 that match both the zone condition passed in.
655 """
656
657 condition = {}
658
659 for c in zone_conditions_data['conditions']:
660
661 if zone_condition != c['name']:
662 continue
663 condition['type'] = c['type']
664 properties = []
665 for p in c['properties']:
666 property = {}
667 property['property'] = p['property']
668 property['interface'] = p['interface']
669 property['path'] = p['path']
670 property['type'] = p['type'].lower()
671 property['value'] = str(p['value']).lower()
672 properties.append(property)
673 condition['properties'] = properties
674
675 return condition
676
677
678def buildZoneData(zone_data, fan_data, events_data, zone_conditions_data):
Matt Spinler78498c92017-04-11 13:59:46 -0500679 """
680 Combines the zone definition YAML and fan
681 definition YAML to create a data structure defining
682 the fan cooling zones.
683 """
684
685 zone_groups = []
686
687 for group in zone_data:
688 conditions = []
Gunnar Millsee8a2812017-06-02 14:26:47 -0500689 # zone conditions are optional
690 if 'zone_conditions' in group and group['zone_conditions'] is not None:
691 for c in group['zone_conditions']:
692
693 if not zone_conditions_data:
Gunnar Millsb751f322017-06-06 15:14:11 -0500694 sys.exit("No zone_conditions YAML file but " +
Gunnar Millsee8a2812017-06-02 14:26:47 -0500695 "zone_conditions used in zone YAML")
696
697 condition = getConditionInZoneConditions(c['name'],
698 zone_conditions_data)
699
700 if not condition:
701 sys.exit("Missing zone condition " + c['name'])
702
703 conditions.append(condition)
Matt Spinler78498c92017-04-11 13:59:46 -0500704
705 zone_group = {}
706 zone_group['conditions'] = conditions
707
708 zones = []
709 for z in group['zones']:
710 zone = {}
711
Gunnar Mills67e95512017-06-02 14:35:18 -0500712 # 'zone' is required
713 if ('zone' not in z) or (z['zone'] is None):
Matt Spinler78498c92017-04-11 13:59:46 -0500714 sys.exit("Missing fan zone number in " + zone_yaml)
715
716 zone['num'] = z['zone']
717
718 zone['full_speed'] = z['full_speed']
719
Matthew Barth1de66622017-06-12 13:13:02 -0500720 zone['default_floor'] = z['default_floor']
721
Matthew Bartha9561842017-06-29 11:43:45 -0500722 # 'increase_delay' is optional (use 0 by default)
723 key = 'increase_delay'
724 zone[key] = z.setdefault(key, 0)
725
726 # 'decrease_interval' is optional (use 0 by default)
727 key = 'decrease_interval'
728 zone[key] = z.setdefault(key, 0)
729
Gunnar Mills67e95512017-06-02 14:35:18 -0500730 # 'cooling_profiles' is optional (use 'all' instead)
731 if ('cooling_profiles' not in z) or \
Matt Spinler78498c92017-04-11 13:59:46 -0500732 (z['cooling_profiles'] is None):
733 profiles = ["all"]
734 else:
735 profiles = z['cooling_profiles']
736
737 fans = getFansInZone(z['zone'], profiles, fan_data)
Gunnar Millsb751f322017-06-06 15:14:11 -0500738 events = getEventsInZone(z['zone'], group['zone_conditions'],
739 events_data)
Matt Spinler78498c92017-04-11 13:59:46 -0500740
741 if len(fans) == 0:
742 sys.exit("Didn't find any fans in zone " + str(zone['num']))
743
744 zone['fans'] = fans
Matthew Barthd4d0f082017-05-16 13:51:10 -0500745 zone['events'] = events
Matt Spinler78498c92017-04-11 13:59:46 -0500746 zones.append(zone)
747
748 zone_group['zones'] = zones
749 zone_groups.append(zone_group)
750
751 return zone_groups
752
753
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500754if __name__ == '__main__':
755 parser = ArgumentParser(
756 description="Phosphor fan zone definition parser")
757
758 parser.add_argument('-z', '--zone_yaml', dest='zone_yaml',
759 default="example/zones.yaml",
760 help='fan zone definitional yaml')
761 parser.add_argument('-f', '--fan_yaml', dest='fan_yaml',
762 default="example/fans.yaml",
763 help='fan definitional yaml')
Matthew Barthd4d0f082017-05-16 13:51:10 -0500764 parser.add_argument('-e', '--events_yaml', dest='events_yaml',
765 help='events to set speeds yaml')
Gunnar Millsee8a2812017-06-02 14:26:47 -0500766 parser.add_argument('-c', '--zone_conditions_yaml',
767 dest='zone_conditions_yaml',
768 help='conditions to determine zone yaml')
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500769 parser.add_argument('-o', '--output_dir', dest='output_dir',
770 default=".",
771 help='output directory')
772 args = parser.parse_args()
773
774 if not args.zone_yaml or not args.fan_yaml:
775 parser.print_usage()
776 sys.exit(-1)
777
778 with open(args.zone_yaml, 'r') as zone_input:
779 zone_data = yaml.safe_load(zone_input) or {}
780
781 with open(args.fan_yaml, 'r') as fan_input:
782 fan_data = yaml.safe_load(fan_input) or {}
783
Matthew Barthd4d0f082017-05-16 13:51:10 -0500784 events_data = {}
785 if args.events_yaml:
786 with open(args.events_yaml, 'r') as events_input:
787 events_data = yaml.safe_load(events_input) or {}
788
Gunnar Millsee8a2812017-06-02 14:26:47 -0500789 zone_conditions_data = {}
790 if args.zone_conditions_yaml:
791 with open(args.zone_conditions_yaml, 'r') as zone_conditions_input:
792 zone_conditions_data = yaml.safe_load(zone_conditions_input) or {}
793
Matt Spinleree7f6422017-05-09 11:03:14 -0500794 zone_config = buildZoneData(zone_data.get('zone_configuration', {}),
Gunnar Millsee8a2812017-06-02 14:26:47 -0500795 fan_data, events_data, zone_conditions_data)
Matt Spinleree7f6422017-05-09 11:03:14 -0500796
797 manager_config = zone_data.get('manager_configuration', {})
798
799 if manager_config.get('power_on_delay') is None:
800 manager_config['power_on_delay'] = 0
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500801
802 output_file = os.path.join(args.output_dir, "fan_zone_defs.cpp")
803 with open(output_file, 'w') as output:
Matt Spinleree7f6422017-05-09 11:03:14 -0500804 output.write(Template(tmpl).render(zones=zone_config,
805 mgr_data=manager_config))