Home Assistant: Интернет радио

16 марта, 2021Изменена: 4 ноября, 2023 в 11:43

На заре своего знакомства с HA меня посетила мысль о том, что было бы неплохо реализовать в его интерфейсе возможность запуска воспроизведения ряда интернет-радиостанций на имевшихся у меня тогда устройствах Google Chromecast. После некоторого кол-ва проб и ошибок у меня получилось вполне рабочее решение, которое я недавно слегка переписал и хочу поделится им здесь.

Это решение позволяет выбрать на каком устройстве запустить воспроизведение, выбрать радиостанцию из заранее определенного списка, а так же изменять громкость воспроизведения.
В моем случае все это работает с Google Home Mini и Google Chromecast подключенными к ТВ, возможно будет работать и с другими объектами media_player, поддерживающими потоковое воспроизведение через интернет.
! Насколько я знаю, на текущий момент с Яндекс Станциями это не работает.

Интерфейс собран из стандартных элементов, за исключением одной кастомной карточки vertical-stack-in-card позволяющей убрать лишнее пространство между ними:

В YAML’е это выглядит вот так:

- type: vertical-stack
  cards:
    - type: markdown
      content: > 
        ### Радио:
    - type: custom:vertical-stack-in-card
      cards:
        - type: entities
          entities:
            - input_select.radio_station
            - input_select.output_device
        - type: entities
          entities:
            - input_number.volume_radio
        - type: horizontal-stack
          cards:
            - type: button
              show_name: false
              icon_height: 32px
              tap_action:
                action: call-service
                service: script.turn_on
                service_data:
                  entity_id: script.radio_play
              entity: script.radio_play
            - type: button
              show_name: false
              icon_height: 32px
              tap_action:
                action: call-service
                service: script.turn_on
                service_data:
                  entity_id: script.radio_stop
              entity: script.radio_stop

Весь код относящийся к радио я собрал в одном пакете (package), можете посмотреть или скачать его у меня на GitHub.
Здесь же я попробую более подробно описать механизм работы.

Для выбора радиостанции и медиаплеера используются два элемента input_select:

input_select:
  radio_station:
    name: 'Радиостанция:'
    options:
      - Радио Jazz
      - Monte Carlo
      - Monte Carlo Lounge
      - Наше Радио
      - ENERGY
      - Русское Радио
      - Maximum
      - Детское Радио
      - Детское Радио (Старое радио)

  output_device:
    name: 'Где включить:'
    options:
      - Гостинная (Home Mini)
      - Гостинная (TV)
      - Детская (Home Mini)
      - Детская (TV)
    initial: Гостинная (Home Mini)
    icon: mdi:speaker-wireless

Т.к. для дальнейшего использования человеческие названия радиостанций и устройств нужно сначала транслировать в URL и имена объектов HA, я сделал две автоматизации – первая на основе выбранного имени радиостанции записывает в объект input_text.radio_url_to_play соответствующий станции URL, а вторая на основе выбранного имени устройства записывает его entity_id в input_text.output_device_to_play. Объекты input_text в данном случае выступают в роли глобальных переменных, значения которых можно многократно использовать в скриптах или автоматизациях.

automation:
  - alias: "Radio - Selected Name to URL"
    trigger:
      # При загрузке
      - platform: homeassistant
        event: start
      # При выборе радиостанции в input_select'е
      - platform: state
        entity_id: input_select.radio_station
    action:
      # Обновляем значение в input_text
      - service: input_text.set_value
        data:
          entity_id: input_text.radio_url_to_play
          # В зависимости от названия станции, записываем в input_text нужный URL
          value: >-
            {% if is_state("input_select.radio_station", "Радио Jazz") -%}
              

            {% elif is_state("input_select.radio_station", "Monte Carlo") -%}
              
            {% elif is_state("input_select.radio_station", "Monte Carlo Lounge") -%}
              http://stream.zeno.fm/953wvvz4gseuv
            {% elif is_state("input_select.radio_station", "Наше Радио") -%}
              
            {% elif is_state("input_select.radio_station", "ENERGY") -%}
              http://ic2.101.ru:8000/v1_1
            {% elif is_state("input_select.radio_station", "Русское Радио") -%}
              
            {% elif is_state("input_select.radio_station", "Maximum") -%}
              
            {% elif is_state("input_select.radio_station", "Детское Радио") -%}
              http://ic7.101.ru:8000/a199
            {% elif is_state("input_select.radio_station", "Детское Радио (Старое радио)") -%}
              http://195.91.237.50:8000/detskoe128
            {% endif %}

   - alias: "Radio - Selected Name to Device"
    trigger:
      # При загрузке
      - platform: homeassistant
        event: start
      # При выборе радиостанции в input_select'е
      - platform: state
        entity_id: input_select.output_device
    action:
      # Обновляем значение в input_text
      - service: input_text.set_value
        data:
          entity_id: input_text.output_device_to_play
          # В зависимости от названия устройства, записываем в input_text его entity_id
          value: >-
            {% if is_state("input_select.output_device", "Гостинная (TV)") -%}
              media_player.gostinaia
            {% elif is_state("input_select.output_device", "Гостинная (Home Mini)") -%} 
              media_player.googlehome9967
            {% elif is_state("input_select.output_device", "Детская (TV)") -%}
              media_player.detskaia
            {% elif is_state("input_select.output_device", "Детская (Home Mini)") -%}
              media_player.googlehome3792
            {% endif %}

Эти автоматизации запускаются однократно при загрузке HA, а также при каждом выборе станции или устройства, обновляя таким образом значения в переменных (input_text’ах).

Для запуска и остановки воспроизведения (кнопки Play\Stop) используются следующие скрипты:

script:
  # Скрипт для кнопки Play
  radio_play:
    alias: Play Internet Radio
    sequence:
      # Если в имени устройства присутствует (TV) - предварительно выполнить shell_command.chromecast_tv_on
      - choose:
        - conditions: "{{ '(TV)' in states('input_select.output_device') }}"
          sequence:
            - service: shell_command.chromecast_tv_on
              data:
                # В зависимости от имени устройства выбирается IP Хромкаста
                ip_addr: >-
                  {% if is_state("input_select.output_device", "Гостинная (TV)") -%}
                    "172.16.16.211"
                  {% elif is_state("input_select.output_device", "Детская (TV)") -%}
                    "172.16.16.212"
                  {% endif %}
      # Устанавливается громкость, выбранная в интерфейсе
      - service: media_player.volume_set
        data:
          entity_id: "{{ states('input_text.output_device_to_play') }}"
          volume_level: "{{ states.input_number.volume_radio.state }}"
      # Запускается проигрывание выбранного URL на выбранном устройстве
      - service: media_player.play_media
        data:
          entity_id: "{{ states('input_text.output_device_to_play') }}"
          media_content_id: "{{ states('input_text.radio_url_to_play') }}"
          media_content_type: music

  # Скрипт для кнопки Stop
   radio_stop:
    alias: Stop Internet Radio
    sequence:
      # Выключение устройства выбранного в интерфейсе
      - service: media_player.turn_off
        data:
          entity_id: "{{ states('input_text.output_device_to_play') }}"

Здесь стоит обратить внимание, что при выборе в качестве устройства Хромкаста, на него предварительно посылается команда (shell_command.chromecast_tv_on), которая заставляет его включить ТВ с помощью CEC. При этом в атрибуте ip_addr передается IP адрес нужного устройства.

Команда для включения ТВ с помощью Chromecast:

shell_command:
  chromecast_tv_on: "curl -s -X POST -H \"Content-Type: application/json\" -H \"Host: {{ ip_addr }}:8008\" -d '{\"use_channel\":true,\"allow_restart\":true,\"allow_empty_post_data\":true,\"app_id\":\"00000000-0000-0000-0000-000000000000\",\"url\":\"chrome://home?remote_url=https%3A%2F%2Fclients3.google.com%2Fcast%2Fchromecast%2Fhome%3Fchs%3D1\",\"dial_enabled\":true}' http://{{ ip_addr }}:8008/apps/00000000-0000-0000-0000-000000000000"

В моем случае это прекрасно работает на разных поколениях ТВ от Samsung c Chromecast’ами 1-го и 3-го поколений. После выполнения этого запроса ТВ будет включен, а видеовход переключен на тот, в который подключен Хромкаст.

Ну и наконец, управление громкостью реализовано с помощью input_number и одной автоматизации:

input_number:
  volume_radio:
    name: Громкость
    icon: mdi:volume-high
    initial: 0.30
    min: 0
    max: 1
    step: 0.05

automation:
  - alias: "Radio - Volume Control"
    trigger:
      # При изменении значения input_number
      platform: state
      entity_id: input_number.volume_radio
    action:
      # Установить выбранную громкость (input_number) на выбранном устройстве (input_text)
      service: media_player.volume_set
      data:
        entity_id: "{{ states('input_text.output_device_to_play') }}"
        volume_level: "{{ states('input_number.volume_radio') }}"