feat: show AIDA + Teams status badges in dashboard, keep original WLED logic
- WLED only controlled when AIDA status is known (original behavior: abwesend->off, homeoffice->yellow, anwesend->Teams color) - Teams presence always queried and stored for dashboard display - Dashboard shows colored badges for both AIDA and Teams status - Works without AIDA CSV (Teams status still visible in dashboard) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8d178eac6d
commit
5e9af4e268
101
scheduler.py
101
scheduler.py
@ -67,7 +67,7 @@ def poll_status():
|
|||||||
for row in conn.execute("SELECT key, value FROM settings").fetchall():
|
for row in conn.execute("SELECT key, value FROM settings").fetchall():
|
||||||
settings[row["key"]] = row["value"]
|
settings[row["key"]] = row["value"]
|
||||||
|
|
||||||
# Get all active users with assignments (auch ohne personal_nr)
|
# Get all active users with assignments
|
||||||
users_with_assignments = conn.execute("""
|
users_with_assignments = conn.execute("""
|
||||||
SELECT u.azure_id, u.display_name, u.personal_nr,
|
SELECT u.azure_id, u.display_name, u.personal_nr,
|
||||||
a.segment, d.hostname,
|
a.segment, d.hostname,
|
||||||
@ -112,64 +112,69 @@ def _process_user(user, aida_lines, settings, conn):
|
|||||||
last_aida = user["last_aida_status"] or ""
|
last_aida = user["last_aida_status"] or ""
|
||||||
last_teams = user["last_teams_status"] or ""
|
last_teams = user["last_teams_status"] or ""
|
||||||
|
|
||||||
# Determine AIDA status (kann None sein wenn keine CSV oder keine Personalnr)
|
# Immer Teams-Status abfragen (fuer Dashboard-Anzeige)
|
||||||
aida_status = determine_aida_status(aida_lines, personal_nr, settings)
|
|
||||||
|
|
||||||
# Immer Teams-Status abfragen
|
|
||||||
teams_status = ""
|
teams_status = ""
|
||||||
presence = graph.get_presence(azure_id)
|
presence = graph.get_presence(azure_id)
|
||||||
if presence and "activity" in presence:
|
if presence and "activity" in presence:
|
||||||
teams_status = "teams_" + presence["activity"].lower()
|
teams_status = "teams_" + presence["activity"].lower()
|
||||||
|
|
||||||
# Wenn AIDA nicht verfuegbar, nur Teams-Status nutzen
|
# AIDA-Status ermitteln
|
||||||
if aida_status is None:
|
aida_status = determine_aida_status(aida_lines, personal_nr, settings)
|
||||||
aida_status = "anwesend" # Default: anwesend wenn AIDA nicht verfuegbar
|
|
||||||
|
|
||||||
# Check if status changed
|
# Check if anything changed
|
||||||
if aida_status == last_aida and teams_status == last_teams:
|
if aida_status == last_aida and teams_status == last_teams:
|
||||||
return # No change
|
return # No change
|
||||||
|
|
||||||
# Determine color
|
# --- WLED nur steuern wenn AIDA-Status bekannt ---
|
||||||
if aida_status == "abwesend":
|
wled_changed = aida_status is not None and (
|
||||||
color = get_color_for_status("abwesend", conn)
|
aida_status != last_aida or
|
||||||
elif aida_status == "homeoffice":
|
(aida_status == "anwesend" and teams_status != last_teams)
|
||||||
color = get_color_for_status("homeoffice", conn)
|
|
||||||
elif teams_status:
|
|
||||||
color = get_color_for_status(teams_status, conn)
|
|
||||||
else:
|
|
||||||
color = get_color_for_status("available", conn)
|
|
||||||
|
|
||||||
# Build URL and call WLED
|
|
||||||
url = build_wled_url(
|
|
||||||
hostname, color["r"], color["g"], color["b"],
|
|
||||||
segment=segment, effect=color.get("effect", "")
|
|
||||||
)
|
)
|
||||||
success, result_text = call_wled(url)
|
|
||||||
|
|
||||||
if success:
|
if wled_changed:
|
||||||
conn.execute("""
|
# Farbe bestimmen nach Originallogik:
|
||||||
INSERT INTO state (user_azure_id, last_aida_status, last_teams_status, updated_at)
|
# abwesend -> abwesend-Farbe
|
||||||
VALUES (?, ?, ?, ?)
|
# homeoffice -> homeoffice-Farbe
|
||||||
ON CONFLICT(user_azure_id)
|
# anwesend -> Teams-Farbe
|
||||||
DO UPDATE SET last_aida_status=?, last_teams_status=?, updated_at=?
|
if aida_status == "abwesend":
|
||||||
""", (
|
color = get_color_for_status("abwesend", conn)
|
||||||
azure_id, aida_status, teams_status, datetime.now(),
|
elif aida_status == "homeoffice":
|
||||||
aida_status, teams_status, datetime.now(),
|
color = get_color_for_status("homeoffice", conn)
|
||||||
))
|
elif aida_status == "anwesend" and teams_status:
|
||||||
conn.commit()
|
color = get_color_for_status(teams_status, conn)
|
||||||
logger.info(
|
else:
|
||||||
"%-40s aida=%-12s teams=%-20s -> %s",
|
color = get_color_for_status("available", conn)
|
||||||
display_name, aida_status, teams_status, result_text,
|
|
||||||
|
url = build_wled_url(
|
||||||
|
hostname, color["r"], color["g"], color["b"],
|
||||||
|
segment=segment, effect=color.get("effect", "")
|
||||||
)
|
)
|
||||||
else:
|
success, result_text = call_wled(url)
|
||||||
conn.execute("""
|
|
||||||
INSERT INTO state (user_azure_id, last_aida_status, last_teams_status, updated_at)
|
|
||||||
VALUES (?, '', '', ?)
|
|
||||||
ON CONFLICT(user_azure_id)
|
|
||||||
DO UPDATE SET last_aida_status='', last_teams_status='', updated_at=?
|
|
||||||
""", (azure_id, datetime.now(), datetime.now()))
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
log_activity(
|
if not success:
|
||||||
azure_id, display_name, aida_status, teams_status, url, result_text
|
logger.warning("WLED Fehler fuer %s: %s", display_name, result_text)
|
||||||
|
|
||||||
|
log_activity(
|
||||||
|
azure_id, display_name,
|
||||||
|
aida_status or "-", teams_status or "-",
|
||||||
|
url, result_text,
|
||||||
|
)
|
||||||
|
|
||||||
|
# State immer aktualisieren (fuer Dashboard)
|
||||||
|
conn.execute("""
|
||||||
|
INSERT INTO state (user_azure_id, last_aida_status, last_teams_status, updated_at)
|
||||||
|
VALUES (?, ?, ?, ?)
|
||||||
|
ON CONFLICT(user_azure_id)
|
||||||
|
DO UPDATE SET last_aida_status=?, last_teams_status=?, updated_at=?
|
||||||
|
""", (
|
||||||
|
azure_id,
|
||||||
|
aida_status or last_aida, teams_status, datetime.now(),
|
||||||
|
aida_status or last_aida, teams_status, datetime.now(),
|
||||||
|
))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"%-40s aida=%-12s teams=%-20s wled=%s",
|
||||||
|
display_name, aida_status or "-", teams_status,
|
||||||
|
"aktualisiert" if wled_changed else "nur Dashboard",
|
||||||
)
|
)
|
||||||
|
|||||||
@ -38,19 +38,51 @@
|
|||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<small class="text-muted d-block mb-1">Segment {{ seg.index }}</small>
|
<small class="text-muted d-block mb-1">Segment {{ seg.index }}</small>
|
||||||
{% if seg.user %}
|
{% if seg.user %}
|
||||||
{% if seg.aida == '-' %}
|
{% if seg.aida == '-' and seg.teams == '-' %}
|
||||||
<div class="segment-bar" style="background: #f0f0f0; border-color: #ccc;">
|
<div class="segment-bar" style="background: #f0f0f0; border-color: #ccc;">
|
||||||
<span class="status-dot me-2" style="background: #ccc;"></span>
|
<span class="status-dot me-2" style="background: #ccc;"></span>
|
||||||
{{ seg.user }}
|
{{ seg.user }}
|
||||||
</div>
|
</div>
|
||||||
<small class="text-muted"><i class="bi bi-hourglass-split"></i> Warte auf Status...</small>
|
<small class="text-muted"><i class="bi bi-hourglass-split"></i> Warte auf Status...</small>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="segment-bar" style="background: rgba({{ seg.r }}, {{ seg.g }}, {{ seg.b }}, 0.3); border-color: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});">
|
<div class="segment-bar" style="background: rgba({{ seg.r }}, {{ seg.g }}, {{ seg.b }}, 0.3); border-color: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});">
|
||||||
<span class="status-dot me-2" style="background: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});"></span>
|
<span class="status-dot me-2" style="background: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});"></span>
|
||||||
{{ seg.user }}
|
{{ seg.user }}
|
||||||
</div>
|
</div>
|
||||||
<small class="text-muted">{{ seg.aida }} / {{ seg.teams }}</small>
|
<div class="d-flex gap-2 mt-1">
|
||||||
{% endif %}
|
{% if seg.aida == 'anwesend' %}
|
||||||
|
<span class="badge bg-success"><i class="bi bi-building"></i> Anwesend</span>
|
||||||
|
{% elif seg.aida == 'abwesend' %}
|
||||||
|
<span class="badge bg-secondary"><i class="bi bi-door-open"></i> Abwesend</span>
|
||||||
|
{% elif seg.aida == 'homeoffice' %}
|
||||||
|
<span class="badge bg-warning text-dark"><i class="bi bi-house"></i> Homeoffice</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-light text-dark">{{ seg.aida }}</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if seg.teams != '-' %}
|
||||||
|
{% if 'available' in seg.teams %}
|
||||||
|
<span class="badge bg-success"><i class="bi bi-microsoft-teams"></i> Verfuegbar</span>
|
||||||
|
{% elif 'busy' in seg.teams or 'inacall' in seg.teams or 'inameeting' in seg.teams %}
|
||||||
|
<span class="badge bg-danger"><i class="bi bi-microsoft-teams"></i> Beschaeftigt</span>
|
||||||
|
{% elif 'donotdisturb' in seg.teams %}
|
||||||
|
<span class="badge" style="background:#8b00ff;color:#fff"><i class="bi bi-microsoft-teams"></i> Nicht stoeren</span>
|
||||||
|
{% elif 'away' in seg.teams or 'berightback' in seg.teams %}
|
||||||
|
<span class="badge bg-warning text-dark"><i class="bi bi-microsoft-teams"></i> Abwesend</span>
|
||||||
|
{% elif 'offline' in seg.teams %}
|
||||||
|
<span class="badge bg-secondary"><i class="bi bi-microsoft-teams"></i> Offline</span>
|
||||||
|
{% elif 'presenting' in seg.teams %}
|
||||||
|
<span class="badge bg-danger"><i class="bi bi-microsoft-teams"></i> Praesentiert</span>
|
||||||
|
{% elif 'outofoffice' in seg.teams %}
|
||||||
|
<span class="badge bg-secondary"><i class="bi bi-microsoft-teams"></i> Nicht im Buero</span>
|
||||||
|
{% elif 'inactive' in seg.teams or 'offwork' in seg.teams %}
|
||||||
|
<span class="badge bg-secondary"><i class="bi bi-microsoft-teams"></i> Inaktiv</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-light text-dark"><i class="bi bi-microsoft-teams"></i> {{ seg.teams }}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="segment-bar empty">
|
<div class="segment-bar empty">
|
||||||
<i class="bi bi-dash-circle me-2"></i> Nicht zugeordnet
|
<i class="bi bi-dash-circle me-2"></i> Nicht zugeordnet
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user