Skip to main content

Attribute History

The Attribute History page displays historical data for any attribute with history tracking enabled. It provides charts, statistics, and analysis of how attribute values change over time.

Overview​

Attribute History enables:

  • Time-Series Charts: Visual representation of attribute changes
  • Statistics: Count, first, and last for any attribute; min, max, and average for numeric ones
  • Aggregation: No aggregation, 5-minute, hourly, or daily rollups
  • Comparison: Multiple attributes on same chart
  • Export: Download data as CSV

Selecting Data​

System Target​

Choose entity type to analyze:

  • zone
  • device
  • subsystem
  • variable
  • monitor
  • etc.

Target Object​

Select specific entity:

  • After choosing system target, dropdown populates with entities
  • Example: Select zone → dropdown shows all zones

Once a target is selected, an open <name> link appears under the dropdown. It opens that record in a reference modal over the chart, so reading a spike and then checking the device or zone that produced it doesn't cost you the chart, the date window, or any series you have already added. Targets with no editor of their own (variable, monitor) show no link.

Attribute​

Select which attribute to chart:

  • Only shows attributes with history enabled
  • Example: temperature, power, level, etc.

Chart Configuration​

Date Range​

Start Date: Beginning of historical period End Date: End of historical period

Quick Range Buttons:

  • 1H - Last 1 hour
  • 1D - Last 1 day
  • 1W - Last 1 week
  • 1M - Last 1 month

Aggregation​

No Aggregation: Raw recorded data points

note

"Raw" means every row in the history table, which is not necessarily every value the device reported. Fast-polling analog values (power, energy, flow) are sampled with a deadband before they are stored — see History Deadband. Integer, string, and boolean attributes are stored on every change.

5 Minutes: Aggregate into 5-minute buckets

  • Average, minimum and maximum of the raw rows in each bucket

1 Hour: Aggregate by hour

  • Average, minimum and maximum per hour

1 Day: Aggregate by day

  • Average, minimum and maximum per day

Every bucket is computed by the database over the raw rows it contains. Earlier versions built the 5-minute buckets from per-minute averages, so a bucket's minimum and maximum were the lowest and highest minute average rather than the true extremes of the readings inside it — a short spike inside a busy minute could vanish from the chart. Nothing needs re-recording; existing rows chart correctly on reload.

note

Automatic aggregation only applies to numeric (int/float) attributes. A long date range on a bool, string, json, or date attribute stays on the raw path so the individual transitions are preserved — averaging a state value would throw away exactly what makes it readable. You can still pick a bucket size explicitly for those attributes; each bucket then charts its representative value rather than an average.

Chart Type​

Line: Default, shows trends Bar: Good for discrete values Area: Emphasizes magnitude Scatter: Individual data points Heatmap (DoW × HoD): Averages bucketed by day-of-week × hour-of-day. Best for surfacing routines (when does HVAC run hardest, when is the room occupied). Requires numeric data.

Compare to Previous​

Toggle to overlay the same attribute from the previous period of equal length. The overlay renders as a dashed series labeled previous: <attribute> with timestamps shifted forward so the prior week (or day, or month) lines up visually with the current window. Most useful for spotting week-over-week or day-over-day deviations.

Trigger Fires Overlay​

When enabled, vertical markers appear on the chart at every point in the visible window where an attribute trigger fired for the displayed attribute. Marker colors:

  • Green: trigger fired successfully
  • Red: trigger fired but an action failed
  • Grey (dashed): trigger conditions matched but the fire was skipped — usually because the day/hour mask blocked it or because the debounce window was still active

Marker data is sourced from the automation_history table — see Automation History below.

A chart label cannot be clicked, so the same fires are listed under the chart as Trigger fires in this window: one line per marker with its time, its status, and the trigger's name as a link. The link opens that trigger in Triggers ready to edit — useful when a spike turns out to have been caused by an automation whose conditions need tightening.

Opening this page on a specific series​

The page accepts the target and the attribute in the address, so an operational page can hand its current series over instead of describing it:

ParameterMeaning
system_targetzone, device, variable or monitor — the four targets the picker offers
target_idthe row id of that zone, device or monitor (ignored for variable, which charts as one pseudo-object)
attributethe attribute name to chart on arrival
device_idshorthand for system_target=device&target_id=<id>
zone_idshorthand for system_target=zone&target_id=<id>

For example /admin/history?system_target=device&target_id=7&attribute=power lands with the meter selected and its power series already charted. Devices, Device Health and Data Retention all link here this way. A target the picker does not offer, or an attribute that keeps no history for that target, is ignored — the page opens on whatever part of the address it could honour rather than half-applying it.

Automation History​

GEM records every automation execution to an automation_history table, complementing the per-artifact summary rows used for reactive debugging:

  • Triggers: every fire (and every condition-matching skip due to mask/debounce)
  • Schedules: every cron fire, plus the macro it dispatched
  • Macros: every run, with the upstream cause (trigger/schedule/ui) preserved across nested macro calls so you can answer "what real-world event caused this?"

Rows include started_at, finished_at, status (success/failed/skipped), caused_by_type/caused_by_id, parent_run_id, and a context JSON with type-specific extras (the attribute that changed, the macro that ran, error messages, etc.). caused_by_* stays pinned to the root cause (the trigger, schedule, or UI action that started the chain), while parent_run_id records the immediate parent row — so a macro that runs another macro gets the calling macro's row id as its parent, building an edge-by-edge call graph.

Retention is configured under Data Retention with two windows:

  • success days (default 14): how long to keep success, skipped, and debounced rows
  • failure days (default 180): how long to keep failed and aborted rows

A per-artifact cap of 10,000 rows also applies as a noisy-neighbor safety net — one chatty trigger can't drown the table even within the retention window.

Statistics Panel​

Shows computed statistics for selected data:

  • Min: Lowest value in range
  • Max: Highest value in range
  • Avg: Mean value
  • Count: Number of data points
  • First: First value in range
  • Last: Most recent value in range

Min, Max, and Avg describe a magnitude, so they only appear for int and float attributes. With an aggregation selected, a bool, string, json, or date attribute shows just Count, First, and Last — printed as the stored value (true, armed, a timestamp) rather than as a rounded number. With No Aggregation, the panel is shown for numeric series only.

Non-Numeric Attributes​

bool, string, and json attributes chart on a category axis: each distinct value gets its own line on the chart (disarmed, armed_home, armed_away) and the y-axis is labeled by value instead of by magnitude. That is the right way to read a state series — what you want from it is when it changed and what it changed to. (date values chart as timestamps, on a normal numeric axis.)

note

Earlier versions failed outright on these attributes: the statistics query asked the database for a minimum, maximum, and average of a boolean or text column, which it cannot compute, so the whole report errored and the chart reported "Failed to fetch aggregated data". Only int and float attributes charted at all. Nothing needs to be re-enabled — existing history rows chart correctly as soon as the page is reloaded.

Export​

Click Export CSV to download the currently displayed data as a CSV file for external analysis.

Multiple Attributes​

Compare multiple attributes on same chart:

  1. Select first attribute, add to chart
  2. Select different attribute, add to chart
  3. Both series display on same chart with independent colors
  4. Useful for correlation analysis

Examples:

  • Temperature vs. setpoint
  • Power consumption vs. outside temperature
  • Multiple room temperatures

Common Use Cases​

Temperature Monitoring​

Track HVAC performance:

Configuration:

System Target: zone
Target: living_room_thermostat
Attribute: temperature
Date Range: Last 7 days
Aggregation: Hour

Analysis:

  • Temperature stability
  • HVAC cycle frequency
  • Correlation with setpoint changes
  • Energy efficiency

Energy Usage​

Monitor power consumption:

Configuration:

System Target: device
Target: main_power_meter
Attribute: power_usage
Date Range: Last 30 days
Aggregation: Day

Analysis:

  • Daily usage patterns
  • Peak consumption times
  • Day-of-week variations
  • Month-over-month trends

Zone Usage Patterns​

Understand room utilization:

Configuration:

System Target: zone
Target: conference_room_occupancy
Attribute: occupied
Date Range: Last 90 days
Aggregation: Day

Analysis:

  • Room occupancy rates
  • Busiest days
  • Underutilized spaces

Monitor environmental sensors:

Configuration:

System Target: zone
Target: outdoor_sensor
Attribute: humidity
Date Range: Last year
Aggregation: Week

Analysis:

  • Seasonal humidity patterns
  • Irrigation scheduling
  • Mold risk assessment

Storage and Performance​

Attribute history is the highest-volume table in the system, and two mechanisms keep it usable:

  • Deadband sampling on fast-moving analog values, so the table records signal rather than jitter. Configured with the history_deadband_percent and history_deadband_max_interval system attributes, or per attribute from Top Attribute History Writers — see History Deadband.
  • Indexes on (system_target, target_id, name, timestamp) and on timestamp, covering the per-series chart reads on this page, the "latest value" lookups, and the nightly retention prune. They are created automatically at startup; on a large existing table the first boot after upgrading spends a few seconds building them.

The table is kept in one partition per calendar day. Writes are batched (about once a second, stamped with the time the attribute changed), and a row that repeats the last one recorded for the same attribute within a second is dropped as a duplicate report of one change rather than a new sample — a different value, or the same value again later, is always kept. The chart reads on this page touch only the days inside the selected range, and a day that passes the retention window is dropped whole by the nightly job rather than deleted row by row. Retention is configured under Data Retention.

Raw rows are short-lived by default. The long-lived tier is the Hourly Attribute Rollup — one row per attribute per hour with a time-weighted average, extremes, and time in each state, kept for over a year and described under Data Retention. This page charts the raw table; the end-user History Chart widget (UI Pages) reads the raw table downsampled for windows up to three days and the hourly rollup beyond that.