mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-06 17:15:38 -08:00
wf work
This commit is contained in:
@@ -41,6 +41,10 @@ Send notifications to more than 80+ services, including Telegram via [Apprise](h
|
||||
Feed your data and device changes into [Home Assistant](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HOME_ASSISTANT.md), read [API endpoints](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md), or use [Webhooks](https://github.com/jokob-sk/NetAlertX/blob/main/docs/WEBHOOK_N8N.md) to setup custom automation flows. You can also
|
||||
build your own scanners with the [Plugin system](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) in as little as [15 minutes](https://www.youtube.com/watch?v=cdbxlwiWhv8).
|
||||
|
||||
### Workflows
|
||||
|
||||
The [workflows module](https://github.com/jokob-sk/NetAlertX/blob/main/docs/WORKFLOWS.md) in NetAlertX allows to automate repetitive tasks, making network management more efficient. Whether you need to assign newly discovered devices to a specific Network Node, auto-group devices from a given vendor, unarchive a device if detected online, or automatically delete devices, this module provides the flexibility to tailor the automations to your needs.
|
||||
|
||||
|
||||
## 📚 Documentation
|
||||
<!--- --------------------------------------------------------------------- --->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# `docker-compose.yaml` Examples
|
||||
|
||||
> [!NOTE]
|
||||
> The container needs to run in `network_mode:"host"`.
|
||||
> The container needs to run in `network_mode:"host"`. This also means that not all functionality is supported on a Widndows host as Docker for Windows doesn't support this networking option.
|
||||
|
||||
### Example 1
|
||||
|
||||
@@ -122,7 +122,6 @@ services:
|
||||
environment:
|
||||
- TZ=Europe/London
|
||||
- PORT=20211
|
||||
# network_mode: host
|
||||
networks:
|
||||
- outside
|
||||
deploy:
|
||||
@@ -130,10 +129,6 @@ services:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
# placement: # ✅ Placement is now correctly inside deploy
|
||||
# constraints:
|
||||
# - node.role == manager
|
||||
# - node.labels.device == NUC2
|
||||
|
||||
networks:
|
||||
outside:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
NetAlertX comes with MQTT support, allowing you to show all detected devices as devices in Home Assistant. It also supplies a collection of stats, such as number of online devices.
|
||||
|
||||
> [!TIP]
|
||||
> You can install NetAlertX also as a Home Assistant addon [](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons) via the [alexbelgium/hassio-addons](https://github.com/alexbelgium/hassio-addons/). This is only possible if you run a supervised instance of Home Assistant. If not, you can still run NetAlertX in a separate Docker container and follow this guide to configure MQTT.
|
||||
> You can install NetAlertX also as a Home Assistant addon [](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons) via the [alexbelgium/hassio-addons](https://github.com/alexbelgium/hassio-addons/) repository. This is only possible if you run a supervised instance of Home Assistant. If not, you can still run NetAlertX in a separate Docker container and follow this guide to configure MQTT.
|
||||
|
||||
## ⚠ Note
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Installation options
|
||||
|
||||
NetAlertX can be installed several ways. The best supported option is Docker, followed by a supervised the Home Assistant instance, as an Unraid app and lastly on bare metal.
|
||||
NetAlertX can be installed several ways. The best supported option is Docker, followed by a supervised Home Assistant instance, as an Unraid app, and lastly, on bare metal.
|
||||
|
||||
- [[Installation] Docker (recommended)](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md)
|
||||
- [[Installation] Home Assistant](https://github.com/alexbelgium/hassio-addons/tree/master/netalertx)
|
||||
|
||||
@@ -51,7 +51,7 @@ services:
|
||||
|
||||

|
||||
|
||||
7. Replace the paths to your volume and/or comment out unnecessary line(s):
|
||||
7. Replace the paths to your volume and comment out unnecessary line(s):
|
||||
|
||||
- This is only an example, your paths will differ.
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ Below are a few examples that demonstrate how this module can be used to simplif
|
||||
|
||||
### Triggers
|
||||
|
||||

|
||||
|
||||
Triggers define the event that activates a workflow. They monitor changes to objects within the system, such as updates to devices or the insertion of new entries. When the specified event occurs, the workflow is executed.
|
||||
|
||||
#### Example Trigger:
|
||||
@@ -32,7 +34,7 @@ Conditions determine whether a workflow should proceed based on certain criteria
|
||||
> [!TIP]
|
||||
> To better understand how to use specific Device fields, please read through the [Database overview](./DATABASE.md) guide.
|
||||
|
||||
### Example Condition:
|
||||
#### Example Condition:
|
||||
- **Logic**: `AND`
|
||||
- **Field**: `devVendor`
|
||||
- **Operator**: `contains` (case in-sensitive)
|
||||
@@ -48,7 +50,7 @@ Actions define the tasks that the workflow will perform once the conditions are
|
||||
|
||||
You can include multiple actions that should execute once the conditions are met.
|
||||
|
||||
### Example Action:
|
||||
#### Example Action:
|
||||
- **Action Type**: `update_field`
|
||||
- **Field**: `devIsNew`
|
||||
- **Value**: `0`
|
||||
|
||||
34
docs/WORKFLOWS_DEBUGGING.md
Executable file
34
docs/WORKFLOWS_DEBUGGING.md
Executable file
@@ -0,0 +1,34 @@
|
||||
# Workflows debugging and troubleshooting
|
||||
|
||||
> [!TIP]
|
||||
> Before troubleshooting, please ensure you have [Debugging enabled](./DEBUG_TIPS.md).
|
||||
|
||||
Workflows are triggered by various events. These events are captured and listed in the _Integrations -> App Events_ section of the application.
|
||||
|
||||
## Troubleshooting triggers
|
||||
|
||||
> [!NOTE]
|
||||
> Workflow events are processed once every 5 seconds. However, if a scan or other background tasks are running, this can cause a delay up to a few minutes.
|
||||
|
||||
If an event doesn't trigger a workflow as expected, check the _App Events_ section for the event. You can filter these by the ID of the device (`devMAC` or `devGUID`).
|
||||
|
||||
Once you find the _Event Guid_ and _Object GUID_, use them to find relevant debug entries.
|
||||
|
||||
Navigate to _Mainetenace -> Logs_ where you can filter the logs based on the _Event or Object GUID_.
|
||||
|
||||
Below you can find some example `app.log` entries that will help you understand why a Workflow was or was not triggered.
|
||||
|
||||
```bash
|
||||
16:27:03 [WF] Checking if '13f0ce26-1835-4c48-ae03-cdaf38f328fe' triggers the workflow 'Sample Device Update Workflow'
|
||||
16:27:03 [WF] self.triggered 'False' for event '[[155], ['13f0ce26-1835-4c48-ae03-cdaf38f328fe'], [0], ['2025-04-02 05:26:56'], ['Devices'], ['050b6980-7af6-4409-950d-08e9786b7b33'], ['DEVICES'], ['00:11:32:ef:a5:6c'], ['192.168.1.82'], ['050b6980-7af6-4409-950d-08e9786b7b33'], [None], [0], [0], ['devPresentLastScan'], ['online'], ['update'], [None], [None], [None], [None]] and trigger {"object_type": "Devices", "event_type": "insert"}'
|
||||
16:27:03 [WF] Checking if '13f0ce26-1835-4c48-ae03-cdaf38f328fe' triggers the workflow 'Location Change'
|
||||
16:27:03 [WF] self.triggered 'True' for event '[[155], ['13f0ce26-1835-4c48-ae03-cdaf38f328fe'], [0], ['2025-04-02 05:26:56'], ['Devices'], ['050b6980-7af6-4409-950d-08e9786b7b33'], ['DEVICES'], ['00:11:32:ef:a5:6c'], ['192.168.1.82'], ['050b6980-7af6-4409-950d-08e9786b7b33'], [None], [0], [0], ['devPresentLastScan'], ['online'], ['update'], [None], [None], [None], [None]] and trigger {"object_type": "Devices", "event_type": "update"}'
|
||||
16:27:03 [WF] Event with GUID '13f0ce26-1835-4c48-ae03-cdaf38f328fe' triggered the workflow 'Location Change'
|
||||
```
|
||||
|
||||
Note how one trigger executed, but the other didn't based on different `"event_type"` values. One is `"event_type": "insert"`, the other `"event_type": "update"`.
|
||||
|
||||
Given the Event is a update event (note `...['online'], ['update'], [None]...` in the event structure), the `"event_type": "insert"` trigger didn't execute.
|
||||
|
||||
|
||||
|
||||
BIN
docs/img/WORKFLOWS/trigger.jpg
Executable file
BIN
docs/img/WORKFLOWS/trigger.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
@@ -1857,6 +1857,11 @@ input[readonly] {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.workflows
|
||||
{
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.workflows .col-sm-12, .workflows .col-sx-12
|
||||
{
|
||||
padding-right: 5px;
|
||||
|
||||
0
front/php/templates/language/uk_ua.json
Normal file → Executable file
0
front/php/templates/language/uk_ua.json
Normal file → Executable file
@@ -66,6 +66,18 @@ let actionTypes = [
|
||||
"update_field", "delete_device"
|
||||
];
|
||||
|
||||
let emptyWorkflow = {
|
||||
"name": "New Workflow",
|
||||
"trigger": {
|
||||
"object_type": "Devices",
|
||||
"event_type": "insert"
|
||||
},
|
||||
"conditions": [
|
||||
],
|
||||
"actions": [
|
||||
]
|
||||
};
|
||||
|
||||
// --------------------------------------
|
||||
// Retrieve and process the data
|
||||
function getData() {
|
||||
@@ -1073,17 +1085,7 @@ function updateWorkflowsJson(workflows)
|
||||
// Get empty workflow JSON
|
||||
function getEmptyWorkflowJson()
|
||||
{
|
||||
return {
|
||||
"name": "New Workflow",
|
||||
"trigger": {
|
||||
"object_type": "Devices",
|
||||
"event_type": "create"
|
||||
},
|
||||
"conditions": [
|
||||
],
|
||||
"actions": [
|
||||
]
|
||||
}
|
||||
return emptyWorkflow;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
|
||||
@@ -61,6 +61,7 @@ nav:
|
||||
- Debugging Invalid JSON: DEBUG_INVALID_JSON.md
|
||||
- Debugging Plugins: DEBUG_PLUGINS.md
|
||||
- Debugging Web UI Port: WEB_UI_PORT_DEBUG.md
|
||||
- Debugging Workflows: WORKFLOWS_DEBUGGING.md
|
||||
- Development:
|
||||
- Plugin and app development:
|
||||
- Environment Setup: DEV_ENV_SETUP.md
|
||||
|
||||
@@ -75,7 +75,6 @@ class DB():
|
||||
|
||||
return arr
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def upgradeDB(self):
|
||||
"""
|
||||
@@ -930,3 +929,18 @@ def get_all_devices(db):
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def get_array_from_sql_rows(rows):
|
||||
# Convert result into list of lists
|
||||
arr = []
|
||||
for row in rows:
|
||||
if isinstance(row, sqlite3.Row):
|
||||
arr.append(list(row)) # Convert row to list
|
||||
elif isinstance(row, (tuple, list)):
|
||||
arr.append(list(row)) # Already iterable, just convert to list
|
||||
else:
|
||||
arr.append([row]) # Handle single values safely
|
||||
|
||||
return arr
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -57,9 +57,7 @@ class ConditionGroup:
|
||||
|
||||
def __init__(self, group_json):
|
||||
|
||||
mylog('none', ["[WF] json.dumps(group_json)"])
|
||||
mylog('none', [json.dumps(group_json)])
|
||||
mylog('none', [group_json])
|
||||
mylog('verbose', [f"[WF] ConditionGroup json.dumps(group_json): {json.dumps(group_json)}"])
|
||||
|
||||
self.logic = group_json.get("logic", "AND").upper()
|
||||
self.conditions = []
|
||||
@@ -78,6 +76,6 @@ class ConditionGroup:
|
||||
elif self.logic == "OR":
|
||||
return any(results)
|
||||
else:
|
||||
m = f"[WF] Unsupported logic: {self.logic}"
|
||||
mylog('none', [m])
|
||||
m = f"[WF] ConditionGroup unsupported logic: {self.logic}"
|
||||
mylog('verbose', [m])
|
||||
raise ValueError(m)
|
||||
|
||||
@@ -58,6 +58,8 @@ class WorkflowManager:
|
||||
# Ensure workflow is enabled before proceeding
|
||||
if workflow.get("enabled", "No").lower() == "yes":
|
||||
|
||||
mylog('debug', [f"[WF] Checking if '{event["GUID"]}' triggers the workflow '{workflow["name"]}'"])
|
||||
|
||||
# construct trigger object which also evaluates if the current event triggers it
|
||||
trigger = Trigger(workflow["trigger"], event, self.db)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import sys
|
||||
import json
|
||||
|
||||
# Register NetAlertX directories
|
||||
INSTALL_PATH="/app"
|
||||
@@ -7,6 +8,7 @@ sys.path.extend([f"{INSTALL_PATH}/server"])
|
||||
import conf
|
||||
from logger import mylog, Logger
|
||||
from helper import get_setting_value, timeNowTZ
|
||||
from database import get_array_from_sql_rows
|
||||
|
||||
# Make sure log level is initialized correctly
|
||||
Logger(get_setting_value('LOG_LEVEL'))
|
||||
@@ -27,7 +29,8 @@ class Trigger:
|
||||
self.event = event # Store the triggered event context, if provided
|
||||
self.triggered = self.object_type == event["ObjectType"] and self.event_type == event["AppEventType"]
|
||||
|
||||
mylog('verbose', [f"[WF] self.triggered '{self.triggered}'"])
|
||||
mylog('debug', [f"""[WF] self.triggered '{self.triggered}' for event '{get_array_from_sql_rows(event)} and trigger {json.dumps(triggerJson)}' """])
|
||||
|
||||
|
||||
if self.triggered:
|
||||
# object type corresponds with the DB table name
|
||||
|
||||
Reference in New Issue
Block a user