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