chore: initial baseline before refactoring

Initial snapshot of Home Assistant config (HAOS 2026.4.4)
prior to dashboard restructuring and helper YAML migration.

Pre-commit cleanup applied:
- Removed blueprints/switch_manager/ (9.4 MB stale, component already gone)
- Removed .storage/switch_manager
- Removed home-assistant.log.{1,old,fault}
- Removed zigbee2mqtt/configuration_backup_v{1..4}.yaml
- Removed zigbee2mqtt/database.db.tmp.2024-09-27 (1.5y old)
- Created empty themes/ to satisfy configuration.yaml include

.gitignore uses allowlist strategy for .storage/ to keep
all tokens, keys, and PINs out of version control.
This commit is contained in:
2026-05-02 14:24:53 +02:00
commit 5f01411780
149 changed files with 47886 additions and 0 deletions
@@ -0,0 +1,112 @@
import abc
from dataclasses import dataclass
from cx_const import Number, StepperDir
class MinMax:
def __init__(self, min: Number, max: Number, margin: float = 0.05) -> None:
self._min = min
self._max = max
self.margin_dist = (max - min) * margin
@property
def min(self) -> Number:
return self._min
@property
def max(self) -> Number:
return self._max
def is_min(self, value: Number) -> bool:
return self._min == value
def is_max(self, value: Number) -> bool:
return self._max == value
def is_between(self, value: Number) -> bool:
return self._min < value < self._max
def in_min_boundaries(self, value: Number) -> bool:
return self._min <= value <= (self._min + self.margin_dist)
def in_max_boundaries(self, value: Number) -> bool:
return (self._max - self.margin_dist) <= value <= self._max
def clip(self, value: Number) -> Number:
return max(self._min, min(value, self._max))
def __repr__(self) -> str:
return f"MinMax({self.min}, {self.max})"
@dataclass
class StepperOutput:
next_value: Number
next_direction: str | None
@property
def exceeded(self) -> bool:
return self.next_direction is None
class Stepper(abc.ABC):
sign_mapping = {StepperDir.UP: 1, StepperDir.DOWN: -1}
min_max: MinMax
steps: Number
previous_direction: str
relative_steps: bool
@staticmethod
def invert_direction(direction: str) -> str:
return StepperDir.UP if direction == StepperDir.DOWN else StepperDir.DOWN
@staticmethod
def sign(direction: str) -> int:
return Stepper.sign_mapping[direction]
@staticmethod
def apply_sign(value: Number, direction: str) -> Number:
return Stepper.sign(direction) * value
def __init__(
self,
min_max: MinMax,
steps: Number,
previous_direction: str = StepperDir.DOWN,
relative_steps: bool = True,
) -> None:
self.min_max = min_max
self.steps = steps
self.previous_direction = previous_direction
self.relative_steps = relative_steps
def _compute_step(self) -> float:
if self.relative_steps:
max_ = self.min_max.max
min_ = self.min_max.min
return (max_ - min_) / self.steps
else:
return self.steps
def get_direction(self, value: Number, direction: str) -> str:
if direction == StepperDir.TOGGLE:
direction = Stepper.invert_direction(self.previous_direction)
self.previous_direction = direction
return direction
@abc.abstractmethod
def step(self, value: Number, direction: str) -> StepperOutput:
"""
This function updates the value according to the steps
that needs to take and returns the new value together with
the new direction it will need to go. If next_direction is
None, the loop will stop executing.
"""
raise NotImplementedError
class InvertStepper(Stepper):
def step(self, value: Number, direction: str) -> StepperOutput:
return StepperOutput(self.apply_sign(value, direction), next_direction=None)
@@ -0,0 +1,17 @@
from cx_const import Number
from cx_core.stepper import Stepper, StepperOutput
class BounceStepper(Stepper):
def step(self, value: Number, direction: str) -> StepperOutput:
value = self.min_max.clip(value)
step = self._compute_step()
new_value = value + Stepper.apply_sign(step, direction)
if self.min_max.is_between(new_value):
return StepperOutput(round(new_value, 3), next_direction=direction)
else:
new_value = 2 * self.min_max.clip(new_value) - new_value
return StepperOutput(
round(new_value, 3), next_direction=Stepper.invert_direction(direction)
)
@@ -0,0 +1,31 @@
from cx_const import Number, StepperDir
from cx_core.stepper import MinMax, Stepper, StepperOutput
class IndexLoopStepper(Stepper):
def __init__(
self,
size: int,
previous_direction: str = StepperDir.DOWN,
relative_steps: bool = True,
) -> None:
super().__init__(
MinMax(0, size - 1),
size,
previous_direction,
relative_steps,
)
def step(self, value: Number, direction: str) -> StepperOutput:
value = self.min_max.clip(value)
sign = self.sign(direction)
# We add +1 to make the max be included
max_ = int(self.min_max.max) + 1
min_ = int(self.min_max.min)
if self.relative_steps:
step = (max_ - min_) // self.steps
else:
step = self.steps
new_value = (int(value) + step * sign) % (max_ - min_) + min_
return StepperOutput(new_value, next_direction=direction)
@@ -0,0 +1,16 @@
from cx_const import Number
from cx_core.stepper import Stepper, StepperOutput
class LoopStepper(Stepper):
def step(self, value: Number, direction: str) -> StepperOutput:
value = self.min_max.clip(value)
max_ = self.min_max.max
min_ = self.min_max.min
step = self._compute_step()
new_value = (
((value + Stepper.apply_sign(step, direction)) - min_) % (max_ - min_)
) + min_
new_value = round(new_value, 3)
return StepperOutput(new_value, next_direction=direction)
@@ -0,0 +1,26 @@
from cx_const import Number, StepperDir
from cx_core.stepper import Stepper, StepperOutput
class StopStepper(Stepper):
def get_direction(self, value: Number, direction: str) -> str:
value = self.min_max.clip(value)
if direction == StepperDir.TOGGLE and self.min_max.in_min_boundaries(value):
self.previous_direction = StepperDir.UP
return self.previous_direction
if direction == StepperDir.TOGGLE and self.min_max.in_max_boundaries(value):
self.previous_direction = StepperDir.DOWN
return self.previous_direction
return super().get_direction(value, direction)
def step(self, value: Number, direction: str) -> StepperOutput:
value = self.min_max.clip(value)
step = self._compute_step()
new_value = value + Stepper.apply_sign(step, direction)
new_value = round(new_value, 3)
if self.min_max.is_between(new_value):
return StepperOutput(new_value, next_direction=direction)
else:
new_value = self.min_max.clip(new_value)
return StepperOutput(new_value, next_direction=None)