Sample dataset · CC0

Telemetry, including the readings that never arrived.

Forty devices across five sites reporting through a thirty-day window. Battery level falls the whole way and never recovers, status is derived from the readings rather than drawn beside them, and about one temperature in two hundred is simply absent.

7 columns · 100 or 1,000 rows as a file · up to 1,000,000 rows generated here · CSV, JSON, JSONL, Excel, Parquet

Take a file

A thousand rows is twenty-five readings per device. The interesting sizes for this dataset are the generated ones, because downsampling is the exercise it is built for.

The sizes that make this dataset interesting

A hundred thousand readings across forty devices over thirty days is roughly one every seventeen minutes per device, which is a realistic cadence for building sensors. This is the dataset where the million-row option earns its place.

The first eight rows

The first eight rows of the 1,000-row file. The forty devices rotate in a fixed order.

reading_tsdevice_idsitetemperature_chumidity_pctbattery_pctstatus
2026-03-01T00:00:00ZDEV-001Plant A17.941.398ok
2026-03-01T00:43:12ZDEV-002Plant B20.644.0100ok
2026-03-01T01:26:24ZDEV-003Warehouse North21.644.298ok
2026-03-01T02:09:36ZDEV-004Warehouse South24.440.499ok
2026-03-01T02:52:48ZDEV-005Lab24.242.098ok
2026-03-01T03:36:00ZDEV-006Plant A19.139.098ok
2026-03-01T04:19:12ZDEV-007Plant B18.743.499ok
2026-03-01T05:02:24ZDEV-008Warehouse North20.241.098ok

Seven columns, and what each one holds

Column Type What it holds Example
reading_ts timestamp UTC timestamp with a Z suffix, ascending through the file. 2026-03-01T00:00:00Z
device_id text DEV-001 to DEV-040, cycling in a fixed order. DEV-001
site text Building the device is installed in. Fixed per device. Plant A
temperature_c decimal Celsius, one decimal. Blank on roughly one reading in 200, where the sensor dropped a sample. 17.9
humidity_pct decimal Relative humidity, one decimal. 41.3
battery_pct integer Battery remaining. Falls monotonically across the file for each device. 98
status text ok, warn or fault. Derived from battery and temperature, never contradicting them. ok

What it models

Building telemetry: forty battery-powered sensors installed across five sites, each reporting temperature, humidity and its own battery level on a fixed cadence. The timestamp column is a full UTC instant with a Z suffix rather than a date, which is the format these systems actually emit and the one that trips up importers expecting a date.

The readings ascend strictly in time and the devices rotate in a fixed order, so consecutive rows are different devices at nearly the same instant. That is what a real ingestion stream looks like, and it means anything you build has to group by device before it can do anything per device.

The battery column tells a story

Battery starts near 100 and falls across the window for every device, at a rate that depends on the device, so some are nearly flat after thirty days and others still hold most of their charge. Nothing recharges, which is a property you can rely on: for any device, a later reading always has a battery level at or below an earlier one.

That makes it a good file for window functions. Compute the difference between consecutive readings per device and the value should never be positive. Compute a per-device slope and you get a drain rate you can rank the fleet by, which is exactly the query a real operations team runs to decide which sites to send somebody to.

Missing readings and derived status

About one row in two hundred has an empty temperature. The row still exists, with its timestamp, device and battery, because the sensor reported and the temperature sample was lost. That is a different failure from a missing row, and telling the two apart is most of what monitoring a fleet consists of.

status is not drawn independently. It is fault when the battery is under twelve percent, warn when the temperature is above 27.5 degrees or the battery is under twenty-five, and ok otherwise. So the alert column always agrees with the numbers beside it, which means you can test alerting logic against a known-correct baseline instead of guessing.

What people use it for

  • Downsampling: turning a reading every few minutes into an hourly or daily mean.
  • Window functions per device, on a column with a guaranteed direction.
  • Gap and anomaly detection, with a small, known rate of missing values.
  • Testing timestamp parsing on a full UTC instant with a Z suffix.
  • Alerting logic, checked against a status column that is derived rather than drawn.

License, and the people in it

This dataset is dedicated to the public domain under CC0 1.0. Put it in a course, a paid product, a test suite, a bug report, a screenshot, a conference talk or a book. There is nothing to ask for, nothing to sign and no attribution required. A link back is welcome and is not a condition.

No people, no locations that exist and no real equipment. Device identifiers are sequential strings, sites are generic building names, and every reading comes from a deterministic function rather than from a real installation.

Questions people ask about this file

Does the battery level ever go up?

Never. For each device the level is a decreasing function of how far through the window the reading is, so any later reading for a device has a battery at or below the earlier one. That guarantee is what makes the file usable for teaching window functions: the difference between consecutive readings per device should never be positive, and if your query says otherwise the query is wrong.

Why are some temperature values empty?

Because sensors drop samples, and about one row in two hundred here does. The row still exists with its timestamp, device and battery, which is the important distinction: a lost reading is not a lost row. Handling the two differently is most of the work in fleet monitoring, and a file with no missing values at all cannot teach it.

Is the status column trustworthy?

It is derived from the numbers on the same row, so yes. Under twelve percent battery is fault, above 27.5 degrees or under twenty-five percent battery is warn, and everything else is ok. That makes it a reference answer: implement the same rules in your own tool and the two should agree on every row, and any disagreement is a bug in the implementation.

What sampling rate should I generate?

A hundred thousand rows over forty devices and thirty days works out to a reading roughly every seventeen minutes per device, which is realistic for building sensors. Ten thousand rows is about one reading every three hours, which is too sparse to demonstrate downsampling. This is the dataset where the larger generated sizes are the point rather than a stress test.