老大哥正在注视着……他自己或一张带有HomeAssistant运动历史的地图

参赛作品


对于我的家庭自动化,我已经使用HomeAssistant很长时间了。 他们说,一旦有朋友问我,为什么HomeAssistant能够仅在地图上指示跟踪器的当前位置,却无法显示整个路线? 从那时起,这个主意吸引了我。 一旦我意识到我真的很想立即拥有此功能。 每个对此有兴趣的人,欢迎来到这只猫...

智商


实际上,要显示路线,您需要具有一组带坐标的点,因此第一步是找出HomeAssistant在哪里存储必要的数据(如果有的话)以及如何从那里获取数据。 对主要来源的简短研究立即得出了解决方案:您需要使用随附的记录器模块在不同的时间点记录数据库中所需传感器的状态,以及历史记录模块,该模块可以使您以优美的方式从数据库中获取数据。 历史记录模块具有详细记录的REST API 。 你需要什么!

接下来,您需要以某种方式在地图上显示接收到的数据。 有许多不同的服务可让您显示运动的历史记录。 我可能没有尝试过所有方法,但是请允许我说说我检查过的内容:
A. yandex和Google。 实际上满足我的需求,甚至还有更多,但是由于付费服务和免费版本的严格限制,它们不适合我。 例如,Yandex只允许免费使用开放项目(也就是说,任何人都应该可以随时打开您的资源并利用其功能),更不用说对请求数量的其他限制。 只有懒惰的人没有写过Google关于api政策的更改。 目前,据我所知,对地图api或路线图api的每个请求都是付费的,请求越多-越便宜。 但是,每位拥有银行卡的用户都可以免费获得每月200美元的限额。 最上面的所有内容都会立即从您的卡中支付。 将卡链接到帐户不是我们的方式。

如果我在google和/或yandex某个地方犯了一个错误,请更正。

B. 一堆OpenRouteService和OpenRouteService映射。 原则上,这些功能与google或yandex并没有太大区别(无论如何,我都没有注意到)。 完全免费(每天和每分钟的请求数量有限制,如果超出限制,建议与支持人员联系...根本没有任何付费资费的描述)。 但是,事实证明使用OpenRouteService地图资源很不方便(长时间加载应用程序以及左侧烦人的宽菜单,默认情况下该菜单打开且未被API禁用,此外,该服务无法从移动设备正确打开)。 公平地说,可以将OpenRouteService映射放置在您的服务器上,并且很有可能在那里自己配置所有内容。

B. Mapbbcode 我偶然发现了一种有趣的简单格式的卡片实现。 原则上,该项目绝对适合我的任务,但是,从本文中,我了解了Leaflet,并决定转向源代码。 最后,他停了下来...

G. 传单。 非常好的用于地图的开源js库,易于学习且文档齐全。 从芯片:允许您使用许多服务(openstreetmaps,yandex,google,mapbox,microsoft等)中的图块。 另外,我使用了leaflet.polylineDecorator插件来指示地图上的移动方向。

值得一提的是,所考虑的最后两个资源不支持“路线”,也就是说,它们不知道如何沿现有道路和/或人行道连接点,而只是将它们与直线连接起来。 就我个人而言,这不是问题,而是有意识的一步。 如果您需要在道路上导航,则需要朝付费Google,Yandex或免费的openrouteservice方向看。

实作


通过REST-API向历史记录模块的请求非常简单(以下代码将使用HomeAssistant语言,即python),并允许您以易于理解的JSON形式获得答案:

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] 

这里self._haddr是您的HA地址,与前端设置中指定的地址相同,self._myid是我们将构建其路线的device_tracker的设备ID,dayBegin是显示路线的开始时间,我默认选择了今天的开始时间, self._token是用于访问api的长令牌,可以在HomeAssistant界面中获得。

当我们试图在地图上显示其历史的对象长时间静止不动或移动得非常缓慢时,我们将得到一堆位置很近的点,从而阻塞了地图。 要纠正这种情况,请让生成的坐标数组通过过滤器:如果上一个点和下一个点之间的距离小于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)对我感兴趣的对象的当前历史记录进行一次请求。 生成的坐标数组通过距离过滤器运行,从而减少了点数。 此外,在www文件夹中具有HomeAssistant配置的文件夹中,形成2个文件:index.html和route.html。 route.html文件包含创建地图的所有逻辑。 而且index.html文件是防止页面缓存的终生工具。 默认情况下,HomeAssistant会缓存所有可能的内容,并且仅重置缓存有助于更新地图上的数据,这当然是不可接受的。 在index.html文件中,将调用route.html的内容,但是会使用动态生成的随机参数来调用,该参数可让您始终从服务器请求最新版本的route.html:

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

关于安全的一点


设计HomeAssistant的目的是使www目录中的所有文件都是公共的,也就是说,www目录中的任何文件都可以在任何浏览器中打开而无需任何授权,并且知道直接链接。 对于我的模块,此链接是: your_address_homeassistant / local / route / index.html 。 如果这对您而言并不重要,则可以跳过本节。 我走得更远,将授权与路线固定在页面上。 为此,我使用了nginx(您可以选择另一个具有反向代理支持的Web服务器)作为代理服务器。 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_components / 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的ID,your_address_homeassistant是HomeAssistant的外部地址,your_long_life_token是先前在HomeAssistant前端中收到的使用REST API的访问令牌。

之后,重新启动HomeAssistant并享受。 该地图将通过直接链接提供: your_address_homeassistant / local / route / index.html 。 如果愿意,可以使用panel_iframe将其添加到HA菜单中,也可以通过lovelace卡“ iframe”将其添加到任何HA窗口中。
就这样,谢谢您的关注。

UPD:
添加了到GitHub的链接 。 修改了一些地方(从配置haddr中删除,自动获取config_dir,添加了设置我的时区的功能)

看起来如何? 小心,布鲁尔!
图片

Source: https://habr.com/ru/post/zh-CN448656/


All Articles