Display Elements
Display elements are read-only values shown in the Doover portal. They present data from tags, config, or static values. Users can view them but cannot interact with them directly.
NumericVariable
Displays a numeric value with optional precision, gauge widgets, ranges, and thresholds.
from pydoover.ui import NumericVariable, Range, Threshold, Colour, Widget, tag_ref
from pydoover.tags import Tags, Number
class MyTags(Tags):
temperature = Number(default=0.0)
# Basic numeric display
temp = NumericVariable("Temperature", value=MyTags.temperature, units="C")
# With precision and gauge widget
pressure = NumericVariable(
"Pressure",
value=tag_ref("pressure", tag_type="number"),
precision=2,
units="kPa",
form=Widget.radial,
)
Ranges
Ranges define coloured zones on the variable's plot. Each Range specifies a labelled band between a minimum and maximum value.
battery = NumericVariable(
"Battery Voltage",
value=tag_ref("battery_v", tag_type="number"),
units="V",
precision=1,
ranges=[
Range(label="Critical", min_val=0, max_val=11.0, colour=Colour.red),
Range(label="Low", min_val=11.0, max_val=12.0, colour=Colour.yellow),
Range(label="Normal", min_val=12.0, max_val=14.5, colour=Colour.green),
],
default_range_view="zone",
)
Range parameters:
| Parameter | Description |
|---|---|
label | Display label for the range |
min_val | Lower bound of the range |
max_val | Upper bound of the range |
colour | Colour of the zone (default: Colour.blue) |
show_on_graph | Whether to display on the graph (default: True) |
Thresholds
Thresholds draw horizontal lines on the variable's plot at specific values.
temperature = NumericVariable(
"Temperature",
value=tag_ref("temp", tag_type="number"),
units="C",
thresholds=[
Threshold(label="High Alarm", value=40, colour=Colour.red),
Threshold(label="Low Alarm", value=5, colour=Colour.yellow),
],
default_range_view="line",
)
Threshold parameters:
| Parameter | Description |
|---|---|
label | Label shown alongside the line |
value | Y-axis value where the line is drawn |
colour | Colour of the line (default: Colour.blue) |
Gauge Widgets
The form parameter controls how the value is visually presented, in addition to the standard number display.
| Widget | Description |
|---|---|
Widget.linear | A horizontal bar gauge |
Widget.radial | A circular dial gauge |
Additional Parameters
| Parameter | Description |
|---|---|
precision | Number of decimal places to display |
earliest_data_time | Earliest datetime for which historical data is available |
default_range_since | timedelta controlling how far back the plot shows on load (default: 1 week) |
default_zoom | Default zoom level for the built-in plot viewer |
default_range_view | Initial range view mode: "line", "zone", or "off" |
log_threshold | Change threshold for logging (0 = log every change, None = no change logging) |
graphable | Whether the variable can be plotted (default: True) |
TextVariable
Displays a text string value.
from pydoover.ui import TextVariable, tag_ref
status = TextVariable("Status", value="Online")
# With tag binding
firmware = TextVariable(
"Firmware Version",
value=tag_ref("firmware_version", tag_type="string"),
)
BooleanVariable
Displays a boolean on/off state.
from pydoover.ui import BooleanVariable, tag_ref
pump_status = BooleanVariable(
"Pump Running",
value=tag_ref("pump_running", tag_type="boolean"),
log_threshold=0, # Log every change
)
The log_threshold parameter controls change-based logging. A value of 0 means every change is logged. A value of None disables change logging entirely.
DateTimeVariable
Displays a date and/or time value.
from datetime import datetime
from pydoover.ui import DateTimeVariable, tag_ref
last_calibration = DateTimeVariable(
"Last Calibration",
value=tag_ref("last_cal_time", tag_type="string"),
)
Timestamp
Displays a timestamp value with millisecond precision. The value is serialised as epoch milliseconds for the portal.
from pydoover.ui import Timestamp, tag_ref
last_reading = Timestamp(
"Last Reading",
value=tag_ref("last_reading_ts", tag_type="number"),
)
Multiplot
Displays a multi-series chart that overlays multiple data streams on a single plot — ideal for dashboards where operators need to compare related readings at a glance, such as temperature vs humidity across multiple sensors, or correlated process variables over time. Each series maps to a tag value and can have its own colour, units, axis, ranges, and thresholds.
from pydoover.ui import Multiplot, Series, Range, Colour, RangeView, tag_ref
environmental_plot = Multiplot(
title="Environmental",
series=[
Series(
"Temperature",
value=tag_ref("temperature", tag_type="number"),
data_type="number",
colour=Colour.red,
units="C",
range=(0, 50),
thresholds=[
Threshold(label="High", value=40, colour=Colour.red),
],
),
Series(
"Humidity",
value=tag_ref("humidity", tag_type="number"),
data_type="number",
colour=Colour.blue,
units="%",
range=(0, 100),
shared_axis=False,
),
],
default_range_view=RangeView.line,
default_zoom="1d",
)
Series Parameters
| Parameter | Description |
|---|---|
display_name | Label for the series in the legend |
value | Tag reference for the data source |
data_type | Data type: "number", "string", "boolean", or "unknown" |
active | Whether the series is visible by default |
colour | Series line colour |
icon | Icon identifier for the series |
shared_axis | True/False or axis name string for sharing Y axes |
units | Units label for the series |
step_labels | Labels for step-type series |
range | (min, max) tuple for the Y axis; values can be numeric or "auto" |
ranges | List of Range objects for zone display |
thresholds | List of Threshold objects for line display |
Multiplot Parameters
| Parameter | Description |
|---|---|
title | Chart title (also used as display_name) |
series | List of Series objects |
earliest_data_time | Earliest datetime for historical data |
default_zoom | Default zoom level (e.g., "1d", "7d") |
default_range_view | Initial range view: "line", "zone", or "off" |
A monitoring UI builds the Multiplot dynamically in setup() based on which sensors are flagged for the overview chart. Each sensor contributes multiple series with distinct colours:
from pydoover import ui
series = []
for elem in self.config.sensor_labels.elements:
if not elem.show_on_overview.value:
continue
s_id = elem.id.value
label = elem.name.value
temp_name, humid_name = sensor_tag_names(s_id)
series.append(ui.Series(
f"{label} Temp",
value=ui.tag_ref(temp_name),
units="°C",
colour=ui.Colour.tomato,
data_type="number",
active=True,
))
series.append(ui.Series(
f"{label} RH",
value=ui.tag_ref(humid_name),
units="%",
colour=ui.Colour.blue,
data_type="number",
active=False,
))
self.add_element(ui.Multiplot("Overview", series=series, position=2))
This pattern — building the series list from config and adding the Multiplot via add_element() — is useful when the number of data streams varies per deployment.
ConnectionInfo
Displays the device's connection status in the portal. This element is typically defined once per application and informs the portal about the expected connection behaviour.
from pydoover.ui import ConnectionInfo, ConnectionType
# Always-connected device
conn = ConnectionInfo(
connection_type=ConnectionType.constant,
offline_after=120, # Show offline after 2 minutes of silence
)
# Periodically-connecting device
conn = ConnectionInfo(
connection_type=ConnectionType.periodic,
connection_period=3600, # Connects every hour
next_connection=3600, # Next connection in 1 hour
offline_after=7200, # Offline after 2 hours
allowed_misses=2, # Tolerate 2 missed connections
)
| Parameter | Description |
|---|---|
connection_type | ConnectionType.constant or ConnectionType.periodic |
connection_period | Seconds between connections (periodic only) |
next_connection | Seconds until next expected connection (periodic only) |
offline_after | Seconds of silence before showing as offline |
allowed_misses | Number of missed connection periods before showing offline (periodic only) |
connection_period, next_connection, and allowed_misses can only be set when connection_type is ConnectionType.periodic. Setting them with ConnectionType.constant raises a RuntimeError.
CameraLiveView
Displays a live camera stream in the portal with optional PTZ (pan-tilt-zoom) controls.
from pydoover.ui import CameraLiveView
live_camera = CameraLiveView(
camera_name="front_gate",
stream_name="main",
allow_ptz_control=True,
display_name="Front Gate Camera",
)
| Parameter | Description |
|---|---|
camera_name | Identifier for the camera device |
stream_name | Name of the video stream |
allow_ptz_control | Whether to show PTZ controls |
display_name | Label in the portal (default: "Live View") |
CameraHistory
Displays historical camera footage with playback controls.
from pydoover.ui import CameraHistory
camera_history = CameraHistory(
camera_name="front_gate",
display_name="Front Gate History",
)
| Parameter | Description |
|---|---|
camera_name | Identifier for the camera device |
display_name | Label in the portal (default: "History") |
Next Steps
- UI Overview -- introduction to the UI system
- Interactive Elements -- user input controls
- Styling -- colours, icons, and visual customisation