Количка + Home Assistant — споделена кошница

Свържи споделената семейна кошница на Количка с вградения списък за пазаруване в Home Assistant — двупосочна синхронизация чрез REST сензор и автоматизации. Готов YAML пакет и Family Basket API.

🛒 Отвори приложението

Обновено: 2026-07-16 · Markdown версия

Какво прави интеграцията

Свързва споделената кошница от приложението Количка (една за цялото семейство, достъпна с код) с вградения списък за пазаруване (todo.shopping_list) в Home Assistant. Промените текат и в двете посоки: добавяне, премахване и отметки „купено“.

Стъпки

  1. Вземи код за семейна кошница
    Отвори приложението Количка → Кошница → иконата „Семейна кошница“. Натисни „Създай нова“, за да получиш код (напр. 442834), или „Влез“ с код, който вече ползвате в семейството. Всеки с този код вижда и редактира същия списък.
  2. Разреши пакети в Home Assistant
    Ако още го нямаш, добави в configuration.yaml (веднъж): под ключа homeassistant добави „packages: !include_dir_named packages“. Създай папка config/packages/.
  3. Добави пакета kolichka.yaml
    Създай config/packages/kolichka.yaml със съдържанието по-долу и замени ВАШИЯТ_КОД с твоя код от Стъпка 1. Пакетът добавя REST сензор (чете кошницата на всеки 30 сек), rest_command (записва обратно) и две автоматизации за двупосочна синхронизация с вградения списък за пазаруване (todo.shopping_list).
  4. Провери конфигурацията и рестартирай
    Настройки → Разработчик → „Провери конфигурацията“ (или командата за check_config). Ако е ОК, рестартирай Home Assistant. След рестарта списъкът за пазаруване се попълва от кошницата до 30 секунди.
  5. Готово — двупосочна синхронизация
    Добавиш ли продукт в приложението, той се появява в HA до ~30 сек. Отметка/промяна в списъка на HA се връща в приложението за няколко секунди. Приложението е водещо (source of truth).

Пакетът за Home Assistant

Замени ВАШИЯТ_КОД с твоя код и запиши като config/packages/kolichka.yaml:

# Количка споделена кошница <-> Home Assistant списък за пазаруване.
# Постави този файл в config/packages/kolichka.yaml
# и добави в configuration.yaml (веднъж):
#   homeassistant:
#     packages: !include_dir_named packages
input_boolean:
  kolichka_syncing:
    name: Kolichka syncing guard

rest_command:
  kolichka_basket_push:
    url: "https://kolichka.gotvach.com/api/fambasket/ВАШИЯТ_КОД"
    method: PUT
    content_type: "application/json"
    payload: "{{ payload }}"

sensor:
  - platform: rest
    name: Kolichka Family Basket
    unique_id: kolichka_family_basket
    resource: "https://kolichka.gotvach.com/api/fambasket/ВАШИЯТ_КОД"
    scan_interval: 30
    value_template: "{{ value_json.remaining }}"
    json_attributes: [items, remaining_names, count, updated_at]

automation:
  # PULL: кошница от приложението -> списък в HA (приложението е водещо)
  - id: kolichka_pull_to_ha
    alias: "Количка: кошница -> списък за пазаруване"
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: sensor.kolichka_family_basket
      - platform: homeassistant
        event: start
      - platform: time_pattern
        minutes: "/2"
    action:
      - service: input_boolean.turn_on
        target: { entity_id: input_boolean.kolichka_syncing }
      - variables:
          want: "{{ state_attr('sensor.kolichka_family_basket','items') | default([], true) }}"
          want_names: "{{ (state_attr('sensor.kolichka_family_basket','items') | default([], true)) | map(attribute='n') | list }}"
      - service: todo.get_items
        target: { entity_id: todo.shopping_list }
        data: { status: [needs_action, completed] }
        response_variable: cur
      - variables:
          have: "{{ cur['todo.shopping_list']['items'] | default([], true) }}"
          have_names: "{{ (cur['todo.shopping_list']['items'] | default([], true)) | map(attribute='summary') | list }}"
      - repeat:
          for_each: "{{ want }}"
          sequence:
            - if: "{{ repeat.item.n not in have_names }}"
              then:
                - service: todo.add_item
                  target: { entity_id: todo.shopping_list }
                  data: { item: "{{ repeat.item.n }}" }
      - repeat:
          for_each: "{{ have }}"
          sequence:
            - if: "{{ repeat.item.summary not in want_names }}"
              then:
                - service: todo.remove_item
                  target: { entity_id: todo.shopping_list }
                  data: { item: "{{ repeat.item.summary }}" }
      - repeat:
          for_each: "{{ want }}"
          sequence:
            - variables:
                m: "{{ have | selectattr('summary','eq',repeat.item.n) | list }}"
            - if: "{{ (m | length > 0) and ((m[0].status == 'completed') != (repeat.item.b | bool)) }}"
              then:
                - service: todo.update_item
                  target: { entity_id: todo.shopping_list }
                  data:
                    item: "{{ repeat.item.n }}"
                    status: "{{ 'completed' if repeat.item.b else 'needs_action' }}"
      - delay: "00:00:02"
      - service: input_boolean.turn_off
        target: { entity_id: input_boolean.kolichka_syncing }

  # PUSH: промяна в списъка на HA -> кошницата в приложението
  - id: kolichka_push_to_app
    alias: "Количка: списък за пазаруване -> кошница"
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: todo.shopping_list
    condition:
      - "{{ is_state('input_boolean.kolichka_syncing','off') }}"
    action:
      - service: todo.get_items
        target: { entity_id: todo.shopping_list }
        data: { status: [needs_action, completed] }
        response_variable: cur
      - variables:
          items: "{{ cur['todo.shopping_list']['items'] | default([], true) }}"
          payload: >-
            {"items":[{% for it in items %}{"n":{{ it.summary | to_json }},"b":{{ (it.status == 'completed') | lower }}}{{ "," if not loop.last else "" }}{% endfor %}]}
      - service: rest_command.kolichka_basket_push
        data:
          payload: "{{ payload }}"

Как работи

За разработчици: Family Basket API

Публично, без токен. Кодът е достъпът.

GET /api/fambasket/{code} → {"code","items":[{"n":name,"b":bought}],"count","remaining","bought","remaining_names","updated_at"}
PUT /api/fambasket/{code}  body {"items":[{"n":name,"b":bought}]} → {"ok":true,"updated_at"}
POST /api/fambasket  body {"items":[...]} → creates a new basket, returns {"code"}

# Пример
curl https://kolichka.gotvach.com/api/fambasket/442834
curl -X PUT https://kolichka.gotvach.com/api/fambasket/442834 \
  -H "Content-Type: application/json" \
  -d '{"items":[{"n":"мляко","b":false},{"n":"хляб","b":true}]}'

Често задавани въпроси

Трябва ли ми акаунт или токен?

Не. Кошницата се ползва само с код. API-то е публично и без токен — код-ът е достъпът.

Колко бързо се синхронизира?

Приложение → Home Assistant: до 30 секунди (REST сензорът чете на всеки 30 сек). Home Assistant → приложение: до няколко секунди на сървъра; в приложението се вижда при следващото отваряне/опресняване на екрана Кошница.

Списъкът в HA е празен, какво да проверя?

Увери се, че обектът todo.shopping_list не е изключен (Настройки → Устройства и услуги → Обекти) и че кодът в kolichka.yaml съвпада с този в приложението. Провери и че интеграцията „Shopping list“ е добавена.

Мога ли да ползвам своя код вместо да редактирам файлове?

Да — просто замени ВАШИЯТ_КОД с твоя код в примера. Всичко останало остава същото.

Работи ли с гласов асистент?

Да. Понеже ползва вградения todo.shopping_list, всичко, което добавиш през Assist/гласов асистент, се синхронизира обратно към приложението.