65. Home Assistant + предупреждение о ракетных обстрелах для Израиля.

В современной реальности к сожалению есть ситуации когда необходимо действовать максимально быстро для сохранения жизни и здоровья. Одна маленькая, но гордая страна имеет вокруг своих границ не самых доброжелательных соседей, и поэтому вынуждена заботиться о выживании собственных граждан любым способом. Умный дом в этом тоже может помочь, своевременно предупредив об опасной ситуации.Армейская служба тыла сделала сайт, на котором в режиме реального времени показываются места потенциального падения ракет, чтобы люди могли успеть укрыться в защищённых помещениях. Так же есть несколько приложений для мобильных платформ, подключенных к той же системе оповещения, чтобы предупреждать людей об опасности.


Раз есть что-то что оповещает о каком-то событии, то можно сделать так, чтобы умный дом тоже принимал это оповещение. А если событие будет зарегистрировано в системе Home Assistant, то на его основе уже можно делать какие-то другие вещи.

Способ первый - интеграция.

Мир полон энтузиастами, которые делают замечательные вещи и делятся ими со всеми. Так, например Amit Finkelstein сделал прекрасную интеграцию, а автор этого блога помог с переводом на русский язык и добавил несколько идей для реализации. На данный момент это один из самых удачных проектов в плане удобства использования и точности определения оповещений.
Для начала ставим саму интеграцию Oref Alert с помощью HACS. Для этого достаточно нажать на кнопку

После этого необходимо настроить установленную интеграцию. Для этого можно нажать другую кнопку

Интеграция поддерживает 3 языка отображения (иврит, русский, английский). И работает на том, который настроен для отображения интерфейса всей системы.
Конфигурация и работа с этим модулем очень просты.
Интеграция создаёт 1 бинарный сенсор, в атрибутах которого отображается вся информация о сработавших оповещениях за последние сутки.
В статусе же будут отображаться города и регионы выбранные пользователем. Можно выбрать несколько населённых пунктов.
Соответственно этот бинарный сенсор будет переходить в положение ВКЛ когда хотя бы в одном из выбранных населённых пунктов есть тревога.
Если необходимо создать ещё один сенсор для другого населённого пункта или их группы, то это можно сделать с помощью соответствующей службы. Для этого необходимо зайти в панель инструментов разработчика, перейти к службам, и выбрать службу этого дополнения.

Все созданные таким образом сенсоры, будут иметь вид: binary_sensor.oref_alert_название.

Чтобы стереть ненужный сенсор, необходимо вызвать аналогичную службу, но предназначенную для удаления сенсоров. Она позволит удалить сущность созданную с помощью вышеуказанного способа.

Если необходимо добавить бинарный сенсор, который бы срабатывал при тревоге в любой части страны, то шаблон для его создания будет таким: {{ state_attr('binary_sensor.oref_alert', 'country_active_alerts') | length > 0 }}.

Так же, интеграция создаёт дополнительный сенсор, который показывает сколько времени есть для укрытия от ракет в выбранной области, в соответствии с инструкциями Службы Тыла для этой области (например, 90 секунд в центре Израиля).
Название этого сенсора похоже на соответствующий бинарный датчик, но с добавлением _time_to_shelter. Например, sensor.oref_alert_time_to_shelter.
Когда в выбранной области срабатывает оповещение о тревоге, сенсор показывает, сколько секунд есть для того чтобы укрыться.
Со временем число в состоянии сенсора уменьшается и становится неизвестным, когда проходит минута после окончания тревоги.
Эта сущность имеет следующие дополнительные атрибуты:
Area: название выбранного региона.
Time to shelter: рекомендованное значение согласно указаниям Службы Тыла для выбранного региона (это число не меняется).
Alert: есть ли сейчас тревога или нет.

Для отображения текущих угроз в интерфейсе, можно сделать следующее:


1. Создать хелпер бинарного сенсора: Oref Alert All Country

2. Использовать для него следующий шаблон: {{ state_attr('binary_sensor.oref_alert', 'country_active_alerts') | length > 0 and (as_timestamp(now()) - as_timestamp(strptime(state_attr('binary_sensor.oref_alert', 'country_active_alerts')[0]['alertDate'], '%Y-%m-%d %H:%M:%S'))) / 60 <= state_attr('binary_sensor.oref_alert', 'alert_max_age') }}

3. В интерфейсе использовать карточку условий (Conditional card). Условием будет состояние ВКЛ только что созданного бинарного сенсора.

4. В качестве отображаемой при таком условии карточки будет Markdown. Она будет показывать угрозы сработавшие в последние 10 минут (или другое время выбранное пользователем при настройке). Код карточки выглядит так:
{% for alert in (state_attr('binary_sensor.oref_alert', 'country_active_alerts') or []) %}
  <ha-alert alert-type="error">
    {{ alert['data'] }} 
    [{{ alert['title'] }}]
    ({{ alert['alertDate'] | as_timestamp | timestamp_custom('%H:%M:%S') }})
  </ha-alert>
{% endfor %}

Для отображения истории угроз с начала текущих суток, можно создать отдельный дэшборд, в котором без всяких условий будет добавлена всё та же карточка Markdown.


Код для этой карточки выглядит так:
{% set current_date = now().strftime('%Y-%m-%d') %}
{% set alerts = state_attr('binary_sensor.oref_alert', 'country_alerts') or [] %} {{ alerts | selectattr('alertDate', 'ge', current_date) | list | length }} Alerts in all country for today.
{% for alert in alerts | selectattr('alertDate', 'ge', current_date) %}
  <ha-alert alert-type="error">
    {{ alert['data'] }} 
    [{{ alert['title'] }}]
    ({{ alert['alertDate'] | as_timestamp | timestamp_custom('%H:%M:%S') }})
  </ha-alert>
{% endfor %}

Второй способ - дополнение.

Для начала стоит отметить что первый способ на самом деле основан на работе способа рассмотренного ниже.
Прежде всего нужен Appdaemon - среда для запуска кода написанного на языке Python (пайтон, питон). Процесс установки и настройки ранее уже был описан здесь. Очень важно добавить в его конфигурацию дополнительных модулей питона, модуль с названием requests.
Далее необходимо создать новый хелпер на платформе input_text, он будет хранить текст сообщения со списком районов/населённых пунктов где сработала в данный момент воздушная тревога.


 Этот хелпер обязательно должен называться redalert2.


Теперь в текстовом редакторе внутри ХА создаём файл: /config/appdaemon/apps/redalert2.py. Этот файл будет содержать основной код программы, который делает следующее:
  • Каждые 3 секунды подключается к серверу управления службы тыла, чтобы проверить есть ли новые оповещения о тревоге.
  • Если сообщение о тревоге есть, то выцепляет из него только данные со списком населённых пунктов и вставляет их в ранее созданный текстовый сенсор.
  • Если сообщения о тревоге нет, а данные в текстовом сенсоре есть, то они удаляются.
Существует 3 типа тревоги: ракетный обстрел, проникновение террористов, и атака с помощью летательного устройства. Т.к. основное текстовое поле такого сенсора имеет ограничение в 255 символа, то тип тревоги записывается не в состояние этой сущности, а в её атрибут alert_title. Это сделано для того, чтобы освободить место в статусе для дополнительных символов, на случай если список населённых пунктов будет большим. И чтобы вместить максимально большое количество названий.

На скриншоте указано 300 символов в качестве эксперимента, в целях проверки.

Таким образом, сенсор input_text.redalert2 будет находиться в точно таком же состоянии как и сервер службы тыла, с максимальным отставанием от него на 3 секунды (плюс время на скорость связи, зависящее от качества интернета).

Если нужна бОльшая частота обращений к серверу чтобы получать оповещения ещё быстрее, можно сократить параметр interval (строка 8) вплоть до минимально испытанного значения в 0,01 секунды.

Собственно сам код:
import requests
import time
import json
import codecs
from datetime import datetime
from appdaemon.plugins.hass.hassapi import Hass

interval = 3

class RedAlert2(Hass):
    def initialize(self):
        self.run_every(self.poll_alerts, datetime.now(), interval)

    def poll_alerts(self, kwargs):
        url = "https://www.oref.org.il/WarningMessages/alert/alerts.json"
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
            'Referer': 'https://www.oref.org.il/',
            'X-Requested-With': 'XMLHttpRequest',
            'Content-Type': 'application/json',
        }

        try:
            response = requests.get(url, headers=headers)
            if response.status_code == 200:
                response_data = codecs.decode(response.content, 'utf-8-sig')
                current_value = self.get_state("input_text.redalert2")
                if response_data.strip():
                    try:
                        data = json.loads(response_data)
                        if 'data' in data and data['data']:
                            alert_title = data['title']
                            alerts_data = ', '.join(data['data'])
                            if not current_value or current_value != alerts_data:
                                self.call_service("input_text/set_value", entity_id="input_text.redalert2", value=alerts_data)
                                self.set_state("input_text.redalert2", state=alerts_data, attributes={"alert_title": alert_title})
                    except json.JSONDecodeError:
                        self.log("Error: Invalid JSON format in the response.")
                else:
                    if current_value:
                        self.call_service("input_text/set_value", entity_id="input_text.redalert2", value="")
                        self.set_state("input_text.redalert2", state="", attributes={"alert_title": ""})
            else:
                self.log(f"Failed to retrieve data. Status code: {response.status_code}")
        except Exception as e:
            self.log(f"Error: {e}")

После сохранения изменений, необходимо открыть файл /config/appdaemon/apps/apps.yaml и добавить в него следующие строки:
redalert2:
  module: redalert2
  class: RedAlert2

Рекомендуется теперь проверить лог дополнения аппдемон, чтобы убедиться что приложение запускается без ошибок.


Финальный этап это создание бинарного сенсора, который будет переключаться в положение ВКЛ, при наличии нужного населённого пункта в списке внутри текстового сенсора.
Для этого создаём соответствующий хелпер на платформе шаблонов.


Код шаблона:
{{ states('input_text.redalert2') is defined and 'GOROD' in states('input_text.redalert2') }}
Слово GOROD заменяем на название нужного населённого пункта, предварительно сверившись с написанием на сайте управления тылом. Название конечно же должно быть написано на иврите.

Теперь максимально легко и просто создать автоматизацию которая будет включать сирену, моргать светом, отсылать оповещения на телефон и делать вообще что угодно, если есть угроза в выбранном районе.

Всем мира.

Комментарии

Отправить комментарий