blob: aa6ae9cc82c763343d44733cbad9c552d2c49b53 [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 Barth7f272fd2017-09-12 16:16:56 -0500252def getEvent(zone_num, zone_conditions, e, events_data):
253 """
254 Parses the sections of an event and populates the properties
255 that construct an event within the generated source.
256 """
257 event = {}
258 # Zone numbers are optional in the events yaml but skip if this
259 # zone's zone number is not in the event's zone numbers
260 if all('zones' in z and
261 z['zones'] is not None and
262 zone_num not in z['zones']
263 for z in e['zone_conditions']):
264 return
265
266 # Zone conditions are optional in the events yaml but skip
267 # if this event's condition is not in this zone's conditions
268 if all('name' in z and z['name'] is not None and
269 not any(c['name'] == z['name'] for c in zone_conditions)
270 for z in e['zone_conditions']):
271 return
272
273 # Add set speed event group
274 group = []
275 groups = next(g for g in events_data['groups']
276 if g['name'] == e['group'])
277 for member in groups['members']:
278 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500279 members['object'] = (groups['type'] +
280 member)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500281 members['interface'] = e['interface']
282 members['property'] = e['property']['name']
Matthew Barth67967f92017-09-22 12:43:57 -0500283 members['type'] = e['property']['type']
Matthew Barth7f272fd2017-09-12 16:16:56 -0500284 group.append(members)
285 event['group'] = group
286
287 # Add set speed actions and function parameters
288 action = []
289 for eActions in e['actions']:
290 actions = {}
291 eAction = next(a for a in events_data['actions']
292 if a['name'] == eActions['name'])
293 actions['name'] = eAction['name']
294 params = []
Matthew Barth4c04a012017-09-15 13:05:30 -0500295 if ('parameters' in eAction) and \
296 (eAction['parameters'] is not None):
297 for p in eAction['parameters']:
Matthew Barth6c997d72017-10-10 15:32:09 -0500298 param = "static_cast<"
Matthew Barth4c04a012017-09-15 13:05:30 -0500299 if type(eActions[p]) is not dict:
300 if p == 'property':
Matthew Barth6c997d72017-10-10 15:32:09 -0500301 param += (str(e['property']['type']).lower() + ">(" +
302 str(eActions[p]).lower() + ")")
Matthew Barth4c04a012017-09-15 13:05:30 -0500303 else:
304 # Default type to 'size_t' when not given
Matthew Barth6c997d72017-10-10 15:32:09 -0500305 param += ("size_t>(" + str(eActions[p]).lower() + ")")
Matthew Barth7f272fd2017-09-12 16:16:56 -0500306 else:
Matthew Barth6c997d72017-10-10 15:32:09 -0500307 param += (str(eActions[p]['type']).lower() + ">(")
Matthew Barth4c04a012017-09-15 13:05:30 -0500308 if p != 'map':
Matthew Barth6c997d72017-10-10 15:32:09 -0500309 param += (str(eActions[p]['value']).lower() + ")")
Matthew Barth4c04a012017-09-15 13:05:30 -0500310 else:
Matthew Barth6c997d72017-10-10 15:32:09 -0500311 param += (convertToMap(str(eActions[p]['value'])) + ")")
312 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500313 actions['parameters'] = params
314 action.append(actions)
315 event['action'] = action
316
Matthew Barth67967f92017-09-22 12:43:57 -0500317 # Add signal handlers
318 signals = []
319 for member in group:
320 for eMatches in e['matches']:
321 signal = {}
322 eMatch = next(m for m in events_data['matches']
323 if m['name'] == eMatches['name'])
324 signal['match'] = eMatch['name']
325 params = []
326 if ('parameters' in eMatch) and \
327 (eMatch['parameters'] is not None):
328 for p in eMatch['parameters']:
329 params.append(member[str(p)])
330 signal['mparams'] = params
331 eSignal = next(s for s in events_data['signals']
332 if s['name'] == eMatch['signal'])
333 signal['signal'] = eSignal['name']
334 sparams = {}
335 if ('parameters' in eSignal) and \
336 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500337 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500338 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500339 sp = str(p)
340 if (sp != 'type'):
341 splist.append(sp)
342 if (sp != 'group'):
343 sparams[sp] = "\"" + member[sp] + "\""
344 else:
345 sparams[sp] = "Group{\n"
346 for m in group:
347 sparams[sp] += (
348 "{\n" +
349 "\"" + str(m['object']) + "\",\n" +
350 "{\"" + str(m['interface']) + "\"," +
351 "\"" + str(m['property']) + "\"}\n" +
352 "},\n")
353 sparams[sp] += "}"
354 else:
355 sparams[sp] = member[sp]
356 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500357 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500358 # Add signal handler
359 eHandler = next(h for h in events_data['handlers']
360 if h['name'] == eSignal['handler'])
361 signal['handler'] = eHandler['name']
362 hparams = {}
363 if ('parameters' in eHandler) and \
364 (eHandler['parameters'] is not None):
365 hplist = []
366 for p in eHandler['parameters']:
367 hp = str(p)
368 if (hp != 'type'):
369 hplist.append(hp)
370 if (hp != 'group'):
371 hparams[hp] = "\"" + member[hp] + "\""
372 else:
373 hparams[hp] = "Group{\n"
374 for m in group:
375 hparams[hp] += (
376 "{\n" +
377 "\"" + str(m['object']) + "\",\n" +
378 "{\"" + str(m['interface']) + "\"," +
379 "\"" + str(m['property']) + "\"}\n" +
380 "},\n")
381 hparams[hp] += "}"
382 else:
383 hparams[hp] = member[hp]
384 hparams['params'] = hplist
385 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500386 signals.append(signal)
387 event['signals'] = signals
Matthew Barth7f272fd2017-09-12 16:16:56 -0500388
389 # Add optional action call timer
390 timer = {}
391 interval = "static_cast<std::chrono::seconds>"
392 if ('timer' in e) and \
393 (e['timer'] is not None):
394 timer['interval'] = (interval +
395 "(" +
396 str(e['timer']['interval']) +
397 ")")
398 else:
399 timer['interval'] = (interval +
400 "(" + str(0) + ")")
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500401 timer['type'] = "util::Timer::TimerType::repeating"
Matthew Barth7f272fd2017-09-12 16:16:56 -0500402 event['timer'] = timer
403
404 return event
405
406
407def addPrecondition(zNum, zCond, event, events_data):
Matthew Barth9af190c2017-08-08 14:20:43 -0500408 """
409 Parses the precondition section of an event and populates the necessary
410 structures to generate a precondition for a set speed event.
411 """
412 precond = {}
413 # Add set speed event precondition group
414 group = []
415 for grp in event['precondition']['groups']:
416 groups = next(g for g in events_data['groups']
417 if g['name'] == grp['name'])
418 for member in groups['members']:
419 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500420 members['object'] = (groups['type'] +
421 member)
Matthew Barth9af190c2017-08-08 14:20:43 -0500422 members['interface'] = grp['interface']
423 members['property'] = grp['property']['name']
424 members['type'] = grp['property']['type']
425 members['value'] = grp['property']['value']
426 group.append(members)
427 precond['pcgrp'] = group
428
Matthew Barth7f272fd2017-09-12 16:16:56 -0500429 # Add set speed event precondition actions
430 pc = []
431 pcs = {}
432 pcs['name'] = event['precondition']['name']
433 epc = next(p for p in events_data['preconditions']
Matthew Barth9af190c2017-08-08 14:20:43 -0500434 if p['name'] == event['precondition']['name'])
435 params = []
Matthew Barth7f272fd2017-09-12 16:16:56 -0500436 for p in epc['parameters']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500437 param = {}
438 if p == 'groups':
439 param['type'] = "std::vector<PrecondGroup>"
440 param['open'] = "{"
441 param['close'] = "}"
442 values = []
443 for pcgrp in group:
444 value = {}
445 value['value'] = (
446 "PrecondGroup{\"" +
Matthew Barth67967f92017-09-22 12:43:57 -0500447 str(pcgrp['object']) + "\",\"" +
Matthew Barth9af190c2017-08-08 14:20:43 -0500448 str(pcgrp['interface']) + "\",\"" +
449 str(pcgrp['property']) + "\"," +
450 "static_cast<" +
451 str(pcgrp['type']).lower() + ">" +
452 "(" + str(pcgrp['value']).lower() + ")}")
453 values.append(value)
454 param['values'] = values
455 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500456 pcs['params'] = params
457 pc.append(pcs)
Matthew Barth9af190c2017-08-08 14:20:43 -0500458 precond['pcact'] = pc
459
Matthew Barth7f272fd2017-09-12 16:16:56 -0500460 pcevents = []
461 for pce in event['precondition']['events']:
462 pcevent = getEvent(zNum, zCond, pce, events_data)
463 if not pcevent:
464 continue
465 pcevents.append(pcevent)
466 precond['pcevts'] = pcevents
467
Matthew Barth67967f92017-09-22 12:43:57 -0500468 # Add precondition signal handlers
469 signals = []
Matthew Barth9af190c2017-08-08 14:20:43 -0500470 for member in group:
Matthew Barth67967f92017-09-22 12:43:57 -0500471 for eMatches in event['precondition']['matches']:
472 signal = {}
473 eMatch = next(m for m in events_data['matches']
474 if m['name'] == eMatches['name'])
475 signal['match'] = eMatch['name']
476 params = []
477 if ('parameters' in eMatch) and \
478 (eMatch['parameters'] is not None):
479 for p in eMatch['parameters']:
480 params.append(member[str(p)])
481 signal['mparams'] = params
482 eSignal = next(s for s in events_data['signals']
483 if s['name'] == eMatch['signal'])
484 signal['signal'] = eSignal['name']
485 sparams = {}
486 if ('parameters' in eSignal) and \
487 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500488 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500489 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500490 sp = str(p)
491 if (sp != 'type'):
492 splist.append(sp)
493 if (sp != 'group'):
494 sparams[sp] = "\"" + member[sp] + "\""
495 else:
496 sparams[sp] = "Group{\n"
497 for m in group:
498 sparams[sp] += (
499 "{\n" +
500 "\"" + str(m['object']) + "\",\n" +
501 "{\"" + str(m['interface']) + "\"," +
502 "\"" + str(m['property']) + "\"}\n" +
503 "},\n")
504 sparams[sp] += "}"
505 else:
506 sparams[sp] = member[sp]
507 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500508 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500509 # Add signal handler
510 eHandler = next(h for h in events_data['handlers']
511 if h['name'] == eSignal['handler'])
512 signal['handler'] = eHandler['name']
513 hparams = {}
514 if ('parameters' in eHandler) and \
515 (eHandler['parameters'] is not None):
516 hplist = []
517 for p in eHandler['parameters']:
518 hp = str(p)
519 if (hp != 'type'):
520 hplist.append(hp)
521 if (hp != 'group'):
522 hparams[hp] = "\"" + member[hp] + "\""
523 else:
524 hparams[hp] = "Group{\n"
525 for m in group:
526 hparams[hp] += (
527 "{\n" +
528 "\"" + str(m['object']) + "\",\n" +
529 "{\"" + str(m['interface']) + "\"," +
530 "\"" + str(m['property']) + "\"}\n" +
531 "},\n")
532 hparams[hp] += "}"
533 else:
534 hparams[hp] = member[hp]
535 hparams['params'] = hplist
536 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500537 signals.append(signal)
538 precond['pcsigs'] = signals
Matthew Barth9af190c2017-08-08 14:20:43 -0500539
Matthew Barth90149802017-08-15 10:51:37 -0500540 # Add optional action call timer
541 timer = {}
542 interval = "static_cast<std::chrono::seconds>"
543 if ('timer' in event['precondition']) and \
544 (event['precondition']['timer'] is not None):
545 timer['interval'] = (interval +
546 "(" +
547 str(event['precondition']['timer']['interval']) +
548 ")")
549 else:
550 timer['interval'] = (interval +
551 "(" + str(0) + ")")
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500552 timer['type'] = "util::Timer::TimerType::repeating"
Matthew Barth90149802017-08-15 10:51:37 -0500553 precond['pctime'] = timer
554
Matthew Barth9af190c2017-08-08 14:20:43 -0500555 return precond
556
557
Gunnar Millsb751f322017-06-06 15:14:11 -0500558def getEventsInZone(zone_num, zone_conditions, events_data):
Matthew Barthd4d0f082017-05-16 13:51:10 -0500559 """
560 Constructs the event entries defined for each zone using the events yaml
561 provided.
562 """
563 events = []
Matthew Barthba102b32017-05-16 16:13:56 -0500564
Matthew Barthd4d0f082017-05-16 13:51:10 -0500565 if 'events' in events_data:
566 for e in events_data['events']:
Matthew Barthd4d0f082017-05-16 13:51:10 -0500567 event = {}
Matthew Barth9af190c2017-08-08 14:20:43 -0500568 # Add precondition if given
569 if ('precondition' in e) and \
570 (e['precondition'] is not None):
Matthew Barth7f272fd2017-09-12 16:16:56 -0500571 event['pc'] = addPrecondition(zone_num,
572 zone_conditions,
573 e,
574 events_data)
Matthew Barth90149802017-08-15 10:51:37 -0500575 else:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500576 event = getEvent(zone_num, zone_conditions, e, events_data)
577 if not event:
578 continue
Matthew Barthd4d0f082017-05-16 13:51:10 -0500579 events.append(event)
580
581 return events
582
583
Matt Spinler78498c92017-04-11 13:59:46 -0500584def getFansInZone(zone_num, profiles, fan_data):
585 """
586 Parses the fan definition YAML files to find the fans
587 that match both the zone passed in and one of the
588 cooling profiles.
589 """
590
591 fans = []
592
593 for f in fan_data['fans']:
594
595 if zone_num != f['cooling_zone']:
596 continue
597
Gunnar Mills67e95512017-06-02 14:35:18 -0500598 # 'cooling_profile' is optional (use 'all' instead)
Matt Spinler78498c92017-04-11 13:59:46 -0500599 if f.get('cooling_profile') is None:
600 profile = "all"
601 else:
602 profile = f['cooling_profile']
603
604 if profile not in profiles:
605 continue
606
607 fan = {}
608 fan['name'] = f['inventory']
609 fan['sensors'] = f['sensors']
610 fans.append(fan)
611
612 return fans
613
614
Gunnar Millsee8a2812017-06-02 14:26:47 -0500615def getConditionInZoneConditions(zone_condition, zone_conditions_data):
616 """
617 Parses the zone conditions definition YAML files to find the condition
618 that match both the zone condition passed in.
619 """
620
621 condition = {}
622
623 for c in zone_conditions_data['conditions']:
624
625 if zone_condition != c['name']:
626 continue
627 condition['type'] = c['type']
628 properties = []
629 for p in c['properties']:
630 property = {}
631 property['property'] = p['property']
632 property['interface'] = p['interface']
633 property['path'] = p['path']
634 property['type'] = p['type'].lower()
635 property['value'] = str(p['value']).lower()
636 properties.append(property)
637 condition['properties'] = properties
638
639 return condition
640
641
642def buildZoneData(zone_data, fan_data, events_data, zone_conditions_data):
Matt Spinler78498c92017-04-11 13:59:46 -0500643 """
644 Combines the zone definition YAML and fan
645 definition YAML to create a data structure defining
646 the fan cooling zones.
647 """
648
649 zone_groups = []
650
651 for group in zone_data:
652 conditions = []
Gunnar Millsee8a2812017-06-02 14:26:47 -0500653 # zone conditions are optional
654 if 'zone_conditions' in group and group['zone_conditions'] is not None:
655 for c in group['zone_conditions']:
656
657 if not zone_conditions_data:
Gunnar Millsb751f322017-06-06 15:14:11 -0500658 sys.exit("No zone_conditions YAML file but " +
Gunnar Millsee8a2812017-06-02 14:26:47 -0500659 "zone_conditions used in zone YAML")
660
661 condition = getConditionInZoneConditions(c['name'],
662 zone_conditions_data)
663
664 if not condition:
665 sys.exit("Missing zone condition " + c['name'])
666
667 conditions.append(condition)
Matt Spinler78498c92017-04-11 13:59:46 -0500668
669 zone_group = {}
670 zone_group['conditions'] = conditions
671
672 zones = []
673 for z in group['zones']:
674 zone = {}
675
Gunnar Mills67e95512017-06-02 14:35:18 -0500676 # 'zone' is required
677 if ('zone' not in z) or (z['zone'] is None):
Matt Spinler78498c92017-04-11 13:59:46 -0500678 sys.exit("Missing fan zone number in " + zone_yaml)
679
680 zone['num'] = z['zone']
681
682 zone['full_speed'] = z['full_speed']
683
Matthew Barth1de66622017-06-12 13:13:02 -0500684 zone['default_floor'] = z['default_floor']
685
Matthew Bartha9561842017-06-29 11:43:45 -0500686 # 'increase_delay' is optional (use 0 by default)
687 key = 'increase_delay'
688 zone[key] = z.setdefault(key, 0)
689
690 # 'decrease_interval' is optional (use 0 by default)
691 key = 'decrease_interval'
692 zone[key] = z.setdefault(key, 0)
693
Gunnar Mills67e95512017-06-02 14:35:18 -0500694 # 'cooling_profiles' is optional (use 'all' instead)
695 if ('cooling_profiles' not in z) or \
Matt Spinler78498c92017-04-11 13:59:46 -0500696 (z['cooling_profiles'] is None):
697 profiles = ["all"]
698 else:
699 profiles = z['cooling_profiles']
700
701 fans = getFansInZone(z['zone'], profiles, fan_data)
Gunnar Millsb751f322017-06-06 15:14:11 -0500702 events = getEventsInZone(z['zone'], group['zone_conditions'],
703 events_data)
Matt Spinler78498c92017-04-11 13:59:46 -0500704
705 if len(fans) == 0:
706 sys.exit("Didn't find any fans in zone " + str(zone['num']))
707
708 zone['fans'] = fans
Matthew Barthd4d0f082017-05-16 13:51:10 -0500709 zone['events'] = events
Matt Spinler78498c92017-04-11 13:59:46 -0500710 zones.append(zone)
711
712 zone_group['zones'] = zones
713 zone_groups.append(zone_group)
714
715 return zone_groups
716
717
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500718if __name__ == '__main__':
719 parser = ArgumentParser(
720 description="Phosphor fan zone definition parser")
721
722 parser.add_argument('-z', '--zone_yaml', dest='zone_yaml',
723 default="example/zones.yaml",
724 help='fan zone definitional yaml')
725 parser.add_argument('-f', '--fan_yaml', dest='fan_yaml',
726 default="example/fans.yaml",
727 help='fan definitional yaml')
Matthew Barthd4d0f082017-05-16 13:51:10 -0500728 parser.add_argument('-e', '--events_yaml', dest='events_yaml',
729 help='events to set speeds yaml')
Gunnar Millsee8a2812017-06-02 14:26:47 -0500730 parser.add_argument('-c', '--zone_conditions_yaml',
731 dest='zone_conditions_yaml',
732 help='conditions to determine zone yaml')
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500733 parser.add_argument('-o', '--output_dir', dest='output_dir',
734 default=".",
735 help='output directory')
736 args = parser.parse_args()
737
738 if not args.zone_yaml or not args.fan_yaml:
739 parser.print_usage()
740 sys.exit(-1)
741
742 with open(args.zone_yaml, 'r') as zone_input:
743 zone_data = yaml.safe_load(zone_input) or {}
744
745 with open(args.fan_yaml, 'r') as fan_input:
746 fan_data = yaml.safe_load(fan_input) or {}
747
Matthew Barthd4d0f082017-05-16 13:51:10 -0500748 events_data = {}
749 if args.events_yaml:
750 with open(args.events_yaml, 'r') as events_input:
751 events_data = yaml.safe_load(events_input) or {}
752
Gunnar Millsee8a2812017-06-02 14:26:47 -0500753 zone_conditions_data = {}
754 if args.zone_conditions_yaml:
755 with open(args.zone_conditions_yaml, 'r') as zone_conditions_input:
756 zone_conditions_data = yaml.safe_load(zone_conditions_input) or {}
757
Matt Spinleree7f6422017-05-09 11:03:14 -0500758 zone_config = buildZoneData(zone_data.get('zone_configuration', {}),
Gunnar Millsee8a2812017-06-02 14:26:47 -0500759 fan_data, events_data, zone_conditions_data)
Matt Spinleree7f6422017-05-09 11:03:14 -0500760
761 manager_config = zone_data.get('manager_configuration', {})
762
763 if manager_config.get('power_on_delay') is None:
764 manager_config['power_on_delay'] = 0
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500765
766 output_file = os.path.join(args.output_dir, "fan_zone_defs.cpp")
767 with open(output_file, 'w') as output:
Matt Spinleree7f6422017-05-09 11:03:14 -0500768 output.write(Template(tmpl).render(zones=zone_config,
769 mgr_data=manager_config))