OK, so I’m using an instance of collectd to pull together some system monitoring stats on my server. It’s running fine, and it’s forwarding data to Home Assistant via MQTT sensors as desired. Each MQTT message from collectd includes a timestamp followed by one or more measurements, with the fields separated by colons.
So to provide a couple of examples, free memory messages look like this:
1572919890.285:11632119808
Each memory-related message has a timestamp followed by the measurement in bytes. That’s a lot of bytes and hard to visually parse.
System Load messages look like this:
1572919890.267:0.0675:0.0728125:0.041875
Here each timestamp is associated with three measurements - 1m, 5m, 15m as is normal with the unix system load average measurement.
It’s easy to pull these measurements into HA with MQTT sensors - I just discard the timestamps and pull the data like this:
value_template: “{{ value.split(’:’)[1] }}” for the memory sensors, and
value_template: “{{ value.split(’:’)[1 or 2 or 3] }}” for each of the load sensors
Unfortunately, any further post-processing in the sensor templates fails - for the memory sensors and the 15m load sensor ONLY. The 1m and 5m load sensors seem to work fine. I suspect there’s something going on with the last split field from each MQTT message that I’m not able to see.
For the load sensors, I want to round the measurements to three digits. “{{ value.split(’:’)[ x ] | round(3) }}” works fine for the 1m and 5m measurements, but the 15m measurement doesn’t ever get truncated.
Some examples:
- platform: mqtt
name: Collectd Test Load 0
state_topic: "collectd/192.168.17.10/load/load-relative"
unit_of_measurement: '%'
value_template: "{{ value }}"
^^^ This provides “1572919890.267:0.0675:0.0728125:0.041875” as expected - time stamp + 3 measurements
- platform: mqtt
name: Collectd Test Load 1
state_topic: "collectd/192.168.17.10/load/load-relative"
unit_of_measurement: '%'
value_template: "{{ value.split(':')[3] }}"
^^^ This provides “0.041875” as expected - the single measurement we want
- platform: mqtt
name: Collectd Test Load 2
state_topic: "collectd/192.168.17.10/load/load-relative"
unit_of_measurement: '%'
value_template: "{{ value.split(':')[3] | round(3) }}"
^^^ This provides “0.041875” - no rounding is occurring here (but for value.split(’:’)[2] | round(3), we would get “0.728” as expected
- platform: mqtt
name: Collectd Test Load 3
state_topic: "collectd/192.168.17.10/load/load-relative"
unit_of_measurement: '%'
value_template: "{{ (float(' ' ~ value.split(':')[3] ~ ' ') | round(3)) }}"
^^^ This provides “0.041875” - adding spaces to the split string doesn’t help
- platform: mqtt
name: Collectd Test Load 4
state_topic: "collectd/192.168.17.10/load/load-relative"
unit_of_measurement: '%'
value_template: "{{ (float(value.split(':')[3]) | round(3)) }}"
^^^ This provides “0.041875” - converting to float then rounding doesn’t work
For the memory sensors, I’d love to convert those raw bytes to gigabytes, but this fails: “{{ (value.split(’:’)[1] / 1073741824.0) | round(3) }}” - and so do various other attempts to rewrite them differently
- platform: mqtt
name: Collectd Test Memory 00
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
value
}}
^^^ This provides “1572919890.285:11632119808” as expected
- platform: mqtt
name: Collectd Test Memory 01
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
value.split(':')[1]
}}
^^^ This provides “11632119808” as expected
- platform: mqtt
name: Collectd Test Memory 02
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
(value.split(':')[1] | float)
}}
^^^ This provides “0.0” as result - seemingly can’t convert this numeric value into a float?
- platform: mqtt
name: Collectd Test Memory 03
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
((value.split(':')[1] | float) / 1073741824.0)
}}
^^^ This provides “0.0” as result
- platform: mqtt
name: Collectd Test Memory 04
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
((" " ~ value.split(':')[1] ~ " ") | float)
}}
^^^ This provides “0.0” as result - adding spaces around doesn’t help
- platform: mqtt
name: Collectd Test Memory 05
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
(((" " ~ value.split(':')[1] ~ " ") | float) / 1073741824.0)
}}
^^^ This provides “0.0” as result
- platform: mqtt
name: Collectd Test Memory 06
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
(float(" " ~ value.split(':')[1] ~ " ") / 1073741824.0)
}}
^^^ This provides “unknown” as result - just moved the float() filter
- platform: mqtt
name: Collectd Test Memory 07
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
((string(value.split(':')[1]) | float) / 1073741824.0)
}}
^^^ This provides “unknown” as result - tried to re-convert to string then float; doesn’t work
- platform: mqtt
name: Collectd Test Memory 08
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
(((value ~ ': ').split(':')[1] | float) / 1073741824.0)
}}
^^^ This provides “0.0” as result - added an extra delimiter and space at the end before splitting - doesn’t help
- platform: mqtt
name: Collectd Test Memory 09
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{{
((value.split(':')[-1] | float) / 1073741824.0)
}}
^^^ This provides “0.0” as result - [-1] as index doesn’t help
- platform: mqtt
name: Collectd Test Memory 10
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{% set test_val = value.split(':')[-1] %}
{{
(test_val | float)
}}
^^^ This provides “0.0” as result - setting a variable first then using the variable in the template doesn’t work
- platform: mqtt
name: Collectd Test Memory 11
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{% set test_val = value.split(':')[-1] %}
{{
(test_val / 1073741824.0)
}}
^^^ This provides “unknown” as result
- platform: mqtt
name: Collectd Test Memory 12
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{% set test_val = value.split(':')[-1] %}
{{
((test_val / 1073741824.0) | round(3))
}}
^^^ This provides “unknown” as result
- platform: mqtt
name: Collectd Test Memory 13
state_topic: "collectd/192.168.17.10/memory/memory-used"
unit_of_measurement: units
value_template: >-
{% set test_val = value.split(':')[-1] %}
{{
(string(test_val) | float)
}}
^^^ This provides “unknown” as result
I have tried just about everything I can think of.
All of these examples work 100% correctly in the template renderer in development tools! I can copy-paste MQTT messages from MQTT Explorer right into the template renderer (quoted literal strings instead of the value variable) and I’ll get correct results every single time. So it appears there’s something going on with the live data I can’t see.
And to add a further data point: I tried to use UPS Charge Percentage (also via collectd) in a mini-graph-card, but the MQTT sensor that feeds into it renders as “NaN” at all times in the graph. What’s up with these numbers? Why can’t they be parsed?
Any thoughts? I’m hoping for a real head-slapper “geez I’m dumb” kind of answer! But any answer will do.
Thanks!