@@ -427,12 +427,15 @@ async def _compile_firewall_rules_switches(
427427 for rule in state .get ("firewall" , {}).get ("rules" , {}).values ():
428428 if not isinstance (rule , dict ):
429429 continue
430+ interface = rule .get ("%interface" , "" )
431+ if interface .count ("," ) > 1 :
432+ interface = "Floating"
430433 entity = OPNsenseFirewallRuleSwitch (
431434 config_entry = config_entry ,
432435 coordinator = coordinator ,
433436 entity_description = SwitchEntityDescription (
434437 key = f"firewall.rule.{ rule .get ('uuid' , 'unknown' )} " ,
435- name = f"Firewall Rule: { rule . get ( '% interface' , '' ) } : { rule .get ('description' , 'unknown' )} " ,
438+ name = f"Firewall Rule: { interface } : { rule .get ('description' , 'unknown' )} " ,
436439 icon = "mdi:play-network-outline" ,
437440 device_class = SwitchDeviceClass .SWITCH ,
438441 entity_registry_enabled_default = False ,
@@ -585,7 +588,7 @@ async def _compile_nat_npt_rules_switches(
585588 coordinator : OPNsenseDataUpdateCoordinator ,
586589 state : MutableMapping [str , Any ],
587590) -> list :
588- """Compile NAT NPT rule switches from OPNsense state.
591+ """Compile NAT NPTv6 rule switches from OPNsense state.
589592
590593 Parameters
591594 ----------
@@ -599,7 +602,7 @@ async def _compile_nat_npt_rules_switches(
599602 Returns
600603 -------
601604 list
602- A list of OPNsenseNATRuleSwitch entities for NPT NAT rules.
605+ A list of OPNsenseNATRuleSwitch entities for NPTv6 NAT rules.
603606
604607 """
605608 if not isinstance (state , MutableMapping ) or not isinstance (
@@ -616,7 +619,7 @@ async def _compile_nat_npt_rules_switches(
616619 coordinator = coordinator ,
617620 entity_description = SwitchEntityDescription (
618621 key = f"firewall.nat.npt.{ rule .get ('uuid' , 'unknown' )} " ,
619- name = f"NAT NPT Rule: { rule .get ('%interface' , '' )} : { rule .get ('description' , 'unknown' )} " ,
622+ name = f"NAT NPTv6 Rule: { rule .get ('%interface' , '' )} : { rule .get ('description' , 'unknown' )} " ,
620623 icon = "mdi:network-outline" ,
621624 device_class = SwitchDeviceClass .SWITCH ,
622625 entity_registry_enabled_default = False ,
@@ -907,6 +910,24 @@ def _handle_coordinator_update(self) -> None:
907910 self .async_write_ha_state ()
908911 return
909912 self ._available = True
913+ self ._attr_extra_state_attributes = {}
914+ properties : dict [str , str ] = {
915+ "description" : "description" ,
916+ "categories" : "categories" ,
917+ "state" : "%statetype" ,
918+ "action" : "%action" ,
919+ "direction" : "%direction" ,
920+ "interfaces" : "%interface" ,
921+ "version" : "%ipprotocol" ,
922+ "protocol" : "protocol" ,
923+ "source" : "source_net" ,
924+ "source_port" : "source_port" ,
925+ "destination" : "destination_net" ,
926+ "destination_port" : "destination_port" ,
927+ "gateway" : "gateway" ,
928+ }
929+ for name , attr in properties .items ():
930+ self ._attr_extra_state_attributes [name ] = rule .get (attr , None )
910931 self .async_write_ha_state ()
911932 _LOGGER .debug (
912933 "[OPNsenseFirewallRuleSwitch handle_coordinator_update] Name: %s, available: %s, is_on: %s, extra_state_attributes: %s" ,
@@ -1046,6 +1067,59 @@ def _handle_coordinator_update(self) -> None:
10461067 self .async_write_ha_state ()
10471068 return
10481069 self ._available = True
1070+ self ._attr_extra_state_attributes = {}
1071+ properties : dict [str , str ] = {
1072+ "description" : "description" ,
1073+ "categories" : "categories" ,
1074+ "interface" : "%interface" ,
1075+ }
1076+ match self ._nat_rule_type :
1077+ case "d_nat" :
1078+ properties .update (
1079+ {
1080+ "version" : "%ipprotocol" ,
1081+ "protocol" : "%protocol" ,
1082+ "source" : "source.network" ,
1083+ "source_port" : "source.port" ,
1084+ "destination" : "destination.%network" ,
1085+ "destination_port" : "destination.port" ,
1086+ "redirect_target" : "target" ,
1087+ "redirect_target_port" : "local-port" ,
1088+ }
1089+ )
1090+ case "source_nat" :
1091+ properties .update (
1092+ {
1093+ "version" : "%ipprotocol" ,
1094+ "protocol" : "protocol" ,
1095+ "source" : "source_net" ,
1096+ "source_port" : "source_port" ,
1097+ "destination" : "destination_net" ,
1098+ "destination_port" : "destination_port" ,
1099+ "translate_source" : "%target" ,
1100+ "translate_source_port" : "target_port" ,
1101+ }
1102+ )
1103+ case "one_to_one" :
1104+ properties .update (
1105+ {
1106+ "type" : "%type" ,
1107+ "external_network" : "external" ,
1108+ "source" : "source_net" ,
1109+ "destination" : "destination_net" ,
1110+ }
1111+ )
1112+ case "npt" :
1113+ properties .update (
1114+ {
1115+ "internal_ipv6_prefix" : "source_net" ,
1116+ "external_ipv6_prefix" : "destination_net" ,
1117+ "track_interface" : "trackif" ,
1118+ }
1119+ )
1120+ for name , attr in properties .items ():
1121+ self ._attr_extra_state_attributes [name ] = rule .get (attr , None )
1122+
10491123 self .async_write_ha_state ()
10501124 _LOGGER .debug (
10511125 "[OPNsenseNATRuleSwitch handle_coordinator_update] Name: %s, available: %s, is_on: %s, extra_state_attributes: %s" ,
0 commit comments