通过Kapacitor通过MQTT发送警报

导航至

很久很久以前(在一个遥远的星系)我写过关于使用这个小GlowOrb来展示Kapacitor警报的事情。它真的很酷,我从那以后一直在演示中使用它,效果很好。但对我来说,总是感觉通过Node-Red端点将其转换为GlowOrb上显示的颜色值的过程有点像是个糟糕的解决方案。

那天我正在忙别的事情——事情不都是这样吗?你正在忙于某事,突然想到一个完全无关的绝妙主意,然后你知道的,你就开始追逐一只松鼠了!所以我追逐了那只松鼠,以下是我想出的东西。

我在我们的内部 Slack 频道中发布了一条消息,说如果能将 Kapacitor 警报发送到 MQTT 代理服务器,那就太棒了。这时有人告诉我,从 v1.4 版本开始,我确实可以做到这一点——原来我不知道这一点,因为 ARM64 版本已经停止更新到 v1.2 版本。现在这个问题已经得到了解决。所以,如果我能让它工作,我就可以绕过 Node-Red 实例,直接将我的颜色警报写入控制 MQTT 代理服务器。

所以我开始着手实现这个功能。

但事情并不像我想的那么简单。我阅读了文档——谁会这样做呢?——但它仍然不起作用。这是因为文档中缺少了一些重要的信息。最重要的是,你必须编辑 kapacitor.conf 文件,取消注释以下行

# MQTT client configuration.
# Mutliple different clients may be configured by
# repeating [[mqtt]] sections.
[[mqtt]]
 enabled = true
 # Unique name for this broker configuration
 name = "localhost"
 # Whether this broker configuration is the default
 default = true
 # URL of the MQTT broker.
 # Possible protocols include:
 # tcp - Raw TCP network connection
 # ssl - TLS protected TCP network connection
 # ws - Websocket network connection
 url = "tcp://127.0.0.1:1883

结果,这是整个过程中的一个关键步骤。现在我可以将消息发布到我的 MQTT 服务器了。第一步完成!

但是如何发布信息。同样,文档有点简略(我很快会提交一个 pull request 来澄清这些问题,以便让后来的每个人都更容易理解)。

所以在我的 Chronograf 实例中,我创建了一个新的 TICK 脚本——实际上,我是在修改我之前为那篇旧帖子写的脚本!——然后我得到了这个

trigger
 |alert()
 .crit(lambda: abs("chng") > crit)
 .stateChangesOnly()
 .message(parseTemp)
 .id(idVar)
 .idTag(idTag)
 .levelTag(levelTag)
 .durationField(durationField)
 .mqtt('colorChange')
 .qos(1)

它很有效,所以我将为你解释一下。首先,当“change”变量大于“crit”的值时,我们触发一个 alert()。很简单。我们将发送包含 ididTaglevelTag 等信息的 message(parseTemp),但实际上这些都不必要,因为我只使用 message() 部分而已。然后,我将它发布到 mqtt 代理服务器下的 colorChange 主题,并且将 qos 的值设置为 1。

现在到了难点。parseTemp 的事情。GlowOrb 预期接收到的消息只是一个包含十六进制字符串的颜色值。Node-Red 节点对传入的值进行了简单的转换

node.log(msg.payload.data.Series[0].values[0][2])
const currentTemp = msg.payload.data.Series[0].values[0][2];
node.log(currentTemp);
const colorCodes = [
    [90, "#ff0000"],
    [88, "#ff4000"],
    [86, "#ff8000"],
    [84, "#ff8000"],
    [82, "#ffff00"],
    [80, "#bfff00"],
    [78, "#80ff00"],
    [76, "#40ff00"],
    [74, "#00ff00"],
    [72, "#00ff40"],
    [70, "#00ff80"],
    [68, "#00ffbf"],
    [66, "#00ffff"],
    [64, "#00bfff"],
    [62, "#0080ff"],
    [60, "#0040ff"],
    [58, "#0000ff"],
    [56, "#4000ff"],
    [54, "#8000ff"],
];
const code = colorCodes.find((temp, code) => currentTemp >= temp)
const payload = code ? code[1] : "#bf00ff"
return {payload, val: currentTemp};

但这只是 JavaScript,我需要在 TICKScript 中完成这个操作。所以请稍等,因为这会变得有些复杂。

首先,我必须复习一下模板变量。结果发现我已经使用了一个

var message = '{{ index .Fields "value" }}'

但这个会更复杂。A. Lot。

我正在计算一个时间窗口内最小值和最大值之间的差异,如果变化大于阈值,则触发警报。因此,我需要根据触发警报的最大值来设置 GlowOrb 的颜色。这个模板变量的样子是这样的

var message = '{{ index .Fields "max" }}'

不要犯我犯的错误,寻找“max.value”,否则你会花半天时间 wondering 为什么它不起作用。相信我。现在,对于这个有趣的 if-then-else 部分。同样,我将使用一个模板变量来完成这个任务,但就像我之前说的,这是一个丑陋的变量。

var parseTemp = ''' {{ if (( index .Fields "max" ) gt 90 ) }} #ff0000 {{ else if 
    (( index .Fields "max" ) gt 88 ) }} #ff4000{ { else if 
    (( index .Fields "max" ) gt 86 ) }} #ff8000 {{ else if 
    (( index .Fields "max" ) gt 84 ) }} #ff8000 {{ else if 
    (( index .Fields "max" ) gt 82 ) }} #ffff00 {{ else if 
    (( index .Fields "max" ) gt 80 ) }} #bfff00 {{ else if 
    (( index .Fields "max" ) gt 78 ) }} #80ff00 {{ else if 
    (( index .Fields "max" ) gt 76 ) }} #40ff00 {{ else if 
    (( index .Fields "max" ) gt 74 ) }} #00ff00 {{ else if 
    (( index .Fields "max" ) gt 72 ) }} #00ff40 {{ else if 
    (( index .Fields "max" ) gt 70 ) }} #00ff80 {{ else if 
    (( index .Fields "max" ) gt 68 ) }} #00ffbf {{ else if 
    (( index .Fields "max" ) gt 66 ) }} #00ffff {{ else if 
    (( index .Fields "max" ) gt 64 ) }} #00bfff {{ else if 
    (( index .Fields "max" ) gt 62 ) }} #0080ff {{ else if 
    (( index .Fields "max" ) gt 60 ) }} #0040ff {{ else if 
    (( index .Fields "max" ) gt 58 ) }} #0000ff {{ else if 
    (( index .Fields "max" ) gt 56 ) }} #4000ff {{ else if 
    (( index .Fields "max" ) gt 54 ) }} #8000ff {{ else }} #bf00ff {{ end }}'''

我必须警告你!遗憾的是,我找不到使其更易读的方法。这就是它的样子。一旦我保存了它,并触发了温度变化事件,我的 MQTT 代理服务器有了这样的回应

MQTT ClientScreenSnapz001

成功了!现在我只需要将我的 GlowOrb 调整为从代理的 colorChange 主题读取,然后就可以了。不再需要向运行 Node-Red 的 http 服务器写入,运行一串 JavaScript,然后再回传到 MQTT 代理。现在我可以直接从 Kapacitor 向 MQTT 代理发送消息,然后完成操作!

我打算将其他一些警报也迁移到 MQTT。

请安装 InfluxDB 和其他 TICK Stack 组件,并开始使用 MQTT 进行数据收集、分析和警报。