mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-21 10:15:04 +02:00
Add persistent auto-off option for smart plugs (#826)
Auto-off now has a "Keep Enabled" toggle that keeps it active between prints instead of disabling after each use (one-shot). Useful for HA accessories like BentoBox filters that should always power off after prints. Default behavior (one-shot) is unchanged.
This commit is contained in:
@@ -346,6 +346,12 @@ async def run_migrations(conn):
|
||||
except OperationalError:
|
||||
pass # Already applied
|
||||
|
||||
# Migration: Add auto_off_persistent column to smart_plugs (keep auto-off enabled between prints)
|
||||
try:
|
||||
await conn.execute(text("ALTER TABLE smart_plugs ADD COLUMN auto_off_persistent BOOLEAN DEFAULT 0"))
|
||||
except OperationalError:
|
||||
pass # Already applied
|
||||
|
||||
# Migration: Add AMS alarm notification columns to notification_providers
|
||||
try:
|
||||
await conn.execute(text("ALTER TABLE notification_providers ADD COLUMN on_ams_humidity_high BOOLEAN DEFAULT 0"))
|
||||
@@ -597,6 +603,7 @@ async def run_migrations(conn):
|
||||
enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||
auto_on BOOLEAN NOT NULL DEFAULT 1,
|
||||
auto_off BOOLEAN NOT NULL DEFAULT 1,
|
||||
auto_off_persistent BOOLEAN NOT NULL DEFAULT 0,
|
||||
off_delay_mode VARCHAR(20) NOT NULL DEFAULT 'time',
|
||||
off_delay_minutes INTEGER NOT NULL DEFAULT 5,
|
||||
off_temp_threshold INTEGER NOT NULL DEFAULT 70,
|
||||
@@ -625,7 +632,8 @@ async def run_migrations(conn):
|
||||
INSERT INTO smart_plugs_new
|
||||
SELECT id, name, ip_address,
|
||||
COALESCE(plug_type, 'tasmota'), ha_entity_id, printer_id,
|
||||
enabled, auto_on, auto_off, off_delay_mode, off_delay_minutes, off_temp_threshold,
|
||||
enabled, auto_on, auto_off, COALESCE(auto_off_persistent, 0),
|
||||
off_delay_mode, off_delay_minutes, off_temp_threshold,
|
||||
username, password, power_alert_enabled, power_alert_high, power_alert_low,
|
||||
power_alert_last_triggered, schedule_enabled, schedule_on_time, schedule_off_time,
|
||||
COALESCE(show_in_switchbar, 0), last_state, last_checked, auto_off_executed,
|
||||
@@ -894,6 +902,7 @@ async def run_migrations(conn):
|
||||
enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||
auto_on BOOLEAN NOT NULL DEFAULT 1,
|
||||
auto_off BOOLEAN NOT NULL DEFAULT 1,
|
||||
auto_off_persistent BOOLEAN NOT NULL DEFAULT 0,
|
||||
off_delay_mode VARCHAR(20) NOT NULL DEFAULT 'time',
|
||||
off_delay_minutes INTEGER NOT NULL DEFAULT 5,
|
||||
off_temp_threshold INTEGER NOT NULL DEFAULT 70,
|
||||
@@ -923,7 +932,8 @@ async def run_migrations(conn):
|
||||
INSERT INTO smart_plugs_temp
|
||||
SELECT id, name, ip_address, plug_type, ha_entity_id, ha_power_entity,
|
||||
ha_energy_today_entity, ha_energy_total_entity, printer_id, enabled,
|
||||
auto_on, auto_off, off_delay_mode, off_delay_minutes, off_temp_threshold,
|
||||
auto_on, auto_off, COALESCE(auto_off_persistent, 0),
|
||||
off_delay_mode, off_delay_minutes, off_temp_threshold,
|
||||
username, password, power_alert_enabled, power_alert_high, power_alert_low,
|
||||
power_alert_last_triggered, schedule_enabled, schedule_on_time, schedule_off_time,
|
||||
show_in_switchbar, last_state, last_checked, auto_off_executed,
|
||||
|
||||
@@ -57,6 +57,7 @@ class SmartPlug(Base):
|
||||
enabled: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
auto_on: Mapped[bool] = mapped_column(Boolean, default=True) # Turn on at print start
|
||||
auto_off: Mapped[bool] = mapped_column(Boolean, default=True) # Turn off at print complete/fail
|
||||
auto_off_persistent: Mapped[bool] = mapped_column(Boolean, default=False) # Keep auto-off enabled between prints
|
||||
|
||||
# Turn-off delay mode: "time" or "temperature"
|
||||
off_delay_mode: Mapped[str] = mapped_column(String(20), default="time")
|
||||
|
||||
@@ -48,6 +48,7 @@ class SmartPlugBase(BaseModel):
|
||||
enabled: bool = True
|
||||
auto_on: bool = True
|
||||
auto_off: bool = True
|
||||
auto_off_persistent: bool = False
|
||||
off_delay_mode: Literal["time", "temperature"] = "time"
|
||||
off_delay_minutes: int = Field(default=5, ge=0, le=60)
|
||||
off_temp_threshold: int = Field(default=70, ge=30, le=150)
|
||||
@@ -115,6 +116,7 @@ class SmartPlugUpdate(BaseModel):
|
||||
enabled: bool | None = None
|
||||
auto_on: bool | None = None
|
||||
auto_off: bool | None = None
|
||||
auto_off_persistent: bool | None = None
|
||||
off_delay_mode: Literal["time", "temperature"] | None = None
|
||||
off_delay_minutes: int | None = Field(default=None, ge=0, le=60)
|
||||
off_temp_threshold: int | None = Field(default=None, ge=30, le=150)
|
||||
|
||||
@@ -416,7 +416,7 @@ class SmartPlugManager:
|
||||
logger.warning("Failed to update plug %s pending state: %s", plug_id, e)
|
||||
|
||||
async def _mark_auto_off_executed(self, plug_id: int):
|
||||
"""Disable auto-off after it was executed (one-shot behavior)."""
|
||||
"""Disable auto-off after it was executed (one-shot behavior unless persistent)."""
|
||||
try:
|
||||
from backend.app.core.database import async_session
|
||||
from backend.app.models.smart_plug import SmartPlug
|
||||
@@ -425,14 +425,18 @@ class SmartPlugManager:
|
||||
result = await db.execute(select(SmartPlug).where(SmartPlug.id == plug_id))
|
||||
plug = result.scalar_one_or_none()
|
||||
if plug:
|
||||
plug.auto_off = False # Disable auto-off (one-shot behavior)
|
||||
if not plug.auto_off_persistent:
|
||||
plug.auto_off = False # Disable auto-off (one-shot behavior)
|
||||
plug.auto_off_executed = False # Reset the flag
|
||||
plug.auto_off_pending = False # Clear pending state
|
||||
plug.auto_off_pending_since = None
|
||||
plug.last_state = "OFF"
|
||||
plug.last_checked = datetime.now(timezone.utc)
|
||||
await db.commit()
|
||||
logger.info("Auto-off executed and disabled for plug %s", plug_id)
|
||||
if plug.auto_off_persistent:
|
||||
logger.info("Auto-off executed for plug %s (persistent, stays enabled)", plug_id)
|
||||
else:
|
||||
logger.info("Auto-off executed and disabled for plug %s", plug_id)
|
||||
except Exception as e:
|
||||
logger.warning("Failed to update plug %s after auto-off: %s", plug_id, e)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user