ups: watch for property changes
Monitor for any changes to the properties the chassis manger is
interested in with the UPower interface.
Tested:
- Changed the properties via busctl after the chassis manager was
running and verified the chassis power status was updated correctly
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: I13f23d33581c2339506f9c4739ce36bf07aef46e
diff --git a/chassis_state_manager.cpp b/chassis_state_manager.cpp
index ae998ef..38b7c94 100644
--- a/chassis_state_manager.cpp
+++ b/chassis_state_manager.cpp
@@ -41,6 +41,11 @@
constexpr auto ACTIVE_STATE = "active";
constexpr auto ACTIVATING_STATE = "activating";
+// Details at https://upower.freedesktop.org/docs/Device.html
+constexpr uint TYPE_UPS = 3;
+constexpr uint STATE_FULLY_CHARGED = 4;
+constexpr uint BATTERY_LVL_FULL = 8;
+
/* Map a transition to it's systemd target */
const std::map<server::Chassis::Transition, std::string> SYSTEMD_TARGET_TABLE =
{
@@ -83,6 +88,14 @@
// has read property function
void Chassis::determineInitialState()
{
+
+ // Monitor for any properties changed signals on UPower device path
+ uPowerPropChangeSignal = std::make_unique<sdbusplus::bus::match_t>(
+ bus,
+ sdbusplus::bus::match::rules::propertiesChangedNamespace(
+ "/org/freedesktop/UPower", UPOWER_INTERFACE),
+ [this](auto& msg) { this->uPowerChangeEvent(msg); });
+
determineStatusOfPower();
std::variant<int> pgood = -1;
@@ -162,12 +175,6 @@
void Chassis::determineStatusOfPower()
{
-
- // Details at https://upower.freedesktop.org/docs/Device.html
- constexpr uint TYPE_UPS = 3;
- constexpr uint STATE_FULLY_CHARGED = 4;
- constexpr uint BATTERY_LVL_FULL = 8;
-
// Default PowerStatus to good
server::Chassis::currentPowerStatus(PowerStatus::Good);
@@ -194,7 +201,6 @@
if (mapperResponse.empty())
{
debug("No UPower devices found in system");
- return;
}
// Iterate through all returned Upower interfaces and look for UPS's
@@ -217,13 +223,6 @@
PropertyMap properties;
response.read(properties);
- if (std::get<bool>(properties["IsPresent"]) != true)
- {
- info("UPower device {OBJ_PATH} is not present", "OBJ_PATH",
- path);
- continue;
- }
-
if (std::get<uint>(properties["Type"]) != TYPE_UPS)
{
info("UPower device {OBJ_PATH} is not a UPS device",
@@ -231,6 +230,15 @@
continue;
}
+ if (std::get<bool>(properties["IsPresent"]) != true)
+ {
+ // There is a UPS detected but it is not officially
+ // "present" yet. Monitor it for state change.
+ info("UPower device {OBJ_PATH} is not present", "OBJ_PATH",
+ path);
+ continue;
+ }
+
if (std::get<uint>(properties["State"]) == STATE_FULLY_CHARGED)
{
info("UPS is fully charged");
@@ -248,6 +256,9 @@
BATTERY_LVL_FULL)
{
info("UPS Battery Level is Full");
+ // Only one UPS per system, we've found it and it's all
+ // good so exit function
+ return;
}
else
{
@@ -271,6 +282,45 @@
return;
}
+void Chassis::uPowerChangeEvent(sdbusplus::message::message& msg)
+{
+ debug("UPS Property Change Event Triggered");
+ std::string statusInterface;
+ std::map<std::string, std::variant<uint, bool>> msgData;
+ msg.read(statusInterface, msgData);
+
+ // If the change is to any of the three properties we are interested in
+ // then call determineStatusOfPower() to see if a power status change
+ // is needed
+ auto propertyMap = msgData.find("IsPresent");
+ if (propertyMap != msgData.end())
+ {
+ info("UPS presence changed to {UPS_PRES_INFO}", "UPS_PRES_INFO",
+ std::get<bool>(propertyMap->second));
+ determineStatusOfPower();
+ return;
+ }
+
+ propertyMap = msgData.find("State");
+ if (propertyMap != msgData.end())
+ {
+ info("UPS State changed to {UPS_STATE}", "UPS_STATE",
+ std::get<uint>(propertyMap->second));
+ determineStatusOfPower();
+ return;
+ }
+
+ propertyMap = msgData.find("BatteryLevel");
+ if (propertyMap != msgData.end())
+ {
+ info("UPS BatteryLevel changed to {UPS_BAT_LEVEL}", "UPS_BAT_LEVEL",
+ std::get<uint>(propertyMap->second));
+ determineStatusOfPower();
+ return;
+ }
+ return;
+}
+
void Chassis::executeTransition(Transition tranReq)
{
auto sysdTarget = SYSTEMD_TARGET_TABLE.find(tranReq)->second;