mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-04-09 11:41:56 -07:00
Compare commits
66 Commits
7e573282d0
...
v25.8.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4712a2ff29 | ||
|
|
f9179a1e89 | ||
|
|
a6df204721 | ||
|
|
101189ae7c | ||
|
|
f25c012fbe | ||
|
|
868a85d84c | ||
|
|
771dd4b176 | ||
|
|
ed4d3bf17c | ||
|
|
7c728fbe36 | ||
|
|
4ff9d01ef5 | ||
|
|
1bce2e80e8 | ||
|
|
1556d74406 | ||
|
|
9b3947cc90 | ||
|
|
18b0309ac4 | ||
|
|
0afd4ae115 | ||
|
|
09e360c746 | ||
|
|
5dbe79ba2f | ||
|
|
779707761f | ||
|
|
16992bb2bd | ||
|
|
3374f83255 | ||
|
|
8f420a14cd | ||
|
|
57024c0cb1 | ||
|
|
db7fb825fe | ||
|
|
49e8c6a4f2 | ||
|
|
66bf4241b2 | ||
|
|
76a5dda553 | ||
|
|
6393aa7f2c | ||
|
|
c5f938113f | ||
|
|
dac7eaba6d | ||
|
|
35e6059068 | ||
|
|
afebc8dc39 | ||
|
|
34151a86b1 | ||
|
|
72d6934345 | ||
|
|
f5f7031030 | ||
|
|
ffccca9424 | ||
|
|
3f5ae334a2 | ||
|
|
bb45c4d345 | ||
|
|
bad3c76de9 | ||
|
|
4ee652cfda | ||
|
|
abaffa4042 | ||
|
|
ad4b5d7c64 | ||
|
|
3b38476c5a | ||
|
|
a42f6a20e4 | ||
|
|
da2afb2fb7 | ||
|
|
dda0d6a898 | ||
|
|
36068aaf77 | ||
|
|
3cb65fa4ec | ||
|
|
26cc757f75 | ||
|
|
2337f96685 | ||
|
|
82ec3b239e | ||
|
|
aa72b0216d | ||
|
|
b002bc34ac | ||
|
|
a84f0d4faf | ||
|
|
a9715cb087 | ||
|
|
827b0d15d1 | ||
|
|
4b4b2f914f | ||
|
|
bf679cdc5d | ||
|
|
4c430c6d5d | ||
|
|
905279aabe | ||
|
|
d92a5da029 | ||
|
|
a3a27fc27a | ||
|
|
0d6bc71d2b | ||
|
|
41397be1bd | ||
|
|
8fbcb07267 | ||
|
|
3c18540c8c | ||
|
|
ab9c940d01 |
@@ -13,7 +13,7 @@ ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
COPY . ${INSTALL_DIR}/
|
||||
|
||||
RUN pip install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag git+https://github.com/foreign-sub/aiofreepybox.git \
|
||||
RUN pip install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask flask-cors tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag git+https://github.com/foreign-sub/aiofreepybox.git \
|
||||
&& bash -c "find ${INSTALL_DIR} -type d -exec chmod 750 {} \;" \
|
||||
&& bash -c "find ${INSTALL_DIR} -type f -exec chmod 640 {} \;" \
|
||||
&& bash -c "find ${INSTALL_DIR} -type f \( -name '*.sh' -o -name '*.py' -o -name 'speedtest-cli' \) -exec chmod 750 {} \;"
|
||||
|
||||
@@ -43,7 +43,7 @@ RUN phpenmod -v 8.2 sqlite3
|
||||
RUN apt-get install -y python3-venv
|
||||
RUN python3 -m venv myenv
|
||||
|
||||
RUN /bin/bash -c "source myenv/bin/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag "
|
||||
RUN /bin/bash -c "source myenv/bin/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask flask-cors tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag "
|
||||
|
||||
# Create a buildtimestamp.txt to later check if a new version was released
|
||||
RUN date +%s > ${INSTALL_DIR}/front/buildtimestamp.txt
|
||||
|
||||
@@ -24,7 +24,7 @@ LOADED_PLUGINS=['ARPSCAN', 'AVAHISCAN', 'CSVBCKP','DBCLNP', 'DIGSCAN', 'INTRNT',
|
||||
|
||||
DAYS_TO_KEEP_EVENTS=90
|
||||
# Used for generating links in emails. Make sure not to add a trailing slash!
|
||||
REPORT_DASHBOARD_URL='http://127.0.0.1'
|
||||
REPORT_DASHBOARD_URL='update_REPORT_DASHBOARD_URL_setting'
|
||||
|
||||
# Make sure at least these scanners are enabled for new installs, other defaults are taken from the config.json
|
||||
INTRNT_RUN='schedule'
|
||||
|
||||
200
back/device_heuristics_rules.json
Executable file
200
back/device_heuristics_rules.json
Executable file
@@ -0,0 +1,200 @@
|
||||
[
|
||||
{
|
||||
"dev_type": "Gateway",
|
||||
"icon_html": "<i class=\"fa fa-globe\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "INTERNET", "vendor": "" }
|
||||
],
|
||||
"name_pattern": []
|
||||
},
|
||||
{
|
||||
"dev_type": "Access Point",
|
||||
"icon_html": "<i class=\"fa fa-network-wired\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "74ACB9", "vendor": "Ubiquiti" },
|
||||
{ "mac_prefix": "002468", "vendor": "Cisco" },
|
||||
{ "mac_prefix": "F4F5D8", "vendor": "TP-Link" },
|
||||
{ "mac_prefix": "F88E85", "vendor": "Netgear" }
|
||||
],
|
||||
"name_pattern": ["router", "gateway", "ap", "access point", "access-point", "switch"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Phone",
|
||||
"icon_html": "<i class=\"fa-brands fa-apple\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "001A79", "vendor": "Apple" },
|
||||
{ "mac_prefix": "B0BE83", "vendor": "Samsung" },
|
||||
{ "mac_prefix": "BC926B", "vendor": "Motorola" }
|
||||
],
|
||||
"name_pattern": ["iphone", "ipad", "pixel", "galaxy", "redmi"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Phone",
|
||||
"icon_html": "<i class=\"fa-solid fa-mobile\"></i>",
|
||||
"matching_pattern": [
|
||||
],
|
||||
"name_pattern": ["android","samsung"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Tablet",
|
||||
"icon_html": "<i class=\"fa fa-tablet\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "001B63", "vendor": "Apple" },
|
||||
{ "mac_prefix": "BC4C4C", "vendor": "Samsung" }
|
||||
],
|
||||
"name_pattern": ["tablet", "pad"]
|
||||
},
|
||||
{
|
||||
"dev_type": "IoT",
|
||||
"icon_html": "<i class=\"fa-brands fa-raspberry-pi\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "B827EB", "vendor": "Raspberry Pi" },
|
||||
{ "mac_prefix": "DCA632", "vendor": "Raspberry Pi" }
|
||||
],
|
||||
"name_pattern": ["raspberry", "pi"]
|
||||
},
|
||||
{
|
||||
"dev_type": "IoT",
|
||||
"icon_html": "<i class=\"fa-solid fa-microchip\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "840D8E", "vendor": "Espressif" },
|
||||
{ "mac_prefix": "ECFABC", "vendor": "Espressif" },
|
||||
{ "mac_prefix": "7C9EBD", "vendor": "Espressif" }
|
||||
],
|
||||
"name_pattern": ["raspberry", "pi"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Desktop",
|
||||
"icon_html": "<i class=\"fa fa-desktop\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "001422", "vendor": "Dell" },
|
||||
{ "mac_prefix": "001874", "vendor": "Lenovo" },
|
||||
{ "mac_prefix": "00E04C", "vendor": "Hewlett Packard" }
|
||||
],
|
||||
"name_pattern": ["desktop", "pc", "computer"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Laptop",
|
||||
"icon_html": "<i class=\"fa fa-laptop\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "3C0754", "vendor": "HP" },
|
||||
{ "mac_prefix": "0017A4", "vendor": "Dell" },
|
||||
{ "mac_prefix": "F4CE46", "vendor": "Lenovo" },
|
||||
{ "mac_prefix": "409F38", "vendor": "Acer" }
|
||||
],
|
||||
"name_pattern": ["macbook", "imac", "laptop", "notebook"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Server",
|
||||
"icon_html": "<i class=\"fa fa-server\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "001CBF", "vendor": "Supermicro" },
|
||||
{ "mac_prefix": "002186", "vendor": "Dell" },
|
||||
{ "mac_prefix": "D02788", "vendor": "Hewlett Packard" },
|
||||
{ "mac_prefix": "002590", "vendor": "IBM" }
|
||||
],
|
||||
"name_pattern": ["server", "nas"]
|
||||
},
|
||||
{
|
||||
"dev_type": "VM",
|
||||
"icon_html": "<i class=\"fa fa-server\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "525400", "vendor": "QEMU" },
|
||||
{ "mac_prefix": "005056", "vendor": "VMware" },
|
||||
{ "mac_prefix": "000C29", "vendor": "VMware" },
|
||||
{ "mac_prefix": "000569", "vendor": "VMware" },
|
||||
{ "mac_prefix": "00163E", "vendor": "Xen" },
|
||||
{ "mac_prefix": "080027", "vendor": "VirtualBox" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"dev_type": "TV",
|
||||
"icon_html": "<i class=\"fa fa-tv\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "0013CE", "vendor": "Samsung" },
|
||||
{ "mac_prefix": "0017C8", "vendor": "LG" },
|
||||
{ "mac_prefix": "D46E0E", "vendor": "Sony" }
|
||||
],
|
||||
"name_pattern": ["tv", "television", "smarttv"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Gaming Console",
|
||||
"icon_html": "<i class=\"fa fa-gamepad\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "001FA7", "vendor": "Sony" },
|
||||
{ "mac_prefix": "7C04D0", "vendor": "Nintendo" },
|
||||
{ "mac_prefix": "EC26CA", "vendor": "Sony" }
|
||||
],
|
||||
"name_pattern": ["playstation", "xbox"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Camera",
|
||||
"icon_html": "<i class=\"fa fa-camera\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "A45E60", "vendor": "Hikvision" },
|
||||
{ "mac_prefix": "00408C", "vendor": "Axis" },
|
||||
{ "mac_prefix": "00156D", "vendor": "Amcrest" },
|
||||
{ "mac_prefix": "AC9E17", "vendor": "Reolink" }
|
||||
],
|
||||
"name_pattern": ["camera", "cam", "webcam"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Smart Speaker",
|
||||
"icon_html": "<i class=\"fa fa-volume-up\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "44650D", "vendor": "Amazon" },
|
||||
{ "mac_prefix": "74ACB9", "vendor": "Google" }
|
||||
],
|
||||
"name_pattern": ["echo", "alexa", "dot"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Router",
|
||||
"icon_html": "<i class=\"fa fa-random\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "000C29", "vendor": "Cisco" },
|
||||
{ "mac_prefix": "00155D", "vendor": "MikroTik" }
|
||||
],
|
||||
"name_pattern": ["router", "gateway", "ap", "access point", "access-point"],
|
||||
"ip_pattern": [
|
||||
"^192\\.168\\.[0-1]\\.1$",
|
||||
"^10\\.0\\.0\\.1$"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dev_type": "Smart Light",
|
||||
"icon_html": "<i class=\"fa fa-lightbulb\"></i>",
|
||||
"matching_pattern": [],
|
||||
"name_pattern": ["hue", "lifx", "bulb"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Smart Home",
|
||||
"icon_html": "<i class=\"fa fa-house\"></i>",
|
||||
"matching_pattern": [],
|
||||
"name_pattern": ["google", "chromecast", "nest"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Smartwatch",
|
||||
"icon_html": "<i class=\"fa fa-watch\"></i>",
|
||||
"matching_pattern": [],
|
||||
"name_pattern": ["watch", "wear"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Printer",
|
||||
"icon_html": "<i class=\"fa fa-print\"></i>",
|
||||
"matching_pattern": [],
|
||||
"name_pattern": ["printer", "print"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Security Device",
|
||||
"icon_html": "<i class=\"fa fa-shield-alt\"></i>",
|
||||
"matching_pattern": [],
|
||||
"name_pattern": ["doorbell", "lock", "security"]
|
||||
},
|
||||
{
|
||||
"dev_type": "Smart Light",
|
||||
"icon_html": "<i class=\"fa-solid fa-lightbulb\"></i>",
|
||||
"matching_pattern": [
|
||||
],
|
||||
"name_pattern": ["light","bulb"]
|
||||
}
|
||||
]
|
||||
@@ -59,6 +59,9 @@ services:
|
||||
- ${DEV_LOCATION}/front/presence.php:/app/front/presence.php
|
||||
- ${DEV_LOCATION}/front/settings.php:/app/front/settings.php
|
||||
- ${DEV_LOCATION}/front/systeminfo.php:/app/front/systeminfo.php
|
||||
- ${DEV_LOCATION}/front/systeminfoNetwork.php:/app/front/systeminfoNetwork.php
|
||||
- ${DEV_LOCATION}/front/systeminfoServer.php:/app/front/systeminfoServer.php
|
||||
- ${DEV_LOCATION}/front/systeminfoStorage.php:/app/front/systeminfoStorage.php
|
||||
- ${DEV_LOCATION}/front/cloud_services.php:/app/front/cloud_services.php
|
||||
- ${DEV_LOCATION}/front/report.php:/app/front/report.php
|
||||
- ${DEV_LOCATION}/front/workflows.php:/app/front/workflows.php
|
||||
|
||||
106
docs/API.md
106
docs/API.md
@@ -221,6 +221,112 @@ Example JSON of the `table_devices.json` endpoint with two Devices (database row
|
||||
|
||||
```
|
||||
|
||||
## API Endpoint: Prometheus Exporter
|
||||
|
||||
* **Endpoint URL**: `/metrics`
|
||||
* **Host**: (where NetAlertX exporter is running)
|
||||
* **Port**: as configured in the `GRAPHQL_PORT` setting (`20212` by default)
|
||||
|
||||
---
|
||||
|
||||
### Example Output of the `/metrics` Endpoint
|
||||
|
||||
Below is a representative snippet of the metrics you may find when querying the `/metrics` endpoint for `netalertx`. It includes both aggregate counters and `device_status` labels per device.
|
||||
|
||||
```
|
||||
netalertx_connected_devices 31
|
||||
netalertx_offline_devices 54
|
||||
netalertx_down_devices 0
|
||||
netalertx_new_devices 0
|
||||
netalertx_archived_devices 31
|
||||
netalertx_favorite_devices 2
|
||||
netalertx_my_devices 54
|
||||
|
||||
netalertx_device_status{device="Net - Huawei", mac="Internet", ip="1111.111.111.111", vendor="None", first_connection="2021-01-01 00:00:00", last_connection="2025-08-04 17:57:00", dev_type="Router", device_status="Online"} 1
|
||||
netalertx_device_status{device="Net - USG", mac="74:ac:74:ac:74:ac", ip="192.168.1.1", vendor="Ubiquiti Networks Inc.", first_connection="2022-02-12 22:05:00", last_connection="2025-06-07 08:16:49", dev_type="Firewall", device_status="Archived"} 1
|
||||
netalertx_device_status{device="Raspberry Pi 4 LAN", mac="74:ac:74:ac:74:74", ip="192.168.1.9", vendor="Raspberry Pi Trading Ltd", first_connection="2022-02-12 22:05:00", last_connection="2025-08-04 17:57:00", dev_type="Singleboard Computer (SBC)", device_status="Online"} 1
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Metrics Explanation
|
||||
|
||||
#### 1. Aggregate Device Counts
|
||||
|
||||
Metric names prefixed with `netalertx_` provide aggregated counts by device status:
|
||||
|
||||
* `netalertx_connected_devices`: number of devices currently connected
|
||||
* `netalertx_offline_devices`: devices currently offline
|
||||
* `netalertx_down_devices`: down/unreachable devices
|
||||
* `netalertx_new_devices`: devices recently detected
|
||||
* `netalertx_archived_devices`: archived devices
|
||||
* `netalertx_favorite_devices`: user-marked favorite devices
|
||||
* `netalertx_my_devices`: devices associated with the current user context
|
||||
|
||||
These numeric values give a high-level overview of device distribution.
|
||||
|
||||
#### 2. Per‑Device Status with Labels
|
||||
|
||||
Each individual device is represented by a `netalertx_device_status` metric, with descriptive labels:
|
||||
|
||||
* `device`: friendly name of the device
|
||||
* `mac`: MAC address (or placeholder)
|
||||
* `ip`: last recorded IP address
|
||||
* `vendor`: manufacturer or "None" if unknown
|
||||
* `first_connection`: timestamp when the device was first observed
|
||||
* `last_connection`: most recent contact timestamp
|
||||
* `dev_type`: device category or type
|
||||
* `device_status`: current status (Online / Offline / Archived / Down / ...)
|
||||
|
||||
The metric value is always `1` (indicating presence or active state) and the combination of labels identifies the device.
|
||||
|
||||
---
|
||||
|
||||
### How to Query with `curl`
|
||||
|
||||
To fetch the metrics from the NetAlertX exporter:
|
||||
|
||||
```sh
|
||||
curl 'http://<server_ip>:<GRAPHQL_PORT>/metrics' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>' \
|
||||
-H 'Accept: text/plain'
|
||||
```
|
||||
|
||||
Replace:
|
||||
|
||||
* `<server_ip>`: IP or hostname of the NetAlertX server
|
||||
* `<GRAPHQL_PORT>`: port specified in your `GRAPHQL_PORT` setting (default: `20212`)
|
||||
* `<API_TOKEN>` your Bearer token from the `API_TOKEN` setting
|
||||
|
||||
---
|
||||
|
||||
### Summary
|
||||
|
||||
* **Endpoint**: `/metrics` provides both summary counters and per-device status entries.
|
||||
* **Aggregate metrics** help monitor overall device states.
|
||||
* **Detailed metrics** expose each device’s metadata via labels.
|
||||
* **Use case**: feed into Prometheus for scraping, monitoring, alerting, or charting dashboard views.
|
||||
|
||||
### Prometheus Scraping Configuration
|
||||
|
||||
```yaml
|
||||
scrape_configs:
|
||||
- job_name: 'netalertx'
|
||||
metrics_path: /metrics
|
||||
scheme: http
|
||||
scrape_interval: 60s
|
||||
static_configs:
|
||||
- targets: ['<server_ip>:<GRAPHQL_PORT>']
|
||||
authorization:
|
||||
type: Bearer
|
||||
credentials: <API_TOKEN>
|
||||
```
|
||||
|
||||
### Grafana template
|
||||
|
||||
Grafana template sample: [Download json](./samples/API/Grafana_Dashboard.json)
|
||||
|
||||
## API Endpoint: /log files
|
||||
|
||||
This API endpoint retrieves files from the `/app/log` folder.
|
||||
|
||||
111
docs/DEVICE_HEURISTICS.md
Executable file
111
docs/DEVICE_HEURISTICS.md
Executable file
@@ -0,0 +1,111 @@
|
||||
# Device Heuristics: Icon and Type Guessing
|
||||
|
||||
This module is responsible for inferring the most likely **device type** and **icon** based on minimal identifying data like MAC address, vendor, IP, or device name.
|
||||
|
||||
It does this using a set of heuristics defined in an external JSON rules file, which it evaluates **in priority order**.
|
||||
|
||||
>[!NOTE]
|
||||
> You can find the full source code of the heuristics module in the `device_heuristics.py` file.
|
||||
|
||||
---
|
||||
|
||||
## JSON Rule Format
|
||||
|
||||
Rules are defined in a file called `device_heuristics_rules.json` (located under `/back`), structured like:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"dev_type": "Phone",
|
||||
"icon_html": "<i class=\"fa-brands fa-apple\"></i>",
|
||||
"matching_pattern": [
|
||||
{ "mac_prefix": "001A79", "vendor": "Apple" }
|
||||
],
|
||||
"name_pattern": ["iphone", "pixel"]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
>[!NOTE]
|
||||
> Feel free to raise a PR in case you'd like to add any rules into the `device_heuristics_rules.json` file. Please place new rules into the correct position and consider the priority of already available rules.
|
||||
|
||||
### Supported fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | -------------------- | --------------------------------------------------------------- |
|
||||
| `dev_type` | `string` | Type to assign if rule matches (e.g. `"Gateway"`, `"Phone"`) |
|
||||
| `icon_html` | `string` | Icon (HTML string) to assign if rule matches. Encoded to base64 at load time. |
|
||||
| `matching_pattern` | `array` | List of `{ mac_prefix, vendor }` objects for first strict and then loose matching |
|
||||
| `name_pattern` | `array` *(optional)* | List of lowercase substrings (used with regex) |
|
||||
| `ip_pattern` | `array` *(optional)* | Regex patterns to match IPs |
|
||||
|
||||
**Order in this array defines priority** — rules are checked top-down and short-circuit on first match.
|
||||
|
||||
---
|
||||
|
||||
## Matching Flow (in Priority Order)
|
||||
|
||||
The function `guess_device_attributes(...)` runs a series of matching functions in strict order:
|
||||
|
||||
1. MAC + Vendor → `match_mac_and_vendor()`
|
||||
2. Vendor only → `match_vendor()`
|
||||
3. Name pattern → `match_name()`
|
||||
4. IP pattern → `match_ip()`
|
||||
5. Final fallback → defaults defined in the `NEWDEV_devIcon` and `NEWDEV_devType` settings.
|
||||
|
||||
### Use of default values
|
||||
|
||||
The guessing process runs for every device **as long as the current type or icon still matches the default values**. Even if earlier heuristics return a match, the system continues evaluating additional clues — like name or IP — to try and replace placeholders.
|
||||
|
||||
```python
|
||||
# Still considered a match attempt if current values are defaults
|
||||
if (not type_ or type_ == default_type) or (not icon or icon == default_icon):
|
||||
type_, icon = match_ip(ip, default_type, default_icon)
|
||||
```
|
||||
|
||||
In other words: if the type or icon is still `"unknown"` (or matches the default), the system assumes the match isn’t final — and keeps looking. It stops only when both values are non-default (defaults are defined in the `NEWDEV_devIcon` and `NEWDEV_devType` settings).
|
||||
|
||||
---
|
||||
|
||||
## Match Behavior (per function)
|
||||
|
||||
These functions are executed in the following order:
|
||||
|
||||
### `match_mac_and_vendor(mac_clean, vendor, ...)`
|
||||
|
||||
* Looks for MAC prefix **and** vendor substring match
|
||||
* Most precise
|
||||
* Stops as soon as a match is found
|
||||
|
||||
### `match_vendor(vendor, ...)`
|
||||
|
||||
* Falls back to substring match on vendor only
|
||||
* Ignores rules where `mac_prefix` is present (ensures this is really a fallback)
|
||||
|
||||
### `match_name(name, ...)`
|
||||
|
||||
* Lowercase name is compared against all `name_pattern` values using regex
|
||||
* Good for user-assigned labels (e.g. "AP Office", "iPhone")
|
||||
|
||||
### `match_ip(ip, ...)`
|
||||
|
||||
* If IP is present and matches regex patterns under any rule, it returns that type/icon
|
||||
* Usually used for gateways or local IP ranges
|
||||
|
||||
---
|
||||
|
||||
## Icons
|
||||
|
||||
* Each rule can define an `icon_html`, which is converted to a `icon_base64` on load
|
||||
* If missing, it falls back to the passed-in `default_icon` (`NEWDEV_devIcon` setting)
|
||||
* If a match is found but icon is still blank, default is used
|
||||
|
||||
**TL;DR:** Type and icon must both be matched. If only one is matched, the other falls back to the default.
|
||||
|
||||
---
|
||||
|
||||
## Priority Mechanics
|
||||
|
||||
* JSON rules are evaluated **top-to-bottom**
|
||||
* Matching is **first-hit wins** — no scoring, no weights
|
||||
* Rules that are more specific (e.g. exact MAC prefixes) should be listed earlier
|
||||
1110
docs/samples/API/Grafana_Dashboard.json
Executable file
1110
docs/samples/API/Grafana_Dashboard.json
Executable file
File diff suppressed because it is too large
Load Diff
@@ -387,6 +387,16 @@ body
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.plugin-content #tabs-location .nav-tabs-custom > .nav-tabs > li
|
||||
{
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.plugin-content .left-nav
|
||||
{
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.pa-small-box-2 .inner h3 {
|
||||
margin-left: 0em;
|
||||
margin-bottom: 1.3em;
|
||||
@@ -1411,6 +1421,7 @@ input[readonly] {
|
||||
.iconPreview svg{
|
||||
min-width: 20px;
|
||||
max-width: 20px;
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1489,7 +1500,7 @@ input[readonly] {
|
||||
}
|
||||
|
||||
#tableDevicesBox td svg, #tableDevicesBox td i{
|
||||
height: 1.5em !important;
|
||||
height: 1em !important;
|
||||
}
|
||||
|
||||
#TileCards .tile .inner
|
||||
@@ -1649,6 +1660,21 @@ input[readonly] {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.custom-badge a
|
||||
{
|
||||
color: #fff !important;
|
||||
font-size: 14px;
|
||||
}
|
||||
.custom-badge
|
||||
{
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
border-style: solid;
|
||||
padding: 0 5px;
|
||||
font-size: 14px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#deviceDetailsEdit .form-control
|
||||
{
|
||||
min-height: 42px;
|
||||
@@ -2093,10 +2119,10 @@ input[readonly] {
|
||||
#loadingSpinner {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* top: 0; */
|
||||
/* left: 0; */
|
||||
/* width: 100%; */
|
||||
/* height: 100%; */
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
pointer-events: none;
|
||||
@@ -2114,16 +2140,16 @@ input[readonly] {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.pa_semitransparent-panel {
|
||||
.nax_semitransparent-panel {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
opacity: 0.8;
|
||||
opacity: 0.5;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.pa_spinner {
|
||||
.nax_spinner {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 50%;
|
||||
@@ -2160,9 +2186,10 @@ input[readonly] {
|
||||
|
||||
}
|
||||
|
||||
.pia-top-left-logo
|
||||
.top-left-logo
|
||||
{
|
||||
height:50px;
|
||||
height:35px;
|
||||
width:35px;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
@@ -659,8 +659,14 @@ input[type="password"]::-webkit-caps-lock-indicator {
|
||||
border-color: #888888;
|
||||
}
|
||||
.table-hover tbody tr:hover td, .table-hover tbody tr:hover th {
|
||||
background-color: rgb(189,192,198);
|
||||
color: #444;
|
||||
background-color: var(--datatable-bgcolor);
|
||||
color: var(--fbc-white);
|
||||
}
|
||||
|
||||
table.dataTable tbody tr.selected, table.dataTable tbody tr .selected
|
||||
{
|
||||
background-color: var(--datatable-bgcolor);
|
||||
color: var(--fbc-white);
|
||||
}
|
||||
|
||||
.db_info_table_cell:nth-child(1) {background: #272c30}
|
||||
@@ -738,7 +744,7 @@ input[type="password"]::-webkit-caps-lock-indicator {
|
||||
top: 0.01em;
|
||||
font-size: 3.25em;
|
||||
}
|
||||
.pa_semitransparent-panel{
|
||||
.nax_semitransparent-panel{
|
||||
background-color: #000 !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
--color-yellow: #f39c12;
|
||||
--color-red: #dd4b39;
|
||||
--color-gray: #8c8c8c;
|
||||
}
|
||||
--color-white: #fff;
|
||||
}
|
||||
|
||||
:root {
|
||||
--datatable-bgcolor: rgba(64, 76, 88, 0.8);
|
||||
@@ -746,7 +747,7 @@
|
||||
top: 0.01em;
|
||||
font-size: 3.25em;
|
||||
}
|
||||
.pa_semitransparent-panel{
|
||||
.nax_semitransparent-panel{
|
||||
background-color: #000 !important;
|
||||
}
|
||||
|
||||
@@ -793,5 +794,5 @@
|
||||
|
||||
.btn:hover
|
||||
{
|
||||
color: var(--color-gray);
|
||||
color: var(--color-white);
|
||||
}
|
||||
@@ -123,7 +123,7 @@
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content" style="min-height: 430px;">
|
||||
<div class="tab-content spinnerTarget" style="min-height: 430px;">
|
||||
|
||||
<!-- tab page 1 ------------------------------------------------------------ -->
|
||||
|
||||
@@ -225,13 +225,6 @@ switch ($UI_THEME) {
|
||||
var selectedTab = 'tabDetails';
|
||||
var emptyArr = ['undefined', "", undefined, null];
|
||||
|
||||
|
||||
// Call renderSmallBoxes, then main
|
||||
(async () => {
|
||||
await renderSmallBoxes();
|
||||
main();
|
||||
})();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function main () {
|
||||
|
||||
@@ -299,17 +292,32 @@ function recordSwitch(direction) {
|
||||
function updateChevrons(currentMac) {
|
||||
const devicesList = getDevicesList();
|
||||
|
||||
// Find the index of the device by MAC
|
||||
pos = devicesList.findIndex(item => item.devMac == currentMac);
|
||||
pos = devicesList.findIndex(item => item.devMac === currentMac);
|
||||
|
||||
// If device not found, optionally add it or handle error
|
||||
if (pos === -1) {
|
||||
// If you want to add a placeholder or handle missing device:
|
||||
// devicesList.push({ mac: currentMac, name: 'Unknown', type: 'Unknown' });
|
||||
// pos = devicesList.length - 1;
|
||||
console.warn('Device not found in cache. Re-caching devices...', currentMac);
|
||||
|
||||
showSpinner();
|
||||
|
||||
cacheDevices().then(() => {
|
||||
hideSpinner();
|
||||
|
||||
// Retry after re-caching
|
||||
const refreshedList = getDevicesList();
|
||||
pos = refreshedList.findIndex(item => item.devMac === currentMac);
|
||||
|
||||
if (pos === -1) {
|
||||
console.error('Still not found after re-cache:', currentMac);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Device found after re-cache:', refreshedList[pos]);
|
||||
// Proceed with using `refreshedList[pos]`
|
||||
}).catch((err) => {
|
||||
hideSpinner();
|
||||
console.error('Failed to cache devices:', err);
|
||||
});
|
||||
|
||||
// Or just return early if device not found
|
||||
console.warn('Device with MAC not found:', currentMac);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -345,7 +353,7 @@ function performSwitch(direction)
|
||||
|
||||
// Update the global position in the devices list variable 'pos'
|
||||
if (direction === "next") {
|
||||
console.log("direction" + direction);
|
||||
console.log("direction:" + direction);
|
||||
|
||||
if (pos < devicesList.length) {
|
||||
pos++;
|
||||
@@ -485,34 +493,58 @@ async function renderSmallBoxes() {
|
||||
}
|
||||
|
||||
function updateDevicePageName(mac) {
|
||||
let name = getDevDataByMac(mac, "devName");
|
||||
let owner = getDevDataByMac(mac, "devOwner");
|
||||
|
||||
name = getDevDataByMac(mac, "devName")
|
||||
owner = getDevDataByMac(mac, "devOwner")
|
||||
// If data is missing, re-cache and retry once
|
||||
if (mac != 'new' && (name === "Unknown" || owner === "Unknown")) {
|
||||
console.warn("Device not found in cache, retrying after re-cache:", mac);
|
||||
showSpinner();
|
||||
cacheDevices().then(() => {
|
||||
hideSpinner();
|
||||
// Retry after successful cache
|
||||
updateDevicePageName(mac);
|
||||
}).catch((err) => {
|
||||
hideSpinner();
|
||||
console.error("Failed to refresh devices:", err);
|
||||
});
|
||||
return; // Exit early to avoid showing bad data
|
||||
}
|
||||
|
||||
// Page title - Name
|
||||
if (mac == "new") {
|
||||
$('#pageTitle').html(`<i title="${getString("Gen_create_new_device")}" class="fa fa-square-plus"></i> ` + getString("Gen_create_new_device"));
|
||||
$('#devicePageInfoPlc .inner').html(`<i class="fa fa-circle-info"></i> ` + getString("Gen_create_new_device_info"));
|
||||
$('#devicePageInfoPlc').show();
|
||||
} else if (owner == null || owner == '' ||
|
||||
(name.toString()).indexOf(owner) != -1) {
|
||||
$('#pageTitle').html(name);
|
||||
$('#devicePageInfoPlc').hide();
|
||||
$('#pageTitle').html(
|
||||
`<i title="${getString("Gen_create_new_device")}" class="fa fa-square-plus"></i> ` + getString("Gen_create_new_device")
|
||||
);
|
||||
$('#devicePageInfoPlc .inner').html(
|
||||
`<i class="fa fa-circle-info"></i> ` + getString("Gen_create_new_device_info")
|
||||
);
|
||||
$('#devicePageInfoPlc').show();
|
||||
} else if (!owner || (name.toString()).indexOf(owner) !== -1) {
|
||||
$('#pageTitle').html(name);
|
||||
$('#devicePageInfoPlc').hide();
|
||||
} else {
|
||||
$('#pageTitle').html(name + ' (' + owner + ')');
|
||||
$('#devicePageInfoPlc').hide();
|
||||
$('#pageTitle').html(name + ' (' + owner + ')');
|
||||
$('#devicePageInfoPlc').hide();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
// Call renderSmallBoxes, then main
|
||||
(async () => {
|
||||
await renderSmallBoxes();
|
||||
main();
|
||||
})();
|
||||
|
||||
|
||||
window.onload = function async()
|
||||
{
|
||||
initializeTabs();
|
||||
// initializeTabs();
|
||||
updateChevrons(mac);
|
||||
updateDevicePageName(mac);
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -443,6 +443,37 @@
|
||||
}
|
||||
|
||||
// init first time
|
||||
initNmapButtons();
|
||||
initCopyFromDevice();
|
||||
// -----------------------------------------------------------
|
||||
var toolsPageInitialized = false;
|
||||
|
||||
function initDeviceToolsPage()
|
||||
{
|
||||
// Only proceed if .panTools is visible
|
||||
if (!$('#panTools:visible').length) {
|
||||
return; // exit early if nothing is visible
|
||||
}
|
||||
|
||||
// init page once
|
||||
if (toolsPageInitialized) return;
|
||||
toolsPageInitialized = true;
|
||||
|
||||
initNmapButtons();
|
||||
initCopyFromDevice();
|
||||
|
||||
hideSpinner();
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Recurring function to monitor the URL and reinitialize if needed
|
||||
function deviceToolsPageUpdater() {
|
||||
initDeviceToolsPage();
|
||||
|
||||
// Run updater again after delay
|
||||
setTimeout(deviceToolsPageUpdater, 200);
|
||||
}
|
||||
|
||||
// start updater
|
||||
deviceToolsPageUpdater();
|
||||
|
||||
</script>
|
||||
|
||||
@@ -148,10 +148,7 @@ function main () {
|
||||
|
||||
//initialize the table headers in the correct order
|
||||
var availableColumns = getSettingOptions("UI_device_columns").split(",");
|
||||
headersDefaultOrder = availableColumns.map(val => getString(val));
|
||||
|
||||
console.log(headersDefaultOrder);
|
||||
|
||||
headersDefaultOrder = availableColumns.map(val => getString(val));
|
||||
|
||||
var selectedColumns = JSON.parse(getSetting("UI_device_columns").replace(/'/g, '"'));
|
||||
|
||||
@@ -353,8 +350,6 @@ function initFilters() {
|
||||
// Clear any existing filters in the DOM
|
||||
$('#columnFilters').empty();
|
||||
|
||||
console.log(displayedFilters);
|
||||
|
||||
// Ensure displayedFilters is an array and not empty
|
||||
if (Array.isArray(displayedFilters) && displayedFilters.length > 0) {
|
||||
$('#columnFiltersWrap').removeClass("hidden");
|
||||
@@ -508,36 +503,36 @@ function collectFilters() {
|
||||
function mapColumnIndexToFieldName(index, tableColumnVisible) {
|
||||
// the order is important, don't change it!
|
||||
const columnNames = [
|
||||
"devName",
|
||||
"devOwner",
|
||||
"devType",
|
||||
"devIcon",
|
||||
"devFavorite",
|
||||
"devGroup",
|
||||
"devFirstConnection",
|
||||
"devLastConnection",
|
||||
"devLastIP",
|
||||
"devIsRandomMac", // resolved on the fly
|
||||
"devStatus", // resolved on the fly
|
||||
"devMac",
|
||||
"devIpLong", //formatIPlong(device.devLastIP) || "", // IP orderable
|
||||
"rowid",
|
||||
"devParentMAC",
|
||||
"devParentChildrenCount", // resolved on the fly
|
||||
"devLocation",
|
||||
"devVendor",
|
||||
"devParentPort",
|
||||
"devGUID",
|
||||
"devSyncHubNode",
|
||||
"devSite",
|
||||
"devSSID",
|
||||
"devSourcePlugin",
|
||||
"devPresentLastScan",
|
||||
"devAlertDown",
|
||||
"devCustomProps",
|
||||
"devFQDN",
|
||||
"devParentRelType",
|
||||
"devReqNicsOnline"
|
||||
"devName", // 0
|
||||
"devOwner", // 1
|
||||
"devType", // 2
|
||||
"devIcon", // 3
|
||||
"devFavorite", // 4
|
||||
"devGroup", // 5
|
||||
"devFirstConnection", // 6
|
||||
"devLastConnection", // 7
|
||||
"devLastIP", // 8
|
||||
"devIsRandomMac", // 9 resolved on the fly
|
||||
"devStatus", // 10 resolved on the fly
|
||||
"devMac", // 11
|
||||
"devIpLong", // 12 formatIPlong(device.devLastIP) || "", // IP orderable
|
||||
"rowid", // 13
|
||||
"devParentMAC", // 14
|
||||
"devParentChildrenCount", // 15 resolved on the fly
|
||||
"devLocation", // 16
|
||||
"devVendor", // 17
|
||||
"devParentPort", // 18
|
||||
"devGUID", // 19
|
||||
"devSyncHubNode", // 20
|
||||
"devSite", // 21
|
||||
"devSSID", // 22
|
||||
"devSourcePlugin", // 23
|
||||
"devPresentLastScan", // 24
|
||||
"devAlertDown", // 25
|
||||
"devCustomProps", // 26
|
||||
"devFQDN", // 27
|
||||
"devParentRelType", // 28
|
||||
"devReqNicsOnline" // 29
|
||||
];
|
||||
|
||||
// console.log("OrderBy: " + columnNames[tableColumnOrder[index]]);
|
||||
@@ -599,7 +594,6 @@ function initializeDatatable (status) {
|
||||
}
|
||||
}
|
||||
|
||||
// todo: dynamically filter based on status
|
||||
var table = $('#tableDevices').DataTable({
|
||||
"serverSide": true,
|
||||
"processing": true,
|
||||
@@ -690,8 +684,6 @@ function initializeDatatable (status) {
|
||||
return JSON.stringify(query); // Send the JSON request
|
||||
},
|
||||
"dataSrc": function (json) {
|
||||
console.log(json);
|
||||
|
||||
// Set the total number of records for pagination
|
||||
json.recordsTotal = json.devices.count || 0;
|
||||
json.recordsFiltered = json.devices.count || 0;
|
||||
@@ -907,6 +899,28 @@ function initializeDatatable (status) {
|
||||
}
|
||||
} },
|
||||
|
||||
// Parent Mac
|
||||
{targets: [mapIndx(14)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
if (!isValidMac(cellData)) {
|
||||
$(td).html('');
|
||||
return;
|
||||
}
|
||||
|
||||
const data = {
|
||||
id: cellData, // MAC address
|
||||
text: cellData // Optional display text (you could use a name or something else)
|
||||
};
|
||||
|
||||
spanWrap = $(`<span class="custom-badge text-white"></span>`)
|
||||
|
||||
$(td).html(spanWrap);
|
||||
|
||||
const chipHtml = renderDeviceLink(data, spanWrap, true); // pass the td as container
|
||||
|
||||
$(spanWrap).append(chipHtml);
|
||||
}
|
||||
},
|
||||
// Status color
|
||||
{targets: [mapIndx(10)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
|
||||
@@ -1039,11 +1039,8 @@ function getDevDataByMac(macAddress, dbColumn) {
|
||||
// Cache the devices as one JSON
|
||||
function cacheDevices()
|
||||
{
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
// if(!getCache('completedCalls').includes('cacheDevices'))
|
||||
// {
|
||||
$.get('php/server/query_json.php', { file: 'table_devices.json', nocache: Date.now() }, function(data) {
|
||||
|
||||
// console.log(data)
|
||||
@@ -1067,8 +1064,7 @@ function cacheDevices()
|
||||
// console.log(getCache('devicesListAll_JSON'))
|
||||
}).then(() => handleSuccess('cacheDevices', resolve())).catch(() => handleFailure('cacheDevices', reject("cacheDevices already completed"))); // handle AJAX synchronization
|
||||
}
|
||||
// }
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
var devicesListAll_JSON = []; // this will contain a list off all devices
|
||||
@@ -1116,38 +1112,92 @@ let animationTime = 300
|
||||
function showSpinner(stringKey = 'Loading') {
|
||||
const text = isEmpty(stringKey) ? "Loading" : getString(stringKey || "Loading");
|
||||
const spinner = $("#loadingSpinner");
|
||||
|
||||
if (spinner.length && spinner.is(':visible')) {
|
||||
clearTimeout(spinnerTimeout);
|
||||
|
||||
$("#loadingSpinnerText").text(text);
|
||||
spinner.addClass("visible");
|
||||
const target = $(".spinnerTarget").first(); // Only use the first one if multiple exist
|
||||
|
||||
spinner.fadeIn(animationTime);
|
||||
$("#loadingSpinnerText").text(text);
|
||||
|
||||
if (target.length) {
|
||||
// Position relative to target
|
||||
const offset = target.offset();
|
||||
const width = target.outerWidth();
|
||||
const height = target.outerHeight();
|
||||
|
||||
spinner.css({
|
||||
position: "absolute",
|
||||
top: offset.top,
|
||||
left: offset.left,
|
||||
width: width,
|
||||
height: height,
|
||||
zIndex: 800
|
||||
});
|
||||
} else {
|
||||
$("#loadingSpinnerText").text(text);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
spinner.addClass("visible");
|
||||
spinner.fadeIn(animationTime);
|
||||
// Fullscreen fallback
|
||||
spinner.css({
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
zIndex: 800
|
||||
});
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
spinner.addClass("visible");
|
||||
spinner.fadeIn(animationTime);
|
||||
});
|
||||
}
|
||||
|
||||
function hideSpinner() {
|
||||
clearTimeout(spinnerTimeout);
|
||||
|
||||
const spinner = $("#loadingSpinner");
|
||||
|
||||
if (spinner.length) {
|
||||
spinner.removeClass("visible");
|
||||
spinner.fadeOut(animationTime);
|
||||
if (!spinner.length) return;
|
||||
|
||||
spinnerTimeout = setTimeout(() => {
|
||||
spinner.removeClass("visible");
|
||||
spinner.fadeOut(animationTime); // optional remove or hide again
|
||||
}, 300);
|
||||
const target = $(".spinnerTarget").first();
|
||||
|
||||
if (target.length) {
|
||||
// Lock position to target
|
||||
const offset = target.offset();
|
||||
const width = target.outerWidth();
|
||||
const height = target.outerHeight();
|
||||
|
||||
spinner.css({
|
||||
position: "absolute",
|
||||
top: offset.top,
|
||||
left: offset.left,
|
||||
width: width,
|
||||
height: height,
|
||||
zIndex: 800
|
||||
});
|
||||
} else {
|
||||
// Fullscreen fallback
|
||||
spinner.css({
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
zIndex: 800
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger fade-out and only remove styles AFTER fade completes AND display is none
|
||||
spinner.removeClass("visible").fadeOut(animationTime, () => {
|
||||
// Ensure it's really hidden before resetting styles
|
||||
spinner.css({
|
||||
display: "none"
|
||||
});
|
||||
|
||||
spinner.css({
|
||||
position: "",
|
||||
top: "",
|
||||
left: "",
|
||||
width: "",
|
||||
height: "",
|
||||
zIndex: ""
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ function modalWarningOK() {
|
||||
} else if (typeof modalCallbackFunction === "string" && typeof window[modalCallbackFunction] === "function") {
|
||||
window[modalCallbackFunction](); // Call via window
|
||||
} else {
|
||||
console.error("Invalid callback function");
|
||||
console.error("Invalid callback function: " + modalCallbackFunction);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
@@ -336,7 +336,8 @@ function execute_settingEvent(element) {
|
||||
getString('DevDetail_button_OverwriteIcons_Warning'),
|
||||
getString('Gen_Cancel'),
|
||||
getString('Gen_Okay'),
|
||||
'overwriteIconType'
|
||||
'overwriteIconType',
|
||||
feSourceId // triggered by id
|
||||
);
|
||||
} else if (["go_to_device"].includes(feEvent)) {
|
||||
|
||||
@@ -347,9 +348,43 @@ function execute_settingEvent(element) {
|
||||
|
||||
} else {
|
||||
console.warn(`🔺Not implemented: ${feEvent}`)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Go to the correct network node in the Network section
|
||||
function overwriteIconType()
|
||||
{
|
||||
const mac = getMac();
|
||||
|
||||
if (!isValidMac(mac)) {
|
||||
showModalOK("Error", getString("Gen_InvalidMac"))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Construct SQL query
|
||||
const rawSql = `
|
||||
UPDATE Devices
|
||||
SET devIcon = (
|
||||
SELECT devIcon FROM Devices WHERE devMac = "${mac}"
|
||||
)
|
||||
WHERE devType IN (
|
||||
SELECT devType FROM Devices WHERE devMac = "${mac}"
|
||||
)
|
||||
`;
|
||||
|
||||
const apiUrl = `php/server/dbHelper.php?action=write&rawSql=${btoa(encodeURIComponent(rawSql))}`;
|
||||
|
||||
$.get(apiUrl, function(response) {
|
||||
if (response === 'OK') {
|
||||
showMessage (response);
|
||||
updateApi("devices")
|
||||
} else {
|
||||
showMessage (response, 3000, "modal_red");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -680,45 +715,7 @@ function initSelect2() {
|
||||
{
|
||||
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-type="${device.devType}"
|
||||
data-lastseen="${device.devLastConnection}"
|
||||
data-firstseen="${device.devFirstConnection}"
|
||||
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;
|
||||
return $(renderDeviceLink(data, container));
|
||||
},
|
||||
escapeMarkup: function (m) {
|
||||
return m; // Allow HTML
|
||||
@@ -782,6 +779,50 @@ function initSelect2() {
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
// Render a device link with hover-over functionality
|
||||
function renderDeviceLink(data, container, useName = false) {
|
||||
if (!data.id) return data.text; // default placeholder etc.
|
||||
|
||||
const device = getDevDataByMac(data.id);
|
||||
|
||||
const badge = getStatusBadgeParts(
|
||||
device.devPresentLastScan,
|
||||
device.devAlertDown,
|
||||
device.devMac
|
||||
);
|
||||
|
||||
// Add badge class and hover-info class to container
|
||||
$(container)
|
||||
.addClass(`${badge.cssClass} hover-node-info`)
|
||||
.attr({
|
||||
'data-name': device.devName,
|
||||
'data-ip': device.devLastIP,
|
||||
'data-mac': device.devMac,
|
||||
'data-vendor': device.devVendor,
|
||||
'data-type': device.devType,
|
||||
'data-lastseen': device.devLastConnection,
|
||||
'data-firstseen': device.devFirstConnection,
|
||||
'data-relationship': device.devParentRelType,
|
||||
'data-status': device.devStatus,
|
||||
'data-present': device.devPresentLastScan,
|
||||
'data-alert': device.devAlertDown,
|
||||
'data-icon': device.devIcon
|
||||
});
|
||||
|
||||
return `
|
||||
<a href="${badge.url}" target="_blank">
|
||||
<span class="custom-chip">
|
||||
<span class="iconPreview">${atob(device.devIcon)}</span>
|
||||
${useName ? device.devName : data.text}
|
||||
<span>
|
||||
(${badge.iconHtml})
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
// Display device info on hover (attach only once)
|
||||
function initHoverNodeInfo() {
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
|
||||
<!-- Main content ---------------------------------------------------------- -->
|
||||
<section class="content">
|
||||
|
||||
|
||||
<script>
|
||||
showSpinner();
|
||||
</script>
|
||||
|
||||
<?php
|
||||
|
||||
@@ -143,7 +146,7 @@ $db->close();
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-content spinnerTarget">
|
||||
<div class="tab-pane active" id="tab_DBTools">
|
||||
<div class="db_info_table">
|
||||
<div class="db_info_table_row">
|
||||
@@ -182,6 +185,12 @@ $db->close();
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_del_ActHistory_text');?></div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" >
|
||||
<button type="button" class="btn btn-default pa-btn pa-btn-delete bg-red dbtools-button" id="btnRestartServer" onclick="askRestartBackend()"><?= lang('Maint_RestartServer');?></button>
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maint_Restart_Server_noti_text');?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -709,6 +718,8 @@ window.onload = function asyncFooter() {
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
hideSpinner();
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@@ -437,7 +437,7 @@
|
||||
|
||||
if(archivedCount > 0)
|
||||
{
|
||||
$('#showArchivedNumber').text(`(${archivedCount})`);
|
||||
$('#showArchivedNumber').text(`(${archivedCount})`);
|
||||
}
|
||||
|
||||
if(offlineCount > 0)
|
||||
@@ -968,7 +968,6 @@ $(window).on('resize', function () {
|
||||
// init pop up hover boxes for device details
|
||||
initHoverNodeInfo();
|
||||
|
||||
// display toggles
|
||||
$(document).ready(function () {
|
||||
// Restore cached values on load
|
||||
const cachedOffline = getCache('showOffline');
|
||||
@@ -981,12 +980,34 @@ $(document).ready(function () {
|
||||
$('input[name="showArchived"]').prop('checked', cachedArchived === 'true');
|
||||
}
|
||||
|
||||
// Function to enable/disable showArchived based on showOffline
|
||||
function updateArchivedToggle() {
|
||||
const isOfflineChecked = $('input[name="showOffline"]').is(':checked');
|
||||
const archivedToggle = $('input[name="showArchived"]');
|
||||
|
||||
if (!isOfflineChecked) {
|
||||
archivedToggle.prop('checked', false);
|
||||
archivedToggle.prop('disabled', true);
|
||||
setCache('showArchived', false);
|
||||
} else {
|
||||
archivedToggle.prop('disabled', false);
|
||||
}
|
||||
}
|
||||
|
||||
// Initial state on load
|
||||
updateArchivedToggle();
|
||||
|
||||
// Bind change event for both toggles
|
||||
$('input[name="showOffline"], input[name="showArchived"]').on('change', function () {
|
||||
const name = $(this).attr('name');
|
||||
const value = $(this).is(':checked');
|
||||
setCache(name, value);
|
||||
|
||||
// Update state of showArchived if showOffline changed
|
||||
if (name === 'showOffline') {
|
||||
updateArchivedToggle();
|
||||
}
|
||||
|
||||
// Refresh page after a brief delay to ensure cache is written
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
@@ -994,6 +1015,7 @@ $(document).ready(function () {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
|
||||
switch ($action) {
|
||||
case 'create': create($defaultValue, $expireMinutes, $dbtable, $columns, $values ); break;
|
||||
case 'read' : read($rawSql); break;
|
||||
case 'write' : write($rawSql); break;
|
||||
case 'update': update($columnName, $id, $defaultValue, $expireMinutes, $dbtable, $columns, $values); break;
|
||||
case 'delete': delete($columnName, $id, $dbtable); break;
|
||||
case 'lockDatabase': lockDatabase($delay); break;
|
||||
@@ -120,6 +121,31 @@ function read($rawSql) {
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// write
|
||||
//------------------------------------------------------------------------------
|
||||
function write($rawSql) {
|
||||
global $db;
|
||||
|
||||
// Construct the SQL query to select values
|
||||
$sql = $rawSql;
|
||||
|
||||
// Execute the SQL query
|
||||
$result = $db->query($sql);
|
||||
|
||||
// Check if the query executed successfully
|
||||
if (! $result == TRUE) {
|
||||
// Output an error message if the query failed
|
||||
echo "Error writing data\n\n " .$sql." \n\n". $db->lastErrorMsg();
|
||||
return;
|
||||
} else
|
||||
{
|
||||
// Output
|
||||
echo "OK";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// update
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
case 'getDevicesListCalendar': getDevicesListCalendar(); break; //todo: slowly deprecate this
|
||||
|
||||
case 'updateNetworkLeaf': updateNetworkLeaf(); break;
|
||||
case 'overwriteIconType': overwriteIconType(); break;
|
||||
case 'getIcons': getIcons(); break;
|
||||
case 'getActions': getActions(); break;
|
||||
case 'getDevices': getDevices(); break;
|
||||
@@ -924,33 +923,6 @@ function updateNetworkLeaf()
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
function overwriteIconType()
|
||||
{
|
||||
$mac = $_REQUEST['mac'];
|
||||
$icon = $_REQUEST['icon'];
|
||||
|
||||
if ((false === filter_var($mac , FILTER_VALIDATE_MAC) && $mac != "Internet" && $mac != "") ) {
|
||||
throw new Exception('Invalid mac address');
|
||||
}
|
||||
else
|
||||
{
|
||||
global $db;
|
||||
// sql
|
||||
$sql = 'UPDATE Devices SET "devIcon" = "'. $icon .'" where devType in (select devType from Devices where devMac = "' . $mac.'")' ;
|
||||
// update Data
|
||||
$result = $db->query($sql);
|
||||
|
||||
// check result
|
||||
if ($result == TRUE) {
|
||||
echo 'OK';
|
||||
} else {
|
||||
echo lang('BackDevices_Device_UpdDevError');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Wake-on-LAN
|
||||
// Inspired by @leiweibau: https://github.com/leiweibau/Pi.Alert/commit/30427c7fea180670c71a2b790699e5d9e9e88ffd
|
||||
|
||||
@@ -139,8 +139,8 @@
|
||||
<body class="hold-transition fixed <?php echo $pia_skin_selected;?> theme-<?php echo $UI_THEME;?> sidebar-mini" onLoad="update_servertime();" >
|
||||
|
||||
<div id="loadingSpinner">
|
||||
<div class="pa_semitransparent-panel"></div>
|
||||
<div class="panel panel-default pa_spinner">
|
||||
<div class="nax_semitransparent-panel"></div>
|
||||
<div class="panel panel-default nax_spinner">
|
||||
<table>
|
||||
<td id="loadingSpinnerText" width="130px" ></td>
|
||||
<td><i class="fa-solid fa-spinner fa-spin-pulse"></i></td>
|
||||
@@ -160,7 +160,7 @@
|
||||
<a href="devices.php" class="logo">
|
||||
<!-- mini logo for sidebar mini 50x50 pixels -->
|
||||
<span class="logo-mini">
|
||||
<img src="img/NetAlertX_logo.png" class="pia-top-left-logo" alt="NetAlertX Logo"/>
|
||||
<img src="img/NetAlertX_logo.png" class="top-left-logo" alt="NetAlertX Logo"/>
|
||||
</span>
|
||||
<!-- logo for regular state and mobile devices -->
|
||||
<span class="logo-lg">Net<b>Alert</b><sup>x</sup>
|
||||
@@ -436,8 +436,24 @@
|
||||
</li>
|
||||
|
||||
<!-- system info menu item -->
|
||||
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('systeminfo.php') ) ){ echo 'active'; } ?>">
|
||||
<a href="systeminfo.php"><i class="fa fa-fw fa-info-circle"></i> <span><?= lang('Navigation_SystemInfo');?></span></a>
|
||||
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('systeminfo.php') ) ){ echo 'active menu-open'; } ?>">
|
||||
<a href="#">
|
||||
<i class="fa fa-fw fa-info-circle"></i> <span><?= lang('Navigation_SystemInfo');?></span>
|
||||
<span class="pull-right-container">
|
||||
<i class="fa fa-angle-left pull-right"></i>
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu " style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('systeminfo.php') ) ){ echo 'block'; } else {echo 'none';} ?>;">
|
||||
<li>
|
||||
<a href="systeminfo.php#panServer" onclick="setCache('activeSysinfoTab','tabServer');initializeTabs()"><?= lang('Systeminfo_System');?></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="systeminfo.php#panNetwork" onclick="setCache('activeSysinfoTab','tabNetwork');initializeTabs()"><?= lang('Systeminfo_Network');?></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="systeminfo.php#panStorage" onclick="setCache('activeSysinfoTab','tabStorage');initializeTabs()"><?= lang('Systeminfo_Storage');?></a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
@@ -450,24 +466,6 @@
|
||||
|
||||
<script defer>
|
||||
|
||||
// Generate work-in-progress icons
|
||||
function workInProgress() {
|
||||
|
||||
if($(".work-in-progress").length > 0 && $(".work-in-progress").html().trim() == "")
|
||||
{
|
||||
$(".work-in-progress").append(`
|
||||
<a href="https://github.com/jokob-sk/NetAlertX/issues" target="_blank">
|
||||
<b class="pointer" title="${getString("Gen_Work_In_Progress")}">🦺</b>
|
||||
</a>
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
||||
function toggleFullscreen() {
|
||||
|
||||
if (document.fullscreenElement) {
|
||||
@@ -485,6 +483,5 @@ function workInProgress() {
|
||||
|
||||
// Update server state in the header
|
||||
updateState()
|
||||
workInProgress()
|
||||
|
||||
</script>
|
||||
|
||||
7
front/php/templates/language/ar_ar.json
Normal file → Executable file
7
front/php/templates/language/ar_ar.json
Normal file → Executable file
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "إلغاء",
|
||||
"Gen_Change": "تغيير",
|
||||
"Gen_Copy": "نسخ",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "تم تحديث البيانات. قد يستغرق تحديث واجهة المستخدم بعض الوقت",
|
||||
"Gen_Delete": "حذف",
|
||||
"Gen_DeleteAll": "حذف الكل",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "خطأ",
|
||||
"Gen_Filter": "تصفية",
|
||||
"Gen_Generate": "إنشاء",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "قاعدة البيانات مقفلة",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "غير متصل",
|
||||
"Gen_Okay": "موافق",
|
||||
"Gen_Online": "متصل",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "اختيار أيقونة",
|
||||
"Gen_SelectToPreview": "اختر للمعاينة",
|
||||
"Gen_Selected_Devices": "الأجهزة المحددة",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "تبديل",
|
||||
"Gen_Upd": "تحديث",
|
||||
"Gen_Upd_Fail": "فشل التحديث",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "عدم تزامن ماسحات الأجهزة",
|
||||
"Settings_device_Scanners_desync_popup": "نافذة عدم تزامن ماسحات الأجهزة",
|
||||
"Speedtest_Results": "نتائج اختبار السرعة",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "المعالج",
|
||||
"Systeminfo_CPU_Cores": "أنوية المعالج",
|
||||
"Systeminfo_CPU_Name": "اسم المعالج",
|
||||
@@ -755,4 +760,4 @@
|
||||
"settings_system_label": "تسمية النظام",
|
||||
"settings_update_item_warning": "تحذير تحديث العنصر",
|
||||
"test_event_tooltip": "تلميح اختبار الحدث"
|
||||
}
|
||||
}
|
||||
7
front/php/templates/language/ca_ca.json
Normal file → Executable file
7
front/php/templates/language/ca_ca.json
Normal file → Executable file
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Cancel·lar",
|
||||
"Gen_Change": "Canviar",
|
||||
"Gen_Copy": "Executar",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "D'acord - Pot passar una estona perquè la interfície d'usuari s'actualitzi si s'està executant una exploració.",
|
||||
"Gen_Delete": "Esborrar",
|
||||
"Gen_DeleteAll": "Esborrar tot",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Error",
|
||||
"Gen_Filter": "Filtrar",
|
||||
"Gen_Generate": "Generar",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "ERROR - DB podria estar bloquejada - Fes servir F12 Eines desenvolupament -> Consola o provar-ho més tard.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "Fora de línia",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "En línia",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Seleccioneu la vista prèvia",
|
||||
"Gen_Selected_Devices": "Dispositius seleccionats:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "Switch",
|
||||
"Gen_Upd": "Actualitzat correctament",
|
||||
"Gen_Upd_Fail": "Actualització fallida",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ Els horaris d'escàner de dispositius no estan en sincronia.",
|
||||
"Settings_device_Scanners_desync_popup": "Els horaris dels escàners de dispositius (<code>*_RUN_SCHD</code>) no són iguals. Això donarà lloc a notificacions inconsistents del dispositiu en línia / fora de línia. Si no és intencionat, utilitzeu el mateix horari per a tots els <b>🔍 escàners de dispositius</b>.",
|
||||
"Speedtest_Results": "Speedtest Resultats",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "CPU",
|
||||
"Systeminfo_CPU_Cores": "Nuclis de CPU:",
|
||||
"Systeminfo_CPU_Name": "Nom de CPU:",
|
||||
@@ -755,4 +760,4 @@
|
||||
"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>",
|
||||
"test_event_tooltip": "Deseu els canvis primer abans de comprovar la configuració."
|
||||
}
|
||||
}
|
||||
7
front/php/templates/language/cs_cz.json
Normal file → Executable file
7
front/php/templates/language/cs_cz.json
Normal file → Executable file
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Zrušit",
|
||||
"Gen_Change": "Změnit",
|
||||
"Gen_Copy": "Spustit",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - může zabrat chvíli aktualizovat rozhraní, pokud běží scan.",
|
||||
"Gen_Delete": "Smazat",
|
||||
"Gen_DeleteAll": "Smazat vše",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Chyba",
|
||||
"Gen_Filter": "Filtr",
|
||||
"Gen_Generate": "Vygenerovat",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "CHYBA - Databáze je možná zamčená - Zkontrolujte F12 -> Nástroje pro vývojáře -> Konzole. nebo to zkuste později.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Vybrat na náhled",
|
||||
"Gen_Selected_Devices": "Vybraná zařízení:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "Přepnout",
|
||||
"Gen_Upd": "Úspěšně aktualizováno",
|
||||
"Gen_Upd_Fail": "Aktualizace se nezdařila",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "",
|
||||
"Settings_device_Scanners_desync_popup": "",
|
||||
"Speedtest_Results": "",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "",
|
||||
"Systeminfo_CPU_Cores": "",
|
||||
"Systeminfo_CPU_Name": "",
|
||||
@@ -755,4 +760,4 @@
|
||||
"settings_system_label": "",
|
||||
"settings_update_item_warning": "",
|
||||
"test_event_tooltip": ""
|
||||
}
|
||||
}
|
||||
13
front/php/templates/language/de_de.json
Normal file → Executable file
13
front/php/templates/language/de_de.json
Normal file → Executable file
@@ -5,14 +5,6 @@
|
||||
"API_TOKEN_name": "API-Schlüssel",
|
||||
"API_display_name": "API",
|
||||
"API_icon": "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
|
||||
"APPRISE_HOST_description": "Apprise host URL starting with <code>http://</code> or <code>https://</code>. (do not forget to include <code>/notify</code> at the end)",
|
||||
"APPRISE_HOST_name": "Apprise host URL",
|
||||
"APPRISE_PAYLOAD_description": "Select the payload type sent to Apprise. For example <code>html</code> works well with emails, <code>text</code> with chat apps, such as Telegram.",
|
||||
"APPRISE_PAYLOAD_name": "Payload type",
|
||||
"APPRISE_SIZE_description": "The maximum size of the apprise payload as number of characters in the passed string. If above limit, it will be truncated and a <code>(text was truncated)</code> message is appended.",
|
||||
"APPRISE_SIZE_name": "Max payload size",
|
||||
"APPRISE_URL_description": "Apprise notification target URL. For example for Telegram it would be <code>tgram://{bot_token}/{chat_id}</code>.",
|
||||
"APPRISE_URL_name": "Apprise notification URL",
|
||||
"About_Design": "Entworfen für:",
|
||||
"About_Exit": "Abmelden",
|
||||
"About_Title": "Netzwerksicherheitsscanner und Benachrichtigungsframework",
|
||||
@@ -313,6 +305,7 @@
|
||||
"Gen_Cancel": "Abbrechen",
|
||||
"Gen_Change": "Ändern",
|
||||
"Gen_Copy": "Ausführen",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "OK – Es kann einen Moment dauern, bis die Benutzeroberfläche aktualisiert wird, während ein Scan ausgeführt wird.",
|
||||
"Gen_Delete": "Löschen",
|
||||
"Gen_DeleteAll": "Alles löschen",
|
||||
@@ -320,7 +313,9 @@
|
||||
"Gen_Error": "Fehler",
|
||||
"Gen_Filter": "Filter",
|
||||
"Gen_Generate": "Generieren",
|
||||
"Gen_InvalidMac": "Ungültige MAC-Adresse.",
|
||||
"Gen_LockedDB": "ERROR - DB eventuell gesperrt - Nutze die Konsole in den Entwickler Werkzeugen (F12) zur Überprüfung oder probiere es später erneut.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
@@ -338,6 +333,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Zur Vorschau auswählen",
|
||||
"Gen_Selected_Devices": "Ausgewählte Geräte:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "Umschalten",
|
||||
"Gen_Upd": "Aktualisierung erfolgreich",
|
||||
"Gen_Upd_Fail": "Aktualisierung fehlgeschlagen",
|
||||
@@ -663,6 +659,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ Die Zeitpläne des Gerätescanners sind nicht synchronisiert.",
|
||||
"Settings_device_Scanners_desync_popup": "",
|
||||
"Speedtest_Results": "Ergebnisse des Geschwindigkeitstests",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "CPU",
|
||||
"Systeminfo_CPU_Cores": "CPU-Kerne:",
|
||||
"Systeminfo_CPU_Name": "CPU-Name:",
|
||||
|
||||
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Cancel",
|
||||
"Gen_Change": "Change",
|
||||
"Gen_Copy": "Run",
|
||||
"Gen_CopyToClipboard": "Copy to clipboard",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - It may take a while for the UI to update if a scan is running.",
|
||||
"Gen_Delete": "Delete",
|
||||
"Gen_DeleteAll": "Delete all",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Error",
|
||||
"Gen_Filter": "Filter",
|
||||
"Gen_Generate": "Generate",
|
||||
"Gen_InvalidMac": "Invalid Mac address.",
|
||||
"Gen_LockedDB": "ERROR - DB might be locked - Check F12 Dev tools -> Console or try later.",
|
||||
"Gen_NetworkMask": "Network mask",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Select to preview",
|
||||
"Gen_Selected_Devices": "Selected devices:",
|
||||
"Gen_Subnet": "Subnet",
|
||||
"Gen_Switch": "Switch",
|
||||
"Gen_Upd": "Updated successfully",
|
||||
"Gen_Upd_Fail": "Update failed",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ Device scanner schedules are out-of-sync.",
|
||||
"Settings_device_Scanners_desync_popup": "Schedules of devices scanners (<code>*_RUN_SCHD</code>) are not the same. This will result into inconsistent device online/offline notifications. Unless this is intended, please use the same schedule for all enabled <b>🔍device scanners</b>.",
|
||||
"Speedtest_Results": "Speedtest Results",
|
||||
"Systeminfo_AvailableIps": "Available IPs",
|
||||
"Systeminfo_CPU": "CPU",
|
||||
"Systeminfo_CPU_Cores": "CPU Cores:",
|
||||
"Systeminfo_CPU_Name": "CPU Name:",
|
||||
|
||||
97
front/php/templates/language/es_es.json
Normal file → Executable file
97
front/php/templates/language/es_es.json
Normal file → Executable file
@@ -5,14 +5,6 @@
|
||||
"API_TOKEN_name": "Token de la API",
|
||||
"API_display_name": "API",
|
||||
"API_icon": "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
|
||||
"APPRISE_HOST_description": "URL del host de Apprise que comienza con <code>http://</code> o <code>https://</code>. (no olvide incluir <code>/notify</code> al final)",
|
||||
"APPRISE_HOST_name": "URL del host de Apprise",
|
||||
"APPRISE_PAYLOAD_description": "Seleccione el tipo de carga útil enviada a Apprise. Por ejemplo, <code>html</code> funciona bien con correos electrónicos, <code>text</code> con aplicaciones de chat, como Telegram.",
|
||||
"APPRISE_PAYLOAD_name": "Tipo de carga",
|
||||
"APPRISE_SIZE_description": "El tamaño máximo de la carga útil de información como número de caracteres en la cadena pasada. Si supera el límite, se truncará y se agregará un mensaje <code>(text was truncated)</code>.",
|
||||
"APPRISE_SIZE_name": "Tamaño máximo de carga útil",
|
||||
"APPRISE_URL_description": "Informar de la URL de destino de la notificación. Por ejemplo, para Telegram sería <code>tgram://{bot_token}/{chat_id}</code>.",
|
||||
"APPRISE_URL_name": "URL de notificación de Apprise",
|
||||
"About_Design": "Diseñado para:",
|
||||
"About_Exit": "Salir",
|
||||
"About_Title": "Escáner de seguridad de la red y marco de notificaciones",
|
||||
@@ -50,7 +42,7 @@
|
||||
"BackDevices_Backup_Failed": "La copia de seguridad se ejecutó parcialmente con éxito. El archivo no se puede crear o está vacío.",
|
||||
"BackDevices_Backup_okay": "La copia de seguridad ejecutada con éxito con el nuevo archivo",
|
||||
"BackDevices_DBTools_DelDevError_a": "Error de eliminación del dispositivo",
|
||||
"BackDevices_DBTools_DelDevError_b": "Error de eliminación de dispositivos",
|
||||
"BackDevices_DBTools_DelDevError_b": "Error eliminando dispositivos",
|
||||
"BackDevices_DBTools_DelDev_a": "Dispositivo eliminado",
|
||||
"BackDevices_DBTools_DelDev_b": "Dispositivos eliminados",
|
||||
"BackDevices_DBTools_DelEvents": "Eventos eliminados",
|
||||
@@ -76,7 +68,7 @@
|
||||
"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_name": "Descubrir plugins",
|
||||
"DevDetail_Children_Title": "",
|
||||
"DevDetail_Children_Title": "Relaciones hijo",
|
||||
"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_CustomProperties_Title": "Propiedades personalizadas",
|
||||
@@ -89,15 +81,15 @@
|
||||
"DevDetail_EveandAl_NewDevice_Tooltip": "Mostrará el estado Nuevo para el dispositivo y lo incluirá en las listas cuando el filtro Nuevos dispositivos esté activo. No afecta a las notificaciones.",
|
||||
"DevDetail_EveandAl_RandomMAC": "MAC al azar",
|
||||
"DevDetail_EveandAl_ScanCycle": "Ciclo de escaneo",
|
||||
"DevDetail_EveandAl_ScanCycle_a": "Escanear Dispositivo",
|
||||
"DevDetail_EveandAl_ScanCycle_z": "No Escanear Dispositivo",
|
||||
"DevDetail_EveandAl_ScanCycle_a": "Escanear dispositivo",
|
||||
"DevDetail_EveandAl_ScanCycle_z": "No escanear dispositivo",
|
||||
"DevDetail_EveandAl_Skip": "Omitir notificaciones repetidas durante",
|
||||
"DevDetail_EveandAl_Title": "Configuración de eventos y alertas",
|
||||
"DevDetail_Events_CheckBox": "Ocultar eventos de conexión",
|
||||
"DevDetail_GoToNetworkNode": "Navegar a la página de Internet del nodo seleccionado.",
|
||||
"DevDetail_Icon": "Icono",
|
||||
"DevDetail_Icon_Descr": "Ingrese un nombre de icono de fuente awesome sin el prefijo fa- o con clase completa, por ejemplo: fa fa-skin fa-apple.",
|
||||
"DevDetail_Loading": "Cargando ...",
|
||||
"DevDetail_Loading": "Cargando…",
|
||||
"DevDetail_MainInfo_Comments": "Comentario",
|
||||
"DevDetail_MainInfo_Favorite": "Favorito",
|
||||
"DevDetail_MainInfo_Group": "Grupo",
|
||||
@@ -113,11 +105,11 @@
|
||||
"DevDetail_MainInfo_Type": "Tipo",
|
||||
"DevDetail_MainInfo_Vendor": "Proveedor",
|
||||
"DevDetail_MainInfo_mac": "MAC",
|
||||
"DevDetail_NavToChildNode": "",
|
||||
"DevDetail_NavToChildNode": "Abrir nodo hijo",
|
||||
"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_Nmap_Scans": "Escaneos de Nmap",
|
||||
"DevDetail_Nmap_Scans_desc": "Aquí puede ejecutar escaneos NMAP manuales. También puede programar escaneos NMAP automáticos regulares a través del complemento Servicios y puertos (NMAP). Dirígete a <a href='/settings.php' target='_blank'>Configuración</a> para obtener más información",
|
||||
"DevDetail_Nmap_Scans_desc": "Aquí puede ejecutar escaneos NMAP manuales. También puede programar escaneos NMAP automáticos regulares a través del complemento Servicios y puertos (NMAP). Dirígete a <a href=\"https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nmap_scan\" target=\"_blank\">Documentación</a> para obtener más información",
|
||||
"DevDetail_Nmap_buttonDefault": "Escaneado predeterminado",
|
||||
"DevDetail_Nmap_buttonDefault_text": "Escaneo predeterminado: NMAP escanea los 1,000 puertos principales para cada protocolo de escaneo solicitado. Esto atrapa aproximadamente el 93% de los puertos TCP y el 49% de los puertos UDP. (aproximadamente 5 segundos)",
|
||||
"DevDetail_Nmap_buttonDetail": "Escaneo detallado",
|
||||
@@ -189,7 +181,7 @@
|
||||
"DevDetail_Tools_WOL": "Enviar comando WOL a ",
|
||||
"DevDetail_Tools_WOL_noti": "Wake-on-LAN",
|
||||
"DevDetail_Tools_WOL_noti_text": "El comando de Wake-on-LAN en enviado a la dirección de escucha. Si el dispositivo no está en la misma subred/vlan que NetAlertX, el dispositivo no responderá.",
|
||||
"DevDetail_Type_hover": "El tipo de dispositivo. Si selecciona cualquiera de los dispositivos de la red predefinidos (por ejemplo: AP, Firewall, enrutador, conmutador...), aparecerán en la configuración del árbol de redes como posibles nodos de la red principal.",
|
||||
"DevDetail_Type_hover": "El tipo de dispositivo. Si selecciona cualquiera de los dispositivos de la red predefinidos (por ejemplo: AP, Firewall, enrutador, conmutador ...), aparecerán en la configuración del árbol de redes como posibles nodos de la red principal.",
|
||||
"DevDetail_Vendor_hover": "El proveedor debe ser detectado automáticamente. Puede sobrescribir o agregar su valor personalizado.",
|
||||
"DevDetail_WOL_Title": "<i class=\"fa fa-power-off\"></i> Wake-on-LAN",
|
||||
"DevDetail_button_AddIcon": "Añadir un nuevo icono",
|
||||
@@ -206,25 +198,25 @@
|
||||
"DevDetail_button_Save": "Guardar",
|
||||
"DeviceEdit_ValidMacIp": "Introduzca una dirección <b>Mac</b> y una dirección <b>IP</b> válidas .",
|
||||
"Device_MultiEdit": "Edición múltiple",
|
||||
"Device_MultiEdit_Backup": "Tenga cuidado, ingresar valores incorrectos o romperá su configuración. Por favor, haga una copia de seguridad de su base de datos o de la configuración de los dispositivos primero (<a href=\"php/server/devices.php?action=ExportCSV\">haga clic para descargar <i class=\"fa-solid fa-download fa-bounce\"></i></a>). Lea cómo recuperar dispositivos de este archivo en la documentación de <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/BACKUPS.md#scenario-2-corrupted-database\" target=\"_blank\">Copia de seguridad</a>.",
|
||||
"Device_MultiEdit_Backup": "Tenga cuidado, ingresar valores incorrectos o romperá su configuración. Por favor, haga una copia de seguridad de su base de datos o de la configuración de los dispositivos primero (<a href=\"php/server/devices.php?action=ExportCSV\">haga clic para descargar <i class=\"fa-solid fa-download fa-bounce\"></i></a>). Lea cómo recuperar dispositivos de este archivo en la documentación de <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/BACKUPS.md#scenario-2-corrupted-database\" target=\"_blank\">Copia de seguridad</a>. Para aplicar sus cambios haga click en el ícono de <b>Guardar<i class=\"fa-solid fa-save\"></i></b> en cada campo que quiera actualizar.",
|
||||
"Device_MultiEdit_Fields": "Editar campos:",
|
||||
"Device_MultiEdit_MassActions": "Acciones masivas:",
|
||||
"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_Shortcut_AllDevices": "Mis dispositivos",
|
||||
"Device_Shortcut_AllNodes": "",
|
||||
"Device_Shortcut_AllNodes": "Todos los nodos",
|
||||
"Device_Shortcut_Archived": "Archivado(s)",
|
||||
"Device_Shortcut_Connected": "Conectado(s)",
|
||||
"Device_Shortcut_Devices": "Dispositivos",
|
||||
"Device_Shortcut_DownAlerts": "Caído y sin conexión",
|
||||
"Device_Shortcut_DownOnly": "Caído",
|
||||
"Device_Shortcut_Favorites": "Favorito(s)",
|
||||
"Device_Shortcut_NewDevices": "Nuevo(s)",
|
||||
"Device_Shortcut_NewDevices": "Nuevos dispositivos",
|
||||
"Device_Shortcut_OnlineChart": "Presencia del dispositivo a lo largo del tiempo",
|
||||
"Device_TableHead_AlertDown": "Alerta desactivada",
|
||||
"Device_TableHead_Connected_Devices": "Conexiones",
|
||||
"Device_TableHead_CustomProps": "Propiedades / Acciones",
|
||||
"Device_TableHead_FQDN": "",
|
||||
"Device_TableHead_FQDN": "FQDN",
|
||||
"Device_TableHead_Favorite": "Favorito",
|
||||
"Device_TableHead_FirstSession": "1ra. sesión",
|
||||
"Device_TableHead_GUID": "GUID",
|
||||
@@ -239,11 +231,11 @@
|
||||
"Device_TableHead_Name": "Nombre",
|
||||
"Device_TableHead_NetworkSite": "Lugar de la red",
|
||||
"Device_TableHead_Owner": "Propietario",
|
||||
"Device_TableHead_ParentRelType": "",
|
||||
"Device_TableHead_ParentRelType": "Tipo de relación",
|
||||
"Device_TableHead_Parent_MAC": "Nodo principal de la red",
|
||||
"Device_TableHead_Port": "Puerto",
|
||||
"Device_TableHead_PresentLastScan": "Historial",
|
||||
"Device_TableHead_ReqNicsOnline": "",
|
||||
"Device_TableHead_ReqNicsOnline": "Requiere que la interfaz de red (NIC) esté conectada",
|
||||
"Device_TableHead_RowID": "ID de fila",
|
||||
"Device_TableHead_Rowid": "ID de fila",
|
||||
"Device_TableHead_SSID": "SSID",
|
||||
@@ -266,7 +258,7 @@
|
||||
"ENCRYPTION_KEY_name": "Llave de cifrado",
|
||||
"Email_display_name": "Email",
|
||||
"Email_icon": "<i class=\"fa fa-at\"></i>",
|
||||
"Events_Loading": "Cargando...",
|
||||
"Events_Loading": "Cargando. . .",
|
||||
"Events_Periodselect_All": "Toda la información",
|
||||
"Events_Periodselect_LastMonth": "El mes pasado",
|
||||
"Events_Periodselect_LastWeek": "La semana pasada",
|
||||
@@ -277,7 +269,7 @@
|
||||
"Events_Shortcut_DownAlerts": "Alerta(s) de caída(s)",
|
||||
"Events_Shortcut_Events": "Eventos",
|
||||
"Events_Shortcut_MissSessions": "Sesiones faltantes",
|
||||
"Events_Shortcut_NewDevices": "Nuevo(s)",
|
||||
"Events_Shortcut_NewDevices": "Nuevos dispositivos",
|
||||
"Events_Shortcut_Sessions": "Sesiones",
|
||||
"Events_Shortcut_VoidSessions": "Sesiones anuladas",
|
||||
"Events_TableHead_AdditionalInfo": "Información adicional",
|
||||
@@ -305,12 +297,13 @@
|
||||
"Gen_Add": "Añadir",
|
||||
"Gen_AddDevice": "Añadir dispositivo",
|
||||
"Gen_Add_All": "Añadir todo",
|
||||
"Gen_All_Devices": "Todo los dispositivos",
|
||||
"Gen_All_Devices": "Todos los dispositivos",
|
||||
"Gen_AreYouSure": "¿Estás seguro?",
|
||||
"Gen_Backup": "Ejecutar copia de seguridad",
|
||||
"Gen_Cancel": "Cancelar",
|
||||
"Gen_Change": "Cambiar",
|
||||
"Gen_Copy": "Ejecutar",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "Correcto - La interfaz puede tardar en actualizarse si se está ejecutando un escaneo.",
|
||||
"Gen_Delete": "Eliminar",
|
||||
"Gen_DeleteAll": "Eliminar todo",
|
||||
@@ -318,7 +311,9 @@
|
||||
"Gen_Error": "Error",
|
||||
"Gen_Filter": "Filtro",
|
||||
"Gen_Generate": "Generar",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "Fallo - La base de datos puede estar bloqueada - Pulsa F1 -> Ajustes de desarrolladores -> Consola o prueba más tarde.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "Desconectado",
|
||||
"Gen_Okay": "Aceptar",
|
||||
"Gen_Online": "En linea",
|
||||
@@ -336,6 +331,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Seleccionar para previsualizar",
|
||||
"Gen_Selected_Devices": "Dispositivos seleccionados:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "Cambiar",
|
||||
"Gen_Upd": "Actualizado correctamente",
|
||||
"Gen_Upd_Fail": "Fallo al actualizar",
|
||||
@@ -348,15 +344,15 @@
|
||||
"Gen_create_new_device_info": "Los dispositivos se suelen descubrir utilizando <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">plugins</a>. Sin embargo, en algunos casos, es posible que necesite agregar dispositivos manualmente. Para explorar escenarios específicos, consulte la documentación <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/REMOTE_NETWORKS.md\">Redes remotas</a>.",
|
||||
"General_display_name": "General",
|
||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "Se trata de una configuración de mantenimiento <b>BORRAR dispositivos</b>. Si está activado (<code>0</code> está desactivado), los dispositivos marcados como <b>Nuevo dispositivo</b> se eliminarán si su fecha de <b>primera sesión</b> es anterior a las horas especificadas en este ajuste. Use este ajuste si desea eliminar automáticamente <b>Nuevos dispositivos</b> después de <code>X</code> horas.",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "Esta es una configuración de mantenimiento <b>BORRAR dispositivos</b>. Si está activado (<code>0</code> está desactivado), los dispositivos marcados como <b>Nuevo dispositivo</b> se eliminarán si su fecha de <b>Primera Sesión</b> es anterior a las horas especificadas en este ajuste. Use este ajuste si desea eliminar automáticamente <b>Nuevos dispositivos</b> después de <code>X</code> horas.",
|
||||
"HRS_TO_KEEP_NEWDEV_name": "Eliminar nuevos dispositivos después",
|
||||
"HRS_TO_KEEP_OFFDEV_description": "Se trata de una configuración de mantenimiento <b>BORRAR dispositivos</b>. Si está activado (<code>0</code> está desactivado), los dispositivos que están <b>sin conexión</b> y su fecha de <b>última conexión</b> es anterior a las horas especificadas en este ajuste se eliminarán. Use este ajuste si desea eliminar automáticamente <b>los dispositivos sin conexión</b> después de que el <code>X</code> horas esté sin conexión.",
|
||||
"HRS_TO_KEEP_OFFDEV_description": "Esta es una configuración de mantenimiento <b>BORRAR dispositivos</b>. Si está activado (<code>0</code> está desactivado), los dispositivos que están <b>Sin Conexión</b> y su fecha de <b>Última Conexión</b> es anterior a las horas especificadas en este ajuste se eliminarán. Use este ajuste si desea eliminar automáticamente <b>los dispositivos sin conexión</b> después de que el <code>X</code> horas esté sin conexión.",
|
||||
"HRS_TO_KEEP_OFFDEV_name": "Borrar dispositivos sin conexión después de",
|
||||
"LOADED_PLUGINS_description": "¿Qué plugins cargar?. Agregar plugins puede ralentizar la aplicación. Obtén más información sobre los complementos que deben habilitarse, los tipos o las opciones de escaneo en los documentos de <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">plugins</a>. Los plugins descargados perderán tu configuración. Solo se pueden descargar los complementos <code>deshabilitados</code>.",
|
||||
"LOADED_PLUGINS_name": "Plugins cargados",
|
||||
"LOG_LEVEL_description": "Esto hará que el registro tenga más información. Util para depurar que eventos se van guardando en la base de datos.",
|
||||
"LOG_LEVEL_name": "Imprimir registros adicionales",
|
||||
"Loading": "Cargando...",
|
||||
"Loading": "Cargando . . .",
|
||||
"Login_Box": "Ingrese su contraseña",
|
||||
"Login_Default_PWD": "La contraseña por defecto \"123456\" sigue activa.",
|
||||
"Login_Info": "Las contraseñas se establecen a través del plugin Establecer contraseña. Compruebe la <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/set_password\">documentación SETPWD</a> si tiene problemas para iniciar sesión.",
|
||||
@@ -388,11 +384,11 @@
|
||||
"Maint_PurgeLog": "Purgar los registros",
|
||||
"Maint_RestartServer": "Restablecer el servidor",
|
||||
"Maint_Restart_Server_noti_text": "¿Estás seguro de que desea reiniciar el servidor backend? Esto puede causar inconsistencia en la aplicación. Primero haga una copia de seguridad de su configuración.<br/> <br/> Nota: Esto puede tardar unos minutos.",
|
||||
"Maintenance_InitCheck": "",
|
||||
"Maintenance_InitCheck_Checking": "",
|
||||
"Maintenance_InitCheck_QuickSetupGuide": "",
|
||||
"Maintenance_InitCheck_Success": "",
|
||||
"Maintenance_ReCheck": "",
|
||||
"Maintenance_InitCheck": "Validación inicial",
|
||||
"Maintenance_InitCheck_Checking": "Validando . . .",
|
||||
"Maintenance_InitCheck_QuickSetupGuide": "Asegúrece de seguir la <a href=\"https://jokob-sk.github.io/NetAlertX/INITIAL_SETUP/\" target=\"_blank\">guía de configuración rápida</a>.",
|
||||
"Maintenance_InitCheck_Success": "¡Aplicación inicializada con éxito!",
|
||||
"Maintenance_ReCheck": "Reintentar validación",
|
||||
"Maintenance_Running_Version": "Versión instalada",
|
||||
"Maintenance_Status": "Situación",
|
||||
"Maintenance_Title": "Herramientas de mantenimiento",
|
||||
@@ -475,7 +471,7 @@
|
||||
"Maintenance_Tools_Tab_UISettings": "Ajustes de interfaz",
|
||||
"Maintenance_arp_status": "Estado de la exploración",
|
||||
"Maintenance_arp_status_off": "está actualmente deshabilitado",
|
||||
"Maintenance_arp_status_on": "escaneo(s) actualmente en ejecución",
|
||||
"Maintenance_arp_status_on": "escaneo en ejecución",
|
||||
"Maintenance_built_on": "Creada",
|
||||
"Maintenance_current_version": "No hay actualizaciones disponibles. Comprueba en que <a href=\"https://github.com/jokob-sk/NetAlertX/issues/138\" target=\"_blank\">se está trabajando</a>.",
|
||||
"Maintenance_database_backup": "Copias de seguridad de BD",
|
||||
@@ -526,10 +522,10 @@
|
||||
"Navigation_Workflows": "Flujo de trabajo",
|
||||
"Network_Assign": "Conectar al nodo de <i class=\"fa fa-server\"></i> red",
|
||||
"Network_Cant_Assign": "No se puede asignar el nodo principal de Internet como nodo secundario.",
|
||||
"Network_Cant_Assign_No_Node_Selected": "",
|
||||
"Network_Cant_Assign_No_Node_Selected": "No es posible asignar, no se ha seleccionado un nodo padre.",
|
||||
"Network_Configuration_Error": "Error en la configuración",
|
||||
"Network_Connected": "Dispositivos conectados",
|
||||
"Network_Devices": "",
|
||||
"Network_Devices": "Dispositivos de red",
|
||||
"Network_ManageAdd": "Añadir dispositivo",
|
||||
"Network_ManageAdd_Name": "Nombre del dispositivo",
|
||||
"Network_ManageAdd_Name_text": "Nombre sin caracteres especiales",
|
||||
@@ -564,8 +560,8 @@
|
||||
"Network_Root": "Nodo principal",
|
||||
"Network_Root_Not_Configured": "Seleccione un tipo de dispositivo de red, por ejemplo un <b>Gateway</b>, en el campo <b>Tipo</b> del <a href=\"deviceDetails.php?mac=Internet\">dispositivo principal de Internet</a> para empezar a configurar esta pantalla. <br/><br/>Puede encontrar más documentación en la guía <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md\" target=\"_blank\">¿Cómo configurar su página de Red?</a>",
|
||||
"Network_Root_Unconfigurable": "Root no configurable",
|
||||
"Network_ShowArchived": "",
|
||||
"Network_ShowOffline": "",
|
||||
"Network_ShowArchived": "Mostrar archivado",
|
||||
"Network_ShowOffline": "Mostrar fuera de línea",
|
||||
"Network_Table_Hostname": "Nombre de host",
|
||||
"Network_Table_IP": "Dirección IP",
|
||||
"Network_Table_State": "Estado",
|
||||
@@ -602,9 +598,9 @@
|
||||
"Presence_Key_OnlineNow_desc": "Dispositivo detectado en el último escaneo como conectado.",
|
||||
"Presence_Key_OnlinePast": "Anterior en línea",
|
||||
"Presence_Key_OnlinePastMiss": "Anterior en línea (miss-match)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "Dispositivo en línea en el pasado, pero actualmente desconectado, pero la sesión de inicio podría estar faltando o tiene datos conflictivos. (Puede ser un error - por favor envíe un PR si sabe cómo solucionarlo - estoy un poco perdido en código)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "Dispositivo en línea en el pasado, pero actualmente desconectado, pero la sesión de inicio podría estar faltando o tiene datos conflictivos.",
|
||||
"Presence_Key_OnlinePast_desc": "Dispositivo en línea en el pasado, pero actualmente no conectado.",
|
||||
"Presence_Loading": "Cargando...",
|
||||
"Presence_Loading": "Cargando. . .",
|
||||
"Presence_Shortcut_AllDevices": "Mis dispositivos",
|
||||
"Presence_Shortcut_Archived": "Archivado(s)",
|
||||
"Presence_Shortcut_Connected": "Conectado(s)",
|
||||
@@ -612,9 +608,9 @@
|
||||
"Presence_Shortcut_DownAlerts": "Alerta(s) de caída(s)",
|
||||
"Presence_Shortcut_Favorites": "Favorito(s)",
|
||||
"Presence_Shortcut_NewDevices": "Nuevo(s)",
|
||||
"Presence_Title": "Historial por dispositivo",
|
||||
"REFRESH_FQDN_description": "",
|
||||
"REFRESH_FQDN_name": "",
|
||||
"Presence_Title": "Presencia por dispositivo",
|
||||
"REFRESH_FQDN_description": "Vuelve a escanear todos los dispositivos y actualiza su nombre de dominio completo (FQDN). Si esta opción está deshabilitada, solo se escanean los dispositivos sin nombre conocido para mejorar el rendimiento. En este caso, el FQDN se actualiza solo durante la detección inicial de dispositivos.",
|
||||
"REFRESH_FQDN_name": "Refrescar FQDN",
|
||||
"REPORT_APPRISE_description": "Habilitar el envío de notificaciones a través de <a target=\"_blank\" href=\"https://hub.docker.com/r/caronc/apprise\">Apprise</a>.",
|
||||
"REPORT_APPRISE_name": "Habilitar Apprise",
|
||||
"REPORT_DASHBOARD_URL_description": "Esta URL se utiliza como base para generar enlaces en los correos electrónicos. Ingrese la URL completa que comienza con <code>http://</code>, incluido el número de puerto (sin barra inclinada al final <code>/</code>).",
|
||||
@@ -662,6 +658,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ Los horarios del escáner de los dispositivos no están sincronizados.",
|
||||
"Settings_device_Scanners_desync_popup": "Los horarios de escáneres de dispositivos (<code> *_RUN_SCHD</code> ) no son lo mismo. Esto resultará en notificaciones inconsistentes del dispositivo en línea/fuera de línea. A menos que sea así, utilice el mismo horario para todos los habilitados.<b> 🔍Escáneres de dispositivos</b> .",
|
||||
"Speedtest_Results": "Resultados de la prueba de velocidad",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "CPU",
|
||||
"Systeminfo_CPU_Cores": "Núcleos de CPU:",
|
||||
"Systeminfo_CPU_Name": "Nombre de la CPU:",
|
||||
@@ -795,10 +792,10 @@
|
||||
"add_icon_event_tooltip": "Agregar nuevo icono",
|
||||
"add_option_event_tooltip": "Añadir nuevo valor",
|
||||
"copy_icons_event_tooltip": "Sobrescribir los iconos de todos los dispositivos con el mismo tipo de dispositivo",
|
||||
"devices_old": "Volviendo a actualizar....",
|
||||
"devices_old": "Refrescando . . .",
|
||||
"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",
|
||||
"go_to_device_event_tooltip": "",
|
||||
"go_to_device_event_tooltip": "Navegar al dispositivo",
|
||||
"go_to_node_event_tooltip": "Vaya a la página de Red del nodo indicado",
|
||||
"new_version_available": "Una nueva versión está disponible.",
|
||||
"report_guid": "Guía de las notificaciones:",
|
||||
@@ -806,12 +803,12 @@
|
||||
"report_select_format": "Selecciona el formato:",
|
||||
"report_time": "Hora de la notificación:",
|
||||
"run_event_tooltip": "Activa el ajuste y guarda tus cambios antes de ejecutarlo.",
|
||||
"select_icon_event_tooltip": "",
|
||||
"select_icon_event_tooltip": "Seleccionar ícono",
|
||||
"settings_core_icon": "fa-solid fa-gem",
|
||||
"settings_core_label": "Núcleo",
|
||||
"settings_device_scanners": "Los escáneres de los dispositivos se utilizan para descubrir dispositivos que escriben en la tabla de base de datos de CurrentScan.",
|
||||
"settings_device_scanners_icon": "fa-solid fa-magnifying-glass-plus",
|
||||
"settings_device_scanners_info": "Cargue aún más escáneres de dispositivos con el ajuste <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_device_scanners_info": "Cargue más escáneres de dispositivos con el ajuste <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_device_scanners_label": "Escáneres de dispositivos",
|
||||
"settings_enabled": "Configuración activada",
|
||||
"settings_enabled_icon": "fa-solid fa-toggle-on",
|
||||
@@ -820,7 +817,7 @@
|
||||
"settings_imported_label": "Configuración importada",
|
||||
"settings_missing": "No se han cargado todos los ajustes. Carga alta en la base de datos o secuencia de inicio de la app. Haz clic en el botón 🔄 recargar en la parte superior.",
|
||||
"settings_missing_block": "Error: La configuración no se ha cargado correctamente. Haga clic en el botón de recarga 🔄 en la parte superior, alternativamente, compruebe el registro del navegador para más detalles (F12).",
|
||||
"settings_old": "Importar ajustes y reiniciar...",
|
||||
"settings_old": "Importar ajustes y reiniciar. . .",
|
||||
"settings_other_scanners": "Otros plugins de escáner no relacionados con dispositivos que están activados actualmente.",
|
||||
"settings_other_scanners_icon": "fa-solid fa-recycle",
|
||||
"settings_other_scanners_label": "Otros escáneres",
|
||||
@@ -829,9 +826,9 @@
|
||||
"settings_publishers_info": "Cargue más editor@s con el ajuste <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_publishers_label": "Editores",
|
||||
"settings_readonly": "No se puede LEER ni ESCRIBIR <code>app.conf</code>. Intente reiniciar el contenedor y lea la <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/FILE_PERMISSIONS.md\" target=\"_blank\">documentación de permisos de archivo</a>",
|
||||
"settings_saved": "<br/>Ajustes guardados. <br/> Recargando... <br/><i class=\"ion ion-ios-loop-strong fa-spin fa-2x fa-fw\"></i> <br/>",
|
||||
"settings_saved": "<br/>Ajustes guardados. <br/> Recargando. . . <br/><i class=\"ion ion-ios-loop-strong fa-spin fa-2x fa-fw\"></i> <br/>",
|
||||
"settings_system_icon": "fa-solid fa-gear",
|
||||
"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>",
|
||||
"test_event_tooltip": "Guarda tus cambios antes de probar nuevos ajustes."
|
||||
}
|
||||
}
|
||||
11
front/php/templates/language/fr_fr.json
Normal file → Executable file
11
front/php/templates/language/fr_fr.json
Normal file → Executable file
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Annuler",
|
||||
"Gen_Change": "Changement",
|
||||
"Gen_Copy": "Lancer",
|
||||
"Gen_CopyToClipboard": "Copier vers le presse-papier",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - cela peut prendre du temps à l'interface pour se mettre à jour si un scan est en cours.",
|
||||
"Gen_Delete": "Supprimer",
|
||||
"Gen_DeleteAll": "Supprimer tous",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Erreur",
|
||||
"Gen_Filter": "Filtrer",
|
||||
"Gen_Generate": "Générer",
|
||||
"Gen_InvalidMac": "Adresse MAC invalide.",
|
||||
"Gen_LockedDB": "Erreur - La base de données est peut-être verrouillée - Vérifier avec les outils de dév via F12 -> Console ou essayer plus tard.",
|
||||
"Gen_NetworkMask": "Masque réseau",
|
||||
"Gen_Offline": "Hors ligne",
|
||||
"Gen_Okay": "OK",
|
||||
"Gen_Online": "En ligne",
|
||||
@@ -325,7 +328,8 @@
|
||||
"Gen_Select": "Sélectionner",
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Sélectionnez pour prévisualiser",
|
||||
"Gen_Selected_Devices": "Appareils sélectionnés :",
|
||||
"Gen_Selected_Devices": "Appareils sélectionnés :",
|
||||
"Gen_Subnet": "Sous-réseau",
|
||||
"Gen_Switch": "Basculer",
|
||||
"Gen_Upd": "Mise à jour réussie",
|
||||
"Gen_Upd_Fail": "Échec de la mise à jour",
|
||||
@@ -494,7 +498,7 @@
|
||||
"Network_Cant_Assign_No_Node_Selected": "Impossible d'assigner, aucun noeud parent sélectionné.",
|
||||
"Network_Configuration_Error": "Erreur de configuration",
|
||||
"Network_Connected": "Appareils connectés",
|
||||
"Network_Devices": "",
|
||||
"Network_Devices": "Appareils réseau",
|
||||
"Network_ManageAdd": "Ajouter un appareil",
|
||||
"Network_ManageAdd_Name": "Nom de l'appareil",
|
||||
"Network_ManageAdd_Name_text": "Nom sans caractère spécial",
|
||||
@@ -563,7 +567,7 @@
|
||||
"Presence_Key_OnlineNow_desc": "Appareil détecté comme étant en ligne lors de la dernière analyse.",
|
||||
"Presence_Key_OnlinePast": "Passé en ligne",
|
||||
"Presence_Key_OnlinePastMiss": "Passé en ligne (correspondance manquée)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "Appareil en ligne dans le passé, mais actuellement hors ligne, mais la session de démarrage pourrait être manquante ou avoir des données contradictoires. (il s'agit peut-être d'un bogue - veuillez soumettre un PR si vous savez comment le corriger - je suis un peu perdu dans le code ici)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "Appareil en ligne dans le passé, mais actuellement hors ligne, mais la session de démarrage pourrait être manquante ou avoir des données contradictoires.",
|
||||
"Presence_Key_OnlinePast_desc": "Appareil en ligne dans le passé, mais actuellement hors ligne.",
|
||||
"Presence_Loading": "Chargement …",
|
||||
"Presence_Shortcut_AllDevices": "Mes appareils",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ La planification des différents scanners d'appareils est désynchronisée.",
|
||||
"Settings_device_Scanners_desync_popup": "La planification des scanners (<code>*_RUN_SCHD</code>) n'est pas identique entre scanners. Cela va entraîner des notifications en ligne/hors-ligne non cohérentes. À moins que cela soit attendu, utilisez la même planification pour tous les <b>🔍scanners d'appareils</b> activés.",
|
||||
"Speedtest_Results": "Résultats du test de débit",
|
||||
"Systeminfo_AvailableIps": "Adresses IP disponibles",
|
||||
"Systeminfo_CPU": "Processeur",
|
||||
"Systeminfo_CPU_Cores": "Cœurs de processeur :",
|
||||
"Systeminfo_CPU_Name": "Nom du processeur :",
|
||||
|
||||
43
front/php/templates/language/it_it.json
Normal file → Executable file
43
front/php/templates/language/it_it.json
Normal file → Executable file
@@ -9,7 +9,7 @@
|
||||
"About_Exit": "Esci",
|
||||
"About_Title": "Scanner di sicurezza di rete e framework di notifica",
|
||||
"AppEvents_AppEventProcessed": "Elaborato",
|
||||
"AppEvents_DateTimeCreated": "Scoperto il",
|
||||
"AppEvents_DateTimeCreated": "Registrato",
|
||||
"AppEvents_Extra": "Extra",
|
||||
"AppEvents_GUID": "GUID evento applicazione",
|
||||
"AppEvents_Helper1": "Aiutante 1",
|
||||
@@ -72,11 +72,11 @@
|
||||
"DevDetail_CustomProperties_Title": "Proprietà personalizzate",
|
||||
"DevDetail_CustomProps_reset_info": "Questa operazione rimuoverà le proprietà personalizzate su questo dispositivo e le ripristinerà al valore predefinito.",
|
||||
"DevDetail_DisplayFields_Title": "Visualizza",
|
||||
"DevDetail_EveandAl_AlertAllEvents": "Notifica eventi",
|
||||
"DevDetail_EveandAl_AlertDown": "Avviso disconnessione",
|
||||
"DevDetail_EveandAl_AlertAllEvents": "Eventi di allerta",
|
||||
"DevDetail_EveandAl_AlertDown": "Avviso inattivo",
|
||||
"DevDetail_EveandAl_Archived": "Archiviato",
|
||||
"DevDetail_EveandAl_NewDevice": "Nuovo dispositivo",
|
||||
"DevDetail_EveandAl_NewDevice_Tooltip": "Mostrerà il Nuovo stato del dispositivo e lo includerà negli elenchi quando il filtro Nuovi dispositivi è attivo. Non influisce sulle notifiche.",
|
||||
"DevDetail_EveandAl_NewDevice_Tooltip": "Mostra lo stato Nuovo del dispositivo e lo include negli elenchi quando il filtro Nuovi dispositivi è attivo. Non influisce sulle notifiche.",
|
||||
"DevDetail_EveandAl_RandomMAC": "MAC casuale",
|
||||
"DevDetail_EveandAl_ScanCycle": "Scansiona dispositivo",
|
||||
"DevDetail_EveandAl_ScanCycle_a": "Scansiona dispositivo",
|
||||
@@ -201,7 +201,7 @@
|
||||
"Device_MultiEdit_MassActions": "Azioni di massa:",
|
||||
"Device_MultiEdit_Tooltip": "Attento. Facendo clic verrà applicato il valore sulla sinistra a tutti i dispositivi selezionati sopra.",
|
||||
"Device_Searchbox": "Cerca",
|
||||
"Device_Shortcut_AllDevices": "Miei dispositivi",
|
||||
"Device_Shortcut_AllDevices": "I miei dispositivi",
|
||||
"Device_Shortcut_AllNodes": "Tutti i nodi",
|
||||
"Device_Shortcut_Archived": "Archiviati",
|
||||
"Device_Shortcut_Connected": "Connessi",
|
||||
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Annulla",
|
||||
"Gen_Change": "Modifica",
|
||||
"Gen_Copy": "Esegui",
|
||||
"Gen_CopyToClipboard": "Copia negli appunti",
|
||||
"Gen_DataUpdatedUITakesTime": "OK: l'aggiornamento dell'interfaccia utente potrebbe richiedere del tempo se è in esecuzione una scansione.",
|
||||
"Gen_Delete": "Elimina",
|
||||
"Gen_DeleteAll": "Elimina tutti",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Errore",
|
||||
"Gen_Filter": "Filtro",
|
||||
"Gen_Generate": "Genera",
|
||||
"Gen_InvalidMac": "Indirizzo Mac non valido.",
|
||||
"Gen_LockedDB": "ERRORE: il DB potrebbe essere bloccato, controlla F12 Strumenti di sviluppo -> Console o riprova più tardi.",
|
||||
"Gen_NetworkMask": "Maschera di rete",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Seleziona per anteprima",
|
||||
"Gen_Selected_Devices": "Dispositivi selezionati:",
|
||||
"Gen_Subnet": "Sottorete",
|
||||
"Gen_Switch": "Cambia",
|
||||
"Gen_Upd": "Aggiornato correttamente",
|
||||
"Gen_Upd_Fail": "Aggiornamento fallito",
|
||||
@@ -338,9 +342,9 @@
|
||||
"Gen_create_new_device_info": "I dispositivi vengono generalmente rilevati utilizzando <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">plugin</a>. Tuttavia, in alcuni casi, potrebbe essere necessario aggiungere manualmente i dispositivi. Per esplorare scenari specifici, consulta la <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/REMOTE_NETWORKS.md\">documentazione sulle reti remote</a>.",
|
||||
"General_display_name": "Generale",
|
||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "Questa è un'impostazione di manutenzione <b>ELIMINAZIONE dispositivi</b>. Se abilitata (<code>0</code> è disabilitata), tutti i dispositivi marcati con <b>Nuovo dispositivo</b> verranno eliminati se l'orario della <b>Prima sessione</b> è precedente all'orario di questa impostazione. Usa questa impostazione se vuoi eliminare automaticamente i <b>Nuovi dispositivi</b> dopo <code>X</code> ore.",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "Questa è un'impostazione di manutenzione che <b>ELIMINA dispositivi</b>. Se abilitata (<code>0</code> è disabilitata), i dispositivi contrassegnati come <b>Nuovo dispositivo</b> verranno eliminati se la loro <b>Prima sessione</b> è antecedente alle ore specificate in questa impostazione. Utilizza questa impostazione se vuoi eliminare automaticamente i <b>Nuovi dispositivi</b> dopo <code>X</code> ore.",
|
||||
"HRS_TO_KEEP_NEWDEV_name": "Elimina nuovi dispositivi dopo",
|
||||
"HRS_TO_KEEP_OFFDEV_description": "Questa è un'impostazione di manutenzione <b>ELIMINAZIONE dispositivi</b>. Se abilitata (<code>0</code> è disabilitata), i dispositivi che sono <b>Offline</b> e la loro data e ora <b>Ultima connessione</b> sono più vecchi delle ore specificate in questa impostazione saranno eliminati. Usa questa impostazione se vuoi eliminare automaticamente <b>Dispositivi offline</b> dopo <code>X</code> ore trascorse offline.",
|
||||
"HRS_TO_KEEP_OFFDEV_description": "Questa è un'impostazione di manutenzione che <b>ELIMINA dispositivi</b>. Se abilitata (<code>0</code> è disabilitata), i dispositivi <b>Offline</b> la cui data e ora di <b>Ultima connessione</b> sono antecedenti alle ore specificate in questa impostazione, verranno eliminati. Utilizza questa impostazione se vuoi eliminare automaticamente i <b>Dispositivi offline</b> dopo <code>X</code> ore trascorse offline.",
|
||||
"HRS_TO_KEEP_OFFDEV_name": "Elimina dispositivi offline dopo",
|
||||
"LOADED_PLUGINS_description": "Quali Plugin caricare. L'aggiunta di plugin potrebbe rallentare l'applicazione. Leggi di più su quali plugin necessitano di essere abilitati, tipi e opzioni di scansione nella <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">documentazione plugin</a>. I plugin disinstallati perdono la loro configurazione. Solo i plugin <code>disabilitati</code> possono essere disinstallati.",
|
||||
"LOADED_PLUGINS_name": "Plugin caricati",
|
||||
@@ -372,12 +376,12 @@
|
||||
"Maintenance_Running_Version": "Versione installata",
|
||||
"Maintenance_Status": "Stato",
|
||||
"Maintenance_Title": "Strumenti di manutenzione",
|
||||
"Maintenance_Tool_DownloadConfig": "Impostazioni Esporta",
|
||||
"Maintenance_Tool_DownloadConfig": "Esportazione delle impostazioni",
|
||||
"Maintenance_Tool_DownloadConfig_text": "Scarica un backup completo della configurazione delle tue Impostazioni memorizzata nel file <code>app.conf</code>.",
|
||||
"Maintenance_Tool_DownloadWorkflows": "Esportazione flussi di lavoro",
|
||||
"Maintenance_Tool_DownloadWorkflows": "Esportazione del flusso di lavoro",
|
||||
"Maintenance_Tool_DownloadWorkflows_text": "Scarica un backup completo dei tuoi flussi di lavoro archiviati nel file <code>workflows.json</code>.",
|
||||
"Maintenance_Tool_ExportCSV": "Esporta dispositivi (csv)",
|
||||
"Maintenance_Tool_ExportCSV_noti": "Esporta dispositivi (csv)",
|
||||
"Maintenance_Tool_ExportCSV": "Esportazione dispositivi (csv)",
|
||||
"Maintenance_Tool_ExportCSV_noti": "Esportazione dispositivi (csv)",
|
||||
"Maintenance_Tool_ExportCSV_noti_text": "Sei sicuro di voler generare un file CSV?",
|
||||
"Maintenance_Tool_ExportCSV_text": "Genera un file CSV (comma separated value) contenente la lista dei dispositivi incluse le relazioni di rete tra i nodi di rete e i dispositivi connessi. Puoi anche eseguire questa azione accedendo all'URL <code>il_tuo_NetAlertX/php/server/devices.php?action=ExportCSV</code> o abilitando il plugin <a href=\"settings.php#CSVBCKP_header\">Backup CSV</a>.",
|
||||
"Maintenance_Tool_ImportCSV": "Importa dispositivi (csv)",
|
||||
@@ -471,7 +475,7 @@
|
||||
"Maintenance_themeselector_lable": "Seleziona skin",
|
||||
"Maintenance_themeselector_text": "Questa modifica avviene lato server, quindi influenza tutti i dispositivi in uso.",
|
||||
"Maintenance_version": "Aggiornamenti app",
|
||||
"NETWORK_DEVICE_TYPES_description": "Quali tipi di dispositivo possono essere utilizzati come dispositivi di rete nella vista Rete. Il tipo di dispositivo deve corrispondere esattamente all'impostazione <code>Tipo</code> su un dispositivo specifico nei Dettagli dispositivo. Aggiungilo sul Dispositivo tramite il pulsante <code>+</code>. Non rimuovere i tipi esistenti, aggiungine solo di nuovi.",
|
||||
"NETWORK_DEVICE_TYPES_description": "Quali tipi di dispositivo possono essere utilizzati come dispositivi di rete nella vista Rete. Il tipo di dispositivo deve corrispondere esattamente all'impostazione <code>Tipo</code> su un dispositivo specifico nei Dettagli dispositivo. Aggiungilo al dispositivo tramite il pulsante <code>+</code>. Non rimuovere i tipi esistenti, aggiungine solo di nuovi.",
|
||||
"NETWORK_DEVICE_TYPES_name": "Tipi di dispositivi di rete",
|
||||
"Navigation_About": "Informazioni su",
|
||||
"Navigation_AppEvents": "Eventi app",
|
||||
@@ -494,7 +498,7 @@
|
||||
"Network_Cant_Assign_No_Node_Selected": "Impossibile assegnare, nessun nodo padre selezionato.",
|
||||
"Network_Configuration_Error": "Errore di configurazione",
|
||||
"Network_Connected": "Dispositivi connessi",
|
||||
"Network_Devices": "",
|
||||
"Network_Devices": "Dispositivi di rete",
|
||||
"Network_ManageAdd": "Aggiungi dispositivo",
|
||||
"Network_ManageAdd_Name": "Nome dispositivo",
|
||||
"Network_ManageAdd_Name_text": "Nome senza caratteri speciali",
|
||||
@@ -563,10 +567,10 @@
|
||||
"Presence_Key_OnlineNow_desc": "Dispositivo rilevato durante l'ultima scansione come online.",
|
||||
"Presence_Key_OnlinePast": "Online in passato",
|
||||
"Presence_Key_OnlinePastMiss": "Online in passato (non corrispondente)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "Dispositivo online in passato, ma attualmente offline, ma la sessione di avvio potrebbe essere mancante o presentare dati in conflitto. (potrebbe trattarsi di un bug: invia una PR se sai come risolverlo, sono un po' perso nel codice qui)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "Dispositivo online in passato, ma attualmente offline, ma la sessione di avvio potrebbe essere mancante o presentare dati in conflitto.",
|
||||
"Presence_Key_OnlinePast_desc": "Dispositivo online in passato, ma attualmente offline.",
|
||||
"Presence_Loading": "Caricamento…",
|
||||
"Presence_Shortcut_AllDevices": "Miei dispositivi",
|
||||
"Presence_Shortcut_AllDevices": "I miei dispositivi",
|
||||
"Presence_Shortcut_Archived": "Archiviati",
|
||||
"Presence_Shortcut_Connected": "Connessi",
|
||||
"Presence_Shortcut_Devices": "Dispositivi",
|
||||
@@ -592,8 +596,9 @@
|
||||
"Settings_Metadata_Toggle": "Mostra/nascondi i metadati per l'impostazione specificata.",
|
||||
"Settings_Show_Description": "Mostra descrizione dell'impostazione.",
|
||||
"Settings_device_Scanners_desync": "⚠ Le pianificazioni dello scanner del dispositivo non sono sincronizzate.",
|
||||
"Settings_device_Scanners_desync_popup": "Gli orari degli scanner dei dispositivi (<code>*_RUN_SCHD</code>) non sono gli stessi. Questo comporterà notifiche online/offline incoerenti del dispositivo. A meno che ciò non sia previsto, utilizza la stessa pianificazione per tutti gli <b>🔍Scanner dispositivi</b> abilitati.",
|
||||
"Settings_device_Scanners_desync_popup": "Gli orari degli scanner dei dispositivi (<code>*_RUN_SCHD</code>) non sono gli stessi. Questo comporterà notifiche online/offline incoerenti del dispositivo. A meno che ciò non sia previsto, utilizza la stessa pianificazione per tutti gli <b>🔍 scanner dispositivi</b> abilitati.",
|
||||
"Speedtest_Results": "Risultati test di velocità",
|
||||
"Systeminfo_AvailableIps": "IP disponibili",
|
||||
"Systeminfo_CPU": "CPU",
|
||||
"Systeminfo_CPU_Cores": "Core CPU:",
|
||||
"Systeminfo_CPU_Name": "Nome CPU:",
|
||||
@@ -677,8 +682,8 @@
|
||||
"UI_ICONS_name": "Icone predefinite",
|
||||
"UI_LANG_description": "Seleziona la lingua preferita dell'interfaccia utente. Aiuta nella traduzione o suggerisci una nuova lingua sul portale online di <a href=\"https://hosted.weblate.org/projects/pialert/core/\" target=\"_blank\">Weblate</a>.",
|
||||
"UI_LANG_name": "Lingua UI",
|
||||
"UI_MY_DEVICES_description": "Dispositivi i cui stati devono essere visualizzati nella visualizzazione predefinita <b>Miei dispositivi</b>.",
|
||||
"UI_MY_DEVICES_name": "Mostra nella vista Miei dispositivi",
|
||||
"UI_MY_DEVICES_description": "Dispositivi i cui stati devono essere visualizzati nella visualizzazione predefinita <b>I miei dispositivi</b>.",
|
||||
"UI_MY_DEVICES_name": "Mostra nella vista I miei dispositivi",
|
||||
"UI_NOT_RANDOM_MAC_description": "Prefissi MAC che non devono essere contrassegnati come dispositivi casuali. Inserisci ad esempio <code>52</code> per escludere i dispositivi che iniziano con <code>52:xx:xx:xx:xx:xx</code> dall'essere contrassegnati come dispositivi con un indirizzo MAC casuale.",
|
||||
"UI_NOT_RANDOM_MAC_name": "Non segnalare come casuale",
|
||||
"UI_PRESENCE_description": "Seleziona quali stati devono essere mostrati nel grafico <b>Presenza dispositivo</b> nella pagina <a href=\"/devices.php\" target=\"_blank\">Dispositivi</a>.",
|
||||
@@ -732,7 +737,7 @@
|
||||
"settings_core_label": "Core",
|
||||
"settings_device_scanners": "Scanner dei dispositivi utilizzati per rilevare i dispositivi che scrivono nella tabella del database CurrentScan.",
|
||||
"settings_device_scanners_icon": "fa-solid fa-magnifying-glass-plus",
|
||||
"settings_device_scanners_info": "Carica ancora più scanner di dispositivi con l'impostazione <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_device_scanners_info": "Carica più scanner di dispositivi con l'impostazione <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_device_scanners_label": "Scanner dispositivi",
|
||||
"settings_enabled": "Impostazioni abilitate",
|
||||
"settings_enabled_icon": "fa-solid fa-toggle-on",
|
||||
|
||||
7
front/php/templates/language/nb_no.json
Normal file → Executable file
7
front/php/templates/language/nb_no.json
Normal file → Executable file
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Avbryt",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Kjør",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - Det kan ta litt tid før brukergrensesnittet oppdateres hvis en skanning kjøres.",
|
||||
"Gen_Delete": "Slett",
|
||||
"Gen_DeleteAll": "Slett alle",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Feil",
|
||||
"Gen_Filter": "Filter",
|
||||
"Gen_Generate": "",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "FEIL - DB kan være låst - Sjekk F12 Dev tools -> Konsoll eller prøv senere.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "Frakoblet",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "Valgte Enheter:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "Bytt",
|
||||
"Gen_Upd": "Oppdatering vellykket",
|
||||
"Gen_Upd_Fail": "Oppdatering feilet",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ Enhetsskanning tidsplan er ikke synkronisert lenger.",
|
||||
"Settings_device_Scanners_desync_popup": "Tidsplanene for enhetsskanning (<code>*_RUN_SCHD</code>) er ikke de samme. Dette vil føre til inkonsekvent enhet på online/offline varsler. Med mindre dette er ment, kan du bruke den samme tidsplanen for alle aktiverte <b> 🔍Enhets-skannere</b>.",
|
||||
"Speedtest_Results": "Speedtest resultater",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "CPU",
|
||||
"Systeminfo_CPU_Cores": "CPU-kjerner:",
|
||||
"Systeminfo_CPU_Name": "CPU-navn:",
|
||||
@@ -755,4 +760,4 @@
|
||||
"settings_system_label": "System",
|
||||
"settings_update_item_warning": "Oppdater verdien nedenfor. Pass på å følge forrige format. <b>Validering etterpå utføres ikke.</b>",
|
||||
"test_event_tooltip": "Lagre endringene først, før du tester innstillingene dine."
|
||||
}
|
||||
}
|
||||
7
front/php/templates/language/pl_pl.json
Normal file → Executable file
7
front/php/templates/language/pl_pl.json
Normal file → Executable file
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Anuluj",
|
||||
"Gen_Change": "Zmiana",
|
||||
"Gen_Copy": "Wykonaj",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "OK – Może to potrwać chwilę, zanim interfejs użytkownika się zaktualizuje, jeśli trwa skan.",
|
||||
"Gen_Delete": "Usuń",
|
||||
"Gen_DeleteAll": "Usuń wszystko",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Błąd",
|
||||
"Gen_Filter": "Filtr",
|
||||
"Gen_Generate": "Wygeneruj",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "Błąd - Baza danych może być zablokowana - Sprawdź narzędzia deweloperskie F12 -> Konsola lub spróbuj później.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "Niedostępne",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Dostępne",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Wybierz, aby podglądnąć",
|
||||
"Gen_Selected_Devices": "Wybrane urządzenia:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "Switch",
|
||||
"Gen_Upd": "Zaktualizowano pomyślnie",
|
||||
"Gen_Upd_Fail": "Aktualizacja nie powiodła się",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ Harmonogramy skanerów urządzeń są niezsynchronizowane.",
|
||||
"Settings_device_Scanners_desync_popup": "Harmonogramy skanerów urządzeń (<code>*_RUN_SCHD</code>) są różne. Może to prowadzić do niespójnych powiadomień o statusie online/offline urządzeń. Jeśli nie jest to zamierzone, proszę używać tego samego harmonogramu dla wszystkich włączonych <b>🔍 Skanerów urządzeń</b>.",
|
||||
"Speedtest_Results": "Wyniki testu prędkości",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "Procesor CPU",
|
||||
"Systeminfo_CPU_Cores": "Rdzenie CPU:",
|
||||
"Systeminfo_CPU_Name": "Nazwa procesora CPU:",
|
||||
@@ -755,4 +760,4 @@
|
||||
"settings_system_label": "System",
|
||||
"settings_update_item_warning": "Zaktualizuj wartość poniżej. Uważaj, aby zachować poprzedni format. <b>Walidacja nie jest wykonywana.</b>",
|
||||
"test_event_tooltip": "Najpierw zapisz swoje zmiany, zanim przetestujesz ustawienia."
|
||||
}
|
||||
}
|
||||
7
front/php/templates/language/pt_br.json
Normal file → Executable file
7
front/php/templates/language/pt_br.json
Normal file → Executable file
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Cancelar",
|
||||
"Gen_Change": "Alterar",
|
||||
"Gen_Copy": "Executar",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - Pode levar um tempo para a interface do usuário ser atualizada se uma verificação estiver em execução.",
|
||||
"Gen_Delete": "Excluir",
|
||||
"Gen_DeleteAll": "Excluir todos",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Erro",
|
||||
"Gen_Filter": "Filtro",
|
||||
"Gen_Generate": "Gerar",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "ERRO - O banco de dados pode estar bloqueado - Verifique F12 Ferramentas de desenvolvimento -> Console ou tente mais tarde.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Selecionar para pré-visualizar",
|
||||
"Gen_Selected_Devices": "Dispositivos selecionados:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "Trocar",
|
||||
"Gen_Upd": "Atualizado com sucesso",
|
||||
"Gen_Upd_Fail": "A atualização falhou",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "",
|
||||
"Settings_device_Scanners_desync_popup": "",
|
||||
"Speedtest_Results": "",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "",
|
||||
"Systeminfo_CPU_Cores": "",
|
||||
"Systeminfo_CPU_Name": "",
|
||||
@@ -755,4 +760,4 @@
|
||||
"settings_system_label": "",
|
||||
"settings_update_item_warning": "",
|
||||
"test_event_tooltip": "Guarde as alterações antes de testar as definições."
|
||||
}
|
||||
}
|
||||
33
front/php/templates/language/ru_ru.json
Normal file → Executable file
33
front/php/templates/language/ru_ru.json
Normal file → Executable file
@@ -9,7 +9,7 @@
|
||||
"About_Exit": "Зарегистрироваться",
|
||||
"About_Title": "Сетевой сканер и система уведомлений",
|
||||
"AppEvents_AppEventProcessed": "Обработанный",
|
||||
"AppEvents_DateTimeCreated": "Обнаружено",
|
||||
"AppEvents_DateTimeCreated": "Зарегистрировано",
|
||||
"AppEvents_Extra": "Дополнительно",
|
||||
"AppEvents_GUID": "GUID события приложения",
|
||||
"AppEvents_Helper1": "Помощник 1",
|
||||
@@ -66,7 +66,7 @@
|
||||
"DAYS_TO_KEEP_EVENTS_name": "Удалить события старше",
|
||||
"DISCOVER_PLUGINS_description": "Отключите эту опцию, чтобы ускорить инициализацию и сохранение настроек. При отключении этой опции плагины не обнаруживаются, и вы не можете добавлять новые плагины в параметр <code>LOADED_PLUGINS</code>.",
|
||||
"DISCOVER_PLUGINS_name": "Обзор плагинов",
|
||||
"DevDetail_Children_Title": "",
|
||||
"DevDetail_Children_Title": "Дочерние отношения",
|
||||
"DevDetail_Copy_Device_Title": "Скопировать данные с устройства",
|
||||
"DevDetail_Copy_Device_Tooltip": "Скопируйте данные с устройства из раскрывающегося списка. Все на этой странице будет перезаписано",
|
||||
"DevDetail_CustomProperties_Title": "Пользовательские свойства",
|
||||
@@ -79,7 +79,7 @@
|
||||
"DevDetail_EveandAl_NewDevice_Tooltip": "Будет показывать статус «Новое» для устройства и включать его в списки, когда фильтр «Новые устройства» активен. Не влияет на уведомления.",
|
||||
"DevDetail_EveandAl_RandomMAC": "Случайный MAC-адрес",
|
||||
"DevDetail_EveandAl_ScanCycle": "Сканировать устройство",
|
||||
"DevDetail_EveandAl_ScanCycle_a": "Сканировать Устройство",
|
||||
"DevDetail_EveandAl_ScanCycle_a": "Сканировать устройство",
|
||||
"DevDetail_EveandAl_ScanCycle_z": "Не сканировать устройство",
|
||||
"DevDetail_EveandAl_Skip": "Пропустить повторные уведомления",
|
||||
"DevDetail_EveandAl_Title": "Конфигурация событий и оповещений",
|
||||
@@ -103,7 +103,7 @@
|
||||
"DevDetail_MainInfo_Type": "Тип",
|
||||
"DevDetail_MainInfo_Vendor": "Поставщик",
|
||||
"DevDetail_MainInfo_mac": "MAC адрес",
|
||||
"DevDetail_NavToChildNode": "",
|
||||
"DevDetail_NavToChildNode": "Открыть дочерний узел",
|
||||
"DevDetail_Network_Node_hover": "Выберите родительское сетевое устройство, к которому подключено текущее устройство, чтобы заполнить дерево сети.",
|
||||
"DevDetail_Network_Port_hover": "Порт, к которому подключено это устройство на родительском сетевом устройстве. Если оставить пустым, в дереве сети отобразится значок Wi-Fi.",
|
||||
"DevDetail_Nmap_Scans": "Ручные сканеры Nmap",
|
||||
@@ -202,7 +202,7 @@
|
||||
"Device_MultiEdit_Tooltip": "Осторожно. При нажатии на эту кнопку значение слева будет применено ко всем устройствам, выбранным выше.",
|
||||
"Device_Searchbox": "Поиск",
|
||||
"Device_Shortcut_AllDevices": "Мои устройства",
|
||||
"Device_Shortcut_AllNodes": "",
|
||||
"Device_Shortcut_AllNodes": "Все узлы",
|
||||
"Device_Shortcut_Archived": "Архив",
|
||||
"Device_Shortcut_Connected": "Подключенные",
|
||||
"Device_Shortcut_Devices": "Устройства",
|
||||
@@ -229,11 +229,11 @@
|
||||
"Device_TableHead_Name": "Имя",
|
||||
"Device_TableHead_NetworkSite": "Сайт устройства",
|
||||
"Device_TableHead_Owner": "Владелец",
|
||||
"Device_TableHead_ParentRelType": "",
|
||||
"Device_TableHead_ParentRelType": "Тип отношений",
|
||||
"Device_TableHead_Parent_MAC": "Родительский узел сети",
|
||||
"Device_TableHead_Port": "Порт",
|
||||
"Device_TableHead_PresentLastScan": "Присутствие",
|
||||
"Device_TableHead_ReqNicsOnline": "",
|
||||
"Device_TableHead_ReqNicsOnline": "Требуется NIC онлайн",
|
||||
"Device_TableHead_RowID": "ID строки",
|
||||
"Device_TableHead_Rowid": "ID строки",
|
||||
"Device_TableHead_SSID": "SSID",
|
||||
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Отмена",
|
||||
"Gen_Change": "Изменить",
|
||||
"Gen_Copy": "Запустить",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "ОК - Обновление UI может занять некоторое время, если сканирование выполняется.",
|
||||
"Gen_Delete": "Удалить",
|
||||
"Gen_DeleteAll": "Удалить все",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Ошибка",
|
||||
"Gen_Filter": "Фильтр",
|
||||
"Gen_Generate": "Генерировать",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "ОШИБКА - Возможно, база данных заблокирована. Проверьте инструменты разработчика F12 -> Консоль или повторите попытку позже.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "Оффлайн",
|
||||
"Gen_Okay": "OK",
|
||||
"Gen_Online": "Онлайн",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Выберите для предварительного просмотра",
|
||||
"Gen_Selected_Devices": "Выбранные устройства:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "Переключить",
|
||||
"Gen_Upd": "Успешное обновление",
|
||||
"Gen_Upd_Fail": "Не удалось обновить",
|
||||
@@ -491,10 +495,10 @@
|
||||
"Navigation_Workflows": "Рабочие процессы",
|
||||
"Network_Assign": "Подключитесь к указанному выше сетевому узлу <i class=\"fa fa-server\"></i>",
|
||||
"Network_Cant_Assign": "Невозможно назначить корневой узел Интернета в качестве дочернего конечного узла.",
|
||||
"Network_Cant_Assign_No_Node_Selected": "",
|
||||
"Network_Cant_Assign_No_Node_Selected": "Невозможно назначить, не выбран узел-родитель.",
|
||||
"Network_Configuration_Error": "Ошибка конфигурации",
|
||||
"Network_Connected": "Подключенные устройства",
|
||||
"Network_Devices": "",
|
||||
"Network_Devices": "Сетевые устройства",
|
||||
"Network_ManageAdd": "Добавить устройство",
|
||||
"Network_ManageAdd_Name": "Имя устройства",
|
||||
"Network_ManageAdd_Name_text": "Имя без специальных символов",
|
||||
@@ -529,8 +533,8 @@
|
||||
"Network_Root": "Корневой узел",
|
||||
"Network_Root_Not_Configured": "Выберите тип сетевого устройства, например <b>Шлюз</b>, в поле <b>Тип</b> <a href=\"deviceDetails.php?mac=Internet\">корневого Интернет-устройства</a>, чтобы начать настройку этого экрана. <br/><br/> Дополнительную документацию можно найти в руководстве <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md\" target=\"_blank \">Как настроить свою сетевую страницу</a>",
|
||||
"Network_Root_Unconfigurable": "Ненастраиваемый ROOT",
|
||||
"Network_ShowArchived": "",
|
||||
"Network_ShowOffline": "",
|
||||
"Network_ShowArchived": "Показать архивные",
|
||||
"Network_ShowOffline": "Показать офлайн устройства",
|
||||
"Network_Table_Hostname": "Имя хоста",
|
||||
"Network_Table_IP": "IP",
|
||||
"Network_Table_State": "Состояние",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ Расписания сканера устройств не синхронизированы.",
|
||||
"Settings_device_Scanners_desync_popup": "Расписания сканеров устройств (<code>*_RUN_SCHD</code>) не совпадают. Это приведет к несогласованным онлайн/оффлайн уведомлениям устройства. Если это не предусмотрено, используйте одно и то же расписание для всех включенных <b>🔍Сканеров устройств</b>.",
|
||||
"Speedtest_Results": "Результаты теста скорости",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "CPU",
|
||||
"Systeminfo_CPU_Cores": "Ядра CPU:",
|
||||
"Systeminfo_CPU_Name": "Имя CPU:",
|
||||
@@ -719,7 +724,7 @@
|
||||
"devices_old": "Актуализируется…",
|
||||
"general_event_description": "Событие, которое вы инициировали, может занять некоторое время, прежде чем фоновые процессы завершатся. Выполнение завершится, как только очередь выполнения, указанная ниже, опустеет (Проверьте <a href='/maintenance.php#tab_Logging'>журнал ошибок</a> при возникновении проблем). <br/> <br/>· · Очередь выполнения:",
|
||||
"general_event_title": "Выполнение специального события",
|
||||
"go_to_device_event_tooltip": "",
|
||||
"go_to_device_event_tooltip": "Перейти к устройству",
|
||||
"go_to_node_event_tooltip": "Переход на страницу \"Сеть\" данного узла",
|
||||
"new_version_available": "Доступна новая версия.",
|
||||
"report_guid": "Идентификатор уведомления:",
|
||||
@@ -727,7 +732,7 @@
|
||||
"report_select_format": "Выбрать формат:",
|
||||
"report_time": "Время уведомления:",
|
||||
"run_event_tooltip": "Включите настройку и сначала сохраните изменения, прежде чем запускать ее.",
|
||||
"select_icon_event_tooltip": "",
|
||||
"select_icon_event_tooltip": "Выбрать значок",
|
||||
"settings_core_icon": "fa-solid fa-gem",
|
||||
"settings_core_label": "Основные",
|
||||
"settings_device_scanners": "Сканеры устройств, используемые для обнаружения устройств, записывающих данные в таблицу базы данных CurrentScan.",
|
||||
@@ -755,4 +760,4 @@
|
||||
"settings_system_label": "Система",
|
||||
"settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>",
|
||||
"test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки."
|
||||
}
|
||||
}
|
||||
7
front/php/templates/language/tr_tr.json
Normal file → Executable file
7
front/php/templates/language/tr_tr.json
Normal file → Executable file
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "İptal",
|
||||
"Gen_Change": "Değiştir",
|
||||
"Gen_Copy": "Çalıştır",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "TAMAM - Eğer bir tarama çalışıyorsa arayüzün güncellenmesi biraz zaman alabilir.",
|
||||
"Gen_Delete": "Sil",
|
||||
"Gen_DeleteAll": "Tümünü sil",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Hata",
|
||||
"Gen_Filter": "Filtre",
|
||||
"Gen_Generate": "Oluştur",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "HATA - Veritabanı kilitlenmiş olabilir - F12 Geliştirici araçlarını -> Konsol kısmını kontrol edin veya daha sonra tekrar deneyin.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "Çevrimdışı",
|
||||
"Gen_Okay": "Tamam",
|
||||
"Gen_Online": "Çevrimiçi",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Önizleme yapmak için seçin",
|
||||
"Gen_Selected_Devices": "Seçilmiş Cihazlar:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "Switch",
|
||||
"Gen_Upd": "Başarılı bir şekilde güncellendi",
|
||||
"Gen_Upd_Fail": "Güncelleme işlemi başarısız oldu",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "",
|
||||
"Settings_device_Scanners_desync_popup": "",
|
||||
"Speedtest_Results": "",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "",
|
||||
"Systeminfo_CPU_Cores": "",
|
||||
"Systeminfo_CPU_Name": "",
|
||||
@@ -755,4 +760,4 @@
|
||||
"settings_system_label": "Sistem",
|
||||
"settings_update_item_warning": "",
|
||||
"test_event_tooltip": ""
|
||||
}
|
||||
}
|
||||
23
front/php/templates/language/uk_ua.json
Normal file → Executable file
23
front/php/templates/language/uk_ua.json
Normal file → Executable file
@@ -73,7 +73,7 @@
|
||||
"DevDetail_CustomProps_reset_info": "Це призведе до видалення настроюваних властивостей на цьому пристрої та скидання їх до значень за замовчуванням.",
|
||||
"DevDetail_DisplayFields_Title": "Дисплей",
|
||||
"DevDetail_EveandAl_AlertAllEvents": "Повідомлення про події",
|
||||
"DevDetail_EveandAl_AlertDown": "Сповіщення вниз",
|
||||
"DevDetail_EveandAl_AlertDown": "Агент вниз",
|
||||
"DevDetail_EveandAl_Archived": "Архівовано",
|
||||
"DevDetail_EveandAl_NewDevice": "Новий пристроїв",
|
||||
"DevDetail_EveandAl_NewDevice_Tooltip": "Відображатиме новий статус для пристрою та включатиме його до списків, коли фільтр нових пристроїв активний. Не впливає на сповіщення.",
|
||||
@@ -185,7 +185,7 @@
|
||||
"DevDetail_button_AddIcon": "Додати новий значок",
|
||||
"DevDetail_button_AddIcon_Help": "Вставте HTML-тег SVG або значок HTML-тегу Font Awesome. Щоб дізнатися більше, прочитайте <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/ICONS.md\" target=\"_blank\">документацію щодо значків</a>.",
|
||||
"DevDetail_button_AddIcon_Tooltip": "Додайте нову піктограму до цього пристрою, яка ще не доступна в спадному меню.",
|
||||
"DevDetail_button_Delete": "Видалити пристрій",
|
||||
"DevDetail_button_Delete": "Видалити Пристрій",
|
||||
"DevDetail_button_DeleteEvents": "Видалити події",
|
||||
"DevDetail_button_DeleteEvents_Warning": "Ви впевнені, що бажаєте видалити всі події цього пристрою?<br><br>(це очистить <b>історію подій</b> і <b>сеанси</b> та може допомогти з постійними (постійними) ) сповіщення)",
|
||||
"DevDetail_button_Delete_ask": "Ви впевнені, що хочете видалити цей пристрій? Натомість ви також можете заархівувати його.",
|
||||
@@ -211,7 +211,7 @@
|
||||
"Device_Shortcut_Favorites": "Вибране",
|
||||
"Device_Shortcut_NewDevices": "Нові пристрої",
|
||||
"Device_Shortcut_OnlineChart": "Наявність пристрою",
|
||||
"Device_TableHead_AlertDown": "Сповіщення вниз",
|
||||
"Device_TableHead_AlertDown": "Агент Вниз",
|
||||
"Device_TableHead_Connected_Devices": "Зв'язки",
|
||||
"Device_TableHead_CustomProps": "Реквізит / дії",
|
||||
"Device_TableHead_FQDN": "FQDN",
|
||||
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "Скасувати",
|
||||
"Gen_Change": "Зміна",
|
||||
"Gen_Copy": "Запустити",
|
||||
"Gen_CopyToClipboard": "Копіювати в буфер обміну",
|
||||
"Gen_DataUpdatedUITakesTime": "Добре. Оновлення інтерфейсу може зайняти деякий час, якщо сканування виконується.",
|
||||
"Gen_Delete": "Видалити",
|
||||
"Gen_DeleteAll": "Видалити все",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "Помилка",
|
||||
"Gen_Filter": "Фільтр",
|
||||
"Gen_Generate": "Генерувати",
|
||||
"Gen_InvalidMac": "Недійсна Mac-адреса.",
|
||||
"Gen_LockedDB": "ПОМИЛКА – БД може бути заблоковано – перевірте F12 Інструменти розробника -> Консоль або спробуйте пізніше.",
|
||||
"Gen_NetworkMask": "Маска мережі",
|
||||
"Gen_Offline": "Офлайн",
|
||||
"Gen_Okay": "Гаразд",
|
||||
"Gen_Online": "Онлайн",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "Виберіть для попереднього перегляду",
|
||||
"Gen_Selected_Devices": "Вибрані пристрої:",
|
||||
"Gen_Subnet": "Підмережа",
|
||||
"Gen_Switch": "Перемикач",
|
||||
"Gen_Upd": "Оновлено успішно",
|
||||
"Gen_Upd_Fail": "Не вдалося оновити",
|
||||
@@ -494,7 +498,7 @@
|
||||
"Network_Cant_Assign_No_Node_Selected": "Неможливо призначити, не вибрано батьківський вузол.",
|
||||
"Network_Configuration_Error": "Помилка конфігурації",
|
||||
"Network_Connected": "Підключені пристрої",
|
||||
"Network_Devices": "",
|
||||
"Network_Devices": "Мережеві пристрої",
|
||||
"Network_ManageAdd": "Додати пристрій",
|
||||
"Network_ManageAdd_Name": "Назва пристрою",
|
||||
"Network_ManageAdd_Name_text": "Назва без спеціальних символів",
|
||||
@@ -502,7 +506,7 @@
|
||||
"Network_ManageAdd_Port_text": "залиште порожнім для wifi та powerline",
|
||||
"Network_ManageAdd_Submit": "Додати пристрій",
|
||||
"Network_ManageAdd_Type": "Тип пристрою",
|
||||
"Network_ManageAdd_Type_text": "-- Виберіть тип --",
|
||||
"Network_ManageAdd_Type_text": "-- Виберіть Тип --",
|
||||
"Network_ManageAssign": "Призначити",
|
||||
"Network_ManageDel": "Видалити пристрій",
|
||||
"Network_ManageDel_Name": "Пристрій для видалення",
|
||||
@@ -537,7 +541,7 @@
|
||||
"Network_Title": "Огляд мережі",
|
||||
"Network_UnassignedDevices": "Непризначені пристрої",
|
||||
"Notifications_All": "Усі сповіщення",
|
||||
"Notifications_Mark_All_Read": "Позначити все як прочитане",
|
||||
"Notifications_Mark_All_Read": "Позначити як прочитане",
|
||||
"PIALERT_WEB_PASSWORD_description": "Пароль за умовчанням — <code>123456</code>. Щоб змінити пароль, запустіть <code>/app/back/pialert-cli</code> у контейнері або скористайтеся <a onclick=\"toggleAllSettings()\" href=\"#SETPWD_RUN\"><code>SETPWD_RUN</code> Плагін встановлення пароля</a>.",
|
||||
"PIALERT_WEB_PASSWORD_name": "Пароль для входу",
|
||||
"PIALERT_WEB_PROTECTION_description": "Якщо ввімкнено, відображається діалогове вікно входу. Уважно прочитайте нижче, якщо вас заблокують у вашому екземплярі.",
|
||||
@@ -563,7 +567,7 @@
|
||||
"Presence_Key_OnlineNow_desc": "Під час останнього сканування пристрій виявлено як онлайн.",
|
||||
"Presence_Key_OnlinePast": "Минулий онлайн",
|
||||
"Presence_Key_OnlinePastMiss": "Минулий онлайн (пропущений матч)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "Пристрій був онлайн, але зараз офлайн, але початковий сеанс може бути відсутнім або містить суперечливі дані. (може бути помилка - будь ласка, надішліть PR, якщо ви знаєте, як це виправити - я трохи загубився в коді тут)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "Пристрій був онлайн у минулому, але зараз офлайн, але початковий сеанс може бути відсутнім або містити суперечливі дані.",
|
||||
"Presence_Key_OnlinePast_desc": "Пристрій був онлайн, але зараз офлайн.",
|
||||
"Presence_Loading": "Завантаження…",
|
||||
"Presence_Shortcut_AllDevices": "Мої пристрої",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ Розклади сканування пристрою не синхронізовані.",
|
||||
"Settings_device_Scanners_desync_popup": "Розклади сканерів пристроїв (<code>*_RUN_SCHD</code>) не однакові. Це призведе до непослідовних сповіщень пристрою онлайн/офлайн. Якщо це не передбачено, використовуйте той самий розклад для всіх увімкнених <b>🔍сканерів пристроїв</b>.",
|
||||
"Speedtest_Results": "Результати Speedtest",
|
||||
"Systeminfo_AvailableIps": "Доступні IP-адреси",
|
||||
"Systeminfo_CPU": "CPU",
|
||||
"Systeminfo_CPU_Cores": "Ядра ЦП:",
|
||||
"Systeminfo_CPU_Name": "Назва ЦП:",
|
||||
@@ -626,7 +631,7 @@
|
||||
"Systeminfo_Network_HTTP_Referer": "HTTP реферер:",
|
||||
"Systeminfo_Network_HTTP_Referer_String": "Немає реферера HTTP",
|
||||
"Systeminfo_Network_Hardware": "Мережеве обладнання",
|
||||
"Systeminfo_Network_Hardware_Interface_Mask": "Маска мережі",
|
||||
"Systeminfo_Network_Hardware_Interface_Mask": "Маска Мережі",
|
||||
"Systeminfo_Network_Hardware_Interface_Name": "Назва інтерфейсу",
|
||||
"Systeminfo_Network_Hardware_Interface_RX": "Отримано",
|
||||
"Systeminfo_Network_Hardware_Interface_TX": "Передано",
|
||||
@@ -732,7 +737,7 @@
|
||||
"settings_core_label": "Ядро",
|
||||
"settings_device_scanners": "Сканери пристроїв, які використовуються для виявлення пристроїв, які записують дані в таблицю бази даних CurrentScan.",
|
||||
"settings_device_scanners_icon": "fa-solid fa-збільшувальне-скло-плюс",
|
||||
"settings_device_scanners_info": "Завантажте ще більше сканерів пристроїв за допомогою параметра <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_device_scanners_info": "Завантажте більше сканерів пристроїв за допомогою налаштування <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_device_scanners_label": "Сканери пристроїв",
|
||||
"settings_enabled": "Увімкнені налаштування",
|
||||
"settings_enabled_icon": "fa-твердий fa-перемикач",
|
||||
|
||||
9
front/php/templates/language/zh_cn.json
Normal file → Executable file
9
front/php/templates/language/zh_cn.json
Normal file → Executable file
@@ -301,6 +301,7 @@
|
||||
"Gen_Cancel": "取消",
|
||||
"Gen_Change": "修改",
|
||||
"Gen_Copy": "运行",
|
||||
"Gen_CopyToClipboard": "",
|
||||
"Gen_DataUpdatedUITakesTime": "好的 - 如果扫描正在运行,UI 可能需要一段时间才能更新。",
|
||||
"Gen_Delete": "删除",
|
||||
"Gen_DeleteAll": "全部删除",
|
||||
@@ -308,7 +309,9 @@
|
||||
"Gen_Error": "错误",
|
||||
"Gen_Filter": "筛选",
|
||||
"Gen_Generate": "生成",
|
||||
"Gen_InvalidMac": "",
|
||||
"Gen_LockedDB": "错误 - DB 可能被锁定 - 检查 F12 开发工具 -> 控制台或稍后重试。",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_Offline": "离线",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "在线",
|
||||
@@ -326,6 +329,7 @@
|
||||
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
|
||||
"Gen_SelectToPreview": "选择预览",
|
||||
"Gen_Selected_Devices": "选定的设备:",
|
||||
"Gen_Subnet": "",
|
||||
"Gen_Switch": "交换",
|
||||
"Gen_Upd": "已成功更新",
|
||||
"Gen_Upd_Fail": "更新失败",
|
||||
@@ -563,7 +567,7 @@
|
||||
"Presence_Key_OnlineNow_desc": "该设备在上次扫描中被检测为在线。",
|
||||
"Presence_Key_OnlinePast": "之前在线",
|
||||
"Presence_Key_OnlinePastMiss": "之前在线(不匹配)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "设备曾在线,但目前离线。初始会话可能缺失或存在数据冲突。(可能是bug - 要是你知道怎么修复,请开个PR - 我不知道怎么处理)",
|
||||
"Presence_Key_OnlinePastMiss_desc": "设备曾在线,但目前离线。初始会话可能缺失或存在数据冲突",
|
||||
"Presence_Key_OnlinePast_desc": "设备曾在线,但目前离线。",
|
||||
"Presence_Loading": "加载中…",
|
||||
"Presence_Shortcut_AllDevices": "我的设备",
|
||||
@@ -594,6 +598,7 @@
|
||||
"Settings_device_Scanners_desync": "⚠ 设备扫描计划不同步。",
|
||||
"Settings_device_Scanners_desync_popup": "设备扫描 (<code>*_RUN_SCHD</code>) 的时间表并不相同。这将导致设备在线/离线通知不一致。除非有意为之,否则请对所有启用的 <b>🔍设备扫描</b> 使用相同的时间表。",
|
||||
"Speedtest_Results": "Speedtest 结果",
|
||||
"Systeminfo_AvailableIps": "",
|
||||
"Systeminfo_CPU": "CPU",
|
||||
"Systeminfo_CPU_Cores": "CPU 核心:",
|
||||
"Systeminfo_CPU_Name": "CPU 名称:",
|
||||
@@ -755,4 +760,4 @@
|
||||
"settings_system_label": "系统",
|
||||
"settings_update_item_warning": "更新下面的值。请注意遵循先前的格式。<b>未执行验证。</b>",
|
||||
"test_event_tooltip": "在测试设置之前,请先保存更改。"
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ def main():
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def check_config():
|
||||
if get_setting_value('APPRISE_URL') == '' or get_setting_value('APPRISE_HOST') == '':
|
||||
if get_setting_value('APPRISE_HOST') == '' or (get_setting_value('APPRISE_URL') == '' and get_setting_value('APPRISE_TAG') == ''):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -106,8 +106,11 @@ def send(html, text):
|
||||
|
||||
# Define Apprise compatible payload (https://github.com/caronc/apprise-api#stateless-solution)
|
||||
|
||||
target_key = "tag" if get_setting_value('APPRISE_TARGETTYPE') == 'tag' else "urls"
|
||||
target_value = get_setting_value('APPRISE_TAG') if target_key == 'tag' else get_setting_value('APPRISE_URL')
|
||||
|
||||
_json_payload = {
|
||||
"urls": get_setting_value('APPRISE_URL'),
|
||||
target_key: target_value,
|
||||
"title": "NetAlertX Notifications",
|
||||
"format": get_setting_value('APPRISE_PAYLOAD'),
|
||||
"body": payloadData
|
||||
|
||||
@@ -422,6 +422,38 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "TARGETTYPE",
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{ "elementType": "select", "elementOptions": [], "transformers": [] }
|
||||
]
|
||||
},
|
||||
"default_value": "url",
|
||||
"options": ["url", "tag"],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Target type"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tipo de alvo"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Select the target type to send to Apprise. If <code>url</code> is selected, the value of the <code>APPRISE_URL</code> setting will be used. If <code>tag</code> is selected, the <code>APPRISE_TAG</code> setting must be specified and will be used instead."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Seleccione el tipo de alvo enviada a Apprise."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "URL",
|
||||
"type": {
|
||||
@@ -454,6 +486,38 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "TAG",
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{ "elementType": "input", "elementOptions": [], "transformers": [] }
|
||||
]
|
||||
},
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Apprise notification tag"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tag de notificación de Apprise"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Apprise notification target tag."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Informar de la tag de destino de la notificación."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "PAYLOAD",
|
||||
"type": {
|
||||
|
||||
@@ -261,36 +261,36 @@ pluginUnprocessedEvents = []
|
||||
pluginObjects = []
|
||||
pluginHistory = []
|
||||
|
||||
function getData(){
|
||||
|
||||
console.log("Plugins getData called");
|
||||
async function getData() {
|
||||
try {
|
||||
showSpinner();
|
||||
console.log("Plugins getData called");
|
||||
|
||||
// Show the loading spinner while generating
|
||||
showSpinner();
|
||||
const [plugins, events, objects, history] = await Promise.all([
|
||||
fetchJson('plugins.json'),
|
||||
fetchJson('table_plugins_events.json'),
|
||||
fetchJson('table_plugins_objects.json'),
|
||||
fetchJson('table_plugins_history.json')
|
||||
]);
|
||||
|
||||
$.get('php/server/query_json.php?file=plugins.json', function(res) {
|
||||
|
||||
pluginDefinitions = res["data"];
|
||||
pluginDefinitions = plugins.data;
|
||||
pluginUnprocessedEvents = events.data;
|
||||
pluginObjects = objects.data;
|
||||
pluginHistory = history.data;
|
||||
|
||||
$.get('php/server/query_json.php?file=table_plugins_events.json', function(res) {
|
||||
|
||||
pluginUnprocessedEvents = res["data"];
|
||||
|
||||
$.get('php/server/query_json.php?file=table_plugins_objects.json', function(res) {
|
||||
|
||||
pluginObjects = res["data"];
|
||||
|
||||
$.get('php/server/query_json.php?file=table_plugins_history.json', function(res) {
|
||||
|
||||
pluginHistory = res["data"];
|
||||
|
||||
generateTabs()
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
generateTabs();
|
||||
} catch (err) {
|
||||
console.error("Failed to load data", err);
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchJson(filename) {
|
||||
const response = await fetch(`php/server/query_json.php?file=${filename}`);
|
||||
if (!response.ok) throw new Error(`Failed to load ${filename}`);
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
|
||||
function generateTabs() {
|
||||
|
||||
// Reset the tabs by clearing previous headers and content
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
// show spinning icon
|
||||
showSpinner()
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Page ------------------------------------------------------------------ -->
|
||||
@@ -28,571 +29,112 @@
|
||||
|
||||
<!-- Main content ---------------------------------------------------------- -->
|
||||
<section class="content">
|
||||
|
||||
<?php
|
||||
//General stats
|
||||
// Date & Time
|
||||
$date = new DateTime();
|
||||
$formatted_date = $date->format('l, F j, Y H:i:s'); // Get date
|
||||
$formatted_date2 = $date->format('d/m/Y H:i:s'); // Get date2
|
||||
$formatted_date3 = $date->format('Y/m/d H:i:s'); // Get date3
|
||||
//System stats
|
||||
// OS-Version
|
||||
$os_version = '';
|
||||
// Raspbian
|
||||
if ($os_version == '') {$os_version = exec('cat /etc/os-release | grep PRETTY_NAME');}
|
||||
// Dietpi
|
||||
if ($os_version == '') {$os_version = exec('uname -o');}
|
||||
//$os_version_arr = explode("\n", trim($os_version));
|
||||
$stat['os_version'] = str_replace('"', '', str_replace('PRETTY_NAME=', '', $os_version));
|
||||
$stat['uptime'] = str_replace('up ', '', shell_exec("uptime -p")); // Get system uptime
|
||||
$system_namekernel = shell_exec("uname"); // Get system name kernel
|
||||
$system_namesystem = shell_exec("uname -o"); // Get name system
|
||||
$system_full = shell_exec("uname -a"); // Get system full
|
||||
$system_architecture = shell_exec("uname -m"); // Get system Architecture
|
||||
$load_average = sys_getloadavg(); // Get load average
|
||||
$system_process_count = shell_exec("ps -e --no-headers | wc -l"); // Count processes
|
||||
//Motherboard stats
|
||||
$motherboard_name = shell_exec('cat /sys/class/dmi/id/board_name'); // Get the Motherboard name
|
||||
$motherboard_manufactured = shell_exec('cat /sys/class/dmi/id/board_vendor'); // Get the Motherboard manufactured
|
||||
$motherboard_revision = shell_exec('cat /sys/class/dmi/id/board_version'); // Get the Motherboard revision
|
||||
$motherboard_bios = shell_exec('cat /sys/class/dmi/id/bios_version'); // Get the Motherboard BIOS
|
||||
$motherboard_biosdate = shell_exec('cat /sys/class/dmi/id/bios_date'); // Get the Motherboard BIOS date
|
||||
$motherboard_biosvendor = shell_exec('cat /sys/class/dmi/id/bios_vendor'); // Get the Motherboard BIOS vendor
|
||||
//CPU stats
|
||||
$prevVal = shell_exec("cat /proc/cpuinfo | grep processor");
|
||||
$prevArr = explode("\n", trim($prevVal));
|
||||
$stat['cpu'] = sizeof($prevArr);
|
||||
$cpu_result = shell_exec("cat /proc/cpuinfo | grep Model");
|
||||
$stat['cpu_model'] = strstr($cpu_result, "\n", true);
|
||||
$stat['cpu_model'] = str_replace(":", "", trim(str_replace("Model", "", $stat['cpu_model'])));
|
||||
if ($stat['cpu_model'] == '') {
|
||||
$cpu_result = shell_exec("cat /proc/cpuinfo | grep model\ name");
|
||||
$stat['cpu_model'] = strstr($cpu_result, "\n", true);
|
||||
$stat['cpu_model'] = str_replace(":", "", trim(str_replace("model name", "", $stat['cpu_model'])));
|
||||
}
|
||||
if (file_exists('/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq')) {
|
||||
// RaspbianOS
|
||||
$stat['cpu_frequ'] = exec('cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq') / 1000;
|
||||
} elseif (is_numeric(str_replace(',', '.', exec('lscpu | grep "MHz" | awk \'{print $3}\'')))) {
|
||||
// Ubuntu Server, DietPi event. others
|
||||
$stat['cpu_frequ'] = round(exec('lscpu | grep "MHz" | awk \'{print $3}\''), 0);
|
||||
} elseif (is_numeric(str_replace(',', '.', exec('lscpu | grep "max MHz" | awk \'{print $4}\'')))) {
|
||||
// RaspbianOS and event. others
|
||||
$stat['cpu_frequ'] = round(str_replace(',', '.', exec('lscpu | grep "max MHz" | awk \'{print $4}\'')), 0);
|
||||
} else {
|
||||
// Fallback
|
||||
$stat['cpu_frequ'] = "unknown";
|
||||
}
|
||||
$cpu_temp = shell_exec('cat /sys/class/hwmon/hwmon0/temp1_input'); // Get the CPU temperature
|
||||
$cpu_temp = floatval($cpu_temp) / 1000; // Convert the temperature to degrees Celsius
|
||||
$cpu_vendor = exec('cat /proc/cpuinfo | grep "vendor_id" | cut -d ":" -f 2' ); // Get the CPU vendor
|
||||
//Memory stats
|
||||
$total_memorykb = shell_exec("cat /proc/meminfo | grep MemTotal | awk '{print $2}'");
|
||||
$total_memorykb = trim($total_memorykb);
|
||||
$total_memorykb = number_format($total_memorykb, 0, '.', '.');
|
||||
$total_memorymb = shell_exec("cat /proc/meminfo | grep MemTotal | awk '{print $2/1024}'");
|
||||
$total_memorymb = trim($total_memorymb);
|
||||
$total_memorymb = number_format($total_memorymb, 0, '.', '.');
|
||||
$mem_used = round(memory_get_usage() / 1048576 * 100, 2);
|
||||
$memory_usage_percent = round(($mem_used / $total_memorymb), 2);
|
||||
//HDD stats
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $1}'");
|
||||
$hdd_devices = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $2}'");
|
||||
$hdd_devices_total = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $3}'");
|
||||
$hdd_devices_used = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $4}'");
|
||||
$hdd_devices_free = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $5}'");
|
||||
$hdd_devices_percent = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $6}'");
|
||||
$hdd_devices_mount = explode("\n", trim($hdd_result));
|
||||
//Network stats
|
||||
// Check Server name
|
||||
if (!empty(gethostname())) { $network_NAME = gethostname(); } else { $network_NAME = lang('Systeminfo_Network_Server_Name_String'); }
|
||||
// Check HTTPS
|
||||
if (isset($_SERVER['HTTPS'])) { $network_HTTPS = 'Yes (HTTPS)'; } else { $network_HTTPS = lang('Systeminfo_Network_Secure_Connection_String'); }
|
||||
// Check Query String
|
||||
if (empty($_SERVER['QUERY_STRING'])) { $network_QueryString = lang('Systeminfo_Network_Server_Query_String'); } else { $network_QueryString = $_SERVER['QUERY_STRING']; }
|
||||
// Check HTTP referer
|
||||
if (empty($_SERVER['HTTP_REFERER'])) { $network_referer = lang('Systeminfo_Network_HTTP_Referer_String'); } else { $network_referer = $_SERVER['HTTP_REFERER']; }
|
||||
//Network Hardware stat
|
||||
$network_result = shell_exec("cat /proc/net/dev | tail -n +3 | awk '{print $1}'");
|
||||
$net_interfaces = explode("\n", trim($network_result));
|
||||
$network_result = shell_exec("cat /proc/net/dev | tail -n +3 | awk '{print $2}'");
|
||||
$net_interfaces_rx = explode("\n", trim($network_result));
|
||||
$network_result = shell_exec("cat /proc/net/dev | tail -n +3 | awk '{print $10}'");
|
||||
$net_interfaces_tx = explode("\n", trim($network_result));
|
||||
//USB devices
|
||||
$usb_result = shell_exec("lsusb");
|
||||
$usb_devices_mount = explode("\n", trim($usb_result));
|
||||
|
||||
// General ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-info-circle"></i> ' . lang('Systeminfo_General') . '</h3>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-sm-12 col-xs-12">
|
||||
<!-- <div class="box-transparent"> -->
|
||||
<div id="navSysInfo" class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs" style="font-size:16px;">
|
||||
<li>
|
||||
<a id="tabServer" href="#panServer" data-toggle="tab">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
<span class="dev-detail-tab-name">
|
||||
<?= lang('Systeminfo_System');?>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="tabNetwork" href="#panNetwork" data-toggle="tab">
|
||||
<i class="fa fa-sitemap fa-rotate-270"></i>
|
||||
<span class="dev-detail-tab-name">
|
||||
<?= lang('Systeminfo_Network');?>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="tabStorage" href="#panStorage" data-toggle="tab">
|
||||
<i class="fa fa-hdd"></i>
|
||||
<span class="dev-detail-tab-name">
|
||||
<?= lang('Systeminfo_Storage');?>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content spinnerTarget" style="min-height: 430px;">
|
||||
<div class="tab-pane fade" data-php-file="systeminfoServer.php" id="panServer">
|
||||
<!-- PLACEHOLDER -->
|
||||
</div>
|
||||
<div class="tab-pane fade" data-php-file="systeminfoNetwork.php" id="panNetwork">
|
||||
<!-- PLACEHOLDER -->
|
||||
</div>
|
||||
<div class="tab-pane fade table-responsive" data-php-file="systeminfoStorage.php" id="panStorage">
|
||||
<!-- PLACEHOLDER -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_general_a">' . lang('Systeminfo_General_Full_Date') . '</div>
|
||||
<div class="col-sm-9 sysinfo_general_b">' . $formatted_date . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_general_a">' . lang('Systeminfo_General_Date') . '</div>
|
||||
<div class="col-sm-9 sysinfo_general_b">' . $formatted_date2 . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_general_a">' . lang('Systeminfo_General_Date2') . '</div>
|
||||
<div class="col-sm-9 sysinfo_general_b">' . $formatted_date3 . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_general_a">' . lang('Systeminfo_General_TimeZone') . '</div>
|
||||
<div class="col-sm-9 sysinfo_general_b">' . $timeZone . '</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// Network Hardware ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-sitemap fa-rotate-270"></i> ' . lang('Systeminfo_Network_Hardware') . '</h3>
|
||||
<!-- /.tab-content -->
|
||||
</div>
|
||||
<!-- /.nav-tabs-custom -->
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table id="networkTable" class="table table-bordered table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>' . lang('Systeminfo_Network_Hardware_Interface_Name') . '</th>
|
||||
<th>' . lang('Systeminfo_Network_Hardware_Interface_Mask') . '</th>
|
||||
<th>' . lang('Systeminfo_Network_Hardware_Interface_RX') . '</th>
|
||||
<th>' . lang('Systeminfo_Network_Hardware_Interface_TX') . '</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
|
||||
for ($x = 0; $x < sizeof($net_interfaces); $x++) {
|
||||
$interface_name = str_replace(':', '', $net_interfaces[$x]);
|
||||
$interface_ip_temp = exec('ip addr show ' . $interface_name . ' | grep "inet "');
|
||||
$interface_ip_arr = explode(' ', trim($interface_ip_temp));
|
||||
|
||||
if (!isset($interface_ip_arr[1])) {
|
||||
$interface_ip_arr[1] = '--';
|
||||
}
|
||||
|
||||
if ($net_interfaces_rx[$x] == 0) {
|
||||
$temp_rx = 0;
|
||||
} else {
|
||||
$temp_rx = number_format(round(($net_interfaces_rx[$x] / 1024 / 1024), 2), 2, ',', '.');
|
||||
}
|
||||
if ($net_interfaces_tx[$x] == 0) {
|
||||
$temp_tx = 0;
|
||||
} else {
|
||||
$temp_tx = number_format(round(($net_interfaces_tx[$x] / 1024 / 1024), 2), 2, ',', '.');
|
||||
}
|
||||
echo '<tr>';
|
||||
echo '<td>' . $interface_name . '</td>';
|
||||
echo '<td>' . $interface_ip_arr[1] . '</td>';
|
||||
echo '<td>' . $temp_rx . ' MB</td>';
|
||||
echo '<td>' . $temp_tx . ' MB</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
|
||||
echo ' </tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// Client ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-globe"></i> ' . lang('Systeminfo_This_Client') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_client_a">' . lang('Systeminfo_Client_User_Agent') . '</div>
|
||||
<div class="col-sm-9 sysinfo_client_b">' . $_SERVER['HTTP_USER_AGENT'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_client_a">' . lang('Systeminfo_Client_Resolution') . '</div>
|
||||
<div class="col-sm-9 sysinfo_client_b" id="resolution"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
echo '<script>
|
||||
var ratio = window.devicePixelRatio || 1;
|
||||
var w = window.innerWidth;
|
||||
var h = window.innerHeight;
|
||||
var rw = window.innerWidth * ratio;
|
||||
var rh = window.innerHeight * ratio;
|
||||
|
||||
var resolutionDiv = document.getElementById("resolution");
|
||||
resolutionDiv.innerHTML = "Width: " + w + "px / Height: " + h + "px<br> " + "Width: " + rw + "px / Height: " + rh + "px (native)";
|
||||
</script>';
|
||||
|
||||
// System ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-computer"></i> ' . lang('Systeminfo_System') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Uptime') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $stat['uptime'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Kernel') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_namekernel . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_System') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_namesystem . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_OSVersion') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $stat['os_version'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Uname') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_full . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Architecture') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_architecture . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_AVG') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">'. $load_average[0] .' '. $load_average[1] .' '. $load_average[2] .'</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Running_Processes') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_process_count . '</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// Motherboard ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-laptop-code"></i> ' . lang('Systeminfo_Motherboard') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_Name') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_name . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_Manufactured') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_manufactured . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_Revision') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_revision. '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_BIOS') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_bios . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_BIOS_Date') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_biosdate . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_BIOS_Vendor') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_biosvendor . '</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// CPU ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-microchip"></i> ' . lang('Systeminfo_CPU') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Vendor') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $cpu_vendor . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Name') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $stat['cpu_model'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Cores') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $stat['cpu'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Speed') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $stat['cpu_frequ'] . ' MHz</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Temp') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">'. $cpu_temp .' °C</div>
|
||||
</div>';
|
||||
// Get the number of CPU cores
|
||||
$num_cpus = $stat['cpu'];
|
||||
$num_cpus = $num_cpus +2;
|
||||
|
||||
// Iterate over the CPU cores
|
||||
for ($i = 2,$a = 0; $i < $num_cpus; $i++,$a++) {
|
||||
|
||||
// Get the CPU temperature
|
||||
$cpu_tempxx = shell_exec('cat /sys/class/hwmon/hwmon0/temp' . $i . '_input');
|
||||
|
||||
// Convert the temperature to degrees Celsius
|
||||
$cpu_tempxx = floatval($cpu_tempxx) / 1000;
|
||||
|
||||
// Print the CPU temperature
|
||||
echo '<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">CPU Temp ' . $a . ':</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $cpu_tempxx . ' °C</div>
|
||||
</div>';
|
||||
}
|
||||
echo '
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// Memory ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-memory"></i> ' . lang('Systeminfo_Memory') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_memory_a">' . lang('Systeminfo_Memory_Usage_Percent') . '</div>
|
||||
<div class="col-sm-9 sysinfo_memory_b">' . $memory_usage_percent . ' %</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_memory_a">' . lang('Systeminfo_Memory_Usage') . '</div>
|
||||
<div class="col-sm-9 sysinfo_memory_b">' . $mem_used . ' MB / ' . $total_memorymb . ' MB</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_memory_a">' . lang('Systeminfo_Memory_Total_Memory') . '</div>
|
||||
<div class="col-sm-9 sysinfo_memory_b">' . $total_memorymb . ' MB (' . $total_memorykb . ' KB)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// Storage ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-hdd"></i> ' . lang('Systeminfo_Storage') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">';
|
||||
|
||||
$storage_lsblk = shell_exec("lsblk -io NAME,SIZE,TYPE,MOUNTPOINT,MODEL --list | tail -n +2 | awk '{print $1\"#\"$2\"#\"$3\"#\"$4\"#\"$5}'");
|
||||
$storage_lsblk_line = explode("\n", $storage_lsblk);
|
||||
$storage_lsblk_line = array_filter($storage_lsblk_line);
|
||||
|
||||
for ($x = 0; $x < sizeof($storage_lsblk_line); $x++) {
|
||||
$temp = array();
|
||||
$temp = explode("#", $storage_lsblk_line[$x]);
|
||||
$storage_lsblk_line[$x] = $temp;
|
||||
}
|
||||
|
||||
for ($x = 0; $x < sizeof($storage_lsblk_line); $x++) {
|
||||
echo '<div class="row">';
|
||||
if (preg_match('~[0-9]+~', $storage_lsblk_line[$x][0])) {
|
||||
echo '<div class="col-sm-4 sysinfo_storage_a">"' . lang('Systeminfo_Storage_Mount') . ' ' . $storage_lsblk_line[$x][3] . '"</div>';
|
||||
} else {
|
||||
echo '<div class="col-sm-4 sysinfo_storage_a">"' . str_replace('_', ' ', $storage_lsblk_line[$x][3]) . '"</div>';
|
||||
}
|
||||
echo '<div class="col-sm-3 sysinfo_storage_b">' . lang('Systeminfo_Storage_Device') . ' /dev/' . $storage_lsblk_line[$x][0] . '</div>';
|
||||
echo '<div class="col-sm-2 sysinfo_storage_b">' . lang('Systeminfo_Storage_Size') . ' ' . $storage_lsblk_line[$x][1] . '</div>';
|
||||
echo '<div class="col-sm-2 sysinfo_storage_b">' . lang('Systeminfo_Storage_Type') . ' ' . $storage_lsblk_line[$x][2] . '</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
echo ' </div>
|
||||
</div>';
|
||||
|
||||
// Storage usage ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-hdd"></i> ' . lang('Systeminfo_Storage_Usage') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">';
|
||||
for ($x = 0; $x < sizeof($hdd_devices); $x++) {
|
||||
if (stristr($hdd_devices[$x], '/dev/')) {
|
||||
if (!stristr($hdd_devices[$x], '/loop')) {
|
||||
if ($hdd_devices_total[$x] == 0 || $hdd_devices_total[$x] == '') {$temp_total = 0;} else { $temp_total = number_format(round(($hdd_devices_total[$x] / 1024 / 1024), 2), 2, ',', '.'); $temp_total = trim($temp_total);}
|
||||
if ($hdd_devices_used[$x] == 0 || $hdd_devices_used[$x] == '') {$temp_used = 0;} else { $temp_used = number_format(round(($hdd_devices_used[$x] / 1024 / 1024), 2), 2, ',', '.'); $temp_used = trim($temp_total);}
|
||||
if ($hdd_devices_free[$x] == 0 || $hdd_devices_free[$x] == '') {$temp_free = 0;} else { $temp_free = number_format(round(($hdd_devices_free[$x] / 1024 / 1024), 2), 2, ',', '.'); $temp_free = trim($temp_total);}
|
||||
echo '<div class="row">';
|
||||
echo '<div class="col-sm-4 sysinfo_storage_usage_a">"' . lang('Systeminfo_Storage_Usage_Mount') . ' ' . $hdd_devices_mount[$x] . '"</div>';
|
||||
echo '<div class="col-sm-2 sysinfo_storage_usage_b">' . lang('Systeminfo_Storage_Usage_Total') . ' ' . $temp_total . ' GB</div>';
|
||||
echo '<div class="col-sm-3 sysinfo_storage_usage_b">' . lang('Systeminfo_Storage_Usage_Used') . ' ' . $temp_used . ' GB (' . $hdd_devices_percent[$x]. ')</div>';
|
||||
echo '<div class="col-sm-2 sysinfo_storage_usage_b">' . lang('Systeminfo_Storage_Usage_Free') . ' ' . $temp_free . ' GB</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
#echo '<br>' . $lang['SysInfo_storage_note'];
|
||||
echo ' </div>
|
||||
</div>';
|
||||
|
||||
// Network ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fas fa-ethernet"></i> ' . lang('Systeminfo_Network') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_IP') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . shell_exec("curl https://ifconfig.co") . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_IP_Connection') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['REMOTE_ADDR'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_IP_Server') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['SERVER_ADDR'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Server_Name') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $network_NAME . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Connection_Port') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['REMOTE_PORT'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Secure_Connection') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $network_HTTPS . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Server_Version') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['SERVER_SOFTWARE'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_gerneral_a">' . lang('Systeminfo_Network_Request_URI') . '</div>
|
||||
<div class="col-sm-9 sysinfo_gerneral_b">' . $_SERVER['REQUEST_URI'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Server_Query') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $network_QueryString . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_HTTP_Host') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['HTTP_HOST'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_HTTP_Referer') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $network_referer . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_MIME') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['HTTP_ACCEPT'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Accept_Language') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['HTTP_ACCEPT_LANGUAGE'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Accept_Encoding') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['HTTP_ACCEPT_ENCODING'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Request_Method') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['REQUEST_METHOD'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Request_Time') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['REQUEST_TIME'] . '</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
|
||||
|
||||
|
||||
// Services ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-database"></i> ' . lang('Systeminfo_Services') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">';
|
||||
echo '<div style="height: 300px; overflow: scroll;">';
|
||||
exec('systemctl --type=service --state=running', $running_services);
|
||||
echo '<table class="table table-bordered table-hover table-striped dataTable no-footer" style="margin-bottom: 10px;">';
|
||||
echo '<thead>
|
||||
<tr role="row">
|
||||
<th style="padding: 8px;">' . lang('Systeminfo_Services_Name') . '</th>
|
||||
<th style="padding: 8px;">' . lang('Systeminfo_Services_Description') . '</th>
|
||||
</tr>
|
||||
</thead>';
|
||||
$table_color = 'odd';
|
||||
for ($x = 0; $x < sizeof($running_services); $x++) {
|
||||
if (stristr($running_services[$x], '.service')) {
|
||||
$temp_services_arr = array_values(array_filter(explode(' ', trim($running_services[$x]))));
|
||||
$servives_name = $temp_services_arr[0];
|
||||
unset($temp_services_arr[0], $temp_services_arr[1], $temp_services_arr[2], $temp_services_arr[3]);
|
||||
$servives_description = implode(" ", $temp_services_arr);
|
||||
if ($table_color == 'odd') {$table_color = 'even';} else { $table_color = 'odd';}
|
||||
|
||||
echo '<tr class="' . $table_color . '"><td style="padding: 3px; padding-left: 10px;">' . substr($servives_name, 0, -8) . '</td><td style="padding: 3px; padding-left: 10px;">' . $servives_description . '</td></tr>';
|
||||
}
|
||||
}
|
||||
echo '</table>';
|
||||
echo '</div>';
|
||||
echo ' </div>
|
||||
</div>';
|
||||
|
||||
// USB ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fab fa-usb"></i> ' . lang('Systeminfo_USB_Devices') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">';
|
||||
echo ' <table class="table table-bordered table-hover table-striped dataTable no-footer" style="margin-bottom: 10px;">';
|
||||
|
||||
$table_color = 'odd';
|
||||
sort($usb_devices_mount);
|
||||
for ($x = 0; $x < sizeof($usb_devices_mount); $x++) {
|
||||
$cut_pos = strpos($usb_devices_mount[$x], ':');
|
||||
$usb_bus = substr($usb_devices_mount[$x], 0, $cut_pos);
|
||||
$usb_dev = substr($usb_devices_mount[$x], $cut_pos + 1);
|
||||
|
||||
if ($table_color == 'odd') {$table_color = 'even';} else { $table_color = 'odd';}
|
||||
echo '<tr class="' . $table_color . '"><td style="padding: 3px; padding-left: 10px; width: 150px;"><b>' . str_replace('Device', 'Dev.', $usb_bus) . '</b></td><td style="padding: 3px; padding-left: 10px;">' . $usb_dev . '</td></tr>';
|
||||
}
|
||||
echo ' </table>';
|
||||
echo ' </div>
|
||||
</div>';
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
echo '<br>';
|
||||
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<!-- /.content -->
|
||||
<?php
|
||||
require 'php/templates/footer.php';
|
||||
?>
|
||||
|
||||
</div>
|
||||
<!-- /.content-wrapper -->
|
||||
|
||||
<?php
|
||||
require 'php/templates/footer.php';
|
||||
?>
|
||||
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
|
||||
<!-- DataTable initialization -->
|
||||
<script>
|
||||
|
||||
setTimeout(() => {
|
||||
$('#networkTable').DataTable({
|
||||
searching: true,
|
||||
order: [[0, "desc"]],
|
||||
initComplete: function(settings, json) {
|
||||
hideSpinner(); // Called after the DataTable is fully initialized
|
||||
}
|
||||
function loadTabContent(target) {
|
||||
const $tab = $(target);
|
||||
const phpFile = $tab.data('php-file');
|
||||
|
||||
if (phpFile && !$tab.data('loaded')) {
|
||||
showSpinner();
|
||||
$tab.load(phpFile, function () {
|
||||
$tab.data('loaded', true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function initializeTabs() {
|
||||
const key = "activeSysinfoTab";
|
||||
let selectedTab = "tabServer"; // fallback default
|
||||
|
||||
const cached = getCache(key);
|
||||
if (!emptyArr.includes(cached)) {
|
||||
selectedTab = cached;
|
||||
}
|
||||
|
||||
// Activate the correct tab
|
||||
const $tabLink = $('.nav-tabs a[id="' + selectedTab + '"]');
|
||||
$tabLink.tab('show');
|
||||
|
||||
// Get the pane's ID from the tab's href attribute
|
||||
const targetSelector = $tabLink.attr("href");
|
||||
loadTabContent(targetSelector);
|
||||
|
||||
// On tab change
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
const newTabId = $(e.target).attr('id');
|
||||
setCache(key, newTabId);
|
||||
|
||||
const newTarget = $(e.target).attr("href");
|
||||
loadTabContent(newTarget);
|
||||
});
|
||||
|
||||
}, 200);
|
||||
}
|
||||
|
||||
window.onload = function async() {
|
||||
initializeTabs();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
316
front/systeminfoNetwork.php
Executable file
316
front/systeminfoNetwork.php
Executable file
@@ -0,0 +1,316 @@
|
||||
<?php
|
||||
//------------------------------------------------------------------------------
|
||||
// check if authenticated
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/server/db.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/language/lang.php';
|
||||
?>
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
function getExternalIp() {
|
||||
$ch = curl_init('https://api64.ipify.org?format=json');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
$response = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
curl_close($ch);
|
||||
return 'ERROR: ' . curl_error($ch);
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$data = json_decode($response, true);
|
||||
if (isset($data['ip'])) {
|
||||
return htmlspecialchars($data['ip']);
|
||||
}
|
||||
return 'ERROR: Invalid response';
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Network
|
||||
// ----------------------------------------------------------
|
||||
|
||||
//Network stats
|
||||
// Server IP
|
||||
|
||||
$externalIp = getExternalIp();
|
||||
|
||||
// Check Server name
|
||||
if (!empty(gethostname())) { $network_NAME = gethostname(); } else { $network_NAME = lang('Systeminfo_Network_Server_Name_String'); }
|
||||
// Check HTTPS
|
||||
if (isset($_SERVER['HTTPS'])) { $network_HTTPS = 'Yes (HTTPS)'; } else { $network_HTTPS = lang('Systeminfo_Network_Secure_Connection_String'); }
|
||||
// Check Query String
|
||||
if (empty($_SERVER['QUERY_STRING'])) { $network_QueryString = lang('Systeminfo_Network_Server_Query_String'); } else { $network_QueryString = $_SERVER['QUERY_STRING']; }
|
||||
// Check HTTP referer
|
||||
if (empty($_SERVER['HTTP_REFERER'])) { $network_referer = lang('Systeminfo_Network_HTTP_Referer_String'); } else { $network_referer = $_SERVER['HTTP_REFERER']; }
|
||||
//Network Hardware stat
|
||||
$network_result = shell_exec("cat /proc/net/dev | tail -n +3 | awk '{print $1}'");
|
||||
$net_interfaces = explode("\n", trim($network_result));
|
||||
$network_result = shell_exec("cat /proc/net/dev | tail -n +3 | awk '{print $2}'");
|
||||
$net_interfaces_rx = explode("\n", trim($network_result));
|
||||
$network_result = shell_exec("cat /proc/net/dev | tail -n +3 | awk '{print $10}'");
|
||||
$net_interfaces_tx = explode("\n", trim($network_result));
|
||||
|
||||
|
||||
// Network Hardware ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-sitemap fa-rotate-270"></i> ' . lang('Systeminfo_Network_Hardware') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table id="networkTable" class="table table-bordered table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>' . lang('Systeminfo_Network_Hardware_Interface_Name') . '</th>
|
||||
<th>' . lang('Systeminfo_Network_Hardware_Interface_Mask') . '</th>
|
||||
<th>' . lang('Systeminfo_Network_Hardware_Interface_RX') . '</th>
|
||||
<th>' . lang('Systeminfo_Network_Hardware_Interface_TX') . '</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
|
||||
for ($x = 0; $x < sizeof($net_interfaces); $x++) {
|
||||
$interface_name = str_replace(':', '', $net_interfaces[$x]);
|
||||
$interface_ip_temp = exec('ip addr show ' . $interface_name . ' | grep "inet "');
|
||||
$interface_ip_arr = explode(' ', trim($interface_ip_temp));
|
||||
|
||||
if (!isset($interface_ip_arr[1])) {
|
||||
$interface_ip_arr[1] = '--';
|
||||
}
|
||||
|
||||
if ($net_interfaces_rx[$x] == 0) {
|
||||
$temp_rx = 0;
|
||||
} else {
|
||||
$temp_rx = number_format(round(($net_interfaces_rx[$x] / 1024 / 1024), 2), 2, ',', '.');
|
||||
}
|
||||
if ($net_interfaces_tx[$x] == 0) {
|
||||
$temp_tx = 0;
|
||||
} else {
|
||||
$temp_tx = number_format(round(($net_interfaces_tx[$x] / 1024 / 1024), 2), 2, ',', '.');
|
||||
}
|
||||
echo '<tr>';
|
||||
echo '<td>' . $interface_name . '</td>';
|
||||
echo '<td>' . $interface_ip_arr[1] . '</td>';
|
||||
echo '<td>' . $temp_rx . ' MB</td>';
|
||||
echo '<td>' . $temp_tx . ' MB</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
|
||||
echo ' </tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// Available IPs ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title availableips_headline"><i class="fa fa-list"></i> ' . lang('Systeminfo_AvailableIps') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table id="availableIpsTable" class="display table table-bordered table-hover dataTable no-footer" style="width:100%"></table>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
|
||||
|
||||
// Network ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fas fa-ethernet"></i> ' . lang('Systeminfo_Network') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_IP') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b" id="external-ip">' .$externalIp. '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_IP_Connection') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['REMOTE_ADDR'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_IP_Server') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['SERVER_ADDR'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Server_Name') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $network_NAME . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Connection_Port') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['REMOTE_PORT'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Secure_Connection') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $network_HTTPS . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Server_Version') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['SERVER_SOFTWARE'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_gerneral_a">' . lang('Systeminfo_Network_Request_URI') . '</div>
|
||||
<div class="col-sm-9 sysinfo_gerneral_b">' . $_SERVER['REQUEST_URI'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Server_Query') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $network_QueryString . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_HTTP_Host') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['HTTP_HOST'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_HTTP_Referer') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $network_referer . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_MIME') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['HTTP_ACCEPT'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Accept_Language') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['HTTP_ACCEPT_LANGUAGE'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Accept_Encoding') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['HTTP_ACCEPT_ENCODING'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Request_Method') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['REQUEST_METHOD'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_network_a">' . lang('Systeminfo_Network_Request_Time') . '</div>
|
||||
<div class="col-sm-9 sysinfo_network_b">' . $_SERVER['REQUEST_TIME'] . '</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Available free IPS functionality
|
||||
function inferNetworkRange(usedIps) {
|
||||
if (!usedIps || usedIps.length === 0) return [];
|
||||
|
||||
const subnetMap = {};
|
||||
|
||||
// Group IPs by /24 subnet
|
||||
for (const ip of usedIps) {
|
||||
const parts = ip.split('.');
|
||||
if (parts.length !== 4) continue;
|
||||
const subnet = `${parts[0]}.${parts[1]}.${parts[2]}`;
|
||||
if (!subnetMap[subnet]) subnetMap[subnet] = [];
|
||||
subnetMap[subnet].push(ip);
|
||||
}
|
||||
|
||||
const result = [];
|
||||
|
||||
for (const [subnet, ips] of Object.entries(subnetMap)) {
|
||||
if (ips.length > 5) {
|
||||
for (let i = 2; i < 255; i++) {
|
||||
const ip = `${subnet}.${i}`;
|
||||
result.push({ subnet, ip });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function fetchUsedIps(callback) {
|
||||
$.ajax({
|
||||
url: 'php/server/query_graphql.php',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
query: `
|
||||
query devices($options: PageQueryOptionsInput) {
|
||||
devices(options: $options) {
|
||||
devices {
|
||||
devLastIP
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
options: {
|
||||
status: "all_devices"
|
||||
}
|
||||
}
|
||||
}),
|
||||
success: function(response) {
|
||||
|
||||
console.log(response);
|
||||
|
||||
const usedIps = (response?.devices?.devices || [])
|
||||
.map(d => d.devLastIP)
|
||||
.filter(ip => ip && ip.includes('.'));
|
||||
callback(usedIps);
|
||||
},
|
||||
error: function(err) {
|
||||
console.error("Error fetching IPs:", err);
|
||||
callback([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderAvailableIpsTable(allIps, usedIps) {
|
||||
const availableIps = allIps.filter(row => !usedIps.includes(row.ip));
|
||||
|
||||
console.log(availableIps);
|
||||
|
||||
$('#availableIpsTable').DataTable({
|
||||
destroy: true,
|
||||
data: availableIps,
|
||||
columns: [
|
||||
{
|
||||
title: getString("Gen_Subnet"),
|
||||
data: "subnet"
|
||||
},
|
||||
{
|
||||
title: getString("Systeminfo_AvailableIps"),
|
||||
data: "ip",
|
||||
render: function (data, type, row, meta) {
|
||||
return `
|
||||
<span>${data}</span>
|
||||
<button class="copy-btn btn btn-sm btn-info ml-2 alignRight" data-text="${data}" title="${getString("Gen_CopyToClipboard")}" onclick="copyToClipboard(this)">
|
||||
<i class="fa-solid fa-copy"></i>
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
],
|
||||
pageLength: 10
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// INIT
|
||||
$(document).ready(function() {
|
||||
|
||||
// available IPs
|
||||
fetchUsedIps(usedIps => {
|
||||
const allIps = inferNetworkRange(usedIps);
|
||||
renderAvailableIpsTable(allIps, usedIps);
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
// Available IPs datatable
|
||||
$('#networkTable').DataTable({
|
||||
searching: true,
|
||||
order: [[0, "desc"]],
|
||||
initComplete: function(settings, json) {
|
||||
hideSpinner(); // Called after the DataTable is fully initialized
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
});
|
||||
|
||||
</script>
|
||||
327
front/systeminfoServer.php
Executable file
327
front/systeminfoServer.php
Executable file
@@ -0,0 +1,327 @@
|
||||
<?php
|
||||
//------------------------------------------------------------------------------
|
||||
// check if authenticated
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/server/db.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/language/lang.php';
|
||||
?>
|
||||
|
||||
<?php
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Server
|
||||
// ----------------------------------------------------------
|
||||
|
||||
//General stats
|
||||
// Date & Time
|
||||
$date = new DateTime();
|
||||
$formatted_date = $date->format('l, F j, Y H:i:s'); // Get date
|
||||
$formatted_date2 = $date->format('d/m/Y H:i:s'); // Get date2
|
||||
$formatted_date3 = $date->format('Y/m/d H:i:s'); // Get date3
|
||||
//System stats
|
||||
// OS-Version
|
||||
$os_version = '';
|
||||
// Raspbian
|
||||
if ($os_version == '') {$os_version = exec('cat /etc/os-release | grep PRETTY_NAME');}
|
||||
// Dietpi
|
||||
if ($os_version == '') {$os_version = exec('uname -o');}
|
||||
//$os_version_arr = explode("\n", trim($os_version));
|
||||
$stat['os_version'] = str_replace('"', '', str_replace('PRETTY_NAME=', '', $os_version));
|
||||
$stat['uptime'] = str_replace('up ', '', shell_exec("uptime -p")); // Get system uptime
|
||||
$system_namekernel = shell_exec("uname"); // Get system name kernel
|
||||
$system_namesystem = shell_exec("uname -o"); // Get name system
|
||||
$system_full = shell_exec("uname -a"); // Get system full
|
||||
$system_architecture = shell_exec("uname -m"); // Get system Architecture
|
||||
$load_average = sys_getloadavg(); // Get load average
|
||||
$system_process_count = shell_exec("ps -e --no-headers | wc -l"); // Count processes
|
||||
//Motherboard stats
|
||||
$motherboard_name = shell_exec('cat /sys/class/dmi/id/board_name'); // Get the Motherboard name
|
||||
$motherboard_manufactured = shell_exec('cat /sys/class/dmi/id/board_vendor'); // Get the Motherboard manufactured
|
||||
$motherboard_revision = shell_exec('cat /sys/class/dmi/id/board_version'); // Get the Motherboard revision
|
||||
$motherboard_bios = shell_exec('cat /sys/class/dmi/id/bios_version'); // Get the Motherboard BIOS
|
||||
$motherboard_biosdate = shell_exec('cat /sys/class/dmi/id/bios_date'); // Get the Motherboard BIOS date
|
||||
$motherboard_biosvendor = shell_exec('cat /sys/class/dmi/id/bios_vendor'); // Get the Motherboard BIOS vendor
|
||||
//CPU stats
|
||||
$prevVal = shell_exec("cat /proc/cpuinfo | grep processor");
|
||||
$prevArr = explode("\n", trim($prevVal));
|
||||
$stat['cpu'] = sizeof($prevArr);
|
||||
$cpu_result = shell_exec("cat /proc/cpuinfo | grep Model");
|
||||
$stat['cpu_model'] = strstr($cpu_result, "\n", true);
|
||||
$stat['cpu_model'] = str_replace(":", "", trim(str_replace("Model", "", $stat['cpu_model'])));
|
||||
if ($stat['cpu_model'] == '') {
|
||||
$cpu_result = shell_exec("cat /proc/cpuinfo | grep model\ name");
|
||||
$stat['cpu_model'] = strstr($cpu_result, "\n", true);
|
||||
$stat['cpu_model'] = str_replace(":", "", trim(str_replace("model name", "", $stat['cpu_model'])));
|
||||
}
|
||||
if (file_exists('/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq')) {
|
||||
// RaspbianOS
|
||||
$stat['cpu_frequ'] = exec('cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq') / 1000;
|
||||
} elseif (is_numeric(str_replace(',', '.', exec('lscpu | grep "MHz" | awk \'{print $3}\'')))) {
|
||||
// Ubuntu Server, DietPi event. others
|
||||
$stat['cpu_frequ'] = round(exec('lscpu | grep "MHz" | awk \'{print $3}\''), 0);
|
||||
} elseif (is_numeric(str_replace(',', '.', exec('lscpu | grep "max MHz" | awk \'{print $4}\'')))) {
|
||||
// RaspbianOS and event. others
|
||||
$stat['cpu_frequ'] = round(str_replace(',', '.', exec('lscpu | grep "max MHz" | awk \'{print $4}\'')), 0);
|
||||
} else {
|
||||
// Fallback
|
||||
$stat['cpu_frequ'] = "unknown";
|
||||
}
|
||||
$cpu_temp = shell_exec('cat /sys/class/hwmon/hwmon0/temp1_input'); // Get the CPU temperature
|
||||
$cpu_temp = floatval($cpu_temp) / 1000; // Convert the temperature to degrees Celsius
|
||||
$cpu_vendor = exec('cat /proc/cpuinfo | grep "vendor_id" | cut -d ":" -f 2' ); // Get the CPU vendor
|
||||
//Memory stats
|
||||
$total_memorykb = shell_exec("cat /proc/meminfo | grep MemTotal | awk '{print $2}'");
|
||||
$total_memorykb = trim($total_memorykb);
|
||||
$total_memorykb = number_format($total_memorykb, 0, '.', '.');
|
||||
$total_memorymb = shell_exec("cat /proc/meminfo | grep MemTotal | awk '{print $2/1024}'");
|
||||
$total_memorymb = trim($total_memorymb);
|
||||
$total_memorymb = number_format($total_memorymb, 0, '.', '.');
|
||||
$mem_used = round(memory_get_usage() / 1048576 * 100, 2);
|
||||
$memory_usage_percent = round(($mem_used / $total_memorymb), 2);
|
||||
|
||||
|
||||
|
||||
// General ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-info-circle"></i> ' . lang('Systeminfo_General') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_general_a">' . lang('Systeminfo_General_Full_Date') . '</div>
|
||||
<div class="col-sm-9 sysinfo_general_b">' . $formatted_date . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_general_a">' . lang('Systeminfo_General_Date') . '</div>
|
||||
<div class="col-sm-9 sysinfo_general_b">' . $formatted_date2 . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_general_a">' . lang('Systeminfo_General_Date2') . '</div>
|
||||
<div class="col-sm-9 sysinfo_general_b">' . $formatted_date3 . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_general_a">' . lang('Systeminfo_General_TimeZone') . '</div>
|
||||
<div class="col-sm-9 sysinfo_general_b">' . $timeZone . '</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
|
||||
// Client ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-globe"></i> ' . lang('Systeminfo_This_Client') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_client_a">' . lang('Systeminfo_Client_User_Agent') . '</div>
|
||||
<div class="col-sm-9 sysinfo_client_b">' . $_SERVER['HTTP_USER_AGENT'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_client_a">' . lang('Systeminfo_Client_Resolution') . '</div>
|
||||
<div class="col-sm-9 sysinfo_client_b" id="resolution"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
echo '<script>
|
||||
var ratio = window.devicePixelRatio || 1;
|
||||
var w = window.innerWidth;
|
||||
var h = window.innerHeight;
|
||||
var rw = window.innerWidth * ratio;
|
||||
var rh = window.innerHeight * ratio;
|
||||
|
||||
var resolutionDiv = document.getElementById("resolution");
|
||||
resolutionDiv.innerHTML = "Width: " + w + "px / Height: " + h + "px<br> " + "Width: " + rw + "px / Height: " + rh + "px (native)";
|
||||
</script>';
|
||||
|
||||
// System ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-computer"></i> ' . lang('Systeminfo_System') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Uptime') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $stat['uptime'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Kernel') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_namekernel . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_System') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_namesystem . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_OSVersion') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $stat['os_version'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Uname') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_full . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Architecture') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_architecture . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_AVG') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">'. $load_average[0] .' '. $load_average[1] .' '. $load_average[2] .'</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_system_a">' . lang('Systeminfo_System_Running_Processes') . '</div>
|
||||
<div class="col-sm-9 sysinfo_system_b">' . $system_process_count . '</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// Motherboard ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-laptop-code"></i> ' . lang('Systeminfo_Motherboard') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_Name') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_name . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_Manufactured') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_manufactured . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_Revision') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_revision. '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_BIOS') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_bios . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_BIOS_Date') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_biosdate . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_motherboard_a">' . lang('Systeminfo_Motherboard_BIOS_Vendor') . '</div>
|
||||
<div class="col-sm-9 sysinfo_motherboard_b">' . $motherboard_biosvendor . '</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// CPU ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-microchip"></i> ' . lang('Systeminfo_CPU') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Vendor') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $cpu_vendor . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Name') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $stat['cpu_model'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Cores') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $stat['cpu'] . '</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Speed') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $stat['cpu_frequ'] . ' MHz</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">' . lang('Systeminfo_CPU_Temp') . '</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">'. $cpu_temp .' °C</div>
|
||||
</div>';
|
||||
// Get the number of CPU cores
|
||||
$num_cpus = $stat['cpu'];
|
||||
$num_cpus = $num_cpus +2;
|
||||
|
||||
// Iterate over the CPU cores
|
||||
for ($i = 2,$a = 0; $i < $num_cpus; $i++,$a++) {
|
||||
|
||||
// Get the CPU temperature
|
||||
$cpu_tempxx = shell_exec('cat /sys/class/hwmon/hwmon0/temp' . $i . '_input');
|
||||
|
||||
// Convert the temperature to degrees Celsius
|
||||
$cpu_tempxx = floatval($cpu_tempxx) / 1000;
|
||||
|
||||
// Print the CPU temperature
|
||||
echo '<div class="row">
|
||||
<div class="col-sm-3 sysinfo_cpu_a">CPU Temp ' . $a . ':</div>
|
||||
<div class="col-sm-9 sysinfo_cpu_b">' . $cpu_tempxx . ' °C</div>
|
||||
</div>';
|
||||
}
|
||||
echo '
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
// Memory ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-memory"></i> ' . lang('Systeminfo_Memory') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_memory_a">' . lang('Systeminfo_Memory_Usage_Percent') . '</div>
|
||||
<div class="col-sm-9 sysinfo_memory_b">' . $memory_usage_percent . ' %</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_memory_a">' . lang('Systeminfo_Memory_Usage') . '</div>
|
||||
<div class="col-sm-9 sysinfo_memory_b">' . $mem_used . ' MB / ' . $total_memorymb . ' MB</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 sysinfo_memory_a">' . lang('Systeminfo_Memory_Total_Memory') . '</div>
|
||||
<div class="col-sm-9 sysinfo_memory_b">' . $total_memorymb . ' MB (' . $total_memorykb . ' KB)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
|
||||
|
||||
// Services ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-database"></i> ' . lang('Systeminfo_Services') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">';
|
||||
echo '<div style="height: 300px; overflow: scroll;">';
|
||||
exec('systemctl --type=service --state=running', $running_services);
|
||||
echo '<table class="table table-bordered table-hover table-striped dataTable no-footer" style="margin-bottom: 10px;">';
|
||||
echo '<thead>
|
||||
<tr role="row">
|
||||
<th style="padding: 8px;">' . lang('Systeminfo_Services_Name') . '</th>
|
||||
<th style="padding: 8px;">' . lang('Systeminfo_Services_Description') . '</th>
|
||||
</tr>
|
||||
</thead>';
|
||||
$table_color = 'odd';
|
||||
for ($x = 0; $x < sizeof($running_services); $x++) {
|
||||
if (stristr($running_services[$x], '.service')) {
|
||||
$temp_services_arr = array_values(array_filter(explode(' ', trim($running_services[$x]))));
|
||||
$servives_name = $temp_services_arr[0];
|
||||
unset($temp_services_arr[0], $temp_services_arr[1], $temp_services_arr[2], $temp_services_arr[3]);
|
||||
$servives_description = implode(" ", $temp_services_arr);
|
||||
|
||||
if ($table_color == 'odd')
|
||||
{
|
||||
$table_color = 'even';
|
||||
} else
|
||||
{
|
||||
$table_color = 'odd';
|
||||
}
|
||||
echo '<tr class="' . $table_color . '"><td style="padding: 3px; padding-left: 10px;">' . substr($servives_name, 0, -8) . '</td><td style="padding: 3px; padding-left: 10px;">' . $servives_description . '</td></tr>';
|
||||
}
|
||||
}
|
||||
echo '</table>';
|
||||
echo '</div>';
|
||||
echo ' </div>
|
||||
</div>';
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<script>
|
||||
hideSpinner();
|
||||
</script>
|
||||
124
front/systeminfoStorage.php
Executable file
124
front/systeminfoStorage.php
Executable file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
//------------------------------------------------------------------------------
|
||||
// check if authenticated
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/server/db.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/language/lang.php';
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Storage
|
||||
// ----------------------------------------------------------
|
||||
|
||||
//HDD stats
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $1}'");
|
||||
$hdd_devices = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $2}'");
|
||||
$hdd_devices_total = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $3}'");
|
||||
$hdd_devices_used = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $4}'");
|
||||
$hdd_devices_free = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $5}'");
|
||||
$hdd_devices_percent = explode("\n", trim($hdd_result));
|
||||
$hdd_result = shell_exec(" df -P | awk '{print $6}'");
|
||||
$hdd_devices_mount = explode("\n", trim($hdd_result));
|
||||
|
||||
// Storage ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-hdd"></i> ' . lang('Systeminfo_Storage') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">';
|
||||
|
||||
$storage_lsblk = shell_exec("lsblk -io NAME,SIZE,TYPE,MOUNTPOINT,MODEL --list | tail -n +2 | awk '{print $1\"#\"$2\"#\"$3\"#\"$4\"#\"$5}'");
|
||||
$storage_lsblk_line = explode("\n", $storage_lsblk);
|
||||
$storage_lsblk_line = array_filter($storage_lsblk_line);
|
||||
|
||||
for ($x = 0; $x < sizeof($storage_lsblk_line); $x++) {
|
||||
$temp = array();
|
||||
$temp = explode("#", $storage_lsblk_line[$x]);
|
||||
$storage_lsblk_line[$x] = $temp;
|
||||
}
|
||||
|
||||
for ($x = 0; $x < sizeof($storage_lsblk_line); $x++) {
|
||||
echo '<div class="row">';
|
||||
if (preg_match('~[0-9]+~', $storage_lsblk_line[$x][0])) {
|
||||
echo '<div class="col-sm-4 sysinfo_storage_a">"' . lang('Systeminfo_Storage_Mount') . ' ' . $storage_lsblk_line[$x][3] . '"</div>';
|
||||
} else {
|
||||
echo '<div class="col-sm-4 sysinfo_storage_a">"' . str_replace('_', ' ', $storage_lsblk_line[$x][3]) . '"</div>';
|
||||
}
|
||||
echo '<div class="col-sm-3 sysinfo_storage_b">' . lang('Systeminfo_Storage_Device') . ' /dev/' . $storage_lsblk_line[$x][0] . '</div>';
|
||||
echo '<div class="col-sm-2 sysinfo_storage_b">' . lang('Systeminfo_Storage_Size') . ' ' . $storage_lsblk_line[$x][1] . '</div>';
|
||||
echo '<div class="col-sm-2 sysinfo_storage_b">' . lang('Systeminfo_Storage_Type') . ' ' . $storage_lsblk_line[$x][2] . '</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
echo ' </div>
|
||||
</div>';
|
||||
|
||||
// Storage usage ----------------------------------------------------------
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fa fa-hdd"></i> ' . lang('Systeminfo_Storage_Usage') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">';
|
||||
for ($x = 0; $x < sizeof($hdd_devices); $x++) {
|
||||
if (stristr($hdd_devices[$x], '/dev/')) {
|
||||
if (!stristr($hdd_devices[$x], '/loop')) {
|
||||
if ($hdd_devices_total[$x] == 0 || $hdd_devices_total[$x] == '') {$temp_total = 0;} else { $temp_total = number_format(round(($hdd_devices_total[$x] / 1024 / 1024), 2), 2, ',', '.'); $temp_total = trim($temp_total);}
|
||||
if ($hdd_devices_used[$x] == 0 || $hdd_devices_used[$x] == '') {$temp_used = 0;} else { $temp_used = number_format(round(($hdd_devices_used[$x] / 1024 / 1024), 2), 2, ',', '.'); $temp_used = trim($temp_total);}
|
||||
if ($hdd_devices_free[$x] == 0 || $hdd_devices_free[$x] == '') {$temp_free = 0;} else { $temp_free = number_format(round(($hdd_devices_free[$x] / 1024 / 1024), 2), 2, ',', '.'); $temp_free = trim($temp_total);}
|
||||
echo '<div class="row">';
|
||||
echo '<div class="col-sm-4 sysinfo_storage_usage_a">"' . lang('Systeminfo_Storage_Usage_Mount') . ' ' . $hdd_devices_mount[$x] . '"</div>';
|
||||
echo '<div class="col-sm-2 sysinfo_storage_usage_b">' . lang('Systeminfo_Storage_Usage_Total') . ' ' . $temp_total . ' GB</div>';
|
||||
echo '<div class="col-sm-3 sysinfo_storage_usage_b">' . lang('Systeminfo_Storage_Usage_Used') . ' ' . $temp_used . ' GB (' . $hdd_devices_percent[$x]. ')</div>';
|
||||
echo '<div class="col-sm-2 sysinfo_storage_usage_b">' . lang('Systeminfo_Storage_Usage_Free') . ' ' . $temp_free . ' GB</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
#echo '<br>' . $lang['SysInfo_storage_note'];
|
||||
echo ' </div>
|
||||
</div>';
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// USB devices
|
||||
// ----------------------------------------------------------
|
||||
|
||||
$usb_result = shell_exec("lsusb");
|
||||
$usb_devices_mount = explode("\n", trim($usb_result));
|
||||
|
||||
echo '<div class="box box-solid">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title sysinfo_headline"><i class="fab fa-usb"></i> ' . lang('Systeminfo_USB_Devices') . '</h3>
|
||||
</div>
|
||||
<div class="box-body">';
|
||||
echo ' <table class="table table-bordered table-hover table-striped dataTable no-footer" style="margin-bottom: 10px;">';
|
||||
|
||||
$table_color = 'odd';
|
||||
sort($usb_devices_mount);
|
||||
for ($x = 0; $x < sizeof($usb_devices_mount); $x++) {
|
||||
$cut_pos = strpos($usb_devices_mount[$x], ':');
|
||||
$usb_bus = substr($usb_devices_mount[$x], 0, $cut_pos);
|
||||
$usb_dev = substr($usb_devices_mount[$x], $cut_pos + 1);
|
||||
|
||||
if ($table_color == 'odd') {$table_color = 'even';} else { $table_color = 'odd';}
|
||||
echo '<tr class="' . $table_color . '"><td style="padding: 3px; padding-left: 10px; width: 150px;"><b>' . str_replace('Device', 'Dev.', $usb_bus) . '</b></td><td style="padding: 3px; padding-left: 10px;">' . $usb_dev . '</td></tr>';
|
||||
}
|
||||
echo ' </table>';
|
||||
echo ' </div>
|
||||
</div>';
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
echo '<br>';
|
||||
|
||||
?>
|
||||
|
||||
<script>
|
||||
hideSpinner();
|
||||
</script>
|
||||
@@ -30,5 +30,5 @@ source myenv/bin/activate
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3 10
|
||||
|
||||
# install packages thru pip3
|
||||
pip3 install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag git+https://github.com/foreign-sub/aiofreepybox.git
|
||||
pip3 install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask flask-cors tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag git+https://github.com/foreign-sub/aiofreepybox.git
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ nav:
|
||||
- Database: DATABASE.md
|
||||
- Settings: SETTINGS_SYSTEM.md
|
||||
- Versions: VERSIONS.md
|
||||
- Icon and Type guessing: DEVICE_HEURISTICS.md
|
||||
- Integrations:
|
||||
- Webhook Secret: WEBHOOK_SECRET.md
|
||||
- API: API.md
|
||||
|
||||
@@ -13,7 +13,7 @@ from models.user_events_queue_instance import UserEventsQueueInstance
|
||||
from messaging.in_app import write_notification
|
||||
|
||||
# Import the start_server function
|
||||
from graphql_server.graphql_server_start import start_server
|
||||
from api_server.api_server_start import start_server
|
||||
|
||||
apiEndpoints = []
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import threading
|
||||
from flask import Flask, request, jsonify
|
||||
from flask import Flask, request, jsonify, Response
|
||||
from flask_cors import CORS
|
||||
from .graphql_schema import devicesSchema
|
||||
from .prometheus_metrics import getMetricStats
|
||||
from graphene import Schema
|
||||
import sys
|
||||
|
||||
@@ -15,9 +17,11 @@ from messaging.in_app import write_notification
|
||||
|
||||
# Flask application
|
||||
app = Flask(__name__)
|
||||
CORS(app, resources={r"/metrics": {"origins": "*"}}, supports_credentials=True, allow_headers=["Authorization"])
|
||||
|
||||
# Retrieve API token and port
|
||||
graphql_port_value = get_setting_value("GRAPHQL_PORT")
|
||||
# --------------------------
|
||||
# GraphQL Endpoints
|
||||
# --------------------------
|
||||
|
||||
# Endpoint used when accessed via browser
|
||||
@app.route("/graphql", methods=["GET"])
|
||||
@@ -29,10 +33,7 @@ def graphql_debug():
|
||||
@app.route("/graphql", methods=["POST"])
|
||||
def graphql_endpoint():
|
||||
# Check for API token in headers
|
||||
incoming_header_token = request.headers.get("Authorization")
|
||||
api_token_value = get_setting_value("API_TOKEN")
|
||||
|
||||
if incoming_header_token != f"Bearer {api_token_value}":
|
||||
if not is_authorized():
|
||||
msg = '[graphql_server] Unauthorized access attempt - make sure your GRAPHQL_PORT and API_TOKEN settings are correct.'
|
||||
mylog('verbose', [msg])
|
||||
return jsonify({"error": msg}), 401
|
||||
@@ -47,6 +48,32 @@ def graphql_endpoint():
|
||||
# Return the result as JSON
|
||||
return jsonify(result.data)
|
||||
|
||||
# --------------------------
|
||||
# Prometheus /metrics Endpoint
|
||||
# --------------------------
|
||||
|
||||
@app.route("/metrics")
|
||||
def metrics():
|
||||
|
||||
# Check for API token in headers
|
||||
if not is_authorized():
|
||||
msg = '[metrics] Unauthorized access attempt - make sure your GRAPHQL_PORT and API_TOKEN settings are correct.'
|
||||
mylog('verbose', [msg])
|
||||
return jsonify({"error": msg}), 401
|
||||
|
||||
|
||||
# Return Prometheus metrics as plain text
|
||||
return Response(getMetricStats(), mimetype="text/plain")
|
||||
|
||||
|
||||
# --------------------------
|
||||
# Background Server Start
|
||||
# --------------------------
|
||||
def is_authorized():
|
||||
token = request.headers.get("Authorization")
|
||||
return token == f"Bearer {get_setting_value('API_TOKEN')}"
|
||||
|
||||
|
||||
def start_server(graphql_port, app_state):
|
||||
"""Start the GraphQL server in a background thread."""
|
||||
|
||||
@@ -197,7 +197,7 @@ class Query(ObjectType):
|
||||
searchable_fields = [
|
||||
"devName", "devMac", "devOwner", "devType", "devVendor", "devLastIP",
|
||||
"devGroup", "devComments", "devLocation", "devStatus", "devSSID",
|
||||
"devSite", "devSourcePlugin", "devSyncHubNode", "devFQDN", "devParentRelType"
|
||||
"devSite", "devSourcePlugin", "devSyncHubNode", "devFQDN", "devParentRelType", "devParentMAC"
|
||||
]
|
||||
|
||||
search_term = options.search.lower()
|
||||
76
server/api_server/prometheus_metrics.py
Executable file
76
server/api_server/prometheus_metrics.py
Executable file
@@ -0,0 +1,76 @@
|
||||
import json
|
||||
import sys
|
||||
|
||||
# Register NetAlertX directories
|
||||
INSTALL_PATH = "/app"
|
||||
sys.path.extend([f"{INSTALL_PATH}/server"])
|
||||
|
||||
from logger import mylog
|
||||
from const import apiPath
|
||||
from helper import is_random_mac, get_number_of_children, format_ip_long, get_setting_value
|
||||
|
||||
def escape_label_value(val):
|
||||
"""
|
||||
Escape special characters for Prometheus labels.
|
||||
"""
|
||||
return str(val).replace('\\', '\\\\').replace('\n', '\\n').replace('"', '\\"')
|
||||
|
||||
# Define a base URL with the user's home directory
|
||||
folder = apiPath
|
||||
|
||||
def getMetricStats():
|
||||
output = []
|
||||
|
||||
# 1. Dashboard totals
|
||||
try:
|
||||
with open(folder + 'table_devices_tiles.json', 'r') as f:
|
||||
tiles_data = json.load(f)["data"]
|
||||
|
||||
if isinstance(tiles_data, list) and tiles_data:
|
||||
totals = tiles_data[0]
|
||||
output.append(f'netalertx_connected_devices {totals.get("connected", 0)}')
|
||||
output.append(f'netalertx_offline_devices {totals.get("offline", 0)}')
|
||||
output.append(f'netalertx_down_devices {totals.get("down", 0)}')
|
||||
output.append(f'netalertx_new_devices {totals.get("new", 0)}')
|
||||
output.append(f'netalertx_archived_devices {totals.get("archived", 0)}')
|
||||
output.append(f'netalertx_favorite_devices {totals.get("favorites", 0)}')
|
||||
output.append(f'netalertx_my_devices {totals.get("my_devices", 0)}')
|
||||
else:
|
||||
output.append("# Unexpected format in table_devices_tiles.json")
|
||||
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||||
mylog('none', f'[metrics] Error loading tiles data: {e}')
|
||||
output.append(f"# Error loading tiles data: {e}")
|
||||
except Exception as e:
|
||||
output.append(f"# General error loading dashboard totals: {e}")
|
||||
|
||||
# 2. Device-level metrics
|
||||
try:
|
||||
with open(folder + 'table_devices.json', 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
devices = data.get("data", [])
|
||||
|
||||
for row in devices:
|
||||
name = escape_label_value(row.get("devName", "unknown"))
|
||||
mac = escape_label_value(row.get("devMac", "unknown"))
|
||||
ip = escape_label_value(row.get("devLastIP", "unknown"))
|
||||
vendor = escape_label_value(row.get("devVendor", "unknown"))
|
||||
first_conn = escape_label_value(row.get("devFirstConnection", "unknown"))
|
||||
last_conn = escape_label_value(row.get("devLastConnection", "unknown"))
|
||||
dev_type = escape_label_value(row.get("devType", "unknown"))
|
||||
raw_status = row.get("devStatus", "Unknown")
|
||||
dev_status = raw_status.replace("-", "").capitalize()
|
||||
|
||||
output.append(
|
||||
f'netalertx_device_status{{device="{name}", mac="{mac}", ip="{ip}", vendor="{vendor}", '
|
||||
f'first_connection="{first_conn}", last_connection="{last_conn}", dev_type="{dev_type}", '
|
||||
f'device_status="{dev_status}"}} 1'
|
||||
)
|
||||
|
||||
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||||
mylog('none', f'[metrics] Error loading devices data: {e}')
|
||||
output.append(f"# Error loading devices data: {e}")
|
||||
except Exception as e:
|
||||
output.append(f"# General error processing device metrics: {e}")
|
||||
|
||||
return "\n".join(output) + "\n"
|
||||
@@ -667,7 +667,10 @@ def checkNewVersion():
|
||||
buildTimestamp = int(f.read().strip())
|
||||
|
||||
try:
|
||||
response = requests.get("https://api.github.com/repos/jokob-sk/NetAlertX/releases")
|
||||
response = requests.get(
|
||||
"https://api.github.com/repos/jokob-sk/NetAlertX/releases",
|
||||
timeout=5
|
||||
)
|
||||
response.raise_for_status() # Raise an exception for HTTP errors
|
||||
text = response.text
|
||||
except requests.exceptions.RequestException as e:
|
||||
|
||||
@@ -157,13 +157,13 @@ def importConfigs (db, all_plugins):
|
||||
# ----------------------------------------
|
||||
# ccd(key, default, config_dir, name, inputtype, options, group, events=[], desc = "", regex = "", setJsonMetadata = {}, overrideTemplate = {})
|
||||
|
||||
conf.LOADED_PLUGINS = ccd('LOADED_PLUGINS', [] , c_d, 'Loaded plugins', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true", "ordeable": "true"}] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.LOADED_PLUGINS = ccd('LOADED_PLUGINS', [] , c_d, 'Loaded plugins', '{"dataType":"array","elements":[{"elementType":"select","elementOptions":[{"multiple":"true","ordeable":"true"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-12"},{"onClick":"selectChange(this)"},{"getStringKey":"Gen_Change"}],"transformers":[]}]}', '[]', 'General')
|
||||
conf.DISCOVER_PLUGINS = ccd('DISCOVER_PLUGINS', True , c_d, 'Discover plugins', """{"dataType": "boolean","elements": [{"elementType": "input","elementOptions": [{ "type": "checkbox" }],"transformers": []}]}""", '[]', 'General')
|
||||
conf.SCAN_SUBNETS = ccd('SCAN_SUBNETS', ['192.168.1.0/24 --interface=eth1', '192.168.1.0/24 --interface=eth0'] , c_d, 'Subnets to scan', '''{"dataType": "array","elements": [{"elementType": "input","elementOptions": [{"placeholder": "192.168.1.0/24 --interface=eth1"},{"suffix": "_in"},{"cssClasses": "col-sm-10"},{"prefillValue": "null"}],"transformers": []},{"elementType": "button","elementOptions": [{"sourceSuffixes": ["_in"]},{"separator": ""},{"cssClasses": "col-xs-12"},{"onClick": "addList(this, false)"},{"getStringKey": "Gen_Add"}],"transformers": []},{"elementType": "select","elementHasInputValue": 1,"elementOptions": [{"multiple": "true"},{"readonly": "true"},{"editable": "true"}],"transformers": []},{"elementType": "button","elementOptions": [{"sourceSuffixes": []},{"separator": ""},{"cssClasses": "col-xs-6"},{"onClick": "removeAllOptions(this)"},{"getStringKey": "Gen_Remove_All"}],"transformers": []},{"elementType": "button","elementOptions": [{"sourceSuffixes": []},{"separator": ""},{"cssClasses": "col-xs-6"},{"onClick": "removeFromList(this)"},{"getStringKey": "Gen_Remove_Last"}],"transformers": []}]}''', '[]', 'General')
|
||||
conf.LOG_LEVEL = ccd('LOG_LEVEL', 'verbose' , c_d, 'Log verboseness', '{"dataType":"string", "elements": [{"elementType" : "select", "elementOptions" : [] ,"transformers": []}]}', "['none', 'minimal', 'verbose', 'debug', 'trace']", 'General')
|
||||
conf.TIMEZONE = ccd('TIMEZONE', default_tz , c_d, 'Time zone', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.PLUGINS_KEEP_HIST = ccd('PLUGINS_KEEP_HIST', 250 , c_d, 'Keep history entries', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.REPORT_DASHBOARD_URL = ccd('REPORT_DASHBOARD_URL', 'http://127.0.0.1/' , c_d, 'NetAlertX URL', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.REPORT_DASHBOARD_URL = ccd('REPORT_DASHBOARD_URL', 'update_REPORT_DASHBOARD_URL_setting' , c_d, 'NetAlertX URL', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.DAYS_TO_KEEP_EVENTS = ccd('DAYS_TO_KEEP_EVENTS', 90 , c_d, 'Delete events days', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.HRS_TO_KEEP_NEWDEV = ccd('HRS_TO_KEEP_NEWDEV', 0 , c_d, 'Keep new devices for', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', "[]", 'General')
|
||||
conf.HRS_TO_KEEP_OFFDEV = ccd('HRS_TO_KEEP_OFFDEV', 0 , c_d, 'Keep offline devices for', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', "[]", 'General')
|
||||
@@ -171,7 +171,7 @@ def importConfigs (db, all_plugins):
|
||||
conf.REFRESH_FQDN = ccd('REFRESH_FQDN', False , c_d, 'Refresh FQDN', """{"dataType": "boolean","elements": [{"elementType": "input","elementOptions": [{ "type": "checkbox" }],"transformers": []}]}""", '[]', 'General')
|
||||
conf.API_CUSTOM_SQL = ccd('API_CUSTOM_SQL', 'SELECT * FROM Devices WHERE devPresentLastScan = 0' , c_d, 'Custom endpoint', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.VERSION = ccd('VERSION', '' , c_d, 'Version', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [{ "readonly": "true" }] ,"transformers": []}]}', '', 'General')
|
||||
conf.NETWORK_DEVICE_TYPES = ccd('NETWORK_DEVICE_TYPES', ['AP', 'Gateway', 'Firewall', 'Hypervisor', 'Powerline', 'Switch', 'WLAN', 'PLC', 'Router','USB LAN Adapter', 'USB WIFI Adapter', 'Internet'] , c_d, 'Network device types', '{"dataType":"array","elements":[{"elementType":"input","elementOptions":[{"placeholder":"Enter value"},{"suffix":"_in"},{"cssClasses":"col-sm-10"},{"prefillValue":"null"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":["_in"]},{"separator":""},{"cssClasses":"col-xs-12"},{"onClick":"addList(this,false)"},{"getStringKey":"Gen_Add"}],"transformers":[]},{"elementType":"select", "elementHasInputValue":1,"elementOptions":[{"multiple":"true"},{"readonly":"true"},{"editable":"true"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeAllOptions(this)"},{"getStringKey":"Gen_Remove_All"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeFromList(this)"},{"getStringKey":"Gen_Remove_Last"}],"transformers":[]}]}', '[]', 'General')
|
||||
conf.NETWORK_DEVICE_TYPES = ccd('NETWORK_DEVICE_TYPES', ['AP', 'Access Point', 'Gateway', 'Firewall', 'Hypervisor', 'Powerline', 'Switch', 'WLAN', 'PLC', 'Router','USB LAN Adapter', 'USB WIFI Adapter', 'Internet'] , c_d, 'Network device types', '{"dataType":"array","elements":[{"elementType":"input","elementOptions":[{"placeholder":"Enter value"},{"suffix":"_in"},{"cssClasses":"col-sm-10"},{"prefillValue":"null"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":["_in"]},{"separator":""},{"cssClasses":"col-xs-12"},{"onClick":"addList(this,false)"},{"getStringKey":"Gen_Add"}],"transformers":[]},{"elementType":"select", "elementHasInputValue":1,"elementOptions":[{"multiple":"true"},{"readonly":"true"},{"editable":"true"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeAllOptions(this)"},{"getStringKey":"Gen_Remove_All"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeFromList(this)"},{"getStringKey":"Gen_Remove_Last"}],"transformers":[]}]}', '[]', 'General')
|
||||
conf.GRAPHQL_PORT = ccd('GRAPHQL_PORT', 20212 , c_d, 'GraphQL port', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.API_TOKEN = ccd('API_TOKEN', 't_' + generate_random_string(20) , c_d, 'API token', '{"dataType": "string","elements": [{"elementType": "input","elementHasInputValue": 1,"elementOptions": [{ "cssClasses": "col-xs-12" }],"transformers": []},{"elementType": "button","elementOptions": [{ "getStringKey": "Gen_Generate" },{ "customParams": "API_TOKEN" },{ "onClick": "generateApiToken(this, 20)" },{ "cssClasses": "col-xs-12" }],"transformers": []}]}', '[]', 'General')
|
||||
|
||||
|
||||
@@ -447,8 +447,8 @@ def create_new_devices (db):
|
||||
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_Name = str(cur_Name).strip() if cur_Name else '(unknown)'
|
||||
cur_Type = str(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"))
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import sys
|
||||
import re
|
||||
import json
|
||||
import base64
|
||||
from pathlib import Path
|
||||
from typing import Optional, List, Tuple, Dict
|
||||
|
||||
# Register NetAlertX directories
|
||||
@@ -11,57 +14,167 @@ from const import *
|
||||
from logger import mylog
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
|
||||
# Load MAC/device-type/icon rules from external file
|
||||
MAC_TYPE_ICON_PATH = Path(f"{INSTALL_PATH}/back/device_heuristics_rules.json")
|
||||
try:
|
||||
with open(MAC_TYPE_ICON_PATH, "r", encoding="utf-8") as f:
|
||||
MAC_TYPE_ICON_RULES = json.load(f)
|
||||
# Precompute base64-encoded icon_html once for each rule
|
||||
for rule in MAC_TYPE_ICON_RULES:
|
||||
icon_html = rule.get("icon_html", "")
|
||||
if icon_html:
|
||||
# encode icon_html to base64 string
|
||||
b64_bytes = base64.b64encode(icon_html.encode("utf-8"))
|
||||
rule["icon_base64"] = b64_bytes.decode("utf-8")
|
||||
else:
|
||||
rule["icon_base64"] = ""
|
||||
except Exception as e:
|
||||
MAC_TYPE_ICON_RULES = []
|
||||
mylog('none', f"[guess_device_attributes] Failed to load device_heuristics_rules.json: {e}")
|
||||
|
||||
# -----------------------------------------
|
||||
# Match device type and base64-encoded icon using MAC prefix and vendor patterns.
|
||||
def match_mac_and_vendor(
|
||||
mac_clean: str,
|
||||
vendor: str,
|
||||
default_type: str,
|
||||
default_icon: str
|
||||
) -> Tuple[str, str]:
|
||||
"""
|
||||
Match device type and base64-encoded icon using MAC prefix and vendor patterns.
|
||||
|
||||
Args:
|
||||
mac_clean: Cleaned MAC address (uppercase, no colons).
|
||||
vendor: Normalized vendor name (lowercase).
|
||||
default_type: Fallback device type.
|
||||
default_icon: Fallback base64 icon.
|
||||
|
||||
Returns:
|
||||
Tuple containing (device_type, base64_icon)
|
||||
"""
|
||||
for rule in MAC_TYPE_ICON_RULES:
|
||||
dev_type = rule.get("dev_type")
|
||||
base64_icon = rule.get("icon_base64", "")
|
||||
patterns = rule.get("matching_pattern", [])
|
||||
|
||||
for pattern in patterns:
|
||||
mac_prefix = pattern.get("mac_prefix", "").upper()
|
||||
vendor_pattern = pattern.get("vendor", "").lower()
|
||||
|
||||
if mac_clean.startswith(mac_prefix):
|
||||
if not vendor_pattern or vendor_pattern in vendor:
|
||||
|
||||
mylog('debug', f"[guess_device_attributes] Matched via MAC+Vendor")
|
||||
|
||||
type_ = dev_type
|
||||
icon = base64_icon or default_icon
|
||||
return type_, icon
|
||||
|
||||
return default_type, default_icon
|
||||
|
||||
# ---------------------------------------------------
|
||||
# Match device type and base64-encoded icon using vendor patterns.
|
||||
def match_vendor(
|
||||
vendor: str,
|
||||
default_type: str,
|
||||
default_icon: str
|
||||
) -> Tuple[str, str]:
|
||||
|
||||
vendor_lc = vendor.lower()
|
||||
|
||||
for rule in MAC_TYPE_ICON_RULES:
|
||||
dev_type = rule.get("dev_type")
|
||||
base64_icon = rule.get("icon_base64", "")
|
||||
patterns = rule.get("matching_pattern", [])
|
||||
|
||||
for pattern in patterns:
|
||||
# Only apply fallback when no MAC prefix is specified
|
||||
mac_prefix = pattern.get("mac_prefix", "")
|
||||
vendor_pattern = pattern.get("vendor", "").lower()
|
||||
|
||||
if vendor_pattern and vendor_pattern in vendor_lc:
|
||||
|
||||
mylog('debug', f"[guess_device_attributes] Matched via Vendor")
|
||||
|
||||
icon = base64_icon or default_icon
|
||||
|
||||
return dev_type, icon
|
||||
|
||||
return default_type, default_icon
|
||||
|
||||
# ---------------------------------------------------
|
||||
# Match device type and base64-encoded icon using name patterns.
|
||||
def match_name(
|
||||
name: str,
|
||||
default_type: str,
|
||||
default_icon: str
|
||||
) -> Tuple[str, str]:
|
||||
"""
|
||||
Match device type and base64-encoded icon using name patterns from global MAC_TYPE_ICON_RULES.
|
||||
|
||||
Args:
|
||||
name: Normalized device name (lowercase).
|
||||
default_type: Fallback device type.
|
||||
default_icon: Fallback base64 icon.
|
||||
|
||||
Returns:
|
||||
Tuple containing (device_type, base64_icon)
|
||||
"""
|
||||
name_lower = name.lower() if name else ""
|
||||
|
||||
for rule in MAC_TYPE_ICON_RULES:
|
||||
dev_type = rule.get("dev_type")
|
||||
base64_icon = rule.get("icon_base64", "")
|
||||
name_patterns = rule.get("name_pattern", [])
|
||||
|
||||
for pattern in name_patterns:
|
||||
# Use regex search to allow pattern substrings
|
||||
if re.search(pattern, name_lower, re.IGNORECASE):
|
||||
|
||||
mylog('debug', f"[guess_device_attributes] Matched via Name")
|
||||
|
||||
type_ = dev_type
|
||||
icon = base64_icon or default_icon
|
||||
return type_, icon
|
||||
|
||||
return default_type, default_icon
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# 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
|
||||
}
|
||||
#
|
||||
def match_ip(
|
||||
ip: str,
|
||||
default_type: str,
|
||||
default_icon: str
|
||||
) -> Tuple[str, str]:
|
||||
"""
|
||||
Match device type and base64-encoded icon using IP regex patterns from global JSON.
|
||||
|
||||
# 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",
|
||||
}
|
||||
Args:
|
||||
ip: Device IP address as string.
|
||||
default_type: Fallback device type.
|
||||
default_icon: Fallback base64 icon.
|
||||
|
||||
Returns:
|
||||
Tuple containing (device_type, base64_icon)
|
||||
"""
|
||||
if not ip:
|
||||
return default_type, default_icon
|
||||
|
||||
for rule in MAC_TYPE_ICON_RULES:
|
||||
ip_patterns = rule.get("ip_pattern", [])
|
||||
dev_type = rule.get("dev_type")
|
||||
base64_icon = rule.get("icon_base64", "")
|
||||
|
||||
for pattern in ip_patterns:
|
||||
if re.match(pattern, ip):
|
||||
|
||||
mylog('debug', f"[guess_device_attributes] Matched via IP")
|
||||
|
||||
type_ = dev_type
|
||||
icon = base64_icon or default_icon
|
||||
return type_, icon
|
||||
|
||||
return default_type, default_icon
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Guess device attributes such as type of device and associated device icon
|
||||
@@ -72,197 +185,46 @@ def guess_device_attributes(
|
||||
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).
|
||||
"""
|
||||
) -> Tuple[str, str]:
|
||||
mylog('debug', f"[guess_device_attributes] Guessing attributes for (vendor|mac|ip|name): ('{vendor}'|'{mac}'|'{ip}'|'{name}')")
|
||||
# Normalize inputs
|
||||
|
||||
# --- 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
|
||||
ip = str(ip).strip() if ip else "169.254.0.0"
|
||||
name = str(name).lower().strip() if name else "(unknown)"
|
||||
mac_clean = mac.replace(':', '').replace('-', '').upper()
|
||||
|
||||
# --- 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
|
||||
# # Internet shortcut
|
||||
# if mac == "INTERNET":
|
||||
# return ICONS.get("globe", default_icon), DEVICE_TYPES.get("Internet", default_type)
|
||||
|
||||
# --- 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
|
||||
type_ = None
|
||||
icon = None
|
||||
|
||||
# --- Strict MAC + vendor rule matching from external file ---
|
||||
type_, icon = match_mac_and_vendor(mac_clean, vendor, default_type, default_icon)
|
||||
|
||||
# --- Loose Vendor-based fallback ---
|
||||
if not type_ or type_ == default_type:
|
||||
type_, icon = match_vendor(vendor, default_type, default_icon)
|
||||
|
||||
# --- Loose Name-based fallback ---
|
||||
if not type_ or type_ == default_type:
|
||||
type_, icon = match_name(name, default_type, default_icon)
|
||||
|
||||
# --- Loose IP-based fallback ---
|
||||
if (not type_ or type_ == default_type) or (not icon or icon == default_icon):
|
||||
type_, icon = match_ip(ip, default_type, default_icon)
|
||||
|
||||
# Final fallbacks
|
||||
type_ = type_ or default_type
|
||||
icon = icon or default_icon
|
||||
|
||||
mylog('debug', f"[guess_device_attributes] Guessed attributes (icon|type_): ('{icon}'|'{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],
|
||||
@@ -308,7 +270,7 @@ def guess_type(
|
||||
default: Default type to return if no match is found.
|
||||
|
||||
Returns:
|
||||
str: Device type from DEVICE_TYPES dictionary.
|
||||
str: Device type.
|
||||
"""
|
||||
|
||||
_, type_ = guess_device_attributes(vendor, mac, ip, name, "unknown_icon", default)
|
||||
|
||||
Reference in New Issue
Block a user