Conectamos qualquer (quase) rastreador GPS (usando o Sinotrack ST-901 como exemplo) à casa inteligente HomeAssistant

1. Introdução


De alguma forma, o rastreador GPS chinês ST-901 caiu em minhas mãos. O dispositivo foi projetado principalmente para uso em tecnologia de automóveis e motocicletas, possui um módulo gsm 2G para comunicação com o mundo exterior, um estojo impermeável e selado, uma pequena bateria interna que permite que você trabalhe cerca de 2-3 dias sem energia externa ao transmitir um sinal a cada 3 minutos, bem como um fio de ignição de sinal, que permite avisar sobre a partida do motor. Você pode gerenciar este rastreador via comandos SMS para o número do rastreador, além de comunicar e receber notificações por SMS e conectando-o à nuvem via GPRS. Depois de brincar com ele por um tempo, joguei-o em uma gaveta até o HomeAssistant aparecer em casa. Havia uma idéia para conectá-lo a uma casa inteligente.

As tarefas


Para conectar o rastreador ao HomeAssistant, é necessário resolver dois problemas: obtenha as coordenadas do rastreador e grave-as no HomeAssistant. Se para a segunda tarefa houver várias soluções possíveis ao mesmo tempo (por exemplo, gpslogger ou owntracks_http ), a solução para a primeira tarefa no meu caso foi complicada pelo fato de que nas configurações do rastreador para transferir coordenadas você pode especificar apenas um endereço IP, não um nome de domínio. Como não tenho um endereço estático em casa, surgiu a ideia de usar um intermediário. Observo que dessa maneira, você pode conectar quase qualquer rastreador GPS (e não apenas considerado no meu artigo), compatível com os recursos de um intermediário . Todo mundo que está interessado no que aconteceu, seja bem-vindo ao gato.


Idéia


Como eu disse acima, esse rastreador pode ser conectado a muitos serviços em nuvem. Alguns deles com certas restrições permitem que você use os serviços gratuitamente. Alguns serviços têm APIs completas para interagir com eles, mas eu não os encontrei entre os gratuitos. Mas quase todos os serviços fornecem o serviço de "compartilhamento" da localização do rastreador por meio de um link permanente. Depois de passar por vários desses serviços e vasculhar o código fonte das páginas compartilhadas, encontrei o que estava procurando no serviço livegpstracks : uma solicitação de coordenadas. Assim, o esquema geral de trabalho é o seguinte: o rastreador se conecta ao serviço livegpstracks e transmite suas coordenadas, o HomeAssistant faz periodicamente uma solicitação http para o serviço e recebe as últimas coordenadas gravadas, que são gravadas no HomeAssistant por outra solicitação http. Aqui está um link para uma lista de todos os rastreadores compatíveis com o serviço.

Implementação


1. Obtenção de coordenadas por solicitação

Registramos no serviço livegpstracks e conectamos nosso rastreador (o site possui instruções detalhadas para vários modelos). Depois disso, através da barra de ferramentas do site, crie um link privado para rastreamento. O link tem o formato:

https://livegpstracks.com/dv_USERID.html 

onde USERID é o ID digital de suas bolas.

Só isso. Você pode acessar o serviço através de solicitações. Para não atormentá-lo por muito tempo, fornecerei apenas o formato da solicitação:

 https://livegpstracks.com/viewer_coos_s.php?username=USER&ctp=one&code=USERID&tgst=site&tgsv=12&tkv11=TIMENOWMS 

Aqui USER é o usuário sob o qual você se registrou no serviço livegpstracks, USERID é a identificação digital atribuída ao link compartilhado, TIMENOWMS é a hora atual em milissegundos (hora unix).

Uma resposta típica é:

 [{"code":"xxx","id":"xxx","lat":"44","lng":"48","speed":"0","azimuth":"0","d":"2018-06-19","t":"09:35:17","altitude":"0","battery":"0","gpsaccuracy":""}] 

Nota: Reduzi significativamente a saída e também alterei o código de parâmetros, id, lat, lng.

O método para obter coordenadas em python é assim:

 def getInfoFrom(self): timenow = int(datetime.now().strftime("%s")) * 1000 response = requests.get('https://livegpstracks.com/viewer_coos_s.php', params={'username': self._user, 'ctp': 'one', 'code': self._myid, 'tgst': 'site', 'tgsv': 12, 'tkv11': timenow}) data = response.json() self._lat = data[0]["lat"] self._lon = data[0]["lng"] self._speed = data[0]["speed"] self._direction = data[0]["azimuth"] self._last_time_rcv = data[0]["d"] + ' ' + data[0]["t"] 

Acho que você não precisa explicar nada neste código: obtemos a hora atual, fazemos uma solicitação de obtenção, obtemos json em resposta, analisamos e obtemos latitude, longitude, velocidade, direção do movimento e o horário em que o servidor recebeu as coordenadas pela última vez.

2. Registro de coordenadas

Para a gravação, usei o módulo GPSLogger para o HomeAssistant, pois ele funciona através de uma solicitação http e permite que você use uma senha separada, diferente da senha para todo o HA. A documentação ( gpslogger ) mostra que a solicitação tem o seguinte formato:

 https://HAADRESS:HAPORT/api/gpslogger?latitude=LAT&longitude=LON&device=DEV&accuracy=ACC&speed=SPD&direction=DIR&api_password=PASS 

Aqui HAADRESS é o endereço IP ou o nome do servidor com HA, HAPORT é a porta do servidor, LAT é latitude, LON é longitude, DEV é o nome do dispositivo a ser exibido em HA, ACC é a precisão de determinar as coordenadas (por algum motivo, não funciona em HA, ocorre um erro, I (SPD - velocidade, DIR - direção do movimento, PASS - senha para transmitir coordenadas)

O método para escrever coordenadas em python é assim:

 def putInfoTo(self): if self._lat != '' and self._lon != '': req_str = self._haddr+'/api/gpslogger' response = requests.get(req_str, params={'latitude': self._lat, 'longitude': self._lon, 'accuracy': 30, 'speed': self._speed, 'direction': self._direction, 'device': self._name, ' api_password': self._pwd}) self._last_time_upd = time.strftime("%Y.%m.%d %H:%M") 

Acho que aqui também os comentários são supérfluos.

3. Módulo

O código completo do módulo para recebimento e gravação de coordenadas é fornecido abaixo.

Código do módulo
 #!/usr/local/bin/python3 # coding: utf-8 import time import requests import json import logging from datetime import datetime from datetime import timedelta import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import (CONF_NAME) from homeassistant.helpers.entity import Entity _LOGGER = logging.getLogger(__name__) CONF_USER = 'user' CONF_ID = 'myid' CONF_PWD = 'pwd' CONF_SITE = 'haddr' ATTR_LAT = '' ATTR_LON = '' ATTR_SPEED = '' DEFAULT_NAME = 'GPS_Sensor' SCAN_INTERVAL = timedelta(seconds=120) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_USER): cv.string, vol.Required(CONF_ID): cv.string, vol.Required(CONF_PWD): cv.string, vol.Required(CONF_SITE): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) def setup_platform(hass, config, add_devices, discovery_info=None): user = config.get(CONF_USER) name = config.get(CONF_NAME) pwd = config.get(CONF_PWD) myid = config.get(CONF_ID) haddr = config.get(CONF_SITE) add_devices([CarGPS(name, user, myid, haddr, pwd)]) class CarGPS(Entity): def __init__(self, name, user, myid, haddr, pwd): self._name = name self._user = user self._myid = myid self._haddr = haddr self._pwd = pwd self._lat = '' self._lon = '' self._speed = '0' self._direction = '0' self._last_time_rcv = '' self._last_time_upd = '' def getInfoFrom(self): try: today = int(datetime.now().strftime("%s")) * 1000 response = requests.get('https://livegpstracks.com/viewer_coos_s.php', params={'username': self._user, 'ctp': 'one', 'code': self._myid, 'tgst': 'site', 'tgsv': 12, 'tkv11': today}) data = response.json() self._lat = data[0]["lat"] self._lon = data[0]["lng"] self._speed = data[0]["speed"] self._direction = data[0]["azimuth"] self._last_time_rcv = data[0]["d"] + ' ' + data[0]["t"] except: _LOGGER.error('coudnt get parameters') def putInfoTo(self): if self._lat != '' and self._lon != '': try: req_str = self._haddr+'/api/gpslogger' response = requests.get(req_str, params={'latitude': self._lat, 'longitude': self._lon, 'accuracy': 30, 'speed': self._speed, 'direction': self._direction, 'device': self._name, ' api_password': self._pwd}) _LOGGER.info(response) self._last_time_upd = time.strftime("%Y.%m.%d %H:%M") except: _LOGGER.error('coudnt put parameters') #for HASS @property def name(self): return self._name @property def state(self): return self._last_time_upd def update(self): self.getInfoFrom() self.putInfoTo() @property def device_state_attributes(self): attr = {} attr[ATTR_LAT] = self._lat attr[ATTR_LON] = self._lon attr[ATTR_SPEED] = self._speed return attr 


Para conectar este módulo, o código deve ser copiado para o diretório "config_folder_homeassistant / custom_components / sensor / car_location.py" e também adicione as seguintes linhas à configuração:

 device_tracker: - platform: gpslogger password: !secret gpslogger_password sensor: - platform: car_location name: car_sensor user: USER myid: USERID haddr: YOUR_HA_ADDRESS pwd: !secret gpslogger_password 

Aqui estão todas as variáveis ​​da seção "Obtendo coordenadas por solicitação".

Este módulo trabalha em alta disponibilidade há mais de um mês sem falhas ou outros problemas.

Só isso, obrigado pela atenção.

UPD:
O HomeAssistant atualizou o componente GPSLogger, com o qual uma nova versão do mod e configurações:

novas configurações
 device_tracker: - platform: gpslogger sensor: - platform: car_location name: car_sensor user: USER myid: USERID haddr: YOUR_HA_ADDRESS_WEBHOOK 

YOUR_HA_ADDRESS_WEBHOOK - endereço de weblog do GPSLogger, você pode encontrá-lo na seção Configurações - Integrações - GPSLogger.


novo código do módulo
 #!/usr/local/bin/python3 # coding: utf-8 import time import requests import json import logging from datetime import datetime from datetime import timedelta import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import (CONF_NAME) from homeassistant.helpers.entity import Entity _LOGGER = logging.getLogger(__name__) CONF_USER = 'user' CONF_ID = 'myid' CONF_SITE = 'haddr' CONF_NAME = 'name' ATTR_LAT = '' ATTR_LON = '' ATTR_SPEED = '' ATTR_DATE = '' DEFAULT_NAME = 'GPS_Sensor' SCAN_INTERVAL = timedelta(seconds=120) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_USER): cv.string, vol.Required(CONF_ID): cv.string, vol.Required(CONF_SITE): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) def setup_platform(hass, config, add_devices, discovery_info=None): user = config.get(CONF_USER) name = config.get(CONF_NAME) myid = config.get(CONF_ID) haddr = config.get(CONF_SITE) add_devices([CarGPS(name, user, myid, haddr)]) class CarGPS(Entity): def __init__(self, name, user, myid, haddr): self._name = name self._user = user self._myid = myid self._haddr = haddr self._lat = '' self._lon = '' self._speed = '0' self._direction = '0' self._last_time_rcv = '' self._last_time_upd = '' def getInfoFrom(self): try: today = int(datetime.now().strftime("%s")) * 1000 response = requests.get('https://livegpstracks.com/viewer_coos_s.php', params={'username': self._user, 'ctp': 'one', 'code': self._myid, 'tgst': 'site', 'tgsv': 12, 'tkv11': today}) data = response.json() self._lat = str(data[0]["lat"]) self._lon = str(data[0]["lng"]) self._speed = str(data[0]["speed"]) self._direction = str(data[0]["azimuth"]) self._last_time_rcv = data[0]["d"] + ' ' + data[0]["t"] except: _LOGGER.error('coudnt get parameters') def putInfoTo(self): if self._lat != '' and self._lon != '': try: header = {'Content-Type': 'application/x-www-form-urlencoded'} body = 'latitude=' + self._lat + '&longitude=' + self._lon + '&device=' + self._name + '&accuracy=30&battery=100&speed=' + self._speed + '&direction=' + self._direction + '&altitude=0&provider=0&activity=0' response = requests.post(self._haddr, headers=header, data=body) self._last_time_upd = time.strftime("%Y.%m.%d %H:%M") except: _LOGGER.error('coudnt put parameters') #for HASS @property def name(self): return self._name @property def state(self): return self._last_time_upd def update(self): self.getInfoFrom() self.putInfoTo() @property def device_state_attributes(self): attr = {} attr[ATTR_LAT] = self._lat attr[ATTR_LON] = self._lon attr[ATTR_SPEED] = self._speed attr[ATTR_DATE] = self._last_time_rcv return attr 



UPD2:
O HomeAssistant atualizou a lógica do trabalho a partir da versão 0.88, com a qual a nova versão do mod: sensor

UPD3:
Nova versão de integração. O projeto foi transferido para o GitHub . A versão atual está lá.

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


All Articles