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():
|
||||
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("""
|
||||
SELECT u.azure_id, u.display_name, u.personal_nr,
|
||||
a.segment, d.hostname,
|
||||
@ -112,64 +112,69 @@ def _process_user(user, aida_lines, settings, conn):
|
||||
last_aida = user["last_aida_status"] or ""
|
||||
last_teams = user["last_teams_status"] or ""
|
||||
|
||||
# Determine AIDA status (kann None sein wenn keine CSV oder keine Personalnr)
|
||||
aida_status = determine_aida_status(aida_lines, personal_nr, settings)
|
||||
|
||||
# Immer Teams-Status abfragen
|
||||
# Immer Teams-Status abfragen (fuer Dashboard-Anzeige)
|
||||
teams_status = ""
|
||||
presence = graph.get_presence(azure_id)
|
||||
if presence and "activity" in presence:
|
||||
teams_status = "teams_" + presence["activity"].lower()
|
||||
|
||||
# Wenn AIDA nicht verfuegbar, nur Teams-Status nutzen
|
||||
if aida_status is None:
|
||||
aida_status = "anwesend" # Default: anwesend wenn AIDA nicht verfuegbar
|
||||
# AIDA-Status ermitteln
|
||||
aida_status = determine_aida_status(aida_lines, personal_nr, settings)
|
||||
|
||||
# Check if status changed
|
||||
# Check if anything changed
|
||||
if aida_status == last_aida and teams_status == last_teams:
|
||||
return # No change
|
||||
|
||||
# Determine color
|
||||
if aida_status == "abwesend":
|
||||
color = get_color_for_status("abwesend", conn)
|
||||
elif aida_status == "homeoffice":
|
||||
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", "")
|
||||
# --- WLED nur steuern wenn AIDA-Status bekannt ---
|
||||
wled_changed = aida_status is not None and (
|
||||
aida_status != last_aida or
|
||||
(aida_status == "anwesend" and teams_status != last_teams)
|
||||
)
|
||||
success, result_text = call_wled(url)
|
||||
|
||||
if success:
|
||||
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, teams_status, datetime.now(),
|
||||
aida_status, teams_status, datetime.now(),
|
||||
))
|
||||
conn.commit()
|
||||
logger.info(
|
||||
"%-40s aida=%-12s teams=%-20s -> %s",
|
||||
display_name, aida_status, teams_status, result_text,
|
||||
if wled_changed:
|
||||
# Farbe bestimmen nach Originallogik:
|
||||
# abwesend -> abwesend-Farbe
|
||||
# homeoffice -> homeoffice-Farbe
|
||||
# anwesend -> Teams-Farbe
|
||||
if aida_status == "abwesend":
|
||||
color = get_color_for_status("abwesend", conn)
|
||||
elif aida_status == "homeoffice":
|
||||
color = get_color_for_status("homeoffice", conn)
|
||||
elif aida_status == "anwesend" and teams_status:
|
||||
color = get_color_for_status(teams_status, conn)
|
||||
else:
|
||||
color = get_color_for_status("available", conn)
|
||||
|
||||
url = build_wled_url(
|
||||
hostname, color["r"], color["g"], color["b"],
|
||||
segment=segment, effect=color.get("effect", "")
|
||||
)
|
||||
else:
|
||||
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()
|
||||
success, result_text = call_wled(url)
|
||||
|
||||
log_activity(
|
||||
azure_id, display_name, aida_status, teams_status, url, result_text
|
||||
if not success:
|
||||
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">
|
||||
<small class="text-muted d-block mb-1">Segment {{ seg.index }}</small>
|
||||
{% if seg.user %}
|
||||
{% if seg.aida == '-' %}
|
||||
<div class="segment-bar" style="background: #f0f0f0; border-color: #ccc;">
|
||||
<span class="status-dot me-2" style="background: #ccc;"></span>
|
||||
{{ seg.user }}
|
||||
</div>
|
||||
<small class="text-muted"><i class="bi bi-hourglass-split"></i> Warte auf Status...</small>
|
||||
{% 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 }});">
|
||||
<span class="status-dot me-2" style="background: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});"></span>
|
||||
{{ seg.user }}
|
||||
</div>
|
||||
<small class="text-muted">{{ seg.aida }} / {{ seg.teams }}</small>
|
||||
{% endif %}
|
||||
{% if seg.aida == '-' and seg.teams == '-' %}
|
||||
<div class="segment-bar" style="background: #f0f0f0; border-color: #ccc;">
|
||||
<span class="status-dot me-2" style="background: #ccc;"></span>
|
||||
{{ seg.user }}
|
||||
</div>
|
||||
<small class="text-muted"><i class="bi bi-hourglass-split"></i> Warte auf Status...</small>
|
||||
{% 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 }});">
|
||||
<span class="status-dot me-2" style="background: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});"></span>
|
||||
{{ seg.user }}
|
||||
</div>
|
||||
<div class="d-flex gap-2 mt-1">
|
||||
{% 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 %}
|
||||
<div class="segment-bar empty">
|
||||
<i class="bi bi-dash-circle me-2"></i> Nicht zugeordnet
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user