Description
When using ON_REPORT_PERIOD or ON_CHANGE_OR_REPORT_PERIOD report strategies, the periodic reporting thread overwrites the original telemetry timestamp with int(time() * 1000) (current wall-clock time) before re-sending. This makes it impossible for downstream consumers to detect stale data. The timestamp always looks fresh even if the source device stopped updating hours ago.
Where
thingsboard_gateway/gateway/report_strategy_service.py, in __periodical_reporting():
if report_strategy_data_record.is_telemetry():
# data_entry.add_to_telemetry(TelemetryEntry({key: value}, report_strategy_data_record.get_ts())) # Can be used to keep first ts, instead of overwriting it with current ts # noqa
current_ts = int(time() * 1000)
data_entry.add_to_telemetry(TelemetryEntry({key: value}, current_ts))
report_strategy_data_record.update_ts(current_ts)
The commented-out line preserves the original timestamp, but the active code replaces it.
Impact
With ON_CHANGE_OR_REPORT_PERIOD, if an OPC-UA node or MQTT device goes stale (stops updating its value), the gateway keeps re-sending the last cached value with a fresh timestamp every report period. ThingsBoard shows the telemetry as recently updated, so there's no way to tell the device is actually offline or stuck.
This breaks any staleness detection on the ThingsBoard side (dashboards, rule chains, frontends checking ts age).
Expected behavior
Periodic resends should preserve the original telemetry timestamp from when the value was last actually received from the device. The receivedTs in metadata already tracks when the gateway forwarded it, so that covers the "last forwarded" use case.
Suggested fix
if report_strategy_data_record.is_telemetry():
data_entry.add_to_telemetry(TelemetryEntry({key: value}, report_strategy_data_record.get_ts()))
Remove the current_ts override and the update_ts(current_ts) call. This way:
- Periodic resends keep the original source timestamp → staleness is detectable
- Value changes still get a fresh timestamp via
filter_datapoint_and_cache
receivedTs in metadata still reflects when the gateway last forwarded
Reproduction
- Configure a device with
ON_CHANGE_OR_REPORT_PERIOD strategy (e.g. 60s report period)
- Send one telemetry value, then stop the device
- Observe ThingsBoard latest telemetry — the
ts keeps updating every 60s even though the device is offline
Version
Latest main branch (also present in 3.x releases)
Description
When using
ON_REPORT_PERIODorON_CHANGE_OR_REPORT_PERIODreport strategies, the periodic reporting thread overwrites the original telemetry timestamp withint(time() * 1000)(current wall-clock time) before re-sending. This makes it impossible for downstream consumers to detect stale data. The timestamp always looks fresh even if the source device stopped updating hours ago.Where
thingsboard_gateway/gateway/report_strategy_service.py, in__periodical_reporting():The commented-out line preserves the original timestamp, but the active code replaces it.
Impact
With
ON_CHANGE_OR_REPORT_PERIOD, if an OPC-UA node or MQTT device goes stale (stops updating its value), the gateway keeps re-sending the last cached value with a fresh timestamp every report period. ThingsBoard shows the telemetry as recently updated, so there's no way to tell the device is actually offline or stuck.This breaks any staleness detection on the ThingsBoard side (dashboards, rule chains, frontends checking
tsage).Expected behavior
Periodic resends should preserve the original telemetry timestamp from when the value was last actually received from the device. The
receivedTsin metadata already tracks when the gateway forwarded it, so that covers the "last forwarded" use case.Suggested fix
Remove the
current_tsoverride and theupdate_ts(current_ts)call. This way:filter_datapoint_and_cachereceivedTsin metadata still reflects when the gateway last forwardedReproduction
ON_CHANGE_OR_REPORT_PERIODstrategy (e.g. 60s report period)tskeeps updating every 60s even though the device is offlineVersion
Latest
mainbranch (also present in 3.x releases)