Help parsing an MQTT message from a Tasmota device

I have a custom Tasmota device that has three temperature sensors on it and I’d like to grab the temperature data with Telegraf. The raw MQTT message that the device sends out looks like this:

{"Time":"2023-06-28T11:23:23","DS18B20-1":{"Id":"3C30E3811D56","Temperature":73.6},"DS18B20-2":{"Id":"3CB0E38110FA","Temperature":75.3},"DS18B20-3":{"Id":"3CEFE381E067","Temperature":76.3},"TempUnit":"F"}

My best attempt at a Telegraf configuration is:

[[inputs.mqtt_consumer]]
  servers = ["tcp://ipaddresshere:1883"]
  topics = [
    "tele/bedroom-temp/SENSOR",
  ]
  username = "usernamehere"
  password = "passwordhere"
  data_format = "json_v2"
  [[inputs.mqtt_consumer.json_v2]]
    [[inputs.mqtt_consumer.json_v2.object]]
      path = "DS18B20-1"
    [[inputs.mqtt_consumer.json_v2.object]]
      path = "DS18B20-2"
    [[inputs.mqtt_consumer.json_v2.object]]
      path = "DS18B20-3"

As far as I can tell, through the data explorer in InfluxDB, this is only grabbing the last value, the path DS18B20-3. It also doesn’t label the data anywhere as being associated with DS18B20-3, so even if it grabbed all three temperatures, I don’t know how I could tell them apart.
What’s the best way to parse this incoming message?

@Jblackburn you can use the [XPath parser] (telegraf/plugins/parsers/xpath at master · influxdata/telegraf · GitHub) for this task

[[inputs.mqtt_consumer]]
  servers = ["tcp://ipaddresshere:1883"]
  topics = [
    "tele/bedroom-temp/SENSOR",
  ]
  username = "usernamehere"
  password = "passwordhere"

  data_format = "xpath_json"

  [[inputs.mqtt_consumer.xpath]]
    metric_name="'tasmota'"
    metric_selection = "child::*[starts-with(name(), 'DS')]"
    timestamp = "/Time"
    timestamp_format = "2006-01-02T15:04:05"
    timezone = "Local"
    [inputs.mqtt_consumer.xpath.tags]
      device="name(.)"
      id = "Id"
      unit="/TempUnit"
    [inputs.mqtt_consumer.xpath.fields]
      temperature = "number(Temperature)"

to get

> tasmota,device=DS18B20-1,host=Hugin,id=3C30E3811D56,unit=F temperature=73.6 1687944203000000000
> tasmota,device=DS18B20-2,host=Hugin,id=3CB0E38110FA,unit=F temperature=75.3 1687944203000000000
> tasmota,device=DS18B20-3,host=Hugin,id=3CEFE381E067,unit=F temperature=76.3 1687944203000000000

That worked flawlessly, thank you very much.
sorta

1 Like

Actually I take that back a bit, it seems to work, except that the timestamp is wrong. The time in the MQTT message is the local time, but I think influxdb is believing it to be the UTC time. In the MQTT message it looks like this:

"Time":"2023-06-28T15:37:35"

In the influxdb database it looks like this:

2023-06-28T15:37:40.000Z

How can I tell influxdb that the timestamp is from a specific timezone, not UTC?
I can’t change the sensors to report in UTC time, as it would get really confusing for me interfacing directly with them if their time is shifted from my local time.

Can you please use a outputs.file plugin to see what Telegraf thinks the timestamp is!? If you use timezone = "Local" Telegraf used the timezone of your host machine (at least it should)…

esp-node,device=DS18B20-1,host=telegraf,id=3C30E3811D56,topic=tele/bedroom-temp/SENSOR,unit=F temperature=76.6 1687968609000000000
esp-node,device=DS18B20-2,host=telegraf,id=3CB0E38110FA,topic=tele/bedroom-temp/SENSOR,unit=F temperature=77.7 1687968609000000000
esp-node,device=DS18B20-3,host=telegraf,id=3CEFE381E067,topic=tele/bedroom-temp/SENSOR,unit=F temperature=78.3 1687968609000000000

I’m not seeing a timestamp in there at all, but this is the first time I’ve seen the outputs.file section, so I don’t know if I’ve configured it correctly. I modified the config you provided slightly:

[[inputs.mqtt_consumer]]
  servers = ["tcp://************:1883"]
  topics = [
    "tele/bedroom-temp/SENSOR",
    "tele/workshop-temp/SENSOR",
    "tele/livingroom-temp/SENSOR",
  ]
  username = "**********"
  password = "************"

  data_format = "xpath_json"

  [[inputs.mqtt_consumer.xpath]]
    metric_name="'esp-node'"
    metric_selection = "child::*[starts-with(name(), 'DS')]"
    timestamp = "/Time"
    timestamp_format = "2006-01-02T15:04:05"
    timezone = "Local"
    [inputs.mqtt_consumer.xpath.tags]
      device="name(.)"
      id = "Id"
      unit="/TempUnit"
    [inputs.mqtt_consumer.xpath.fields]
      temperature = "number(Temperature)"

[[outputs.file]]
  files = ["stdout", "/tmp/metrics.out"]
  data_format = "influx"

It seems the solution to the timezone thing is to use a specific timezone, like “America/New York”, rather than “Local”.

1 Like