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