Skip to content
Stand with Ukraine flag

Duty cycle

  • Widget
  • 13 installs
  • v1.0.0
  • Jul 30, 2026
  • MIT license
  • v4.2+
Duty cycle

How much of the time window each state held, as a ring with percentages and durations — running, idle, fault, or any values you map. Shares are weighted by time rather than by reading count, so a value that stood for six hours outweighs one reported three times in a minute. States match an exact value or a numeric interval, with their own labels and colors; unmatched readings still appear. The figure in the middle can be uptime, the dominant state, the current one, or total measured time.

Widget Type
  • Timeseries
Category
  • Cards & Info
  • Charts & Graphs
  • Gauges & Indicators

Duty cycle

Shows the duty cycle of one telemetry key: how much of the time window a device spent in each state — running, idle, fault, or whatever values it reports — as a ring with percentages and durations. The share of a state is how long it held, not how many readings carried it.

Features

  • Time-weighted shares: each reading counts until the next one arrives, so a value that stood for six hours outweighs a value reported three times in a minute
  • States detected automatically: every distinct value in the window becomes a slice, labelled with the value exactly as the device sent it and coloured by meaning — green for running or ok, red for faults, amber for warnings and maintenance, grey for off
  • Or mapped by hand, by exact value or numeric interval, each with its own label, colour and order
  • A row matching true also matches devices that report 1
  • The middle of the ring shows the figure you care about: uptime for a state you nominate, the longest-running state, the state holding right now, or the total measured time
  • That figure either fills the ring and follows its size, or keeps an exact font size you set
  • Legend with percentages and durations, and a marker on the state holding right now
  • Legend sits beside or under the ring, following the card’s proportions; a narrow card drops legend columns rather than spilling out of the container
  • Optional percentages on the segments, in white or dark ink depending on the fill, stepping aside on a segment too small to hold them
  • Hovering a segment dims the rest and shows its label, share and duration
  • Optional click action on the ring

Data keys

This is a Time series widget. One datasource, one entity, one data key — the configuration form enforces all three. The key can be boolean, string or numeric; values are not coerced, so RUNNING and 3 work as readily as true. Empty and null readings are skipped rather than treated as a state.

Time window

The ring follows the widget’s own window or the dashboard’s, via use dashboard timewindow.

Two rules decide what the ring adds up to, and both are fixed rather than configurable:

The last reading holds to the end of the window. That is what makes the ring cover the whole period instead of stopping at the last message. It also means a device that stops reporting shows its last state for the rest of the window — the widget cannot tell silence from a state that has not changed. Where that distinction matters, pair the card with an inactivity alarm.

The stretch before the first reading is left out of the total. The state that preceded the window is not knowable from the subscription, so percentages describe the measured stretch rather than inventing a value for the gap.

The ring redraws when readings arrive rather than on every interval tick, so between two reports it can be up to one reporting interval behind. That keeps a realtime window from re-animating every second.

Set the time window’s own Aggregation to NONE. Grouped data delivers one value per interval, which flattens exactly the transitions this widget exists to measure.

Settings

GroupDescription
StatesAutomatic detection, or a list you map yourself. In manual mode rows are checked top to bottom and the first match wins: Match is either Constant valuetrue, false, RUNNING, 3 — or Numeric range, entered as From inclusive and To exclusive, either of which may be left unbounded.
RingThickness, gap between segments, percentages on the segments, percent decimals.
CenterWhat the middle shows, how it is sized, and its fonts and colours.
LegendShow or hide, position, durations, the now marker, font and colour.

Title, background, padding and margins come from the widget’s own Appearance settings — the card does not duplicate them.

How states are decided

Detect automatically is the default and needs no configuration: every distinct value in the window becomes a slice, ordered by how long it held. Labels are the values verbatim — RUNNING stays RUNNING, not “Running” — so what you read is what the device sent.

Colours are chosen by meaning rather than by position, on whole words: green for running, on, ok, active, normal; red for fault, error, alarm, failed, offline; amber for warning, maintenance, idle, paused; grey for off, stopped, inactive, unknown. true and false read as green and grey, and so do 1 and 0 — but only when the key really is two-valued, so a numeric key that happens to contain 0 and 1 keeps neutral colours. Anything unrecognised gets a palette colour derived from the value itself, which means it stays the same between refreshes and across every widget showing that key.

Most states to show separately caps the slices. Past the cap the remainder is merged into one Other (n) slice, so pointing the widget at a key with dozens of distinct values does not produce a ring of slivers. The state holding right now is always kept separate, whatever its share.

Map them myself turns off detection and uses the States list, which is what you want for labels in your own wording, a fixed order, brand colours, or numeric bands such as Low / Normal / High.

Center of the ring

OptionShows
Share of the longest-running stateThe state that held longest, and its share. Nothing to configure.
Share of one nominated stateThe share of the state named in Nominated state, which must match a label in the States list. This is the uptime mode: nominate Running and the middle of the ring is availability for the period. A nominated state that never occurred reads 0.0% rather than falling back to the runner-up.
Share of the state holding right nowThe state of the last reading, and how much of the window it accounts for.
Total measured timeA duration instead of a percentage, with a caption under it. Useful when how much data the window holds is itself the question.
EmptyNothing in the middle; the legend carries everything.

Center figure size has two modes. Auto sizes the figure to the ring’s hole, so it follows every resize and shrinks for a long value like 3 d 4 h where 48.7% would have fit; the font’s family, weight and style still apply, and the caption keeps its configured proportion to the figure. Manual uses the font size exactly as set, which is what you want when several cards sit side by side and their figures have to match.

Color the center figure like its state paints the figure in its own state’s colour — green for Running, grey for Stopped. Turn it off to fix one colour for every state.

When the window has no readings

The ring is not drawn at all — no empty grey circle — and the card shows a single quiet line of text centred in the space instead. It wraps rather than truncating, so the message stays readable on a narrow card. Nothing else about the card changes, so a dashboard of these does not jump around as devices come in and out of reporting.

Legend on a narrow card

Below roughly 260 px of card width the legend drops the duration column, and below 190 px the now marker, so the rows keep fitting instead of being clipped. Under the ring the legend takes at most 55% of the height and scrolls, so a long list of states cannot squeeze the ring out.

Requirements

The widget renders with ECharts, which travels with it — nothing to install. If the library cannot be reached, the card says so and offers a retry instead of sitting on a spinner. The gap between segments needs ECharts 5.4 or newer; on older builds the segments simply sit flush.

Tips

  • Uptime card: map true → Running and false → Stopped, set the middle to the nominated state Running, and the ring reads as availability for the period.
  • For a numeric key such as load or level, use ranges — Low / Normal / High — and the ring becomes a time-in-band breakdown.
  • Percentages are shares of the measured time, so they always total 100%. The durations in the legend are what tell you how much time that was.
  • A state that took a hair of the window is drawn at a one-degree minimum so it stays visible. The legend and the tooltip carry the true share, down to <0.1%.
  • Auto legend position follows the card’s proportions as it is resized: beside the ring on a wide card, under it on a tall one.

Share Your Widget with the Community

Built a custom widget? Export it as a JSON from ThingsBoard and publish it to the IoT Hub through a simple 4-step wizard (Upload, Listing, Readme, Review & Submit). Share it with thousands of ThingsBoard developers worldwide and get featured in the catalog.