blob: e458ba784c6de46fb225b1c60a604aa850d1d602 [file] [log] [blame]
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001/**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "config_file_parser.hpp"
18
19#include "config_file_parser_error.hpp"
Bob Kingf617f892020-03-30 19:03:35 +080020#include "i2c_interface.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050021#include "pmbus_utils.hpp"
22
23#include <exception>
24#include <fstream>
25#include <optional>
26#include <utility>
27
28using json = nlohmann::json;
29
30namespace phosphor::power::regulators::config_file_parser
31{
32
33std::tuple<std::vector<std::unique_ptr<Rule>>,
34 std::vector<std::unique_ptr<Chassis>>>
35 parse(const std::filesystem::path& pathName)
36{
37 try
38 {
39 // Use standard JSON parser to create tree of JSON elements
40 std::ifstream file{pathName};
41 json rootElement = json::parse(file);
42
43 // Parse tree of JSON elements and return corresponding C++ objects
44 return internal::parseRoot(rootElement);
45 }
46 catch (const std::exception& e)
47 {
48 throw ConfigFileParserError{pathName, e.what()};
49 }
50}
51
52namespace internal
53{
54
55std::unique_ptr<Action> parseAction(const json& element)
56{
57 verifyIsObject(element);
58 unsigned int propertyCount{0};
59
60 // Optional comments property; value not stored
61 if (element.contains("comments"))
62 {
63 ++propertyCount;
64 }
65
66 // Required action type property; there must be exactly one specified
67 std::unique_ptr<Action> action{};
68 if (element.contains("and"))
69 {
Bob King3a787542020-04-14 13:45:01 +080070 action = parseAnd(element["and"]);
71 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050072 }
73 else if (element.contains("compare_presence"))
74 {
75 // TODO: Not implemented yet
76 // action = parseComparePresence(element["compare_presence"]);
77 // ++propertyCount;
78 }
79 else if (element.contains("compare_vpd"))
80 {
81 // TODO: Not implemented yet
82 // action = parseCompareVPD(element["compare_vpd"]);
83 // ++propertyCount;
84 }
85 else if (element.contains("i2c_compare_bit"))
86 {
Bob Kingf09bfe02020-04-13 17:21:15 +080087 action = parseI2CCompareBit(element["i2c_compare_bit"]);
88 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050089 }
90 else if (element.contains("i2c_compare_byte"))
91 {
Bob Kingf09bfe02020-04-13 17:21:15 +080092 action = parseI2CCompareByte(element["i2c_compare_byte"]);
93 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050094 }
95 else if (element.contains("i2c_compare_bytes"))
96 {
Bob Kingf09bfe02020-04-13 17:21:15 +080097 action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
98 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050099 }
100 else if (element.contains("i2c_write_bit"))
101 {
Bob Kingf617f892020-03-30 19:03:35 +0800102 action = parseI2CWriteBit(element["i2c_write_bit"]);
103 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500104 }
105 else if (element.contains("i2c_write_byte"))
106 {
Bob King87ff9d72020-03-31 14:02:55 +0800107 action = parseI2CWriteByte(element["i2c_write_byte"]);
108 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500109 }
110 else if (element.contains("i2c_write_bytes"))
111 {
Bob Kingbafcb862020-03-31 16:39:00 +0800112 action = parseI2CWriteBytes(element["i2c_write_bytes"]);
113 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500114 }
115 else if (element.contains("if"))
116 {
117 // TODO: Not implemented yet
118 // action = parseIf(element["if"]);
119 // ++propertyCount;
120 }
121 else if (element.contains("not"))
122 {
123 // TODO: Not implemented yet
124 // action = parseNot(element["not"]);
125 // ++propertyCount;
126 }
127 else if (element.contains("or"))
128 {
129 // TODO: Not implemented yet
130 // action = parseOr(element["or"]);
131 // ++propertyCount;
132 }
133 else if (element.contains("pmbus_read_sensor"))
134 {
135 // TODO: Not implemented yet
136 // action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
137 // ++propertyCount;
138 }
139 else if (element.contains("pmbus_write_vout_command"))
140 {
141 action =
142 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
143 ++propertyCount;
144 }
145 else if (element.contains("run_rule"))
146 {
Bob King315b0b62020-04-03 21:47:58 +0800147 action = parseRunRule(element["run_rule"]);
148 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500149 }
150 else if (element.contains("set_device"))
151 {
152 // TODO: Not implemented yet
153 // action = parseSetDevice(element["set_device"]);
154 // ++propertyCount;
155 }
156 else
157 {
158 throw std::invalid_argument{"Required action type property missing"};
159 }
160
161 // Verify no invalid properties exist
162 verifyPropertyCount(element, propertyCount);
163
164 return action;
165}
166
167std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
168{
169 verifyIsArray(element);
170 std::vector<std::unique_ptr<Action>> actions;
171 for (auto& actionElement : element)
172 {
173 actions.emplace_back(parseAction(actionElement));
174 }
175 return actions;
176}
177
Bob King3a787542020-04-14 13:45:01 +0800178std::unique_ptr<AndAction> parseAnd(const json& element)
179{
180 verifyIsArray(element);
181
182 // Verify if array size less than 2
183 if (element.size() < 2)
184 {
185 throw std::invalid_argument{"Array must contain two or more actions"};
186 }
187 // Array of two or more actions
188 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
189
190 return std::make_unique<AndAction>(std::move(actions));
191}
192
Bob King0e701132020-04-03 21:50:31 +0800193std::unique_ptr<Chassis> parseChassis(const json& element)
194{
195 verifyIsObject(element);
196 unsigned int propertyCount{0};
197
198 // Optional comments property; value not stored
199 if (element.contains("comments"))
200 {
201 ++propertyCount;
202 }
203
204 // Required number property
205 const json& numberElement = getRequiredProperty(element, "number");
206 unsigned int number = parseUnsignedInteger(numberElement);
207 if (number < 1)
208 {
209 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
210 }
211 ++propertyCount;
212
213 // Optional devices property
214 std::vector<std::unique_ptr<Device>> devices{};
215 auto devicesIt = element.find("devices");
216 if (devicesIt != element.end())
217 {
218 devices = parseDeviceArray(*devicesIt);
219 ++propertyCount;
220 }
221
222 // Verify no invalid properties exist
223 verifyPropertyCount(element, propertyCount);
224
225 return std::make_unique<Chassis>(number, std::move(devices));
226}
227
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500228std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
229{
230 verifyIsArray(element);
231 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800232 for (auto& chassisElement : element)
233 {
234 chassis.emplace_back(parseChassis(chassisElement));
235 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500236 return chassis;
237}
238
Bob King33e7eaa2020-04-01 18:09:34 +0800239std::unique_ptr<Configuration> parseConfiguration(const json& element)
240{
241 verifyIsObject(element);
242 unsigned int propertyCount{0};
243
244 // Optional comments property; value not stored
245 if (element.contains("comments"))
246 {
247 ++propertyCount;
248 }
249
250 // Optional volts property
251 std::optional<double> volts{};
252 auto voltsIt = element.find("volts");
253 if (voltsIt != element.end())
254 {
255 volts = parseDouble(*voltsIt);
256 ++propertyCount;
257 }
258
259 // Required rule_id or actions property
260 std::vector<std::unique_ptr<Action>> actions{};
261 actions = parseRuleIDOrActionsProperty(element);
262 ++propertyCount;
263
264 // Verify no invalid properties exist
265 verifyPropertyCount(element, propertyCount);
266
267 return std::make_unique<Configuration>(volts, std::move(actions));
268}
269
Bob King9c36c5f2020-04-06 11:34:09 +0800270std::unique_ptr<Device> parseDevice(const json& element)
271{
272 verifyIsObject(element);
273 unsigned int propertyCount{0};
274
275 // Optional comments property; value not stored
276 if (element.contains("comments"))
277 {
278 ++propertyCount;
279 }
280
281 // Required id property
282 const json& idElement = getRequiredProperty(element, "id");
283 std::string id = parseString(idElement);
284 ++propertyCount;
285
286 // Required is_regulator property
287 const json& isRegulatorElement =
288 getRequiredProperty(element, "is_regulator");
289 bool isRegulator = parseBoolean(isRegulatorElement);
290 ++propertyCount;
291
292 // Required fru property
293 const json& fruElement = getRequiredProperty(element, "fru");
294 std::string fru = parseString(fruElement);
295 ++propertyCount;
296
297 // Required i2c_interface property
298 const json& i2cInterfaceElement =
299 getRequiredProperty(element, "i2c_interface");
300 std::unique_ptr<i2c::I2CInterface> i2cInterface =
301 parseI2CInterface(i2cInterfaceElement);
302 ++propertyCount;
303
304 // Optional presence_detection property
305 // TODO: Not implemented yet
306 std::unique_ptr<PresenceDetection> presenceDetection{};
307 // auto presenceDetectionIt = element.find("presence_detection");
308 // if (presenceDetectionIt != element.end())
309 // {
310 // presenceDetection = parsePresenceDetection(*presenceDetectionIt);
311 // ++propertyCount;
312 // }
313
314 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800315 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800316 auto configurationIt = element.find("configuration");
317 if (configurationIt != element.end())
318 {
319 configuration = parseConfiguration(*configurationIt);
320 ++propertyCount;
321 }
Bob King9c36c5f2020-04-06 11:34:09 +0800322
323 // Optional rails property
324 std::vector<std::unique_ptr<Rail>> rails{};
325 auto railsIt = element.find("rails");
326 if (railsIt != element.end())
327 {
328 if (!isRegulator)
329 {
330 throw std::invalid_argument{
331 "Invalid rails property when is_regulator is false"};
332 }
333 rails = parseRailArray(*railsIt);
334 ++propertyCount;
335 }
336
337 // Verify no invalid properties exist
338 verifyPropertyCount(element, propertyCount);
339
340 return std::make_unique<Device>(id, isRegulator, fru,
341 std::move(i2cInterface),
342 std::move(presenceDetection),
343 std::move(configuration), std::move(rails));
344}
345
Bob King0e701132020-04-03 21:50:31 +0800346std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
347{
348 verifyIsArray(element);
349 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800350 for (auto& deviceElement : element)
351 {
352 devices.emplace_back(parseDevice(deviceElement));
353 }
Bob King0e701132020-04-03 21:50:31 +0800354 return devices;
355}
356
Bob Kingbafcb862020-03-31 16:39:00 +0800357std::vector<uint8_t> parseHexByteArray(const json& element)
358{
359 verifyIsArray(element);
360 std::vector<uint8_t> values;
361 for (auto& valueElement : element)
362 {
363 values.emplace_back(parseHexByte(valueElement));
364 }
365 return values;
366}
367
Bob Kingf09bfe02020-04-13 17:21:15 +0800368std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
369{
370 verifyIsObject(element);
371 unsigned int propertyCount{0};
372
373 // Required register property
374 const json& regElement = getRequiredProperty(element, "register");
375 uint8_t reg = parseHexByte(regElement);
376 ++propertyCount;
377
378 // Required position property
379 const json& positionElement = getRequiredProperty(element, "position");
380 uint8_t position = parseBitPosition(positionElement);
381 ++propertyCount;
382
383 // Required value property
384 const json& valueElement = getRequiredProperty(element, "value");
385 uint8_t value = parseBitValue(valueElement);
386 ++propertyCount;
387
388 // Verify no invalid properties exist
389 verifyPropertyCount(element, propertyCount);
390
391 return std::make_unique<I2CCompareBitAction>(reg, position, value);
392}
393
394std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
395{
396 verifyIsObject(element);
397 unsigned int propertyCount{0};
398
399 // Required register property
400 const json& regElement = getRequiredProperty(element, "register");
401 uint8_t reg = parseHexByte(regElement);
402 ++propertyCount;
403
404 // Required value property
405 const json& valueElement = getRequiredProperty(element, "value");
406 uint8_t value = parseHexByte(valueElement);
407 ++propertyCount;
408
409 // Optional mask property
410 uint8_t mask = 0xff;
411 auto maskIt = element.find("mask");
412 if (maskIt != element.end())
413 {
414 mask = parseHexByte(*maskIt);
415 ++propertyCount;
416 }
417
418 // Verify no invalid properties exist
419 verifyPropertyCount(element, propertyCount);
420
421 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
422}
423
424std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
425{
426 verifyIsObject(element);
427 unsigned int propertyCount{0};
428
429 // Required register property
430 const json& regElement = getRequiredProperty(element, "register");
431 uint8_t reg = parseHexByte(regElement);
432 ++propertyCount;
433
434 // Required values property
435 const json& valueElement = getRequiredProperty(element, "values");
436 std::vector<uint8_t> values = parseHexByteArray(valueElement);
437 ++propertyCount;
438
439 // Optional masks property
440 std::vector<uint8_t> masks{};
441 auto masksIt = element.find("masks");
442 if (masksIt != element.end())
443 {
444 masks = parseHexByteArray(*masksIt);
445 ++propertyCount;
446 }
447
448 // Verify masks array (if specified) was same size as values array
449 if ((!masks.empty()) && (masks.size() != values.size()))
450 {
451 throw std::invalid_argument{"Invalid number of elements in masks"};
452 }
453
454 // Verify no invalid properties exist
455 verifyPropertyCount(element, propertyCount);
456
457 if (masks.empty())
458 {
459 return std::make_unique<I2CCompareBytesAction>(reg, values);
460 }
461 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
462}
463
Bob King9c36c5f2020-04-06 11:34:09 +0800464std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
465{
466 verifyIsObject(element);
467 unsigned int propertyCount{0};
468
469 // Required bus property
470 const json& busElement = getRequiredProperty(element, "bus");
471 uint8_t bus = parseUint8(busElement);
472 ++propertyCount;
473
474 // Required address property
475 const json& addressElement = getRequiredProperty(element, "address");
476 uint8_t address = parseHexByte(addressElement);
477 ++propertyCount;
478
479 verifyPropertyCount(element, propertyCount);
480 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
481}
482
Bob Kingf617f892020-03-30 19:03:35 +0800483std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
484{
485 verifyIsObject(element);
486 unsigned int propertyCount{0};
487
488 // Required register property
489 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800490 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800491 ++propertyCount;
492
493 // Required position property
494 const json& positionElement = getRequiredProperty(element, "position");
495 uint8_t position = parseBitPosition(positionElement);
496 ++propertyCount;
497
498 // Required value property
499 const json& valueElement = getRequiredProperty(element, "value");
500 uint8_t value = parseBitValue(valueElement);
501 ++propertyCount;
502
503 // Verify no invalid properties exist
504 verifyPropertyCount(element, propertyCount);
505
506 return std::make_unique<I2CWriteBitAction>(reg, position, value);
507}
508
Bob King87ff9d72020-03-31 14:02:55 +0800509std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
510{
511 verifyIsObject(element);
512 unsigned int propertyCount{0};
513
514 // Required register property
515 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800516 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800517 ++propertyCount;
518
519 // Required value property
520 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800521 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800522 ++propertyCount;
523
524 // Optional mask property
525 uint8_t mask = 0xff;
526 auto maskIt = element.find("mask");
527 if (maskIt != element.end())
528 {
Bob Kingbafcb862020-03-31 16:39:00 +0800529 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800530 ++propertyCount;
531 }
532
533 // Verify no invalid properties exist
534 verifyPropertyCount(element, propertyCount);
535
536 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
537}
538
Bob Kingbafcb862020-03-31 16:39:00 +0800539std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
540{
541 verifyIsObject(element);
542 unsigned int propertyCount{0};
543
544 // Required register property
545 const json& regElement = getRequiredProperty(element, "register");
546 uint8_t reg = parseHexByte(regElement);
547 ++propertyCount;
548
549 // Required values property
550 const json& valueElement = getRequiredProperty(element, "values");
551 std::vector<uint8_t> values = parseHexByteArray(valueElement);
552 ++propertyCount;
553
554 // Optional masks property
555 std::vector<uint8_t> masks{};
556 auto masksIt = element.find("masks");
557 if (masksIt != element.end())
558 {
559 masks = parseHexByteArray(*masksIt);
560 ++propertyCount;
561 }
562
563 // Verify masks array (if specified) was same size as values array
564 if ((!masks.empty()) && (masks.size() != values.size()))
565 {
566 throw std::invalid_argument{"Invalid number of elements in masks"};
567 }
568
569 // Verify no invalid properties exist
570 verifyPropertyCount(element, propertyCount);
571
572 if (masks.empty())
573 {
574 return std::make_unique<I2CWriteBytesAction>(reg, values);
575 }
576 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
577}
578
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500579std::unique_ptr<PMBusWriteVoutCommandAction>
580 parsePMBusWriteVoutCommand(const json& element)
581{
582 verifyIsObject(element);
583 unsigned int propertyCount{0};
584
585 // Optional volts property
586 std::optional<double> volts{};
587 auto voltsIt = element.find("volts");
588 if (voltsIt != element.end())
589 {
590 volts = parseDouble(*voltsIt);
591 ++propertyCount;
592 }
593
594 // Required format property
595 const json& formatElement = getRequiredProperty(element, "format");
596 std::string formatString = parseString(formatElement);
597 if (formatString != "linear")
598 {
599 throw std::invalid_argument{"Invalid format value: " + formatString};
600 }
601 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
602 ++propertyCount;
603
604 // Optional exponent property
605 std::optional<int8_t> exponent{};
606 auto exponentIt = element.find("exponent");
607 if (exponentIt != element.end())
608 {
609 exponent = parseInt8(*exponentIt);
610 ++propertyCount;
611 }
612
613 // Optional is_verified property
614 bool isVerified = false;
615 auto isVerifiedIt = element.find("is_verified");
616 if (isVerifiedIt != element.end())
617 {
618 isVerified = parseBoolean(*isVerifiedIt);
619 ++propertyCount;
620 }
621
622 // Verify no invalid properties exist
623 verifyPropertyCount(element, propertyCount);
624
625 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
626 exponent, isVerified);
627}
628
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800629std::unique_ptr<Rail> parseRail(const json& element)
630{
631 verifyIsObject(element);
632 unsigned int propertyCount{0};
633
634 // Optional comments property; value not stored
635 if (element.contains("comments"))
636 {
637 ++propertyCount;
638 }
639
640 // Required id property
641 const json& idElement = getRequiredProperty(element, "id");
642 std::string id = parseString(idElement);
643 ++propertyCount;
644
645 // Optional configuration property
646 std::unique_ptr<Configuration> configuration{};
647 auto configurationIt = element.find("configuration");
648 if (configurationIt != element.end())
649 {
650 configuration = parseConfiguration(*configurationIt);
651 ++propertyCount;
652 }
653
654 // Optional sensor_monitoring property
655 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
656 auto sensorMonitoringIt = element.find("sensor_monitoring");
657 if (sensorMonitoringIt != element.end())
658 {
659 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
660 ++propertyCount;
661 }
662
663 // Verify no invalid properties exist
664 verifyPropertyCount(element, propertyCount);
665
666 return std::make_unique<Rail>(id, std::move(configuration),
667 std::move(sensorMonitoring));
668}
669
Bob King9c36c5f2020-04-06 11:34:09 +0800670std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
671{
672 verifyIsArray(element);
673 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800674 for (auto& railElement : element)
675 {
676 rails.emplace_back(parseRail(railElement));
677 }
Bob King9c36c5f2020-04-06 11:34:09 +0800678 return rails;
679}
680
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500681std::tuple<std::vector<std::unique_ptr<Rule>>,
682 std::vector<std::unique_ptr<Chassis>>>
683 parseRoot(const json& element)
684{
685 verifyIsObject(element);
686 unsigned int propertyCount{0};
687
688 // Optional comments property; value not stored
689 if (element.contains("comments"))
690 {
691 ++propertyCount;
692 }
693
694 // Optional rules property
695 std::vector<std::unique_ptr<Rule>> rules{};
696 auto rulesIt = element.find("rules");
697 if (rulesIt != element.end())
698 {
699 rules = parseRuleArray(*rulesIt);
700 ++propertyCount;
701 }
702
703 // Required chassis property
704 const json& chassisElement = getRequiredProperty(element, "chassis");
705 std::vector<std::unique_ptr<Chassis>> chassis =
706 parseChassisArray(chassisElement);
707 ++propertyCount;
708
709 // Verify no invalid properties exist
710 verifyPropertyCount(element, propertyCount);
711
712 return std::make_tuple(std::move(rules), std::move(chassis));
713}
714
715std::unique_ptr<Rule> parseRule(const json& element)
716{
717 verifyIsObject(element);
718 unsigned int propertyCount{0};
719
720 // Optional comments property; value not stored
721 if (element.contains("comments"))
722 {
723 ++propertyCount;
724 }
725
726 // Required id property
727 const json& idElement = getRequiredProperty(element, "id");
728 std::string id = parseString(idElement);
729 ++propertyCount;
730
731 // Required actions property
732 const json& actionsElement = getRequiredProperty(element, "actions");
733 std::vector<std::unique_ptr<Action>> actions =
734 parseActionArray(actionsElement);
735 ++propertyCount;
736
737 // Verify no invalid properties exist
738 verifyPropertyCount(element, propertyCount);
739
740 return std::make_unique<Rule>(id, std::move(actions));
741}
742
743std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
744{
745 verifyIsArray(element);
746 std::vector<std::unique_ptr<Rule>> rules;
747 for (auto& ruleElement : element)
748 {
749 rules.emplace_back(parseRule(ruleElement));
750 }
751 return rules;
752}
753
Bob King33e7eaa2020-04-01 18:09:34 +0800754std::vector<std::unique_ptr<Action>>
755 parseRuleIDOrActionsProperty(const json& element)
756{
757 verifyIsObject(element);
758 // Required rule_id or actions property
759 std::vector<std::unique_ptr<Action>> actions{};
760 auto ruleIDIt = element.find("rule_id");
761 auto actionsIt = element.find("actions");
762 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
763 {
764 std::string ruleID = parseString(*ruleIDIt);
765 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
766 }
767 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
768 {
769 actions = parseActionArray(*actionsIt);
770 }
771 else
772 {
773 throw std::invalid_argument{"Invalid property combination: Must "
774 "contain either rule_id or actions"};
775 }
776
777 return actions;
778}
779
Bob King315b0b62020-04-03 21:47:58 +0800780std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
781{
782 // String ruleID
783 std::string ruleID = parseString(element);
784
785 return std::make_unique<RunRuleAction>(ruleID);
786}
787
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800788std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
789{
790 verifyIsObject(element);
791 unsigned int propertyCount{0};
792
793 // Optional comments property; value not stored
794 if (element.contains("comments"))
795 {
796 ++propertyCount;
797 }
798
799 // Required rule_id or actions property
800 std::vector<std::unique_ptr<Action>> actions{};
801 actions = parseRuleIDOrActionsProperty(element);
802 ++propertyCount;
803
804 // Verify no invalid properties exist
805 verifyPropertyCount(element, propertyCount);
806
807 return std::make_unique<SensorMonitoring>(std::move(actions));
808}
809
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500810} // namespace internal
811
812} // namespace phosphor::power::regulators::config_file_parser