busylight_modular/migrate.py
Christian Mueller 63d8ee3e99 fix: use cp1252 encoding for config.cfg (Windows umlauts)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 21:11:19 +02:00

149 lines
5.4 KiB
Python

#!/usr/bin/env python3
"""Migrate old config.cfg to SQLite database."""
import re
import sys
from configparser import ConfigParser
from database import init_db, get_db, set_setting
def parse_color(value):
"""Parse 'R=255&G=0&B=0' or '/win&A=255&R=200&G=200&B=200' into (r, g, b, effect)."""
effect = ""
# Extract effect prefix (e.g., /win&A=255)
if value.startswith("/"):
parts = value.split("&R=")
if len(parts) == 2:
effect = parts[0]
value = "R=" + parts[1]
r = g = b = 0
for part in value.replace("&", " ").split():
if part.startswith("R="):
r = int(part[2:])
elif part.startswith("G="):
g = int(part[2:])
elif part.startswith("B="):
b = int(part[2:])
return r, g, b, effect
def migrate(config_path="config.cfg"):
"""Import old config.cfg into the SQLite database."""
config = ConfigParser()
config.read(config_path, encoding="cp1252")
init_db()
conn = get_db()
# Azure settings
if config.has_section("azure"):
az = config["azure"]
set_setting("azure_client_id", az.get("clientid", ""))
set_setting("azure_client_secret", az.get("clientsecret", ""))
set_setting("azure_tenant_id", az.get("tenantid", ""))
set_setting("azure_auth_tenant", az.get("authtenant", "common"))
set_setting("azure_scopes", az.get("graphuserscopes", ""))
# Auth record
if config.has_option("cred", "value"):
set_setting("azure_auth_record", config["cred"]["value"])
# Config settings
if config.has_section("config"):
cfg = config["config"]
set_setting("poll_interval", cfg.get("intervall", "15"))
set_setting("aida_csv_path", cfg.get("anwesenheit_csv", ""))
set_setting("aida_status_anwesend", cfg.get("anwesenheit_anwesend", "~~1~~"))
set_setting("aida_status_abwesend", cfg.get("anwesenheit_abwesend", "~~0~~"))
set_setting("aida_status_homeoffice", cfg.get("anwesenheit_homeoffice", "~~2~~"))
# WLED color rules
if config.has_section("wled"):
for status, value in config["wled"].items():
r, g, b, effect = parse_color(value)
conn.execute(
"""INSERT OR REPLACE INTO color_rules (status, r, g, b, effect)
VALUES (?, ?, ?, ?, ?)""",
(status, r, g, b, effect),
)
# Users and WLED devices
devices = {} # hostname -> device_id
if config.has_section("user"):
for azure_id, entry in config["user"].items():
parts = entry.split(" - ", 1)
hostname = parts[0].strip()
display_name = parts[1].strip() if len(parts) > 1 else ""
# Get personal number from anwesenheit section
personal_nr = ""
if config.has_option("anwesenheit", azure_id):
anw_val = config["anwesenheit"][azure_id].split()[0]
personal_nr = anw_val
# Determine if user is active (has a known hostname)
is_active = 0 if hostname == "unbekannt" else 1
conn.execute(
"""INSERT OR REPLACE INTO users (azure_id, display_name, personal_nr, active)
VALUES (?, ?, ?, ?)""",
(azure_id, display_name, personal_nr, is_active),
)
# Create WLED device if hostname is known
if hostname != "unbekannt" and hostname not in devices:
conn.execute(
"INSERT OR IGNORE INTO wled_devices (hostname, name, segment_count) VALUES (?, ?, 2)",
(hostname, hostname),
)
row = conn.execute(
"SELECT id FROM wled_devices WHERE hostname = ?", (hostname,)
).fetchone()
if row:
devices[hostname] = row["id"]
# Segment assignments
if config.has_section("segment"):
for azure_id, entry in config["segment"].items():
parts = entry.split()
seg_str = parts[0] if parts else "-"
if seg_str == "-":
continue
try:
segment = int(seg_str)
except ValueError:
continue
# Find the user's hostname
if config.has_option("user", azure_id):
user_entry = config["user"][azure_id]
hostname = user_entry.split(" - ", 1)[0].strip()
if hostname in devices:
device_id = devices[hostname]
conn.execute(
"""INSERT OR REPLACE INTO assignments
(user_azure_id, wled_device_id, segment)
VALUES (?, ?, ?)""",
(azure_id, device_id, segment),
)
conn.commit()
conn.close()
print(f"Migration abgeschlossen.")
print(f" - {len(devices)} WLED-Geraete importiert")
conn = get_db()
user_count = conn.execute("SELECT COUNT(*) as c FROM users").fetchone()["c"]
active_count = conn.execute("SELECT COUNT(*) as c FROM users WHERE active=1").fetchone()["c"]
assign_count = conn.execute("SELECT COUNT(*) as c FROM assignments").fetchone()["c"]
conn.close()
print(f" - {user_count} User importiert ({active_count} aktiv)")
print(f" - {assign_count} Segment-Zuordnungen importiert")
if __name__ == "__main__":
path = sys.argv[1] if len(sys.argv) > 1 else "config.cfg"
migrate(path)