blob: 64b61217bda1e1f77585a29af35397aef5eff662 [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 {
70 // TODO: Not implemented yet
71 // action = parseAnd(element["and"]);
72 // ++propertyCount;
73 }
74 else if (element.contains("compare_presence"))
75 {
76 // TODO: Not implemented yet
77 // action = parseComparePresence(element["compare_presence"]);
78 // ++propertyCount;
79 }
80 else if (element.contains("compare_vpd"))
81 {
82 // TODO: Not implemented yet
83 // action = parseCompareVPD(element["compare_vpd"]);
84 // ++propertyCount;
85 }
86 else if (element.contains("i2c_compare_bit"))
87 {
Bob Kingf09bfe02020-04-13 17:21:15 +080088 action = parseI2CCompareBit(element["i2c_compare_bit"]);
89 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050090 }
91 else if (element.contains("i2c_compare_byte"))
92 {
Bob Kingf09bfe02020-04-13 17:21:15 +080093 action = parseI2CCompareByte(element["i2c_compare_byte"]);
94 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050095 }
96 else if (element.contains("i2c_compare_bytes"))
97 {
Bob Kingf09bfe02020-04-13 17:21:15 +080098 action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
99 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500100 }
101 else if (element.contains("i2c_write_bit"))
102 {
Bob Kingf617f892020-03-30 19:03:35 +0800103 action = parseI2CWriteBit(element["i2c_write_bit"]);
104 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500105 }
106 else if (element.contains("i2c_write_byte"))
107 {
Bob King87ff9d72020-03-31 14:02:55 +0800108 action = parseI2CWriteByte(element["i2c_write_byte"]);
109 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500110 }
111 else if (element.contains("i2c_write_bytes"))
112 {
Bob Kingbafcb862020-03-31 16:39:00 +0800113 action = parseI2CWriteBytes(element["i2c_write_bytes"]);
114 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500115 }
116 else if (element.contains("if"))
117 {
118 // TODO: Not implemented yet
119 // action = parseIf(element["if"]);
120 // ++propertyCount;
121 }
122 else if (element.contains("not"))
123 {
124 // TODO: Not implemented yet
125 // action = parseNot(element["not"]);
126 // ++propertyCount;
127 }
128 else if (element.contains("or"))
129 {
130 // TODO: Not implemented yet
131 // action = parseOr(element["or"]);
132 // ++propertyCount;
133 }
134 else if (element.contains("pmbus_read_sensor"))
135 {
136 // TODO: Not implemented yet
137 // action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
138 // ++propertyCount;
139 }
140 else if (element.contains("pmbus_write_vout_command"))
141 {
142 action =
143 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
144 ++propertyCount;
145 }
146 else if (element.contains("run_rule"))
147 {
Bob King315b0b62020-04-03 21:47:58 +0800148 action = parseRunRule(element["run_rule"]);
149 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500150 }
151 else if (element.contains("set_device"))
152 {
153 // TODO: Not implemented yet
154 // action = parseSetDevice(element["set_device"]);
155 // ++propertyCount;
156 }
157 else
158 {
159 throw std::invalid_argument{"Required action type property missing"};
160 }
161
162 // Verify no invalid properties exist
163 verifyPropertyCount(element, propertyCount);
164
165 return action;
166}
167
168std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
169{
170 verifyIsArray(element);
171 std::vector<std::unique_ptr<Action>> actions;
172 for (auto& actionElement : element)
173 {
174 actions.emplace_back(parseAction(actionElement));
175 }
176 return actions;
177}
178
Bob King0e701132020-04-03 21:50:31 +0800179std::unique_ptr<Chassis> parseChassis(const json& element)
180{
181 verifyIsObject(element);
182 unsigned int propertyCount{0};
183
184 // Optional comments property; value not stored
185 if (element.contains("comments"))
186 {
187 ++propertyCount;
188 }
189
190 // Required number property
191 const json& numberElement = getRequiredProperty(element, "number");
192 unsigned int number = parseUnsignedInteger(numberElement);
193 if (number < 1)
194 {
195 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
196 }
197 ++propertyCount;
198
199 // Optional devices property
200 std::vector<std::unique_ptr<Device>> devices{};
201 auto devicesIt = element.find("devices");
202 if (devicesIt != element.end())
203 {
204 devices = parseDeviceArray(*devicesIt);
205 ++propertyCount;
206 }
207
208 // Verify no invalid properties exist
209 verifyPropertyCount(element, propertyCount);
210
211 return std::make_unique<Chassis>(number, std::move(devices));
212}
213
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500214std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
215{
216 verifyIsArray(element);
217 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800218 for (auto& chassisElement : element)
219 {
220 chassis.emplace_back(parseChassis(chassisElement));
221 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500222 return chassis;
223}
224
Bob King33e7eaa2020-04-01 18:09:34 +0800225std::unique_ptr<Configuration> parseConfiguration(const json& element)
226{
227 verifyIsObject(element);
228 unsigned int propertyCount{0};
229
230 // Optional comments property; value not stored
231 if (element.contains("comments"))
232 {
233 ++propertyCount;
234 }
235
236 // Optional volts property
237 std::optional<double> volts{};
238 auto voltsIt = element.find("volts");
239 if (voltsIt != element.end())
240 {
241 volts = parseDouble(*voltsIt);
242 ++propertyCount;
243 }
244
245 // Required rule_id or actions property
246 std::vector<std::unique_ptr<Action>> actions{};
247 actions = parseRuleIDOrActionsProperty(element);
248 ++propertyCount;
249
250 // Verify no invalid properties exist
251 verifyPropertyCount(element, propertyCount);
252
253 return std::make_unique<Configuration>(volts, std::move(actions));
254}
255
Bob King9c36c5f2020-04-06 11:34:09 +0800256std::unique_ptr<Device> parseDevice(const json& element)
257{
258 verifyIsObject(element);
259 unsigned int propertyCount{0};
260
261 // Optional comments property; value not stored
262 if (element.contains("comments"))
263 {
264 ++propertyCount;
265 }
266
267 // Required id property
268 const json& idElement = getRequiredProperty(element, "id");
269 std::string id = parseString(idElement);
270 ++propertyCount;
271
272 // Required is_regulator property
273 const json& isRegulatorElement =
274 getRequiredProperty(element, "is_regulator");
275 bool isRegulator = parseBoolean(isRegulatorElement);
276 ++propertyCount;
277
278 // Required fru property
279 const json& fruElement = getRequiredProperty(element, "fru");
280 std::string fru = parseString(fruElement);
281 ++propertyCount;
282
283 // Required i2c_interface property
284 const json& i2cInterfaceElement =
285 getRequiredProperty(element, "i2c_interface");
286 std::unique_ptr<i2c::I2CInterface> i2cInterface =
287 parseI2CInterface(i2cInterfaceElement);
288 ++propertyCount;
289
290 // Optional presence_detection property
291 // TODO: Not implemented yet
292 std::unique_ptr<PresenceDetection> presenceDetection{};
293 // auto presenceDetectionIt = element.find("presence_detection");
294 // if (presenceDetectionIt != element.end())
295 // {
296 // presenceDetection = parsePresenceDetection(*presenceDetectionIt);
297 // ++propertyCount;
298 // }
299
300 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800301 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800302 auto configurationIt = element.find("configuration");
303 if (configurationIt != element.end())
304 {
305 configuration = parseConfiguration(*configurationIt);
306 ++propertyCount;
307 }
Bob King9c36c5f2020-04-06 11:34:09 +0800308
309 // Optional rails property
310 std::vector<std::unique_ptr<Rail>> rails{};
311 auto railsIt = element.find("rails");
312 if (railsIt != element.end())
313 {
314 if (!isRegulator)
315 {
316 throw std::invalid_argument{
317 "Invalid rails property when is_regulator is false"};
318 }
319 rails = parseRailArray(*railsIt);
320 ++propertyCount;
321 }
322
323 // Verify no invalid properties exist
324 verifyPropertyCount(element, propertyCount);
325
326 return std::make_unique<Device>(id, isRegulator, fru,
327 std::move(i2cInterface),
328 std::move(presenceDetection),
329 std::move(configuration), std::move(rails));
330}
331
Bob King0e701132020-04-03 21:50:31 +0800332std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
333{
334 verifyIsArray(element);
335 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800336 for (auto& deviceElement : element)
337 {
338 devices.emplace_back(parseDevice(deviceElement));
339 }
Bob King0e701132020-04-03 21:50:31 +0800340 return devices;
341}
342
Bob Kingbafcb862020-03-31 16:39:00 +0800343std::vector<uint8_t> parseHexByteArray(const json& element)
344{
345 verifyIsArray(element);
346 std::vector<uint8_t> values;
347 for (auto& valueElement : element)
348 {
349 values.emplace_back(parseHexByte(valueElement));
350 }
351 return values;
352}
353
Bob Kingf09bfe02020-04-13 17:21:15 +0800354std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
355{
356 verifyIsObject(element);
357 unsigned int propertyCount{0};
358
359 // Required register property
360 const json& regElement = getRequiredProperty(element, "register");
361 uint8_t reg = parseHexByte(regElement);
362 ++propertyCount;
363
364 // Required position property
365 const json& positionElement = getRequiredProperty(element, "position");
366 uint8_t position = parseBitPosition(positionElement);
367 ++propertyCount;
368
369 // Required value property
370 const json& valueElement = getRequiredProperty(element, "value");
371 uint8_t value = parseBitValue(valueElement);
372 ++propertyCount;
373
374 // Verify no invalid properties exist
375 verifyPropertyCount(element, propertyCount);
376
377 return std::make_unique<I2CCompareBitAction>(reg, position, value);
378}
379
380std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
381{
382 verifyIsObject(element);
383 unsigned int propertyCount{0};
384
385 // Required register property
386 const json& regElement = getRequiredProperty(element, "register");
387 uint8_t reg = parseHexByte(regElement);
388 ++propertyCount;
389
390 // Required value property
391 const json& valueElement = getRequiredProperty(element, "value");
392 uint8_t value = parseHexByte(valueElement);
393 ++propertyCount;
394
395 // Optional mask property
396 uint8_t mask = 0xff;
397 auto maskIt = element.find("mask");
398 if (maskIt != element.end())
399 {
400 mask = parseHexByte(*maskIt);
401 ++propertyCount;
402 }
403
404 // Verify no invalid properties exist
405 verifyPropertyCount(element, propertyCount);
406
407 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
408}
409
410std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
411{
412 verifyIsObject(element);
413 unsigned int propertyCount{0};
414
415 // Required register property
416 const json& regElement = getRequiredProperty(element, "register");
417 uint8_t reg = parseHexByte(regElement);
418 ++propertyCount;
419
420 // Required values property
421 const json& valueElement = getRequiredProperty(element, "values");
422 std::vector<uint8_t> values = parseHexByteArray(valueElement);
423 ++propertyCount;
424
425 // Optional masks property
426 std::vector<uint8_t> masks{};
427 auto masksIt = element.find("masks");
428 if (masksIt != element.end())
429 {
430 masks = parseHexByteArray(*masksIt);
431 ++propertyCount;
432 }
433
434 // Verify masks array (if specified) was same size as values array
435 if ((!masks.empty()) && (masks.size() != values.size()))
436 {
437 throw std::invalid_argument{"Invalid number of elements in masks"};
438 }
439
440 // Verify no invalid properties exist
441 verifyPropertyCount(element, propertyCount);
442
443 if (masks.empty())
444 {
445 return std::make_unique<I2CCompareBytesAction>(reg, values);
446 }
447 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
448}
449
Bob King9c36c5f2020-04-06 11:34:09 +0800450std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
451{
452 verifyIsObject(element);
453 unsigned int propertyCount{0};
454
455 // Required bus property
456 const json& busElement = getRequiredProperty(element, "bus");
457 uint8_t bus = parseUint8(busElement);
458 ++propertyCount;
459
460 // Required address property
461 const json& addressElement = getRequiredProperty(element, "address");
462 uint8_t address = parseHexByte(addressElement);
463 ++propertyCount;
464
465 verifyPropertyCount(element, propertyCount);
466 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
467}
468
Bob Kingf617f892020-03-30 19:03:35 +0800469std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
470{
471 verifyIsObject(element);
472 unsigned int propertyCount{0};
473
474 // Required register property
475 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800476 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800477 ++propertyCount;
478
479 // Required position property
480 const json& positionElement = getRequiredProperty(element, "position");
481 uint8_t position = parseBitPosition(positionElement);
482 ++propertyCount;
483
484 // Required value property
485 const json& valueElement = getRequiredProperty(element, "value");
486 uint8_t value = parseBitValue(valueElement);
487 ++propertyCount;
488
489 // Verify no invalid properties exist
490 verifyPropertyCount(element, propertyCount);
491
492 return std::make_unique<I2CWriteBitAction>(reg, position, value);
493}
494
Bob King87ff9d72020-03-31 14:02:55 +0800495std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
496{
497 verifyIsObject(element);
498 unsigned int propertyCount{0};
499
500 // Required register property
501 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800502 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800503 ++propertyCount;
504
505 // Required value property
506 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800507 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800508 ++propertyCount;
509
510 // Optional mask property
511 uint8_t mask = 0xff;
512 auto maskIt = element.find("mask");
513 if (maskIt != element.end())
514 {
Bob Kingbafcb862020-03-31 16:39:00 +0800515 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800516 ++propertyCount;
517 }
518
519 // Verify no invalid properties exist
520 verifyPropertyCount(element, propertyCount);
521
522 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
523}
524
Bob Kingbafcb862020-03-31 16:39:00 +0800525std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
526{
527 verifyIsObject(element);
528 unsigned int propertyCount{0};
529
530 // Required register property
531 const json& regElement = getRequiredProperty(element, "register");
532 uint8_t reg = parseHexByte(regElement);
533 ++propertyCount;
534
535 // Required values property
536 const json& valueElement = getRequiredProperty(element, "values");
537 std::vector<uint8_t> values = parseHexByteArray(valueElement);
538 ++propertyCount;
539
540 // Optional masks property
541 std::vector<uint8_t> masks{};
542 auto masksIt = element.find("masks");
543 if (masksIt != element.end())
544 {
545 masks = parseHexByteArray(*masksIt);
546 ++propertyCount;
547 }
548
549 // Verify masks array (if specified) was same size as values array
550 if ((!masks.empty()) && (masks.size() != values.size()))
551 {
552 throw std::invalid_argument{"Invalid number of elements in masks"};
553 }
554
555 // Verify no invalid properties exist
556 verifyPropertyCount(element, propertyCount);
557
558 if (masks.empty())
559 {
560 return std::make_unique<I2CWriteBytesAction>(reg, values);
561 }
562 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
563}
564
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500565std::unique_ptr<PMBusWriteVoutCommandAction>
566 parsePMBusWriteVoutCommand(const json& element)
567{
568 verifyIsObject(element);
569 unsigned int propertyCount{0};
570
571 // Optional volts property
572 std::optional<double> volts{};
573 auto voltsIt = element.find("volts");
574 if (voltsIt != element.end())
575 {
576 volts = parseDouble(*voltsIt);
577 ++propertyCount;
578 }
579
580 // Required format property
581 const json& formatElement = getRequiredProperty(element, "format");
582 std::string formatString = parseString(formatElement);
583 if (formatString != "linear")
584 {
585 throw std::invalid_argument{"Invalid format value: " + formatString};
586 }
587 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
588 ++propertyCount;
589
590 // Optional exponent property
591 std::optional<int8_t> exponent{};
592 auto exponentIt = element.find("exponent");
593 if (exponentIt != element.end())
594 {
595 exponent = parseInt8(*exponentIt);
596 ++propertyCount;
597 }
598
599 // Optional is_verified property
600 bool isVerified = false;
601 auto isVerifiedIt = element.find("is_verified");
602 if (isVerifiedIt != element.end())
603 {
604 isVerified = parseBoolean(*isVerifiedIt);
605 ++propertyCount;
606 }
607
608 // Verify no invalid properties exist
609 verifyPropertyCount(element, propertyCount);
610
611 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
612 exponent, isVerified);
613}
614
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800615std::unique_ptr<Rail> parseRail(const json& element)
616{
617 verifyIsObject(element);
618 unsigned int propertyCount{0};
619
620 // Optional comments property; value not stored
621 if (element.contains("comments"))
622 {
623 ++propertyCount;
624 }
625
626 // Required id property
627 const json& idElement = getRequiredProperty(element, "id");
628 std::string id = parseString(idElement);
629 ++propertyCount;
630
631 // Optional configuration property
632 std::unique_ptr<Configuration> configuration{};
633 auto configurationIt = element.find("configuration");
634 if (configurationIt != element.end())
635 {
636 configuration = parseConfiguration(*configurationIt);
637 ++propertyCount;
638 }
639
640 // Optional sensor_monitoring property
641 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
642 auto sensorMonitoringIt = element.find("sensor_monitoring");
643 if (sensorMonitoringIt != element.end())
644 {
645 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
646 ++propertyCount;
647 }
648
649 // Verify no invalid properties exist
650 verifyPropertyCount(element, propertyCount);
651
652 return std::make_unique<Rail>(id, std::move(configuration),
653 std::move(sensorMonitoring));
654}
655
Bob King9c36c5f2020-04-06 11:34:09 +0800656std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
657{
658 verifyIsArray(element);
659 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800660 for (auto& railElement : element)
661 {
662 rails.emplace_back(parseRail(railElement));
663 }
Bob King9c36c5f2020-04-06 11:34:09 +0800664 return rails;
665}
666
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500667std::tuple<std::vector<std::unique_ptr<Rule>>,
668 std::vector<std::unique_ptr<Chassis>>>
669 parseRoot(const json& element)
670{
671 verifyIsObject(element);
672 unsigned int propertyCount{0};
673
674 // Optional comments property; value not stored
675 if (element.contains("comments"))
676 {
677 ++propertyCount;
678 }
679
680 // Optional rules property
681 std::vector<std::unique_ptr<Rule>> rules{};
682 auto rulesIt = element.find("rules");
683 if (rulesIt != element.end())
684 {
685 rules = parseRuleArray(*rulesIt);
686 ++propertyCount;
687 }
688
689 // Required chassis property
690 const json& chassisElement = getRequiredProperty(element, "chassis");
691 std::vector<std::unique_ptr<Chassis>> chassis =
692 parseChassisArray(chassisElement);
693 ++propertyCount;
694
695 // Verify no invalid properties exist
696 verifyPropertyCount(element, propertyCount);
697
698 return std::make_tuple(std::move(rules), std::move(chassis));
699}
700
701std::unique_ptr<Rule> parseRule(const json& element)
702{
703 verifyIsObject(element);
704 unsigned int propertyCount{0};
705
706 // Optional comments property; value not stored
707 if (element.contains("comments"))
708 {
709 ++propertyCount;
710 }
711
712 // Required id property
713 const json& idElement = getRequiredProperty(element, "id");
714 std::string id = parseString(idElement);
715 ++propertyCount;
716
717 // Required actions property
718 const json& actionsElement = getRequiredProperty(element, "actions");
719 std::vector<std::unique_ptr<Action>> actions =
720 parseActionArray(actionsElement);
721 ++propertyCount;
722
723 // Verify no invalid properties exist
724 verifyPropertyCount(element, propertyCount);
725
726 return std::make_unique<Rule>(id, std::move(actions));
727}
728
729std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
730{
731 verifyIsArray(element);
732 std::vector<std::unique_ptr<Rule>> rules;
733 for (auto& ruleElement : element)
734 {
735 rules.emplace_back(parseRule(ruleElement));
736 }
737 return rules;
738}
739
Bob King33e7eaa2020-04-01 18:09:34 +0800740std::vector<std::unique_ptr<Action>>
741 parseRuleIDOrActionsProperty(const json& element)
742{
743 verifyIsObject(element);
744 // Required rule_id or actions property
745 std::vector<std::unique_ptr<Action>> actions{};
746 auto ruleIDIt = element.find("rule_id");
747 auto actionsIt = element.find("actions");
748 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
749 {
750 std::string ruleID = parseString(*ruleIDIt);
751 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
752 }
753 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
754 {
755 actions = parseActionArray(*actionsIt);
756 }
757 else
758 {
759 throw std::invalid_argument{"Invalid property combination: Must "
760 "contain either rule_id or actions"};
761 }
762
763 return actions;
764}
765
Bob King315b0b62020-04-03 21:47:58 +0800766std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
767{
768 // String ruleID
769 std::string ruleID = parseString(element);
770
771 return std::make_unique<RunRuleAction>(ruleID);
772}
773
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800774std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
775{
776 verifyIsObject(element);
777 unsigned int propertyCount{0};
778
779 // Optional comments property; value not stored
780 if (element.contains("comments"))
781 {
782 ++propertyCount;
783 }
784
785 // Required rule_id or actions property
786 std::vector<std::unique_ptr<Action>> actions{};
787 actions = parseRuleIDOrActionsProperty(element);
788 ++propertyCount;
789
790 // Verify no invalid properties exist
791 verifyPropertyCount(element, propertyCount);
792
793 return std::make_unique<SensorMonitoring>(std::move(actions));
794}
795
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500796} // namespace internal
797
798} // namespace phosphor::power::regulators::config_file_parser