Telegraf/InfluxDB - Split integer into bits or boolean values

607 Views Asked by At

I've the following situation: I'm using Telegraf to get data from ModBUS and store into InfluxDB. One metric is a Integer number that they are really boolean/bits values all together. For example, int 9 are true (1), false (0), false (0) and true (1) values. Which is the best aproach to get that Integer, and save it againt into InfluxDB as separate bits/boolean values? Installed tools are Telegraf, InfluxDB and Kapacitor. Also it have Grafana but would nice to have a post-processed boolean values saved into InfluxDB for later analytics with another tools. Thanks in advance!!

2

There are 2 best solutions below

0
mhall119 On

You can probably do what you want using the starlark processor plugin for Telegraf and Python's bitshift operators

0
ebabeshko On

Here is the sample Telegraf configuration:

[[inputs.modbus]]
 interval = "10s"
 name_override="TestModbusDevice"
 tagexclude = ["type", "name", "host", "slave_id"]
 name = "NOT USED"
 slave_id = 12
 timeout = "3s"
 controller = "tcp://127.0.0.1:502"
 holding_registers = [     
    { name = "Status1",   byte_order = "AB",   data_type = "UINT16",  scale=1.0,   address = [32008]},     
]
[inputs.modbus.tags]
location="Test Location"

[[processors.starlark]]
    namepass = ["*Modbus*"]
    source = '''
def apply(metric):
    data1 = metric.fields.get("Status1")
    metric.fields["bit00"] = bool(data1 & 1)
    metric.fields["bit01"] = bool(data1 >> 1 & 1)
    metric.fields["bit02"] = bool(data1 >> 2 & 1)
    metric.fields["bit03"] = bool(data1 >> 3 & 1)
    metric.fields["bit04"] = bool(data1 >> 4 & 1)
    metric.fields["bit05"] = bool(data1 >> 5 & 1)
    metric.fields["bit06"] = bool(data1 >> 6 & 1)
    metric.fields["bit07"] = bool(data1 >> 7 & 1)
    metric.fields["bit08"] = bool(data1 >> 8 & 1)
    metric.fields["bit09"] = bool(data1 >> 9 & 1)
    metric.fields["bit10"] = bool(data1 >> 10 & 1)
    metric.fields["bit11"] = bool(data1 >> 11 & 1)
    metric.fields["bit12"] = bool(data1 >> 12 & 1)
    metric.fields["bit13"] = bool(data1 >> 13 & 1)
    metric.fields["bit14"] = bool(data1 >> 14 & 1)
    metric.fields["bit15"] = bool(data1 >> 15 & 1)
    return metric
'''

[[outputs.file]]
   files = ["stdout"]

Sample output:

TestModbusDevice,location=Test\ Location Status1=9i,bit00=true,bit01=false,bit02=false,bit03=true,bit04=false,bit05=false,bit06=false,bit07=false,bit08=false,bit09=false,bit10=false,bit11=false,bit12=false,bit13=false,bit14=false,bit15=false 1704120270000000000
TestModbusDevice,location=Test\ Location Status1=5i,bit00=true,bit01=false,bit02=true,bit03=false,bit04=false,bit05=false,bit06=false,bit07=false,bit08=false,bit09=false,bit10=false,bit11=false,bit12=false,bit13=false,bit14=false,bit15=false 1704120280000000000

If you do not need original integer (Status1 in the example above) and need only bits in the resulting metric, just change metric.fields.get to metric.fields.pop