This commit is contained in:
jokob-sk
2025-04-03 07:51:59 +11:00
parent e1f9ca05b7
commit 2889be28e4
16 changed files with 89 additions and 29 deletions

View File

@@ -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
<!--- --------------------------------------------------------------------- --->

View File

@@ -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:

View File

@@ -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 [![Home Assistant](https://img.shields.io/badge/Repo-blue?logo=home-assistant&style=for-the-badge&color=0aa8d2&logoColor=fff&label=Add)](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 [![Home Assistant](https://img.shields.io/badge/Repo-blue?logo=home-assistant&style=for-the-badge&color=0aa8d2&logoColor=fff&label=Add)](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

View File

@@ -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)

View File

@@ -51,7 +51,7 @@ services:
![Project settings](./img/SYNOLOGY/07_Create_project.png)
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.

View File

@@ -15,6 +15,8 @@ Below are a few examples that demonstrate how this module can be used to simplif
### Triggers
![Trigger example](./img/WORKFLOWS/trigger.jpg)
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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -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
View File

View 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;
}
// ---------------------------------------------------

View File

@@ -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

View File

@@ -75,7 +75,6 @@ class DB():
return arr
#-------------------------------------------------------------------------------
def upgradeDB(self):
"""
@@ -929,4 +928,19 @@ def get_all_devices(db):
return db.read(sql_devices_all)
#-------------------------------------------------------------------------------
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
#-------------------------------------------------------------------------------

View File

@@ -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)

View File

@@ -57,6 +57,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)

View File

@@ -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