Да, подключил и Звифт к “Умному дому” 🙂
Пока ограничился только LED-подсветкой на мониторе, меняющей цвет в зависимости от пульса и мощности. Позже, возможно, сделаю управление вентиляторами – хотя мне они обычно требуются всегда на максимальной мощности.
LED-лента на мониторе – уже вторая реализация; первая была на мониторе на рабочем месте. Правда, та пока только предупреждает при воздушных тревогах, потом расширю автоматизацию.
Вернемся к Zwift’у. Для интеграции в Home Assistant (Core):
- Качаем это.
- Размещаем в $HOME у Home Assistant по пути ~/.homeassistant/custom_components/zwift/ содержимое каталога по ссылке выше (~/.homeassistant/ – то, где лежит configuration.yaml, база и так далее).
- На момент написания плагин дефолтно добавляет User ID в Zwift’e к именам и названиям сенсоров. Завел Issue, будет движение или нет – не знаю, но у себя поправил код, чтобы этого не было:
$ diff sensor.py sensor.py.orig
187,188c187,188
< self._unique_id = “{}_{}”.format(self._base_name, SENSOR_TYPES[self._type].get(
< ‘name’)).replace(” “, “”).lower()
—
> self._unique_id = “{}_{}_{}”.format(self._base_name, SENSOR_TYPES[self._type].get(
> ‘name’), self._player.player_id).replace(” “, “”).lower()
198c198
< return “{} {}”.format(self._base_name, SENSOR_TYPES[self._type].get(‘name’))
—
> return “{} {} ({})”.format(self._base_name, SENSOR_TYPES[self._type].get(‘name’), self._player.player_id)
203c203
< return “{} {}”.format(self._base_name, SENSOR_TYPES[self._type].get(‘name’))
—
> return “{} {} ({})”.format(self._base_name, SENSOR_TYPES[self._type].get(‘name’), self._player.friendly_player_id)
- В configuration.yaml добавляем
sensor:
- platform: zwift
username: !secret my_zwift_username
password: !secret my_zwift_password
И в secrets.yaml – логин/пароль. Перезапуск HA (перечитывание конфигов мне почему-то не помогало :(). Дальше в “Настройки – Устройства – Объекты” появляются различные сенсоры. У “Zwift Online” дополнительно есть атрибуты с кучей самых разных данных из Zwift’а.
Исполнение в железе:
Корпус для конструкции решил (пока?) не делать. Подходящих нет; все равно ее там никто не видит, да и внешних воздействий нет. Питание берем прямо с монитора, там 12В. Лента – WS2812B с Али, вариант “60 шт/метр IP30”. На мониторе на нижней стороне разместились 32 штуки. Брал на 5В, как более универсальный. В итоге 12В с монитора через KIS 3R33 (да, надо их утилизировать наконец-то) получаем 5В, а для ESP01 дополнительно стоит l78l33. При настройке KIS 3R33 (резистор примерно на 9,1 кОм между входом регулировки и общим) желательно напряжение чуть-чуть завышать относительно 5В (для более четкой работы 78l33).
Конфиг для ESP01 для ESP Home.
Заводим девайс в HA, дальше автоматизация:
alias: Zwift power led description: "" trigger: - platform: state entity_id: - sensor.zwift_power condition: [] action: - if: - condition: template value_template: >- {{ states("sensor.zwift_power") | float < state_attr("sensor.zwift_online","ftp") | float * 0.6 }} then: - service: light.turn_on metadata: {} data: rgb_color: - 204 - 204 - 204 transition: 0 brightness_pct: 75 target: entity_id: light.dell_zwift_led_power - if: - condition: template value_template: >- {{ state_attr("sensor.zwift_online","ftp") | float * 0.6 <= states("sensor.zwift_power") | float < state_attr("sensor.zwift_online","ftp") | float * 0.75 }} then: - service: light.turn_on metadata: {} data: rgb_color: - 0 - 145 - 255 transition: 0 brightness_pct: 75 target: entity_id: light.dell_zwift_led_power - if: - condition: template value_template: >- {{ state_attr("sensor.zwift_online","ftp") | float * 0.75 <= states("sensor.zwift_power") | float < state_attr("sensor.zwift_online","ftp") | float * 0.89 }} then: - service: light.turn_on metadata: {} data: rgb_color: - 43 - 255 - 0 transition: 0 brightness_pct: 75 target: entity_id: light.dell_zwift_led_power - if: - condition: template value_template: >- {{ state_attr("sensor.zwift_online","ftp") | float * 0.89 <= states("sensor.zwift_power") | float < state_attr("sensor.zwift_online","ftp") | float * 1.04 }} then: - service: light.turn_on metadata: {} data: rgb_color: - 255 - 234 - 0 transition: 0 brightness_pct: 75 target: entity_id: light.dell_zwift_led_power - if: - condition: template value_template: >- {{ state_attr("sensor.zwift_online","ftp") | float * 1.04 <= states("sensor.zwift_power") | float < state_attr("sensor.zwift_online","ftp") | float * 1.18 }} then: - service: light.turn_on metadata: {} data: rgb_color: - 255 - 136 - 0 transition: 0 brightness_pct: 82 target: entity_id: light.dell_zwift_led_power - if: - condition: template value_template: >- {{ state_attr("sensor.zwift_online","ftp") | float * 1.18 <= states("sensor.zwift_power") | float }} then: - service: light.turn_on metadata: {} data: rgb_color: - 255 - 0 - 0 transition: 0 brightness_pct: 95 target: entity_id: light.dell_zwift_led_power mode: single
Пока не знаю, как использовать zwift_online->ftp для расчетов зон – ругается на синтаксис, а то и вообще страница HA виснет (!). Разберусь – поменяю. Update: переделал автоматизацию целиком, теперь подтягивает FTP. Возможно, стоит задать (если его нет) какое-то дефолтное значение на тот случай, если FTP не указан.
Аналогичная автоматизация и для HR-подсветки:
alias: Zwift LED HR description: "" trigger: - platform: state entity_id: - sensor.zwift_heart_rate condition: [] action: - if: - condition: numeric_state entity_id: sensor.zwift_heart_rate below: 108 then: - service: light.turn_on metadata: {} data: rgb_color: - 0 - 204 - 255 transition: 0 brightness_pct: 75 effect: Pulse 1 target: entity_id: - light.dell_zwift_led_hr_r - light.dell_zwift_led_hr_l - if: - condition: numeric_state entity_id: sensor.zwift_heart_rate below: 126 above: 108 then: - service: light.turn_on metadata: {} data: rgb_color: - 4 - 255 - 0 transition: 0 brightness_pct: 75 effect: Pulse 2 target: entity_id: - light.dell_zwift_led_hr_r - light.dell_zwift_led_hr_l - if: - condition: numeric_state entity_id: sensor.zwift_heart_rate below: 144 above: 126 then: - service: light.turn_on metadata: {} data: rgb_color: - 255 - 247 - 0 transition: 0 brightness_pct: 75 effect: Pulse 3 target: entity_id: - light.dell_zwift_led_hr_r - light.dell_zwift_led_hr_l - if: - condition: numeric_state entity_id: sensor.zwift_heart_rate below: 162 above: 144 then: - service: light.turn_on metadata: {} data: rgb_color: - 255 - 115 - 0 transition: 0 brightness_pct: 75 effect: Pulse 4 target: entity_id: - light.dell_zwift_led_hr_r - light.dell_zwift_led_hr_l - if: - condition: numeric_state entity_id: sensor.zwift_heart_rate above: 162 then: - service: light.turn_on metadata: {} data: rgb_color: - 255 - 0 - 0 transition: 0 brightness_pct: 82 effect: Pulse 5 target: entity_id: - light.dell_zwift_led_hr_r - light.dell_zwift_led_hr_l mode: single
Первый пример (до разделения ленты на 3 раздела):
После этого решил вывести мощность в центр, а пульс – по краям и сделать легкую пульсацию для HR (надеюсь, не будет мешать – еще не пробовал).
Да, для partition-сущностей в esphome эффекты надо описывать отдельно.
PS: вообще изначально понравилась эта реализация:
Но тут без каких-либо ссылок. Однако именно тут упоминалось подключение к HA, с чего все и началось.
Update: как-то так:
Update: добавил “Радугу” для like’ов и смены уровня, а также возможность предупреждения о воздушной тревоге. На деле эффект “Радуга” не сильно наглядный по отношению к штатной работе, лучше какой-нибудь “Фейерверк”. Так или иначе, чтобы все работало – в секцию эффектов в esphome добавляем “– addressable_rainbow:” для всей ленты целиком (!), а не разделов. Шьем, дальше можно эффект использовать из Home Assistant.
В свою очередь в HA нужен некий флаг, позволяющий прервать работу основной автоматизации и включить некое уведомление. Идем в “Настройки – Устройства – Вспомогательное“, создаем Template-переключатель. Я его назвал “Dell LED alert”. И дальше в созданных выше автоматизациях добавляем дополнительную проверку – “если созданный переключатель выключен”:
В коде это будет так:
alias: Zwift power led description: "" trigger: - platform: state entity_id: - sensor.zwift_power condition: - condition: state entity_id: input_boolean.dell_led_alert state: "off" action: - if: - condition: template value_template: >- {{ states("sensor.zwift_power") | float < state_attr("sensor.zwift_online","ftp") | float * 0.6 }} ************ и так далее **************
А дальше создаем еще одну автоматизацию и вспомогательный сенсор. Сенсор потребуется, чтобы вытаскивать текущее число лайков из Zwift-сенсора. Идем в “Настройки – устройства – вспомогательное” и создаем сенсор-шаблон вида
{{ state_attr("sensor.zwift_online","latest_activity").activityRideOnCount | float
}}
Возможно, можно вытаскивать значение и прямо в автоматизации, но я остановился на таком варианте.
А дальше – в автоматизации используем изменения этого числа, как триггер. И по срабатыванию триггера включаем созданную ранее блокировку, мигаем лентой так, как нам надо и в конце – выключаем блокировку:
alias: Zwift Ride On and LVLs description: "" trigger: - platform: state entity_id: - sensor.zwift_ride_ons - platform: state entity_id: - sensor.zwift_online attribute: playerLevel condition: [] action: - service: input_boolean.turn_on metadata: {} data: {} target: entity_id: input_boolean.dell_led_alert - service: light.turn_on metadata: {} data: effect: Rainbow target: entity_id: light.dell_zwift_led_light - delay: hours: 0 minutes: 0 seconds: 5 milliseconds: 0 - service: light.turn_off metadata: {} data: {} target: entity_id: light.dell_zwift_led_light - service: input_boolean.turn_off metadata: {} data: {} target: entity_id: input_boolean.dell_led_alert mode: single
Аналогичным образом сделано и уведомление о воздушных тревогах: в автоматизации воздушки добавлено выключение основной автоматизации Звифта, мигаем несколько раз красным, дальше снимаем блок и по первому же событию у нас продолжается отображение мощности и пульса.
Update: при окончании trial-периода в 2 недели API перестает работать – т.е., перестает работать и подсветка, даже если в профиль добавлена платежная карта и сам по себе Zwift продолжает работать во время попыток списать деньги с карты.
Одна мысль про “Zwift, Home Assistant и LED-подсветка”