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_ESP_RMAKER_NEO_TIMESERIES_DATA_QUEUE_LENGTH100Data points held in the queue; ~24 bytes each
CONFIG_ESP_RMAKER_NEO_TIMESERIES_PUBLISH_INITIAL_DELAY_MS100Minimum gap between publishes; range 10–1000
CONFIG_ESP_RMAKER_NEO_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_NEO_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.