O Big brother está assistindo ... ele ou um mapa com a história dos movimentos no HomeAssistant

Entrada


Para minha automação residencial, uso o HomeAssistant há muito tempo. Quando um amigo me perguntou, eles disseram: por que o HomeAssistant tem a capacidade de indicar apenas a posição atual do rastreador no mapa, mas não é possível exibir a rota inteira? Desde então, essa ideia me capturou. E uma vez percebi que realmente quero ter essa função agora. Todo mundo que está interessado no que aconteceu, seja bem-vindo ao gato…

Inteligência


Na verdade, para exibir a rota, você precisa ter um conjunto de pontos com coordenadas; portanto, o primeiro passo foi descobrir onde o HomeAssistant armazena os dados necessários (se houver) e como obtê-los. Um breve estudo da fonte primária levou imediatamente à solução: você precisa do módulo gravador incluído para registrar o status dos sensores desejados no banco de dados em diferentes momentos no tempo, bem como do módulo de histórico, que permite obter dados do banco de dados de uma maneira bonita. O módulo de histórico possui uma API REST bem documentada. O que você precisa!

Em seguida, você precisa exibir de alguma forma os dados recebidos no mapa. Existem muitos serviços diferentes que permitem exibir o histórico dos movimentos. Provavelmente tentei longe de todos eles, mas vou me permitir algumas palavras sobre as que verifiquei:
A. yandex e google. Na verdade, para minhas necessidades, há de tudo e ainda mais, mas devido aos serviços pagos e às fortes restrições das versões gratuitas, eles não me agradaram imediatamente. O Yandex, por exemplo, permite o uso gratuito apenas para projetos abertos (ou seja, qualquer pessoa deve poder abrir seu recurso a qualquer momento e tirar proveito de seus recursos), sem mencionar outras restrições ao número de solicitações. Somente os preguiçosos não escreveram sobre alterações nas políticas do Google em relação à API. No momento, pelo que entendi, cada solicitação de mapas da API ou direções da API é paga, mais solicitações - mais baratas. No entanto, cada usuário com um cartão bancário conectado à sua conta recebe um limite gratuito de US $ 200 por mês. Tudo no topo é pago imediatamente no seu cartão. Vincular um cartão a uma conta não é o nosso caminho.

Corrija se cometi um erro em algum lugar sobre o google e / ou yandex.

B. Vários mapas OpenRouteService e OpenRouteService. Em princípio, os recursos não são muito diferentes do google ou yandex (em qualquer caso, eu não percebi). Completamente gratuito (há restrições no número de solicitações por dia e por minuto, se excedido, é aconselhável entrar em contato com o suporte ... não há descrição de tarifas pagas). No entanto, o uso do recurso de mapas OpenRouteService acabou sendo inconveniente (carregamento longo do aplicativo e o menu amplo e irritante à esquerda, que é aberto por padrão e não é desabilitado pela API, além disso, o serviço não é aberto corretamente a partir de dispositivos móveis). Para ser justo, os mapas do OpenRouteService podem ser colocados no seu servidor e é bem possível que você possa configurar tudo por si mesmo.

B. Mapbbcode Eu me deparei com uma implementação interessante de cartões em um formato simples. Em princípio, o projeto é absolutamente adequado para minha tarefa, no entanto, a partir deste artigo, aprendi sobre o Leaflet e decidi recorrer à fonte. No final, ele parou nisso ...

G. Folheto. Muito boa biblioteca js de código aberto para mapas, fácil de aprender e bem documentada. Dos chips: permite usar blocos de vários serviços (openstreetmaps, yandex, google, mapbox, microsoft, etc., etc.). Além disso, usei o plug-in leaflet.polylineDecorator para indicar a direção do movimento no mapa.

Vale ressaltar que os dois últimos recursos em consideração não suportam “rotas”, ou seja, eles não sabem como conectar pontos ao longo de estradas e / ou calçadas existentes, mas simplesmente conectam os pontos com uma linha reta. Para mim, pessoalmente, isso não é um problema, mas um passo consciente. Se você precisa de navegação nas estradas, precisa procurar na direção do google, yandex pago ou serviço de openroutes grátis.

Implementação


A solicitação para o módulo de histórico via REST-API é bastante simples (a seguir, o código estará na linguagem HomeAssistant, por exemplo, python) e permite que você obtenha a resposta na forma de JSON fácil de entender:

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] 

aqui self._haddr é o endereço do seu HA igual ao especificado nas configurações de front-end, self._myid é o ID do dispositivo device_tracker, cuja rota criaremos, dayBegin é o início do período para a exibição da rota, selecionei o início do dia atual por padrão, self._token é um token de longa duração para acessar a API, que pode ser obtido na interface do HomeAssistant.

Quando o objeto cuja história estamos tentando exibir no mapa fica parado por um longo tempo ou se move muito devagar, obteremos vários pontos que estão bem localizados e obstruirão o mapa. Para corrigir a situação, deixe a matriz de coordenadas resultante passar pelo filtro: se a distância entre o ponto anterior e o próximo for inferior a 100 metros, não exiba o ponto no mapa. Para calcular as distâncias entre dois pontos vizinhos, usamos uma fórmula simplificada com uma aproximação equiangular . A aproximação é aplicável quando a distância entre pontos vizinhos não excede vários km:

  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 

Aqui dst é a distância em km.

Descrever a API do Leaflet aqui não entende o ponto. Para isso - no site oficial . O módulo funciona da seguinte maneira: A cada n segundos (eu o configurei para 300), é feita uma solicitação ao histórico de hoje do objeto de interesse para mim. A matriz de coordenadas resultante é executada através do filtro de distância, reduzindo o número de pontos. Além disso, na pasta com a configuração do HomeAssistant na pasta www, dois arquivos são formados: index.html e route.html. O arquivo route.html contém toda a lógica para criar um mapa. E o arquivo index.html é um truque vitalício para impedir o cache da página. Por padrão, o HomeAssistant armazena em cache tudo o que é possível, e somente redefinir o cache ajudou a atualizar os dados no mapa, o que, é claro, é inaceitável. No arquivo index.html, o conteúdo de route.html é chamado, no entanto, com um parâmetro aleatório gerado dinamicamente, que permite solicitar sempre a versão atual do route.html do servidor:

 src = 'route.html?datetime=' + (new Date()).getTime() + Math.floor(Math.random() * 1000000) 

Um pouco sobre segurança


O HomeAssistant foi projetado para que todos os arquivos dentro do diretório www sejam públicos, ou seja, qualquer arquivo dentro do diretório www possa ser aberto em qualquer navegador sem autorização, conhecendo o link direto. No caso do meu módulo, este link é este: seu_ endereço_de_instalação_do_domínio / local / route / index.html . Se isso não for crítico para você, você pode pular esta seção. Eu fui um pouco mais longe e estraguei a autorização para a página com rotas. Para isso, usei o nginx (você pode escolher outro servidor Web com suporte a proxy reverso) como servidor proxy. O site do HomeAssistant possui instruções oficiais para definir esta configuração. Após configurar a operação de proxy e verificação, é necessário adicionar autorização às páginas necessárias na configuração do 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; } 

Em seguida, crie o arquivo "/etc/nginx/.htpasswd" e execute os seguintes comandos no console:

 sh -c "echo -n 'admin:' >> /etc/nginx/.htpasswd" sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd" 

admin - substitua pelo login desejado.

Depois disso, reinicie o nginx e verifique: ao tentar abrir uma página com uma rota, o navegador deve solicitar um nome de usuário e senha. Observo que esta é uma autorização separada que não tem nada a ver com a autorização do próprio HomeAssistant.

Conclusão


Talvez tudo o que se possa dizer sobre este módulo.
Quem estiver interessado, aqui está um link para o módulo. Coloque o arquivo no caminho: config_folder_homeassistant / custom_components / route / sensor.py, não se esqueça dos direitos.

Se não existir, crie a pasta config_folder_homeassistant / www e dê os direitos apropriados.

No arquivo de configuração configuration.yaml, escreva as seguintes linhas:

 sensor: - platform: route name: route entityid: your_device_tracker_entity_id haddr: your_address_homeassistant token: your_long_life_token 

aqui your_device_tracker_entity_id é o ID do seu dispositivo device_tracker, your_address_homeassistant é o endereço externo do seu HomeAssistant, your_long_life_token é o token de acesso recebido anteriormente no front end do HomeAssistant para usar a API REST.

Depois disso, reinicie o HomeAssistant e aproveite. O mapa estará disponível através de um link direto: your_address_homeassistant / local / route / index.html . Se desejar, você pode adicioná-lo ao menu HA usando panel_iframe ou a qualquer janela de HA através do cartão lovelace “iframe”.
Só isso, obrigado pela atenção.

UPD:
Adicionado um link para o GitHub. Foram modificados alguns locais (removidos da configuração haddr, obtém automaticamente config_dir, adicionada a capacidade de definir meu fuso horário)

E como tudo isso parece? Cuidado, Bluer!
imagem

Source: https://habr.com/ru/post/pt448656/


All Articles