继上次搭建完框架获得了个粗糙的demo之后,基本的图形组件试了个遍没什么阻力。我天真地觉得我离真理的距离简直就只有一步之遥了。
想着我还有些模拟的地理数据没有作可视化,数据信息的内容放在名为location的属性之下,具体格式如:javascript
{ "location": { "lat":12.345, "lon":56.789 }, "temperature": 49.966, "more-props": "value" }
一个很天然而然想法萌生了---用地图来展现相关信息。但!万万那没想到,一进地图的坑,卡了10天都没出坑。(部分缘由是圣诞节让我懒惰[写不出来就让圣诞节背锅哈哈哈哈],没有作功课)。
关于基于地图的信息可视化,Power BI上的Map工具给我留下了用户友好简单易用的好印象。只要使用直接的经纬度数据对就能在地图上对位置定位并展现。逻辑惯性让我想固然了,天真地觉得全部的地图插件都同样”单纯”。
首先,在Grafana的标准可视化工具中是不包括地图相关的工具的, 但在插件库中官方发布了一款名为Worldmap Panel基于地图可视化的工具,符合个人需求看起来效果也不错。前端
在简单地下载安装了这个插件后,我发现事情并无想象简单。该工具和个人可视化框架最大的冲突是:
Worldmap Panel并不支持经过经纬度数据对 e.g. (latitude, longtitude)在地图上定位与可视化, 其支持的数据格式有且仅有两种:Country/State Code或geohash。 java
如下从官方文档中摘出的这句话很好地的解释了这两种数据类型。 node
There are currently two ways to connect data with points on a map. Either by matching a tag or series name to a country code/state code (e.g. SE for Sweden, TX for Texas) or by using geohashes to map against geographic coordinates。
Grafana和InfluxDB的文档大概是我有生以来看到过写的最逻辑混乱的文档之一了,吐槽请见上篇博客。
在这新年之际,我要邀请你们继续欣赏出自Grafana官方WorldMap Panel的documentation。 说实话我一口气看了三遍后居然比看第一遍时还要混乱。文档以table data, time series data和json为data source的介绍相关配置实在是很是地不明智之举。以个人构架为例:首先,使用influxdb获得的数据照理说应该是time series data吧?毕竟人家influxdb号称time-series数据库,以写入数据库时的时间戳做为表格的惟一索引。 然而最后使用的配置方法居然归档在table data下(influxdb: 我不要面子的哦);
其次"time-series data"这个称谓也许还可以直观地理解是以时间戳为索引的数据(更有甚者我这样的理解实际上是错误的),那么“table data”该如何去理解呢?"time-series data"难道不是以表格的形式组织排列储存的吗?至于“json”就更为模糊了,是以json为格式的数据?仍是经过json的形式传递的数据? 那么json这种格式的数据就不能同时是"time-series data"或"table data"吗?这三种类型的数据不具有互斥性,因而可知这种分类方法是不科学的。
我我的主观认为正确的分类方法正如文档开头所说,我在本文的第一章节也引用了这句话:git
There are currently two ways to connect data with points on a map. Either by matching a tag or series name to a country code/state code (e.g. SE for Sweden, TX for Texas) or by using geohashes to map against geographic coordinates.
注解:
对于code: 可使用grafana预先定义的code, 也能够自定义一些code并用json/jsonp方式导入;
对于geohash: 主要是为了支持elasticsearch, 可是对于influxdb, 能够人工添加geohash的tag,并将数据看做是表格读取geohash tag中的内容;
“以country code和geohash为区分,详述在不一样数据库下针对这两种数据源的配置方法”---若是用这样的方法组织文档,一目了然,结构清晰;读者按图索骥,效率大大提升,至少好过如今的文档。而全文档如此重要的一句话,居然放在一个绝不起眼的角落。恕我实在没法理解撰写者的意图。github
为了解决这个如鲠在喉的数据匹配问题,几种可能的解决方法一番折腾后初现原形: 1. 在原始数据中人工硬是添加个country code field或geohash field;
最容易想到的方法。简单粗暴快捷!可是考虑到这样的方法并不能适配全部的IoT设备,且大部分的GPS产生的数据仍是经纬度。排除排除! 算法
2. 在Telegraf中添加可以对经纬度数据对作处理并产生geohash的plug-in;
惋惜我并无找到这样能够直接使用的plug-in。转念想到能够本身开发plug-in,可是对我而言时间,学习成本太。高。(Golang小白,geohash算法不了解)。两个字:排除!
P.S:有兴趣的朋友能够看看telegraf的文档,他们是欢迎各类形式的plugin PR的。暗中观察,这样的plug-in应该要归在processor plug-in一类中。而目前官方只在这类中给了个printer。基本等于没什么卵用,就是在cmd里打印下数据流。亟待小伙伴填坑!
ref:https://github.com/influxdata... 数据库
3. 使用Kapacitor对流出数据库的数据分析处理,后而送至可视化终端;
Kapacitor是influxdata四个开源核心产品之一(TICK stack, K--Kapacitor),能够对数据进行相应的分析处理,好比使用机器学习模型处理分析数据。具体其余功能不是特别清楚没作仔细调研,有兴趣的同窗移架这里。
至于排除的缘由和2相似,没有可用的脚本,开发成本过高。 npm
4. 使用node-influx和node-geohash等开源插件, 后端语言(如node.js)处理,向数据库直接添加geohash tag并写入值;
看起来彷佛是个物美价廉的正经解决方法。不过因为本文讨论的是实时IoT数据的可视化,可能每分钟就会向数据库内写入大量的数据,若是在数据存储后再对数据进行操做,则要频繁地调用数据库I/O进行读写操做,将已经存入的数据记录逐条处理并写回,增长了数据库负担。所以排除。
ref: https://community.influxdata.... json
5. 使用Node-Red对数据流向管理,在数据存入数据库以前利用已有的集成块调用接口计算geohash以减轻对数据库的负担。
Node-RED为一个开源的IoT设备数据流编辑器,主要用于可视化IoT数据的流向而且对数据流向进行管理和链接。 它依赖于活跃的node.js社区,拥有大量可用资源和强大的社区支持。 既能有效地将数据从源头历经的各个技术栈以流程图的形式表达出来,又能对数据流进行简单管理,支持javascript对数据流的处理,所以对前端工程师十分友好。
而吸引我使用Red-Node很重要的一个缘由是:Node-RED中有一个名为node-red-node-geohash的结点模块,在Node-RED项目中使用npm简单安装后,便可将数据中的经纬度数据对直接编码成geohash码,反之亦然。这样就避免了我投入大量时间成本和开发成本在geohash到经纬度的转码上;
其次,Node-RED对数据流向进行管理和编辑处理的强大功能,容许在流向中插入自定义的javascript功能代码;这让数据流向设计的灵活度大大提升了,所以也能充分利用这种灵活度将个人数据在存入数据库以前将关于经纬度的数据转译成geohash,这样一来就避免了方法4中对数据库资源的浪费和复写;
最后,Node-RED的可视化编辑界面能有效将数据流向以一种简单直接的方式表达出来,是选择使用该工具的加分点。权衡性价比以后,决定采起最后一种方案。
tips: 使用Node-RED的前提条件是保证node.js已安装;
若是是和我同样使用windows系统的小伙伴们, 推荐一个插件叫作chocolately, 今后Windows也拥有了软件包管理工具,命令行安装package不是梦!
打开 windows cmd使用chocolately安装node.js: choco install nodejs-lts
C:\WINDOWS\system32>npm install -g --unsafe-perm node-red
用户app路径\npm\node_modules\node-red>npm install node-red-node-geohash
用户app路径\npm\node_modules\node-red>node-red
Node-RED的数据流向编辑器采用模块拖拽的形式,用户很容易理解和使用,所以上手不难,学习曲线平缓。
根据个人案例状况,在Node-RED上搭建的数据流向以下
从我机器上的MQTT broker上订阅从个人模拟器中发出的特定话题的数据后,利用geohash结点模块处理经纬度数据,生成geohash,而后再一次利用MQTT broker发布一个新的话题,用于传递通过处理的数据, 这时只要数据库订阅这个新话题,就能利用telegraf顺利地将数据存入数据库中。
在这个流向中除了必备的mqtt和geohash节点,我还利用了两个function节点来自定义代码。它们分别用于处理流入geohash结点以前的数据,和geohash结点以后的数据。
根据官方文档中的描述,geohash节点将会直接读取msg.payload中的lat和lon属性,若是规定了精确度即msg.payload.precision存在,那么会一并处理生成惟一的geohash码。具体描述以下:
A function that encodes lat,lon to and from a geohash.
If the msg.payload is an object with properties lat or latitude and lon or longitude - it will add a geohash property to the payload.
The precision can be set by msg.payload.precision from 1 to 9.
Note: If the msg contains a .location property it will operate on that in preference to the .payload.
在第一章中,我提到过,个人地理数据是被包裹在location属性中的,即msg.payload.location。所以geohash没法直接获得经纬度信息。这时就借助了location-preprocessor的功能节点将location中的信息提取出来。注意在引用的文档叙述中的最后一句, 若是msg中包含了location属性,会直接处理location属性中的lat,lon属性,忽略payload中的信息。 借助这一点,咱们则能够将msg.payload.location中的信息直接放入msg.location让其计算geohash。
location-preprocessor的代码:
//The main purpose of this snippet is to extract the location info from msg.payload and then put it to msg.location to get the calculated geohash. var message=JSON.parse(msg.payload); if(message[0].location!==null) { msg.location={ "lat":message[0].location.lat.toString(), "lon":message[0].location.lon.toString(), "precision":"8" }; //msg.location=message; } return msg;
当获得有效的geohash码后,此时,只需将msg.location.geohash的值复制进入msg.payload中,此时数据中就拥有了geohash码了。接着只需新建一个mqtt话题,将处理的数据经过mqtt broker发布出去,则Node-RED的配置到这里就结束了。
location-afterprocessor的代码:
//The main purpose for this snippet is to put the geohash property into msg.payload which is then transferred by mqtt-broker via certain topic if(msg.location.geohash!==null) { var message=JSON.parse(msg.payload); message[0].geohash=msg.location.geohash; msg.payload=JSON.stringify(message); msg.topic="sensors/wrap_geohash"; } return msg;
[注意]在使用telegraf接受数据以前,要将geohash一项设置为tag才能被Worldpanel识别和使用。同时若是使用了mqtt的新话题,要记得在配置文件中修改相关项
到这里,运行telegraf和influxdb,数据应该安然无恙地被telegraf简单处理后存入数据库。这时对数据库进行简单的操做检查数据是否如本身预期地被写入了指定数据库。
既然到这里已经保证数据库里有了可用的数据,那么接下来开始设置Worldmap Panel工具吧!
欣喜伴随着绝望。又要开始研究文档T.T。
瞅来瞅去,文章里关于配置最重要的一段话就是这里了:
An example of Table Data would using InfluxDB and then formatting the data returned from the metric query as Table.
Similar to the Elasticsearch query above, 3 fields are expected (2 of them are mandatory)
- field named metric
- geohash tag named geohash
- an optional location name (shown in the mouse over). This location name has to be specified in the Worldmap settings tab too.
我给你们用直白的话翻译一下这段话的意思: 老子Worldmap Panel只认两个兄弟,一个叫作metric,还有一个就是geohash!location name的这我的能够考虑,可是无关紧要。其余的都滚一边去!
geohash就是个打手,Worldmap Panel说让它去哪儿它就得去哪儿,该在那个地理位置就给定在哪里;
metric是个师爷,在geohash的定位基础上,每一个点要显示的值都靠metric去提供。可是师爷这种人聪明绝顶,行走江湖容易遭人暗算,因此metric是个化名,真正名字叫什么,主要看数据库给什么值了。总之在Worldmap上他就叫metric。
这样一来咱们就能够设置数据集按照geohash来定位,而在每一个geohash的点上须要显示的值则由metric肯定。好比从个人需求出发,须要显示个人每台设备在地图上的定位并能让用户看到每台机器的当前运行的温度状况,那么我就应该这样来设置个人query。
同时,在worldmap一栏对map data options进行设置:
location data必定要选择table,且通常table field name设置为geohash;
到这里应该能够看到美腻的demo了!Worldmap panel到这里终于可用了!
脸上笑嘻嘻,内心真是mmp啊!朋友们填坑不易,且填且珍惜哦! 也不知道本身还能坚持填坑多久,前路漫漫啊前路漫漫! 最后是否是要祝盆友们元旦快乐呢?虽然我知道看到最后的基本都是真爱,而真爱的几率和在这个现实世界同样基本为0。