Compare commits

..

8 Commits

Author SHA1 Message Date
5b33e2d656 Merge pull request 'dev' (#2) from dev into main
Reviewed-on: #2
2025-10-12 17:19:37 +02:00
3b7acfbac1 revert a09454211b
revert srv/poe_manager/templates/index.html aktualisiert
2025-10-12 17:19:29 +02:00
a09454211b srv/poe_manager/templates/index.html aktualisiert 2025-10-12 17:00:15 +02:00
ba11861336 Merge pull request 'dev' (#1) from dev into main
Reviewed-on: #1
2025-10-12 13:44:14 +02:00
df000eace9 revert 74617a1e0f
revert srv/poe_manager/templates/switche.html aktualisiert
2025-10-07 18:19:42 +02:00
74617a1e0f srv/poe_manager/templates/switche.html aktualisiert 2025-10-07 18:17:58 +02:00
bc80b5fcf1 srv/poe_manager/create_db.py aktualisiert 2025-09-30 19:11:09 +02:00
0c82ce6100 srv/poe_manager/create_db.py aktualisiert 2025-09-30 19:10:13 +02:00
8 changed files with 43 additions and 88 deletions

View File

@@ -4,7 +4,6 @@ from flask_login import LoginManager, login_user, login_required, logout_user, U
from flask_bcrypt import Bcrypt from flask_bcrypt import Bcrypt
from cryptography.fernet import Fernet from cryptography.fernet import Fernet
from datetime import datetime from datetime import datetime
from collections import defaultdict
import sqlite3, glob, os, re import sqlite3, glob, os, re
app = Flask(__name__) app = Flask(__name__)
@@ -105,8 +104,9 @@ def get_last_seen(dev_name: str):
continue continue
if latest_time: if latest_time:
datetime_str = latest_time.strftime("Zuletzt Online am %d.%m.%Y um %H:%M Uhr") date_str = latest_time.strftime("Zuletzt Online am %d.%m.%Y")
return f"{datetime_str}" time_str = latest_time.strftime("um %H:%M Uhr")
return f"{date_str}\n{time_str}"
return None return None
@@ -119,13 +119,6 @@ def index():
c.execute("SELECT mac, name, is_active FROM devices ORDER BY name ASC") c.execute("SELECT mac, name, is_active FROM devices ORDER BY name ASC")
devices = c.fetchall() devices = c.fetchall()
devices = sorted(devices, key=lambda d: d[1][0].upper())
grouped_devices = defaultdict(list)
for d in devices:
first_letter = d[1][:2].upper()
grouped_devices[first_letter].append(d)
# Intervall aus DB laden # Intervall aus DB laden
c.execute("SELECT value FROM settings WHERE key='interval'") c.execute("SELECT value FROM settings WHERE key='interval'")
row = c.fetchone() row = c.fetchone()
@@ -159,7 +152,7 @@ def index():
else: else:
status_dict[dev[0]] = "unbekannt" status_dict[dev[0]] = "unbekannt"
return render_template("index.html", grouped_devices=grouped_devices, devices=devices, status=status_dict, last_seen=last_seen_dict, interval=interval) return render_template("index.html", devices=devices, status=status_dict, last_seen=last_seen_dict, interval=interval)
@app.route("/settings", methods=["GET", "POST"]) @app.route("/settings", methods=["GET", "POST"])
@login_required @login_required

Binary file not shown.

View File

@@ -87,33 +87,25 @@ pre {
#log-container { #log-container {
position: relative; position: relative;
height: calc(100vh - 252px); /* Füllt die Seite minus Header */ height: calc(100vh - 150px); /* Füllt die Seite minus Header */
padding: 1rem; /* optional, Abstand innen */
box-sizing: border-box; /* damit Padding nicht die Höhe sprengt */
display: flex;
flex-direction: column;
} }
#log-box { #log-box {
flex: 1 1 auto; /* füllt den Container, berücksichtigt Header/Padding */ height: 97%;
overflow: auto; overflow: auto;
white-space: pre-wrap; white-space: pre-wrap;
font-family: monospace; font-family: monospace;
border: 1px solid #dee2e6; border: 1px solid #dee2e6; /* Bootstrap-like border */
padding: 1rem;
background-color: #f8f9fa; background-color: #f8f9fa;
padding: 0.5rem;
} }
#refresh-timer { #refresh-timer {
position: absolute; position: absolute;
bottom: 18px; bottom: 10px;
right: 30px; right: 10px;
font-size: 0.9em; font-size: 0.9em;
color: gray; color: gray;
background-color: rgba(255,255,255,0.7); /* optional, besser lesbar */
padding: 2px 4px;
border-radius: 3px;
pointer-events: none; /* damit Scrollbar nicht blockiert wird */
} }
/* Tabelle anpassen */ /* Tabelle anpassen */

View File

@@ -8,7 +8,7 @@
<button class="btn btn-success mb-3" data-bs-toggle="modal" data-bs-target="#deviceModal" onclick="openDeviceModal()">Neues Gerät hinzufügen</button> <button class="btn btn-success mb-3" data-bs-toggle="modal" data-bs-target="#deviceModal" onclick="openDeviceModal()">Neues Gerät hinzufügen</button>
{% endif %} {% endif %}
<table class="table table-striped"> <table class="table table-bordered">
<thead> <thead>
<tr> <tr>
<th>Hostname</th> <th>Hostname</th>

View File

@@ -7,17 +7,11 @@
Nächste Prüfung in -- Sekunden Nächste Prüfung in -- Sekunden
</span> </span>
</h2> </h2>
<div class="row g-3"> <div class="row row-cols-1 row-cols-md-6 g-3">
{% for letter, group in grouped_devices.items() %} {% for d in devices %}
<div class="row g-3"> <div class="col">
{% for d in group %}
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
<div class="card text-center p-2" <div class="card text-center p-2"
{% if last_seen.get(d[0]) %} {% if last_seen[d[0]] %} title="{{ last_seen[d[0]][0] }}&#10;{{ last_seen[d[0]][1] }}" {% elif status[d[0]] == 'offline' %} title="Noch nie online" {% endif %}>
title="{{ last_seen[d[0]] }}"
{% elif status[d[0]] == 'offline' %}
title="Noch nie online"
{% endif %}>
<div class="card-header">{{ d[1] }}</div> <div class="card-header">{{ d[1] }}</div>
<div class="card-body"> <div class="card-body">
<span class="fw-bold" style="color: <span class="fw-bold" style="color:
@@ -36,8 +30,6 @@
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% endfor %}
</div>
<script> <script>
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
const intervalMinutes = {{ interval | int }}; // aus DB const intervalMinutes = {{ interval | int }}; // aus DB

View File

@@ -5,7 +5,7 @@
<!-- Button zum Hinzufügen --> <!-- Button zum Hinzufügen -->
<button class="btn btn-success mb-3" data-bs-toggle="modal" data-bs-target="#addSwitchModal">Neuen Switch hinzufügen</button> <button class="btn btn-success mb-3" data-bs-toggle="modal" data-bs-target="#addSwitchModal">Neuen Switch hinzufügen</button>
<table class="table table-striped"> <table class="table table-bordered">
<thead> <thead>
<tr> <tr>
<th>Hostname</th> <th>Hostname</th>

View File

@@ -8,7 +8,7 @@
<button class="btn btn-success mb-3" data-bs-toggle="modal" data-bs-target="#userModal" onclick="openUserModal()">Neuen Benutzer</button> <button class="btn btn-success mb-3" data-bs-toggle="modal" data-bs-target="#userModal" onclick="openUserModal()">Neuen Benutzer</button>
{% endif %} {% endif %}
<table class="table table-striped"> <table class="table table-bordered">
<thead> <thead>
<tr> <tr>
<th class="col-ip">Username</th> <th class="col-ip">Username</th>

View File

@@ -87,26 +87,15 @@ EOF
echo "" > "$LOGFILE" echo "" > "$LOGFILE"
MAX_PARALLEL=10 # maximal gleichzeitig laufende Geräte
while true; do while true; do
echo "--------------------------------------------------------------------" >> "$LOGFILE" echo "--------------------------------------------------------------------" >> "$LOGFILE"
python3 /srv/poe_manager/generate_ips.py | while IFS=: read -r rpi_ip dev_name switch_ip switch_hostname switch_port switch_user switch_pass; do python3 /srv/poe_manager/generate_ips.py | while IFS=: read -r rpi_ip dev_name switch_ip switch_hostname switch_port switch_user switch_pass; do
# Funktion für ein Gerät if ping -c 1 -W 2 "$rpi_ip" &> /dev/null; then
check_device() {
local rpi_ip="$1"
local dev_name="$2"
local switch_ip="$3"
local switch_hostname="$4"
local switch_port="$5"
local switch_user="$6"
local switch_pass="$7"
if ping -c 4 -W 1 "$rpi_ip" &> /dev/null; then
echo "$(date '+%Y-%m-%d %H:%M:%S') $dev_name ist erreichbar!" >> "$LOGFILE" echo "$(date '+%Y-%m-%d %H:%M:%S') $dev_name ist erreichbar!" >> "$LOGFILE"
else else
echo "$(date '+%Y-%m-%d %H:%M:%S') $dev_name ist nicht erreichbar!" >> "$LOGFILE" echo "$(date '+%Y-%m-%d %H:%M:%S') $dev_name ist nicht erreichbar!" >> "$LOGFILE"
# Nur PoE neu starten, wenn Port vorhanden ist
if [ -n "$switch_port" ] && [ "$switch_port" != "None" ]; then if [ -n "$switch_port" ] && [ "$switch_port" != "None" ]; then
disable_poe "$switch_ip" "$switch_port" "$switch_user" "$switch_pass" disable_poe "$switch_ip" "$switch_port" "$switch_user" "$switch_pass"
echo "$(date '+%Y-%m-%d %H:%M:%S') $dev_name PoE auf Port $switch_port am Switch $switch_hostname deaktiviert." >> "$LOGFILE" echo "$(date '+%Y-%m-%d %H:%M:%S') $dev_name PoE auf Port $switch_port am Switch $switch_hostname deaktiviert." >> "$LOGFILE"
@@ -115,17 +104,6 @@ while true; do
echo "$(date '+%Y-%m-%d %H:%M:%S') $dev_name PoE auf Port $switch_port am Switch $switch_hostname aktiviert." >> "$LOGFILE" echo "$(date '+%Y-%m-%d %H:%M:%S') $dev_name PoE auf Port $switch_port am Switch $switch_hostname aktiviert." >> "$LOGFILE"
fi fi
fi fi
}
# Job in Hintergrund starten
check_device "$rpi_ip" "$dev_name" "$switch_ip" "$switch_hostname" "$switch_port" "$switch_user" "$switch_pass" &
# Limit auf MAX_PARALLEL Jobs
while [ "$(jobs -rp | wc -l)" -ge "$MAX_PARALLEL" ]; do
sleep 0.2
done done
done
wait # alle Hintergrundjobs beenden, bevor sleep
sleep "$SLEEP" sleep "$SLEEP"
done done