Metadata Display¶
Render any value from a Milestone metadata channel as a dashboard widget in the Smart Client. One widget per value, eight render styles (Lamp, Number, Gauge, Text, Line Chart, Table, Trend, Base64 Image).
Built for ONVIF metadata like: Axis CameraApplicationPlatform analytics (area occupancy, line crossing, object counts), digital I/O port states, vendor counters - anything emitted as tt:Message over the metadata stream.
Update: (V3.2.9) Package Picker instead of learn mode. We changed how metadata packages are selected. This is a follow-up video to the tutorial videos below. Since those tutorial videos show all widgets, I don’t want to remake them.
Part-1
Part-2
Prerequisites¶
Before the widget can show anything, the camera and the VMS need to be set up to actually deliver metadata to the Smart Client:
- Metadata channel enabled on the camera - in Management Client, expand the camera under Devices > Metadata, select the metadata channel, and on its Settings tab set Metadata stream > Event data to Yes. This is what makes the camera publish its ONVIF events (analytics, I/O port states, vendor counters) on the stream the plugin reads. Analytics data and PTZ data can stay No unless you specifically need bounding boxes or PTZ position - the widget reads
tt:Messageitems, which arrive under Event data. - Metadata recording enabled - on the metadata channel, set Recording to enabled. This is required for the Playback mode and for the Line Chart's archive backfill (the wide-window view, the cold-start seed in Playback, and the in-pane window picker all read from recorded data). Without recordings the widget still works in Live mode but cannot show any history.
- Recording rule for the metadata channel - in Management Client under Rules, make sure a rule records the metadata channel (either always-on, or on the same trigger as the corresponding video). The default recording rule typically covers cameras but not their metadata channels - check that the rule's device list includes the metadata items, otherwise nothing ends up in the archive even though recording is "enabled" on the channel.
- User permissions - the Smart Client user needs Live and Playback rights on the metadata channel. Without these the channel won't appear in the configuration's channel picker, or the widget will sit on Waiting for data... forever.
If the configuration's Pick packet... button opens a list of recorded packets, prerequisites are met. If the list is empty, the channel is not flowing or its recordings are not reaching the archive - fix the camera or rule before tuning the widget.
Quick Start¶
- In Setup mode, drag a Metadata Display view item into a slot
- Click Open configuration...
- Select channel... -> pick a metadata channel
- Click Pick packet... to load a recent recorded packet from the channel. The Topic and Field dropdowns populate from it and the picked row's topic is auto-selected. (No recordings? Use Import packet... to paste an XML sample instead.)
- Choose a render type (Lamp / Number / Gauge / Text / Line Chart / Table / Trend / Base64 Image), tune the options, hit Save
- Switch to Live - the widget starts displaying as soon as a matching packet arrives.
Render Types¶
Lamp¶
Discrete state indicator. Map raw values to a label, color, and optional FontAwesome icon. Ideal for I/O ports, alarm states, on/off counters.
- Each row:
value -> label : color : icon - Icon picker has ~140 curated solid icons with search
- Falls back to a colored circle when no icon is set
- Unmapped values render with the raw value as the label
Number¶
Big-number readout with optional unit suffix and threshold colors.
- Value and unit share the same baseline so the readout looks like a single piece of typography (e.g.
43.99 km/h) - Color shifts between Ok / Warn / Bad based on Threshold Min / Threshold Max when Enable thresholds is on
- "High value is bad" toggle inverts the direction
- Min/Max chips below the value use a warn triangle for the lower bound and a critical circle for the upper bound, color-coded to the threshold direction
Gauge¶
Five styles, all driven by the same numeric/threshold settings as the Number widget plus a Scale Min/Max range:
| Style | When to use |
|---|---|
| Modern - Half arc (180°) | Compact tile, single quick-glance value |
| Modern - Three-quarter arc (270°) | More resolution per unit of arc; bigger needles |
| Classic - Half arc (180°) | Traditional speedometer with three colored bands and needle |
| Classic - Three-quarter arc (270°) | Classic style with extra range |
| Bar | Side-by-side rows; reads well at small heights |
Modern styles draw a single same-thickness progress arc that fills the threshold color. Classic styles draw three colored bands plus a needle. Both honor:
- Show value + Font size for the inline numeric readout
- Track thickness - applies to both gauge thickness and bar height (default 6 for arc gauges, 2 for the bar; max 20)
- Show ticks + Count - tick marks evenly spaced inside the arc / above the bar
- Enable thresholds - turns the colored band model on or off; when off, gauges show a single neutral track
The Bar gauge places the value, unit, and the Min/Max scale labels in a single row underneath the bar so nothing collides with the ticks above. The vertical value indicator is intentionally thin so it doesn't hide the underlying scale.
Text¶
Plain text passthrough. Use for string values like license plates, names, statuses where the raw value is the message. Configurable font size; no background.
Line Chart¶
Time-series chart for numeric values. Plots a rolling history of the data key against time, with optional thresholds, an envelope (min/max band), zoom and pan, an in-pane time-window picker, and up to 8 series on the same chart.
- Time window - choose how far back the chart looks. Presets cover 60 seconds, 5 / 10 / 30 minutes, 1 hour, 6 hours, and 24 hours, plus a free-form Custom entry in seconds. The saved value is the default; the in-pane picker (top-right of the chart) lets viewers temporarily switch windows without going into Setup mode.
- Backfill from archive - long windows (over 60 seconds) are seeded from recorded data when the chart appears, so a 6-hour view shows real history immediately instead of waiting 6 hours to fill. A loading spinner is shown while the seed query runs.
- Aggregation - Mean (default), Min, or Max. The chart groups samples into time slices that fit the chosen window, so very long windows still draw quickly.
- Show min/max envelope - draws two dashed lines around the main line: the lowest value and the highest value seen inside each time slice. The wider the gap, the more the value jumped around within that slice.
- On short windows (60 sec, 5 min) each slice covers about 1 second of data. Slow-changing values like a "people in scene" counter often have only one reading per slice, so the envelope sits right on top of the main line and looks invisible. That is correct behavior, just nothing to show.
- On longer windows (10 min and up) each slice covers several seconds, so even slow values usually have a visible spread and the envelope opens up.
- Fast-changing values like vehicle speed always show a clear envelope because the value jumps every video frame.
- Series 1 - the existing single-line settings (Topic / Data key / line color / thickness / line type / fill / markers / threshold) define the first series.
- Additional series (up to 8 total) - a collapsible accordion under Series 1 lets you add more lines on the same chart. Each row has its own Topic / Source filters / Data key (for fanning out across multiple data keys in the same metadata stream), display name (legend label), color, thickness, Straight / Smooth / Step line type, fill / marker toggles, Y axis assignment (Left or Right - the right axis only renders when at least one series uses it), and an optional independent threshold sub-panel. Click "+ Add series" up to the cap; "Remove this series" deletes a row.
- Show series legend strip - when enabled, the chart shows a strip of colored chips above the plot with each series's display name. Click a chip in the running widget to toggle that line on / off (session-only - the toggle is forgotten on reload).
- Line type - Straight (default), Smooth (curved), or Step (discrete level changes). Per-series.
- Line color, thickness, fill area, show markers - per-series styling.
- Y-axis Min / Max - clamps the (left) value axis. Leave blank to auto-fit. The right axis (when used) always auto-fits.
- Thresholds - when Enable thresholds is on, warn (Min) and critical (Max) values are drawn as dashed horizontal lines (no filled bands - the line stays readable through them). With multiple series, each line carries its own threshold band painted on its own axis.
- Zoom and pan - mouse wheel zooms the time axis; drag pans. While zoomed in Live mode the chart auto-pauses (a small "Paused (click to resume live)" badge appears) so the view does not jump as new data arrives. Click the badge to resume the rolling window.
Multi-series widgets walk the metadata XML once per packet (one parse fans out to every matching series) and run a single archive scan per backfill - cost stays close to a single-line chart's. Existing single-series widgets auto-migrate; the saved JSON blob is empty until you add a second series.
In-pane Window Picker¶
The small badge in the top-right corner of the chart shows the current effective window (e.g. 5m, 6h). Click it to temporarily switch:
- Pick any preset (60 seconds up to 24 hours) - the chart is reloaded for the new range, with a loading indicator while the archive backfill runs
- Pick Default (xx) to revert to the saved Setup value
- An asterisk (e.g.
1h*) on the badge label means a session override is active
The override is session only: it is dropped when the configuration is saved or the view is reopened, and never modifies the saved configuration. It needs no permission and applies to whichever pane is in front of you.
Live vs Playback¶
- Live - new samples stream in and the right edge advances. Auto-pause kicks in when you zoom or pan so you can study a region without it sliding away.
- Playback - zoom and pan are always on (there is no live tail to fight with) and the auto-pause badge is suppressed. Moving the timeline cursor moves the chart's cursor line; jumping further than half the visible window triggers a fresh range scan from the archive. The chart seeds itself at the current playback time on entry, so you do not need to scrub once to populate it.
Trend¶
Compact tile: a big current value plus an arrow and a Δ% (percent change) versus the same time yesterday, last week, or last month. Useful as a status indicator on dashboards where a full chart is too much - a wall of small tiles that each answer "is this number up or down compared to a normal day".
- Window - how far back the value averages and how wide the comparison sample is. Defaults to 5 min. Like Line Chart and Table, the in-pane window picker (top-right) lets viewers temporarily change it without going into Setup.
- Compare to - Same time yesterday, Same time last week, or Same time last month. The widget reads recorded values from that period and compares them to the live value to compute the Δ%.
- Value font size - lets a Trend tile blend in on a tight wall (small) or read across the room (large).
- Show Δ% / Show arrow - either of the two indicators can be hidden; the big value always shows.
- Enable thresholds - tints the displayed value (and the arrow) using the configured Threshold Min / Max and the OK / Warn / Bad colors. The arrow color also follows the High value is bad direction:
- High value is bad off (high is good): up arrow is OK color, down arrow is Bad color.
- High value is bad on: up arrow is Bad color, down arrow is OK color.
- A near-zero Δ shows a neutral horizontal indicator instead of an arrow.
- No data to compare - if the channel was not recording during the comparison period (e.g. a camera that came online today and has no data from "yesterday"), the tile shows no data to compare with the exact date and time window underneath it (e.g.
06.06.2026 18:30 - 19:30). Operators can hover the line for a tooltip with the comparison mode. - Live archive backfill / playback - the tile seeds its sample buffer from recordings on first appearance so the Δ% is populated immediately. In playback the comparison anchors at the timeline cursor instead of wall-clock now.
- Export to CSV - in playback mode, the Export badge produces a 2-column
timestamp, valueCSV like the other single-key renderers.
Table¶
Scrolling time-ordered table of (Time, Value) rows. Use when you want to read the actual values (numbers or text) in sequence rather than inferring them from a curve. Reuses the same archive backfill, in-pane window picker, and playback cursor machinery as the Line Chart.
- Newest on top - the latest row is always inserted at the top of the table; older rows scroll down and off the bottom. Auto-follow keeps the viewport pinned to the top in Live mode; if the operator scrolls down to inspect older rows, a "Paused (click to jump back to newest)" badge appears at the bottom of the pane. Click the badge or scroll back to the top to resume following.
- Time window - same preset list as the Line Chart (60 seconds up to 24 hours, plus Custom). Drives both the archive backfill scan range on first entry and the rolling age cutoff for in-memory rows.
- Max rows - hard cap on stored rows independent of the window (default 200, max 5000). Whichever cuts harder wins: a 24-hour window with
Max rows = 200keeps only the 200 newest, while a 60-second window withMax rows = 5000keeps only the last 60 seconds even if fewer than 5000. - Header name - custom header text for the value column; leave blank to use "Value". Useful when the data key is something opaque (
@Value,Level) and the column should read "Speed", "PlateNumber", "Counter", etc. - Timestamp column - toggle the Time column on/off and pick a format string (default
HH:mm:ss; standard .NETDateTimeformat strings work, e.g.HH:mm:ss.fffordd.MM HH:mm). - Value column - font size and Left / Center / Right alignment.
- Show Δ column - optional numeric difference between a row and the row immediately older than it. Renders blank for non-numeric values, so it's safe to enable on text-based fields without crashing.
- Thresholds - same shared model as Number / Gauge / Line Chart. When Enable thresholds is on, the value text is tinted Ok / Warn / Bad based on Min / Max and the High-is-bad direction. Non-numeric values stay neutral.
- Live archive backfill - on first appearance of a Table widget, the configured window of recorded data is loaded from the archive so the table opens with real history instead of accumulating a single row per packet from cold.
- Playback - the row at-or-before the timeline cursor is highlighted as the cursor moves. Large jumps trigger a fresh range scan around the new cursor position, identical to the Line Chart behavior.
Base64 Image¶
Renders an image carried in the metadata value as a base64-encoded string. Use it for cameras / analytics that embed JPEG / PNG snapshots (vehicle plates, face thumbnails, ROI crops) inside the ONVIF metadata stream.
- Empty value - the widget shows a "No Image" placeholder so an absent payload is visibly different from a render bug.
- Decode error - if the value isn't valid base64 (or the bytes aren't a known image format), the widget shows "Decode error:
" in the Bad color instead of going blank, so the operator can see the payload isn't usable. - Image displayed - any string that decodes as JPEG, PNG, BMP, or GIF is shown. The raw
base64...form and thedata:image/png;base64,...URI form are both accepted; the prefix is stripped automatically. - No widget-specific options - title, density, and stale handling work the same as every other render type. There are no thresholds, no font sizes, no axes; the image either renders or it doesn't.
What to Read¶
The "What to read" section is the bridge from the raw stream to a single value:
- Topic - the ONVIF topic to listen for. Match is exact - the camera's topic must equal the configured value letter for letter. Pick a topic from the dropdown (populated by Pick packet or Import packet) or paste one in directly.
- Field - the
tt:SimpleItem Nameto pull the value from. The dropdown filters to only the fields seen under the currently-selected Topic, so changing the Topic refreshes the available fields. - Pick packet... - browse recorded packets from the selected channel (last 1h / 6h / 24h / 7d) and apply one with a click. The selected packet's topic is set on Topic, and Topic / Field / Source filter dropdowns populate from its contents.
- Import packet... - paste an XML packet from a vendor SDK sample, an exported packet from another widget, or any other source. Same effect as Pick packet, no channel required.
- Source filter (advanced, under the Advanced expander) - constrain to specific Source SimpleItem
name=valuepairs (e.g.port=1for I/O input port 1, orobjectid=42for one tracked object). Multiple pairs can be combined with semicolons.
Pick packet¶
The fastest path on any channel that has metadata recordings. Click Pick packet... to open the recorded-packets browser:
- Lookback - pick Last 1 hour, 6 hours, 24 hours (default), or 7 days. Click Reload after changing it.
- Search - filters the list by topic, field name, or value as you type.
- Packet list - one row per NotificationMessage in the recordings, newest first. Columns: capture time (UTC), topic, and a summary of the message's Source and Data SimpleItems (e.g.
[VideoSource=1]; speed_kmh=43). - Preview - clicking a row syntax-highlights the full packet XML in the right pane so you can see exactly what arrived at that moment.
- Use selected packet - applies the picked packet: the row's topic is set on Topic, the Field / Source filter dropdowns populate from the packet's contents, and the configuration window's live preview re-extracts immediately. Double-click a row to apply without using the button.
The dialog runs against the channel's recordings via its own playback source, so it does not disturb the live preview that's already streaming behind the configuration window. A hard cap of 10000 rows protects the dialog from very noisy channels; if you hit it, narrow the lookback or use the search box to find the message you want.
For multi-series Line Chart widgets, each Additional series row has its own Pick packet... button (alongside Import packet...) so you can wire each series from a different sample without disturbing the others.
Prerequisites are the same as Playback mode: metadata recording must be enabled on the channel and a recording rule must cover it (see Prerequisites). If Pick packet opens empty for a channel you know publishes events, recording isn't reaching the archive.
Import packet¶
When the channel has no recordings yet, or when you have a sample XML packet from the vendor's documentation, click Import packet..., paste the XML, and the dialog parses it and reports Parsed N topic(s), M field(s), K source value(s). Click Import to apply.
- The first topic in the packet is selected on Topic.
- The imported XML seeds the configuration window's live preview so the widget renders right away; subsequent live packets keep refreshing it.
- For multi-series Line Chart widgets, each Additional series row has its own Import packet... button so you can wire each series from a different sample without disturbing the others.
Title and Density¶
Every widget has the same theme tokens (palette, type scale) so a wall of mixed widgets reads coherently.
- Title - optional title text above the widget. Position Left / Center / Right, font size, color
- Density - Compact (0.82x), Comfortable (1.0x), Spacious (1.18x). Multiplier applied to non-user-set sizes (lamp label, number value/unit, gauge unit, title) so widgets line up across panes without forcing identical absolute sizes everywhere
User-set sizes (Title font size, Gauge value font size, Text font size, Lamp icon size) are not scaled by Density - if you set them explicitly, they are taken as-is.
Live Preview¶
The configuration window has a live preview pane on the right. As soon as a metadata packet matches your Topic + Data key, the preview shows the same widget that will render in the view. Until a value arrives, the preview shows the same Waiting for data... indicator that the live view uses, so what you see in Setup matches what users will see at runtime.
Pick packet and Import packet seed the preview immediately from the picked/pasted XML so you see a value before the next live packet arrives. After that, every live packet on the channel keeps re-rendering the preview. Changing the Topic or Data key re-extracts against the last packet seen, so you don't have to wait for a fresh one to validate the choice. The Line Chart and Table previews are sized at 16:9 inside the configuration window so the rendered shape matches the runtime pane.
Stale Handling¶
Optional. Mark stale after (seconds) - if no matching packet arrives within that window, the widget dims and a "stale" badge appears in the corner. Useful for catching dead channels: if the camera silently stops emitting metadata, the widget visibly fades instead of pretending the last value is still current. Set to 0 to disable.
Export to CSV¶
Every render type can save its archive history to a CSV file directly from the widget. Use it for shift reports, export to Excel for charting, or feeding analytics off the VMS.
- Enable / disable per widget - Enable Export to CSV in the configuration window controls whether the Export badge appears on the widget. Default is on; turn it off on dashboards / video walls where the badge is just clutter.
- Where the badge appears - top-right of the widget in Playback mode only.
Export dialog¶
Opens with a two-column layout. The left column is editable settings; the right column is a live preview of the rows that will land in the CSV.
- Time range - From and To, the overall range to query data.
- Daily window (optional) - turn on to keep only rows whose time-of-day falls inside a
Start-Endwindow. Set Start later than End for an overnight window (e.g.22:00 → 06:00keeps every night between 22:00 and 06:00 the next morning). Identical Start and End match nothing. - Days - combo with Every day (default), Weekdays (Mon-Fri), Weekends (Sat+Sun), and Custom... which reveals a row of 7 day checkboxes. At least one day must be selected.
- CSV format - delimiter (Comma / Semicolon / Tab), decimal separator (Period / Comma).
- Live preview - up to the first 200 matching rows are shown in a scrolling list as you tweak settings, with the full match count above the list (e.g. showing 200 of 1,847 matching rows). Updates 500 ms after the last keystroke so rapid edits do not pile up scans. A spinner overlays the preview while the archive scan runs.
For Lamp widgets the CSV gets an extra label column with the resolved Lamp-map label (raw value 0 becomes Off, 1 becomes On, etc.). Unmapped values fall back to the raw value so the column is never blank. Other render types produce a 2-column timestamp, value CSV.
For multi-series Line Chart widgets the CSV is wide-format: one timestamp column followed by one value column per series, headers using each series's display name. Coincident timestamps across series collapse into a single row; missing values render as empty cells.
No-Data and Loading Indicators¶
A pulsing dot with a status line is shown:
- Waiting for data... - live mode is up, no matching packet yet
- Loading recent values from archive... - Line Chart or Table cold-start in playback mode while the seed query runs
- Loading last 6h from archive... - Line Chart or Table cold-start in live mode (or after a window switch) while history is being backfilled
The chart or table appears as soon as the loading step finishes, regardless of whether any samples were found.
Playback¶
Playback mode is supported: as the timeline cursor moves, the widget shows the value that was emitted at that timestamp. Useful for replaying analytics events alongside recorded video.
For Line Chart and Table specifically, the view is seeded with archive data on entry (no scrubbing needed to populate). For Line Chart the cursor line tracks the timeline position; for Table the row at-or-before the cursor is highlighted. In both cases, large jumps trigger a fresh range scan around the new cursor.
Storage Format¶
The plugin stores all settings as MIP item properties on the view item. No external configuration files. Lamp rows serialize as value=label:#color[:IconName]|... so they survive backup / restore.
Troubleshooting¶
| Problem | Fix |
|---|---|
| "Waiting for data..." never goes away | Check the channel is recording metadata. Use Pick packet... to see what topics are in the recordings. Confirm Topic and Data key are correct. |
| Plugin doesn't appear in Setup | Check MIPPlugins\MetadataDisplay\ exists. Unblock the ZIP if installed manually. |
| Wrong value shown | Topic / Data key mismatch (case-insensitive but the names must match). Use Pick packet... to copy them from the actual recorded packets. |
| Gauge value clipped or off-center | Set the Scale Min/Max to bracket your real value range. Reduce Title font size if it's eating the canvas. |
| Line Chart starts empty for a wide window | Recorded metadata is required for backfill. Confirm a recording rule covers the metadata channel (see Prerequisites). Without recordings the chart still works, it just fills only with new live samples. |
| Channel does not appear in the configuration channel picker | Either the metadata stream is not enabled on the camera, the user has no rights on the channel, or the channel is in a folder you cannot browse. See Prerequisites. |
| Playback view stays empty | The metadata channel exists but is not being recorded. Add or extend a recording rule so the metadata channel is included. |
| Line Chart "Paused" badge keeps appearing | You are zoomed in or panned in Live mode, which auto-pauses to keep the view stable. Click the badge to resume the rolling live window. |
| Export badge does not appear | The widget is in Live mode (badge is Playback-only), or Enable Export to CSV has been turned off in the widget configuration. |
| Export CSV is empty / has fewer rows than expected | Time range too narrow, daily-window setting too aggressive, or the metadata channel was not recorded for that period (recordings are required for export - see Prerequisites). |
| Table "Paused" badge keeps appearing | You scrolled down from the top to inspect older rows; auto-follow stops so the view does not jump while you are reading. Click the badge or scroll back to the top to resume following the newest row. |
| Table Δ column is blank | The data key is text-based (or only one value has been seen so far). Δ is only computed when both adjacent rows parse as numbers; non-numeric values render blank rather than wrong. |
| In-pane window picker change does not persist | This is by design - the picker is session-only. Open the configuration and change Time window there to make it permanent. |