Skip to content

Commit c311860

Browse files
committed
Enhance UniFi Network Rules integration with real-time trigger system
This update introduces a comprehensive real-time trigger system for UniFi Network Rules, allowing users to receive instant notifications on rule changes. Key changes include: - Added a new section in `README.md` detailing the real-time triggers, their features, and setup instructions. - Updated `trigger.py` to support device automation style schemas and improved logging for better debugging. - Enabled detailed logging for trigger detection and processing, enhancing the ability to monitor rule changes. - Updated `const.py` to enable trigger logging for state-diff debugging. - Incremented version in `manifest.json` to 3.0.0 to reflect the significant enhancements. These improvements significantly enhance the responsiveness and usability of the UniFi Network Rules integration.
1 parent 214d0f0 commit c311860

7 files changed

Lines changed: 1002 additions & 93 deletions

File tree

README.md

Lines changed: 319 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,324 @@ icon: mdi:cloud-upload
155155

156156
> **Note**: For `rule_types` parameter, you can specify one or more of: `policy` (zone-based firewall rules), `port_forward` (port forwarding rules), `route` (traffic routes), or `qos_rule` (quality of service rules). See the "Understanding Rule Types" section for more details.
157157

158-
## Automation Examples
158+
## Real-Time Triggers 🔔
159+
160+
UniFi Network Rules provides a **sophisticated trigger system** that gives you real-time notifications when network rules change, regardless of whether the changes originate from Home Assistant or directly from the UniFi console. This bi-directional monitoring enables powerful automations and monitoring scenarios.
161+
162+
### Key Features
163+
164+
- **🔄 Bi-Directional Monitoring**: Triggers fire for changes made both from Home Assistant and directly from the UniFi console
165+
- **⚡ Real-Time Updates**: Uses UniFi OS websocket connections for instant notifications
166+
- **🎯 Granular Filtering**: Filter triggers by rule type, specific rule IDs, or rule name patterns
167+
- **📊 Rich Data**: Each trigger includes rule names, old/new states, and change details
168+
- **🛡️ Reliable Detection**: Smart state-diff approach ensures accurate change detection
169+
170+
### Trigger Types
171+
172+
| Trigger Type | Description | When It Fires |
173+
|--------------|-------------|---------------|
174+
| `rule_enabled` | Rule is enabled/activated | When a rule's enabled state changes from false to true |
175+
| `rule_disabled` | Rule is disabled/deactivated | When a rule's enabled state changes from true to false |
176+
| `rule_changed` | Rule configuration is modified | When any rule settings change (ports, IPs, names, etc.) |
177+
| `rule_deleted` | Rule is completely removed | When a rule is deleted from UniFi |
178+
179+
### Supported Rule Types
180+
181+
- **Firewall Policies** (`firewall_policies`): Zone-based firewall rules
182+
- **Port Forwards** (`port_forwards`): Port forwarding rules
183+
- **Traffic Routes** (`traffic_routes`): Network routing rules
184+
- **QoS Rules** (`qos_rules`): Quality of Service rules
185+
- **VPN Clients** (`vpn_clients`): VPN client configurations
186+
- **VPN Servers** (`vpn_servers`): VPN server configurations
187+
- **WLANs** (`wlans`): Wireless network configurations
188+
189+
### Setting Up Triggers
190+
191+
#### Using the Automation UI
192+
193+
**Note:** UI support is currently limited. Triggers may appear as "unknown" in the automation UI. For now, we recommend using YAML configuration.
194+
195+
1. Go to Settings → Automations & Scenes → Create Automation
196+
2. Choose "When" → Manual trigger
197+
3. Click "Edit in YAML" and use the YAML format shown below
198+
4. Configure your automation actions in the UI or YAML
199+
200+
#### YAML Configuration
201+
202+
```yaml
203+
triggers:
204+
- type: rule_enabled
205+
trigger: unifi_network_rules
206+
rule_type: port_forwards # Optional: filter by rule type
207+
name_filter: "Minecraft" # Optional: filter by rule name
208+
```
209+
210+
### Available Trigger Data
211+
212+
Each trigger provides rich data you can use in conditions and actions:
213+
214+
```yaml
215+
# Available in automations as trigger.event.*
216+
rule_id: "64f1a2b3c4d5e6f7g8h9i0j1" # Unique rule identifier
217+
rule_name: "Minecraft Server Access" # Human-readable rule name
218+
rule_type: "port_forwards" # Type of rule that changed
219+
old_state: { ... } # Previous rule configuration
220+
new_state: { ... } # New rule configuration (null for deletions)
221+
trigger_type: "rule_enabled" # Which trigger fired
222+
```
223+
224+
## Trigger Automation Examples
225+
226+
### 1. Security Monitoring - Alert on Unexpected Rule Changes
227+
228+
Get notified when someone makes firewall changes outside of Home Assistant:
229+
230+
```yaml
231+
alias: Security Alert - Firewall Changes
232+
description: Alert when firewall rules are modified outside of HA
233+
triggers:
234+
- type: rule_changed
235+
trigger: unifi_network_rules
236+
rule_type: firewall_policies
237+
- type: rule_deleted
238+
trigger: unifi_network_rules
239+
rule_type: firewall_policies
240+
condition:
241+
# Add conditions to filter out expected changes if needed
242+
action:
243+
- action: notify.mobile_app_admin_phone
244+
data:
245+
title: "🚨 Network Security Alert"
246+
message: >
247+
Firewall rule "{{ trigger.event.rule_name }}" was {{ trigger.event.trigger_type.replace('rule_', '') }}
248+
Rule ID: {{ trigger.event.rule_id }}
249+
data:
250+
priority: high
251+
category: security
252+
mode: single
253+
```
254+
255+
### 2. Game Server Management - Auto-Disable After Hours
256+
257+
Automatically disable game server access when enabled outside of allowed hours:
258+
259+
```yaml
260+
alias: Game Server Auto-Disable
261+
description: Disable Minecraft server if enabled during school hours
262+
triggers:
263+
- type: rule_enabled
264+
trigger: unifi_network_rules
265+
name_filter: "Minecraft"
266+
condition:
267+
- condition: time
268+
after: "08:00:00"
269+
before: "15:30:00"
270+
- condition: time
271+
weekday:
272+
- mon
273+
- tue
274+
- wed
275+
- thu
276+
- fri
277+
action:
278+
- delay:
279+
minutes: 5 # Give a 5-minute grace period
280+
- action: switch.turn_off
281+
target:
282+
entity_id: >
283+
{% set rule_id = trigger.event.rule_id %}
284+
{% set entities = states.switch | selectattr('attributes.rule_id', 'eq', rule_id) | map(attribute='entity_id') | list %}
285+
{{ entities[0] if entities else none }}
286+
- action: notify.family_devices
287+
data:
288+
title: "🎮 Game Server Disabled"
289+
message: "Minecraft server was automatically disabled during school hours"
290+
mode: single
291+
```
292+
293+
### 3. Backup Trigger - Save Config on Important Changes
294+
295+
Automatically backup network rules when critical changes are made by combining triggers and services:
296+
297+
```yaml
298+
alias: Auto-Backup on Critical Changes
299+
description: Backup rules when important firewall or VPN changes occur
300+
triggers:
301+
- type: rule_changed
302+
trigger: unifi_network_rules
303+
rule_type: firewall_policies
304+
- type: rule_deleted
305+
trigger: unifi_network_rules
306+
rule_type: firewall_policies
307+
- type: rule_changed
308+
trigger: unifi_network_rules
309+
rule_type: vpn_servers
310+
condition:
311+
# Only backup if it's been more than 1 hour since last backup
312+
- condition: template
313+
value_template: >
314+
{{ (now() - states.automation.auto_backup_on_critical_changes.attributes.last_triggered).total_seconds() > 3600 }}
315+
action:
316+
- action: unifi_network_rules.backup_rules
317+
data:
318+
filename: "auto_backup_{{ now().strftime('%Y%m%d_%H%M') }}.json"
319+
- action: persistent_notification.create
320+
data:
321+
title: "📁 Network Rules Backed Up"
322+
message: >
323+
Automatic backup created due to {{ trigger.event.trigger_type.replace('rule_', '') }}
324+
of {{ trigger.event.rule_type.replace('_', ' ').title() }}: "{{ trigger.event.rule_name }}"
325+
mode: single
326+
```
327+
328+
### 4. VPN Connection Monitoring
329+
330+
Monitor VPN client connections and send notifications:
331+
332+
```yaml
333+
alias: VPN Connection Monitoring
334+
description: Monitor when VPN clients connect or disconnect
335+
triggers:
336+
- type: rule_enabled
337+
trigger: unifi_network_rules
338+
rule_type: vpn_clients
339+
- type: rule_disabled
340+
trigger: unifi_network_rules
341+
rule_type: vpn_clients
342+
action:
343+
actions:
344+
- action: persistent_notification.create
345+
data:
346+
title: 🔒 VPN Status Change
347+
message: >-
348+
VPN "{{ trigger.event.rule_name }}" was {{ 'connected' if
349+
trigger.event.trigger_type == 'rule_enabled' else 'disconnected'
350+
}} {% if trigger.event.trigger_type == 'rule_enabled' %}
351+
🟢 Secure connection established {% else %} 🔴
352+
Connection terminated {% endif %}
353+
mode: parallel
354+
```
355+
356+
### 5. Kids' Device Management with Notifications
357+
358+
Monitor and log when parental control rules change:
359+
360+
```yaml
361+
alias: Parental Control Monitor
362+
description: Track changes to kids' internet access rules
363+
triggers:
364+
- type: rule_enabled
365+
trigger: unifi_network_rules
366+
name_filter: "Kid"
367+
- type: rule_disabled
368+
trigger: unifi_network_rules
369+
name_filter: "Kid"
370+
- type: rule_changed
371+
trigger: unifi_network_rules
372+
name_filter: "Block"
373+
action:
374+
- action: logbook.log
375+
data:
376+
name: "Parental Controls"
377+
message: >
378+
{{ trigger.event.rule_name }} was {{ trigger.event.trigger_type.replace('rule_', '') }}
379+
{% if trigger.event.trigger_type == 'rule_enabled' %}
380+
✅ Internet access restored
381+
{% elif trigger.event.trigger_type == 'rule_disabled' %}
382+
🚫 Internet access blocked
383+
{% else %}
384+
🔧 Settings modified
385+
{% endif %}
386+
entity_id: automation.parental_control_monitor
387+
- action: notify.parents_devices
388+
data:
389+
title: "👨‍👩‍👧‍👦 Parental Control Update"
390+
message: "{{ trigger.event.rule_name }} - {{ trigger.event.trigger_type.replace('rule_', '').title() }}"
391+
mode: parallel
392+
```
393+
394+
### 6. Network Health Dashboard
395+
396+
Create input helpers to track network rule changes on your dashboard:
397+
398+
```yaml
399+
alias: Update Network Stats
400+
description: Update dashboard counters for network changes
401+
triggers:
402+
- type: rule_enabled
403+
trigger: unifi_network_rules
404+
- type: rule_disabled
405+
trigger: unifi_network_rules
406+
- type: rule_changed
407+
trigger: unifi_network_rules
408+
action:
409+
- action: counter.increment
410+
target:
411+
entity_id: counter.network_rule_changes
412+
- action: input_text.set_value
413+
target:
414+
entity_id: input_text.last_network_change
415+
data:
416+
value: >
417+
{{ now().strftime('%H:%M') }}: {{ trigger.event.rule_name }} ({{ trigger.event.trigger_type.replace('rule_', '') }})
418+
- action: input_datetime.set_datetime
419+
target:
420+
entity_id: input_datetime.last_rule_change
421+
data:
422+
datetime: "{{ now() }}"
423+
mode: parallel
424+
```
425+
426+
### Advanced Filtering Examples
427+
428+
#### Filter by Multiple Rule Types
429+
430+
```yaml
431+
triggers:
432+
- type: rule_changed
433+
trigger: unifi_network_rules
434+
rule_type: port_forwards
435+
- type: rule_changed
436+
trigger: unifi_network_rules
437+
rule_type: vpn_clients
438+
```
439+
440+
#### Filter by Specific Rule Names
441+
442+
```yaml
443+
triggers:
444+
- type: rule_enabled
445+
trigger: unifi_network_rules
446+
name_filter: "Gaming" # Matches any rule containing "Gaming"
447+
```
448+
449+
#### Monitor Specific Rule ID
450+
451+
```yaml
452+
triggers:
453+
- type: rule_changed
454+
trigger: unifi_network_rules
455+
rule_id: "64f1a2b3c4d5e6f7g8h9i0j1" # Monitor one specific rule
456+
```
457+
458+
### Best Practices for Triggers
459+
460+
1. **Use Specific Filters**: Filter triggers to avoid unnecessary automation runs
461+
2. **Add Conditions**: Use time, state, or template conditions to refine when automations run
462+
3. **Set Appropriate Modes**: Use `single`, `parallel`, or `queued` based on your needs
463+
4. **Log Important Changes**: Use logbook entries for audit trails
464+
5. **Test Thoroughly**: Test triggers with both HA-initiated and console-initiated changes
465+
6. **Monitor Performance**: Triggers are real-time, so ensure your automations are efficient
466+
467+
### Troubleshooting Triggers
468+
469+
- **UI Shows "Unknown"**: Currently, trigger UI support is limited. Use YAML configuration instead
470+
- **Enable Debug Logging**: Set `LOG_TRIGGERS = True` in `const.py` for detailed trigger logs
471+
- **Check WebSocket Connection**: Triggers require active WebSocket connection to UniFi OS
472+
- **Verify Permissions**: Ensure your UniFi user has admin access to receive all rule change events
473+
- **Test Both Sources**: Verify triggers work for both HA-initiated and console-initiated changes
474+
475+
## Service Automation Examples
159476

160477
### Automated Daily Backup
161478

@@ -361,6 +678,7 @@ For more focused debugging of specific subsystems, you can enable only what you
361678
- `LOG_API_CALLS`: Log API requests and responses
362679
- `LOG_DATA_UPDATES`: Log data refresh and update cycles
363680
- `LOG_ENTITY_CHANGES`: Log entity addition, removal, and state changes
681+
- `LOG_TRIGGERS`: Log trigger detection and firing
364682

365683
These targeted flags help reduce log noise when troubleshooting specific issues.
366684

custom_components/unifi_network_rules/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
LOG_API_CALLS: Final = False # API requests and responses
5858
LOG_DATA_UPDATES: Final = False # Data refresh and update cycles
5959
LOG_ENTITY_CHANGES: Final = False # Entity addition/removal/state changes
60-
LOG_TRIGGERS: Final = False # Trigger detection and firing logs - TEMPORARILY ENABLED FOR DEBUG
60+
LOG_TRIGGERS: Final = True # Trigger detection and firing logs - ENABLED FOR STATE-DIFF DEBUGGING
6161

6262
# For backwards compatibility - will be removed in a future update
6363
# Use LOG_WEBSOCKET instead

custom_components/unifi_network_rules/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@
1616
"aiounifi>=82.0.0",
1717
"orjson>=3.8.0"
1818
],
19-
"version": "2.3.0"
19+
"version": "3.0.0"
2020
}

custom_components/unifi_network_rules/translations/en.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,43 @@
2424
"already_configured": "Device is already configured"
2525
}
2626
},
27+
"device_automation": {
28+
"trigger_type": {
29+
"rule_enabled": "Rule enabled",
30+
"rule_disabled": "Rule disabled",
31+
"rule_changed": "Rule changed",
32+
"rule_deleted": "Rule deleted"
33+
},
34+
"trigger_subtype": {
35+
"firewall_policies": "Firewall Policy",
36+
"traffic_routes": "Traffic Route",
37+
"port_forwards": "Port Forward",
38+
"qos_rules": "QoS Rule",
39+
"vpn_clients": "VPN Client",
40+
"vpn_servers": "VPN Server",
41+
"legacy_firewall_rules": "Legacy Firewall Rule",
42+
"traffic_rules": "Traffic Rule",
43+
"wlans": "WLAN"
44+
}
45+
},
46+
"triggers": {
47+
"rule_enabled": {
48+
"name": "UniFi rule enabled",
49+
"description": "Triggered when a UniFi Network rule is enabled"
50+
},
51+
"rule_disabled": {
52+
"name": "UniFi rule disabled",
53+
"description": "Triggered when a UniFi Network rule is disabled"
54+
},
55+
"rule_changed": {
56+
"name": "UniFi rule changed",
57+
"description": "Triggered when a UniFi Network rule configuration is modified"
58+
},
59+
"rule_deleted": {
60+
"name": "UniFi rule deleted",
61+
"description": "Triggered when a UniFi Network rule is deleted"
62+
}
63+
},
2764
"services": {
2865
"refresh": {
2966
"name": "Refresh",

0 commit comments

Comments
 (0)