refactor: rename project to LedGrab, split HA integration into separate repo
Lint & Test / test (push) Successful in 1m56s

- Rename Python package: wled_controller -> ledgrab
- Rename env var prefix: WLED_ -> LEDGRAB_ (with auto-migration for old vars)
- Rename localStorage key: wled_api_key -> ledgrab_api_key (with migration)
- Rename HA integration domain: wled_screen_controller -> ledgrab
- Update all imports, build scripts, Docker, installer, config, docs
- Remove HA integration (moved to ledgrab-haos-integration repo)
- Remove hacs.json (belongs in HA repo now)
- Add startup warning for users with old WLED_ env vars
- All tests pass (715/715), ruff clean, tsc clean, frontend builds
This commit is contained in:
2026-04-12 22:45:28 +03:00
parent 38f73badbf
commit 02cd9d519c
548 changed files with 3502 additions and 5180 deletions
+3 -3
View File
@@ -4,9 +4,9 @@ from typing import Any
import pytest
from wled_controller.core.game_integration.adapter_registry import AdapterRegistry
from wled_controller.core.game_integration.base_adapter import GameAdapter
from wled_controller.core.game_integration.events import GameEvent
from ledgrab.core.game_integration.adapter_registry import AdapterRegistry
from ledgrab.core.game_integration.base_adapter import GameAdapter
from ledgrab.core.game_integration.events import GameEvent
class FakeAdapter(GameAdapter):
+6 -6
View File
@@ -3,15 +3,15 @@
import numpy as np
import pytest
from wled_controller.core.audio.analysis import NUM_BANDS, AudioAnalysis
from wled_controller.core.audio.filters.base import AudioFilter
from wled_controller.core.audio.filters.pipeline import AudioFilterPipeline
from wled_controller.core.audio.filters.registry import AudioFilterRegistry
from ledgrab.core.audio.analysis import NUM_BANDS, AudioAnalysis
from ledgrab.core.audio.filters.base import AudioFilter
from ledgrab.core.audio.filters.pipeline import AudioFilterPipeline
from ledgrab.core.audio.filters.registry import AudioFilterRegistry
# Import the package to trigger auto-registration of all built-in filters
import wled_controller.core.audio.filters # noqa: F401
import ledgrab.core.audio.filters # noqa: F401
from wled_controller.core.filters.filter_instance import FilterInstance
from ledgrab.core.filters.filter_instance import FilterInstance
# ---------------------------------------------------------------------------
+4 -4
View File
@@ -5,8 +5,8 @@ from unittest.mock import MagicMock, patch
import pytest
from wled_controller.core.automations.automation_engine import AutomationEngine
from wled_controller.storage.automation import (
from ledgrab.core.automations.automation_engine import AutomationEngine
from ledgrab.storage.automation import (
ApplicationRule,
Automation,
DisplayStateRule,
@@ -15,7 +15,7 @@ from wled_controller.storage.automation import (
TimeOfDayRule,
WebhookRule,
)
from wled_controller.storage.automation_store import AutomationStore
from ledgrab.storage.automation_store import AutomationStore
# ---------------------------------------------------------------------------
@@ -43,7 +43,7 @@ def engine(mock_store, mock_manager) -> AutomationEngine:
causes access violations in the test environment, so we replace it
with a simple MagicMock.
"""
with patch("wled_controller.core.automations.automation_engine.PlatformDetector"):
with patch("ledgrab.core.automations.automation_engine.PlatformDetector"):
eng = AutomationEngine(
automation_store=mock_store,
processor_manager=mock_manager,
@@ -5,7 +5,7 @@ from pathlib import Path
import pytest
from wled_controller.core.game_integration.community_loader import (
from ledgrab.core.game_integration.community_loader import (
clear_community_adapters,
get_community_adapter,
get_community_adapter_info,
@@ -213,11 +213,7 @@ class TestBuiltInYamlFiles:
def test_load_bundled_adapters(self) -> None:
"""Load the built-in game_adapters directory."""
bundled_dir = (
Path(__file__).parent.parent.parent
/ "src"
/ "wled_controller"
/ "data"
/ "game_adapters"
Path(__file__).parent.parent.parent / "src" / "ledgrab" / "data" / "game_adapters"
)
if not bundled_dir.exists():
pytest.skip("Bundled adapter directory not found")
@@ -232,11 +228,7 @@ class TestBuiltInYamlFiles:
def test_minecraft_adapter_parses(self) -> None:
"""Test that the Minecraft community adapter can parse a payload."""
bundled_dir = (
Path(__file__).parent.parent.parent
/ "src"
/ "wled_controller"
/ "data"
/ "game_adapters"
Path(__file__).parent.parent.parent / "src" / "ledgrab" / "data" / "game_adapters"
)
adapters = load_community_adapters(bundled_dir)
mc = adapters.get("community_minecraft")
@@ -260,11 +252,7 @@ class TestBuiltInYamlFiles:
def test_rocket_league_adapter_parses(self) -> None:
"""Test that the Rocket League community adapter can parse a payload."""
bundled_dir = (
Path(__file__).parent.parent.parent
/ "src"
/ "wled_controller"
/ "data"
/ "game_adapters"
Path(__file__).parent.parent.parent / "src" / "ledgrab" / "data" / "game_adapters"
)
adapters = load_community_adapters(bundled_dir)
rl = adapters.get("community_rocket_league")
+1 -1
View File
@@ -2,7 +2,7 @@
import pytest
from wled_controller.core.game_integration.adapters.cs2_adapter import CS2Adapter
from ledgrab.core.game_integration.adapters.cs2_adapter import CS2Adapter
# ── Realistic CS2 GSI payload samples ────────────────────────────────────
+1 -1
View File
@@ -2,7 +2,7 @@
import pytest
from wled_controller.core.game_integration.adapters.dota2_adapter import Dota2Adapter
from ledgrab.core.game_integration.adapters.dota2_adapter import Dota2Adapter
def _make_dota2_payload(
+2 -2
View File
@@ -3,8 +3,8 @@
import threading
from wled_controller.core.game_integration.event_bus import GameEventBus
from wled_controller.core.game_integration.events import GameEvent
from ledgrab.core.game_integration.event_bus import GameEventBus
from ledgrab.core.game_integration.events import GameEvent
def _make_event(event_type: str = "health", value: float = 0.5) -> GameEvent:
+5 -5
View File
@@ -5,11 +5,11 @@ from datetime import datetime, timezone
import numpy as np
from wled_controller.core.game_integration.event_bus import GameEventBus
from wled_controller.core.game_integration.events import GameEvent
from wled_controller.core.processing.game_event_stream import GameEventColorStripStream
from wled_controller.storage.bindable import BindableColor
from wled_controller.storage.color_strip_source import (
from ledgrab.core.game_integration.event_bus import GameEventBus
from ledgrab.core.game_integration.events import GameEvent
from ledgrab.core.processing.game_event_stream import GameEventColorStripStream
from ledgrab.storage.bindable import BindableColor
from ledgrab.storage.color_strip_source import (
ColorStripSource,
GameEventColorStripSource,
)
@@ -5,10 +5,10 @@ import threading
import pytest
from wled_controller.core.game_integration.event_bus import GameEventBus
from wled_controller.core.game_integration.events import GameEvent
from wled_controller.core.value_sources.game_event_value_source import GameEventValueStream
from wled_controller.storage.value_source import (
from ledgrab.core.game_integration.event_bus import GameEventBus
from ledgrab.core.game_integration.events import GameEvent
from ledgrab.core.value_sources.game_event_value_source import GameEventValueStream
from ledgrab.storage.value_source import (
GameEventValueSource,
ValueSource,
)
+2 -2
View File
@@ -2,12 +2,12 @@
import pytest
from wled_controller.core.game_integration.presets import (
from ledgrab.core.game_integration.presets import (
EffectPreset,
get_all_presets,
get_preset,
)
from wled_controller.storage.game_integration import EventMapping
from ledgrab.storage.game_integration import EventMapping
class TestPresetData:
+2 -2
View File
@@ -4,8 +4,8 @@ Ensures that GameEventBus is properly threaded through to
ColorStripStreamManager and ValueStreamManager.
"""
from wled_controller.core.game_integration.event_bus import GameEventBus
from wled_controller.core.processing.processor_manager import (
from ledgrab.core.game_integration.event_bus import GameEventBus
from ledgrab.core.processing.processor_manager import (
ProcessorDependencies,
ProcessorManager,
)
@@ -2,7 +2,7 @@
import pytest
from wled_controller.core.game_integration.adapters.generic_webhook_adapter import (
from ledgrab.core.game_integration.adapters.generic_webhook_adapter import (
GenericWebhookAdapter,
)
+1 -1
View File
@@ -4,7 +4,7 @@ import threading
import pytest
from wled_controller.core.game_integration.adapters.lol_adapter import (
from ledgrab.core.game_integration.adapters.lol_adapter import (
LoLAdapter,
LoLPoller,
)
+1 -1
View File
@@ -5,7 +5,7 @@ from pathlib import Path
import pytest
from wled_controller.core.game_integration.mapping_adapter import (
from ledgrab.core.game_integration.mapping_adapter import (
MappingAdapter,
load_adapter_from_yaml,
validate_adapter_yaml,
+1 -1
View File
@@ -4,7 +4,7 @@ import threading
import time
from wled_controller.core.processing.sync_clock_runtime import SyncClockRuntime
from ledgrab.core.processing.sync_clock_runtime import SyncClockRuntime
class TestSyncClockRuntimeInit: