Ограничение карточки number в Mushroom для Home Assistant: разбор issue и патч

В карточке Mushroom Number для Home Assistant на Lovelace UI drag-управление работает неочевидно и ограничивает пользовательский опыт. В статье разобрана причина такого поведения и предложен патч (issue #1832), улучшающий взаимодействие с карточкой.

В Telegram-канале @iot7m_ru публикуются практические заметки по Home Assistant: опыт эксплуатации устройств, интеграция с различным оборудованием, создание дашбордов и разбор типовых проблем. Многие материалы основаны на реальных запросах и консультациях. Подпишитесь на @iot7m_ru, если используете Home Assistant на практике.

Ограничение карточки number в Mushroom для Home Assistant: разбор issue и патч

Проблема

В карточке Mushroom Number Card наблюдается некорректное поведение при перемещении ползунка, когда связанная сущность обновляется извне с высокой частотой. Проблема зафиксирована на версии Mushroom v5.0.8 и особенно заметна в реальных проектах умного дома, где значения могут обновляться десятки раз в секунду — например, при интеграции с системами учёта электроэнергии или промышленными контроллерами вроде Wiren Board. В небольших инсталляциях это может быть почти незаметно, но в крупных системах проблема сразу бросается в глаза: при взаимодействии пользователя значение number сбрасывается на текущее состояние, приходящее от Home Assistant, что делает настройку неудобной.

Воспроизведение проблемы

Для демонстрации проблемы используется простой сценарий: создаются две number-сущности input_number. Первая обновляется автоматически из автоматизации с периодичностью примерно раз в секунду. Вторая используется для ручного управления через интерфейс и не обновляется автоматически. Все сущности выводятся на один дашборд для наглядного сравнения поведения карточек. В результате на экране присутствуют четыре карточки: две для сущностей, которые обновляются автоматически, и две для сущностей без автоматического обновления. В каждой группе используется одна стандартная карточка number и одна карточка Mushroom Number Card. При попытке перемещать ползунок становится заметно различие в поведении карточек. В группе карточек, где происходит автоматическое обновление значения, в стандартной карточке number значение ползунка отображается во всплывающем тултипе и отражает текущее положение слайдера во время движения. В Mushroom Number Card значение также визуально меняется на карточке, однако при каждом обновлении состояния от Home Assistant оно перезаписывается значением, приходящим из Home Assistant, даже если пользователь ещё удерживает ползунок и не завершил перемещение.

Причина поведения

Причина заключается в том, как Mushroom Number Card обрабатывает входящие обновления состояния. Со стороны Home Assistant регулярно приходят события обновления состояния сущности number. Mushroom Number Card применяет эти обновления сразу же, даже в тот момент, когда пользователь уже начал перемещать ползунок, но ещё не отпустил его. В результате любое внешнее обновление немедленно перезаписывает ввод пользователя, даже в процессе активного взаимодействия.

Предложенное решение

Решение заключается в отслеживании начала и окончания движения ползунка и игнорировании обновлений состояния от Home Assistant в этот промежуток времени. Пока пользователь перемещает ползунок, входящие обновления игнорируются, а синхронизация с состоянием происходит после завершения действия. Такой подход соответствует поведению стандартной number-карточки Home Assistant и заметно улучшает пользовательский опыт.

Для этого в карточку добавляется отслеживание начала и окончания перемещения ползунка (pointer events). Пока пользователь удерживает ползунок, внешние обновления значения игнорируются. После завершения взаимодействия синхронизация со state сущности восстанавливается.

diff --git a/src/cards/number-card/number-card.ts b/src/cards/number-card/number-card.ts
index f223f7a69..15762e2b6 100644
--- a/src/cards/number-card/number-card.ts
+++ b/src/cards/number-card/number-card.ts
@@ -79,10 +79,20 @@ export class NumberCard
   @state() private value?: number;

+  @state() private isDragging = false;
+
+  private _onPointerDown = () => {
+    this.isDragging = true;
+  };
+
+  private _onPointerUp = () => {
+    this.isDragging = false;
+  };
+
   updateValue() {
+    if (this.isDragging) return;
     this.value = undefined;
   }
@@ -158,7 +170,10 @@ export class NumberCard
-          <div class="actions" ?rtl=${rtl}>
+          <div class="actions" ?rtl=${rtl}
+               @pointerdown=${this._onPointerDown}
+               @pointerup=${this._onPointerUp}
+               @pointercancel=${this._onPointerUp}>

Согласно правилам проекта Mushroom pull request не принимаются до тех пор, пока проблема официально не признана ошибкой. Поэтому на данный момент исправление оформлено в виде локального патча и обсуждается в рамках issue.

Итог

Предложенное решение приводит поведение Mushroom Number Card в соответствие со стандартной number-карточкой Home Assistant: значение ползунка больше не перезаписывается во время активного взаимодействия пользователя, а синхронизация с состоянием происходит корректно после завершения движения.

Обзорная статья Home Assistant dashboard: как собрать удобный интерфейс дашборда из карточек содержит описание структуры интерфейса Home Assistant и базовых принципов работы с карточками.

Полезные ссылки

Приложение

Конфигурация input_number

input_number:
  comfort:
    name: "Comfort"
    icon: mdi:heating-coil
    min: 5
    max: 45
    step: 1
    initial: 22
    unit_of_measurement: "°C"
    mode: slider
  eco:
    name: "Eco"
    icon: mdi:heating-coil
    min: 5
    max: 45
    step: 1
    initial: 22
    unit_of_measurement: "°C"
    mode: slider

Автоматизация с обновлением значения каждую секунду

- id: setup_random_comfort_every_second
  alias: "Setup random value for comfort input number every second"
  trigger:
    - platform: time_pattern
      seconds: "/1"
  action:
    - service: input_number.set_value
      target:
        entity_id: input_number.comfort
      data:
        value: >
          {{ range(5, 46) | random }}%

Пример дашборда для воспроизведения проблемы

title: Number
icon: mdi:numeric
cards:
  - type: entities
    entities:
      - entity: input_number.comfort
        name: Comfort(update by timer)
      - entity: input_number.eco
        name: Eco
  - type: custom:mushroom-number-card
    entity: input_number.comfort
    name: Comfort(update by timer)
  - type: custom:mushroom-number-card
    entity: input_number.eco
    name: Eco