Skip to main content

Time series data

Time series turns a parameter into a history: every value change is published as a timestamped data point, and the cloud stores and aggregates it so an app can draw a graph or answer "how much energy did this use last week".

There is no API to call. It is a property flag on the parameter.

Enabling it

/* A sensor reading — one value per sample */
esp_rmaker_param_t *temp = esp_rmaker_param_create("Temperature",
ESP_RMAKER_PARAM_TEMPERATURE,
esp_rmaker_float(25.0),
PROP_FLAG_READ | PROP_FLAG_TIME_SERIES);

/* An energy meter — monotonically increasing */
esp_rmaker_param_t *energy = esp_rmaker_param_create("Energy",
"acme.param.energy",
esp_rmaker_float(0.0),
PROP_FLAG_READ | PROP_FLAG_TS_CUMULATIVE);

From then on, every esp_rmaker_param_update() that actually changes the value queues a data point.

Simple vs cumulative

FlagUse forCloud treats it as
PROP_FLAG_TIME_SERIESInstantaneous readings — temperature, humidity, power drawIndependent samples; averages, min/max, and latest are meaningful
PROP_FLAG_TS_CUMULATIVEMonotonically increasing counters — energy consumed, run hours, litres dispensedA running total; the cloud can difference consecutive points to get consumption per period

Pick correctly. A cumulative counter reported as simple time series gives you a meaningless "average total", and an instantaneous reading reported as cumulative produces nonsense deltas whenever it goes down.

Set exactly one of the two flags on a given parameter.

What gets published

Each data point is a compact JSON object:

{
"k": "Light.Power",
"dt": "bool",
"v": true,
"t": 1769000000000,
"tz": "America/New_York",
"cumulative": false
}
FieldMeaning
kPath: "<device_id>.<param_id>"
dt"int", "float", "bool", or "string"
vThe value
tUnix timestamp in milliseconds, UTC, int64
tzIANA timezone at the time of the sample
cumulativePresent and true for PROP_FLAG_TS_CUMULATIVE
No dots in IDs

The path separator is ., so device and parameter IDs must not contain a dot. A parameter called Temp.Out produces an unparseable path. This constraint is easy to violate and hard to notice.

Data points are queued and published at a throttled rate on the state-reporting flow, at QoS 1. Several points are batched into one MQTT message where possible.

Timestamps need a clock

The t field is the node's wall clock at the moment of the update. That means:

  • Time sync is mandatory. Points generated before the first successful sync are deferred or dropped, depending on the startup flow. See Time and timezone.
  • The timezone is captured per sample. If a user changes the timezone, existing points keep the timezone they were recorded with.

If your graphs are empty or start at 1970, check local-time on the serial console first.

Throughput and the queue

The queue is the thing to size, because when it is full new data points are silently dropped.

OptionDefaultNotes
CONFIG_RMAKER_TIMESERIES_DATA_QUEUE_LENGTH100Data points held in the queue; ~24 bytes each
CONFIG_RMAKER_TIMESERIES_PUBLISH_INITIAL_DELAY_MS100Minimum gap between publishes; range 10–1000
CONFIG_RMAKER_TIMESERIES_PUBLISH_MAX_DELAY_MS300000Ceiling for the exponential backoff after a failed publish

Raise the queue length if either applies:

  • You generate points faster than the publish delay drains them.
  • Your network is unreliable, so backoff can stretch to five minutes and a lot of points accumulate.

100 points at the default 100 ms delay covers about ten seconds of continuous drain — comfortable for a sensor sampling every few seconds, tight for anything reporting at 10 Hz.

MQTT budgeting drops timeseries too

With CONFIG_ESP_RMAKER_MQTT_ENABLE_BUDGETING=y (the default), an exhausted budget drops timeseries publishes. A chatty timeseries parameter can starve your state reports, and vice versa. Budget is 100 by default, reviving 1 message every 5 seconds — so sustained reporting above roughly one message per five seconds will eventually hit the limit. See Configure and build.

Choosing what to record

Every timeseries parameter costs MQTT messages on the device and storage plus query cost in the cloud. Two habits keep that under control:

  • Report on meaningful change, not on every sample. Apply a deadband in your driver — a temperature that wobbles by 0.05 °C does not need a data point. esp_rmaker_param_update() already suppresses updates to the identical value, but it does not know your noise floor.
  • Don't flag control parameters. Power and Brightness are already in the shadow with their current value; a history of them is rarely worth the traffic.

Reading it back

Firmware does not read time series. Queries — raw, latest, and aggregates by hour/day/week/month — are cloud-side APIs used by apps and dashboards. See Cloud specifications → Timeseries and the Platform API reference.