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 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). 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 ## 📚 Documentation
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->

View File

@@ -1,7 +1,7 @@
# `docker-compose.yaml` Examples # `docker-compose.yaml` Examples
> [!NOTE] > [!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 ### Example 1
@@ -122,7 +122,6 @@ services:
environment: environment:
- TZ=Europe/London - TZ=Europe/London
- PORT=20211 - PORT=20211
# network_mode: host
networks: networks:
- outside - outside
deploy: deploy:
@@ -130,10 +129,6 @@ services:
replicas: 1 replicas: 1
restart_policy: restart_policy:
condition: on-failure condition: on-failure
# placement: # ✅ Placement is now correctly inside deploy
# constraints:
# - node.role == manager
# - node.labels.device == NUC2
networks: networks:
outside: 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. 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] > [!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 ## ⚠ Note

View File

@@ -2,7 +2,7 @@
## Installation options ## 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] 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) - [[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) ![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. - 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 ### 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. 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: #### Example Trigger:
@@ -32,7 +34,7 @@ Conditions determine whether a workflow should proceed based on certain criteria
> [!TIP] > [!TIP]
> To better understand how to use specific Device fields, please read through the [Database overview](./DATABASE.md) guide. > To better understand how to use specific Device fields, please read through the [Database overview](./DATABASE.md) guide.
### Example Condition: #### Example Condition:
- **Logic**: `AND` - **Logic**: `AND`
- **Field**: `devVendor` - **Field**: `devVendor`
- **Operator**: `contains` (case in-sensitive) - **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. You can include multiple actions that should execute once the conditions are met.
### Example Action: #### Example Action:
- **Action Type**: `update_field` - **Action Type**: `update_field`
- **Field**: `devIsNew` - **Field**: `devIsNew`
- **Value**: `0` - **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; padding: 5px;
} }
.workflows
{
max-width: 800px;
}
.workflows .col-sm-12, .workflows .col-sx-12 .workflows .col-sm-12, .workflows .col-sx-12
{ {
padding-right: 5px; 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" "update_field", "delete_device"
]; ];
let emptyWorkflow = {
"name": "New Workflow",
"trigger": {
"object_type": "Devices",
"event_type": "insert"
},
"conditions": [
],
"actions": [
]
};
// -------------------------------------- // --------------------------------------
// Retrieve and process the data // Retrieve and process the data
function getData() { function getData() {
@@ -1073,17 +1085,7 @@ function updateWorkflowsJson(workflows)
// Get empty workflow JSON // Get empty workflow JSON
function getEmptyWorkflowJson() function getEmptyWorkflowJson()
{ {
return { return emptyWorkflow;
"name": "New Workflow",
"trigger": {
"object_type": "Devices",
"event_type": "create"
},
"conditions": [
],
"actions": [
]
}
} }
// --------------------------------------------------- // ---------------------------------------------------

View File

@@ -61,6 +61,7 @@ nav:
- Debugging Invalid JSON: DEBUG_INVALID_JSON.md - Debugging Invalid JSON: DEBUG_INVALID_JSON.md
- Debugging Plugins: DEBUG_PLUGINS.md - Debugging Plugins: DEBUG_PLUGINS.md
- Debugging Web UI Port: WEB_UI_PORT_DEBUG.md - Debugging Web UI Port: WEB_UI_PORT_DEBUG.md
- Debugging Workflows: WORKFLOWS_DEBUGGING.md
- Development: - Development:
- Plugin and app development: - Plugin and app development:
- Environment Setup: DEV_ENV_SETUP.md - Environment Setup: DEV_ENV_SETUP.md

View File

@@ -75,7 +75,6 @@ class DB():
return arr return arr
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def upgradeDB(self): def upgradeDB(self):
""" """
@@ -929,4 +928,19 @@ def get_all_devices(db):
return db.read(sql_devices_all) 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): def __init__(self, group_json):
mylog('none', ["[WF] json.dumps(group_json)"]) mylog('verbose', [f"[WF] ConditionGroup json.dumps(group_json): {json.dumps(group_json)}"])
mylog('none', [json.dumps(group_json)])
mylog('none', [group_json])
self.logic = group_json.get("logic", "AND").upper() self.logic = group_json.get("logic", "AND").upper()
self.conditions = [] self.conditions = []
@@ -78,6 +76,6 @@ class ConditionGroup:
elif self.logic == "OR": elif self.logic == "OR":
return any(results) return any(results)
else: else:
m = f"[WF] Unsupported logic: {self.logic}" m = f"[WF] ConditionGroup unsupported logic: {self.logic}"
mylog('none', [m]) mylog('verbose', [m])
raise ValueError(m) raise ValueError(m)

View File

@@ -57,6 +57,8 @@ class WorkflowManager:
# Ensure workflow is enabled before proceeding # Ensure workflow is enabled before proceeding
if workflow.get("enabled", "No").lower() == "yes": 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 # construct trigger object which also evaluates if the current event triggers it
trigger = Trigger(workflow["trigger"], event, self.db) trigger = Trigger(workflow["trigger"], event, self.db)

View File

@@ -1,4 +1,5 @@
import sys import sys
import json
# Register NetAlertX directories # Register NetAlertX directories
INSTALL_PATH="/app" INSTALL_PATH="/app"
@@ -7,6 +8,7 @@ sys.path.extend([f"{INSTALL_PATH}/server"])
import conf import conf
from logger import mylog, Logger from logger import mylog, Logger
from helper import get_setting_value, timeNowTZ from helper import get_setting_value, timeNowTZ
from database import get_array_from_sql_rows
# Make sure log level is initialized correctly # Make sure log level is initialized correctly
Logger(get_setting_value('LOG_LEVEL')) Logger(get_setting_value('LOG_LEVEL'))
@@ -27,7 +29,8 @@ class Trigger:
self.event = event # Store the triggered event context, if provided self.event = event # Store the triggered event context, if provided
self.triggered = self.object_type == event["ObjectType"] and self.event_type == event["AppEventType"] 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: if self.triggered:
# object type corresponds with the DB table name # object type corresponds with the DB table name