Add battery widget (device's own last-reported level, no live upstream)
Shows Frame.battery_percent/battery_as_of, already set by every device wake-on-battery report, plus routers/common.py's existing battery_estimate_s time-remaining estimate -- nothing new to fetch or cache. Compact (icon + percent) or detailed (+ estimate, last report age) display mode. No button actions.
This commit is contained in:
@@ -54,6 +54,7 @@ from ..models import (
|
||||
)
|
||||
from ..text_content import has_text, parse_rich_text
|
||||
from ..widgets import WIDGET_TYPES
|
||||
from ..widgets import battery as battery_widget
|
||||
from ..widgets import text as text_widget
|
||||
from .common import (
|
||||
calendar_sources_for_widget,
|
||||
@@ -291,6 +292,8 @@ def api_widget_config_save(
|
||||
weather_units: str | None = Form(None),
|
||||
weather_hourly_interval_hours: int | None = Form(None),
|
||||
weather_daily_days: int | None = Form(None),
|
||||
# battery
|
||||
battery_mode: str | None = Form(None),
|
||||
):
|
||||
"""Every field optional -- same partial-update, form-urlencoded
|
||||
convention as the old frame-level api_config_save, now scoped to one
|
||||
@@ -417,6 +420,10 @@ def api_widget_config_save(
|
||||
wcfg.hourly_interval_hours = max(1, min(24, weather_hourly_interval_hours))
|
||||
if weather_daily_days is not None:
|
||||
wcfg.daily_days = max(1, min(14, weather_daily_days))
|
||||
elif widget.widget_type == "battery":
|
||||
with widget_locked(db, frame.id, widget.id) as (_, _, bcfg):
|
||||
if battery_mode is not None:
|
||||
bcfg.mode = battery_mode if battery_mode in ("compact", "detailed") else "detailed"
|
||||
with frame_locked(db, frame.id) as cfg:
|
||||
cfg.stats_config_saves += 1
|
||||
return {"status": "saved"}
|
||||
@@ -1059,6 +1066,25 @@ def api_widget_preview_text(
|
||||
return Response(content=png, media_type="image/png")
|
||||
|
||||
|
||||
# --- Battery: preview --------------------------------------------------------
|
||||
|
||||
@router.get("/api/frames/{frame_id}/widgets/{widget_id}/preview/battery")
|
||||
def api_widget_preview_battery(
|
||||
frame_widget: tuple[Frame, Widget] = Depends(require_widget_view), db: Session = Depends(get_db)
|
||||
):
|
||||
"""Unlike every other preview endpoint, there's no "not configured
|
||||
yet" 400 case -- the content is frame-level state (battery_percent)
|
||||
that either exists or doesn't, and render() already degrades to a
|
||||
"No reports yet" placeholder either way, same as a live device
|
||||
render would."""
|
||||
frame, widget = frame_widget
|
||||
_require_widget_type(widget, "battery")
|
||||
png = battery_widget.render_preview_png(
|
||||
db, frame, widget, orientation=frame.orientation, palette_rgb=frame.palette_rgb
|
||||
)
|
||||
return Response(content=png, media_type="image/png")
|
||||
|
||||
|
||||
# --- Whiteboard: source/preview ------------------------------------------
|
||||
|
||||
class WhiteboardSourceRequest(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user