IoT 传感器常用查询
以下场景说明了用于从 IoT 传感器数据中提取信息的常用查询
以下所有场景都使用 InfluxDB sample
包提供的 machineProduction
示例数据集。有关更多信息,请参阅示例数据。
计算状态持续时间
在此场景中,我们查看生产线是否运行平稳 (state
=OK
),以及生产线平稳运行或不平稳运行 (state
=NOK
) 的时间百分比。如果在间隔期间未记录任何数据点 (state
=NaN
),您可以选择检索间隔之前的最后一个状态。
要可视化状态持续时间,请参阅 Mosaic 可视化。
计算机器在每种状态下花费的时间百分比
- 导入
contrib/tomhollingworth/events
包。 - 查询
state
字段。 - 使用
events.duration()
返回每个数据点之间的时间量(以指定单位),并将间隔存储在duration
列中。 - 按状态值列(在本例中为
_value
)、_start
、_stop
和其他相关维度对列进行分组。 - 对
duration
列求和以计算每种状态下花费的总时间量。 - 将求和的持续时间透视到
_value
列中。 - 使用
map()
计算每种状态下花费的时间百分比。
import "contrib/tomhollingworth/events"
from(bucket: "machine")
|> range(start: 2021-08-01T00:00:00Z, stop: 2021-08-02T00:30:00Z)
|> filter(fn: (r) => r["_measurement"] == "machinery")
|> filter(fn: (r) => r["_field"] == "state")
|> events.duration(unit: 1h, columnName: "duration")
|> group(columns: ["_value", "_start", "_stop", "station_id"])
|> sum(column: "duration")
|> pivot(rowKey: ["_stop"], columnKey: ["_value"], valueColumn: "duration")
|> map(
fn: (r) => {
totalTime = float(v: r.NOK + r.OK)
return {r with NOK: float(v: r.NOK) / totalTime * 100.0, OK: float(v: r.OK) / totalTime * 100.0}
},
)
上面的查询侧重于生产线中报告的状态更改的特定时间范围。
range()
定义要查询的时间范围。filter()
定义要筛选的字段 (state
) 和 measurement (machinery
)。events.duration()
计算点之间的时间。group()
按字段值重新分组数据,因此字段值为OK
和NOK
的点被分组到单独的表中。sum()
返回每种状态下花费的持续时间总和。
此时查询的输出为
_value | duration |
---|---|
NOK | 22 |
_value | duration |
---|---|
OK | 172 |
pivot()
为 _value
列中的每个唯一值创建列,然后将关联的持续时间分配为列值。透视操作的输出为
NOK | OK |
---|---|
22 | 172 |
鉴于以上输出,map()
执行以下操作
- 添加
NOK
和OK
值以计算totalTime
。 - 将
NOK
除以totalTime
,然后将商乘以 100。 - 将
OK
除以totalTime
,然后将商乘以 100。
这将返回
NOK | OK |
---|---|
11.34020618556701 | 88.65979381443299 |
结果表明,生产时间有 88.66% 处于 OK
状态,而 11.34% 的时间处于 NOK
状态。
Mosaic 可视化
mosaic 可视化 随时间显示状态变化。在此示例中,mosaic 可视化根据 state
字段显示不同的彩色图块。
from(bucket: "machine")
|> range(start: 2021-08-01T00:00:00Z, stop: 2021-08-02T00:30:00Z)
|> filter(fn: (r) => r._measurement == "machinery")
|> filter(fn: (r) => r._field == "state")
|> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false)
当可视化数据时,可能存在比可用像素更多的数据点。要将数据划分为跨越单个像素的时间窗口,请使用 aggregateWindow
,并将 every
参数设置为 v.windowPeriod
。使用 last
作为聚合 fn
以返回每个时间窗口中的最后一个值。将 createEmpty
设置为 false
,以便结果不包含空时间窗口。
计算时间加权平均值
要计算数据点的时间加权平均值,请使用 timeWeightedAvg()
函数。
以下示例查询 machinery
measurement 中的 oil_temp
字段。timeWeightedAvg()
函数返回基于 5 秒间隔的油温时间加权平均值。
from(bucket: "machine")
|> range(start: 2021-08-01T00:00:00Z, stop: 2021-08-01T00:00:30Z)
|> filter(fn: (r) => r._measurement == "machinery" and r._field == "oil_temp")
|> timeWeightedAvg(unit: 5s)
输出数据
stationID | _start | _stop | _value |
---|---|---|---|
g1 | 2021-08-01T01:00:00.000Z | 2021-08-01T00:00:30.000Z | 40.25396118491921 |
g2 | 2021-08-01T01:00:00.000Z | 2021-08-01T00:00:30.000Z | 40.6 |
g3 | 2021-08-01T01:00:00.000Z | 2021-08-01T00:00:30.000Z | 41.384505595567866 |
g4 | 2021-08-01T01:00:00.000Z | 2021-08-01T00:00:30.000Z | 41.26735518634935 |
计算事件之间的值
通过获取特定时间范围内的平均值来计算事件之间的值。
以下场景查询四个生产线开始和结束时的数据。以下查询计算该期间每个研磨站的平均油温。
batchStart = 2021-08-01T00:00:00Z
batchStop = 2021-08-01T00:00:20Z
from(bucket: "machine")
|> range(start: batchStart, stop: batchStop)
|> filter(fn: (r) => r._measurement == "machinery" and r._field == "oil_temp")
|> mean()
输出
stationID | _start | _stop | _value |
---|---|---|---|
g1 | 2021-08-01T01:00:00.000Z | 2021-08-02T00:00:00.000Z | 40 |
g2 | 2021-08-01T01:00:00.000Z | 2021-08-02T00:00:00.000Z | 40.6 |
g3 | 2021-08-01T01:00:00.000Z | 2021-08-02T00:00:00.000Z | 41.379999999999995 |
g4 | 2021-08-01T01:00:00.000Z | 2021-08-02T00:00:00.000Z | 41.2 |
确定现有值范围内的状态
使用多个现有值来确定状态。以下示例根据 machine-production 示例数据中 pressure
和 pressure-target
字段之间的差异计算状态。要通过比较现有字段来确定状态
- 查询要比较的字段(在本例中为
pressure
和pressure_target
)。 - (可选)使用
aggregateWindow()
将数据窗口化到基于时间的窗口中,并应用聚合函数(如mean()
)以返回表示更大时间窗口的值。 - 使用
pivot()
将字段值移动到列中。 - 使用
map()
比较或操作不同的字段列值。 - 使用
map()
分配状态(在本例中为needsMaintenance
),这基于字段列值的关系。
import "math"
from(bucket: "machine")
|> range(start: 2021-08-01T00:00:00Z, stop: 2021-08-02T00:00:00Z)
|> filter(fn: (r) => r["_measurement"] == "machinery")
|> filter(fn: (r) => r["_field"] == "pressure" or r["_field"] == "pressure_target")
|> aggregateWindow(every: 12h, fn: mean)
|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
|> map(fn: (r) => ({ r with pressureDiff: r.pressure - r.pressure_target }))
|> map(fn: (r) => ({ r with needsMaintenance: if math.abs(x: r.pressureDiff) >= 15.0 then true else false }))
输出
_time | needsMaintenance | pressure | pressure_target | pressureDiff | stationID |
---|---|---|---|---|---|
2021-08-01T12:00:00.000Z | false | 101.83929080014092 | 104.37786394078252 | -2.5385731406416028 | g1 |
2021-08-02T00:00:00.000Z | false | 96.04368008245874 | 102.27698650674662 | -6.233306424287889 | g1 |
_time | needsMaintenance | pressure | pressure_target | pressureDiff | stationID |
---|---|---|---|---|---|
2021-08-01T12:00:00.000Z | false | 101.62490431541765 | 104.83915260886623 | -3.214248293448577 | g2 |
2021-08-02T00:00:00.000Z | false | 94.52039415465273 | 105.90869375273046 | -11.388299598077722 | g2 |
_time | needsMaintenance | pressure | pressure_target | pressureDiff | stationID |
---|---|---|---|---|---|
2021-08-01T12:00:00.000Z | false | 92.23774168403503 | 104.81867444768653 | -12.580932763651504 | g3 |
2021-08-02T00:00:00.000Z | true | 89.20867846153847 | 108.2579185520362 | -19.049240090497733 | g3 |
_time | needsMaintenance | pressure | pressure_target | pressureDiff | stationID |
---|---|---|---|---|---|
2021-08-01T12:00:00.000Z | false | 94.40834093349847 | 107.6827757125155 | -13.274434779017028 | g4 |
2021-08-02T00:00:00.000Z | true | 88.61785638936534 | 108.25471698113208 | -19.636860591766734 | g4 |
该表显示,来自 g4 站的 pressureDiff
值 -19.636860591766734
和来自 g3 站的 -19.049240090497733
高于 15,因此状态发生了变化,将 needMaintenance
值标记为“true”,并且需要对该站进行工作以将该值恢复为 false
。
此页面是否对您有帮助?
感谢您的反馈!