1010from aiounifi .models .port_forward import PortForward
1111from aiounifi .models .firewall_zone import FirewallZone
1212from aiounifi .models .wlan import Wlan
13+ from aiounifi .models .device import Device
1314
1415# Import our custom models
1516from ..models .firewall_rule import FirewallRule
@@ -35,6 +36,16 @@ def get_rule_enabled(rule: Any) -> bool:
3536 if isinstance (rule , (PortForward , TrafficRoute , FirewallPolicy , TrafficRule , Wlan , QoSRule , VPNConfig )):
3637 return getattr (rule , "enabled" , False )
3738
39+ # Special handling for Device LED state
40+ if isinstance (rule , Device ):
41+ # For devices, "enabled" means LED is not overridden (default state)
42+ # When led_override is "default", the LED follows normal behavior (enabled)
43+ # When led_override is "off", the LED is disabled
44+ if hasattr (rule , 'raw' ) and 'led_override' in rule .raw :
45+ led_state = rule .raw .get ('led_override' )
46+ return led_state != 'off' # True if not explicitly turned off
47+ return True # Default to enabled if no override info
48+
3849 # For dictionaries, try common enabled attributes
3950 if isinstance (rule , dict ):
4051 return rule .get ("enabled" , False )
@@ -63,6 +74,7 @@ def get_rule_id(rule: Any) -> str | None:
6374 Examples:
6475 - unr_policy_123456
6576 - unr_route_abcdef
77+ - unr_device_abc123_led
6678 """
6779 # Access different rule types and return appropriate ID with type prefix
6880 if isinstance (rule , PortForward ):
@@ -134,6 +146,14 @@ def get_rule_id(rule: Any) -> str | None:
134146 LOGGER .warning ("VPNConfig without id: %s" , rule )
135147 return None
136148
149+ # Handle Device objects for LED switches
150+ if isinstance (rule , Device ):
151+ if hasattr (rule , 'mac' ) and rule .mac :
152+ return f"unr_device_{ rule .mac } _led"
153+ else :
154+ LOGGER .warning ("Device without mac attribute: %s" , rule )
155+ return None
156+
137157 # Dictionary fallback - this should not happen with properly typed data
138158 if isinstance (rule , dict ):
139159 _id = rule .get ("_id" ) or rule .get ("id" )
@@ -165,7 +185,8 @@ def get_rule_prefix(rule_type: str) -> str:
165185 "traffic_rules" : "Traffic Rule" ,
166186 "legacy_firewall_rules" : "Legacy Rule" ,
167187 "qos_rules" : "QoS" ,
168- "wlans" : "WLAN"
188+ "wlans" : "WLAN" ,
189+ "devices" : "Device"
169190 }
170191
171192 return rule_types .get (rule_type , "Rule" )
@@ -312,6 +333,16 @@ def extract_descriptive_name(rule: Any, coordinator=None) -> str | None:
312333
313334 return None
314335
336+ elif isinstance (rule , Device ):
337+ # For devices, return the device name for LED switches
338+ if hasattr (rule , 'name' ) and rule .name :
339+ return f"{ rule .name } "
340+ elif hasattr (rule , 'raw' ) and 'name' in rule .raw :
341+ return f"{ rule .raw ['name' ]} "
342+ elif hasattr (rule , 'mac' ) and rule .mac :
343+ return f"Device { rule .mac } "
344+ return "Device"
345+
315346 elif isinstance (rule , dict ):
316347 # For dictionaries, try common name attributes
317348 return rule .get ("name" ) or rule .get ("description" )
@@ -341,6 +372,8 @@ def get_rule_name(rule: Any, coordinator=None) -> str | None:
341372 rule_type = "wlans"
342373 elif isinstance (rule , QoSRule ):
343374 rule_type = "qos_rules"
375+ elif isinstance (rule , Device ):
376+ rule_type = "devices"
344377 elif isinstance (rule , dict ) and "type" in rule :
345378 rule_type = rule .get ("type" )
346379
0 commit comments