%% Add m-Script Instrument Panel App to Tank Model
%
%% 
% This example shows how a MATLAB m-script can create an instrument panel for the 
% Simulink Real-Time application that you build from the model |slrt_ex_tank|. The instrument 
% panel contains these UI components:
%
% * Slider &mdash; To tune the required tank level (SetPoint).
% * Linear Gauge &mdash; To display the actual tank level (TankLevel).
% * Semicircular Gauge &mdash; To display the pump control status (ControlValue).
% * Axes &mdash; To display signal output for SetPoint, TankLevel, and 
% ControlValue.
% 
% This example also shows how to stream signal and parameter data between the 
% real-time application and the instrument panel by using the instrumentation 
% object.
% 
% The example UI and callback code demonstrate the subtle syntax 
% differences between applying the instrumentation object in an m-script versus 
% applying the instrumentation object in an App Designer app. 
%
open_system(fullfile(matlabroot,'toolbox','slrealtime','examples','slrt_ex_tank'));
%% Start Target Computer and Build Real-Time Application
% These operations generate the real-time application that streams data to the instrument panel app. 
%
% # Start the target computer.
% # Open the model <matlab:open_system(docpath(fullfile(matlabroot,'toolbox','slrealtime','examples','slrt_ex_tank'))) |slrt_ex_tank|>.
% # Connect the development computer to the target computer. Build the |slrt_ex_tank| model. Deploy the real-time 
% application to the target computer. In the MATLAB Command Window, type:
%
mdl = 'slrt_ex_tank';
set_param(mdl, 'RTWVerbose', 'off');
tg = slrealtime;
rtwbuild(mdl);
tg.load(mdl);
%% Run Instrument Panel App
% The instrument panel app |slrt_tankAppScript| provides controls to start
% and interact with the real-time application |slrt_ex_tank|. 
%
% # Run the app. Right-click the |slrt_tankAppScript.m| file and click *Run*. Or, in the 
% Command Window, type: |slrt_tankAppScript|
% # Start the real-time application and stream data. In the instrument
% panel app, click *Start*. The real-time application runs and streams data
% to the app. The axes display changes to signal values.
% # Adjust the SetPoint slider. The real-time application signals react to
% the set point change.
% # To stop the app, click *Stop*.
% 
% <<../slrt_ex_tank_initial.png>>
% 
%% Set Up Instrument Panel App
% To provide an interactive instrument panel display for simulation, create 
% the instrument panel app as a UIFigure. Hide the app until all UI components 
% are created.
% 
%  hf = uifigure('Visible', 'off', ...
%      'Position', [100 100 640 504], ...
%      'CloseRequestFcn', @closeRequest);
%%
% *Note:* The Position settings are optional. This information is provided if 
% you want your instrument panel layout to exactly match the example panel.
% 
%% Create Plot Axes
% Add a plot axe by using the UIAxes command. These axes use animation to
% display the signal data that streams from the real-time application.
%
%  ha = uiaxes(hf, 'Position', [197 94 424 396]);
%  xlabel(ha, 'time')
%% Create Tank Level Gauge
% Add a linear gauge by using the UIGauge command and |'linear'| argument. 
% This gauge displays the tank level signal data. 
% 
%  tlGauge = uigauge(hf, 'linear', ...
%      'Limits', [0 10], ...
%      'Orientation', 'vertical', ...
%      'Position', [110 168 32 270]);
%% 
% Add a label for the tank level gauge.
% 
%  uilabel(hf, ...
%      'HorizontalAlignment', 'center', ...
%      'Position', [110 136 63 22], ...
%      'Text', 'Tank Level');
%% Create Set Point Slider
% Add a slider by using the UISlider command. This slider enables changes to
% the set point parameter value.
% 
%  spSlider = uislider(hf, ...
%      'Limits', [0 10], ...
%      'Orientation', 'vertical', ...
%      'Position', [58 172 3 259], ...
%      'ValueChangedFcn', @SetPointSliderValueChanged);
%% 
% Update the slider from the set point parameter value.
%
%  value = tg.getparam('slrt_ex_tank/SetPoint','Value');
%  spSlider.Value = value;
%% 
% Add a label to the set point slider.
% 
%  uilabel(hf, ...
%      'HorizontalAlignment', 'right', ...
%      'Position', [41 136 54 22], ...
%      'Text', 'Set Point');
%% Create Control Value Gauge
% Add a semicircular gauge by using the UIGauge command and |'semicircular'| 
% argument. This gauge displays the control value as |'Off'| or |'On'|. 
% 
%  cvGauge = uigauge(hf, 'semicircular', ...
%      'Limits', [-2 12], ...
%      'MajorTicks', [0 10], ...
%      'MajorTickLabels', {'Off', 'On'}, ...
%      'MinorTicks', [], ...
%      'Position', [55 55 92 50]);
%% 
% Add a label to the control value gauge.
% 
%  uilabel(hf, ...
%      'HorizontalAlignment', 'center', ...
%      'Position', [79 12 44 28], ...
%      'Text', {'Control'; 'Value'});
%% Create Start-Stop Button
% Add a start or stop button by using the UIButton command. This button
% starts the real-time application and begins streaming data to the instrument 
% panel. This button also stops the real-time application. 
% 
%  ssButton = uibutton(hf, 'push', ...
%      'Icon', 'run_24.png', ...
%      'Position', [18 449 171 41], ...
%      'Text', 'Start', ...
%      'ButtonPushedFcn', @StartStopButtonPushed);
%% Show Instrument Panel App
% After all the UI instruments are created, display the instrument panel. 
% 
%  hf.Visible = 'on';
%% Create Instrumentation Object
% Creates the instrumentation object for the real-time application:
% 
%  hInst  = slrealtime.Instrument(mdl);
%% Connect Signals to Axes
% The |connectLine| commands connect the signals to lines that are plotted on the
% axes.
% 
%  hInst.connectLine(ha,[mdl '/SetPoint']    ,1);
%  hInst.connectLine(ha,[mdl '/TankLevel']   ,1);
%  hInst.connectLine(ha,[mdl '/ControlValue'],1);
%  hLine = [hInst.hObjects{:}];
%%
% When using the |connectLine| function to connect output signals from the
% real-time application to the instrumentation object, the Simulink
% Real-Time Explorer provides a useful view of the signals and their port
% numbers. To open the Explorer and view the signals, in the MATLAB Command 
% Window, type:
% 
%  slrtExplorer
% 
% <<../slrtExplorer.png>> 
%% Add Axes Legend
% The legend command labels each line in the legend with the signal name.
% 
%  legend(ha,{hLine(1,1).lineName,hLine(1,2).lineName,hLine(1,3).lineName})
%% Connect Signals to Scalar Displays
% The |connectScalar| commands connects the parameter values to the scalar displays. 
% 
% hInst.connectScalar(tlGauge,[mdl '/TankLevel']   ,1);
% hInst.connectScalar(cvGauge,[mdl '/ControlValue'],1);
%% Add Callback to Wrap x Axis
% This |connectCallback| command helps animate plotting signals on the axes. 
% The command wraps the display of signal data by changing the x origin value to keep 
% the signal data within the plot UI.
% 
%  hInst.connectCallback(@(instObj,eventData)handleAxes(instObj,eventData,ha));
%  ha.XLim = [0 10];
%  ha.YLim = [-1 13];
%% Store UI Object Handles in User Data
% Add object handles for the UI object. These handles enable adding callbacks 
% to process object events. 
% 
%  handle.ha        = ha;
%  handle.tlGauge   = tlGauge;
%  handle.spSlider  = spSlider;
%  handle.cvGauge   = cvGauge;
%  handle.ssButton  = ssButton;
%  handle.tg        = tg;
%  handle.hInst     = hInst;
%  handle.startIcon = 'run_24.png';
%  handle.stopIcon  = 'stop_24.png';
%  hf.UserData = handle;
%  tg.addInstrument(hInst);
%% Add Callback to Update XLim and Prevent Axis Wrap
% The |handleAxes| callback processes signal data that plots signals on the axes.
% 
%  function handleAxes(instObj, eventData, ha)
%  currTime = eventData.ExecTime;
%  if max(currTime)<max(ha.XLim) % do nothing
%  else
%      ha.XLim = max(ha.XLim) + [0 10];
%  end
%  end
%% Add Callback for Clean Up on Instrument Panel Close
% The |closeRequest| callback processes UI close requests, including stop of 
% the real-time application. The instrumentation object uses 
% callbacks to add streaming data to your UIAxes.  If you delete the UIAxes 
% by deleting and closing the UIFigure without first deleting the instrumentation 
% object, the callback state can produce errors or warnings. It is best practice 
% to add a close request callback to your app that stops the instrumentation 
% object and deletes it.  
% 
%  function closeRequest(hfigure, event)
%  handle = hfigure.UserData;
%  if ~isempty(handle.tg)
%      handle.tg.stop;
%  end
%  if ~isempty(handle.hInst)
%      delete(handle.hInst)
%  end
%  delete(hfigure)
%  end
%% Add Callback to Handle Slider Value Changes
% The |SetPointSliderValueChanged| callback processes changes to the slider
% value by streaming the parameter value data to the real-time application.
% 
%  function SetPointSliderValueChanged(hslider, event)
%  hfigure = hslider.Parent;
%  handle = hfigure.UserData;
%  if ~isempty(handle.tg)
%      value = handle.spSlider.Value;
%      handle.tg.setparam('slrt_ex_tank/SetPoint','Value',value);
%  end
%  end
%% Add Callback to Handle Button-Push Events
% The |StartStopButtonPushed| callback processes button-push events. For *Start* 
% button push, the callback starts the real-time application and toggles the 
% button label to *Stop*. For *Stop* button push, the callback stops the real-time 
% application and toggles the button label to *Start*. 
% 
%  function StartStopButtonPushed(hbutton, event)
%  hfigure = hbutton.Parent;
%  handle = hfigure.UserData;
%  if strcmp(handle.ssButton.Icon, handle.startIcon) % START
%      handle.hInst.clearScalarAndLineData; % clear old data
%      handle.tg.start; % start instrumentation and target
%      handle.ssButton.Icon = handle.stopIcon; % change the icon
%      handle.ssButton.Text = 'Stop';
%  else % STOP
%      handle.tg.stop;
%      handle.ssButton.Icon = handle.startIcon; % change the icon
%      handle.ssButton.Text = 'Start';
%  end
%  end
%%
bdclose('all')
%%
% Copyright 2020 The MathWorks, Inc.