Compare commits

...

56 Commits

Author SHA1 Message Date
jokob-sk
09fd345528 color alignemnt network tab, pop-up box devDetails
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-16 08:32:51 +10:00
jokob-sk
edfba9f1bc hover box css fixes, docs
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-15 23:21:28 +10:00
Максим Горпиніч
bb844ceac4 Translated using Weblate (Ukrainian)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-15 06:03:36 +00:00
Massimo Pissarello
c6f3b60671 Translated using Weblate (Italian)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-15 06:03:35 +00:00
Massimo Pissarello
3178a65e72 Translated using Weblate (Italian)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-15 06:03:35 +00:00
Sylvain Pichon
aedfb4e5dd Translated using Weblate (French)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-15 06:03:34 +00:00
jokob-sk
e0dcc191c7 hover box, network page improvements, Last Seen changed logic ⚠
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-15 08:34:47 +10:00
jokob-sk
c80e6d3474 css hover box #724
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-14 20:42:12 +10:00
jokob-sk
46cd4887a3 css fixes #724 2025-07-14 19:52:16 +10:00
jokob-sk
bfbf70cf1a colored relationships #724
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-14 15:24:38 +10:00
jokob-sk
61de54bc34 net refactor 2025-07-14 11:01:16 +10:00
Максим Горпиніч
e27af88690 Translated using Weblate (Ukrainian)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 100.0% (756 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-13 18:01:48 +02:00
jokob-sk
393c3fd3b6 nics work 724
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-13 09:02:21 +10:00
Hosted Weblate
0e53aef9ea Merge branch 'origin/main' into Weblate.
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-12 05:45:29 +00:00
Safeguard
8a742b0ec0 Translated using Weblate (Russian)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-07-12 05:45:27 +00:00
jokob-sk
b17b70a91f pl conflict resolution 2025-07-12 15:44:58 +10:00
jokob-sk
6f536f9952 ntfy disable cert #1117, initial nics work #724 2025-07-12 15:40:08 +10:00
Adam Stańczyk
034caf965a Translated using Weblate (Polish)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:22 +00:00
Adam Stańczyk
6322e3f4cf Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:20 +00:00
Adam Stańczyk
6b78adb702 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:19 +00:00
Adam Stańczyk
6e8c931bf3 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:18 +00:00
Adam Stańczyk
b80fe44c08 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:17 +00:00
Adam Stańczyk
0921773666 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:16 +00:00
Adam Stańczyk
13e960f5cb Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:15 +00:00
Adam Stańczyk
094583b8f6 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:14 +00:00
Adam Stańczyk
fd7ec5d2cf Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:13 +00:00
Adam Stańczyk
370659f461 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:12 +00:00
Adam Stańczyk
1f853a8bb1 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:11 +00:00
Adam Stańczyk
b93c3b6093 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:10 +00:00
Adam Stańczyk
6145fff2fd Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:09 +00:00
Adam Stańczyk
48687dc6dd Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:08 +00:00
Adam Stańczyk
4591cc87e2 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:07 +00:00
Adam Stańczyk
67491615c0 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:06 +00:00
Adam Stańczyk
fadf64450b Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:05 +00:00
Adam Stańczyk
34bb7bb93f Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:04 +00:00
Adam Stańczyk
67f8401dce Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:03 +00:00
Adam Stańczyk
f9fb711881 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:01 +00:00
Adam Stańczyk
26c35a01f3 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:00 +00:00
Adam Stańczyk
9538842fcb Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:59 +00:00
Adam Stańczyk
8ca31ab049 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:58 +00:00
Adam Stańczyk
b19c9b5eb6 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:58 +00:00
Adam Stańczyk
896ead0bb8 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:56 +00:00
Adam Stańczyk
9835381186 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:55 +00:00
Adam Stańczyk
d49ced8942 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:54 +00:00
Adam Stańczyk
9a01263d70 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:53 +00:00
jokob-sk
7980554924 small refactor, docs
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-07 09:05:35 +10:00
jokob-sk
8949bcb567 icon and device type guessing from @slammingprogramming
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-06 17:08:11 +10:00
jokob-sk
ac90bb702e string issue #1104
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-06 12:22:42 +10:00
jokob-sk
088c913ede session events fix 2025-07-06 09:03:26 +10:00
jokob-sk
7554a7f246 apprise_telegram settings screenshot update 2025-07-06 08:23:04 +10:00
jokob-sk
31e5c9fe96 twitter automation removal 2025-07-05 09:04:46 +10:00
jokob-sk
e21c1771c7 docs
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-05 08:14:24 +10:00
jokob-sk
502a331754 docs 2025-07-05 07:33:42 +10:00
Jokob @NetAlertX
6203c3c257 Merge pull request #1108 from scalerow/bugfix/unifimp_not_running
nax_pyunifi.controller not found
2025-07-05 07:23:00 +10:00
Jan Fredrik Sundblom
c7d9ef97ee nax_pyunifi.controller not found
Could not import nax_pyunifi.controller, pyunifi.controller works as expected.
2025-07-04 15:46:40 +02:00
GitHub Actions
608fc5bbd0 Add release tweet for v25.7.3 - 🌍 Arabic translation and various fixes
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-03 22:07:40 +00:00
54 changed files with 2332 additions and 1421 deletions

2
.github/tweet.md vendored
View File

@@ -1,2 +0,0 @@
🎉 New release: **v25.6.7 - Legacy upgrade removal and Fully Qualified Domain Names 🆎** is live! 🚀
Check it out here: https://github.com/jokob-sk/NetAlertX/releases/tag/v25.6.7

View File

@@ -1,4 +1,4 @@
name: 📧 Twitter and Discord Posts name: 📧 Social Posts
on: on:
release: release:
types: [published] types: [published]
@@ -16,38 +16,3 @@ jobs:
-d '{"content": "🎉 New release: **${{ github.event.release.name }}** is live! 🚀\nCheck it out here: ${{ github.event.release.html_url }}"}' \ -d '{"content": "🎉 New release: **${{ github.event.release.name }}** is live! 🚀\nCheck it out here: ${{ github.event.release.html_url }}"}' \
${{ secrets.DISCORD_WEBHOOK_URL }} ${{ secrets.DISCORD_WEBHOOK_URL }}
post-twitter:
runs-on: ubuntu-latest
steps:
- name: Wait for 15 minutes
run: sleep 900 # 15 minutes delay
- name: Checkout repository
uses: actions/checkout@v3
- name: Set Git config
run: |
git config --global user.email "github-actions@github.com"
git config --global user.name "GitHub Actions"
- name: Create tweet file
run: |
echo "🎉 New release: **${{ github.event.release.name }}** is live! 🚀" > .github/tweet.md
echo "Check it out here: ${{ github.event.release.html_url }}" >> .github/tweet.md
git add .github/tweet.md
git commit -m "Add release tweet for ${{ github.event.release.name }}"
- name: Push changes
run: |
git push https://github.com/${{ github.repository }}.git HEAD:main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Tweet
uses: twitter-together/action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
TWITTER_API_KEY: ${{ secrets.TWITTER_API_KEY }}
TWITTER_API_SECRET_KEY: ${{ secrets.TWITTER_API_SECRET_KEY }}

View File

@@ -23,11 +23,11 @@ services:
# - ${DEV_LOCATION}/api:/app/api # - ${DEV_LOCATION}/api:/app/api
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes # DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp1.leases:/mnt/dhcp1.leases - ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp1.leases:/mnt/dhcp1.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp2.leases:/mnt/dhcp2.leases - ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp2.leases:/mnt/dhcp2.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_full.leases:/etc/pihole/dhcp.leases - ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_full.leases:/etc/pihole/dhcp.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_2.leases:/etc/pihole/dhcp2.leases - ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_2.leases:/etc/pihole/dhcp2.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/pihole/etc-pihole/pihole-FTL.db:/etc/pihole/pihole-FTL.db - ${APP_DATA_LOCATION}/pihole/etc-pihole/pihole-FTL.db:/etc/pihole/pihole-FTL.db # test data for PIHOLE plugin
- ${DEV_LOCATION}/mkdocs.yml:/app/mkdocs.yml - ${DEV_LOCATION}/mkdocs.yml:/app/mkdocs.yml
- ${DEV_LOCATION}/docs:/app/docs - ${DEV_LOCATION}/docs:/app/docs
- ${DEV_LOCATION}/server:/app/server - ${DEV_LOCATION}/server:/app/server

View File

@@ -39,6 +39,8 @@
| `devSourcePlugin` | Source plugin that discovered the device. | `ARPSCAN` | | `devSourcePlugin` | Source plugin that discovered the device. | `ARPSCAN` |
| `devCustomProps` | [Custom properties](./CUSTOM_PROPERTIES.md) related to the device. The value is a base64-encoded JSON object. | `PHN2ZyB...` | | `devCustomProps` | [Custom properties](./CUSTOM_PROPERTIES.md) related to the device. The value is a base64-encoded JSON object. | `PHN2ZyB...` |
| `devFQDN` | Fully qualified domain name. | `raspberrypi.local` | | `devFQDN` | Fully qualified domain name. | `raspberrypi.local` |
| `devParentRelType` | The type of relationship between the current device and it's parent node. By default, selecting `nic` will hide it from lists. | `nic` |
| `devReqNicsOnline` | If all NICs are required to be online to mark teh current device online. | `0` |
To understand how values of these fields influuence application behavior, such as Notifications or Network topology, see also: To understand how values of these fields influuence application behavior, such as Notifications or Network topology, see also:

View File

@@ -10,7 +10,7 @@ Check the the HTTP response of the failing backend call by following these steps
- Copy the URL causing the error and enter it in the address bar of your browser directly and hit enter. The copied URLs could look something like this (notice the query strings at the end): - Copy the URL causing the error and enter it in the address bar of your browser directly and hit enter. The copied URLs could look something like this (notice the query strings at the end):
- `http://<NetAlertX URL>:20211/api/table_devices.json?nocache=1704141103121` - `http://<NetAlertX URL>:20211/api/table_devices.json?nocache=1704141103121`
- `http://<NetAlertX URL>:20211/php/server/devices.php?action=getDevicesTotals` - `http://<NetAlertX URL>:20211/php/server/devices.php?action=getDevicesTotals`
- `http://<NetAlertX URL>:20211/php/server/devices.php?action=getDevicesList&status=all`
- Post the error response in the existing issue thread on GitHub or create a new issue and include the redacted response of the failing query. - Post the error response in the existing issue thread on GitHub or create a new issue and include the redacted response of the failing query.

View File

@@ -1,13 +1,14 @@
# Docker Update Strategies to upgrade NetAlertX # Docker Update Strategies to upgrade NetAlertX
> [!WARNING] > [!WARNING]
> For versions prior to `v25.6.7` upgrade to version `v25.5.24` first (`docker pull ghcr.io/jokob-sk/netalertx:25.5.24`) as later versions don't support a full upgrade. Alternatovelly, devices and settings can be migrated manually, e.g. via [CSV import](./DEVICES_BULK_EDITING.md). > For versions prior to `v25.6.7` upgrade to version `v25.5.24` first (`docker pull ghcr.io/jokob-sk/netalertx:25.5.24`) as later versions don't support a full upgrade. Alternatively, devices and settings can be migrated manually, e.g. via [CSV import](./DEVICES_BULK_EDITING.md).
This guide outlines approaches for updating Docker containers, usually when upgrading to a newer version of NetAlertX. Each method offers different benefits depending on the situation. Here are the methods: This guide outlines approaches for updating Docker containers, usually when upgrading to a newer version of NetAlertX. Each method offers different benefits depending on the situation. Here are the methods:
- Manual: Direct commands to stop, remove, and rebuild containers. - Manual: Direct commands to stop, remove, and rebuild containers.
- Dockcheck: Semi-automated with more control, suited for bulk updates. - Dockcheck: Semi-automated with more control, suited for bulk updates.
- Watchtower: Fully automated, runs continuously to check and update containers. - Watchtower: Fully automated, runs continuously to check and update containers.
- Portainer: Manual with UI.
You can choose any approach that fits your workflow. You can choose any approach that fits your workflow.
@@ -107,10 +108,42 @@ docker run -d \
``` ```
## 4. Portainer controlled image
This assumes you're using Portainer to manage Docker (or Docker Swarm) and want to pull the latest version of an image and redeploy the container.
> [!NOTE]
> * Portainer does **not auto-update** containers. For automation, use **Watchtower** or similar tools.
> * Make sure you have the [persistent volumes mounted or backups ready](BACKUPS.md) before recreating.
### 4.1 Steps to Update an Image in Portainer (Standalone Docker)
1. **Login to Portainer.**
2. Go to **"Containers"** in the left sidebar.
3. Find the container you want to update, click its name.
4. Click **"Recreate"** (top right).
5. **Tick**: _Pull latest image_ (this ensures Portainer fetches the newest version from Docker Hub or your registry).
6. Click **"Recreate"** again.
7. Wait for the container to be stopped, removed, and recreated with the updated image.
### 4.2 For Docker Swarm Services
If you're using Docker Swarm (under **"Stacks"** or **"Services"**):
1. Go to **"Stacks"**.
2. Select the stack managing the container.
3. Click **"Editor"** (or "Update the Stack").
4. Add a version tag or use `:latest` if your image tag is `latest` (not recommended for production).
5. Click **"Update the Stack"**. ⚠ Portainer will not pull the new image unless the tag changes OR the stack is forced to recreate.
6. If image tag hasn't changed, go to **"Services"**, find the service, and click **"Force Update"**.
## Summary ## Summary
- Manual: Ideal for individual or critical updates. | Method | Type | Pros | Cons |
- Dockcheck: Suitable for controlled, mass updates. |------------|--------------|----------------------------------|------------------------------|
- Watchtower: Fully automated, best for continuous deployment setups. | Manual | CLI | Full control, no dependencies | Tedious for many containers |
| Dockcheck | CLI Script | Great for batch updates | Needs setup, semi-automated |
| Watchtower | Daemonized | Fully automated updates | Less control, version drift |
| Portainer | UI | Easy via web interface | No auto-updates |
These approaches allow you to maintain flexibility in how you update Docker containers, depending on the urgency and scale of the update. These approaches allow you to maintain flexibility in how you update Docker containers, depending on the urgency and scale of the update.

View File

@@ -63,68 +63,8 @@ You can include multiple actions that should execute once the conditions are met
# Examples # Examples
Below you can find a couple of configuration examples. You can find a couple of configuration examples in [Workflow Examples](WORKFLOW_EXAMPLES.md).
![Workflow example](./img/WORKFLOWS/workflows.png)
---
## Example 1: Assign Device to Network Node Based on IP
This workflow assigns newly added devices with IP addresses in the `192.168.1.*` range to the device with the MAC address `6c:6d:6d:6c:6c:6c`.
### Trigger:
- **Object Type**: `Devices`
- **Event Type**: `insert`
### Conditions:
- **Logic**: `AND`
- `Field`: `devLastIP`
- `Operator`: `contains`
- `Value`: `192.168.1.`
This condition ensures that the workflow only applies to devices with an IP address in the `192.168.1.*` range.
### Actions:
- **Action Type**: `update_field`
- **Field**: `devNetworkNode`
- **Value**: `6c:6d:6d:6c:6c:6c`
---
## Example 2: Mark Device as Not New and Delete If from Google Vendor
This workflow automates the process of marking Google devices as not new and deleting them if they meet the criteria.
### Trigger:
- **Object Type**: `Devices`
- **Event Type**: `update`
### Conditions:
- **Logic**: `AND`
- `Field`: `devVendor`
- `Operator`: `contains`
- `Value`: `Google`
This condition checks if the device's vendor is `Google`.
- **Logic**: `AND`
- `Field`: `devIsNew`
- `Operator`: `equals`
- `Value`: `1`
This ensures the workflow applies only to new devices.
### Actions:
1. **Action Type**: `update_field`
- **Field**: `devIsNew`
- **Value**: `0`
This action marks the device as no longer new.
2. **Action Type**: `delete_device`
This action deletes the device after it is marked as not new.
> [!TIP] > [!TIP]
> Share your workflows in [Discord](https://discord.com/invite/NczTUTWyRr) or [GitHub Discussions](https://github.com/jokob-sk/NetAlertX/discussions). > Share your workflows in [Discord](https://discord.com/invite/NczTUTWyRr) or [GitHub Discussions](https://github.com/jokob-sk/NetAlertX/discussions).

View File

@@ -2,7 +2,7 @@
Workflows in NetAlertX automate actions based on real-time events and conditions. Below are practical examples that demonstrate how to build automation using triggers, conditions, and actions. Workflows in NetAlertX automate actions based on real-time events and conditions. Below are practical examples that demonstrate how to build automation using triggers, conditions, and actions.
## Un-archive devices if detected online ## Example 1: Un-archive devices if detected online
This workflow automatically unarchives a device if it was previously archived but has now been detected as online. This workflow automatically unarchives a device if it was previously archived but has now been detected as online.
@@ -57,4 +57,129 @@ Sometimes devices are manually archived (e.g., no longer expected on the network
### ✅ Result ### ✅ Result
Whenever a previously archived device shows up during a network scan, it will be automatically unarchived — allowing it to reappear in your device lists and dashboards. Whenever a previously archived device shows up during a network scan, it will be automatically unarchived — allowing it to reappear in your device lists and dashboards.
Here is your updated version of **Example 2** and **Example 3**, fully aligned with the format and structure of **Example 1** for consistency and professionalism:
---
## Example 2: Assign Device to Network Node Based on IP
This workflow assigns newly added devices with IP addresses in the `192.168.1.*` range to a specific network node with MAC address `6c:6d:6d:6c:6c:6c`.
### 📋 Use Case
When new devices join your network, assigning them to the correct network node is important for accurate topology and grouping. This workflow ensures devices in a specific subnet are automatically linked to the intended node.
### ⚙️ Workflow Configuration
```json
{
"name": "Assign Device to Network Node Based on IP",
"trigger": {
"object_type": "Devices",
"event_type": "insert"
},
"conditions": [
{
"logic": "AND",
"conditions": [
{
"field": "devLastIP",
"operator": "contains",
"value": "192.168.1."
}
]
}
],
"actions": [
{
"type": "update_field",
"field": "devNetworkNode",
"value": "6c:6d:6d:6c:6c:6c"
}
],
"enabled": "Yes"
}
```
### 🔍 Explanation
* **Trigger**: Activates when a new device is added.
* **Condition**:
* `devLastIP` contains `192.168.1.` (matches subnet).
* **Action**:
* Sets `devNetworkNode` to the specified MAC address.
### ✅ Result
New devices with IPs in the `192.168.1.*` subnet are automatically assigned to the correct network node, streamlining device organization and reducing manual work.
---
## Example 3: Mark Device as Not New and Delete If from Google Vendor
This workflow automatically marks newly detected Google devices as not new and deletes them immediately.
### 📋 Use Case
You may want to automatically clear out newly detected Google devices (such as Chromecast or Google Home) if theyre not needed in your device database. This workflow handles that clean-up automatically.
### ⚙️ Workflow Configuration
```json
{
"name": "Mark Device as Not New and Delete If from Google Vendor",
"trigger": {
"object_type": "Devices",
"event_type": "update"
},
"conditions": [
{
"logic": "AND",
"conditions": [
{
"field": "devVendor",
"operator": "contains",
"value": "Google"
},
{
"field": "devIsNew",
"operator": "equals",
"value": "1"
}
]
}
],
"actions": [
{
"type": "update_field",
"field": "devIsNew",
"value": "0"
},
{
"type": "delete_device"
}
],
"enabled": "Yes"
}
```
### 🔍 Explanation
* **Trigger**: Runs on device updates.
* **Conditions**:
* Vendor contains `Google`.
* Device is marked as new (`devIsNew` is `1`).
* **Actions**:
1. Set `devIsNew` to `0` (mark as not new).
2. Delete the device.
### ✅ Result
Any newly detected Google devices are cleaned up instantly — first marked as not new, then deleted — helping you avoid clutter in your device records.

View File

@@ -1399,7 +1399,8 @@ input[readonly] {
cursor: -webkit-grab; cursor: -webkit-grab;
} }
.select2-container--default .select2-selection--multiple .select2-selection__choice #settingsPage .select2-container--default .select2-selection--multiple .select2-selection__choice,
#maintenancePage .select2-container--default .select2-selection--multiple .select2-selection__choice
{ {
background-color:#258744 !important; background-color:#258744 !important;
} }
@@ -1413,6 +1414,15 @@ input[readonly] {
background-color:#606060 !important; background-color:#606060 !important;
} }
.select2-container--default .select2-selection--multiple,
.select2-container--default .select2-selection--single
{
border-radius: 0px !important;
border-color: #d2d6de !important;
min-height: 42px;
}
.helpIconSmallTopRight{ .helpIconSmallTopRight{
position: absolute; position: absolute;
font-size: x-small; font-size: x-small;
@@ -1539,6 +1549,93 @@ input[readonly] {
display: none; display: none;
} }
#deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice a
{
color: #FFF0E0;
}
#deviceDetailsEdit .iconPreview svg
{
height: 14px;
}
#deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice
{
height: 20px;
}
#deviceDetailsEdit .select2-container--disabled
{
background-color: #606060;
}
#deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice span
{
font-size: 14px;
}
#deviceDetailsEdit .select2-selection
{
width: initial;
display: inline-block;
min-height: 42px;
}
/* Remove the default Select2 chevron (the down arrow) */
.select2-container .select2-selection__arrow b {
display: none !important;
}
/* Add custom icon */
.select2-container .select2-selection__arrow::after {
font-family: 'Font Awesome 6 Free';
content: "\f078"; /* fa-chevron-down */
font-weight: 700;
position: absolute;
top: 75%;
left: 30%;
transform: translate(-50%, -50%);
pointer-events: none;
}
#deviceDetailsEdit .form-control
{
min-height: 42px;
}
.select2-selection--single .custom-chip
{
margin-top: 11px;
display: flex;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single, .select2-selection .select2-selection--single
{
padding: 0px 0px;
min-height: 42px;
}
/* .select2-container--default .select2-selection--single .select2-selection__rendered, */
.select2-container--default .select2-selection--single
{
/* color:initial !important; */
background-color:initial !important;
}
#deviceDetailsEdit .select2-container
{
width: 100% !important;
}
#deviceDetailsEdit .select2-container .selection
{
width: 100% !important;
display: inline-grid;
}
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
/* MODAL popups */ /* MODAL popups */
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
@@ -1620,6 +1717,43 @@ input[readonly] {
} }
#hover-box
{
background-color: #ffffff;;
}
#hover-box .iconPreview
{
padding: 0px;
display: flex;
}
#hover-box .devName
{
font-size: larger;
display: contents;
}
#hover-box b
{
float: left;
}
#hover-box .line
{
float: left;
width: 100%;
}
#hover-box span
{
float: right;
text-overflow: ellipsis;
overflow: hidden;
display: block;
max-width: 200px;
}
#networkTree .netCollapse #networkTree .netCollapse
{ {
position: absolute; position: absolute;
@@ -1629,7 +1763,7 @@ input[readonly] {
#networkTree .highlightedNode #networkTree .highlightedNode
{ {
/* border: solid; */ /* border: solid; */
border-color:cyan; border-color:#3c8dbc;
} }
#networkTree .netStatus-Off-line i, #networkTree .netStatus-Off-line i,
#networkTree .netStatus-Off-line svg #networkTree .netStatus-Off-line svg
@@ -1735,7 +1869,7 @@ input[readonly] {
.plugin-content #tabs-content-location .plugin-content #tabs-content-location
{ {
margin: 0px; margin: 0px;
/* padding-top: 0; */ padding-top: 0;
} }
.integrations-plugins .content .integrations-plugins .content

View File

@@ -722,7 +722,7 @@ input[type="password"]::-webkit-caps-lock-indicator {
margin-left: 0px; margin-left: 0px;
} }
.small-box:hover .icon { .small-box:hover .icon {
font-size: 3.74em; font-size: 3em;
} }
.small-box .icon { .small-box .icon {
top: 0.01em; top: 0.01em;

View File

@@ -724,7 +724,7 @@
margin-left: 0px; margin-left: 0px;
} }
.small-box:hover .icon { .small-box:hover .icon {
font-size: 3.74em; font-size: 3em;
} }
.small-box .icon { .small-box .icon {
top: 0.01em; top: 0.01em;
@@ -734,6 +734,35 @@
background-color: #000 !important; background-color: #000 !important;
} }
.select2-container--default .select2-selection--single {
color: initial !important;
background-color: #353c42 !important;
}
/* Chevron color */
.select2-container .select2-selection__arrow::after {
color: #bec5cb;
}
/* Chevron color */
.select2-selection .select2-selection--single {
color: #bec5cb;
}
.select2-container--default .select2-selection--multiple, .select2-container--default .select2-selection--single {
border-color: #3d444b !important;
}
.select2-container--default .select2-selection--single .select2-selection__rendered .custom-chip
{
color: #bec5cb;
}
#hover-box
{
background-color: #353c42 !important;
}
} }
.callout code { .callout code {

View File

@@ -5,7 +5,7 @@
?> ?>
<div class="row"> <div class="row" id="deviceDetailsEdit">
<div class="box-body form-horizontal"> <div class="box-body form-horizontal">
<form id="edit-form"> <form id="edit-form">
<!-- Form fields will be appended here --> <!-- Form fields will be appended here -->
@@ -85,7 +85,7 @@
}, },
// Group for event and alert settings // Group for event and alert settings
DevDetail_EveandAl_Title: { DevDetail_EveandAl_Title: {
data: ["devAlertEvents", "devAlertDown", "devSkipRepeated"], data: ["devAlertEvents", "devAlertDown", "devSkipRepeated", "devReqNicsOnline", "devChildrenNicsDynamic"],
docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/NOTIFICATIONS.md", docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/NOTIFICATIONS.md",
iconClass: "fa fa-bell", iconClass: "fa fa-bell",
inputGroupClasses: "field-group alert-group col-lg-4 col-sm-6 col-xs-12", inputGroupClasses: "field-group alert-group col-lg-4 col-sm-6 col-xs-12",
@@ -94,7 +94,7 @@
}, },
// Group for network details // Group for network details
DevDetail_MainInfo_Network_Title: { DevDetail_MainInfo_Network_Title: {
data: ["devParentMAC", "devParentPort", "devSSID", "devSite", "devSyncHubNode"], data: ["devParentMAC", "devParentRelType", "devParentPort", "devSSID", "devSite", "devSyncHubNode"],
docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md", docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md",
iconClass: "fa fa-network-wired", iconClass: "fa fa-network-wired",
inputGroupClasses: "field-group network-group col-lg-4 col-sm-6 col-xs-12", inputGroupClasses: "field-group network-group col-lg-4 col-sm-6 col-xs-12",
@@ -119,6 +119,15 @@
labelClasses: "col-sm-4 col-xs-12 control-label", labelClasses: "col-sm-4 col-xs-12 control-label",
inputClasses: "col-sm-8 col-xs-12 input-group" inputClasses: "col-sm-8 col-xs-12 input-group"
}, },
// Group for Children.
DevDetail_Children_Title: {
data: ["devChildrenDynamic"],
docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/CUSTOM_PROPERTIES.md",
iconClass: "fa fa-list",
inputGroupClasses: "field-group cutprop-group col-lg-12 col-sm-12 col-xs-12",
labelClasses: "col-sm-12 col-xs-12 control-label",
inputClasses: "col-sm-12 col-xs-12 input-group"
},
// Group for Custom properties. // Group for Custom properties.
DevDetail_CustomProperties_Title: { DevDetail_CustomProperties_Title: {
data: ["devCustomProps"], data: ["devCustomProps"],
@@ -167,6 +176,7 @@
// Get the field data (replace 'NEWDEV_' prefix from the key) // Get the field data (replace 'NEWDEV_' prefix from the key)
fieldData = deviceData[setting.setKey.replace('NEWDEV_', '')] fieldData = deviceData[setting.setKey.replace('NEWDEV_', '')]
fieldData = fieldData == null ? "" : fieldData; fieldData = fieldData == null ? "" : fieldData;
fieldOptionsOverride = null;
// console.log(setting.setKey); // console.log(setting.setKey);
// console.log(fieldData); // console.log(fieldData);
@@ -208,6 +218,20 @@
</span>`; </span>`;
} }
// handle devChildrenDynamic or NEWDEV_devChildrenNicsDynamic - selected values and options are the same
if (
Array.isArray(fieldData) &&
(setting.setKey == "NEWDEV_devChildrenDynamic" ||
setting.setKey == "NEWDEV_devChildrenNicsDynamic" )
)
{
fieldDataNew = []
fieldData.forEach(child => {
fieldDataNew.push(child.devMac)
})
fieldData = fieldDataNew;
fieldOptionsOverride = fieldDataNew;
}
// Generate the input field HTML // Generate the input field HTML
const inputFormHtml = `<div class="form-group col-xs-12"> const inputFormHtml = `<div class="form-group col-xs-12">
@@ -219,7 +243,7 @@
</i> </i>
</label> </label>
<div class="${obj.inputClasses}"> <div class="${obj.inputClasses}">
${generateFormHtml(settingsData, setting, fieldData.toString(), null, null)} ${generateFormHtml(settingsData, setting, fieldData.toString(), fieldOptionsOverride, null)}
${inlineControl} ${inlineControl}
</div> </div>
</div>`; </div>`;
@@ -364,7 +388,7 @@
mac: $('#NEWDEV_devMac').val(), mac: $('#NEWDEV_devMac').val(),
name: encodeURIComponent($('#NEWDEV_devName').val().replace(/'/g, "")), name: encodeURIComponent($('#NEWDEV_devName').val().replace(/'/g, "")),
owner: encodeURIComponent($('#NEWDEV_devOwner').val().replace(/'/g, "")), owner: encodeURIComponent($('#NEWDEV_devOwner').val().replace(/'/g, "")),
type: $('#NEWDEV_devType').val().replace(/'/g, ""), type: $('#NEWDEV_devType').val().replace(/'/g, ""),
vendor: encodeURIComponent($('#NEWDEV_devVendor').val().replace(/'/g, "")), vendor: encodeURIComponent($('#NEWDEV_devVendor').val().replace(/'/g, "")),
icon: encodeURIComponent($('#NEWDEV_devIcon').val()), icon: encodeURIComponent($('#NEWDEV_devIcon').val()),
favorite: ($('#NEWDEV_devFavorite')[0].checked * 1), favorite: ($('#NEWDEV_devFavorite')[0].checked * 1),
@@ -380,6 +404,8 @@
alertevents: ($('#NEWDEV_devAlertEvents')[0].checked * 1), alertevents: ($('#NEWDEV_devAlertEvents')[0].checked * 1),
alertdown: ($('#NEWDEV_devAlertDown')[0].checked * 1), alertdown: ($('#NEWDEV_devAlertDown')[0].checked * 1),
skiprepeated: $('#NEWDEV_devSkipRepeated').val().split(' ')[0], skiprepeated: $('#NEWDEV_devSkipRepeated').val().split(' ')[0],
relType: $('#NEWDEV_devParentRelType').val().replace(/'/g, ""),
reqNics: ($('#NEWDEV_devReqNicsOnline')[0].checked * 1),
newdevice: ($('#NEWDEV_devIsNew')[0].checked * 1), newdevice: ($('#NEWDEV_devIsNew')[0].checked * 1),
archived: ($('#NEWDEV_devIsArchived')[0].checked * 1), archived: ($('#NEWDEV_devIsArchived')[0].checked * 1),
devFirstConnection: ($('#NEWDEV_devFirstConnection').val()), devFirstConnection: ($('#NEWDEV_devFirstConnection').val()),

View File

@@ -14,7 +14,7 @@
<?= lang("DevDetail_Tab_Tools_Internet_Info_Description") ?> <?= lang("DevDetail_Tab_Tools_Internet_Info_Description") ?>
</h5> </h5>
<br> <br>
<div style="width:100%; text-align: center; margin-bottom: 50px;"> <div style="width:100%; text-align: center;">
<button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto;" onclick="internetinfo()"> <button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto;" onclick="internetinfo()">
<?= lang("DevDetail_Tab_Tools_Internet_Info_Start") ?></button> <?= lang("DevDetail_Tab_Tools_Internet_Info_Start") ?></button>
<br> <br>
@@ -33,13 +33,13 @@
<?= lang("DevDetail_Copy_Device_Tooltip") ?> <?= lang("DevDetail_Copy_Device_Tooltip") ?>
</h5> </h5>
<br> <br>
<div style="width:100%; text-align: center; margin-bottom: 50px;"> <div style="width:100%; text-align: center;">
<select class="form-control" <select class="form-control"
title="<?= lang('DevDetail_Copy_Device_Tooltip');?>" title="<?= lang('DevDetail_Copy_Device_Tooltip');?>"
id="txtCopyFromDevice" > id="txtCopyFromDevice" >
<option value="lemp_loading" id="lemp_loading">Loading</option> <option value="lemp_loading" id="lemp_loading">Loading</option>
</select> </select>
<button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto;" onclick="()"> <button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto; margin-top:10px;" onclick="copyFromDevice()">
<?= lang("BackDevDetail_Copy_Title") ?></button> <?= lang("BackDevDetail_Copy_Title") ?></button>
<br> <br>
</div> </div>
@@ -56,7 +56,7 @@
<?= lang("DevDetail_Tools_WOL_noti_text") ?> <?= lang("DevDetail_Tools_WOL_noti_text") ?>
</h5> </h5>
<br> <br>
<div style="width:100%; text-align: center; margin-bottom: 50px;"> <div style="width:100%; text-align: center;">
<button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto;" onclick="wakeonlan()"> <button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto;" onclick="wakeonlan()">
<?= lang("DevDetail_Tools_WOL_noti") ?></button> <?= lang("DevDetail_Tools_WOL_noti") ?></button>
<br> <br>
@@ -74,7 +74,7 @@
<?= lang("DevDetail_button_DeleteEvents_Warning") ?> <?= lang("DevDetail_button_DeleteEvents_Warning") ?>
</h5> </h5>
<br> <br>
<div style="width:100%; text-align: center; margin-bottom: 50px;"> <div style="width:100%; text-align: center;">
<button type="button" <button type="button"
class="btn btn-default pa-btn pa-btn-delete" class="btn btn-default pa-btn pa-btn-delete"
style="margin-left:0px;" style="margin-left:0px;"
@@ -94,7 +94,7 @@
<?= lang("DevDetail_CustomProps_reset_info") ?> <?= lang("DevDetail_CustomProps_reset_info") ?>
</h5> </h5>
<br> <br>
<div style="width:100%; text-align: center; margin-bottom: 50px;"> <div style="width:100%; text-align: center;">
<button type="button" <button type="button"
class="btn btn-default pa-btn pa-btn-delete" class="btn btn-default pa-btn pa-btn-delete"
style="margin-left:0px;" style="margin-left:0px;"
@@ -116,7 +116,7 @@
<?= lang("DevDetail_Tab_Tools_Speedtest_Description") ?> <?= lang("DevDetail_Tab_Tools_Speedtest_Description") ?>
</h5> </h5>
<br> <br>
<div style="width:100%; text-align: center; margin-bottom: 50px;"> <div style="width:100%; text-align: center;">
<button type="button" id="speedtestcli" class="btn btn-primary pa-btn" style="margin: auto;" onclick="speedtestcli()"> <button type="button" id="speedtestcli" class="btn btn-primary pa-btn" style="margin: auto;" onclick="speedtestcli()">
<?= lang("DevDetail_Tab_Tools_Speedtest_Start") ?></button> <?= lang("DevDetail_Tab_Tools_Speedtest_Start") ?></button>
<br> <br>
@@ -133,7 +133,7 @@
<h5 class=""> <h5 class="">
<?= lang("DevDetail_Tab_Tools_Traceroute_Description") ?> <?= lang("DevDetail_Tab_Tools_Traceroute_Description") ?>
</h5> </h5>
<div style="width:100%; text-align: center; margin-bottom: 50px;"> <div style="width:100%; text-align: center;">
<button type="button" id="traceroute" class="btn btn-primary pa-btn" style="margin: auto;" onclick="traceroute()"> <button type="button" id="traceroute" class="btn btn-primary pa-btn" style="margin: auto;" onclick="traceroute()">
<?= lang("DevDetail_Tab_Tools_Traceroute_Start") ?> <?= lang("DevDetail_Tab_Tools_Traceroute_Start") ?>
</button> </button>
@@ -151,7 +151,7 @@
<h5 class=""> <h5 class="">
<?= lang("DevDetail_Tab_Tools_Nslookup_Description") ?> <?= lang("DevDetail_Tab_Tools_Nslookup_Description") ?>
</h5> </h5>
<div style="width:100%; text-align: center; margin-bottom: 50px;"> <div style="width:100%; text-align: center;">
<button type="button" id="nslookup" class="btn btn-primary pa-btn" style="margin: auto;" onclick="nslookup()"> <button type="button" id="nslookup" class="btn btn-primary pa-btn" style="margin: auto;" onclick="nslookup()">
<?= lang("DevDetail_Tab_Tools_Nslookup_Start") ?> <?= lang("DevDetail_Tab_Tools_Nslookup_Start") ?>
</button> </button>

View File

@@ -539,7 +539,9 @@ function mapColumnIndexToFieldName(index, tableColumnVisible) {
"devPresentLastScan", "devPresentLastScan",
"devAlertDown", "devAlertDown",
"devCustomProps", "devCustomProps",
"devFQDN" "devFQDN",
"devParentRelType",
"devReqNicsOnline"
]; ];
// console.log("OrderBy: " + columnNames[tableColumnOrder[index]]); // console.log("OrderBy: " + columnNames[tableColumnOrder[index]]);
@@ -650,6 +652,8 @@ function initializeDatatable (status) {
devIpLong devIpLong
devCustomProps devCustomProps
devFQDN devFQDN
devParentRelType
devReqNicsOnline
} }
count count
} }
@@ -725,7 +729,9 @@ function initializeDatatable (status) {
device.devPresentLastScan || "", device.devPresentLastScan || "",
device.devAlertDown || "", device.devAlertDown || "",
device.devCustomProps || "", device.devCustomProps || "",
device.devFQDN || "" device.devFQDN || "",
device.devParentRelType || "",
device.devReqNicsOnline || 0
]; ];
const newRow = []; const newRow = [];
@@ -893,25 +899,14 @@ function initializeDatatable (status) {
tmp_devPresentLastScan = rowData[mapIndx(24)] tmp_devPresentLastScan = rowData[mapIndx(24)]
tmp_devAlertDown = rowData[mapIndx(25)] tmp_devAlertDown = rowData[mapIndx(25)]
if (tmp_devPresentLastScan == 1) const badge = getStatusBadgeParts(
{ rowData[mapIndx(24)], // tmp_devPresentLastScan
css = "green text-white statusOnline" rowData[mapIndx(25)], // tmp_devAlertDown
icon = '<i class="fa-solid fa-plug"></i>' rowData[mapIndx(11)], // MAC
} else if (tmp_devPresentLastScan != 1 && tmp_devAlertDown == 1) cellData // optional text
{ );
css = "red text-white statusDown"
icon = '<i class="fa-solid fa-triangle-exclamation"></i>'
} else if(tmp_devPresentLastScan != 1)
{
css = "gray text-white statusOffline"
icon = '<i class="fa-solid fa-xmark"></i>'
} else
{
css = "gray text-white statusUnknown"
icon = '<i class="fa-solid fa-question"></i>'
}
$(td).html (`<a href="deviceDetails.php?mac=${rowData[mapIndx(11)]}" class="badge bg-${css}">${icon} ${cellData.replace('-', '')}</a>`); $(td).html (`<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.text}</a>`);
} }, } },
], ],

View File

@@ -363,8 +363,6 @@ function removeAllOptions(element) {
function selectAll(element) { function selectAll(element) {
settingsChanged(); settingsChanged();
// Get the <select> element with the class 'deviceSelector'
// var selectElement = $('.deviceSelector select');
var selectElement = $(`#${$(element).attr("my-input-to")}`); var selectElement = $(`#${$(element).attr("my-input-to")}`);
// Iterate over each option within the select element // Iterate over each option within the select element
@@ -381,8 +379,6 @@ function selectAll(element) {
// UN-Select All // UN-Select All
function unselectAll(element) { function unselectAll(element) {
settingsChanged(); settingsChanged();
// Get the <select> element with the class 'deviceSelector'
// var selectElement = $('.deviceSelector select');
var selectElement = $(`#${$(element).attr("my-input-to")}`); var selectElement = $(`#${$(element).attr("my-input-to")}`);
// Iterate over each option within the select element // Iterate over each option within the select element
@@ -399,8 +395,7 @@ function unselectAll(element) {
// Trigger change to open up the dropdown filed // Trigger change to open up the dropdown filed
function selectChange(element) { function selectChange(element) {
settingsChanged(); settingsChanged();
// Get the <select> element with the class 'deviceSelector'
// var selectElement = $('.deviceSelector select');
var selectElement = $(`#${$(element).attr("my-input-to")}`); var selectElement = $(`#${$(element).attr("my-input-to")}`);
selectElement.parent().find("input").focus().click(); selectElement.parent().find("input").focus().click();
@@ -624,6 +619,7 @@ function generateOptionsOrSetOptions(
// console.log( setKey); // console.log( setKey);
// NOTE {value} options to replace with a setting or SQL value are handled in the cacheSettings() function // NOTE {value} options to replace with a setting or SQL value are handled in the cacheSettings() function
// obj.push({ id: item, name: item })
options = arrayToObject(createArray(overrideOptions ? overrideOptions : getSettingOptions(setKey))) options = arrayToObject(createArray(overrideOptions ? overrideOptions : getSettingOptions(setKey)))
@@ -689,6 +685,13 @@ function reverseTransformers(val, transformers) {
// retrieve string // retrieve string
val = getString(val); val = getString(val);
break; break;
case "deviceChip":
mac = val // value is mac
val = `${getDevDataByMac(mac, "devName")}`
break;
case "deviceRelType":
val = val; // nothing to do
break;
default: default:
console.warn(`Unknown transformer: ${transformer}`); console.warn(`Unknown transformer: ${transformer}`);
} }
@@ -822,13 +825,14 @@ function arrayToObject(array) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Processor to generate options // Processor to generate options
// options - available options
// valuesArray - values = selected options
function generateOptions(options, valuesArray, targetField, transformers, placeholder) { function generateOptions(options, valuesArray, targetField, transformers, placeholder) {
var optionsHtml = ""; var optionsHtml = "";
resultArray = [] resultArray = []
selectedArray = [] selectedArray = []
cssClass = "" cssClass = ""
// determine if options or values are used in the listing // determine if options or values are used in the listing
if (valuesArray.length > 0 && options.length > 0){ if (valuesArray.length > 0 && options.length > 0){
@@ -847,7 +851,6 @@ function generateOptions(options, valuesArray, targetField, transformers, placeh
// dropdown -> options only (value == 1 STRING not ARRAY) // dropdown -> options only (value == 1 STRING not ARRAY)
resultArray = options; resultArray = options;
} }
// Create a map to track the index of each item in valuesArray // Create a map to track the index of each item in valuesArray
const orderMap = new Map(valuesArray.map((item, index) => [item, index])); const orderMap = new Map(valuesArray.map((item, index) => [item, index]));
@@ -1007,10 +1010,12 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori
class="form-control ${addCss} ${cssClasses}" class="form-control ${addCss} ${cssClasses}"
name="${setKey}" name="${setKey}"
id="${setKey}" id="${setKey}"
my-transformers=${transformers}
my-customparams="${customParams}" my-customparams="${customParams}"
my-customid="${customId}" my-customid="${customId}"
my-originalSetKey="${originalSetKey}" my-originalSetKey="${originalSetKey}"
${multi}> ${multi}
${readOnly ? "disabled" : ""}>
<option value="" id="${setKey + "_temp_"}"></option> <option value="" id="${setKey + "_temp_"}"></option>
</select>`; </select>`;
@@ -1188,22 +1193,46 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori
const eventsList = createArray(set['setEvents']); const eventsList = createArray(set['setEvents']);
// inline buttons events // inline buttons events
if (eventsList.length > 0) {
eventsList.forEach(event => {
let eventIcon = "fa-play";
if (eventsList.length > 0) { switch (event) {
eventsList.forEach(event => { case "add_icon":
case "add_option":
eventIcon = "fa-square-plus";
break;
case "copy_icons":
eventIcon = "fa-copy";
break;
case "go_to_device":
eventIcon = "fa-square-up-right";
break;
case "go_to_node":
eventIcon = "fa-network-wired";
break;
case "run":
eventIcon = "fa-play";
break;
case "test":
eventIcon = "fa-vial-circle-check";
break;
default:
eventIcon = "fa-play";
break;
}
eventsHtml += `<span class="input-group-addon pointer" eventsHtml += `<span class="input-group-addon pointer"
id="${`${event}_${setKey}`}" id="${`${event}_${setKey}`}"
data-myparam-setkey="${setKey}" data-myparam-setkey="${setKey}"
data-myparam="${setKey}" data-myparam="${setKey}"
data-myparam-plugin="${setKey.split('_')[0] || ''}" data-myparam-plugin="${setKey.split('_')[0] || ''}"
data-myevent="${event}" data-myevent="${event}"
onclick="execute_settingEvent(this)"> onclick="execute_settingEvent(this)">
<i title="${getString(event + "_event_tooltip")}" class="fa ${getString(event + "_event_icon")}"></i> <i title="${getString(event + "_event_tooltip")}" class="fa ${eventIcon}"></i>
</span>`; </span>`;
}); });
} }
// Combine and return the final HTML // Combine and return the final HTML
return inputHtml + eventsHtml; return inputHtml + eventsHtml;

View File

@@ -128,9 +128,6 @@ function getRandomBytes(elem, length) {
targetElement.val(formattedHex); targetElement.val(formattedHex);
} }
// ---------------------------------------------- // ----------------------------------------------
// Updates the icon preview // Updates the icon preview
function updateAllIconPreviews() { function updateAllIconPreviews() {
@@ -342,6 +339,7 @@ function execute_settingEvent(element) {
feSetKey = $(element).attr('data-myparam-setkey'); feSetKey = $(element).attr('data-myparam-setkey');
feParam = $(element).attr('data-myparam'); feParam = $(element).attr('data-myparam');
feSourceId = $(element).attr('id'); feSourceId = $(element).attr('id');
feValue = $("#"+feSetKey).val();
if (["test", "run"].includes(feEvent)) { if (["test", "run"].includes(feEvent)) {
// Calls a backend function to add a front-end event (specified by the attributes 'data-myevent' and 'data-myparam-plugin' on the passed element) to an execution queue // Calls a backend function to add a front-end event (specified by the attributes 'data-myevent' and 'data-myparam-plugin' on the passed element) to an execution queue
@@ -394,9 +392,12 @@ function execute_settingEvent(element) {
getString('Gen_Okay'), getString('Gen_Okay'),
'overwriteIconType' 'overwriteIconType'
); );
} else if (["go_to_node"].includes(feEvent)) { } else if (["go_to_device"].includes(feEvent)) {
goToNetworkNode('NEWDEV_devParentMAC'); goToDevice(feValue);
} else if (["go_to_node"].includes(feEvent)) {
goToNetworkNode(feValue);
} else { } else {
console.warn(`🔺Not implemented: ${feEvent}`) console.warn(`🔺Not implemented: ${feEvent}`)
@@ -408,12 +409,24 @@ function execute_settingEvent(element) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Go to the correct network node in the Network section // Go to the correct network node in the Network section
function goToNetworkNode(dropdownId) function goToNetworkNode(mac)
{ {
setCache('activeNetworkTab', $('#'+dropdownId).val().replaceAll(":","_")+'_id'); setCache('activeNetworkTab', mac.replaceAll(":","_")+'_id');
window.location.href = './network.php'; window.location.href = './network.php';
} }
// -----------------------------------------------------------------------------
// Go to the device
function goToDevice(mac, newtab = false) {
const url = './deviceDetails.php?mac=' + encodeURIComponent(mac);
if (newtab) {
window.open(url, '_blank');
} else {
window.location.href = url;
}
}
// -------------------------------------------------------- // --------------------------------------------------------
@@ -574,19 +587,9 @@ function showIconSelection() {
} }
// "Device_TableHead_Owner",
// "Device_TableHead_Type",
// "Device_TableHead_Group",
// "Device_TableHead_Status",
// "Device_TableHead_Location",
// "Device_TableHead_Vendor",
// "Device_TableHead_SyncHubNodeName",
// "Device_TableHead_NetworkSite",
// "Device_TableHead_SSID",
// "Device_TableHead_SourcePlugin"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Get teh correct db column code name based on table header title string // Get the correct db column code name based on table header title string
function getColumnNameFromLangString(headStringKey) { function getColumnNameFromLangString(headStringKey) {
columnNameMap = { columnNameMap = {
"Device_TableHead_Name": "devName", "Device_TableHead_Name": "devName",
@@ -621,6 +624,87 @@ function getColumnNameFromLangString(headStringKey) {
return columnNameMap[headStringKey] || ""; return columnNameMap[headStringKey] || "";
} }
//--------------------------------------------------------------
// Generating the device status chip
function getStatusBadgeParts(tmp_devPresentLastScan, tmp_devAlertDown, macAddress, statusText = '') {
let css = 'bg-gray text-white statusUnknown';
let icon = '<i class="fa-solid fa-question"></i>';
let status = 'unknown';
let cssText = '';
if (tmp_devPresentLastScan == 1) {
css = 'bg-green text-white statusOnline';
cssText = 'text-green';
icon = '<i class="fa-solid fa-plug"></i>';
status = 'online';
} else if (tmp_devAlertDown == 1) {
css = 'bg-red text-white statusDown';
cssText = 'text-red';
icon = '<i class="fa-solid fa-triangle-exclamation"></i>';
status = 'down';
} else if (tmp_devPresentLastScan != 1) {
css = 'bg-gray text-white statusOffline';
cssText = 'text-gray50';
icon = '<i class="fa-solid fa-xmark"></i>';
status = 'offline';
}
const cleanedText = statusText.replace(/-/g, '');
const url = `deviceDetails.php?mac=${encodeURIComponent(macAddress)}`;
return {
cssClass: css,
cssText: cssText,
iconHtml: icon,
mac: macAddress,
text: cleanedText,
status: status,
url: url
};
}
//--------------------------------------------------------------
// Getting the color and css class for device relationships
function getRelationshipConf(relType) {
let cssClass = '';
let color = '';
// --color-aqua: #00c0ef;
// --color-blue: #0060df;
// --color-green: #00a65a;
// --color-yellow: #f39c12;
// --color-red: #dd4b39;
switch (relType) {
case "child":
color = "#f39c12"; // yellow
cssClass = "text-yellow";
break;
case "nic":
color = "#dd4b39"; // red
cssClass = "text-red";
break;
case "virtual":
color = "#0060df"; // blue
cssClass = "text-blue";
break;
case "logical":
color = "#00a65a"; // green
cssClass = "text-green";
break;
default:
color = "#5B5B66"; // grey
cssClass = "text-light-grey";
break;
}
return {
cssClass: cssClass,
color: color
};
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// initialize // initialize
@@ -636,15 +720,88 @@ function initSelect2() {
{ {
// prepare HTML DOM before initializing the frotend // prepare HTML DOM before initializing the frotend
initDeviceSelectors(devicesListAll_JSON) initDeviceSelectors(devicesListAll_JSON)
// -------------------------------------------------------- // --------------------------------------------------------
//Initialize Select2 Elements and make them sortable //Initialize Select2 Elements and make them sortable
$(function () { $(function () {
// Iterate over each Select2 dropdown // Iterate over each Select2 dropdown
$('.select2').each(function() { $('.select2').each(function() {
var selectEl = $(this).select2(); // handle Device chips, if my-transformers="deviceChip"
if($(this).attr("my-transformers") == "deviceChip")
{
var selectEl = $(this).select2({
templateSelection: function (data, container) {
if (!data.id) return data.text; // default for placeholder etc.
const device = getDevDataByMac(data.id);
const badge = getStatusBadgeParts(
device.devPresentLastScan,
device.devAlertDown,
device.devMac
)
$(container).addClass(badge.cssClass);
// Custom HTML
const html = $(`
<a href="${badge.url}" target="_blank">
<span class="custom-chip hover-node-info"
data-name="${device.devName}"
data-ip="${device.devLastIP}"
data-mac="${device.devMac}"
data-vendor="${device.devVendor}"
data-lastseen="${device.devLastConnection}"
data-relationship="${device.devParentRelType}"
data-status="${device.devStatus}"
data-present="${device.devPresentLastScan}"
data-alert="${device.devAlertDown}"
data-icon="${device.devIcon}"
>
<span class="iconPreview">${atob(device.devIcon)}</span>
${data.text}
<span>
(${badge.iconHtml})
</span
</span>
</a>
`);
return html;
},
escapeMarkup: function (m) {
return m; // Allow HTML
}
});
} else if($(this).attr("my-transformers") == "deviceRelType") // handling dropdown for relationships
{
var selectEl = $(this).select2({
minimumResultsForSearch: Infinity,
templateSelection: function (data, container) {
if (!data.id) return data.text; // default for placeholder etc.
const relConf = getRelationshipConf(data.text);
// Custom HTML
const html = $(`
<span class="custom-chip ${relConf.cssClass}" >
${data.text}
</span>
`);
return html;
},
escapeMarkup: function (m) {
return m; // Allow HTML
}
});
} else // default handling - default template
{
var selectEl = $(this).select2();
}
// Apply sortable functionality to the dropdown's dropdown-container // Apply sortable functionality to the dropdown's dropdown-container
selectEl.next().children().children().children().sortable({ selectEl.next().children().children().children().sortable({
@@ -675,13 +832,131 @@ function initSelect2() {
} }
} }
// ------------------------------------------
// Display device info on hover (attach only once)
function initHoverNodeInfo() {
if ($('#hover-box').length === 0) {
$('<div id="hover-box"></div>').appendTo('body').hide().css({
position: 'absolute',
zIndex: 9999,
border: '1px solid #ccc',
borderRadius: '8px',
padding: '10px',
boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
minWidth: '200px',
maxWidth: '300px',
fontSize: '14px',
pointerEvents: 'none',
backgroundColor: '#fff'
});
}
// check if handlers already attached to prevent flickering
if (initHoverNodeInfo._handlersAttached) return;
initHoverNodeInfo._handlersAttached = true;
let hoverTimeout = null;
let lastTarget = null;
// remove title as it's replaced by the hover-box
$(document).on('mouseover', '.hover-node-info', function () {
this.removeAttribute('title');
$(this).attr("title", ""); // remove title as it's replaced by the hover-box
});
$(document).on('mouseenter', '.hover-node-info', function (e) {
const $el = $(this);
lastTarget = this;
// use timeout to prevent a quick hover and exit toi flash a card when navigating to a target node with your mouse
clearTimeout(hoverTimeout);
hoverTimeout = setTimeout(() => {
if (lastTarget !== this) return;
const icon = $el.data('icon');
const name = $el.data('name') || 'Unknown';
const ip = $el.data('ip') || 'N/A';
const mac = $el.data('mac') || 'N/A';
const vendor = $el.data('vendor') || 'Unknown';
const lastseen = $el.data('lastseen') || 'Unknown';
const relationship = $el.data('relationship') || 'Unknown';
const badge = getStatusBadgeParts( $el.data('present'), $el.data('alert'), $el.data('mac'))
const status =`<span class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.status}</span>`
const html = `
<div>
<b> <div class="iconPreview">${atob(icon)}</div> </b><b class="devName"> ${name}</b><br>
</div>
<hr/>
<div class="line">
<b>Status:</b> <span>${status}</span><br>
</div>
<div class="line">
<b>IP:</b> <span>${ip}</span><br>
</div>
<div class="line">
<b>MAC:</b> <span>${mac}</span><br>
</div>
<div class="line">
<b>Vendor:</b> <span>${vendor}</span><br>
</div>
<div class="line">
<b>Last seen:</b> <span>${lastseen}</span><br>
</div>
<div class="line">
<b>Relationship:</b> <span class="${getRelationshipConf(relationship).cssClass}">${relationship}</span>
</div>
`;
$('#hover-box').html(html).fadeIn(150);
}, 300);
});
$(document).on('mousemove', '.hover-node-info', function (e) {
const hoverBox = $('#hover-box');
const boxWidth = hoverBox.outerWidth();
const boxHeight = hoverBox.outerHeight();
const padding = 15;
const winWidth = $(window).width();
const winHeight = $(window).height();
let left = e.pageX + padding;
let top = e.pageY + padding;
// Position leftward if close to right edge
if (e.pageX + boxWidth + padding > winWidth) {
left = e.pageX - boxWidth - padding;
}
// Position upward if close to bottom edge
if (e.pageY + boxHeight + padding > winHeight) {
top = e.pageY - boxHeight - padding;
}
hoverBox.css({ top: top + 'px', left: left + 'px' });
});
$(document).on('mouseleave', '.hover-node-info', function () {
clearTimeout(hoverTimeout);
lastTarget = null;
$('#hover-box').fadeOut(100);
});
}
// init functions after dom loaded // init functions after dom loaded
window.addEventListener("load", function() { window.addEventListener("load", function() {
// try to initialize // try to initialize
setTimeout(() => { setTimeout(() => {
initSelect2() initSelect2();
initHoverNodeInfo();
// initializeiCheck(); // initializeiCheck();
}, 1000); }, 500);
}); });

View File

@@ -77,7 +77,7 @@
settingsData = res["data"]; settingsData = res["data"];
excludedColumns = ["NEWDEV_devMac", "NEWDEV_devFirstConnection", "NEWDEV_devLastConnection", "NEWDEV_devLastNotification", "NEWDEV_devScan", "NEWDEV_devPresentLastScan", "NEWDEV_devCustomProps" ] excludedColumns = ["NEWDEV_devMac", "NEWDEV_devFirstConnection", "NEWDEV_devLastConnection", "NEWDEV_devLastNotification", "NEWDEV_devScan", "NEWDEV_devPresentLastScan", "NEWDEV_devCustomProps", "NEWDEV_devChildrenNicsDynamic", "NEWDEV_devChildrenDynamic" ]
const relevantColumns = settingsData.filter(set => const relevantColumns = settingsData.filter(set =>
set.setGroup === "NEWDEV" && set.setGroup === "NEWDEV" &&

View File

@@ -28,7 +28,7 @@
<section class="content networkTable"> <section class="content networkTable">
<?php <?php
// Create top-level node (network devices) tabs // Create top-level node (network devices) tabs
function createDeviceTabs($node_mac, $node_name, $node_status, $node_type, $node_ports_count, $icon, $activetab) { function createDeviceTabs($node_mac, $node_name, $node_status, $node_type, $node_ports_count, $icon, $node_alert, $activetab) {
// prepare string with port number in brackets if available // prepare string with port number in brackets if available
$str_port = ""; $str_port = "";
@@ -37,18 +37,22 @@
} }
// online/offline status circle (red/green) // online/offline status circle (red/green)
$icon_style = ""; $icon_class = "";
if($node_status == 0) // 1 means online, 0 offline if($node_status == 0 && $node_alert == 1) // 1 means online, 0 offline
{ {
$icon_style = "style=\"color:var(--color-red);\""; $icon_class = " text-red";
} } elseif ($node_status == 1) {
$icon_class = " text-green";
} elseif ($node_status == 0) {
$icon_class = " text-gray50";
}
$decoded_icon = base64_decode($icon); $decoded_icon = base64_decode($icon);
$idFromMac = str_replace(":", "_", $node_mac); $idFromMac = str_replace(":", "_", $node_mac);
$str_tab_header = '<li class="networkNodeTabHeaders '.$activetab.' " > $str_tab_header = '<li class="networkNodeTabHeaders '.$activetab.' " >
<a href="#'.$idFromMac.'" data-mytabmac="'.$node_mac.'" id="'.$idFromMac.'_id" data-toggle="tab" title="'.$node_name.' ">' // _id is added so it doesn't conflict with AdminLTE tab behavior <a href="#'.$idFromMac.'" data-mytabmac="'.$node_mac.'" id="'.$idFromMac.'_id" data-toggle="tab" title="'.$node_name.' ">' // _id is added so it doesn't conflict with AdminLTE tab behavior
.'<div class="icon" '.$icon_style.'>'.$decoded_icon.' </div> <span class="node-name">'.$node_name.'</span>' .$str_port. .'<div class="icon '.$icon_class.'" >'.$decoded_icon.' </div> <span class="node-name">'.$node_name.'</span>' .$str_port.
'</a> '</a>
</li>'; </li>';
@@ -269,7 +273,7 @@
$networkDeviceTypes = str_replace("]", "",(str_replace("[", "", getSettingValue("NETWORK_DEVICE_TYPES")))); $networkDeviceTypes = str_replace("]", "",(str_replace("[", "", getSettingValue("NETWORK_DEVICE_TYPES"))));
$sql = "SELECT node_name, node_mac, online, node_type, node_ports_count, parent_mac, node_icon $sql = "SELECT node_name, node_mac, online, node_type, node_ports_count, parent_mac, node_icon, node_alert
FROM FROM
( (
SELECT a.devName as node_name, SELECT a.devName as node_name,
@@ -277,7 +281,8 @@
a.devPresentLastScan as online, a.devPresentLastScan as online,
a.devType as node_type, a.devType as node_type,
a.devParentMAC as parent_mac, a.devParentMAC as parent_mac,
a.devIcon as node_icon a.devIcon as node_icon,
a.devAlertDown as node_alert
FROM Devices a FROM Devices a
WHERE a.devType in (".$networkDeviceTypes.") WHERE a.devType in (".$networkDeviceTypes.")
AND devIsArchived = 0 AND devIsArchived = 0
@@ -304,7 +309,9 @@
'node_type' => $row['node_type'], 'node_type' => $row['node_type'],
'parent_mac' => $row['parent_mac'], 'parent_mac' => $row['parent_mac'],
'node_icon' => $row['node_icon'], 'node_icon' => $row['node_icon'],
'node_ports_count' => $row['node_ports_count']); 'node_ports_count' => $row['node_ports_count'],
'node_alert' => $row['node_alert']
);
} }
// Control no rows // Control no rows
@@ -323,6 +330,7 @@
$row['node_type'], $row['node_type'],
$row['node_ports_count'], $row['node_ports_count'],
$row['node_icon'], $row['node_icon'],
$row['node_alert'],
$activetab); $activetab);
$activetab = ""; // reset active tab indicator, only the first tab is active $activetab = ""; // reset active tab indicator, only the first tab is active
@@ -463,12 +471,19 @@
<script src="lib/treeviz/bundle.js"></script> <script src="lib/treeviz/bundle.js"></script>
<script defer> <script defer>
$.get('php/server/devices.php?action=getDevicesList&status=all&forceDefaultOrder', function(data) { const apiUrl = `php/server/dbHelper.php?action=read&rawSql=${btoa(encodeURIComponent(
`select *, CASE WHEN devAlertDown !=0 AND devPresentLastScan=0 THEN "Down"
WHEN devPresentLastScan=1 THEN "On-line"
ELSE "Off-line" END as devStatus
from Devices`))}`;
$.get(apiUrl, function (data) {
rawData = JSON.parse (data) rawData = JSON.parse (data)
console.log(rawData);
if(rawData["data"] == "") if(rawData["data"] == "")
{ {
showModalOK (getString('Gen_Warning'), getString('Network_NoDevices')) showModalOK (getString('Gen_Warning'), getString('Network_NoDevices'))
@@ -478,38 +493,26 @@
orderTopologyBy = createArray(getSetting("UI_TOPOLOGY_ORDER")) orderTopologyBy = createArray(getSetting("UI_TOPOLOGY_ORDER"))
devicesListnew = rawData["data"].map(item => { devicesListnew = rawData.sort((a, b) => {
return {
"name": item[0],
"type": item[2],
"icon": item[3],
"mac": item[11],
"parentMac": item[14],
"rowid": item[13],
"status": item[10],
"childrenQty": item[15],
"port": item[18]
};
}).sort((a, b) => {
// Helper to safely parse port into an integer; invalid ports become Infinity for sorting // Helper to safely parse port into an integer; invalid ports become Infinity for sorting
const parsePort = (port) => { const parsePort = (devParentPort) => {
const parsed = parseInt(port, 10); const parsed = parseInt(devParentPort, 10);
return isNaN(parsed) ? Infinity : parsed; return isNaN(parsed) ? Infinity : parsed;
}; };
switch (orderTopologyBy[0]) { switch (orderTopologyBy[0]) {
case "Name": case "Name":
// First sort by name alphabetically // First sort by name alphabetically
const nameCompare = a.name.localeCompare(b.name); const nameCompare = a.devName.localeCompare(b.devName);
if (nameCompare !== 0) { if (nameCompare !== 0) {
return nameCompare; return nameCompare;
} }
// If names are the same, sort by port numerically // If names are the same, sort by port numerically
return parsePort(a.port) - parsePort(b.port); return parsePort(a.devParentPort) - parsePort(b.devParentPort);
case "Port": case "Port":
// Sort by port numerically // Sort by port numerically
return parsePort(a.port) - parsePort(b.port); return parsePort(a.devParentPort) - parsePort(b.devParentPort);
default: default:
// Default: Sort by rowid (as a fallback) // Default: Sort by rowid (as a fallback)
@@ -544,9 +547,6 @@ var hiddenMacs = []; // hidden children
var hiddenChildren = []; var hiddenChildren = [];
var deviceListGlobal = null; var deviceListGlobal = null;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Recursively get children nodes and build a tree // Recursively get children nodes and build a tree
function getChildren(node, list, path, visited = []) function getChildren(node, list, path, visited = [])
@@ -554,23 +554,23 @@ function getChildren(node, list, path, visited = [])
var children = []; var children = [];
// Check for infinite recursion by seeing if the node has been visited before // Check for infinite recursion by seeing if the node has been visited before
if (visited.includes(node.mac.toLowerCase())) { if (visited.includes(node.devMac.toLowerCase())) {
console.error("Infinite recursion detected at node:", node.mac); console.error("Infinite recursion detected at node:", node.devMac);
write_notification("[ERROR] ⚠ Infinite recursion detected. You probably have assigned the Internet node to another children node or to itself. Please open a new issue on GitHub and describe how you did it.", 'interrupt') write_notification("[ERROR] ⚠ Infinite recursion detected. You probably have assigned the Internet node to another children node or to itself. Please open a new issue on GitHub and describe how you did it.", 'interrupt')
return { error: "Infinite recursion detected", node: node.mac }; return { error: "Infinite recursion detected", node: node.devMac };
} }
// Add current node to visited list // Add current node to visited list
visited.push(node.mac.toLowerCase()); visited.push(node.devMac.toLowerCase());
// Loop through all items to find children of the current node // Loop through all items to find children of the current node
for (var i in list) { for (var i in list) {
if (list[i].parentMac.toLowerCase() == node.mac.toLowerCase() && !hiddenMacs.includes(list[i].parentMac)) { if (list[i].devParentMAC.toLowerCase() == node.devMac.toLowerCase() && !hiddenMacs.includes(list[i].devParentMAC)) {
visibleNodesCount++; visibleNodesCount++;
// Process children recursively, passing a copy of the visited list // Process children recursively, passing a copy of the visited list
children.push(getChildren(list[i], list, path + ((path == "") ? "" : '|') + list[i].parentMac, visited)); children.push(getChildren(list[i], list, path + ((path == "") ? "" : '|') + list[i].devParentMAC, visited));
} }
} }
@@ -582,17 +582,23 @@ function getChildren(node, list, path, visited = [])
} }
return { return {
name: node.name, name: node.devName,
path: path, path: path,
mac: node.mac, mac: node.devMac,
port: node.port, port: node.devParentPort,
id: node.mac, id: node.devMac,
parentMac: node.parentMac, parentMac: node.devParentMAC,
icon: node.icon, icon: node.devIcon,
type: node.type, type: node.devType,
status: node.status, vendor: node.devVendor,
hasChildren: children.length > 0 || hiddenMacs.includes(node.mac), lastseen: node.devLastConnection,
hiddenChildren: hiddenMacs.includes(node.mac), ip: node.devLastIP,
status: node.devStatus,
presentLastScan: node.devPresentLastScan,
alertDown: node.devAlertDown,
hasChildren: children.length > 0 || hiddenMacs.includes(node.devMac),
relType: node.devParentRelType,
hiddenChildren: hiddenMacs.includes(node.devMac),
qty: children.length, qty: children.length,
children: children children: children
}; };
@@ -603,63 +609,13 @@ function getHierarchy()
{ {
for(i in deviceListGlobal) for(i in deviceListGlobal)
{ {
if(deviceListGlobal[i].mac == 'Internet') if(deviceListGlobal[i].devMac == 'Internet')
{ {
return (getChildren(deviceListGlobal[i], deviceListGlobal, '')) return (getChildren(deviceListGlobal[i], deviceListGlobal, ''))
break; break;
} }
} }
} }
// ---------------------------------------------------------------------------
function getFlatData() {
var result = [];
var leafNodesCount = 0;
var parentNodesCount = 0;
var visibleNodesCount = 0;
for (let node of deviceListGlobal) {
let path = "";
let childrenCount = 0;
// count children of this node
for (let nodeTmp of deviceListGlobal) {
if (nodeTmp.parentMac === node.mac) {
childrenCount++;
}
}
// store parent and leaf node count
if (childrenCount === 0) {
leafNodesCount++;
} else {
parentNodesCount++;
}
if (!hiddenMacs.includes(node.parentMac)) {
if (!((node.parentMac == "") && node.mac != "Internet")) { // skip leaf nodes without father that are not the root
visibleNodesCount++;
result.push({
name: node.name,
path: path,
mac: node.mac, // Replacing "mac" with "id"
parentMac: node.mac == "Internet" ? "" : node.parentMac, // Replacing "parentMac" with "father"
port: node.port,
icon: node.icon,
type: node.type,
status: node.status,
hasChildren: childrenCount > 0 || hiddenMacs.includes(node.mac),
hiddenChildren: hiddenMacs.includes(node.mac),
qty: childrenCount,
});
}
}
}
return result;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
function toggleSubTree(parentMac, treePath) function toggleSubTree(parentMac, treePath)
@@ -697,6 +653,7 @@ function handleNodeClick(el)
{ {
const targetTabMAC = $(el).attr("data-mytreemacmain"); const targetTabMAC = $(el).attr("data-mytreemacmain");
// handle network node
var targetTab = $(`a[data-mytabmac="${targetTabMAC}"]`); var targetTab = $(`a[data-mytabmac="${targetTabMAC}"]`);
if (targetTab.length) { if (targetTab.length) {
@@ -707,6 +664,10 @@ function handleNodeClick(el)
$('html, body').animate({ $('html, body').animate({
scrollTop: targetTab.offset().top - 50 scrollTop: targetTab.offset().top - 50
}, 500); // Adjust the duration as needed }, 500); // Adjust the duration as needed
} else
{
// handle regular device - open in new tab
goToDevice($(el).data("mac"), true)
} }
} }
@@ -739,7 +700,7 @@ function initTree(myHierarchy)
emSize = pxToEm((treeAreaHeight/(leafNodesCount)).toFixed(2)); emSize = pxToEm((treeAreaHeight/(leafNodesCount)).toFixed(2));
let screenWidthEm = pxToEm($('.networkTable').width()); let screenWidthEm = pxToEm($('.networkTable').width()-15);
// init the drawing area size // init the drawing area size
$("#networkTree").attr('style', `height:${treeAreaHeight}px; width:${emToPx(screenWidthEm)}px`) $("#networkTree").attr('style', `height:${treeAreaHeight}px; width:${emToPx(screenWidthEm)}px`)
@@ -802,17 +763,26 @@ function initTree(myHierarchy)
highlightedCss = nodeData.data.mac == selectedNodeMac ? highlightedCss = nodeData.data.mac == selectedNodeMac ?
" highlightedNode" : ""; " highlightedNode" : "";
// css indicating online/offline status const badgeConf = getStatusBadgeParts(nodeData.data.presentLastScan, nodeData.data.alertDown, nodeData.data.mac, statusText = '')
statusCss = ` netStatus-${nodeData.data.status}`;
return result = `<div return result = `<div
class="node-inner box ${nodeData.data.hasChildren ? "pointer":""} ${statusCss} ${highlightedCss}" class="node-inner hover-node-info box pointer ${highlightedCss}"
data-mytreemacmain="${nodeData.data.mac}" data-mytreemacmain="${nodeData.data.mac}"
style="height:${nodeHeightPx}px;font-size:${nodeHeightPx-5}px;" style="height:${nodeHeightPx}px;font-size:${nodeHeightPx-5}px;"
onclick="handleNodeClick(this)" onclick="handleNodeClick(this)"
data-name="${nodeData.data.name}"
data-ip="${nodeData.data.ip}"
data-mac="${nodeData.data.mac}"
data-vendor="${nodeData.data.vendor}"
data-lastseen="${nodeData.data.lastseen}"
data-relationship="${nodeData.data.relType}"
data-status="${nodeData.data.status}"
data-present="${nodeData.data.presentLastScan}"
data-alert="${nodeData.data.alertDown}"
data-icon="${nodeData.data.icon}"
> >
<div class="netNodeText"> <div class="netNodeText">
<strong>${devicePort} ${deviceIcon} <strong><span class="${badgeConf.cssText}">${devicePort} ${deviceIcon}</span>
<span class="spanNetworkTree anonymizeDev" style="width:${nodeWidthPx-50}px">${nodeData.data.name}</span> <span class="spanNetworkTree anonymizeDev" style="width:${nodeWidthPx-50}px">${nodeData.data.name}</span>
</strong> </strong>
</div> </div>
@@ -827,12 +797,18 @@ function initTree(myHierarchy)
isHorizontal : true, isHorizontal : true,
hasZoom: true, hasZoom: true,
hasPan: true, hasPan: true,
marginLeft: '15', marginLeft: '10',
marginRight: '10',
idKey: "mac", idKey: "mac",
hasFlatData: false, hasFlatData: false,
relationnalField: "children", relationnalField: "children",
linkWidth: (nodeData) => 3, linkWidth: (nodeData) => 3,
linkColor: (nodeData) => "#ffcc80" linkColor: (nodeData) => {
relConf = getRelationshipConf(nodeData.data.relType)
return relConf.color;
}
// onNodeClick: (nodeData) => handleNodeClick(nodeData), // onNodeClick: (nodeData) => handleNodeClick(nodeData),
}); });

View File

@@ -63,7 +63,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
} }
if (isset ($_REQUEST['rawSql'])) { if (isset ($_REQUEST['rawSql'])) {
$rawSql = urldecode(base64_decode($_REQUEST['rawSql'])); $rawSql = urldecode(base64_decode($_REQUEST['rawSql'])); // base64 encoded SQL
} }
if (isset ($_REQUEST['dbtable'])) { if (isset ($_REQUEST['dbtable'])) {

View File

@@ -26,7 +26,7 @@
if (isset ($_REQUEST['action']) && !empty ($_REQUEST['action'])) { if (isset ($_REQUEST['action']) && !empty ($_REQUEST['action'])) {
$action = $_REQUEST['action']; $action = $_REQUEST['action'];
switch ($action) { switch ($action) {
case 'getServerDeviceData': getServerDeviceData(); break; case 'getServerDeviceData': getServerDeviceData(); break;
case 'setDeviceData': setDeviceData(); break; case 'setDeviceData': setDeviceData(); break;
case 'deleteDevice': deleteDevice(); break; case 'deleteDevice': deleteDevice(); break;
case 'deleteAllWithEmptyMACs': deleteAllWithEmptyMACs(); break; case 'deleteAllWithEmptyMACs': deleteAllWithEmptyMACs(); break;
@@ -45,8 +45,7 @@
case 'ImportCSV': ImportCSV(); break; case 'ImportCSV': ImportCSV(); break;
case 'getDevicesTotals': getDevicesTotals(); break; case 'getDevicesTotals': getDevicesTotals(); break;
case 'getDevicesList': getDevicesList(); break; case 'getDevicesListCalendar': getDevicesListCalendar(); break; //todo: slowly deprecate this
case 'getDevicesListCalendar': getDevicesListCalendar(); break;
case 'updateNetworkLeaf': updateNetworkLeaf(); break; case 'updateNetworkLeaf': updateNetworkLeaf(); break;
case 'overwriteIconType': overwriteIconType(); break; case 'overwriteIconType': overwriteIconType(); break;
@@ -92,6 +91,8 @@ function getServerDeviceData() {
"devLogEvents" => 0, "devLogEvents" => 0,
"devAlertEvents" => 0, "devAlertEvents" => 0,
"devAlertDown" => 0, "devAlertDown" => 0,
"devParentRelType" => "default",
"devReqNicsOnline" => 0,
"devSkipRepeated" => 0, "devSkipRepeated" => 0,
"devLastNotification" => "", "devLastNotification" => "",
"devPresentLastScan" => 0, "devPresentLastScan" => 0,
@@ -139,6 +140,30 @@ function getServerDeviceData() {
$deviceData['devIsRandomMAC'] = isRandomMAC($mac); $deviceData['devIsRandomMAC'] = isRandomMAC($mac);
// devChildrenDynamic
$sql = 'SELECT rowid, * FROM Devices WHERE devParentMAC = "' . $mac . '" order by devPresentLastScan DESC';
$result = $db->query($sql);
$children = [];
if ($result) {
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$children[] = $row;
}
}
$deviceData['devChildrenDynamic'] = $children;
// devChildrenNicsDynamic
$sql = 'SELECT rowid, * FROM Devices WHERE devParentMAC = "' . $mac . '" and devParentRelType = "nic" order by devPresentLastScan DESC';
$result = $db->query($sql);
$childrenNics = [];
if ($result) {
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$childrenNics[] = $row;
}
}
$deviceData['devChildrenNicsDynamic'] = $childrenNics;
// Count Totals // Count Totals
$condition = ' WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate; $condition = ' WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate;
@@ -211,6 +236,8 @@ function setDeviceData() {
$scancycle = quotes($_POST['scancycle']); $scancycle = quotes($_POST['scancycle']);
$alertevents = quotes($_POST['alertevents']); $alertevents = quotes($_POST['alertevents']);
$alertdown = quotes($_POST['alertdown']); $alertdown = quotes($_POST['alertdown']);
$relType = quotes($_POST['relType']);
$reqNics = quotes($_POST['reqNics']);
$skiprepeated = quotes($_POST['skiprepeated']); $skiprepeated = quotes($_POST['skiprepeated']);
$newdevice = quotes($_POST['newdevice']); $newdevice = quotes($_POST['newdevice']);
$archived = quotes($_POST['archived']); $archived = quotes($_POST['archived']);
@@ -242,6 +269,8 @@ function setDeviceData() {
devScan = '$scancycle', devScan = '$scancycle',
devAlertEvents = '$alertevents', devAlertEvents = '$alertevents',
devAlertDown = '$alertdown', devAlertDown = '$alertdown',
devParentRelType = '$relType',
devReqNicsOnline = '$reqNics',
devSkipRepeated = '$skiprepeated', devSkipRepeated = '$skiprepeated',
devIsNew = '$newdevice', devIsNew = '$newdevice',
devIsArchived = '$archived', devIsArchived = '$archived',
@@ -267,6 +296,8 @@ function setDeviceData() {
devScan, devScan,
devAlertEvents, devAlertEvents,
devAlertDown, devAlertDown,
devParentRelType,
devReqNicsOnline,
devSkipRepeated, devSkipRepeated,
devIsNew, devIsNew,
devIsArchived, devIsArchived,
@@ -295,6 +326,8 @@ function setDeviceData() {
'$scancycle', '$scancycle',
'$alertevents', '$alertevents',
'$alertdown', '$alertdown',
'$relType',
'$reqNics',
'$skiprepeated', '$skiprepeated',
'$newdevice', '$newdevice',
'$archived', '$archived',
@@ -744,143 +777,6 @@ function getDevicesTotals() {
echo ($resultJSON); echo ($resultJSON);
} }
//------------------------------------------------------------------------------
// Query the List of devices in a determined Status
//------------------------------------------------------------------------------
function getDevicesList() {
global $db;
$forceDefaultOrder = FALSE;
if (isset ($_REQUEST['forceDefaultOrder']) )
{
$forceDefaultOrder = TRUE;
}
// This object is used to map from the old order ( second parameter, first number) to the new mapping, that is represented by the 3rd parameter (Second number)
$columnOrderMapping = array(
array("devName", 0, 0),
array("devOwner", 1, 1),
array("devType", 2, 2),
array("devIcon", 3, 3),
array("devFavorite", 4, 4),
array("devGroup", 5, 5),
array("devFirstConnection", 6, 6),
array("devLastConnection", 7, 7),
array("devLastIP", 8, 8),
array("devMac", 9, 9),
array("devStatus", 10, 10),
array("devMac_full", 11, 11),
array("devLastIP_orderable", 12, 12),
array("rowid", 13, 13),
array("devParentMAC", 14, 14),
array("connected_devices", 15, 15),
array("devLocation", 16, 16),
array("devVendor", 17, 17),
array("devParentPort", 18, 18),
array("devGUID", 19, 19),
array("devSyncHubNode", 20, 20),
array("devSite", 21, 21),
array("devSSID", 22, 22),
array("devSourcePlugin", 23, 23)
);
if($forceDefaultOrder == FALSE)
{
// get device columns order
$sql = 'SELECT par_Value FROM Parameters where par_ID = "Front_Devices_Columns_Order"';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
if($row != NULL && count($row) == 1)
{
// ordered columns setting from the maintenance page
$orderedColumns = createArray($row[0]);
// init ordered columns
for($i = 0; $i < count($orderedColumns); $i++) {
$columnOrderMapping[$i][2] = $orderedColumns[$i];
}
}
}
// SQL
$condition = getDeviceCondition ($_REQUEST['status']);
$sql = 'SELECT * FROM (
SELECT rowid, *, CASE
WHEN t1.devAlertDown !=0 AND t1.devPresentLastScan=0 THEN "Down"
WHEN t1.devIsNew=1 THEN "New"
WHEN t1.devPresentLastScan=1 THEN "On-line"
ELSE "Off-line" END AS devStatus
FROM Devices t1 '.$condition.') t3
LEFT JOIN
(
SELECT devParentMAC as devParentMAC_t2, devMac as devMac_t2,
count() as connected_devices
FROM Devices b
WHERE b.devParentMAC NOT NULL group by b.devParentMAC
) t2
ON (t3.devMac = t2.devParentMAC_t2);';
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$defaultOrder = array (
$row['devName'],
$row['devOwner'],
handleNull($row['devType']),
handleNull($row['devIcon'], "PGkgY2xhc3M9J2ZhIGZhLWxhcHRvcCc+PC9pPg=="), // laptop icon
$row['devFavorite'],
$row['devGroup'],
// ----
formatDate ($row['devFirstConnection']),
formatDate ($row['devLastConnection']),
$row['devLastIP'],
( isRandomMAC($row['devMac']) ),
$row['devStatus'],
$row['devMac'], // MAC (hidden)
formatIPlong ($row['devLastIP']), // IP orderable
$row['rowid'], // Rowid (hidden)
handleNull($row['devParentMAC']),
handleNull($row['connected_devices']),
handleNull($row['devLocation']),
handleNull($row['devVendor']),
handleNull($row['devParentPort']),
handleNull($row['devGUID']),
handleNull($row['devSyncHubNode']),
handleNull($row['devSite']),
handleNull($row['devSSID']),
handleNull($row['devSourcePlugin'])
);
$newOrder = array();
// reorder columns based on user settings
for($index = 0; $index < count($columnOrderMapping); $index++)
{
array_push($newOrder, $defaultOrder[$columnOrderMapping[$index][2]]);
}
$tableData['data'][] = $newOrder;
}
// Control no rows
if (empty($tableData['data'])) {
$tableData['data'] = '';
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Determine if Random MAC // Determine if Random MAC
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@@ -587,7 +587,9 @@ function getDevicesColumns(){
"devSSID", "devSSID",
"devSourcePlugin", "devSourcePlugin",
"devCustomProps", "devCustomProps",
"devFQDN" "devFQDN",
"devParentRelType",
"devReqNicsOnline"
]; ];
return $columns; return $columns;

View File

@@ -136,7 +136,7 @@
<!-- ----------------------------------------------------------------------- --> <!-- ----------------------------------------------------------------------- -->
<!-- Layout Boxed Yellow --> <!-- Layout Boxed Yellow -->
<body class="hold-transition fixed <?php echo $pia_skin_selected;?> sidebar-mini" onLoad="update_servertime();" > <body class="hold-transition fixed <?php echo $pia_skin_selected;?> theme-<?php echo $UI_THEME;?> sidebar-mini" onLoad="update_servertime();" >
<!-- Site wrapper --> <!-- Site wrapper -->
<div class="wrapper"> <div class="wrapper">
@@ -297,6 +297,9 @@
<li> <li>
<a href="devices.php#archived" onclick="forceLoadUrl('devices.php#archived')" > <?= lang("Device_Shortcut_Archived");?> </a> <a href="devices.php#archived" onclick="forceLoadUrl('devices.php#archived')" > <?= lang("Device_Shortcut_Archived");?> </a>
</li> </li>
<li>
<a href="devices.php#all" onclick="forceLoadUrl('devices.php#all_nodes')" > <?= lang("Device_Shortcut_AllNodes");?> </a>
</li>
</ul> </ul>
</li> </li>

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "مدة الاحتفاظ بالأحداث", "DAYS_TO_KEEP_EVENTS_name": "مدة الاحتفاظ بالأحداث",
"DISCOVER_PLUGINS_description": "اكتشاف المكونات الإضافية المتاحة", "DISCOVER_PLUGINS_description": "اكتشاف المكونات الإضافية المتاحة",
"DISCOVER_PLUGINS_name": "اكتشاف المكونات الإضافية", "DISCOVER_PLUGINS_name": "اكتشاف المكونات الإضافية",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "نسخ التفاصيل من الجهاز", "DevDetail_Copy_Device_Title": "نسخ التفاصيل من الجهاز",
"DevDetail_Copy_Device_Tooltip": "انسخ تفاصيل الجهاز من القائمة المنسدلة. سيتم استبدال كل ما في هذه الصفحة.", "DevDetail_Copy_Device_Tooltip": "انسخ تفاصيل الجهاز من القائمة المنسدلة. سيتم استبدال كل ما في هذه الصفحة.",
"DevDetail_CustomProperties_Title": "الخصائص المخصصة", "DevDetail_CustomProperties_Title": "الخصائص المخصصة",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "النوع", "DevDetail_MainInfo_Type": "النوع",
"DevDetail_MainInfo_Vendor": "المصنع", "DevDetail_MainInfo_Vendor": "المصنع",
"DevDetail_MainInfo_mac": "عنوان MAC", "DevDetail_MainInfo_mac": "عنوان MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "انقر للذهاب إلى عقدة الشبكة", "DevDetail_Network_Node_hover": "انقر للذهاب إلى عقدة الشبكة",
"DevDetail_Network_Port_hover": "منفذ الشبكة", "DevDetail_Network_Port_hover": "منفذ الشبكة",
"DevDetail_Nmap_Scans": "عمليات فحص Nmap", "DevDetail_Nmap_Scans": "عمليات فحص Nmap",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "تعديل الأجهزة المحددة", "Device_MultiEdit_Tooltip": "تعديل الأجهزة المحددة",
"Device_Searchbox": "بحث", "Device_Searchbox": "بحث",
"Device_Shortcut_AllDevices": "جميع الأجهزة", "Device_Shortcut_AllDevices": "جميع الأجهزة",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "مؤرشف", "Device_Shortcut_Archived": "مؤرشف",
"Device_Shortcut_Connected": "متصل", "Device_Shortcut_Connected": "متصل",
"Device_Shortcut_Devices": "الأجهزة", "Device_Shortcut_Devices": "الأجهزة",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "الاسم", "Device_TableHead_Name": "الاسم",
"Device_TableHead_NetworkSite": "موقع الشبكة", "Device_TableHead_NetworkSite": "موقع الشبكة",
"Device_TableHead_Owner": "المالك", "Device_TableHead_Owner": "المالك",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "عنوان MAC الأصل", "Device_TableHead_Parent_MAC": "عنوان MAC الأصل",
"Device_TableHead_Port": "المنفذ", "Device_TableHead_Port": "المنفذ",
"Device_TableHead_PresentLastScan": "موجود في آخر فحص", "Device_TableHead_PresentLastScan": "موجود في آخر فحص",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "معرف الصف", "Device_TableHead_RowID": "معرف الصف",
"Device_TableHead_Rowid": "معرف الصف", "Device_TableHead_Rowid": "معرف الصف",
"Device_TableHead_SSID": "معرف الشبكة اللاسلكية", "Device_TableHead_SSID": "معرف الشبكة اللاسلكية",
@@ -704,23 +709,18 @@
"WF_Trigger": "المشغل", "WF_Trigger": "المشغل",
"WF_Trigger_event_type": "نوع حدث المشغل", "WF_Trigger_event_type": "نوع حدث المشغل",
"WF_Trigger_type": "نوع المشغل", "WF_Trigger_type": "نوع المشغل",
"add_icon_event_icon": "أيقونة إضافة أيقونة",
"add_icon_event_tooltip": "تلميح إضافة أيقونة", "add_icon_event_tooltip": "تلميح إضافة أيقونة",
"add_option_event_icon": "أيقونة إضافة خيار",
"add_option_event_tooltip": "تلميح إضافة خيار", "add_option_event_tooltip": "تلميح إضافة خيار",
"copy_icons_event_icon": "أيقونة نسخ الأيقونات",
"copy_icons_event_tooltip": "تلميح نسخ الأيقونات", "copy_icons_event_tooltip": "تلميح نسخ الأيقونات",
"devices_old": "الأجهزة القديمة", "devices_old": "الأجهزة القديمة",
"general_event_description": "وصف الحدث العام", "general_event_description": "وصف الحدث العام",
"general_event_title": "عنوان الحدث العام", "general_event_title": "عنوان الحدث العام",
"go_to_node_event_icon": "أيقونة الانتقال إلى العقدة",
"go_to_node_event_tooltip": "تلميح الانتقال إلى العقدة", "go_to_node_event_tooltip": "تلميح الانتقال إلى العقدة",
"new_version_available": "يتوفر إصدار جديد", "new_version_available": "يتوفر إصدار جديد",
"report_guid": "معرف التقرير", "report_guid": "معرف التقرير",
"report_guid_missing": "معرف التقرير مفقود", "report_guid_missing": "معرف التقرير مفقود",
"report_select_format": "اختر تنسيق التقرير", "report_select_format": "اختر تنسيق التقرير",
"report_time": "وقت التقرير", "report_time": "وقت التقرير",
"run_event_icon": "أيقونة تشغيل الحدث",
"run_event_tooltip": "تلميح تشغيل الحدث", "run_event_tooltip": "تلميح تشغيل الحدث",
"settings_core_icon": "أيقونة الإعدادات الأساسية", "settings_core_icon": "أيقونة الإعدادات الأساسية",
"settings_core_label": "تسمية الإعدادات الأساسية", "settings_core_label": "تسمية الإعدادات الأساسية",
@@ -748,6 +748,5 @@
"settings_system_icon": "أيقونة النظام", "settings_system_icon": "أيقونة النظام",
"settings_system_label": "تسمية النظام", "settings_system_label": "تسمية النظام",
"settings_update_item_warning": "تحذير تحديث العنصر", "settings_update_item_warning": "تحذير تحديث العنصر",
"test_event_icon": "أيقونة اختبار الحدث",
"test_event_tooltip": "تلميح اختبار الحدث" "test_event_tooltip": "تلميح اختبار الحدث"
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Esborrar esdeveniments més vells de", "DAYS_TO_KEEP_EVENTS_name": "Esborrar esdeveniments més vells de",
"DISCOVER_PLUGINS_description": "Desactiva aquesta opció per accelerar la inicialització i l'estalvi de configuració. Quan està desactivat, els connectors no es descobreixen, i no podeu afegir nous connectors a la configuració <code>LOADED_PLUGINS</code>.", "DISCOVER_PLUGINS_description": "Desactiva aquesta opció per accelerar la inicialització i l'estalvi de configuració. Quan està desactivat, els connectors no es descobreixen, i no podeu afegir nous connectors a la configuració <code>LOADED_PLUGINS</code>.",
"DISCOVER_PLUGINS_name": "Descobreix els plugins", "DISCOVER_PLUGINS_name": "Descobreix els plugins",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Copiar detalls des del dispositiu", "DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Copiar detalls des del dispositiu",
"DevDetail_Copy_Device_Tooltip": "Copiar detalls del dispositius des de la llista desplegable. Tot el d'aquesta pàgina es sobre-escriurà", "DevDetail_Copy_Device_Tooltip": "Copiar detalls del dispositius des de la llista desplegable. Tot el d'aquesta pàgina es sobre-escriurà",
"DevDetail_CustomProperties_Title": "Propietats personalitzades", "DevDetail_CustomProperties_Title": "Propietats personalitzades",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Tipus", "DevDetail_MainInfo_Type": "Tipus",
"DevDetail_MainInfo_Vendor": "Venedor", "DevDetail_MainInfo_Vendor": "Venedor",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "Seleccioneu el dispositiu de xarxa al qual aquest dispositiu està connectat, per poder omplir l'arbre de xarxa.", "DevDetail_Network_Node_hover": "Seleccioneu el dispositiu de xarxa al qual aquest dispositiu està connectat, per poder omplir l'arbre de xarxa.",
"DevDetail_Network_Port_hover": "El port on el dispositiu està connectat al dispositiu de xarxa del pare. Si es deixa buit, sortirà una icona wifi a la representació de la Xarxa.", "DevDetail_Network_Port_hover": "El port on el dispositiu està connectat al dispositiu de xarxa del pare. Si es deixa buit, sortirà una icona wifi a la representació de la Xarxa.",
"DevDetail_Nmap_Scans": "Escaneig manual Nmap", "DevDetail_Nmap_Scans": "Escaneig manual Nmap",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Atenció. Si feu clic a això s'aplicarà el valor de l'esquerra a tots els dispositius seleccionats a dalt.", "Device_MultiEdit_Tooltip": "Atenció. Si feu clic a això s'aplicarà el valor de l'esquerra a tots els dispositius seleccionats a dalt.",
"Device_Searchbox": "Cerca", "Device_Searchbox": "Cerca",
"Device_Shortcut_AllDevices": "Els meus dispositius", "Device_Shortcut_AllDevices": "Els meus dispositius",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "Arxivat", "Device_Shortcut_Archived": "Arxivat",
"Device_Shortcut_Connected": "Connectat", "Device_Shortcut_Connected": "Connectat",
"Device_Shortcut_Devices": "Dispositius", "Device_Shortcut_Devices": "Dispositius",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Nom", "Device_TableHead_Name": "Nom",
"Device_TableHead_NetworkSite": "Network Site", "Device_TableHead_NetworkSite": "Network Site",
"Device_TableHead_Owner": "Propietari", "Device_TableHead_Owner": "Propietari",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "Node pare de xarxa", "Device_TableHead_Parent_MAC": "Node pare de xarxa",
"Device_TableHead_Port": "Port", "Device_TableHead_Port": "Port",
"Device_TableHead_PresentLastScan": "Presència", "Device_TableHead_PresentLastScan": "Presència",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "ID de fila", "Device_TableHead_RowID": "ID de fila",
"Device_TableHead_Rowid": "ID de fila", "Device_TableHead_Rowid": "ID de fila",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -704,23 +709,18 @@
"WF_Trigger": "Disparador(Trigger)", "WF_Trigger": "Disparador(Trigger)",
"WF_Trigger_event_type": "Tipus d'esdeveniment", "WF_Trigger_event_type": "Tipus d'esdeveniment",
"WF_Trigger_type": "Tipus de disparador", "WF_Trigger_type": "Tipus de disparador",
"add_icon_event_icon": "fa-square-plus",
"add_icon_event_tooltip": "Afegir nova icona", "add_icon_event_tooltip": "Afegir nova icona",
"add_option_event_icon": "fa-square-plus",
"add_option_event_tooltip": "Afegir nou valor", "add_option_event_tooltip": "Afegir nou valor",
"copy_icons_event_icon": "fa-copy",
"copy_icons_event_tooltip": "Sobreescriure icones de tots els dispositius amb el mateix tipus de dispositiu", "copy_icons_event_tooltip": "Sobreescriure icones de tots els dispositius amb el mateix tipus de dispositiu",
"devices_old": "Refrescant...", "devices_old": "Refrescant...",
"general_event_description": "L'esdeveniment que has desencadenat pot trigar un temps fins que acabin els processos de fons. L'execució acabarà una cop buida la cua d'execució (Comprova el registre d'errors <a href='/maintenance.php#tab_Logging'></a> si hi ha problemes). <br/> <br/> Cua d'execució:", "general_event_description": "L'esdeveniment que has desencadenat pot trigar un temps fins que acabin els processos de fons. L'execució acabarà una cop buida la cua d'execució (Comprova el registre d'errors <a href='/maintenance.php#tab_Logging'></a> si hi ha problemes). <br/> <br/> Cua d'execució:",
"general_event_title": "Execució d'un esdeveniment ad-hoc", "general_event_title": "Execució d'un esdeveniment ad-hoc",
"go_to_node_event_icon": "fa-square-up-right",
"go_to_node_event_tooltip": "Navegació a la pàgina de la Xarxa del node donat", "go_to_node_event_tooltip": "Navegació a la pàgina de la Xarxa del node donat",
"new_version_available": "Ja està disponible una nova versió.", "new_version_available": "Ja està disponible una nova versió.",
"report_guid": "Notificació guid:", "report_guid": "Notificació guid:",
"report_guid_missing": "No s'ha trobat la notificació enllaçada. Hi ha un petit retard entre les notificacions enviades recentment i que estiguin disponibles. Refresqui la pàgina i la memòria cau d'aquí uns segons. També és possible que la notificació seleccionada s'hagi esborrat durant el manteniment tal com s'especifica a la configuració <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/>L'última notificació es mostra en el seu lloc. La notificació perduda té el següent GUID:", "report_guid_missing": "No s'ha trobat la notificació enllaçada. Hi ha un petit retard entre les notificacions enviades recentment i que estiguin disponibles. Refresqui la pàgina i la memòria cau d'aquí uns segons. També és possible que la notificació seleccionada s'hagi esborrat durant el manteniment tal com s'especifica a la configuració <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/>L'última notificació es mostra en el seu lloc. La notificació perduda té el següent GUID:",
"report_select_format": "Seleccioneu Format:", "report_select_format": "Seleccioneu Format:",
"report_time": "Data de recepció:", "report_time": "Data de recepció:",
"run_event_icon": "fa-play",
"run_event_tooltip": "Habiliteu la configuració i deseu els canvis al principi abans d'executar-lo.", "run_event_tooltip": "Habiliteu la configuració i deseu els canvis al principi abans d'executar-lo.",
"settings_core_icon": "fa-solid fa-gem", "settings_core_icon": "fa-solid fa-gem",
"settings_core_label": "Nucli", "settings_core_label": "Nucli",
@@ -748,6 +748,5 @@
"settings_system_icon": "fa-solid fa-gear", "settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "Sistema", "settings_system_label": "Sistema",
"settings_update_item_warning": "Actualitza el valor sota. Sigues curós de seguir el format anterior. <b>No hi ha validació.</b>", "settings_update_item_warning": "Actualitza el valor sota. Sigues curós de seguir el format anterior. <b>No hi ha validació.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Deseu els canvis primer abans de comprovar la configuració." "test_event_tooltip": "Deseu els canvis primer abans de comprovar la configuració."
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "", "DAYS_TO_KEEP_EVENTS_name": "",
"DISCOVER_PLUGINS_description": "", "DISCOVER_PLUGINS_description": "",
"DISCOVER_PLUGINS_name": "", "DISCOVER_PLUGINS_name": "",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "", "DevDetail_Copy_Device_Title": "",
"DevDetail_Copy_Device_Tooltip": "", "DevDetail_Copy_Device_Tooltip": "",
"DevDetail_CustomProperties_Title": "", "DevDetail_CustomProperties_Title": "",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "", "DevDetail_MainInfo_Type": "",
"DevDetail_MainInfo_Vendor": "", "DevDetail_MainInfo_Vendor": "",
"DevDetail_MainInfo_mac": "", "DevDetail_MainInfo_mac": "",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "", "DevDetail_Network_Node_hover": "",
"DevDetail_Network_Port_hover": "", "DevDetail_Network_Port_hover": "",
"DevDetail_Nmap_Scans": "", "DevDetail_Nmap_Scans": "",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "", "Device_MultiEdit_Tooltip": "",
"Device_Searchbox": "", "Device_Searchbox": "",
"Device_Shortcut_AllDevices": "", "Device_Shortcut_AllDevices": "",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "", "Device_Shortcut_Archived": "",
"Device_Shortcut_Connected": "", "Device_Shortcut_Connected": "",
"Device_Shortcut_Devices": "", "Device_Shortcut_Devices": "",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "", "Device_TableHead_Name": "",
"Device_TableHead_NetworkSite": "", "Device_TableHead_NetworkSite": "",
"Device_TableHead_Owner": "", "Device_TableHead_Owner": "",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "", "Device_TableHead_Parent_MAC": "",
"Device_TableHead_Port": "", "Device_TableHead_Port": "",
"Device_TableHead_PresentLastScan": "", "Device_TableHead_PresentLastScan": "",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "", "Device_TableHead_RowID": "",
"Device_TableHead_Rowid": "", "Device_TableHead_Rowid": "",
"Device_TableHead_SSID": "", "Device_TableHead_SSID": "",
@@ -704,23 +709,18 @@
"WF_Trigger": "", "WF_Trigger": "",
"WF_Trigger_event_type": "", "WF_Trigger_event_type": "",
"WF_Trigger_type": "", "WF_Trigger_type": "",
"add_icon_event_icon": "fa-square-plus",
"add_icon_event_tooltip": "Přidat novou ikonu", "add_icon_event_tooltip": "Přidat novou ikonu",
"add_option_event_icon": "fa-square-plus",
"add_option_event_tooltip": "Přidat novou hodnotu", "add_option_event_tooltip": "Přidat novou hodnotu",
"copy_icons_event_icon": "fa-copy",
"copy_icons_event_tooltip": "Přepiš ikony všech zařízení za stejný typ zařízení", "copy_icons_event_tooltip": "Přepiš ikony všech zařízení za stejný typ zařízení",
"devices_old": "Obnovuji…", "devices_old": "Obnovuji…",
"general_event_description": "", "general_event_description": "",
"general_event_title": "", "general_event_title": "",
"go_to_node_event_icon": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "", "report_guid": "",
"report_guid_missing": "", "report_guid_missing": "",
"report_select_format": "", "report_select_format": "",
"report_time": "", "report_time": "",
"run_event_icon": "",
"run_event_tooltip": "", "run_event_tooltip": "",
"settings_core_icon": "", "settings_core_icon": "",
"settings_core_label": "", "settings_core_label": "",
@@ -748,6 +748,5 @@
"settings_system_icon": "", "settings_system_icon": "",
"settings_system_label": "", "settings_system_label": "",
"settings_update_item_warning": "", "settings_update_item_warning": "",
"test_event_icon": "",
"test_event_tooltip": "" "test_event_tooltip": ""
} }

View File

@@ -78,6 +78,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Ereignisse löschen, die älter sind als", "DAYS_TO_KEEP_EVENTS_name": "Ereignisse löschen, die älter sind als",
"DISCOVER_PLUGINS_description": "Deaktiviere diese Option, um Initialisierung und Speichern der Einstellungen zu beschleunigen. Wenn es deaktiviert ist, werden keine neuen Plugins gefunden und es können keine manuell hinzugefügt werden.", "DISCOVER_PLUGINS_description": "Deaktiviere diese Option, um Initialisierung und Speichern der Einstellungen zu beschleunigen. Wenn es deaktiviert ist, werden keine neuen Plugins gefunden und es können keine manuell hinzugefügt werden.",
"DISCOVER_PLUGINS_name": "Entdecke Erweiterungen", "DISCOVER_PLUGINS_name": "Entdecke Erweiterungen",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "Details von Gerät kopieren", "DevDetail_Copy_Device_Title": "Details von Gerät kopieren",
"DevDetail_Copy_Device_Tooltip": "Details vom Gerät aus der Dropdown-Liste kopieren. Alles auf dieser Seite wird überschrieben", "DevDetail_Copy_Device_Tooltip": "Details vom Gerät aus der Dropdown-Liste kopieren. Alles auf dieser Seite wird überschrieben",
"DevDetail_CustomProperties_Title": "Benutzerdefinierte Eigenschaften", "DevDetail_CustomProperties_Title": "Benutzerdefinierte Eigenschaften",
@@ -114,6 +115,7 @@
"DevDetail_MainInfo_Type": "Typ", "DevDetail_MainInfo_Type": "Typ",
"DevDetail_MainInfo_Vendor": "Hersteller", "DevDetail_MainInfo_Vendor": "Hersteller",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "Wählen Sie das Elternnetzgerät aus, an das das aktuelle Gerät angeschlossen ist, um den Netzwerkbaum zu erstellen.", "DevDetail_Network_Node_hover": "Wählen Sie das Elternnetzgerät aus, an das das aktuelle Gerät angeschlossen ist, um den Netzwerkbaum zu erstellen.",
"DevDetail_Network_Port_hover": "Der Port, mit dem dieses Gerät am übergeordneten Netzwerkgerät verbunden ist. Bleibt er leer, wird ein WLAN-Symbol in der Netzwerkstruktur angezeigt.", "DevDetail_Network_Port_hover": "Der Port, mit dem dieses Gerät am übergeordneten Netzwerkgerät verbunden ist. Bleibt er leer, wird ein WLAN-Symbol in der Netzwerkstruktur angezeigt.",
"DevDetail_Nmap_Scans": "Nmap Scans", "DevDetail_Nmap_Scans": "Nmap Scans",
@@ -212,6 +214,7 @@
"Device_MultiEdit_Tooltip": "Achtung! Beim Drücken werden alle Werte auf die oben ausgewählten Geräte übertragen.", "Device_MultiEdit_Tooltip": "Achtung! Beim Drücken werden alle Werte auf die oben ausgewählten Geräte übertragen.",
"Device_Searchbox": "Suche", "Device_Searchbox": "Suche",
"Device_Shortcut_AllDevices": "Meine Geräte", "Device_Shortcut_AllDevices": "Meine Geräte",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "Archiviert", "Device_Shortcut_Archived": "Archiviert",
"Device_Shortcut_Connected": "Verbunden", "Device_Shortcut_Connected": "Verbunden",
"Device_Shortcut_Devices": "Geräte", "Device_Shortcut_Devices": "Geräte",
@@ -238,9 +241,11 @@
"Device_TableHead_Name": "Name", "Device_TableHead_Name": "Name",
"Device_TableHead_NetworkSite": "Netzwerkseite", "Device_TableHead_NetworkSite": "Netzwerkseite",
"Device_TableHead_Owner": "Eigentümer", "Device_TableHead_Owner": "Eigentümer",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "Übergeordneter Netzwerkknoten", "Device_TableHead_Parent_MAC": "Übergeordneter Netzwerkknoten",
"Device_TableHead_Port": "Port", "Device_TableHead_Port": "Port",
"Device_TableHead_PresentLastScan": "Anwesenheit", "Device_TableHead_PresentLastScan": "Anwesenheit",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "Zeilen ID", "Device_TableHead_RowID": "Zeilen ID",
"Device_TableHead_Rowid": "Zeilennummer", "Device_TableHead_Rowid": "Zeilennummer",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -785,23 +790,18 @@
"WF_Trigger_type": "Auslösertyp", "WF_Trigger_type": "Auslösertyp",
"Webhooks_display_name": "Webhooks", "Webhooks_display_name": "Webhooks",
"Webhooks_icon": "<i class=\"fa fa-circle-nodes\"></i>", "Webhooks_icon": "<i class=\"fa fa-circle-nodes\"></i>",
"add_icon_event_icon": "",
"add_icon_event_tooltip": "Neues Symbol hinzufügen", "add_icon_event_tooltip": "Neues Symbol hinzufügen",
"add_option_event_icon": "",
"add_option_event_tooltip": "Neuen Wert hinzufügen", "add_option_event_tooltip": "Neuen Wert hinzufügen",
"copy_icons_event_icon": "",
"copy_icons_event_tooltip": "Icons aller Geräte mit demselben Gerätetyp überschreiben", "copy_icons_event_tooltip": "Icons aller Geräte mit demselben Gerätetyp überschreiben",
"devices_old": "Aktualisiert...", "devices_old": "Aktualisiert...",
"general_event_description": "Das Ereignis, das Sie ausgelöst haben, könnte eine Weile dauern, bis Hintergrundprozesse abgeschlossen sind. Die Ausführung endet, wenn die unten ausgeführte Warteschlangen abgearbeitet ist. (Siehe <a href='/maintenance.php#tab_Logging'>error log</a>, wenn Probleme auftreten.)<br/> <br/> Ausführungsschlange:", "general_event_description": "Das Ereignis, das Sie ausgelöst haben, könnte eine Weile dauern, bis Hintergrundprozesse abgeschlossen sind. Die Ausführung endet, wenn die unten ausgeführte Warteschlangen abgearbeitet ist. (Siehe <a href='/maintenance.php#tab_Logging'>error log</a>, wenn Probleme auftreten.)<br/> <br/> Ausführungsschlange:",
"general_event_title": "", "general_event_title": "",
"go_to_node_event_icon": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "Es ist eine neue Version verfügbar.", "new_version_available": "Es ist eine neue Version verfügbar.",
"report_guid": "", "report_guid": "",
"report_guid_missing": "", "report_guid_missing": "",
"report_select_format": "Format auswählen:", "report_select_format": "Format auswählen:",
"report_time": "Benachrichtigungszeit:", "report_time": "Benachrichtigungszeit:",
"run_event_icon": "",
"run_event_tooltip": "Aktiviere die Einstellung und speichere deine Änderungen, bevor du sie ausführst.", "run_event_tooltip": "Aktiviere die Einstellung und speichere deine Änderungen, bevor du sie ausführst.",
"settings_core_icon": "", "settings_core_icon": "",
"settings_core_label": "Kern", "settings_core_label": "Kern",
@@ -829,6 +829,5 @@
"settings_system_icon": "", "settings_system_icon": "",
"settings_system_label": "System", "settings_system_label": "System",
"settings_update_item_warning": "", "settings_update_item_warning": "",
"test_event_icon": "",
"test_event_tooltip": "Speichere die Änderungen, bevor Sie die Einstellungen testen." "test_event_tooltip": "Speichere die Änderungen, bevor Sie die Einstellungen testen."
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Delete events older than", "DAYS_TO_KEEP_EVENTS_name": "Delete events older than",
"DISCOVER_PLUGINS_description": "Disable this option to speed up initialization and settings saving. When disabled, plugins are not discovered, and you cannot add new plugins to the <code>LOADED_PLUGINS</code> setting.", "DISCOVER_PLUGINS_description": "Disable this option to speed up initialization and settings saving. When disabled, plugins are not discovered, and you cannot add new plugins to the <code>LOADED_PLUGINS</code> setting.",
"DISCOVER_PLUGINS_name": "Discover plugins", "DISCOVER_PLUGINS_name": "Discover plugins",
"DevDetail_Children_Title": "Children Relationships",
"DevDetail_Copy_Device_Title": "Copy details from device", "DevDetail_Copy_Device_Title": "Copy details from device",
"DevDetail_Copy_Device_Tooltip": "Copy details from device from the dropdown list. Everything on this page will be overwritten", "DevDetail_Copy_Device_Tooltip": "Copy details from device from the dropdown list. Everything on this page will be overwritten",
"DevDetail_CustomProperties_Title": "Custom Properties", "DevDetail_CustomProperties_Title": "Custom Properties",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Type", "DevDetail_MainInfo_Type": "Type",
"DevDetail_MainInfo_Vendor": "Vendor", "DevDetail_MainInfo_Vendor": "Vendor",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "Open children node",
"DevDetail_Network_Node_hover": "Select the parent network device the current device is connected to, to populate the Network tree.", "DevDetail_Network_Node_hover": "Select the parent network device the current device is connected to, to populate the Network tree.",
"DevDetail_Network_Port_hover": "The port this device is connected to on the parent network device. If left empty a wifi icon is displayed in the Network tree.", "DevDetail_Network_Port_hover": "The port this device is connected to on the parent network device. If left empty a wifi icon is displayed in the Network tree.",
"DevDetail_Nmap_Scans": "Manual Nmap Scans", "DevDetail_Nmap_Scans": "Manual Nmap Scans",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Careful. Clicking this will apply the value on the left to all devices selected above.", "Device_MultiEdit_Tooltip": "Careful. Clicking this will apply the value on the left to all devices selected above.",
"Device_Searchbox": "Search", "Device_Searchbox": "Search",
"Device_Shortcut_AllDevices": "My Devices", "Device_Shortcut_AllDevices": "My Devices",
"Device_Shortcut_AllNodes": "All Nodes",
"Device_Shortcut_Archived": "Archived", "Device_Shortcut_Archived": "Archived",
"Device_Shortcut_Connected": "Connected", "Device_Shortcut_Connected": "Connected",
"Device_Shortcut_Devices": "Devices", "Device_Shortcut_Devices": "Devices",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Name", "Device_TableHead_Name": "Name",
"Device_TableHead_NetworkSite": "Network Site", "Device_TableHead_NetworkSite": "Network Site",
"Device_TableHead_Owner": "Owner", "Device_TableHead_Owner": "Owner",
"Device_TableHead_ParentRelType": "Relationship Type",
"Device_TableHead_Parent_MAC": "Parent network node", "Device_TableHead_Parent_MAC": "Parent network node",
"Device_TableHead_Port": "Port", "Device_TableHead_Port": "Port",
"Device_TableHead_PresentLastScan": "Presence", "Device_TableHead_PresentLastScan": "Presence",
"Device_TableHead_ReqNicsOnline": "Require NICs Online",
"Device_TableHead_RowID": "Row ID", "Device_TableHead_RowID": "Row ID",
"Device_TableHead_Rowid": "Row ID", "Device_TableHead_Rowid": "Row ID",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -704,23 +709,19 @@
"WF_Trigger": "Trigger", "WF_Trigger": "Trigger",
"WF_Trigger_event_type": "Event type", "WF_Trigger_event_type": "Event type",
"WF_Trigger_type": "Trigger type", "WF_Trigger_type": "Trigger type",
"add_icon_event_icon": "fa-square-plus",
"add_icon_event_tooltip": "Add new icon", "add_icon_event_tooltip": "Add new icon",
"add_option_event_icon": "fa-square-plus",
"add_option_event_tooltip": "Add new value", "add_option_event_tooltip": "Add new value",
"copy_icons_event_icon": "fa-copy",
"copy_icons_event_tooltip": "Overwrite icons of all devices with the same device type", "copy_icons_event_tooltip": "Overwrite icons of all devices with the same device type",
"devices_old": "Refreshing…", "devices_old": "Refreshing…",
"general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:", "general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:",
"general_event_title": "Executing an ad-hoc event", "general_event_title": "Executing an ad-hoc event",
"go_to_node_event_icon": "fa-square-up-right",
"go_to_node_event_tooltip": "Navigate to the Network page of the given node", "go_to_node_event_tooltip": "Navigate to the Network page of the given node",
"go_to_device_event_tooltip": "Navigate to the Device",
"new_version_available": "A new version is available.", "new_version_available": "A new version is available.",
"report_guid": "Notification guid:", "report_guid": "Notification guid:",
"report_guid_missing": "Linked notification not found. There is a small delay between recently sent notifications and them being available. Referesh your page and cache after a few seconds. It's also possible the selected notification have been deleted during maintenance as specified in the <code>DBCLNP_NOTIFI_HIST</code> setting. <br/> <br/>The latest notification is displayed instead. The missing notification has the following GUID:", "report_guid_missing": "Linked notification not found. There is a small delay between recently sent notifications and them being available. Referesh your page and cache after a few seconds. It's also possible the selected notification have been deleted during maintenance as specified in the <code>DBCLNP_NOTIFI_HIST</code> setting. <br/> <br/>The latest notification is displayed instead. The missing notification has the following GUID:",
"report_select_format": "Select Format:", "report_select_format": "Select Format:",
"report_time": "Notification time:", "report_time": "Notification time:",
"run_event_icon": "fa-play",
"run_event_tooltip": "Enable the setting and save your changes at first before you run it.", "run_event_tooltip": "Enable the setting and save your changes at first before you run it.",
"settings_core_icon": "fa-solid fa-gem", "settings_core_icon": "fa-solid fa-gem",
"settings_core_label": "Core", "settings_core_label": "Core",
@@ -748,6 +749,5 @@
"settings_system_icon": "fa-solid fa-gear", "settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "System", "settings_system_label": "System",
"settings_update_item_warning": "Update the value below. Be careful to follow the previous format. <b>Validation is not performed.</b>", "settings_update_item_warning": "Update the value below. Be careful to follow the previous format. <b>Validation is not performed.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Save your changes at first before you test your settings." "test_event_tooltip": "Save your changes at first before you test your settings."
} }

View File

@@ -76,6 +76,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Eliminar eventos anteriores a", "DAYS_TO_KEEP_EVENTS_name": "Eliminar eventos anteriores a",
"DISCOVER_PLUGINS_description": "Desactive esta opción para acelerar la inicialización y el ahorro de ajustes. Cuando está desactivado, los plugins no se descubren y no puede añadir nuevos plugins a la configuración <code>LOADED_PLUGINS</code>.", "DISCOVER_PLUGINS_description": "Desactive esta opción para acelerar la inicialización y el ahorro de ajustes. Cuando está desactivado, los plugins no se descubren y no puede añadir nuevos plugins a la configuración <code>LOADED_PLUGINS</code>.",
"DISCOVER_PLUGINS_name": "Descubrir plugins", "DISCOVER_PLUGINS_name": "Descubrir plugins",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "Copiar detalles del dispositivo", "DevDetail_Copy_Device_Title": "Copiar detalles del dispositivo",
"DevDetail_Copy_Device_Tooltip": "Copiar detalles del dispositivo de la lista desplegable. Todo en esta página se sobrescribirá", "DevDetail_Copy_Device_Tooltip": "Copiar detalles del dispositivo de la lista desplegable. Todo en esta página se sobrescribirá",
"DevDetail_CustomProperties_Title": "Propiedades personalizadas", "DevDetail_CustomProperties_Title": "Propiedades personalizadas",
@@ -112,6 +113,7 @@
"DevDetail_MainInfo_Type": "Tipo", "DevDetail_MainInfo_Type": "Tipo",
"DevDetail_MainInfo_Vendor": "Proveedor", "DevDetail_MainInfo_Vendor": "Proveedor",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "Seleccione el dispositivo de red principal al que está conectado el dispositivo actual para completar el árbol de Red.", "DevDetail_Network_Node_hover": "Seleccione el dispositivo de red principal al que está conectado el dispositivo actual para completar el árbol de Red.",
"DevDetail_Network_Port_hover": "El puerto al que está conectado este dispositivo en el dispositivo de red principal. Si se deja vacío, se muestra un icono de wifi en el árbol de Red.", "DevDetail_Network_Port_hover": "El puerto al que está conectado este dispositivo en el dispositivo de red principal. Si se deja vacío, se muestra un icono de wifi en el árbol de Red.",
"DevDetail_Nmap_Scans": "Escaneos de Nmap", "DevDetail_Nmap_Scans": "Escaneos de Nmap",
@@ -210,6 +212,7 @@
"Device_MultiEdit_Tooltip": "Cuidado. Al hacer clic se aplicará el valor de la izquierda a todos los dispositivos seleccionados anteriormente.", "Device_MultiEdit_Tooltip": "Cuidado. Al hacer clic se aplicará el valor de la izquierda a todos los dispositivos seleccionados anteriormente.",
"Device_Searchbox": "Búsqueda", "Device_Searchbox": "Búsqueda",
"Device_Shortcut_AllDevices": "Mis dispositivos", "Device_Shortcut_AllDevices": "Mis dispositivos",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "Archivado(s)", "Device_Shortcut_Archived": "Archivado(s)",
"Device_Shortcut_Connected": "Conectado(s)", "Device_Shortcut_Connected": "Conectado(s)",
"Device_Shortcut_Devices": "Dispositivos", "Device_Shortcut_Devices": "Dispositivos",
@@ -236,9 +239,11 @@
"Device_TableHead_Name": "Nombre", "Device_TableHead_Name": "Nombre",
"Device_TableHead_NetworkSite": "Lugar de la red", "Device_TableHead_NetworkSite": "Lugar de la red",
"Device_TableHead_Owner": "Propietario", "Device_TableHead_Owner": "Propietario",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "Nodo principal de la red", "Device_TableHead_Parent_MAC": "Nodo principal de la red",
"Device_TableHead_Port": "Puerto", "Device_TableHead_Port": "Puerto",
"Device_TableHead_PresentLastScan": "Historial", "Device_TableHead_PresentLastScan": "Historial",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "ID de fila", "Device_TableHead_RowID": "ID de fila",
"Device_TableHead_Rowid": "ID de fila", "Device_TableHead_Rowid": "ID de fila",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -783,23 +788,18 @@
"Webhooks_display_name": "Webhooks", "Webhooks_display_name": "Webhooks",
"Webhooks_icon": "<i class=\"fa fa-circle-nodes\"></i>", "Webhooks_icon": "<i class=\"fa fa-circle-nodes\"></i>",
"Webhooks_settings_group": "<i class=\"fa fa-circle-nodes\"></i> Webhooks", "Webhooks_settings_group": "<i class=\"fa fa-circle-nodes\"></i> Webhooks",
"add_icon_event_icon": "fa-square-plus",
"add_icon_event_tooltip": "Agregar nuevo icono", "add_icon_event_tooltip": "Agregar nuevo icono",
"add_option_event_icon": "fa-square-plus",
"add_option_event_tooltip": "Añadir nuevo valor", "add_option_event_tooltip": "Añadir nuevo valor",
"copy_icons_event_icon": "fa-copy",
"copy_icons_event_tooltip": "Sobrescribir los iconos de todos los dispositivos con el mismo tipo de dispositivo", "copy_icons_event_tooltip": "Sobrescribir los iconos de todos los dispositivos con el mismo tipo de dispositivo",
"devices_old": "Volviendo a actualizar....", "devices_old": "Volviendo a actualizar....",
"general_event_description": "El evento que ha activado puede tardar un poco hasta que finalicen los procesos en segundo plano. La ejecución finalizó una vez que se vacía la cola de ejecución a continuación (consulte el <a href='/maintenance.php#tab_Logging'>registro de errores</a> si encuentra problemas). <br/> <br/> Cola de ejecución:", "general_event_description": "El evento que ha activado puede tardar un poco hasta que finalicen los procesos en segundo plano. La ejecución finalizó una vez que se vacía la cola de ejecución a continuación (consulte el <a href='/maintenance.php#tab_Logging'>registro de errores</a> si encuentra problemas). <br/> <br/> Cola de ejecución:",
"general_event_title": "Ejecutar un evento ad-hoc", "general_event_title": "Ejecutar un evento ad-hoc",
"go_to_node_event_icon": "fa-square-up-right",
"go_to_node_event_tooltip": "Vaya a la página de Red del nodo indicado", "go_to_node_event_tooltip": "Vaya a la página de Red del nodo indicado",
"new_version_available": "Una nueva versión está disponible.", "new_version_available": "Una nueva versión está disponible.",
"report_guid": "Guía de las notificaciones:", "report_guid": "Guía de las notificaciones:",
"report_guid_missing": "No se ha encontrado la notificación vinculada. Hay un pequeño retraso entre las notificaciones enviadas recientemente y su disponibilidad. Actualiza tu página y la caché después de unos segundos. También es posible que la notificación seleccionada se haya eliminado durante el mantenimiento, tal y como se especifica en la configuración <code>de DBCLNP_NOTIFI_HIST</code>. <br/> <br/>En su lugar, se muestra la notificación más reciente. La notificación que falta tiene el siguiente GUID:", "report_guid_missing": "No se ha encontrado la notificación vinculada. Hay un pequeño retraso entre las notificaciones enviadas recientemente y su disponibilidad. Actualiza tu página y la caché después de unos segundos. También es posible que la notificación seleccionada se haya eliminado durante el mantenimiento, tal y como se especifica en la configuración <code>de DBCLNP_NOTIFI_HIST</code>. <br/> <br/>En su lugar, se muestra la notificación más reciente. La notificación que falta tiene el siguiente GUID:",
"report_select_format": "Selecciona el formato:", "report_select_format": "Selecciona el formato:",
"report_time": "Hora de la notificación:", "report_time": "Hora de la notificación:",
"run_event_icon": "fa-play",
"run_event_tooltip": "Activa el ajuste y guarda tus cambios antes de ejecutarlo.", "run_event_tooltip": "Activa el ajuste y guarda tus cambios antes de ejecutarlo.",
"settings_core_icon": "fa-solid fa-gem", "settings_core_icon": "fa-solid fa-gem",
"settings_core_label": "Núcleo", "settings_core_label": "Núcleo",
@@ -827,6 +827,5 @@
"settings_system_icon": "fa-solid fa-gear", "settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "Sistema", "settings_system_label": "Sistema",
"settings_update_item_warning": "Actualice el valor a continuación. Tenga cuidado de seguir el formato anterior. <b>O la validación no se realiza.</b>", "settings_update_item_warning": "Actualice el valor a continuación. Tenga cuidado de seguir el formato anterior. <b>O la validación no se realiza.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Guarda tus cambios antes de probar nuevos ajustes." "test_event_tooltip": "Guarda tus cambios antes de probar nuevos ajustes."
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Supprimer les événements plus anciens que", "DAYS_TO_KEEP_EVENTS_name": "Supprimer les événements plus anciens que",
"DISCOVER_PLUGINS_description": "Désactivez cette option pour accélérer le démarrage et l'enregistrement de paramètres. Quand elle est désactivée, les plugins ne sont pas découverts, et vous ne pouvez près ajouter de nouveaux plugins au paramètre <code>LOADED_PLUGINS</code>.", "DISCOVER_PLUGINS_description": "Désactivez cette option pour accélérer le démarrage et l'enregistrement de paramètres. Quand elle est désactivée, les plugins ne sont pas découverts, et vous ne pouvez près ajouter de nouveaux plugins au paramètre <code>LOADED_PLUGINS</code>.",
"DISCOVER_PLUGINS_name": "Découvrir des plugins", "DISCOVER_PLUGINS_name": "Découvrir des plugins",
"DevDetail_Children_Title": "Relations avec les éléments inférieurs",
"DevDetail_Copy_Device_Title": "Copier les détails de l'appareil", "DevDetail_Copy_Device_Title": "Copier les détails de l'appareil",
"DevDetail_Copy_Device_Tooltip": "Copier les détails de l'appareil dans la liste déroulante. Tout ce qui se trouve sur cette page sera remplacé", "DevDetail_Copy_Device_Tooltip": "Copier les détails de l'appareil dans la liste déroulante. Tout ce qui se trouve sur cette page sera remplacé",
"DevDetail_CustomProperties_Title": "Champs personnalisés", "DevDetail_CustomProperties_Title": "Champs personnalisés",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Type", "DevDetail_MainInfo_Type": "Type",
"DevDetail_MainInfo_Vendor": "Fabricant", "DevDetail_MainInfo_Vendor": "Fabricant",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "Ouvrir le noeud de l'élément inférieur",
"DevDetail_Network_Node_hover": "Sélectionner l'appareil du réseau principal auquel cet appareil est connecté afin de compléter l'arborescence du Réseau.", "DevDetail_Network_Node_hover": "Sélectionner l'appareil du réseau principal auquel cet appareil est connecté afin de compléter l'arborescence du Réseau.",
"DevDetail_Network_Port_hover": "Le port auquel cet appareil est connecté sur l'appareil du réseau principal. Si vide, une icône Wifi est affichée dans l'arborescence du Réseau.", "DevDetail_Network_Port_hover": "Le port auquel cet appareil est connecté sur l'appareil du réseau principal. Si vide, une icône Wifi est affichée dans l'arborescence du Réseau.",
"DevDetail_Nmap_Scans": "Scans manuels via Nmap", "DevDetail_Nmap_Scans": "Scans manuels via Nmap",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Attention. Ceci va appliquer la valeur de gauche à tous les appareils sélectionnés au-dessus.", "Device_MultiEdit_Tooltip": "Attention. Ceci va appliquer la valeur de gauche à tous les appareils sélectionnés au-dessus.",
"Device_Searchbox": "Rechercher", "Device_Searchbox": "Rechercher",
"Device_Shortcut_AllDevices": "Mes appareils", "Device_Shortcut_AllDevices": "Mes appareils",
"Device_Shortcut_AllNodes": "Tous les nœuds",
"Device_Shortcut_Archived": "Archivés", "Device_Shortcut_Archived": "Archivés",
"Device_Shortcut_Connected": "Connectés", "Device_Shortcut_Connected": "Connectés",
"Device_Shortcut_Devices": "Appareils", "Device_Shortcut_Devices": "Appareils",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Nom", "Device_TableHead_Name": "Nom",
"Device_TableHead_NetworkSite": "Site Réseau", "Device_TableHead_NetworkSite": "Site Réseau",
"Device_TableHead_Owner": "Propriétaire", "Device_TableHead_Owner": "Propriétaire",
"Device_TableHead_ParentRelType": "Type de relation",
"Device_TableHead_Parent_MAC": "Nœud réseau principal", "Device_TableHead_Parent_MAC": "Nœud réseau principal",
"Device_TableHead_Port": "Port", "Device_TableHead_Port": "Port",
"Device_TableHead_PresentLastScan": "Présence", "Device_TableHead_PresentLastScan": "Présence",
"Device_TableHead_ReqNicsOnline": "Nécessite que l'interface réseau (NIC) soit connectée",
"Device_TableHead_RowID": "ID de colonne", "Device_TableHead_RowID": "ID de colonne",
"Device_TableHead_Rowid": "ID de colonne", "Device_TableHead_Rowid": "ID de colonne",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -704,23 +709,18 @@
"WF_Trigger": "Déclencheur", "WF_Trigger": "Déclencheur",
"WF_Trigger_event_type": "Type d'événement", "WF_Trigger_event_type": "Type d'événement",
"WF_Trigger_type": "Type de déclencheur", "WF_Trigger_type": "Type de déclencheur",
"add_icon_event_icon": "fa-square-plus",
"add_icon_event_tooltip": "Ajouter une nouvelle icône", "add_icon_event_tooltip": "Ajouter une nouvelle icône",
"add_option_event_icon": "fa-square-plus",
"add_option_event_tooltip": "Ajouter une nouvelle valeur", "add_option_event_tooltip": "Ajouter une nouvelle valeur",
"copy_icons_event_icon": "fa-copy",
"copy_icons_event_tooltip": "Remplace les icônes de tous les appareils du même type", "copy_icons_event_tooltip": "Remplace les icônes de tous les appareils du même type",
"devices_old": "Rafraichissement…", "devices_old": "Rafraichissement…",
"general_event_description": "L'événement que vous avez lancé peut prendre du temps avant que les tâches de fond ne soit terminées. La durée d'exécution finira une fois que la file d'exécution ci-dessous sera vide (consulter les <a href='/maintenance.php#tab_Logging'>journaux d'erreur</a> si vous rencontrez des erreurs). <br/> <br/> File d'exécution:", "general_event_description": "L'événement que vous avez lancé peut prendre du temps avant que les tâches de fond ne soit terminées. La durée d'exécution finira une fois que la file d'exécution ci-dessous sera vide (consulter les <a href='/maintenance.php#tab_Logging'>journaux d'erreur</a> si vous rencontrez des erreurs). <br/> <br/> File d'exécution:",
"general_event_title": "Lancement d'un événement sur mesure", "general_event_title": "Lancement d'un événement sur mesure",
"go_to_node_event_icon": "fa-square-up-right",
"go_to_node_event_tooltip": "Aller vers la page Réseau du nœud concerné", "go_to_node_event_tooltip": "Aller vers la page Réseau du nœud concerné",
"new_version_available": "Une nouvelle version est disponible.", "new_version_available": "Une nouvelle version est disponible.",
"report_guid": "GUID de la notification:", "report_guid": "GUID de la notification:",
"report_guid_missing": "La notification associée n'a pas été trouvée. Un petit délai existe entre l'envoi d'une notification et sa disponibilité réelle pour affichage. Rafraichissez la page et votre cache après quelques secondes. Il est aussi possible que la notification sélectionnée ait été supprimée durant une opération de maintenance, comme renseigné dans le paramètre <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/> La dernière notification est affichée à sa place. La notification manquante dispose du GUID suivant:", "report_guid_missing": "La notification associée n'a pas été trouvée. Un petit délai existe entre l'envoi d'une notification et sa disponibilité réelle pour affichage. Rafraichissez la page et votre cache après quelques secondes. Il est aussi possible que la notification sélectionnée ait été supprimée durant une opération de maintenance, comme renseigné dans le paramètre <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/> La dernière notification est affichée à sa place. La notification manquante dispose du GUID suivant:",
"report_select_format": "Sélectionner un format:", "report_select_format": "Sélectionner un format:",
"report_time": "Heure de la notification:", "report_time": "Heure de la notification:",
"run_event_icon": "fa-play",
"run_event_tooltip": "Activez le paramètre et enregistrez vos changements avant de le lancer.", "run_event_tooltip": "Activez le paramètre et enregistrez vos changements avant de le lancer.",
"settings_core_icon": "fa-solid fa-gem", "settings_core_icon": "fa-solid fa-gem",
"settings_core_label": "Principal", "settings_core_label": "Principal",
@@ -748,6 +748,6 @@
"settings_system_icon": "fa-solid fa-gear", "settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "Système", "settings_system_label": "Système",
"settings_update_item_warning": "Mettre à jour la valeur ci-dessous. Veillez à bien suivre le même format qu'auparavant. <b>Il n'y a pas de pas de contrôle.</b>", "settings_update_item_warning": "Mettre à jour la valeur ci-dessous. Veillez à bien suivre le même format qu'auparavant. <b>Il n'y a pas de pas de contrôle.</b>",
"test_event_icon": "fa-vial-circle-check", "test_event_tooltip": "Enregistrer d'abord vos modifications avant de tester vôtre paramétrage.",
"test_event_tooltip": "Enregistrer d'abord vos modifications avant de tester vôtre paramétrage." "go_to_device_event_tooltip": "Naviguer vers cet appareil"
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Elimina eventi più vecchi di", "DAYS_TO_KEEP_EVENTS_name": "Elimina eventi più vecchi di",
"DISCOVER_PLUGINS_description": "Disattiva questa opzione per velocizzare l'inizializzazione e il salvataggio delle impostazioni. Quando è disattivata, i plugin non vengono scoperti e non puoi aggiungere nuovi plugin all'impostazione <code>LOADED_PLUGINS</code>.", "DISCOVER_PLUGINS_description": "Disattiva questa opzione per velocizzare l'inizializzazione e il salvataggio delle impostazioni. Quando è disattivata, i plugin non vengono scoperti e non puoi aggiungere nuovi plugin all'impostazione <code>LOADED_PLUGINS</code>.",
"DISCOVER_PLUGINS_name": "Scopri i plugin", "DISCOVER_PLUGINS_name": "Scopri i plugin",
"DevDetail_Children_Title": "Relazioni tra figli",
"DevDetail_Copy_Device_Title": "Copia dettagli dal dispositivo", "DevDetail_Copy_Device_Title": "Copia dettagli dal dispositivo",
"DevDetail_Copy_Device_Tooltip": "Copia i dettagli dal dispositivo dall'elenco a discesa. Tutto in questa pagina verrà sovrascritto", "DevDetail_Copy_Device_Tooltip": "Copia i dettagli dal dispositivo dall'elenco a discesa. Tutto in questa pagina verrà sovrascritto",
"DevDetail_CustomProperties_Title": "Proprietà personalizzate", "DevDetail_CustomProperties_Title": "Proprietà personalizzate",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Tipo", "DevDetail_MainInfo_Type": "Tipo",
"DevDetail_MainInfo_Vendor": "Produttore", "DevDetail_MainInfo_Vendor": "Produttore",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "Apri nodo figlio",
"DevDetail_Network_Node_hover": "Seleziona il dispositivo di rete principale a cui è connesso il dispositivo corrente per popolare la struttura di rete.", "DevDetail_Network_Node_hover": "Seleziona il dispositivo di rete principale a cui è connesso il dispositivo corrente per popolare la struttura di rete.",
"DevDetail_Network_Port_hover": "La porta a cui è connesso questo dispositivo sul dispositivo di rete principale. Se lasciato vuoto, verrà visualizzata un'icona Wi-Fi nella struttura di rete.", "DevDetail_Network_Port_hover": "La porta a cui è connesso questo dispositivo sul dispositivo di rete principale. Se lasciato vuoto, verrà visualizzata un'icona Wi-Fi nella struttura di rete.",
"DevDetail_Nmap_Scans": "Scansioni Nmap manuali", "DevDetail_Nmap_Scans": "Scansioni Nmap manuali",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Attento. Facendo clic verrà applicato il valore sulla sinistra a tutti i dispositivi selezionati sopra.", "Device_MultiEdit_Tooltip": "Attento. Facendo clic verrà applicato il valore sulla sinistra a tutti i dispositivi selezionati sopra.",
"Device_Searchbox": "Cerca", "Device_Searchbox": "Cerca",
"Device_Shortcut_AllDevices": "Miei dispositivi", "Device_Shortcut_AllDevices": "Miei dispositivi",
"Device_Shortcut_AllNodes": "Tutti i nodi",
"Device_Shortcut_Archived": "Archiviati", "Device_Shortcut_Archived": "Archiviati",
"Device_Shortcut_Connected": "Connessi", "Device_Shortcut_Connected": "Connessi",
"Device_Shortcut_Devices": "Dispositivi", "Device_Shortcut_Devices": "Dispositivi",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Nome", "Device_TableHead_Name": "Nome",
"Device_TableHead_NetworkSite": "Sito di rete", "Device_TableHead_NetworkSite": "Sito di rete",
"Device_TableHead_Owner": "Proprietario", "Device_TableHead_Owner": "Proprietario",
"Device_TableHead_ParentRelType": "Tipo di relazione",
"Device_TableHead_Parent_MAC": "Nodo di rete principale", "Device_TableHead_Parent_MAC": "Nodo di rete principale",
"Device_TableHead_Port": "Porta", "Device_TableHead_Port": "Porta",
"Device_TableHead_PresentLastScan": "Presenza", "Device_TableHead_PresentLastScan": "Presenza",
"Device_TableHead_ReqNicsOnline": "Richiedi NIC online",
"Device_TableHead_RowID": "ID riga", "Device_TableHead_RowID": "ID riga",
"Device_TableHead_Rowid": "ID riga", "Device_TableHead_Rowid": "ID riga",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -704,23 +709,18 @@
"WF_Trigger": "Trigger", "WF_Trigger": "Trigger",
"WF_Trigger_event_type": "Tipo evento", "WF_Trigger_event_type": "Tipo evento",
"WF_Trigger_type": "Tipo di trigger", "WF_Trigger_type": "Tipo di trigger",
"add_icon_event_icon": "fa-square-plus",
"add_icon_event_tooltip": "Aggiungi nuova icona", "add_icon_event_tooltip": "Aggiungi nuova icona",
"add_option_event_icon": "fa-square-plus",
"add_option_event_tooltip": "Aggiungi nuovo valore", "add_option_event_tooltip": "Aggiungi nuovo valore",
"copy_icons_event_icon": "fa-copy",
"copy_icons_event_tooltip": "Sovrascrivi le icone di tutti i dispositivi con lo stesso tipo di dispositivo", "copy_icons_event_tooltip": "Sovrascrivi le icone di tutti i dispositivi con lo stesso tipo di dispositivo",
"devices_old": "Aggiornamento…", "devices_old": "Aggiornamento…",
"general_event_description": "L'evento che hai attivato potrebbe richiedere del tempo prima che i processi in background vengano completati. L'esecuzione è terminata una volta che la coda di esecuzione sottostante si è svuotata (controlla il <a href='/maintenance.php#tab_Logging'>log degli errori</a> se riscontri problemi). <br/> <br/> Coda di esecuzione:", "general_event_description": "L'evento che hai attivato potrebbe richiedere del tempo prima che i processi in background vengano completati. L'esecuzione è terminata una volta che la coda di esecuzione sottostante si è svuotata (controlla il <a href='/maintenance.php#tab_Logging'>log degli errori</a> se riscontri problemi). <br/> <br/> Coda di esecuzione:",
"general_event_title": "Esecuzione di un evento ad-hoc", "general_event_title": "Esecuzione di un evento ad-hoc",
"go_to_node_event_icon": "fa-square-up-right",
"go_to_node_event_tooltip": "Passa alla pagina Rete del nodo specificato", "go_to_node_event_tooltip": "Passa alla pagina Rete del nodo specificato",
"new_version_available": "È disponibile una nuova versione.", "new_version_available": "È disponibile una nuova versione.",
"report_guid": "GUID notifica:", "report_guid": "GUID notifica:",
"report_guid_missing": "Notifica collegata non trovata. C'è un piccolo ritardo tra la disponibilità delle notifiche inviate di recente e la loro disponibilità. Aggiorna la pagina e la cache dopo alcuni secondi. È anche possibile che la notifica selezionata sia stata eliminata durante la manutenzione come specificato nell'impostazione <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/>Viene invece visualizzata l'ultima notifica. La notifica mancante ha il seguente GUID:", "report_guid_missing": "Notifica collegata non trovata. C'è un piccolo ritardo tra la disponibilità delle notifiche inviate di recente e la loro disponibilità. Aggiorna la pagina e la cache dopo alcuni secondi. È anche possibile che la notifica selezionata sia stata eliminata durante la manutenzione come specificato nell'impostazione <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/>Viene invece visualizzata l'ultima notifica. La notifica mancante ha il seguente GUID:",
"report_select_format": "Seleziona formato:", "report_select_format": "Seleziona formato:",
"report_time": "Orario notifica:", "report_time": "Orario notifica:",
"run_event_icon": "fa-play",
"run_event_tooltip": "Abilita l'impostazione e salva le modifiche prima di eseguirla.", "run_event_tooltip": "Abilita l'impostazione e salva le modifiche prima di eseguirla.",
"settings_core_icon": "fa-solid fa-gem", "settings_core_icon": "fa-solid fa-gem",
"settings_core_label": "Core", "settings_core_label": "Core",
@@ -748,6 +748,6 @@
"settings_system_icon": "fa-solid fa-gear", "settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "Sistema", "settings_system_label": "Sistema",
"settings_update_item_warning": "Aggiorna il valore qui sotto. Fai attenzione a seguire il formato precedente. <b>La convalida non viene eseguita.</b>", "settings_update_item_warning": "Aggiorna il valore qui sotto. Fai attenzione a seguire il formato precedente. <b>La convalida non viene eseguita.</b>",
"test_event_icon": "fa-vial-circle-check", "test_event_tooltip": "Salva le modifiche prima di provare le nuove impostazioni.",
"test_event_tooltip": "Salva le modifiche prima di provare le nuove impostazioni." "go_to_device_event_tooltip": "Naviga al dispositivo"
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Slett hendelser eldre enn", "DAYS_TO_KEEP_EVENTS_name": "Slett hendelser eldre enn",
"DISCOVER_PLUGINS_description": "", "DISCOVER_PLUGINS_description": "",
"DISCOVER_PLUGINS_name": "", "DISCOVER_PLUGINS_name": "",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Kopier detaljer fra enhet", "DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Kopier detaljer fra enhet",
"DevDetail_Copy_Device_Tooltip": "Kopier detaljer fra enheten via nedtrekks menyen. Alt på denne siden vil bli overskrevet", "DevDetail_Copy_Device_Tooltip": "Kopier detaljer fra enheten via nedtrekks menyen. Alt på denne siden vil bli overskrevet",
"DevDetail_CustomProperties_Title": "", "DevDetail_CustomProperties_Title": "",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Type", "DevDetail_MainInfo_Type": "Type",
"DevDetail_MainInfo_Vendor": "Leverandør", "DevDetail_MainInfo_Vendor": "Leverandør",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "Velg overordnet nettverksenhet til enheten som er tilkoblet, for å fylle nettverkstreet.", "DevDetail_Network_Node_hover": "Velg overordnet nettverksenhet til enheten som er tilkoblet, for å fylle nettverkstreet.",
"DevDetail_Network_Port_hover": "Porten denne enheten er koblet til på overordnet nettverksenhet. Hvis den er tom, vises et wifi-ikon i nettverkstreet i stedet.", "DevDetail_Network_Port_hover": "Porten denne enheten er koblet til på overordnet nettverksenhet. Hvis den er tom, vises et wifi-ikon i nettverkstreet i stedet.",
"DevDetail_Nmap_Scans": "Manuelle Nmap-skanninger", "DevDetail_Nmap_Scans": "Manuelle Nmap-skanninger",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Forsiktig. Ved å klikke på denne vil verdien til venstre brukes på alle enhetene som er valgt ovenfor.", "Device_MultiEdit_Tooltip": "Forsiktig. Ved å klikke på denne vil verdien til venstre brukes på alle enhetene som er valgt ovenfor.",
"Device_Searchbox": "Søk", "Device_Searchbox": "Søk",
"Device_Shortcut_AllDevices": "Mine Enheter", "Device_Shortcut_AllDevices": "Mine Enheter",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "Arkivert", "Device_Shortcut_Archived": "Arkivert",
"Device_Shortcut_Connected": "Tilkoblet", "Device_Shortcut_Connected": "Tilkoblet",
"Device_Shortcut_Devices": "Enheter", "Device_Shortcut_Devices": "Enheter",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Navn", "Device_TableHead_Name": "Navn",
"Device_TableHead_NetworkSite": "", "Device_TableHead_NetworkSite": "",
"Device_TableHead_Owner": "Eier", "Device_TableHead_Owner": "Eier",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "Overordnet node MAC", "Device_TableHead_Parent_MAC": "Overordnet node MAC",
"Device_TableHead_Port": "Port", "Device_TableHead_Port": "Port",
"Device_TableHead_PresentLastScan": "", "Device_TableHead_PresentLastScan": "",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "Rad ID", "Device_TableHead_RowID": "Rad ID",
"Device_TableHead_Rowid": "Rad ID", "Device_TableHead_Rowid": "Rad ID",
"Device_TableHead_SSID": "", "Device_TableHead_SSID": "",
@@ -704,23 +709,18 @@
"WF_Trigger": "", "WF_Trigger": "",
"WF_Trigger_event_type": "", "WF_Trigger_event_type": "",
"WF_Trigger_type": "", "WF_Trigger_type": "",
"add_icon_event_icon": "",
"add_icon_event_tooltip": "", "add_icon_event_tooltip": "",
"add_option_event_icon": "",
"add_option_event_tooltip": "", "add_option_event_tooltip": "",
"copy_icons_event_icon": "",
"copy_icons_event_tooltip": "", "copy_icons_event_tooltip": "",
"devices_old": "Oppdaterer...", "devices_old": "Oppdaterer...",
"general_event_description": "Hendelsen du har utløst kan ta en stund til før bakgrunnsprosesser er ferdig. Utførelsen ble avsluttet når utførelseskøen nedenfor tømmes (sjekk <a href='/maintenance.php#tab_Logging'>Feillogg</a> Hvis du møter problemer). <br/> <br/> Utførelseskø:", "general_event_description": "Hendelsen du har utløst kan ta en stund til før bakgrunnsprosesser er ferdig. Utførelsen ble avsluttet når utførelseskøen nedenfor tømmes (sjekk <a href='/maintenance.php#tab_Logging'>Feillogg</a> Hvis du møter problemer). <br/> <br/> Utførelseskø:",
"general_event_title": "Utfører en ad-hoc hendelse", "general_event_title": "Utfører en ad-hoc hendelse",
"go_to_node_event_icon": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "Notifikasjons GUID:", "report_guid": "Notifikasjons GUID:",
"report_guid_missing": "Koblet notifikasjon ikke funnet. Det er en liten forsinkelse mellom nylig sendt notifikasjoner og at de er tilgjengelige. Oppdater siden din og hurtigbufferen etter noen sekunder. Det er også mulig den valgte notifikasjonen er slettet under vedlikehold som spesifisert i <code>DBCLNP_NOTIFI_HIST</code> innstillingen. <br/> <br/> Den siste notifikasjonen vises i stedet. Den manglende notifikasjonen har følgende GUID:", "report_guid_missing": "Koblet notifikasjon ikke funnet. Det er en liten forsinkelse mellom nylig sendt notifikasjoner og at de er tilgjengelige. Oppdater siden din og hurtigbufferen etter noen sekunder. Det er også mulig den valgte notifikasjonen er slettet under vedlikehold som spesifisert i <code>DBCLNP_NOTIFI_HIST</code> innstillingen. <br/> <br/> Den siste notifikasjonen vises i stedet. Den manglende notifikasjonen har følgende GUID:",
"report_select_format": "Velg format:", "report_select_format": "Velg format:",
"report_time": "Notifikasjonstid:", "report_time": "Notifikasjonstid:",
"run_event_icon": "fa-play",
"run_event_tooltip": "Aktiver innstillingen og lagre endringene først før du kjører den.", "run_event_tooltip": "Aktiver innstillingen og lagre endringene først før du kjører den.",
"settings_core_icon": "fa-solid fa-gem", "settings_core_icon": "fa-solid fa-gem",
"settings_core_label": "Core", "settings_core_label": "Core",
@@ -748,6 +748,5 @@
"settings_system_icon": "fa-solid fa-gear", "settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "System", "settings_system_label": "System",
"settings_update_item_warning": "Oppdater verdien nedenfor. Pass på å følge forrige format. <b>Validering etterpå utføres ikke.</b>", "settings_update_item_warning": "Oppdater verdien nedenfor. Pass på å følge forrige format. <b>Validering etterpå utføres ikke.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Lagre endringene først, før du tester innstillingene dine." "test_event_tooltip": "Lagre endringene først, før du tester innstillingene dine."
} }

File diff suppressed because it is too large Load Diff

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Excluir eventos mais antigos que", "DAYS_TO_KEEP_EVENTS_name": "Excluir eventos mais antigos que",
"DISCOVER_PLUGINS_description": "Desative esta opção para acelerar a inicialização e a gravação de definições. Quando desativada, os plug-ins não são descobertos e não é possível adicionar novos plug-ins à definição<code>LOADED_PLUGINS</code>.", "DISCOVER_PLUGINS_description": "Desative esta opção para acelerar a inicialização e a gravação de definições. Quando desativada, os plug-ins não são descobertos e não é possível adicionar novos plug-ins à definição<code>LOADED_PLUGINS</code>.",
"DISCOVER_PLUGINS_name": "Descobrir plugins", "DISCOVER_PLUGINS_name": "Descobrir plugins",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "Copiar detalhes do dispositivo", "DevDetail_Copy_Device_Title": "Copiar detalhes do dispositivo",
"DevDetail_Copy_Device_Tooltip": "Copiar detalhes do dispositivo a partir da lista pendente. Tudo o que se encontra nesta página será substituído", "DevDetail_Copy_Device_Tooltip": "Copiar detalhes do dispositivo a partir da lista pendente. Tudo o que se encontra nesta página será substituído",
"DevDetail_CustomProperties_Title": "Propriedades personalizadas", "DevDetail_CustomProperties_Title": "Propriedades personalizadas",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Tipo", "DevDetail_MainInfo_Type": "Tipo",
"DevDetail_MainInfo_Vendor": "Vendedor", "DevDetail_MainInfo_Vendor": "Vendedor",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "Selecione o dispositivo de rede principal ao qual o dispositivo atual está conectado, para preencher a árvore Rede.", "DevDetail_Network_Node_hover": "Selecione o dispositivo de rede principal ao qual o dispositivo atual está conectado, para preencher a árvore Rede.",
"DevDetail_Network_Port_hover": "A porta a que este dispositivo está ligado no dispositivo de rede principal. Se for deixado vazio, é apresentado um ícone wifi na árvore Rede.", "DevDetail_Network_Port_hover": "A porta a que este dispositivo está ligado no dispositivo de rede principal. Se for deixado vazio, é apresentado um ícone wifi na árvore Rede.",
"DevDetail_Nmap_Scans": "Varreduras manuais do Nmap", "DevDetail_Nmap_Scans": "Varreduras manuais do Nmap",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Cuidadoso. Clicar aqui aplicará o valor à esquerda a todos os dispositivos selecionados acima.", "Device_MultiEdit_Tooltip": "Cuidadoso. Clicar aqui aplicará o valor à esquerda a todos os dispositivos selecionados acima.",
"Device_Searchbox": "Procurar", "Device_Searchbox": "Procurar",
"Device_Shortcut_AllDevices": "Meus dispositivos", "Device_Shortcut_AllDevices": "Meus dispositivos",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "Arquivado", "Device_Shortcut_Archived": "Arquivado",
"Device_Shortcut_Connected": "Conectado", "Device_Shortcut_Connected": "Conectado",
"Device_Shortcut_Devices": "Dispositivos", "Device_Shortcut_Devices": "Dispositivos",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Nome", "Device_TableHead_Name": "Nome",
"Device_TableHead_NetworkSite": "Site da rede", "Device_TableHead_NetworkSite": "Site da rede",
"Device_TableHead_Owner": "Proprietário", "Device_TableHead_Owner": "Proprietário",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "Nó pai MAC", "Device_TableHead_Parent_MAC": "Nó pai MAC",
"Device_TableHead_Port": "Porta", "Device_TableHead_Port": "Porta",
"Device_TableHead_PresentLastScan": "Presente", "Device_TableHead_PresentLastScan": "Presente",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "ID da linha", "Device_TableHead_RowID": "ID da linha",
"Device_TableHead_Rowid": "ID da linha", "Device_TableHead_Rowid": "ID da linha",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -704,23 +709,18 @@
"WF_Trigger": "", "WF_Trigger": "",
"WF_Trigger_event_type": "", "WF_Trigger_event_type": "",
"WF_Trigger_type": "", "WF_Trigger_type": "",
"add_icon_event_icon": "",
"add_icon_event_tooltip": "", "add_icon_event_tooltip": "",
"add_option_event_icon": "",
"add_option_event_tooltip": "", "add_option_event_tooltip": "",
"copy_icons_event_icon": "",
"copy_icons_event_tooltip": "", "copy_icons_event_tooltip": "",
"devices_old": "", "devices_old": "",
"general_event_description": "", "general_event_description": "",
"general_event_title": "", "general_event_title": "",
"go_to_node_event_icon": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "", "report_guid": "",
"report_guid_missing": "", "report_guid_missing": "",
"report_select_format": "", "report_select_format": "",
"report_time": "", "report_time": "",
"run_event_icon": "",
"run_event_tooltip": "", "run_event_tooltip": "",
"settings_core_icon": "", "settings_core_icon": "",
"settings_core_label": "", "settings_core_label": "",
@@ -748,6 +748,5 @@
"settings_system_icon": "", "settings_system_icon": "",
"settings_system_label": "", "settings_system_label": "",
"settings_update_item_warning": "", "settings_update_item_warning": "",
"test_event_icon": "",
"test_event_tooltip": "Guarde as alterações antes de testar as definições." "test_event_tooltip": "Guarde as alterações antes de testar as definições."
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Удалить события старше", "DAYS_TO_KEEP_EVENTS_name": "Удалить события старше",
"DISCOVER_PLUGINS_description": "Отключите эту опцию, чтобы ускорить инициализацию и сохранение настроек. При отключении этой опции плагины не обнаруживаются, и вы не можете добавлять новые плагины в параметр <code>LOADED_PLUGINS</code>.", "DISCOVER_PLUGINS_description": "Отключите эту опцию, чтобы ускорить инициализацию и сохранение настроек. При отключении этой опции плагины не обнаруживаются, и вы не можете добавлять новые плагины в параметр <code>LOADED_PLUGINS</code>.",
"DISCOVER_PLUGINS_name": "Обзор плагинов", "DISCOVER_PLUGINS_name": "Обзор плагинов",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "Скопировать данные с устройства", "DevDetail_Copy_Device_Title": "Скопировать данные с устройства",
"DevDetail_Copy_Device_Tooltip": "Скопируйте данные с устройства из раскрывающегося списка. Все на этой странице будет перезаписано", "DevDetail_Copy_Device_Tooltip": "Скопируйте данные с устройства из раскрывающегося списка. Все на этой странице будет перезаписано",
"DevDetail_CustomProperties_Title": "Пользовательские свойства", "DevDetail_CustomProperties_Title": "Пользовательские свойства",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Тип", "DevDetail_MainInfo_Type": "Тип",
"DevDetail_MainInfo_Vendor": "Поставщик", "DevDetail_MainInfo_Vendor": "Поставщик",
"DevDetail_MainInfo_mac": "MAC адрес", "DevDetail_MainInfo_mac": "MAC адрес",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "Выберите родительское сетевое устройство, к которому подключено текущее устройство, чтобы заполнить дерево сети.", "DevDetail_Network_Node_hover": "Выберите родительское сетевое устройство, к которому подключено текущее устройство, чтобы заполнить дерево сети.",
"DevDetail_Network_Port_hover": "Порт, к которому подключено это устройство на родительском сетевом устройстве. Если оставить пустым, в дереве сети отобразится значок Wi-Fi.", "DevDetail_Network_Port_hover": "Порт, к которому подключено это устройство на родительском сетевом устройстве. Если оставить пустым, в дереве сети отобразится значок Wi-Fi.",
"DevDetail_Nmap_Scans": "Ручные сканеры Nmap", "DevDetail_Nmap_Scans": "Ручные сканеры Nmap",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Осторожно. При нажатии на эту кнопку значение слева будет применено ко всем устройствам, выбранным выше.", "Device_MultiEdit_Tooltip": "Осторожно. При нажатии на эту кнопку значение слева будет применено ко всем устройствам, выбранным выше.",
"Device_Searchbox": "Поиск", "Device_Searchbox": "Поиск",
"Device_Shortcut_AllDevices": "Мои устройства", "Device_Shortcut_AllDevices": "Мои устройства",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "Архив", "Device_Shortcut_Archived": "Архив",
"Device_Shortcut_Connected": "Подключенные", "Device_Shortcut_Connected": "Подключенные",
"Device_Shortcut_Devices": "Устройства", "Device_Shortcut_Devices": "Устройства",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Имя", "Device_TableHead_Name": "Имя",
"Device_TableHead_NetworkSite": "Сайт устройства", "Device_TableHead_NetworkSite": "Сайт устройства",
"Device_TableHead_Owner": "Владелец", "Device_TableHead_Owner": "Владелец",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "Родительский узел сети", "Device_TableHead_Parent_MAC": "Родительский узел сети",
"Device_TableHead_Port": "Порт", "Device_TableHead_Port": "Порт",
"Device_TableHead_PresentLastScan": "Присутствие", "Device_TableHead_PresentLastScan": "Присутствие",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "ID строки", "Device_TableHead_RowID": "ID строки",
"Device_TableHead_Rowid": "ID строки", "Device_TableHead_Rowid": "ID строки",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -704,23 +709,18 @@
"WF_Trigger": "Триггер", "WF_Trigger": "Триггер",
"WF_Trigger_event_type": "Тип события", "WF_Trigger_event_type": "Тип события",
"WF_Trigger_type": "Тип триггера", "WF_Trigger_type": "Тип триггера",
"add_icon_event_icon": "fa-square-plus",
"add_icon_event_tooltip": "Добавить новую иконку", "add_icon_event_tooltip": "Добавить новую иконку",
"add_option_event_icon": "fa-square-plus",
"add_option_event_tooltip": "Добавить новое значение", "add_option_event_tooltip": "Добавить новое значение",
"copy_icons_event_icon": "fa-copy",
"copy_icons_event_tooltip": "Заменить иконки всех устройств с одним и тем же типом устройства", "copy_icons_event_tooltip": "Заменить иконки всех устройств с одним и тем же типом устройства",
"devices_old": "Актуализируется…", "devices_old": "Актуализируется…",
"general_event_description": "Событие, которое вы инициировали, может занять некоторое время, прежде чем фоновые процессы завершатся. Выполнение завершится, как только очередь выполнения, указанная ниже, опустеет (Проверьте <a href='/maintenance.php#tab_Logging'>журнал ошибок</a> при возникновении проблем). <br/> <br/>· · Очередь выполнения:", "general_event_description": "Событие, которое вы инициировали, может занять некоторое время, прежде чем фоновые процессы завершатся. Выполнение завершится, как только очередь выполнения, указанная ниже, опустеет (Проверьте <a href='/maintenance.php#tab_Logging'>журнал ошибок</a> при возникновении проблем). <br/> <br/>· · Очередь выполнения:",
"general_event_title": "Выполнение специального события", "general_event_title": "Выполнение специального события",
"go_to_node_event_icon": "fa-square-up-right",
"go_to_node_event_tooltip": "Переход на страницу \"Сеть\" данного узла", "go_to_node_event_tooltip": "Переход на страницу \"Сеть\" данного узла",
"new_version_available": "Доступна новая версия.", "new_version_available": "Доступна новая версия.",
"report_guid": "Идентификатор уведомления:", "report_guid": "Идентификатор уведомления:",
"report_guid_missing": "Связанное уведомление не найдено. Между недавно отправленными уведомлениями и их доступностью существует небольшая задержка. Обновите страницу и кэшируйте ее через несколько секунд. Также возможно, что выбранное уведомление было удалено во время обслуживания, как указано в настройке <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/>Вместо этого отображается последнее уведомление. Отсутствующее уведомление имеет следующий GUID:", "report_guid_missing": "Связанное уведомление не найдено. Между недавно отправленными уведомлениями и их доступностью существует небольшая задержка. Обновите страницу и кэшируйте ее через несколько секунд. Также возможно, что выбранное уведомление было удалено во время обслуживания, как указано в настройке <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/>Вместо этого отображается последнее уведомление. Отсутствующее уведомление имеет следующий GUID:",
"report_select_format": "Выбрать формат:", "report_select_format": "Выбрать формат:",
"report_time": "Время уведомления:", "report_time": "Время уведомления:",
"run_event_icon": "fa-play",
"run_event_tooltip": "Включите настройку и сначала сохраните изменения, прежде чем запускать ее.", "run_event_tooltip": "Включите настройку и сначала сохраните изменения, прежде чем запускать ее.",
"settings_core_icon": "fa-solid fa-gem", "settings_core_icon": "fa-solid fa-gem",
"settings_core_label": "Основные", "settings_core_label": "Основные",
@@ -748,6 +748,5 @@
"settings_system_icon": "fa-solid fa-gear", "settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "Система", "settings_system_label": "Система",
"settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>", "settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки." "test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки."
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Şu tarihten eski olayları sil", "DAYS_TO_KEEP_EVENTS_name": "Şu tarihten eski olayları sil",
"DISCOVER_PLUGINS_description": "Bu seçeneği devre dışı bırakmak, başlatma süresini ve ayarların kaydedilmesini hızlandırır. Devre dışı bırakıldığında, eklentiler keşfedilmez ve <code>LOADED_PLUGINS</code> ayarına yeni eklentiler eklenemez.", "DISCOVER_PLUGINS_description": "Bu seçeneği devre dışı bırakmak, başlatma süresini ve ayarların kaydedilmesini hızlandırır. Devre dışı bırakıldığında, eklentiler keşfedilmez ve <code>LOADED_PLUGINS</code> ayarına yeni eklentiler eklenemez.",
"DISCOVER_PLUGINS_name": "Eklentileri keşfet", "DISCOVER_PLUGINS_name": "Eklentileri keşfet",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "Cihazdan detayları kopyala", "DevDetail_Copy_Device_Title": "Cihazdan detayları kopyala",
"DevDetail_Copy_Device_Tooltip": "Aşağıdaki açılır listeden cihazın detaylarını kopyalayın. Bu sayfadaki her şey üzerine yazılacaktır", "DevDetail_Copy_Device_Tooltip": "Aşağıdaki açılır listeden cihazın detaylarını kopyalayın. Bu sayfadaki her şey üzerine yazılacaktır",
"DevDetail_CustomProperties_Title": "Özelleştirilmiş Özellikler", "DevDetail_CustomProperties_Title": "Özelleştirilmiş Özellikler",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Tür", "DevDetail_MainInfo_Type": "Tür",
"DevDetail_MainInfo_Vendor": "Üretici", "DevDetail_MainInfo_Vendor": "Üretici",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "Cihazın bağlı olduğu üst ağ cihazını seçerek Ağ ağacının doldurulmasını sağlayın.", "DevDetail_Network_Node_hover": "Cihazın bağlı olduğu üst ağ cihazını seçerek Ağ ağacının doldurulmasını sağlayın.",
"DevDetail_Network_Port_hover": "Bu cihazın, üst ağ cihazı üzerindeki bağlı olduğu port. Boş bırakılırsa, Ağ ağacında bir Wi-Fi simgesi görüntülenir.", "DevDetail_Network_Port_hover": "Bu cihazın, üst ağ cihazı üzerindeki bağlı olduğu port. Boş bırakılırsa, Ağ ağacında bir Wi-Fi simgesi görüntülenir.",
"DevDetail_Nmap_Scans": "Manuel Nmap Taramaları", "DevDetail_Nmap_Scans": "Manuel Nmap Taramaları",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Dikkat. Buna tıklamak, soldaki değeri yukarıda seçilen tüm cihazlara uygulayacaktır.", "Device_MultiEdit_Tooltip": "Dikkat. Buna tıklamak, soldaki değeri yukarıda seçilen tüm cihazlara uygulayacaktır.",
"Device_Searchbox": "Arama", "Device_Searchbox": "Arama",
"Device_Shortcut_AllDevices": "Cihazlarım", "Device_Shortcut_AllDevices": "Cihazlarım",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "Arşivlenmiş", "Device_Shortcut_Archived": "Arşivlenmiş",
"Device_Shortcut_Connected": "Bağlandı", "Device_Shortcut_Connected": "Bağlandı",
"Device_Shortcut_Devices": "Cihazlar", "Device_Shortcut_Devices": "Cihazlar",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "İsim", "Device_TableHead_Name": "İsim",
"Device_TableHead_NetworkSite": "Ağ Alanı", "Device_TableHead_NetworkSite": "Ağ Alanı",
"Device_TableHead_Owner": "Kurucu", "Device_TableHead_Owner": "Kurucu",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "Üst ağ düğümü", "Device_TableHead_Parent_MAC": "Üst ağ düğümü",
"Device_TableHead_Port": "Port", "Device_TableHead_Port": "Port",
"Device_TableHead_PresentLastScan": "Varlık", "Device_TableHead_PresentLastScan": "Varlık",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "Satır ID", "Device_TableHead_RowID": "Satır ID",
"Device_TableHead_Rowid": "Satır ID", "Device_TableHead_Rowid": "Satır ID",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -704,23 +709,18 @@
"WF_Trigger": "", "WF_Trigger": "",
"WF_Trigger_event_type": "", "WF_Trigger_event_type": "",
"WF_Trigger_type": "", "WF_Trigger_type": "",
"add_icon_event_icon": "",
"add_icon_event_tooltip": "", "add_icon_event_tooltip": "",
"add_option_event_icon": "",
"add_option_event_tooltip": "", "add_option_event_tooltip": "",
"copy_icons_event_icon": "",
"copy_icons_event_tooltip": "", "copy_icons_event_tooltip": "",
"devices_old": "Yenileniyor...", "devices_old": "Yenileniyor...",
"general_event_description": "", "general_event_description": "",
"general_event_title": "", "general_event_title": "",
"go_to_node_event_icon": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "", "report_guid": "",
"report_guid_missing": "", "report_guid_missing": "",
"report_select_format": "", "report_select_format": "",
"report_time": "Bildirim zamanı:", "report_time": "Bildirim zamanı:",
"run_event_icon": "",
"run_event_tooltip": "", "run_event_tooltip": "",
"settings_core_icon": "", "settings_core_icon": "",
"settings_core_label": "", "settings_core_label": "",
@@ -748,6 +748,5 @@
"settings_system_icon": "", "settings_system_icon": "",
"settings_system_label": "Sistem", "settings_system_label": "Sistem",
"settings_update_item_warning": "", "settings_update_item_warning": "",
"test_event_icon": "",
"test_event_tooltip": "" "test_event_tooltip": ""
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Видалити події, старші за", "DAYS_TO_KEEP_EVENTS_name": "Видалити події, старші за",
"DISCOVER_PLUGINS_description": "Вимкніть цю опцію, щоб прискорити ініціалізацію та збереження налаштувань. Якщо вимкнено, плагіни не виявляються, і ви не можете додавати нові плагіни до параметра <code>LOADED_PLUGINS</code>.", "DISCOVER_PLUGINS_description": "Вимкніть цю опцію, щоб прискорити ініціалізацію та збереження налаштувань. Якщо вимкнено, плагіни не виявляються, і ви не можете додавати нові плагіни до параметра <code>LOADED_PLUGINS</code>.",
"DISCOVER_PLUGINS_name": "Відкрийте для себе плагіни", "DISCOVER_PLUGINS_name": "Відкрийте для себе плагіни",
"DevDetail_Children_Title": "Стосунки з дітьми",
"DevDetail_Copy_Device_Title": "Скопіюйте деталі з пристрою", "DevDetail_Copy_Device_Title": "Скопіюйте деталі з пристрою",
"DevDetail_Copy_Device_Tooltip": "Скопіюйте деталі пристрою зі спадного списку. Усе на цій сторінці буде перезаписано", "DevDetail_Copy_Device_Tooltip": "Скопіюйте деталі пристрою зі спадного списку. Усе на цій сторінці буде перезаписано",
"DevDetail_CustomProperties_Title": "Спеціальні властивості", "DevDetail_CustomProperties_Title": "Спеціальні властивості",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Тип", "DevDetail_MainInfo_Type": "Тип",
"DevDetail_MainInfo_Vendor": "Продавець", "DevDetail_MainInfo_Vendor": "Продавець",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "Відкрити дочірній вузол",
"DevDetail_Network_Node_hover": "Виберіть батьківський мережевий пристрій, до якого підключено поточний пристрій, щоб заповнити дерево мережі.", "DevDetail_Network_Node_hover": "Виберіть батьківський мережевий пристрій, до якого підключено поточний пристрій, щоб заповнити дерево мережі.",
"DevDetail_Network_Port_hover": "Порт, до якого підключено цей пристрій на батьківському мережевому пристрої. Якщо залишити пустим, у дереві мережі відобразиться значок Wi-Fi.", "DevDetail_Network_Port_hover": "Порт, до якого підключено цей пристрій на батьківському мережевому пристрої. Якщо залишити пустим, у дереві мережі відобразиться значок Wi-Fi.",
"DevDetail_Nmap_Scans": "Сканування Nmap вручну", "DevDetail_Nmap_Scans": "Сканування Nmap вручну",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Обережно. Якщо натиснути це, значення зліва буде застосовано до всіх пристроїв, вибраних вище.", "Device_MultiEdit_Tooltip": "Обережно. Якщо натиснути це, значення зліва буде застосовано до всіх пристроїв, вибраних вище.",
"Device_Searchbox": "Пошук", "Device_Searchbox": "Пошук",
"Device_Shortcut_AllDevices": "Мої пристрої", "Device_Shortcut_AllDevices": "Мої пристрої",
"Device_Shortcut_AllNodes": "Усі вузли",
"Device_Shortcut_Archived": "Архівовано", "Device_Shortcut_Archived": "Архівовано",
"Device_Shortcut_Connected": "Підключено", "Device_Shortcut_Connected": "Підключено",
"Device_Shortcut_Devices": "Пристрої", "Device_Shortcut_Devices": "Пристрої",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Ім'я", "Device_TableHead_Name": "Ім'я",
"Device_TableHead_NetworkSite": "Мережевий сайт", "Device_TableHead_NetworkSite": "Мережевий сайт",
"Device_TableHead_Owner": "Власник", "Device_TableHead_Owner": "Власник",
"Device_TableHead_ParentRelType": "Тип зв'язку",
"Device_TableHead_Parent_MAC": "Узел родительской сети", "Device_TableHead_Parent_MAC": "Узел родительской сети",
"Device_TableHead_Port": "Порт", "Device_TableHead_Port": "Порт",
"Device_TableHead_PresentLastScan": "Присутність", "Device_TableHead_PresentLastScan": "Присутність",
"Device_TableHead_ReqNicsOnline": "Вимагати мережевих карт онлайн",
"Device_TableHead_RowID": "ID рядка", "Device_TableHead_RowID": "ID рядка",
"Device_TableHead_Rowid": "ID рядка", "Device_TableHead_Rowid": "ID рядка",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -704,23 +709,18 @@
"WF_Trigger": "Тригер", "WF_Trigger": "Тригер",
"WF_Trigger_event_type": "Тип події", "WF_Trigger_event_type": "Тип події",
"WF_Trigger_type": "Тип тригера", "WF_Trigger_type": "Тип тригера",
"add_icon_event_icon": "фа-квадрат-плюс",
"add_icon_event_tooltip": "додати новий значок", "add_icon_event_tooltip": "додати новий значок",
"add_option_event_icon": "фа-квадрат-плюс",
"add_option_event_tooltip": "Додати нове значення", "add_option_event_tooltip": "Додати нове значення",
"copy_icons_event_icon": "фа-копія",
"copy_icons_event_tooltip": "Перезаписати піктограми всіх пристроїв одним типом пристрою", "copy_icons_event_tooltip": "Перезаписати піктограми всіх пристроїв одним типом пристрою",
"devices_old": "Освіжає…", "devices_old": "Освіжає…",
"general_event_description": "Подія, яку ви ініціювали, може зайняти деякий час, поки завершаться фонові процеси. Виконання завершилося, коли наведена нижче черга виконання спорожнилася (перевірте <a href='/maintenance.php#tab_Logging'>журнал помилок</a>, якщо виникнуть проблеми). <br/> <br/> Черга виконання:", "general_event_description": "Подія, яку ви ініціювали, може зайняти деякий час, поки завершаться фонові процеси. Виконання завершилося, коли наведена нижче черга виконання спорожнилася (перевірте <a href='/maintenance.php#tab_Logging'>журнал помилок</a>, якщо виникнуть проблеми). <br/> <br/> Черга виконання:",
"general_event_title": "Виконання спеціальної події", "general_event_title": "Виконання спеціальної події",
"go_to_node_event_icon": "fa-квадрат-вгору-вправо",
"go_to_node_event_tooltip": "Перейдіть на сторінку Мережа даного вузла", "go_to_node_event_tooltip": "Перейдіть на сторінку Мережа даного вузла",
"new_version_available": "Доступна нова версія.", "new_version_available": "Доступна нова версія.",
"report_guid": "Довідник сповіщень:", "report_guid": "Довідник сповіщень:",
"report_guid_missing": "Пов’язане сповіщення не знайдено. Існує невелика затримка між нещодавно надісланими сповіщеннями та їх доступністю. Оновіть сторінку та кеш через кілька секунд. Також можливо, вибране сповіщення було видалено під час обслуговування, як зазначено в параметрі <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/>Натомість відображається останнє сповіщення. Відсутнє сповіщення має такий GUID:", "report_guid_missing": "Пов’язане сповіщення не знайдено. Існує невелика затримка між нещодавно надісланими сповіщеннями та їх доступністю. Оновіть сторінку та кеш через кілька секунд. Також можливо, вибране сповіщення було видалено під час обслуговування, як зазначено в параметрі <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/>Натомість відображається останнє сповіщення. Відсутнє сповіщення має такий GUID:",
"report_select_format": "Виберіть формат:", "report_select_format": "Виберіть формат:",
"report_time": "Час сповіщення:", "report_time": "Час сповіщення:",
"run_event_icon": "fa- play",
"run_event_tooltip": "Увімкніть налаштування та збережіть зміни, перш ніж запускати його.", "run_event_tooltip": "Увімкніть налаштування та збережіть зміни, перш ніж запускати його.",
"settings_core_icon": "фа-твердий фа-самоцвіт", "settings_core_icon": "фа-твердий фа-самоцвіт",
"settings_core_label": "Ядро", "settings_core_label": "Ядро",
@@ -748,6 +748,6 @@
"settings_system_icon": "фа-твердий фа-передача", "settings_system_icon": "фа-твердий фа-передача",
"settings_system_label": "Система", "settings_system_label": "Система",
"settings_update_item_warning": "Оновіть значення нижче. Слідкуйте за попереднім форматом. <b>Перевірка не виконана.</b>", "settings_update_item_warning": "Оновіть значення нижче. Слідкуйте за попереднім форматом. <b>Перевірка не виконана.</b>",
"test_event_icon": "fa-vial-circle- check", "test_event_tooltip": "Перш ніж перевіряти налаштування, збережіть зміни.",
"test_event_tooltip": "Перш ніж перевіряти налаштування, збережіть зміни." "go_to_device_event_tooltip": "Перейдіть до пристрою"
} }

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "删除早于", "DAYS_TO_KEEP_EVENTS_name": "删除早于",
"DISCOVER_PLUGINS_description": "禁用此选项可加快初始化和设置保存的速度。当禁用时,插件不会被发现,并且您无法将新插件添加到 <code>LOADED_PLUGINS</code>设置中。", "DISCOVER_PLUGINS_description": "禁用此选项可加快初始化和设置保存的速度。当禁用时,插件不会被发现,并且您无法将新插件添加到 <code>LOADED_PLUGINS</code>设置中。",
"DISCOVER_PLUGINS_name": "", "DISCOVER_PLUGINS_name": "",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> 从设备复制详细信息", "DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> 从设备复制详细信息",
"DevDetail_Copy_Device_Tooltip": "从下拉列表中复制设备的详细信息。此页面上的所有内容都将被覆盖", "DevDetail_Copy_Device_Tooltip": "从下拉列表中复制设备的详细信息。此页面上的所有内容都将被覆盖",
"DevDetail_CustomProperties_Title": "自定义属性", "DevDetail_CustomProperties_Title": "自定义属性",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "类型", "DevDetail_MainInfo_Type": "类型",
"DevDetail_MainInfo_Vendor": "制造商", "DevDetail_MainInfo_Vendor": "制造商",
"DevDetail_MainInfo_mac": "MAC", "DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "选择当前设备连接到的父网络设备,以填充网络树。", "DevDetail_Network_Node_hover": "选择当前设备连接到的父网络设备,以填充网络树。",
"DevDetail_Network_Port_hover": "此设备连接到父网络设备上的端口。如果留空,则网络树中会显示一个 wifi 图标。", "DevDetail_Network_Port_hover": "此设备连接到父网络设备上的端口。如果留空,则网络树中会显示一个 wifi 图标。",
"DevDetail_Nmap_Scans": "手动 Nmap 扫描", "DevDetail_Nmap_Scans": "手动 Nmap 扫描",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "小心。 单击此按钮会将左侧的值应用到上面选择的所有设备。", "Device_MultiEdit_Tooltip": "小心。 单击此按钮会将左侧的值应用到上面选择的所有设备。",
"Device_Searchbox": "搜索", "Device_Searchbox": "搜索",
"Device_Shortcut_AllDevices": "我的设备", "Device_Shortcut_AllDevices": "我的设备",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "已存档", "Device_Shortcut_Archived": "已存档",
"Device_Shortcut_Connected": "在线设备", "Device_Shortcut_Connected": "在线设备",
"Device_Shortcut_Devices": "设备管理", "Device_Shortcut_Devices": "设备管理",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "名字", "Device_TableHead_Name": "名字",
"Device_TableHead_NetworkSite": "网络站点", "Device_TableHead_NetworkSite": "网络站点",
"Device_TableHead_Owner": "所有者", "Device_TableHead_Owner": "所有者",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "父节点", "Device_TableHead_Parent_MAC": "父节点",
"Device_TableHead_Port": "端口", "Device_TableHead_Port": "端口",
"Device_TableHead_PresentLastScan": "", "Device_TableHead_PresentLastScan": "",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "排行", "Device_TableHead_RowID": "排行",
"Device_TableHead_Rowid": "排行", "Device_TableHead_Rowid": "排行",
"Device_TableHead_SSID": "SSID", "Device_TableHead_SSID": "SSID",
@@ -704,23 +709,18 @@
"WF_Trigger": "", "WF_Trigger": "",
"WF_Trigger_event_type": "", "WF_Trigger_event_type": "",
"WF_Trigger_type": "", "WF_Trigger_type": "",
"add_icon_event_icon": "",
"add_icon_event_tooltip": "", "add_icon_event_tooltip": "",
"add_option_event_icon": "",
"add_option_event_tooltip": "", "add_option_event_tooltip": "",
"copy_icons_event_icon": "",
"copy_icons_event_tooltip": "", "copy_icons_event_tooltip": "",
"devices_old": "刷新中...", "devices_old": "刷新中...",
"general_event_description": "您触发的事件可能需要一段时间才能完成后台进程。一旦以下执行队列清空,执行就会结束(如果遇到问题,请检查<a href='/maintenance.php#tab_Logging'>错误日志</a>)。<br/> <br/> 执行队列:", "general_event_description": "您触发的事件可能需要一段时间才能完成后台进程。一旦以下执行队列清空,执行就会结束(如果遇到问题,请检查<a href='/maintenance.php#tab_Logging'>错误日志</a>)。<br/> <br/> 执行队列:",
"general_event_title": "执行自组织网络事件", "general_event_title": "执行自组织网络事件",
"go_to_node_event_icon": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "通知guid", "report_guid": "通知guid",
"report_guid_missing": "未找到链接的通知。最近发送的通知与可用通知之间存在短暂延迟。几秒钟后刷新页面并缓存。所选通知也可能已在维护期间被删除,如 <code>DBCLNP_NOTIFI_HIST</code> 设置中所述。<br/> <br/>系统将改为显示最新通知。缺失的通知具有以下 GUID", "report_guid_missing": "未找到链接的通知。最近发送的通知与可用通知之间存在短暂延迟。几秒钟后刷新页面并缓存。所选通知也可能已在维护期间被删除,如 <code>DBCLNP_NOTIFI_HIST</code> 设置中所述。<br/> <br/>系统将改为显示最新通知。缺失的通知具有以下 GUID",
"report_select_format": "选择格式:", "report_select_format": "选择格式:",
"report_time": "通知时间:", "report_time": "通知时间:",
"run_event_icon": "",
"run_event_tooltip": "在运行之前,请先启用设置并保存更改。", "run_event_tooltip": "在运行之前,请先启用设置并保存更改。",
"settings_core_icon": "", "settings_core_icon": "",
"settings_core_label": "核", "settings_core_label": "核",
@@ -748,6 +748,5 @@
"settings_system_icon": "", "settings_system_icon": "",
"settings_system_label": "系统", "settings_system_label": "系统",
"settings_update_item_warning": "更新下面的值。请注意遵循先前的格式。<b>未执行验证。</b>", "settings_update_item_warning": "更新下面的值。请注意遵循先前的格式。<b>未执行验证。</b>",
"test_event_icon": "",
"test_event_tooltip": "在测试设置之前,请先保存更改。" "test_event_tooltip": "在测试设置之前,请先保存更改。"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View File

@@ -527,6 +527,34 @@
"string": "All NTFY messages have a priority, which defines how urgently your phone notifies you. On Android, you can set custom notification sounds and vibration patterns on your phone to map to these priorities (see <a href=\"https://docs.ntfy.sh/subscribe/phone/\">Android config</a>)." "string": "All NTFY messages have a priority, which defines how urgently your phone notifies you. On Android, you can set custom notification sounds and vibration patterns on your phone to map to these priorities (see <a href=\"https://docs.ntfy.sh/subscribe/phone/\">Android config</a>)."
} }
] ]
},
{
"function": "VERIFY_SSL",
"type": {
"dataType": "boolean",
"elements": [
{
"elementType": "input",
"elementOptions": [{ "type": "checkbox" }],
"transformers": []
}
]
},
"default_value": true,
"options": [],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "Verify SSL"
}
],
"description": [
{
"language_code": "en_us",
"string": "Enable TLS support. Disable if you are using a self-signed certificate."
}
]
} }
] ]
} }

View File

@@ -98,6 +98,7 @@ def send(html, text):
token = get_setting_value('NTFY_TOKEN') token = get_setting_value('NTFY_TOKEN')
user = get_setting_value('NTFY_USER') user = get_setting_value('NTFY_USER')
pwd = get_setting_value('NTFY_PASSWORD') pwd = get_setting_value('NTFY_PASSWORD')
verify_ssl = get_setting_value('NTFY_VERIFY_SSL')
# prepare request headers # prepare request headers
headers = { headers = {
@@ -121,7 +122,8 @@ def send(html, text):
response = requests.post("{}/{}".format( get_setting_value('NTFY_HOST'), response = requests.post("{}/{}".format( get_setting_value('NTFY_HOST'),
get_setting_value('NTFY_TOPIC')), get_setting_value('NTFY_TOPIC')),
data = text, data = text,
headers = headers) headers = headers,
verify = verify_ssl)
response_status_code = response.status_code response_status_code = response.status_code

View File

@@ -1338,7 +1338,8 @@
{ {
"function": "devParentMAC", "function": "devParentMAC",
"events": [ "events": [
"go_to_node" "go_to_node",
"go_to_device"
], ],
"type": { "type": {
"dataType": "string", "dataType": "string",
@@ -1373,13 +1374,47 @@
"name": [ "name": [
{ {
"language_code": "en_us", "language_code": "en_us",
"string": "Network Node" "string": "Parent Node"
} }
], ],
"description": [ "description": [
{ {
"language_code": "en_us", "language_code": "en_us",
"string": "The MAC address of the network node." "string": "The MAC address of the Parent network node."
}
]
},
{
"function": "devParentRelType",
"type": {
"dataType": "array",
"elements": [
{
"elementType": "select",
"elementOptions": [{ "ordeable": "true"}],
"transformers": ["deviceRelType"]
}
]
},
"default_value": "default",
"options": [
"default",
"child",
"logical",
"nic",
"virtual"
],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "Relationship Type"
}
],
"description": [
{
"language_code": "en_us",
"string": "Defines the relationship between this device and its parent. Selecting <code>nic</code> links it as a network interface, allowing the parents online status to be evaluated using its <code>devReqNicsOnline</code> (“Require NICs Online”) setting. Some relationship types may hide the device from lists; see the <code>UI_hide_rel_types</code> setting for details."
} }
] ]
}, },
@@ -1404,7 +1439,7 @@
"name": [ "name": [
{ {
"language_code": "en_us", "language_code": "en_us",
"string": "Network Node Port" "string": "Parent Node Port"
} }
], ],
"description": [ "description": [
@@ -1414,6 +1449,34 @@
} }
] ]
}, },
{
"function": "devChildrenDynamic",
"type": {
"dataType": "array",
"elements": [
{
"elementType": "select",
"elementOptions": [{ "multiple": "true", "ordeable": "true", "readonly": "true" }],
"transformers": ["deviceChip"]
}
]
},
"default_value": [],
"options": [],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "Children Nodes"
}
],
"description": [
{
"language_code": "en_us",
"string": "Children nodes assigned to this device. Navigate to the child device directly to edit the relationship and details."
}
]
},
{ {
"function": "devSSID", "function": "devSSID",
"type": { "type": {
@@ -1665,6 +1728,69 @@
"string": "Fully Qualified Domain Name - Autodetected and Uneditable. Can be auto-refreshed by enabling the <code>REFRESH_FQDN</code> setting." "string": "Fully Qualified Domain Name - Autodetected and Uneditable. Can be auto-refreshed by enabling the <code>REFRESH_FQDN</code> setting."
} }
] ]
},
{
"function": "devReqNicsOnline",
"type": {
"dataType": "integer",
"elements": [
{
"elementType": "input",
"elementOptions": [
{
"type": "checkbox"
}
],
"transformers": []
}
]
},
"default_value": 0,
"options": [],
"localized": [
"name",
"description"
],
"name": [
{
"language_code": "en_us",
"string": "Require NICs Online"
}
],
"description": [
{
"language_code": "en_us",
"string": "Indicates whether this device should be considered online only if all associated NICs (devices with the <code>nic</code> relationship type) are online. If disabled, the device is considered online if any NIC is online."
}
]
},
{
"function": "devChildrenNicsDynamic",
"type": {
"dataType": "array",
"elements": [
{
"elementType": "select",
"elementOptions": [{ "multiple": "true", "ordeable": "true", "readonly": "true" }],
"transformers": ["deviceChip"]
}
]
},
"default_value": [],
"options": [],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "NICs"
}
],
"description": [
{
"language_code": "en_us",
"string": "Children nodes with the <code>nic</code> Relationship Type. Navigate to the child device directly to edit the relationship and details."
}
]
} }
], ],
"required": [], "required": [],

View File

@@ -378,7 +378,9 @@
"Device_TableHead_PresentLastScan", "Device_TableHead_PresentLastScan",
"Device_TableHead_AlertDown", "Device_TableHead_AlertDown",
"Device_TableHead_CustomProps", "Device_TableHead_CustomProps",
"Device_TableHead_FQDN" "Device_TableHead_FQDN",
"Device_TableHead_ParentRelType",
"Device_TableHead_ReqNicsOnline"
], ],
"localized": ["name", "description"], "localized": ["name", "description"],
"name": [ "name": [
@@ -515,6 +517,43 @@
} }
] ]
}, },
{
"function": "hide_rel_types",
"type": {
"dataType": "array",
"elements": [
{
"elementType": "select",
"elementOptions": [{ "multiple": "true", "ordeable": "true" }],
"transformers": []
}
]
},
"maxLength": 50,
"default_value": [
"nic",
"virtual"
],
"options": [
"child",
"logical",
"nic",
"virtual"
],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "Relationships to hide"
}
],
"description": [
{
"language_code": "en_us",
"string": "Specifies which device relationships to their parent node should be hidden from the devices lists. Devices with a matching <code>devParentRelType</code> will be excluded from most lists."
}
]
},
{ {
"function": "hide_empty", "function": "hide_empty",
"type": { "type": {

View File

@@ -11,16 +11,16 @@ Specify the following settings in the Settings section of NetAlertX:
- `UNFIMP_host` - Host URL or IP address where the UNIFI controller is hosted (excluding `http://`) - `UNFIMP_host` - Host URL or IP address where the UNIFI controller is hosted (excluding `http://`)
- `UNFIMP_sites` - Name of the sites (usually 'default', check the URL in your UniFi controller UI if unsure. The site id is in the following part of the URL: `https://192.168.1.1:8443/manage/site/this-is-the-site-id/settings/`). - `UNFIMP_sites` - Name of the sites (usually 'default', check the URL in your UniFi controller UI if unsure. The site id is in the following part of the URL: `https://192.168.1.1:8443/manage/site/this-is-the-site-id/settings/`).
- `UNFIMP_protocol` - https:// or http:// - `UNFIMP_protocol` - https:// or http://
- `UNFIMP_port` - Usually `8443` or `8843` - `UNFIMP_port` - Usually `8443`, `8843`, or `443`
- `UNFIMP_version` - see below table for details - `UNFIMP_version` - see below table for details
#### Version table #### Config overview
| Controller | `UNFIMP_version` | | Controller | `UNFIMP_version` | `UNFIMP_port` |
| ------------------------------------------------------ | ------------------------- | | ------------------------------------------------------ | ------------------------- | ---------------- |
| Cloud Gateway Ultra / UCK cloudkey V2 plus (v4.0.18) | `UDMP-unifiOS` | | Cloud Gateway Ultra / UCK cloudkey V2 plus (v4.0.18) | `UDMP-unifiOS` | `443` |
| Docker hosted | `v5` | | Docker hosted | `v5` | `8443` (usually) |
### Notes ### Notes

View File

@@ -12,7 +12,7 @@ import sys
import requests import requests
from requests import Request, Session, packages from requests import Request, Session, packages
from requests.packages.urllib3.exceptions import InsecureRequestWarning from requests.packages.urllib3.exceptions import InsecureRequestWarning
from nax_pyunifi.controller import Controller from pyunifi.controller import Controller
# Register NetAlertX directories # Register NetAlertX directories

View File

@@ -44,7 +44,8 @@ let fieldOptions = [
"devLastIP", "devStaticIP", "devScan", "devLogEvents", "devAlertEvents", "devLastIP", "devStaticIP", "devScan", "devLogEvents", "devAlertEvents",
"devAlertDown", "devSkipRepeated", "devLastNotification", "devPresentLastScan", "devAlertDown", "devSkipRepeated", "devLastNotification", "devPresentLastScan",
"devIsNew", "devLocation", "devIsArchived", "devParentMAC", "devParentPort", "devIsNew", "devLocation", "devIsArchived", "devParentMAC", "devParentPort",
"devIcon", "devSite", "devSSID", "devSyncHubNode", "devSourcePlugin", "devFQDN" "devIcon", "devSite", "devSSID", "devSyncHubNode", "devSourcePlugin", "devFQDN",
"devParentRelType", "devReqNicsOnline"
]; ];
let triggerTypes = [ let triggerTypes = [

View File

@@ -46,6 +46,16 @@ You will need to install dependencies in the container:
pip install paramiko pip install paramiko
``` ```
You could achieve this by mounting a custom cron file to `/etc/crontabs/root`:
```bash
# Schedule cron jobs
* * * * * /app/back/cron_script.sh
* * * * * /opt/venv/bin/python3 -c "import paramiko" || (/opt/venv/bin/pip install paramiko >/dev/null 2>&1 && sed -i '/pip install paramiko/d' /etc/crontabs/root)
```
Please double check the [default cron file](https://github.com/jokob-sk/NetAlertX/blob/main/install/crontab) hasn't changed.
#### Using Password Authentication #### Using Password Authentication
```sh ```sh
./script.py --host 192.168.1.1 --username admin --password mypassword --output /tmp/dnsmasq.leases ./script.py --host 192.168.1.1 --username admin --password mypassword --output /tmp/dnsmasq.leases

View File

@@ -47,7 +47,7 @@ sql_devices_all = """
IFNULL(devAlertDown, '') AS devAlertDown, IFNULL(devAlertDown, '') AS devAlertDown,
IFNULL(devSkipRepeated, '') AS devSkipRepeated, IFNULL(devSkipRepeated, '') AS devSkipRepeated,
IFNULL(devLastNotification, '') AS devLastNotification, IFNULL(devLastNotification, '') AS devLastNotification,
IFNULL(devPresentLastScan, '') AS devPresentLastScan, IFNULL(devPresentLastScan, 0) AS devPresentLastScan,
IFNULL(devIsNew, '') AS devIsNew, IFNULL(devIsNew, '') AS devIsNew,
IFNULL(devLocation, '') AS devLocation, IFNULL(devLocation, '') AS devLocation,
IFNULL(devIsArchived, '') AS devIsArchived, IFNULL(devIsArchived, '') AS devIsArchived,
@@ -61,6 +61,8 @@ sql_devices_all = """
IFNULL(devSourcePlugin, '') AS devSourcePlugin, IFNULL(devSourcePlugin, '') AS devSourcePlugin,
IFNULL(devCustomProps, '') AS devCustomProps, IFNULL(devCustomProps, '') AS devCustomProps,
IFNULL(devFQDN, '') AS devFQDN, IFNULL(devFQDN, '') AS devFQDN,
IFNULL(devParentRelType, '') AS devParentRelType,
IFNULL(devReqNicsOnline, '') AS devReqNicsOnline,
CASE CASE
WHEN devIsNew = 1 THEN 'New' WHEN devIsNew = 1 THEN 'New'
WHEN devPresentLastScan = 1 THEN 'On-line' WHEN devPresentLastScan = 1 THEN 'On-line'

View File

@@ -87,6 +87,14 @@ class DB():
# devFQDN # devFQDN
if ensure_column(self.sql, "Devices", "devFQDN", "TEXT") is False: if ensure_column(self.sql, "Devices", "devFQDN", "TEXT") is False:
return # addition failed return # addition failed
# devParentRelType
if ensure_column(self.sql, "Devices", "devParentRelType", "TEXT") is False:
return # addition failed
# devRequireNicsOnline
if ensure_column(self.sql, "Devices", "devReqNicsOnline", "INTEGER") is False:
return # addition failed
# Settings table setup # Settings table setup
ensure_Settings(self.sql) ensure_Settings(self.sql)

View File

@@ -56,7 +56,7 @@ def ensure_column(sql, table: str, column_name: str, column_type: str) -> bool:
return False return False
if extra: if extra:
msg = f'[db_upgrade] Extra DB columns detected in {table}: {', '.join(extra)}' msg = f"[db_upgrade] Extra DB columns detected in {table}: {', '.join(extra)}"
mylog('none', [msg]) mylog('none', [msg])
# Add missing column # Add missing column

View File

@@ -74,6 +74,8 @@ class Device(ObjectType):
devIpLong = Int() devIpLong = Int()
devFilterStatus = String() devFilterStatus = String()
devFQDN = String() devFQDN = String()
devParentRelType = String()
devReqNicsOnline = Int()
class DeviceResult(ObjectType): class DeviceResult(ObjectType):
@@ -133,12 +135,19 @@ class Query(ObjectType):
status = options.status status = options.status
mylog('verbose', f'[graphql_schema] Applying status filter: {status}') mylog('verbose', f'[graphql_schema] Applying status filter: {status}')
# Example filtering based on the "status" # Filtering based on the "status"
if status == "my_devices": if status == "my_devices":
# Include devices matching criteria in UI_MY_DEVICES # Include devices matching criteria in UI_MY_DEVICES
allowed_statuses = get_setting_value("UI_MY_DEVICES") allowed_statuses = get_setting_value("UI_MY_DEVICES")
hidden_relationships = get_setting_value("UI_hide_rel_types") # 🆕
mylog('verbose', f'[graphql_schema] allowed_statuses: {allowed_statuses}') mylog('verbose', f'[graphql_schema] allowed_statuses: {allowed_statuses}')
mylog('verbose', f'[graphql_schema] hidden_relationships: {hidden_relationships}')
devices_data = [
device for device in devices_data
if ( device.get("devParentRelType") not in hidden_relationships)
]
devices_data = [ devices_data = [
device for device in devices_data device for device in devices_data
@@ -165,6 +174,8 @@ class Query(ObjectType):
devices_data = [device for device in devices_data if device["devIsArchived"] == 1] devices_data = [device for device in devices_data if device["devIsArchived"] == 1]
elif status == "offline": elif status == "offline":
devices_data = [device for device in devices_data if device["devPresentLastScan"] == 0] devices_data = [device for device in devices_data if device["devPresentLastScan"] == 0]
elif status == "all_nodes":
devices_data = devices_data # keep all
# additional filters # additional filters
if options.filters: if options.filters:
@@ -175,13 +186,13 @@ class Query(ObjectType):
if str(device.get(filter.filterColumn, "")).lower() == str(filter.filterValue).lower() if str(device.get(filter.filterColumn, "")).lower() == str(filter.filterValue).lower()
] ]
# Filter data if a search term is provided # Search data if a search term is provided
if options.search: if options.search:
# Define static list of searchable fields # Define static list of searchable fields
searchable_fields = [ searchable_fields = [
"devName", "devMac", "devOwner", "devType", "devVendor", "devLastIP", "devName", "devMac", "devOwner", "devType", "devVendor", "devLastIP",
"devGroup", "devComments", "devLocation", "devStatus", "devGroup", "devComments", "devLocation", "devStatus", "devSSID",
"devSSID", "devSite", "devSourcePlugin", "devSyncHubNode", "devFQDN" "devSite", "devSourcePlugin", "devSyncHubNode", "devFQDN", "devParentRelType"
] ]
search_term = options.search.lower() search_term = options.search.lower()

View File

@@ -1,18 +1,19 @@
import sys import sys
import subprocess
import conf
import os
import re
# Register NetAlertX directories # Register NetAlertX directories
INSTALL_PATH="/app" INSTALL_PATH="/app"
sys.path.extend([f"{INSTALL_PATH}/server"]) sys.path.extend([f"{INSTALL_PATH}/server"])
import subprocess from helper import timeNowTZ, get_setting_value, list_to_where, check_IP_format, sanitize_SQL_input
import conf
import os
import re
from helper import timeNowTZ, get_setting, get_setting_value, list_to_where, check_IP_format, sanitize_SQL_input
from logger import mylog from logger import mylog
from const import vendorsPath, vendorsPathNewest, sql_generateGuid from const import vendorsPath, vendorsPathNewest, sql_generateGuid
from models.device_instance import DeviceInstance from models.device_instance import DeviceInstance
from scan.name_resolution import NameResolver from scan.name_resolution import NameResolver
from scan.device_heuristics import guess_icon, guess_type
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Removing devices from the CurrentScan DB table which the user chose to ignore by MAC or IP # Removing devices from the CurrentScan DB table which the user chose to ignore by MAC or IP
@@ -44,228 +45,8 @@ def exclude_ignored_devices(db):
mylog('debug', f'[New Devices] Excluding Ignored Devices Query: {query}') mylog('debug', f'[New Devices] Excluding Ignored Devices Query: {query}')
sql.execute(query) sql.execute(query)
#-------------------------------------------------------------------------------
def save_scanned_devices (db):
sql = db.sql #TO-DO
# Add Local MAC of default local interface
local_mac_cmd = ["/sbin/ifconfig `ip -o route get 1 | sed 's/^.*dev \\([^ ]*\\).*$/\\1/;q'` | grep ether | awk '{print $2}'"]
local_mac = subprocess.Popen (local_mac_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0].decode().strip()
local_ip_cmd = ["ip -o route get 1 | sed 's/^.*src \\([^ ]*\\).*$/\\1/;q'"]
local_ip = subprocess.Popen (local_ip_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0].decode().strip()
mylog('debug', ['[Save Devices] Saving this IP into the CurrentScan table:', local_ip])
if check_IP_format(local_ip) == '':
local_ip = '0.0.0.0'
# Proceed if variable contains valid MAC
if check_mac_or_internet(local_mac):
sql.execute (f"""INSERT OR IGNORE INTO CurrentScan (cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod) VALUES ( '{local_mac}', '{local_ip}', Null, 'local_MAC') """)
#-------------------------------------------------------------------------------
def print_scan_stats(db):
sql = db.sql # TO-DO
query = """
SELECT
(SELECT COUNT(*) FROM CurrentScan) AS devices_detected,
(SELECT COUNT(*) FROM CurrentScan WHERE NOT EXISTS (SELECT 1 FROM Devices WHERE devMac = cur_MAC)) AS new_devices,
(SELECT COUNT(*) FROM Devices WHERE devAlertDown != 0 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE devMac = cur_MAC)) AS down_alerts,
(SELECT COUNT(*) FROM Devices WHERE devAlertDown != 0 AND devPresentLastScan = 1 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE devMac = cur_MAC)) AS new_down_alerts,
(SELECT COUNT(*) FROM Devices WHERE devPresentLastScan = 0) AS new_connections,
(SELECT COUNT(*) FROM Devices WHERE devPresentLastScan = 1 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE devMac = cur_MAC)) AS disconnections,
(SELECT COUNT(*) FROM Devices, CurrentScan WHERE devMac = cur_MAC AND devLastIP <> cur_IP) AS ip_changes,
cur_ScanMethod,
COUNT(*) AS scan_method_count
FROM CurrentScan
GROUP BY cur_ScanMethod
"""
sql.execute(query)
stats = sql.fetchall()
mylog('verbose', f'[Scan Stats] Devices Detected.......: {stats[0]["devices_detected"]}')
mylog('verbose', f'[Scan Stats] New Devices............: {stats[0]["new_devices"]}')
mylog('verbose', f'[Scan Stats] Down Alerts............: {stats[0]["down_alerts"]}')
mylog('verbose', f'[Scan Stats] New Down Alerts........: {stats[0]["new_down_alerts"]}')
mylog('verbose', f'[Scan Stats] New Connections........: {stats[0]["new_connections"]}')
mylog('verbose', f'[Scan Stats] Disconnections.........: {stats[0]["disconnections"]}')
mylog('verbose', f'[Scan Stats] IP Changes.............: {stats[0]["ip_changes"]}')
# if str(stats[0]["new_devices"]) != '0':
mylog('trace', f' ================ DEVICES table content ================')
sql.execute('select * from Devices')
rows = sql.fetchall()
for row in rows:
row_dict = dict(row)
mylog('trace', f' {row_dict}')
mylog('trace', f' ================ CurrentScan table content ================')
sql.execute('select * from CurrentScan')
rows = sql.fetchall()
for row in rows:
row_dict = dict(row)
mylog('trace', f' {row_dict}')
mylog('trace', f' ================ Events table content where eve_PendingAlertEmail = 1 ================')
sql.execute('select * from Events where eve_PendingAlertEmail = 1')
rows = sql.fetchall()
for row in rows:
row_dict = dict(row)
mylog('trace', f' {row_dict}')
mylog('trace', f' ================ Events table COUNT ================')
sql.execute('select count(*) from Events')
rows = sql.fetchall()
for row in rows:
row_dict = dict(row)
mylog('trace', f' {row_dict}')
mylog('verbose', '[Scan Stats] Scan Method Statistics:')
for row in stats:
if row["cur_ScanMethod"] is not None:
mylog('verbose', f' {row["cur_ScanMethod"]}: {row["scan_method_count"]}')
#-------------------------------------------------------------------------------
def create_new_devices (db):
sql = db.sql # TO-DO
startTime = timeNowTZ()
# Insert events for new devices from CurrentScan
mylog('debug','[New Devices] New devices - 1 Events')
query = f"""INSERT INTO Events (eve_MAC, eve_IP, eve_DateTime,
eve_EventType, eve_AdditionalInfo,
eve_PendingAlertEmail)
SELECT cur_MAC, cur_IP, '{startTime}', 'New Device', cur_Vendor, 1
FROM CurrentScan
WHERE NOT EXISTS (SELECT 1 FROM Devices
WHERE devMac = cur_MAC)
"""
mylog('debug',f'[New Devices] Log Events Query: {query}')
sql.execute(query)
mylog('debug',f'[New Devices] Insert Connection into session table')
sql.execute (f"""INSERT INTO Sessions (ses_MAC, ses_IP, ses_EventTypeConnection, ses_DateTimeConnection,
ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_StillConnected, ses_AdditionalInfo)
SELECT cur_MAC, cur_IP,'Connected','{startTime}', NULL , NULL ,1, cur_Vendor
FROM CurrentScan
WHERE NOT EXISTS (SELECT 1 FROM Sessions
WHERE ses_MAC = cur_MAC)
""")
# Create new devices from CurrentScan
mylog('debug','[New Devices] 2 Create devices')
# default New Device values preparation
newDevColumns = """devAlertEvents,
devAlertDown,
devPresentLastScan,
devIsArchived,
devIsNew,
devSkipRepeated,
devScan,
devOwner,
devFavorite,
devGroup,
devComments,
devLogEvents,
devLocation,
devCustomProps"""
newDevDefaults = f"""{get_setting_value('NEWDEV_devAlertEvents')},
{get_setting_value('NEWDEV_devAlertDown')},
{get_setting_value('NEWDEV_devPresentLastScan')},
{get_setting_value('NEWDEV_devIsArchived')},
{get_setting_value('NEWDEV_devIsNew')},
{get_setting_value('NEWDEV_devSkipRepeated')},
{get_setting_value('NEWDEV_devScan')},
'{sanitize_SQL_input(get_setting_value('NEWDEV_devOwner'))}',
{get_setting_value('NEWDEV_devFavorite')},
'{sanitize_SQL_input(get_setting_value('NEWDEV_devGroup'))}',
'{sanitize_SQL_input(get_setting_value('NEWDEV_devComments'))}',
{get_setting_value('NEWDEV_devLogEvents')},
'{sanitize_SQL_input(get_setting_value('NEWDEV_devLocation'))}',
'{sanitize_SQL_input(get_setting_value('NEWDEV_devCustomProps'))}'
"""
# Fetch data from CurrentScan skipping ignored devices by IP and MAC
query = f"""SELECT cur_MAC, cur_Name, cur_Vendor, cur_ScanMethod, cur_IP, cur_SyncHubNodeName, cur_NetworkNodeMAC, cur_PORT, cur_NetworkSite, cur_SSID, cur_Type
FROM CurrentScan """
mylog('debug',f'[New Devices] Collecting New Devices Query: {query}')
current_scan_data = sql.execute(query).fetchall()
for row in current_scan_data:
cur_MAC, cur_Name, cur_Vendor, cur_ScanMethod, cur_IP, cur_SyncHubNodeName, cur_NetworkNodeMAC, cur_PORT, cur_NetworkSite, cur_SSID, cur_Type = row
# Handle NoneType
cur_Name = cur_Name.strip() if cur_Name else '(unknown)'
cur_Type = cur_Type.strip() if cur_Type else get_setting_value("NEWDEV_devType")
cur_NetworkNodeMAC = cur_NetworkNodeMAC.strip() if cur_NetworkNodeMAC else ''
cur_NetworkNodeMAC = cur_NetworkNodeMAC if cur_NetworkNodeMAC and cur_MAC != "Internet" else (get_setting_value("NEWDEV_devParentMAC") if cur_MAC != "Internet" else "null")
cur_SyncHubNodeName = cur_SyncHubNodeName if cur_SyncHubNodeName and cur_SyncHubNodeName != "null" else (get_setting_value("SYNC_node_name"))
# Preparing the individual insert statement
sqlQuery = f"""INSERT OR IGNORE INTO Devices
(
devMac,
devName,
devVendor,
devLastIP,
devFirstConnection,
devLastConnection,
devSyncHubNode,
devGUID,
devParentMAC,
devParentPort,
devSite,
devSSID,
devType,
devSourcePlugin,
{newDevColumns}
)
VALUES
(
'{sanitize_SQL_input(cur_MAC)}',
'{sanitize_SQL_input(cur_Name)}',
'{sanitize_SQL_input(cur_Vendor)}',
'{sanitize_SQL_input(cur_IP)}',
?,
?,
'{sanitize_SQL_input(cur_SyncHubNodeName)}',
{sql_generateGuid},
'{sanitize_SQL_input(cur_NetworkNodeMAC)}',
'{sanitize_SQL_input(cur_PORT)}',
'{sanitize_SQL_input(cur_NetworkSite)}',
'{sanitize_SQL_input(cur_SSID)}',
'{sanitize_SQL_input(cur_Type)}',
'{sanitize_SQL_input(cur_ScanMethod)}',
{newDevDefaults}
)"""
mylog('trace', f'[New Devices] Create device SQL: {sqlQuery}')
sql.execute(sqlQuery, (startTime, startTime))
mylog('debug','[New Devices] New Devices end')
db.commitDB()
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def update_devices_data_from_scan (db): def update_devices_data_from_scan (db):
sql = db.sql #TO-DO sql = db.sql #TO-DO
@@ -275,8 +56,7 @@ def update_devices_data_from_scan (db):
mylog('debug', '[Update Devices] 1 Last Connection') mylog('debug', '[Update Devices] 1 Last Connection')
sql.execute(f"""UPDATE Devices SET devLastConnection = '{startTime}', sql.execute(f"""UPDATE Devices SET devLastConnection = '{startTime}',
devPresentLastScan = 1 devPresentLastScan = 1
WHERE devPresentLastScan = 0 WHERE EXISTS (SELECT 1 FROM CurrentScan
AND EXISTS (SELECT 1 FROM CurrentScan
WHERE devMac = cur_MAC) """) WHERE devMac = cur_MAC) """)
# Clean no active devices # Clean no active devices
@@ -433,14 +213,15 @@ def update_devices_data_from_scan (db):
if len(recordsToUpdate) > 0: if len(recordsToUpdate) > 0:
sql.executemany ("UPDATE Devices SET devVendor = ? WHERE devMac = ? ", recordsToUpdate ) sql.executemany ("UPDATE Devices SET devVendor = ? WHERE devMac = ? ", recordsToUpdate )
# Update devPresentLastScan based on NICs presence
update_devPresentLastScan_based_on_nics(db)
# Guess ICONS # Guess ICONS
recordsToUpdate = [] recordsToUpdate = []
default_icon = get_setting_value('NEWDEV_devIcon') default_icon = get_setting_value('NEWDEV_devIcon')
if get_setting_value('NEWDEV_replace_preset_icon'): if get_setting_value('NEWDEV_replace_preset_icon'):
query = f"""SELECT * FROM Devices query = f"""SELECT * FROM Devices
WHERE devIcon in ('', 'null', '{default_icon}') WHERE devIcon in ('', 'null', '{default_icon}')
@@ -481,6 +262,231 @@ def update_devices_data_from_scan (db):
mylog('debug','[Update Devices] Update devices end') mylog('debug','[Update Devices] Update devices end')
#-------------------------------------------------------------------------------
def save_scanned_devices (db):
sql = db.sql #TO-DO
# Add Local MAC of default local interface
local_mac_cmd = ["/sbin/ifconfig `ip -o route get 1 | sed 's/^.*dev \\([^ ]*\\).*$/\\1/;q'` | grep ether | awk '{print $2}'"]
local_mac = subprocess.Popen (local_mac_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0].decode().strip()
local_ip_cmd = ["ip -o route get 1 | sed 's/^.*src \\([^ ]*\\).*$/\\1/;q'"]
local_ip = subprocess.Popen (local_ip_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0].decode().strip()
mylog('debug', ['[Save Devices] Saving this IP into the CurrentScan table:', local_ip])
if check_IP_format(local_ip) == '':
local_ip = '0.0.0.0'
# Proceed if variable contains valid MAC
if check_mac_or_internet(local_mac):
sql.execute (f"""INSERT OR IGNORE INTO CurrentScan (cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod) VALUES ( '{local_mac}', '{local_ip}', Null, 'local_MAC') """)
#-------------------------------------------------------------------------------
def print_scan_stats(db):
sql = db.sql # TO-DO
query = """
SELECT
(SELECT COUNT(*) FROM CurrentScan) AS devices_detected,
(SELECT COUNT(*) FROM CurrentScan WHERE NOT EXISTS (SELECT 1 FROM Devices WHERE devMac = cur_MAC)) AS new_devices,
(SELECT COUNT(*) FROM Devices WHERE devAlertDown != 0 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE devMac = cur_MAC)) AS down_alerts,
(SELECT COUNT(*) FROM Devices WHERE devAlertDown != 0 AND devPresentLastScan = 1 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE devMac = cur_MAC)) AS new_down_alerts,
(SELECT COUNT(*) FROM Devices WHERE devPresentLastScan = 0) AS new_connections,
(SELECT COUNT(*) FROM Devices WHERE devPresentLastScan = 1 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE devMac = cur_MAC)) AS disconnections,
(SELECT COUNT(*) FROM Devices, CurrentScan WHERE devMac = cur_MAC AND devLastIP <> cur_IP) AS ip_changes,
cur_ScanMethod,
COUNT(*) AS scan_method_count
FROM CurrentScan
GROUP BY cur_ScanMethod
"""
sql.execute(query)
stats = sql.fetchall()
mylog('verbose', f'[Scan Stats] Devices Detected.......: {stats[0]["devices_detected"]}')
mylog('verbose', f'[Scan Stats] New Devices............: {stats[0]["new_devices"]}')
mylog('verbose', f'[Scan Stats] Down Alerts............: {stats[0]["down_alerts"]}')
mylog('verbose', f'[Scan Stats] New Down Alerts........: {stats[0]["new_down_alerts"]}')
mylog('verbose', f'[Scan Stats] New Connections........: {stats[0]["new_connections"]}')
mylog('verbose', f'[Scan Stats] Disconnections.........: {stats[0]["disconnections"]}')
mylog('verbose', f'[Scan Stats] IP Changes.............: {stats[0]["ip_changes"]}')
# if str(stats[0]["new_devices"]) != '0':
mylog('trace', f' ================ DEVICES table content ================')
sql.execute('select * from Devices')
rows = sql.fetchall()
for row in rows:
row_dict = dict(row)
mylog('trace', f' {row_dict}')
mylog('trace', f' ================ CurrentScan table content ================')
sql.execute('select * from CurrentScan')
rows = sql.fetchall()
for row in rows:
row_dict = dict(row)
mylog('trace', f' {row_dict}')
mylog('trace', f' ================ Events table content where eve_PendingAlertEmail = 1 ================')
sql.execute('select * from Events where eve_PendingAlertEmail = 1')
rows = sql.fetchall()
for row in rows:
row_dict = dict(row)
mylog('trace', f' {row_dict}')
mylog('trace', f' ================ Events table COUNT ================')
sql.execute('select count(*) from Events')
rows = sql.fetchall()
for row in rows:
row_dict = dict(row)
mylog('trace', f' {row_dict}')
mylog('verbose', '[Scan Stats] Scan Method Statistics:')
for row in stats:
if row["cur_ScanMethod"] is not None:
mylog('verbose', f' {row["cur_ScanMethod"]}: {row["scan_method_count"]}')
#-------------------------------------------------------------------------------
def create_new_devices (db):
sql = db.sql # TO-DO
startTime = timeNowTZ()
# Insert events for new devices from CurrentScan
mylog('debug','[New Devices] New devices - 1 Events')
query = f"""INSERT INTO Events (eve_MAC, eve_IP, eve_DateTime,
eve_EventType, eve_AdditionalInfo,
eve_PendingAlertEmail)
SELECT cur_MAC, cur_IP, '{startTime}', 'New Device', cur_Vendor, 1
FROM CurrentScan
WHERE NOT EXISTS (SELECT 1 FROM Devices
WHERE devMac = cur_MAC)
"""
mylog('debug',f'[New Devices] Log Events Query: {query}')
sql.execute(query)
mylog('debug',f'[New Devices] Insert Connection into session table')
sql.execute (f"""INSERT INTO Sessions (ses_MAC, ses_IP, ses_EventTypeConnection, ses_DateTimeConnection,
ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_StillConnected, ses_AdditionalInfo)
SELECT cur_MAC, cur_IP,'Connected','{startTime}', NULL , NULL ,1, cur_Vendor
FROM CurrentScan
WHERE NOT EXISTS (SELECT 1 FROM Sessions
WHERE ses_MAC = cur_MAC)
""")
# Create new devices from CurrentScan
mylog('debug','[New Devices] 2 Create devices')
# default New Device values preparation
newDevColumns = """devAlertEvents,
devAlertDown,
devPresentLastScan,
devIsArchived,
devIsNew,
devSkipRepeated,
devScan,
devOwner,
devFavorite,
devGroup,
devComments,
devLogEvents,
devLocation,
devCustomProps,
devParentRelType,
devReqNicsOnline
"""
newDevDefaults = f"""{get_setting_value('NEWDEV_devAlertEvents')},
{get_setting_value('NEWDEV_devAlertDown')},
{get_setting_value('NEWDEV_devPresentLastScan')},
{get_setting_value('NEWDEV_devIsArchived')},
{get_setting_value('NEWDEV_devIsNew')},
{get_setting_value('NEWDEV_devSkipRepeated')},
{get_setting_value('NEWDEV_devScan')},
'{sanitize_SQL_input(get_setting_value('NEWDEV_devOwner'))}',
{get_setting_value('NEWDEV_devFavorite')},
'{sanitize_SQL_input(get_setting_value('NEWDEV_devGroup'))}',
'{sanitize_SQL_input(get_setting_value('NEWDEV_devComments'))}',
{get_setting_value('NEWDEV_devLogEvents')},
'{sanitize_SQL_input(get_setting_value('NEWDEV_devLocation'))}',
'{sanitize_SQL_input(get_setting_value('NEWDEV_devCustomProps'))}',
'{sanitize_SQL_input(get_setting_value('NEWDEV_devParentRelType'))}',
{sanitize_SQL_input(get_setting_value('NEWDEV_devReqNicsOnline'))}
"""
# Fetch data from CurrentScan skipping ignored devices by IP and MAC
query = f"""SELECT cur_MAC, cur_Name, cur_Vendor, cur_ScanMethod, cur_IP, cur_SyncHubNodeName, cur_NetworkNodeMAC, cur_PORT, cur_NetworkSite, cur_SSID, cur_Type
FROM CurrentScan """
mylog('debug',f'[New Devices] Collecting New Devices Query: {query}')
current_scan_data = sql.execute(query).fetchall()
for row in current_scan_data:
cur_MAC, cur_Name, cur_Vendor, cur_ScanMethod, cur_IP, cur_SyncHubNodeName, cur_NetworkNodeMAC, cur_PORT, cur_NetworkSite, cur_SSID, cur_Type = row
# Handle NoneType
cur_Name = cur_Name.strip() if cur_Name else '(unknown)'
cur_Type = cur_Type.strip() if cur_Type else get_setting_value("NEWDEV_devType")
cur_NetworkNodeMAC = cur_NetworkNodeMAC.strip() if cur_NetworkNodeMAC else ''
cur_NetworkNodeMAC = cur_NetworkNodeMAC if cur_NetworkNodeMAC and cur_MAC != "Internet" else (get_setting_value("NEWDEV_devParentMAC") if cur_MAC != "Internet" else "null")
cur_SyncHubNodeName = cur_SyncHubNodeName if cur_SyncHubNodeName and cur_SyncHubNodeName != "null" else (get_setting_value("SYNC_node_name"))
# Preparing the individual insert statement
sqlQuery = f"""INSERT OR IGNORE INTO Devices
(
devMac,
devName,
devVendor,
devLastIP,
devFirstConnection,
devLastConnection,
devSyncHubNode,
devGUID,
devParentMAC,
devParentPort,
devSite,
devSSID,
devType,
devSourcePlugin,
{newDevColumns}
)
VALUES
(
'{sanitize_SQL_input(cur_MAC)}',
'{sanitize_SQL_input(cur_Name)}',
'{sanitize_SQL_input(cur_Vendor)}',
'{sanitize_SQL_input(cur_IP)}',
?,
?,
'{sanitize_SQL_input(cur_SyncHubNodeName)}',
{sql_generateGuid},
'{sanitize_SQL_input(cur_NetworkNodeMAC)}',
'{sanitize_SQL_input(cur_PORT)}',
'{sanitize_SQL_input(cur_NetworkSite)}',
'{sanitize_SQL_input(cur_SSID)}',
'{sanitize_SQL_input(cur_Type)}',
'{sanitize_SQL_input(cur_ScanMethod)}',
{newDevDefaults}
)"""
mylog('trace', f'[New Devices] Create device SQL: {sqlQuery}')
sql.execute(sqlQuery, (startTime, startTime))
mylog('debug','[New Devices] New Devices end')
db.commitDB()
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def update_devices_names(db): def update_devices_names(db):
sql = db.sql sql = db.sql
@@ -582,8 +588,69 @@ def update_devices_names(db):
# Commit all database changes # Commit all database changes
db.commitDB() db.commitDB()
#-------------------------------------------------------------------------------
# Updates devPresentLastScan for parent devices based on the presence of their NICs
def update_devPresentLastScan_based_on_nics(db):
"""
Updates devPresentLastScan in the Devices table for parent devices
based on the presence of their NICs and the devReqNicsOnline setting.
Args:
db: A database object with `.execute()` and `.fetchall()` methods.
"""
sql = db.sql
# Step 1: Load all devices from the DB
devices = sql.execute("SELECT * FROM Devices").fetchall()
# Convert rows to dicts (assumes sql.row_factory = sqlite3.Row or similar)
devices = [dict(row) for row in devices]
# Build MAC -> NICs map
mac_to_nics = {}
for device in devices:
if device.get("devParentRelType") == "nic":
parent_mac = device.get("devParentMAC")
if parent_mac:
mac_to_nics.setdefault(parent_mac, []).append(device)
# Step 2: For each non-NIC device, determine new devPresentLastScan
updates = []
for device in devices:
if device.get("devParentRelType") == "nic":
continue # skip NICs
mac = device.get("devMac")
if not mac:
continue
req_all = str(device.get("devReqNicsOnline")) == "1"
nics = mac_to_nics.get(mac, [])
original = device.get("devPresentLastScan", 0)
new_present = original
if nics:
nic_statuses = [nic.get("devPresentLastScan") == 1 for nic in nics]
if req_all:
new_present = int(all(nic_statuses))
else:
new_present = int(any(nic_statuses))
# Only add update if changed
if original != new_present:
updates.append((new_present, mac))
# Step 3: Execute batch update
for present, mac in updates:
sql.execute(
"UPDATE Devices SET devPresentLastScan = ? WHERE devMac = ?",
(present, mac)
)
db.commitDB()
return len(updates)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Check if the variable contains a valid MAC address or "Internet" # Check if the variable contains a valid MAC address or "Internet"
@@ -598,12 +665,8 @@ def check_mac_or_internet(input_str):
else: else:
return False return False
#===============================================================================
# Lookup unknown vendors on devices
#===============================================================================
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Lookup unknown vendors on devices
def query_MAC_vendor (pMAC): def query_MAC_vendor (pMAC):
pMACstr = str(pMAC) pMACstr = str(pMAC)
@@ -643,122 +706,4 @@ def query_MAC_vendor (pMAC):
return -1 return -1
#===============================================================================
# Icons
#===============================================================================
#-------------------------------------------------------------------------------
# Base64 encoded HTML string for FontAwesome icons
icons = {
"globe": "PGkgY2xhc3M9ImZhcyBmYS1nbG9iZSI+PC9pPg==", # globe icon
"phone": "PGkgY2xhc3M9ImZhcyBmYS1tb2JpbGUtYWx0Ij48L2k+",
"laptop": "PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==",
"printer": "PGkgY2xhc3M9ImZhIGZhLXByaW50ZXIiPjwvaT4=",
"router": "PGkgY2xhc3M9ImZhcyBmYS1yYW5kb20iPjwvaT4=",
"tv": "PGkgY2xhc3M9ImZhIGZhLXR2Ij48L2k+",
"desktop": "PGkgY2xhc3M9ImZhIGZhLWRlc2t0b3AiPjwvaT4=",
"tablet": "PGkgY2xhc3M9ImZhIGZhLXRhYmxldCI+PC9pPg==",
"watch": "PGkgY2xhc3M9ImZhIGZhLXdhbmNoIj48L2k+",
"camera": "PGkgY2xhc3M9ImZhIGZhLWNhbWVyYSI+PC9pPg==",
"home": "PGkgY2xhc3M9ImZhIGZhLWhvbWUiPjwvaT4=",
"apple": "PGkgY2xhc3M9ImZhYiBmYS1hcHBsZSI+PC9pPg==",
"ethernet": "PGkgY2xhc3M9ImZhcyBmYS1ldGhlcm5ldCI+PC9pPg==",
"google": "PGkgY2xhc3M9ImZhYiBmYS1nb29nbGUiPjwvaT4=",
"raspberry": "PGkgY2xhc3M9ImZhYiBmYS1yYXNwYmVycnktcGkiPjwvaT4=",
"microchip": "PGkgY2xhc3M9ImZhcyBmYS1taWNyb2NoaXAiPjwvaT4="
}
#-------------------------------------------------------------------------------
# Guess device icon
def guess_icon(vendor, mac, ip, name, default):
mylog('debug', [f"[guess_icon] Guessing icon for (vendor|mac|ip|name): ('{vendor}'|'{mac}'|{ip}|{name})"])
result = default
mac = str(mac).upper() if mac else "00:00:00:00:00:00"
vendor = str(vendor).lower() if vendor else "unknown"
name = str(name).lower() if name else "(unknown)"
# Guess icon based on vendor
if any(brand in vendor for brand in {"samsung", "motorola"}):
result = icons.get("phone")
elif "dell" in vendor:
result = icons.get("laptop")
elif "hp" in vendor:
result = icons.get("printer")
elif "cisco" in vendor:
result = icons.get("router")
elif "lg" in vendor:
result = icons.get("tv")
elif "raspberry" in vendor:
result = icons.get("raspberry")
elif "apple" in vendor:
result = icons.get("apple")
elif "google" in vendor:
result = icons.get("google")
elif "ubiquiti" in vendor:
result = icons.get("router")
elif any(brand in vendor for brand in {"espressif"}):
result = icons.get("microchip")
# Guess icon based on MAC address patterns
elif mac == "INTERNET":
result = icons.get("globe")
elif mac.startswith("00:1A:79"): # Apple
result = icons.get("apple")
elif mac.startswith("B0:BE:83"): # Apple
result = icons.get("apple")
elif mac.startswith("00:1B:63"): # Sony
result = icons.get("tablet")
elif mac.startswith("74:AC:B9"): # Unifi
result = icons.get("ethernet")
# Guess icon based on name
elif 'google' in name:
result = icons.get("google")
elif 'desktop' in name:
result = icons.get("desktop")
elif 'raspberry' in name:
result = icons.get("raspberry")
# Guess icon based on IP address ranges
elif ip.startswith("192.168.1."):
result = icons.get("laptop")
return result
#-------------------------------------------------------------------------------
# Guess device type
def guess_type(vendor, mac, ip, name, default):
result = default
mac = str(mac).upper() if mac else "00:00:00:00:00:00"
vendor = str(vendor).lower() if vendor else "unknown"
name = str(name).lower() if name else "(unknown)"
# Guess icon based on vendor
if any(brand in vendor for brand in {"samsung", "motorola"}):
result = "Phone"
elif "cisco" in vendor:
result = "Router"
elif "lg" in vendor:
result = "TV"
elif "google" in vendor:
result = "Phone"
elif "ubiquiti" in vendor:
result = "Router"
# Guess type based on MAC address patterns
elif mac == "INTERNET":
result = "Internet"
# Guess type based on name
elif 'google' in name:
result = "Phone"
# Guess type based on IP address ranges
elif ip == ("192.168.1.1"):
result = "Router"
return result

320
server/scan/device_heuristics.py Executable file
View File

@@ -0,0 +1,320 @@
import sys
import re
from typing import Optional, List, Tuple, Dict
# Register NetAlertX directories
INSTALL_PATH = "/app"
sys.path.extend([f"{INSTALL_PATH}/server"])
import conf
from const import *
from logger import mylog
from helper import timeNowTZ, get_setting_value
#-------------------------------------------------------------------------------
# Base64 encoded HTML strings for FontAwesome icons, now with an extended icons dictionary for broader device coverage
ICONS = {
"globe": "PGkgY2xhc3M9ImZhcyBmYS1nbG9iZSI+PC9pPg==", # Internet or global network
"phone": "PGkgY2xhc3M9ImZhcyBmYS1tb2JpbGUtYWx0Ij48L2k+", # Smartphone
"laptop": "PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==", # Laptop
"printer": "PGkgY2xhc3M9ImZhIGZhLXByaW50ZXIiPjwvaT4=", # Printer
"router": "PGkgY2xhc3M9ImZhcyBmYS1yYW5kb20iPjwvaT4=", # Router or network switch
"tv": "PGkgY2xhc3M9ImZhIGZhLXR2Ij48L2k+", # Television
"desktop": "PGkgY2xhc3M9ImZhIGZhLWRlc2t0b3AiPjwvaT4=", # Desktop PC
"tablet": "PGkgY2xhc3M9ImZhIGZhLXRhYmxldCI+PC9pPg==", # Tablet
"watch": "PGkgY2xhc3M9ImZhcyBmYS1jbG9jayI+PC9pPg==", # Fallback to clock since smartwatch is nonfree in FontAwesome
"camera": "PGkgY2xhc3M9ImZhIGZhLWNhbWVyYSI+PC9pPg==", # Camera or webcam
"home": "PGkgY2xhc3M9ImZhIGZhLWhvbWUiPjwvaT4=", # Smart home device
"apple": "PGkgY2xhc3M9ImZhYiBmYS1hcHBsZSI+PC9pPg==", # Apple device
"ethernet": "PGkgY2xhc3M9ImZhcyBmYS1uZXR3b3JrLXdpcmVkIj48L2k+", # Free alternative for ethernet icon in FontAwesome
"google": "PGkgY2xhc3M9ImZhYiBmYS1nb29nbGUiPjwvaT4=", # Google device
"raspberry": "PGkgY2xhc3M9ImZhYiBmYS1yYXNwYmVycnktcGkiPjwvaT4=", # Raspberry Pi
"microchip": "PGkgY2xhc3M9ImZhcyBmYS1taWNyb2NoaXAiPjwvaT4=", # IoT or embedded device
"server": "PGkgY2xhc3M9ImZhcyBmYS1zZXJ2ZXIiPjwvaT4=", # Server
"gamepad": "PGkgY2xhc3M9ImZhcyBmYS1nYW1lcGFkIj48L2k+", # Gaming console
"lightbulb": "PGkgY2xhc3M9ImZhcyBmYS1saWdodGJ1bGIiPjwvaT4=", # Smart light
"speaker": "PGkgY2xhc3M9ImZhcyBmYS12b2x1bWUtdXAiPjwvaT4=", # Free speaker alt icon for smart speakers in FontAwesome
"lock": "PGkgY2xhc3M9ImZhcyBmYS1sb2NrIj48L2k+", # Security device
}
# Extended device types for comprehensive classification
DEVICE_TYPES = {
"Internet": "Internet Gateway",
"Phone": "Smartphone",
"Laptop": "Laptop",
"Printer": "Printer",
"Router": "Router",
"TV": "Television",
"Desktop": "Desktop PC",
"Tablet": "Tablet",
"Smartwatch": "Smartwatch",
"Camera": "Camera",
"SmartHome": "Smart Home Device",
"Server": "Server",
"GamingConsole": "Gaming Console",
"IoT": "IoT Device",
"NetworkSwitch": "Network Switch",
"AccessPoint": "Access Point",
"SmartLight": "Smart Light",
"SmartSpeaker": "Smart Speaker",
"SecurityDevice": "Security Device",
"Unknown": "Unknown Device",
}
#-------------------------------------------------------------------------------
# Guess device attributes such as type of device and associated device icon
def guess_device_attributes(
vendor: Optional[str],
mac: Optional[str],
ip: Optional[str],
name: Optional[str],
default_icon: str,
default_type: str
) -> Tuple[str, str]:
"""
Guess the appropriate FontAwesome icon and device type based on device attributes.
Args:
vendor: Device vendor name.
mac: Device MAC address.
ip: Device IP address.
name: Device name.
default_icon: Default icon to return if no match is found.
default_type: Default type to return if no match is found.
Returns:
Tuple[str, str]: A tuple containing the guessed icon (Base64-encoded HTML string)
and the guessed device type (string).
"""
mylog('debug', f"[guess_device_attributes] Guessing attributes for (vendor|mac|ip|name): ('{vendor}'|'{mac}'|'{ip}'|'{name}')")
# Normalize inputs
vendor = str(vendor).lower().strip() if vendor else "unknown"
mac = str(mac).upper().strip() if mac else "00:00:00:00:00:00"
ip = str(ip).strip() if ip else "169.254.0.0" # APIPA address for unknown IPs per RFC 3927
name = str(name).lower().strip() if name else "(unknown)"
# --- Icon Guessing Logic ---
if mac == "INTERNET":
icon = ICONS.get("globe", default_icon)
else:
# Vendor-based icon guessing
icon_vendor_patterns = {
"apple": "apple",
"samsung|motorola|xiaomi|huawei": "phone",
"dell|lenovo|asus|acer": "laptop",
"hp|epson|canon|brother": "printer",
"cisco|ubiquiti|netgear|tp-link|d-link|mikrotik": "router",
"lg|samsung electronics|sony|vizio": "tv",
"raspberry pi": "raspberry",
"google": "google",
"espressif|particle": "microchip",
"intel|amd": "desktop",
"amazon": "speaker",
"philips hue|lifx": "lightbulb",
"aruba|meraki": "ethernet",
"qnap|synology": "server",
"nintendo|sony interactive|microsoft": "gamepad",
"ring|blink|arlo": "camera",
"nest": "home",
}
for pattern, icon_key in icon_vendor_patterns.items():
if re.search(pattern, vendor, re.IGNORECASE):
icon = ICONS.get(icon_key, default_icon)
break
else:
# MAC-based icon guessing
mac_clean = mac.replace(':', '').replace('-', '').upper()
icon_mac_patterns = {
"001A79|B0BE83|BC926B": "apple",
"001B63|BC4C4C": "tablet",
"74ACB9|002468": "ethernet",
"B827EB": "raspberry",
"001422|001874": "desktop",
"001CBF|002186": "server",
}
for pattern_str, icon_key in icon_mac_patterns.items():
patterns = [p.replace(':', '').replace('-', '').upper() for p in pattern_str.split('|')]
if any(mac_clean.startswith(p) for p in patterns):
icon = ICONS.get(icon_key, default_icon)
break
else:
# Name-based icon guessing
icon_name_patterns = {
"iphone|ipad|macbook|imac": "apple",
"pixel|galaxy|redmi": "phone",
"laptop|notebook": "laptop",
"printer|print": "printer",
"router|gateway|ap|access[ -]?point": "router",
"tv|television|smarttv": "tv",
"desktop|pc|computer": "desktop",
"tablet|pad": "tablet",
"watch|wear": "watch",
"camera|cam|webcam": "camera",
"echo|alexa|dot": "speaker",
"hue|lifx|bulb": "lightbulb",
"server|nas": "server",
"playstation|xbox|switch": "gamepad",
"raspberry|pi": "raspberry",
"google|chromecast|nest": "google",
"doorbell|lock|security": "lock",
}
for pattern, icon_key in icon_name_patterns.items():
if re.search(pattern, name, re.IGNORECASE):
icon = ICONS.get(icon_key, default_icon)
break
else:
# IP-based icon guessing
icon_ip_patterns = {
r"^192\.168\.[0-1]\.1$": "router",
r"^10\.0\.0\.1$": "router",
r"^192\.168\.[0-1]\.[2-9]$": "desktop",
r"^192\.168\.[0-1]\.1\d{2}$": "phone",
}
for pattern, icon_key in icon_ip_patterns.items():
if re.match(pattern, ip):
icon = ICONS.get(icon_key, default_icon)
break
else:
icon = default_icon
# --- Type Guessing Logic ---
if mac == "INTERNET":
type_ = DEVICE_TYPES.get("Internet", default_type)
else:
# Vendor-based type guessing
type_vendor_patterns = {
"apple|samsung|motorola|xiaomi|huawei": "Phone",
"dell|lenovo|asus|acer|hp": "Laptop",
"epson|canon|brother": "Printer",
"cisco|ubiquiti|netgear|tp-link|d-link|mikrotik|aruba|meraki": "Router",
"lg|samsung electronics|sony|vizio": "TV",
"raspberry pi": "IoT",
"google|nest": "SmartHome",
"espressif|particle": "IoT",
"intel|amd": "Desktop",
"amazon": "SmartSpeaker",
"philips hue|lifx": "SmartLight",
"qnap|synology": "Server",
"nintendo|sony interactive|microsoft": "GamingConsole",
"ring|blink|arlo": "Camera",
}
for pattern, type_key in type_vendor_patterns.items():
if re.search(pattern, vendor, re.IGNORECASE):
type_ = DEVICE_TYPES.get(type_key, default_type)
break
else:
# MAC-based type guessing
mac_clean = mac.replace(':', '').replace('-', '').upper()
type_mac_patterns = {
"00:1A:79|B0:BE:83|BC:92:6B": "Phone",
"00:1B:63|BC:4C:4C": "Tablet",
"74:AC:B9|00:24:68": "AccessPoint",
"B8:27:EB": "IoT",
"00:14:22|00:18:74": "Desktop",
"00:1C:BF|00:21:86": "Server",
}
for pattern_str, type_key in type_mac_patterns.items():
patterns = [p.replace(':', '').replace('-', '').upper() for p in pattern_str.split('|')]
if any(mac_clean.startswith(p) for p in patterns):
type_ = DEVICE_TYPES.get(type_key, default_type)
break
else:
# Name-based type guessing
type_name_patterns = {
"iphone|ipad": "Phone",
"macbook|imac": "Laptop",
"pixel|galaxy|redmi": "Phone",
"laptop|notebook": "Laptop",
"printer|print": "Printer",
"router|gateway|ap|access[ -]?point": "Router",
"tv|television|smarttv": "TV",
"desktop|pc|computer": "Desktop",
"tablet|pad": "Tablet",
"watch|wear": "Smartwatch",
"camera|cam|webcam": "Camera",
"echo|alexa|dot": "SmartSpeaker",
"hue|lifx|bulb": "SmartLight",
"server|nas": "Server",
"playstation|xbox|switch": "GamingConsole",
"raspberry|pi": "IoT",
"google|chromecast|nest": "SmartHome",
"doorbell|lock|security": "SecurityDevice",
}
for pattern, type_key in type_name_patterns.items():
if re.search(pattern, name, re.IGNORECASE):
type_ = DEVICE_TYPES.get(type_key, default_type)
break
else:
# IP-based type guessing
type_ip_patterns = {
r"^192\.168\.[0-1]\.1$": "Router",
r"^10\.0\.0\.1$": "Router",
r"^192\.168\.[0-1]\.[2-9]$": "Desktop",
r"^192\.168\.[0-1]\.1\d{2}$": "Phone",
}
for pattern, type_key in type_ip_patterns.items():
if re.match(pattern, ip):
type_ = DEVICE_TYPES.get(type_key, default_type)
break
else:
type_ = default_type
return icon, type_
# Deprecated functions with redirects (To be removed once all calls for these have been adjusted to use the updated function)
def guess_icon(
vendor: Optional[str],
mac: Optional[str],
ip: Optional[str],
name: Optional[str],
default: str
) -> str:
"""
[DEPRECATED] Guess the appropriate FontAwesome icon for a device based on its attributes.
Use guess_device_attributes instead.
Args:
vendor: Device vendor name.
mac: Device MAC address.
ip: Device IP address.
name: Device name.
default: Default icon to return if no match is found.
Returns:
str: Base64-encoded FontAwesome icon HTML string.
"""
icon, _ = guess_device_attributes(vendor, mac, ip, name, default, "unknown_type")
return icon
def guess_type(
vendor: Optional[str],
mac: Optional[str],
ip: Optional[str],
name: Optional[str],
default: str
) -> str:
"""
[DEPRECATED] Guess the device type based on its attributes.
Use guess_device_attributes instead.
Args:
vendor: Device vendor name.
mac: Device MAC address.
ip: Device IP address.
name: Device name.
default: Default type to return if no match is found.
Returns:
str: Device type from DEVICE_TYPES dictionary.
"""
_, type_ = guess_device_attributes(vendor, mac, ip, name, "unknown_icon", default)
return type_
# Handler for when this is run as a program instead of called as a module.
if __name__ == "__main__":
mylog('error', "This module is not intended to be run directly.")

View File

@@ -5,7 +5,7 @@ INSTALL_PATH="/app"
sys.path.extend([f"{INSTALL_PATH}/server"]) sys.path.extend([f"{INSTALL_PATH}/server"])
import conf import conf
from scan.device_handling import create_new_devices, print_scan_stats, save_scanned_devices, update_devices_data_from_scan, exclude_ignored_devices from scan.device_handling import create_new_devices, print_scan_stats, save_scanned_devices, exclude_ignored_devices, update_devices_data_from_scan
from helper import timeNowTZ, print_table_schema, get_setting_value from helper import timeNowTZ, print_table_schema, get_setting_value
from logger import mylog, Logger from logger import mylog, Logger
from messaging.reporting import skip_repeated_notifications from messaging.reporting import skip_repeated_notifications
@@ -252,9 +252,9 @@ def insertOnlineHistory(db):
query = """ query = """
SELECT SELECT
COUNT(*) AS allDevices, COUNT(*) AS allDevices,
SUM(CASE WHEN devIsArchived = 1 THEN 1 ELSE 0 END) AS archivedDevices, COALESCE(SUM(CASE WHEN devIsArchived = 1 THEN 1 ELSE 0 END), 0) AS archivedDevices,
SUM(CASE WHEN devPresentLastScan = 1 THEN 1 ELSE 0 END) AS onlineDevices, COALESCE(SUM(CASE WHEN devPresentLastScan = 1 THEN 1 ELSE 0 END), 0) AS onlineDevices,
SUM(CASE WHEN devPresentLastScan = 0 AND devAlertDown = 1 THEN 1 ELSE 0 END) AS downDevices COALESCE(SUM(CASE WHEN devPresentLastScan = 0 AND devAlertDown = 1 THEN 1 ELSE 0 END), 0) AS downDevices
FROM Devices FROM Devices
""" """

View File

@@ -87,9 +87,11 @@ def insert_devices(db_path, num_entries=1):
devSyncHubNode, devSyncHubNode,
devSourcePlugin, devSourcePlugin,
devCustomProps, devCustomProps,
devFQDN devFQDN,
devParentRelType,
devReqNicsOnline
) )
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""" """
# List of device types, vendors, groups, locations # List of device types, vendors, groups, locations