1 #include "event_parser.hpp" 2 3 #include <xyz/openbmc_project/Common/error.hpp> 4 5 #include <filesystem> 6 #include <fstream> 7 #include <iostream> 8 #include <set> 9 10 namespace pldm::responder::events 11 { 12 13 namespace fs = std::filesystem; 14 using InternalFailure = 15 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 16 17 const Json emptyJson{}; 18 const std::vector<Json> emptyJsonList{}; 19 const std::vector<std::string> emptyStringVec{}; 20 21 const std::set<std::string_view> supportedDbusPropertyTypes = { 22 "bool", "uint8_t", "int16_t", "uint16_t", "int32_t", 23 "uint32_t", "int64_t", "uint64_t", "double", "string"}; 24 25 StateSensorHandler::StateSensorHandler(const std::string& dirPath) 26 { 27 fs::path dir(dirPath); 28 if (!fs::exists(dir) || fs::is_empty(dir)) 29 { 30 std::cerr << "Event config directory does not exist or empty, DIR=" 31 << dirPath << "\n"; 32 return; 33 } 34 35 for (auto& file : fs::directory_iterator(dirPath)) 36 { 37 std::ifstream jsonFile(file.path()); 38 39 auto data = Json::parse(jsonFile, nullptr, false); 40 if (data.is_discarded()) 41 { 42 std::cerr << "Parsing Event state sensor JSON file failed, FILE=" 43 << file.path(); 44 continue; 45 } 46 47 auto entries = data.value("entries", emptyJsonList); 48 for (const auto& entry : entries) 49 { 50 StateSensorEntry stateSensorEntry{}; 51 stateSensorEntry.containerId = 52 static_cast<uint16_t>(entry.value("containerID", 0)); 53 stateSensorEntry.entityType = 54 static_cast<uint16_t>(entry.value("entityType", 0)); 55 stateSensorEntry.entityInstance = 56 static_cast<uint16_t>(entry.value("entityInstance", 0)); 57 stateSensorEntry.sensorOffset = 58 static_cast<uint8_t>(entry.value("sensorOffset", 0)); 59 60 pldm::utils::DBusMapping dbusInfo{}; 61 62 auto dbus = entry.value("dbus", emptyJson); 63 dbusInfo.objectPath = dbus.value("object_path", ""); 64 dbusInfo.interface = dbus.value("interface", ""); 65 dbusInfo.propertyName = dbus.value("property_name", ""); 66 dbusInfo.propertyType = dbus.value("property_type", ""); 67 if (dbusInfo.objectPath.empty() || dbusInfo.interface.empty() || 68 dbusInfo.propertyName.empty() || 69 (supportedDbusPropertyTypes.find(dbusInfo.propertyType) == 70 supportedDbusPropertyTypes.end())) 71 { 72 std::cerr << "Invalid dbus config," 73 << " OBJPATH=" << dbusInfo.objectPath << " INTERFACE=" 74 << dbusInfo.interface << " PROPERTY_NAME=" 75 << dbusInfo.propertyName 76 << " PROPERTY_TYPE=" << dbusInfo.propertyType << "\n"; 77 continue; 78 } 79 80 auto eventStates = entry.value("event_states", emptyJsonList); 81 auto propertyValues = dbus.value("property_values", emptyJsonList); 82 if ((eventStates.size() == 0) || (propertyValues.size() == 0) || 83 (eventStates.size() != propertyValues.size())) 84 { 85 std::cerr << "Invalid event state JSON config," 86 << " EVENT_STATE_SIZE=" << eventStates.size() 87 << " PROPERTY_VALUE_SIZE=" << propertyValues.size() 88 << "\n"; 89 continue; 90 } 91 92 auto eventStateMap = mapStateToDBusVal(eventStates, propertyValues, 93 dbusInfo.propertyType); 94 eventMap.emplace( 95 stateSensorEntry, 96 std::make_tuple(std::move(dbusInfo), std::move(eventStateMap))); 97 } 98 } 99 } 100 101 StateToDBusValue StateSensorHandler::mapStateToDBusVal( 102 const Json& eventStates, const Json& propertyValues, std::string_view type) 103 { 104 StateToDBusValue eventStateMap{}; 105 auto stateIt = eventStates.begin(); 106 auto propIt = propertyValues.begin(); 107 108 for (; stateIt != eventStates.end(); ++stateIt, ++propIt) 109 { 110 auto propValue = utils::jsonEntryToDbusVal(type, propIt.value()); 111 eventStateMap.emplace((*stateIt).get<uint8_t>(), std::move(propValue)); 112 } 113 114 return eventStateMap; 115 } 116 117 int StateSensorHandler::eventAction(const StateSensorEntry& entry, 118 pdr::EventState state) 119 { 120 try 121 { 122 const auto& [dbusMapping, eventStateMap] = eventMap.at(entry); 123 utils::PropertyValue propValue{}; 124 try 125 { 126 propValue = eventStateMap.at(state); 127 } 128 catch (const std::out_of_range& e) 129 { 130 std::cerr << "Invalid event state" << static_cast<unsigned>(state) 131 << '\n'; 132 return PLDM_ERROR_INVALID_DATA; 133 } 134 135 try 136 { 137 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, propValue); 138 } 139 catch (const std::exception& e) 140 { 141 std::cerr << "Error setting property, ERROR=" << e.what() 142 << " PROPERTY=" << dbusMapping.propertyName 143 << " INTERFACE=" << dbusMapping.interface << " PATH=" 144 << dbusMapping.objectPath << "\n"; 145 return PLDM_ERROR; 146 } 147 } 148 catch (const std::out_of_range& e) 149 { 150 // There is no BMC action for this PLDM event 151 return PLDM_SUCCESS; 152 } 153 return PLDM_SUCCESS; 154 } 155 156 } // namespace pldm::responder::events