Dashboard Studio 1.11.0: energy card, climate popup, car and appliance redesigns, Home Connect
- Energy card: live power flow between solar, grid, battery and home, with line width and speed following the power, battery level and today's totals; sign of grid and battery sensors can be flipped - Climate popup (room card thermostat and any climate entity): dial, -/+ that batch quick taps, modes, presets and fan modes, live updates - Car card redesigned around 3x4 with a drawn car or photo, compact, wide and tall layouts - Appliance card redesigned with a progress ring; Home Connect support: all operation states, auto-fill from the operation state sensor via the device registry, readable program names, door state, pause/ resume/stop buttons, power switch and alerts. Fixes ready/inactive being shown as finished/running - Horizontal scroll card: width in pixels or cards per view, and a width per card - Swipe card: no lost tap after a touch swipe, no broken swipes over images, lost pointer capture ends the swipe, trackpad swiping Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,27 @@ class MockHA:
|
||||
entity("sensor.phone_battery", "76", friendly_name="Phone Battery", unit_of_measurement="%", device_class="battery"),
|
||||
entity("binary_sensor.front_door", "off", friendly_name="Front Door", device_class="door"),
|
||||
entity("binary_sensor.hallway_motion", "off", friendly_name="Hallway Motion", device_class="motion"),
|
||||
entity("climate.thermostat", "heat", friendly_name="Thermostat", current_temperature=20.5, temperature=21, min_temp=7, max_temp=30, hvac_modes=["off", "heat", "auto"]),
|
||||
entity("climate.thermostat", "heat", friendly_name="Thermostat", current_temperature=20.5, temperature=21, min_temp=7, max_temp=30, hvac_modes=["off", "heat", "auto"],
|
||||
preset_modes=["none", "eco", "comfort", "away"], preset_mode="comfort", fan_modes=["auto", "low", "high"], fan_mode="auto", hvac_action="heating", current_humidity=46, target_temp_step=0.5),
|
||||
entity("sensor.grid_power", "-680", friendly_name="Grid Power", unit_of_measurement="W", device_class="power"),
|
||||
entity("sensor.home_battery_power", "500", friendly_name="Home Battery Power", unit_of_measurement="W", device_class="power"),
|
||||
entity("sensor.home_battery_level", "64", friendly_name="Home Battery Level", unit_of_measurement="%", device_class="battery"),
|
||||
entity("sensor.solar_energy_today", "12.4", friendly_name="Produced today", unit_of_measurement="kWh", device_class="energy"),
|
||||
entity("sensor.home_energy_today", "8.1", friendly_name="Used today", unit_of_measurement="kWh", device_class="energy"),
|
||||
entity("binary_sensor.washer_door", "off", friendly_name="Washer Door", device_class="door"),
|
||||
# A dishwasher as the Home Connect integration exposes it
|
||||
entity("sensor.dishwasher_operation_state", "run", friendly_name="Dishwasher Operation state", device_class="enum",
|
||||
options=["inactive", "ready", "delayedstart", "run", "pause", "actionrequired", "finished", "error", "aborting"]),
|
||||
entity("sensor.dishwasher_program_progress", "40", friendly_name="Dishwasher Program progress", unit_of_measurement="%"),
|
||||
entity("sensor.dishwasher_program_finish_time", (datetime.now(timezone.utc) + timedelta(minutes=52)).isoformat(), friendly_name="Dishwasher Program finish time", device_class="timestamp"),
|
||||
entity("sensor.dishwasher_door", "locked", friendly_name="Dishwasher Door", device_class="enum", options=["closed", "locked", "open"]),
|
||||
entity("select.dishwasher_active_program", "dishcare_dishwasher_program_eco_50", friendly_name="Dishwasher Active program",
|
||||
options=["dishcare_dishwasher_program_eco_50", "dishcare_dishwasher_program_auto_2", "dishcare_dishwasher_program_quick_45"]),
|
||||
entity("button.dishwasher_resume_program", "unknown", friendly_name="Dishwasher Resume program"),
|
||||
entity("button.dishwasher_stop_program", "unknown", friendly_name="Dishwasher Stop program"),
|
||||
entity("switch.dishwasher_power", "on", friendly_name="Dishwasher Power"),
|
||||
entity("sensor.dishwasher_rinse_aid_nearly_empty", "present", friendly_name="Dishwasher Rinse aid nearly empty", device_class="enum"),
|
||||
entity("sensor.washer_energy", "0.4", friendly_name="Washer Energy", unit_of_measurement="kWh", device_class="energy"),
|
||||
entity("cover.garage_door", "closed", friendly_name="Garage Door"),
|
||||
entity("lock.front_door", "locked", friendly_name="Front Door Lock"),
|
||||
entity("media_player.living_room_speaker", "playing", friendly_name="Living Room Speaker", media_title="Blue in Green", media_artist="Miles Davis", media_album_name="Kind of Blue", volume_level=0.35, entity_picture="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><defs><linearGradient id='g' x1='0' y1='0' x2='1' y2='1'><stop offset='0' stop-color='%23234'/><stop offset='1' stop-color='%23c58'/></linearGradient></defs><rect width='100' height='100' fill='url(%23g)'/><circle cx='50' cy='50' r='22' fill='none' stroke='%23fff' stroke-width='3' opacity='.7'/></svg>"),
|
||||
@@ -155,6 +175,12 @@ class MockHA:
|
||||
for eid in expanded:
|
||||
if eid not in self.states:
|
||||
continue
|
||||
if eid.startswith("button.dishwasher_"): # Home Connect program buttons
|
||||
st_ = {"stop": "aborting", "pause": "pause", "resume": "run"}[eid.split("_")[-2]]
|
||||
self.set_state("sensor.dishwasher_operation_state", st_)
|
||||
if st_ == "aborting":
|
||||
asyncio.get_event_loop().call_later(3, lambda: self.set_state("sensor.dishwasher_operation_state", "ready"))
|
||||
continue
|
||||
if domain == "vacuum" or eid.startswith("vacuum."):
|
||||
self._vacuum(eid, service, data)
|
||||
continue
|
||||
@@ -177,6 +203,9 @@ class MockHA:
|
||||
self.set_state(eid, "on" if on else "off", **extra)
|
||||
elif service == "set_temperature":
|
||||
self.set_state(eid, None, temperature=data.get("temperature"))
|
||||
elif service in ("set_preset_mode", "set_fan_mode"):
|
||||
key = "preset_mode" if service == "set_preset_mode" else "fan_mode"
|
||||
self.set_state(eid, None, **{key: data.get(key)})
|
||||
elif service == "set_hvac_mode":
|
||||
self.set_state(eid, data.get("hvac_mode"))
|
||||
elif service in ("open_cover", "close_cover"):
|
||||
@@ -261,6 +290,8 @@ class MockHA:
|
||||
lvl = float(self.states["sensor.model_y_battery"]["state"])
|
||||
if lvl < 80:
|
||||
self.set_state("sensor.model_y_battery", f"{lvl + 0.2:.1f}")
|
||||
home, solar, batt = float(self.states["sensor.power_usage"]["state"]), float(self.states["sensor.solar_production"]["state"]), float(self.states["sensor.home_battery_power"]["state"])
|
||||
self.set_state("sensor.grid_power", f"{home + batt - solar:.0f}")
|
||||
if self.states["sensor.washer_status"]["state"] == "running":
|
||||
left = max(0, int(self.states["sensor.washer_remaining_time"]["state"]) - 1)
|
||||
self.set_state("sensor.washer_remaining_time", str(left))
|
||||
@@ -329,6 +360,8 @@ class MockHA:
|
||||
"garage": ["cover.garage_door", "lock.front_door"],
|
||||
}
|
||||
rows = [{"entity_id": e, "area_id": a, "device_id": None, "disabled_by": None, "hidden_by": None, "entity_category": None} for a, es in areas.items() for e in es]
|
||||
rows += [{"entity_id": e, "area_id": "kitchen", "device_id": "hc-dishwasher", "disabled_by": None, "hidden_by": None, "entity_category": None}
|
||||
for e in self.states if e.split(".")[1].startswith("dishwasher_")]
|
||||
await ws.send_json({"id": mid, "type": "result", "success": True, "result": rows})
|
||||
elif typ == "config/device_registry/list":
|
||||
await ws.send_json({"id": mid, "type": "result", "success": True, "result": []})
|
||||
|
||||
Reference in New Issue
Block a user