HASS: как получить список покупок или to-do одной строкой?

HASS: как получить список покупок или to-do одной строкой?

В последних версиях Home Assistant произошли изменения, из-за которых старые конфигурации списков дел (to-do) и покупок могут не работать:

  1. В Home Assistant 2023.11 появился новый домен todo специально для списков дел. Раньше использовался домен calendar.
  2. Список покупок (shopping_list) теперь является частью todo.
  3. Отдельные записи списка дел больше нельзя получить из атрибутов сенсора (так же как и, например, события календаря и прогноз погоды).
Список покупок в Home Assistant

Поэтому если раньше у вас были шаблоны, в которых выводился список покупок, используя state_attr('sensor.shoppinglist', 'list'), то теперь такое работать не будет.

Как теперь подставить список покупок в шаблон?

Теперь предварительно нужно вызывать службу todo.get_items для получения всех элементов списка.

Например, если вы хотите отправить список покупок в Telegram, то можно использовать вот такую автоматизацию:

automation:
  - alias: "Send shopping list to Telegram daily"
    trigger:
      - platform: time
        at: "18:00:00"
    action:
      - service: todo.get_items # запрашиваем все элементы…
        target:
  	entity_id: todo.shopping_list # …из списка покупок…
        response_variable: shopping_list # …и сохраняем в переменную shopping_list
      - service: notify.telegram_roland
        data:
  	message: "Список покупок: {{ shopping_list['todo.shopping_list']['items'] | map(attribute='summary') | join(', ') }}."

Со списками дел принцип тот же, нужно только заменить todo.shopping_list на нужный объект.

Хочу как раньше!

Можно настроить специальный сенсор, в значении которого будут перечисляться все элементы списка покупок через запятую. Для этого в configuration.yaml достаточно добавить:

template:
  - trigger:
      - platform: event
        event_type: shopping_list_updated
    action:
      - service: todo.get_items
        target:
          entity_id: todo.shopping_list
        response_variable: shopping_list
    sensor:
      - name: Shopping list
        unique_id: shopping_list
        state: "{{ shopping_list['todo.shopping_list']['items'] | map(attribute='summary') | join(', ') }}"

После перезапуска Home Assistant появится новый сенсор:

Список покупок в Home Assistant

Который можно использовать вот так:

automation:
  - alias: "Send shopping list to Telegram daily"
    trigger:
      - platform: time
        at: "18:00:00"
    action:
      - service: notify.telegram_roland
        data:
          message: "Список покупок: {{ states('sensor.shopping_list') }}."

Правда, если вам нужен такой же сенсор для списка дел, а не для списка покупок, то тут есть нюансы:

  • В Home Asssitant для to-do нет события похожего на shopping_list_updated. То есть, не получится повесить какой-то общий триггер, который бы вызывался при любом изменении списка дел.
  • Можно использовать триггер по состоянию:
    - platform: state
      entity_id:
        - todo.tasks
    
    Но такой триггер срабатывает только при изменении количества элементов в списке и не вызывается при обновлении отдельных элементов.
  • Можно повесить триггер на событие call_service с доменом todo, но это событие вызывается до того, как to-do реально обновится.

Поэтому с учетом всех ограничений, рабочий вариант сенсора для списка дел выглядит так:

template:
  - trigger:
      - platform: event
        event_type: call_service
        event_data:
          domain: todo
          service: add_item
          service_data:
            entity_id: [todo.tasks] # todo.tasks нужно заменить на ваш список
      - platform: event
        event_type: call_service
        event_data:
          domain: todo
          service: remove_item
          service_data:
            entity_id: [todo.tasks] # и здесь
      - platform: event
        event_type: call_service
        event_data:
          domain: todo
          service: update_item
          service_data:
            entity_id: [todo.tasks] # и тут
    action:
      - delay:
          milliseconds: 500
      - service: todo.get_items
        target:
          entity_id: todo.tasks # и вот тут
        response_variable: tasks_list
    sensor:
      - name: Tasks list
        unique_id: tasks_list
        state: "{{ tasks_list['todo.tasks']['items'] | map(attribute='summary') | join(', ') }}" # и здесь тоже…

Раньше я использовал обновление по таймеру, а этот вариант посоветовали в комментариях. Лайки ставить сюда 🙂

Да, вариант кривенький, но рабочий. Если вдруг найду решение получше, то обязательно сообщу.

man smart-home
Telegram про умный дом: идеи, девайсы, Home Assistant.

Сообщу в Telegram.

Была ли статья полезна?

Хотите сказать спасибо? Кофе автору — ваша благодарность.

На кофе
Подписка на новые статьи

Уведомления, как только в блоге появится что-нибудь интересненькое.

Подписываясь, вы даете согласие на обработку персональных данных.