追踪实时天气更新

导航至

不久前,我开始思考是否可以使用 InfluxDB 实时追踪天气事件。最近我们经历了几次重大天气事件——特别是名为哈维、艾尔玛和玛丽亚的事件——我想看看是否可以进行一些追踪,并可能对新的热带风暴和飓风事件发出警报。事实证明,国家飓风中心提供了所有大西洋盆地热带气旋的实时 RSS/XML 馈送(他们也有其他地区的馈送)。完美!正是我想要的。我将引导您了解如何设置 RSS 订阅阅读器、解析 XML 馈送并将数据插入到我的 InfluxDB 实例中。我甚至会展示一些我创建的用于追踪这些风暴的仪表板。我甚至决定看看是否可以设置一些 Grafana 仪表板,所以我也会向您展示如何做到这一点。

获取 XML RSS 订阅

RSS 订阅都列在国家飓风中心的页面上,所以很容易找到。解析它有点挑战性。我再次选择使用 Node-Red,因为它有一些易于使用的内置数据源,其中之一就是 RSS 订阅阅读器。这是我的 Node-Red 流的全部内容

SafariScreenSnapz038

真的很简单,至少在流程方面是这样。事实证明,NOAA XML 馈送相当嘈杂,其中一些更新实际上并不相关,并且实际上不包含风暴数据。在查看了一些馈送结果后,我选定“摘要”馈送项作为获取有用风暴数据的最佳项。我运行原始馈送通过一个 Switch 节点来仅抓取“摘要”更新,这很容易设置。

然后是有趣的部分。从订阅中解析实际的 XML。而且它是一些繁忙的 XML!

对象

topic"热带风暴奥菲莉亚 (AT2/AL172017) 摘要"
payloadobject
title"热带风暴奥菲莉亚 (AT2/AL172017) 摘要"
description"...奥菲莉亚在卫星上看像飓风,但还不是飓风?截至美国东部时间 10 月 11 日星期三上午 11:00?奥菲莉亚中心位于 30.0, -36.5 附近?以每小时 3 英里的速度向东移动?最低中心压力为 992 毫巴?最大持续风速约为每小时 70 英里。"
summary"...奥菲莉亚在卫星上看像飓风,但还不是飓风?截至美国东部时间 10 月 11 日星期三上午 11:00?奥菲莉亚中心位于 30.0, -36.5 附近?以每小时 3 英里的速度向东移动?最低中心压力为 992 毫巴?最大持续风速约为每小时 70 英里。"
date"2017-10-11T14:35:32.000Z"
pubdate"2017-10-11T14:35:32.000Z"
pubDate"2017-10-11T14:35:32.000Z"
guid"summary-al172017-201710111435"
author"NHC Webmaster"
commentsnull
origlinknull
imageobject
sourceobject
categoriesarray[0]
enclosuresarray[0]
rss:@object
rss:titleobject
rss:guidobject
rss:pubdateobject
rss:authorobject
rss:linkobject
rss:descriptionobject
nhc:cycloneobject
@object
nhc:centerobject
@object
#"30.0, -36.5"
nhc:typeobject
@object
#"热带风暴"
nhc:nameobject
@object
#"奥菲莉亚"
nhc:walletobject
@object
#"AT2"
nhc:atcfobject
nhc:datetimeobject
nhc:movementobject
@object
#"以每小时 3 英里的速度向东"
nhc:pressureobject
@object
#"992 毫巴"
nhc:windobject
@object
#"70 英里/小时"
nhc:headlineobject
metaobject

 

哎呀!很多嵌套对象等等。尽管如此,我还是学到了一个很棒的 Node-Red 新技巧,我将与您分享。在窗口的“Debug”部分,如果您深入到 JSON 对象中,并单击小按钮——工具提示会更好——您可以复制该元素的整个路径。

SelectPath

我大量使用了该功能来提出解析例程

var myMsg = {};
    myMsg.payload = [];
    myMsg.payload[0] = {};
    myMsg.payload[1] = {};
    myMsg.payload[1].name = msg.article["nhc:cyclone"]["nhc:name"]["#"];
    myMsg.payload[1].type = msg.article["nhc:cyclone"]["nhc:type"]["#"];
    const center = msg.article["nhc:cyclone"]["nhc:center"]["#"].split(",");
    myMsg.payload[0].lat=parseFloat(center[0]);
    myMsg.payload[0].lng=parseFloat(center[1].trim());
    myMsg.payload[0].pressure=parseInt(msg.article["nhc:cyclone"]["nhc:pressure"]["#"].split(" ")[0]);
    myMsg.payload[0].move_dir=msg.article["nhc:cyclone"]["nhc:movement"]["#"].split(" ")[0];
    if(isNaN(parseInt(msg.article["nhc:cyclone"]["nhc:movement"]["#"].split(" ")[2]))) {
        myMsg.payload[0].move_speed=0;
    } else {
        myMsg.payload[0].move_speed=parseInt(msg.article["nhc:cyclone"]["nhc:movement"]["#"].split(" ")[2]);
    }
    myMsg.payload[0].wind_speed=parseInt(msg.article["nhc:cyclone"]["nhc:wind"]["#"].split(" ")[0]);
    return myMsg;

检查风暴的移动是否真的是一个数字非常重要,因为当风暴停滞时,其移动方向和速度都被报告为“静止”,这将无法解析为整数。

我将“payload”格式化为一个包含 2 个对象的数组,因为我将让 Node-Red InfluxDB 节点为我将标签和值插入到数据库中。为了使其工作,Payload 必须包含此对象数组。第一个对象是键值对,第二个对象是标签。我的对象如下所示

10/12/2017, 下午 4:49:06node: 42f137ce.5d8b6msg : Object

对象

将其发送到 InfluxDB 节点会导致这些值和标签被写入数据库。

我的新风暴仪表板

既然我已经让数据流式传输进来,我决定设置一个仪表板来查看我的数据。

SafariScreenSnapz040

由于 NHC 更新数据的频率相当低,因此图表不够平滑。在绝大多数时间里,数值变化不大(我在查询中添加了 fill(previous),以便始终显示数值)。我可以一眼看出它目前没有移动,持续风速为 100 英里/小时,压力为 973 毫巴。

从上面的数据中您会注意到,我也存储了风暴的纬度和经度。我目前正在寻找一种方法将其也显示在仪表板上,可能是在地图中。

这就引出了 Grafana

我决定试用 Grafana 作为我的数据前端,因为我们的许多客户都在使用它,而且我见过一些用它制作的非常漂亮的仪表板。安装它非常简单。

$ brew install grafana
$ brew service start grafana

我必须将我的 InfluxDB 实例设置为数据源,然后才能开始构建我的仪表板。坦率地说,我发现它不如 Chronograf 那样直观。但我确实找到了一个用于仪表盘式元素的插件,所以我安装了它。它叫做 D3Gauge,看起来非常适合显示风速。

SafariScreenSnapz041

然而,我发现的是,如果您有多个仪表盘,您最好希望它们具有相同的测量尺度。

SafariScreenSnapz042

我确实尝试调整第二个仪表盘的刻度,但显然仪表盘刻度是系统范围的,所以在一个仪表盘上更改它会更改所有仪表盘的刻度,最终使我的仪表板不那么美观。

SafariScreenSnapz043

展望未来

我正在寻找其他可以免费访问的实时数据集,我可以开始将其拉入我的 InfluxDB 实例以跟踪信息。如果您有任何建议,请在此处或在 Twitter 上 @TechEvangelist1 与我联系。