Hello:
I am getting this MQTT message from a LoRa station, encoded in base16:
ffffffe20000005a505332323a30333a31303a31303a 30353a303030303032202b36312e3036202b31362e36313830
When decoded manually it contains this string:
ZPS22:03:10:10:05:000002 +61.06 +16.6180
with a timestamp and two data: humidity and temperature measurements.
My problem is that I don’t know how to configure telegraf to extract those data and save into the InfluxDB database.
Is there any base16 decoder processor?
I haven’t found that in the documentation.
Thanks in advance.
There are also some non-printable leading characters included.
Afaik, there is no such parser in Telegraf.
I would solve this with a processors.execd
plugin.
Here is a quick working example in python that i tested with your data:
Telegraf Config
[[inputs.file]]
files = ["AntMan.txt"]
name_override = "AntMan"
data_format = "value"
data_type = "string"
[[processors.execd]]
namepass = ["AntMan"]
command = ["python", "AntMan.py"]
[[outputs.file]] # only for debugging
files = ["AntMan.out"]
influx_sort_fields = true
Python Script
import base64
import re
from datetime import datetime
# 3rd party libraries:
# pip install influxdb-client
# pip install line-protocol-parser
from influxdb_client import Point
from line_protocol_parser import parse_line
while True:
try:
input_line = input() # read from stdin
except (EOFError, KeyboardInterrupt): # catch EOF and KeyboardInterrupt error
break
else:
data = parse_line(input_line) # parse input line
value = data['fields'].pop('value') # get and remove original field
decoded = base64.b16decode(value, casefold=True) # decode base16
decoded = decoded.decode('ascii', errors='ignore') # convert to ascii
decoded = re.sub(r'[^\x20-\x7f]', "", decoded) # remove non-printable characters
decoded = decoded.strip('ZPS') # remove leading characters
timestamp, humidity, temperature = decoded.split(' ')
temperature = float(temperature) # convert string to float
humidity = float(humidity) # convert string to float
timestamp = datetime.strptime(timestamp, '%y:%m:%d:%H:%M:%f') # convert string to datetime
data['fields'].update({'temperature': temperature, 'humidity': humidity}) # add fields
data['time'] = timestamp # set new time
point = Point.from_dict(data) # metric from dict
print(point.to_line_protocol()) # write to stdout