Skip to content

mqtt preset: templates render without a timeout by default, disabling staleness detection #33083

Description

@chriszero

Describe the bug

The shared MQTT include drops the timeout key when its value is exactly 30s, which is the preset's own default. Templates that do not declare their own default therefore render no timeout at all, and nothing in the code supplies one afterwards. The timeout stays at zero, and zero is not treated as thirty seconds but as no expiry, so staleness detection is off.

The guard is in util/templates/includes/mqtt.tpl:9:

{{- if ne .timeout "30s" }}
timeout: {{ .timeout }}
{{- end }}

The parameter it guards is declared in util/templates/defaults.yaml with default: 30s and help text reading "Don't accept values older than this value".

Decoding does not repair it. In plugin/mqtt.go the config struct initialises only Scale: 1, leaving Timeout at its zero value, and cc.Timeout is passed to NewMqtt, which stores it unchecked. At runtime util/monitor.go takes the if m.timeout == 0 branch in GetFuncContext, which returns the cached value once one has been received and never returns api.ErrOutdated again.

Four of the five bundled templates using preset: mqtt inherit the default and are affected: charger/tinkerforge-warp, charger/tinkerforge-warp3, charger/tinkerforge-warp3-smart and meter/solaranzeige-mqtt. Rendering them with ordinary inputs produces zero timeout: lines. charger/onekey produces seven, because it declares its own default of 90s.

The consequence is that a value which stops arriving is reported indefinitely as though it were current, and evcc keeps deciding on it. Read plugins are affected; setters do not use the monitor.

I may be missing something. It is possible that client keepalive or a last will catches this elsewhere, that zero-as-no-expiry is intended and staleness is meant to be handled by the device implementation, or that the affected templates rely on it deliberately. I could not find any of those, but I do not know the codebase well.

Steps to reproduce

  1. Run an MQTT broker on localhost.
  2. Publish a single retained value and then stop, so the source goes quiet: mosquitto_pub -t evcc-repro/pv_leistung -r -m 1234
  3. Run evcc -c repro.yaml meter --repeat with the configuration below, which uses the solaranzeige template with usage: pv and inherits the preset timeout.
  4. Observe that the meter reports Power: 1234W continuously for as long as it is left running, well past the 30s the parameter documents. In an 80 second run there were no outdated lines at all.
  5. Add timeout: 45s to the same meter entry and repeat. The meter now reports Power: 1234W at first and switches to Power: outdated once the value ages past the limit. The same 80 second run produced 41 outdated lines.

A device-free way to see the cause is to render an affected template through Template.RenderResult(..., RenderModeInstance, ...) with only host, port, topic and usage set, and count the timeout: lines. There are none. Setting the parameter to 45s or 30000ms produces one per plugin, so the comparison is against the string rather than the duration.

Configuration details

meters:
  - name: pv
    type: template
    template: solaranzeige
    usage: pv
    host: 127.0.0.1
    port: 1883
    topic: evcc-repro

Log details

There is no error output, and that is the symptom. The expected behaviour after
the source stops publishing is an outdated error for the device; instead the log
stays quiet and the stale value continues to be served.

Inherited default, 80 second run, source silent after one retained publish:

    Power:  1234W
    ... unchanged throughout ...
    Power:  1234W

    outdated lines: 0

Same run with timeout: 45s declared on the template:

    Power:       1234W  39ms
    ... becomes ...
    Power:       outdated  682ms
    Power:       outdated  764ms

    outdated lines: 41

What type of operating system or environment does evcc run on?

Linux

External automation

  • I have made sure that no external automation like HomeAssistant or Node-RED is active or accessing any of the mentioned devices when this issue occurs.

Nightly build

  • I have verified that the issue is reproducible with the latest nightly build

Version

evcc version 0.314.0-72-g83d322b5e

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions