Введение Я уже давно использую HomeAssistant для домашней автоматизации.
Однажды друг спросил меня, почему HomeAssistant имеет возможность указать только текущее положение трекера на карте, но не может отобразить весь маршрут? С тех пор эта идея увлекла меня.
И однажды я понял, что мне очень хочется иметь эту функцию прямо сейчас.
Всем, кому интересно, что из этого получилось, добро пожаловать под кат.
Разведка
Собственно, чтобы отобразить маршрут, нужно иметь набор точек с координатами, поэтому первым делом нужно было выяснить, где HomeAssistant хранит необходимые данные (если он их вообще хранит) и как их оттуда получить.Небольшое изучение первоисточника сразу привело к решению: необходим включенный модуль регистратора для записи в базу данных состояний нужных датчиков в различные моменты времени, а также модуль истории, позволяющий получать данные из база данных в красивом виде.
Модуль истории имеет хорошо документированную ОТДЫХ API .
Именно то, что нужно! Далее нужно как-то отобразить полученные данные на карте.
Существует множество различных сервисов, которые позволяют отображать историю ваших перемещений.
Наверное, я не все пробовал, но позволю себе пару слов о тех, что опробовал: А .
яндекс и гугл.
Собственно, для моих нужд есть все и даже больше, однако из-за платности услуг и сильных ограничений бесплатных версий они меня не устроили сразу.
Яндекс, например, разрешает бесплатное использование только открытых проектов (то есть каждый должен иметь возможность в любой момент открыть ваш ресурс и воспользоваться его возможностями), не говоря уже о других ограничениях на количество запросов.
Об изменениях в политике API Google не написал только ленивый.
На данный момент, насколько я понимаю, каждый запрос к API карт или API маршрутов платный; чем больше запросов, тем дешевле.
Однако каждому пользователю, к аккаунту которого подключена банковская карта, предоставляется бесплатный лимит в размере 200 долларов в месяц.
Все вышеперечисленное сразу оплачивается с вашей карты.
Привязывать карту к счету – это не наш путь.
Поправьте меня, если я где-то ошибся насчет гугла и/или яндекса.
Б .
Связка ОпенРоутСервис и карты OpenRouteService. В принципе, по возможностям он мало чем отличается от гугла или яндекса (по крайней мере я не заметил).
Полностью бесплатно (есть ограничения на количество запросов в день и в минуту, при превышении рекомендуется обращаться в службу поддержки.
описания платных тарифов вообще нет).
Однако пользоваться ресурсом карт OpenRouteService оказалось неудобно (долгая загрузка приложения и раздражающее широкое меню слева, которое открывается по умолчанию и не может быть отключено с помощью API; к тому же с мобильного сервис открывается не совсем корректно устройства).
Справедливости ради, карты OpenRouteService можно установить на свой сервер и вполне возможно, что вы сможете там все настроить под себя.
В .
Наткнулся на хабре за интересную реализацию карточек в простом формате.
В принципе, проект абсолютно подходит под мою задачу, но из этой статьи я узнал о Листовка и решил обратиться к источнику.
Наконец-то я на этом остановился.
г .
Листовка.
Очень хорошая js-библиотека с открытым исходным кодом для карт, простая в освоении и хорошо документированная.
Из особенностей: позволяет использовать тайлы от многих сервисов (openstreetmaps, yandex, google, мапбокс, майкрософт и т.д. и т.п.
).
Дополнительно я использовал плагин Leaflet.polylineDecorator для указания направления движения на карте.
Стоит отметить, что два последних рассматриваемых ресурса не поддерживают «маршруты», то есть не умеют соединять точки вдоль существующих дорог и/или тротуаров, а просто соединяют точки прямой линией.
Лично для меня это не проблема, а осознанный шаг.
Если вам нужна дорожная навигация, то нужно смотреть в сторону платного Google, Яндекса или бесплатного openrouteservice.
Выполнение
Запрос к модулю истории через REST-API достаточно прост (здесь и далее код будет на языке HomeAssistant, то есть Python) и позволяет получить ответ в виде понятного JSON:здесь self._haddr — адрес вашего ХА, такой же, как указан в настройках фронтенда, self._myid — идентификатор устройства_трекера, маршрут которого мы будем строить, dayBegin — начало периода отображения маршрута, я выбрал с начала текущего дня по умолчанию self._token — это долгосрочный токен для доступа к API, который можно получить в интерфейсе HomeAssistant. Когда объект, историю которого мы пытаемся отобразить на карте, длительное время стоит неподвижно или движется крайне медленно, мы получим кучу точек, которые расположены близко друг к другу и засоряют карту.response = requests.get(self._haddr + '/api/history/period/' + dayBegin + 'Эfilter_entity_id=' + self._myid, headers={'Authorization': 'Bearer ' + self._token, 'content-type': 'application/json'}) data = response.json()[0]
Чтобы исправить ситуацию, пропустим полученный массив координат через фильтр: если расстояние между предыдущей точкой и следующей меньше 100 метров, то не отображать точку на карте.
Для расчета расстояний между двумя соседними точками воспользуемся упрощенной формулой с равноугольное приближение .
Аппроксимация применима, когда расстояние между соседними точками не превышает нескольких км: def getDistance(self, latA, lonA, latB, lonB):
dst = 0
latRadA = math.radians(latA)
lonRadA = math.radians(lonA)
latRadB = math.radians(latB)
lonRadB = math.radians(lonB)
x = latRadB - latRadA
y = (lonRadB-lonRadA)*math.cos((latRadB+latRadA)*0.5)
dst = 6371*math.sqrt(x*x+y*y)
return dst
Здесь dst — расстояние в км.
Я не вижу здесь никакого смысла описывать Leaflet API. За этим - на официальный сайт .
Модуль работает следующим образом: Каждые n секунд (у меня установлено 300) делается запрос к сегодняшней истории интересующего меня объекта.
Полученный массив координат пропускается через фильтр расстояний, уменьшая количество точек.
Далее в папке конфигурации HomeAssistant в папке www создаются 2 файла: index.html иroute.html. Файл маршрута.
html содержит всю логику создания карты.
А файл index.html — это лайфхак для предотвращения кэширования страниц.
По умолчанию HomeAssistant кеширует все, что может, и только сброс кеша помог обновить данные на карте, что, конечно, недопустимо.
В файле index.html вызывается содержимое маршрута.
html, но со случайным, динамически генерируемым параметром, который позволяет всегда запрашивать с сервера текущую версию файла маршрута.
html: src = 'route.htmlЭdatetime=' + (new Date()).
getTime() + Math.floor(Math.random() * 1000000)
Немного о безопасности
HomeAssistant устроен таким образом, что все файлы внутри каталога www являются общедоступными, то есть любой файл внутри каталога www можно открыть в любом браузере без какой-либо авторизации, если вы знаете прямую ссылку.В случае моего модуля эта ссылка выглядит так: your_address_homeassistant/local/route/index.html .
Если для вас это не критично, то этот раздел можно пропустить.
Я пошел немного дальше и прикрепил авторизацию к странице с маршрутами.
Для этого я использовал nginx (вы можете выбрать другой веб-сервер с поддержкой обратного прокси) в качестве прокси-сервера.
На сайте HomeAssistant есть официальный инструкции для настройки этой конфигурации.
После настройки прокси и проверки его работы необходимо в конфигурацию nginx добавить авторизацию для нужных страниц: location /local/route/route.html {
proxy_pass http://localhost:8123/local/route/route.html ;
proxy_set_header Host $host;
proxy_redirect http:// https://;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
auth_basic "Unauthorized";
auth_basic_user_file /etc/nginx/.
htpasswd;
}
Затем создайте файл «/etc/nginx/.
htpasswd» и выполните в консоли следующие команды: sh -c "echo -n 'admin:' >> /etc/nginx/.
htpasswd" sh -c "openssl passwd -apr1 >> /etc/nginx/.
htpasswd"
admin – замените на нужный логин.
После этого перезапускаем nginx и проверяем: при попытке открыть страницу с маршрутом браузер должен запросить логин и пароль.
Замечу, что это отдельная авторизация, никак не связанная с авторизацией самого HomeAssistant.
Заключение
Это пожалуй все, что можно сказать об этом модуле.Кому интересно? Ссылка здесь за модуль.
Поместите файл по пути: config_folder_homeassistant/custom_comComponents/route/sensor.py, не забудьте про права.
Если ее нет, то создайте папку config_folder_homeassistant/www и дайте ей соответствующие права.
В файле конфигурации Configuration.yaml пропишите следующие строки: sensor:
- platform: route
name: route
entityid: your_device_tracker_entity_id
haddr: your_address_homeassistant
token: your_long_life_token
здесь your_device_tracker_entity_id — это идентификатор вашего устройства device_tracker, your_address_homeassistant — это внешний адрес вашего HomeAssistant, your_long_life_token — это токен доступа, ранее полученный во внешнем интерфейсе HomeAssistant для использования REST API.
После этого перезапустите HomeAssistant и наслаждайтесь.
Карта будет доступна по прямой ссылке: your_address_homeassistant/local/route/index.html .
При желании вы можете добавить его в меню HA с помощью Panel_iframe или в любое окно HA через карточку ловеласа «iframe».
На этом все, спасибо за внимание.
УПД: Добавлен связь на Гитхабе.
Некоторые места улучшил (убрал Haddr из конфигурации, config_dir получаю автоматически, добавил возможность устанавливать свой часовой пояс) И как все это выглядит? Будь осторожен, размытие!
Теги: #Умный дом #домашний помощник #gps маршруты
-
Библиотека Сериализации Json Для Erlang
19 Oct, 24 -
Как Работает Локализация В Netflix — Перевод
19 Oct, 24 -
Agile Ит-Консалтинговые Проекты?
19 Oct, 24 -
Дизайнеры! Умеешь Ли Ты Рисовать От Руки?
19 Oct, 24 -
Конференция Drupalconf – 3 Декабря В Москве!
19 Oct, 24