feat: poll Teams presence independently of AIDA CSV
- Teams status is now always queried, even without AIDA CSV - Users without personal_nr are also polled (Teams-only mode) - If AIDA is unavailable, default to 'anwesend' and use Teams color - Dashboard will now show Teams status even without SMB mount Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ce19dec8c1
commit
8d178eac6d
41
scheduler.py
41
scheduler.py
@ -12,10 +12,9 @@ graph = None
|
|||||||
|
|
||||||
|
|
||||||
def read_aida_csv(csv_path):
|
def read_aida_csv(csv_path):
|
||||||
"""Read AIDA status CSV. Returns dict: personal_nr -> line content."""
|
"""Read AIDA status CSV. Returns list of lines."""
|
||||||
if not csv_path or not os.path.exists(csv_path):
|
if not csv_path or not os.path.exists(csv_path):
|
||||||
logger.warning("AIDA CSV nicht gefunden: %s", csv_path)
|
return []
|
||||||
return {}
|
|
||||||
try:
|
try:
|
||||||
with open(csv_path, "r", encoding="utf-8", errors="replace") as f:
|
with open(csv_path, "r", encoding="utf-8", errors="replace") as f:
|
||||||
lines = f.read().splitlines()
|
lines = f.read().splitlines()
|
||||||
@ -35,11 +34,11 @@ def determine_aida_status(lines, personal_nr, settings):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
line = matching[0]
|
line = matching[0]
|
||||||
if line.endswith(settings["aida_status_abwesend"]):
|
if line.endswith(settings.get("aida_status_abwesend", "~~0~~")):
|
||||||
return "abwesend"
|
return "abwesend"
|
||||||
if line.endswith(settings["aida_status_anwesend"]):
|
if line.endswith(settings.get("aida_status_anwesend", "~~1~~")):
|
||||||
return "anwesend"
|
return "anwesend"
|
||||||
if line.endswith(settings["aida_status_homeoffice"]):
|
if line.endswith(settings.get("aida_status_homeoffice", "~~2~~")):
|
||||||
return "homeoffice"
|
return "homeoffice"
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -68,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
|
# Get all active users with assignments (auch ohne personal_nr)
|
||||||
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,
|
||||||
@ -77,14 +76,14 @@ def poll_status():
|
|||||||
JOIN assignments a ON a.user_azure_id = u.azure_id
|
JOIN assignments a ON a.user_azure_id = u.azure_id
|
||||||
JOIN wled_devices d ON d.id = a.wled_device_id
|
JOIN wled_devices d ON d.id = a.wled_device_id
|
||||||
LEFT JOIN state s ON s.user_azure_id = u.azure_id
|
LEFT JOIN state s ON s.user_azure_id = u.azure_id
|
||||||
WHERE u.active = 1 AND u.personal_nr != ''
|
WHERE u.active = 1
|
||||||
""").fetchall()
|
""").fetchall()
|
||||||
|
|
||||||
if not users_with_assignments:
|
if not users_with_assignments:
|
||||||
logger.debug("Keine aktiven User mit Zuordnungen gefunden")
|
logger.debug("Keine aktiven User mit Zuordnungen gefunden")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Read AIDA CSV
|
# Read AIDA CSV (kann leer sein)
|
||||||
aida_lines = read_aida_csv(settings.get("aida_csv_path", ""))
|
aida_lines = read_aida_csv(settings.get("aida_csv_path", ""))
|
||||||
|
|
||||||
for user in users_with_assignments:
|
for user in users_with_assignments:
|
||||||
@ -113,24 +112,21 @@ 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
|
# Determine AIDA status (kann None sein wenn keine CSV oder keine Personalnr)
|
||||||
aida_status = determine_aida_status(aida_lines, personal_nr, settings)
|
aida_status = determine_aida_status(aida_lines, personal_nr, settings)
|
||||||
if aida_status is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Determine Teams status
|
# Immer Teams-Status abfragen
|
||||||
teams_status = ""
|
teams_status = ""
|
||||||
if aida_status == "anwesend":
|
|
||||||
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
|
||||||
|
if aida_status is None:
|
||||||
|
aida_status = "anwesend" # Default: anwesend wenn AIDA nicht verfuegbar
|
||||||
|
|
||||||
# Check if status changed
|
# Check if status changed
|
||||||
if aida_status == last_aida:
|
if aida_status == last_aida and teams_status == last_teams:
|
||||||
if aida_status == "anwesend":
|
|
||||||
if teams_status == last_teams:
|
|
||||||
return # No change
|
|
||||||
else:
|
|
||||||
return # No change
|
return # No change
|
||||||
|
|
||||||
# Determine color
|
# Determine color
|
||||||
@ -138,10 +134,8 @@ def _process_user(user, aida_lines, settings, conn):
|
|||||||
color = get_color_for_status("abwesend", conn)
|
color = get_color_for_status("abwesend", conn)
|
||||||
elif aida_status == "homeoffice":
|
elif aida_status == "homeoffice":
|
||||||
color = get_color_for_status("homeoffice", conn)
|
color = get_color_for_status("homeoffice", conn)
|
||||||
elif aida_status == "anwesend" and teams_status:
|
elif teams_status:
|
||||||
color = get_color_for_status(teams_status, conn)
|
color = get_color_for_status(teams_status, conn)
|
||||||
if not color:
|
|
||||||
color = get_color_for_status("teams_available", conn)
|
|
||||||
else:
|
else:
|
||||||
color = get_color_for_status("available", conn)
|
color = get_color_for_status("available", conn)
|
||||||
|
|
||||||
@ -153,7 +147,6 @@ def _process_user(user, aida_lines, settings, conn):
|
|||||||
success, result_text = call_wled(url)
|
success, result_text = call_wled(url)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
# Update state
|
|
||||||
conn.execute("""
|
conn.execute("""
|
||||||
INSERT INTO state (user_azure_id, last_aida_status, last_teams_status, updated_at)
|
INSERT INTO state (user_azure_id, last_aida_status, last_teams_status, updated_at)
|
||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
@ -169,7 +162,6 @@ def _process_user(user, aida_lines, settings, conn):
|
|||||||
display_name, aida_status, teams_status, result_text,
|
display_name, aida_status, teams_status, result_text,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Reset state on failure
|
|
||||||
conn.execute("""
|
conn.execute("""
|
||||||
INSERT INTO state (user_azure_id, last_aida_status, last_teams_status, updated_at)
|
INSERT INTO state (user_azure_id, last_aida_status, last_teams_status, updated_at)
|
||||||
VALUES (?, '', '', ?)
|
VALUES (?, '', '', ?)
|
||||||
@ -178,7 +170,6 @@ def _process_user(user, aida_lines, settings, conn):
|
|||||||
""", (azure_id, datetime.now(), datetime.now()))
|
""", (azure_id, datetime.now(), datetime.now()))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
# Log activity
|
|
||||||
log_activity(
|
log_activity(
|
||||||
azure_id, display_name, aida_status, teams_status, url, result_text
|
azure_id, display_name, aida_status, teams_status, url, result_text
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user