Skip to content

Commit 90175b9

Browse files
committed
Merge: simple_live_dashboard example
2 parents a06b6e5 + 23ef746 commit 90175b9

1 file changed

Lines changed: 105 additions & 0 deletions

File tree

examples/simple_live_dashboard.m

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
function ctx = simple_live_dashboard()
2+
%SIMPLE_LIVE_DASHBOARD Minimal one-FastSensePlot dashboard with live mode + events.
3+
%
4+
% Shows the smallest possible DashboardEngine setup that exercises both
5+
% live refresh and threshold-driven event markers:
6+
% - one SensorTag fed by a writer timer (1 sample / second)
7+
% - one MonitorTag tripping when y > 5 (drives the EventStore)
8+
% - one FastSenseWidget on the dashboard with ShowEventMarkers=true
9+
% - engine.startLive() refreshes the plot every LiveInterval
10+
%
11+
% Returns:
12+
% ctx — struct with fields:
13+
% engine — DashboardEngine handle (rendered, live)
14+
% writerTimer — MATLAB timer pushing synthetic samples
15+
% tag — SensorTag streaming the signal
16+
% monitor — MonitorTag tripping on y > 5
17+
% store — EventStore receiving events
18+
%
19+
% Teardown is wired to the figure's CloseRequestFcn — closing the
20+
% window stops the writer + live timer cleanly. Calling
21+
% simple_live_dashboard_teardown(ctx) does the same explicitly.
22+
%
23+
% Example:
24+
% ctx = simple_live_dashboard();
25+
% pause(60); % watch a few cycles
26+
% evts = ctx.store.getEventsForTag('demo.signal.high');
27+
%
28+
% See also DashboardEngine, FastSenseWidget, MonitorTag, EventStore,
29+
% example_event_markers.
30+
31+
install();
32+
33+
% --- Domain objects --------------------------------------------------
34+
es = EventStore();
35+
tag = SensorTag('demo.signal', 'Name', 'Demo Signal', 'Units', 'units');
36+
mon = MonitorTag('demo.signal.high', tag, @(x, y) y > 5, ...
37+
'EventStore', es, 'MinDuration', 0);
38+
39+
% --- Dashboard with a single FastSenseWidget -------------------------
40+
engine = DashboardEngine('Simple Live Dashboard', ...
41+
'Theme', 'light', 'LiveInterval', 1.0);
42+
engine.addWidget('fastsense', ...
43+
'Title', 'Demo Signal (threshold y > 5)', ...
44+
'Tag', tag, ...
45+
'ShowEventMarkers', true, ...
46+
'EventStore', es, ...
47+
'Position', [1 1 24 8]);
48+
engine.render();
49+
engine.startLive();
50+
51+
% --- Writer timer: one synthetic sample per second -------------------
52+
% Slow sine swinging 1..7, crossing the y=5 threshold roughly every
53+
% 15 s — gives the user a steady cadence of events to watch.
54+
t0 = posixtime(datetime('now'));
55+
writer = timer( ...
56+
'ExecutionMode', 'fixedRate', ...
57+
'Period', 1.0, ...
58+
'BusyMode', 'drop', ...
59+
'TimerFcn', @(~,~) writeOne_(), ...
60+
'ErrorFcn', @(~,~) []);
61+
start(writer);
62+
63+
ctx = struct( ...
64+
'engine', engine, ...
65+
'writerTimer', writer, ...
66+
'tag', tag, ...
67+
'monitor', mon, ...
68+
'store', es);
69+
70+
% --- Wire CloseRequestFcn so X-button cleans up ----------------------
71+
if ~isempty(engine.hFigure) && ishandle(engine.hFigure)
72+
set(engine.hFigure, 'CloseRequestFcn', @(s, ~) closeAll_(s));
73+
end
74+
75+
% ===== nested helpers ==============================================
76+
77+
function writeOne_()
78+
try
79+
elapsed = posixtime(datetime('now')) - t0;
80+
y = 4 + 3 * sin(elapsed * 2 * pi / 30);
81+
tag.updateData([tag.X, elapsed], [tag.Y, y]);
82+
mon.appendData(elapsed, y);
83+
catch
84+
% Writer ticks must never crash the timer.
85+
end
86+
end
87+
88+
function closeAll_(fig)
89+
try
90+
if ~isempty(writer) && isvalid(writer)
91+
if strcmp(writer.Running, 'on'); stop(writer); end
92+
delete(writer);
93+
end
94+
catch
95+
end
96+
try
97+
if ~isempty(engine) && isvalid(engine) ...
98+
&& ismethod(engine, 'stopLive')
99+
engine.stopLive();
100+
end
101+
catch
102+
end
103+
try; delete(fig); catch; end
104+
end
105+
end

0 commit comments

Comments
 (0)