Playback Enable Function
I'm adding a button called "Playback", and it's function needs to take Start and End Date/Time Pickers, calculate span, update screen properties, and set playback properties automatically. I know how to script most of that, but I want to be able to Enable the PlaybackMode in the script. I just can't find any documentation on the Playback functionality.
I can see that certain properties like PlaybackStart, PlaybackDuration, PlaybackSpeed, PlaybackMode, and even PlaybackPosition exist, but I need to know how to set PlaybackMode to "Enabled" and push DateTime and span values into the properties using script initiated with a Button.
Does anyone know how to do this? I can't find it in any of the documentation.
4 replies
-
Hi ryan ,
I asked our development team about this. Unfortunately, the Playback properties were not meant to be posted publicly as they were only for internal use. We never intended users to interact with the Playback functionality through scripting as it is a little weird/complex getting Apps/Trends to work together. Sorry I don't have a better answer for you.
-
Hi ryan ,
You can control playback with scripting and you can even loop the playback if you like. Getting references to the playback properties requires using reflection. And once you do that, you do have to create your own EventTimer to periodically update the playback position.
Some interesting applications could be setting up an EventsTable to set the playback parameters to the start and end time of an event when an event from the table is clicked.
Below is a example application and the script to create it.
using AxiomCore2.Client; using AxiomCore2.ControlProperties; using AxiomCore2.Controls; using AxiomCore2.Data; using AxiomCore2.Events; using AxiomCore2.Legacy; using AxiomCore2.Log; using AxiomCore2.Managers; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Collections; using System.Drawing; //using CanaryWebServiceHelper; //using CanaryWebServiceHelper.HistorianWebService; namespace AxiomScript { public partial class ScreenScript : IDisposable { // NOTE: click help icon in dialog header for API documentation and examples. // NOTE: use EventTimer class when timer is necessary. See API documentation. // axiom references public ControlApplication Application { get; } = ControlApplication.Instance; public ControlFactoryManager ControlFactory { get; } = ControlFactoryManager.Instance; public IDataProvider DataProvider { get; } = DataProviderManager.CreateInstance(); public ILog Log { get; } = ClientLog.UserScript; public NavigationManager Navigation { get; } = NavigationManager.Instance; public ControlScreen Screen => _screen; System.Reflection.PropertyInfo playbackModeProperty; System.Reflection.PropertyInfo playbackPositionProperty; System.Reflection.PropertyInfo playbackDurationProperty; System.Reflection.PropertyInfo playbackSpeedProperty; System.Reflection.PropertyInfo playbackStartProperty; bool loopPlayback; private EventTimer playbackTimer = null; private int playbackTimerInitialTime = 0; private int playbackTimerInterval = 250; public void OnScreenVisible() { //Get references to the playback properties using reflection playbackModeProperty = Application.GetType().GetProperty("AxiomCore2.IComponentPlayback.PlaybackMode",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); playbackPositionProperty = Application.GetType().GetProperty("AxiomCore2.IComponentPlayback.PlaybackPosition",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); playbackDurationProperty = Application.GetType().GetProperty("AxiomCore2.IComponentPlayback.PlaybackDuration",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); playbackSpeedProperty = Application.GetType().GetProperty("AxiomCore2.IComponentPlayback.PlaybackSpeed",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); playbackStartProperty = Application.GetType().GetProperty("AxiomCore2.IComponentPlayback.PlaybackStart",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); #region Controls //Set up example playback controls if(!Screen.ScreenControls.ContainsKey("SetStartButton")){ var setStartButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "SetStartButton"); Screen.Children.Add(setStartButton); setStartButton.Text = "Set Start"; setStartButton.Width = 175; setStartButton.X = 0; setStartButton.Y = 0; setStartButton.OnClick = "SetStartButton_OnClick"; } //Start Time ControlDateTimePicker playbackStartDateTimePicker; if(!Screen.ScreenControls.ContainsKey("PlaybackStartDateTimePicker")){ playbackStartDateTimePicker = (ControlDateTimePicker)ControlFactory.CreateControl(ControlKind.DateTimePicker, "PlaybackStartDateTimePicker"); Screen.Children.Add(playbackStartDateTimePicker); playbackStartDateTimePicker.X = 0; playbackStartDateTimePicker.Y = 50; playbackStartDateTimePicker.DateTime = (DateTime)playbackStartProperty.GetValue(Application); } else { playbackStartDateTimePicker = Screen.ScreenControls["PlaybackStartDateTimePicker"] as ControlDateTimePicker; playbackStartDateTimePicker.DateTime = (DateTime)playbackStartProperty.GetValue(Application); } playbackStartDateTimePicker.DateTime = (DateTime)playbackStartProperty.GetValue(Application); if(!Screen.ScreenControls.ContainsKey("SetPositionButton")){ var setPositionButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "SetPositionButton"); Screen.Children.Add(setPositionButton); setPositionButton.Text = "Set Position"; setPositionButton.Width = 175; setPositionButton.X = 250; setPositionButton.Y = 0; setPositionButton.OnClick = "SetPositionButton_OnClick"; } //Position ControlDateTimePicker playbackPositionDateTimePicker; if(!Screen.ScreenControls.ContainsKey("PlaybackPositionDateTimePicker")){ playbackPositionDateTimePicker = (ControlDateTimePicker)ControlFactory.CreateControl(ControlKind.DateTimePicker, "PlaybackPositionDateTimePicker"); Screen.Children.Add(playbackPositionDateTimePicker); playbackPositionDateTimePicker.X = 250; playbackPositionDateTimePicker.Y = 50; } else { playbackPositionDateTimePicker = Screen.ScreenControls["PlaybackPositionDateTimePicker"] as ControlDateTimePicker; } playbackPositionDateTimePicker.DateTime = (DateTime)playbackPositionProperty.GetValue(Application); if(!Screen.ScreenControls.ContainsKey("SetDurationButton")){ var setDurationButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "SetDurationButton"); Screen.Children.Add(setDurationButton); setDurationButton.Text = "Set Duration"; setDurationButton.Width = 175; setDurationButton.X = 500; setDurationButton.Y = 0; setDurationButton.OnClick = "SetDurationButton_OnClick"; } if(!Screen.ScreenControls.ContainsKey("DurationTextBox")){ var durationTextBox = (ControlTextBox)ControlFactory.CreateControl(ControlKind.TextBox, "DurationTextBox"); Screen.Children.Add(durationTextBox); durationTextBox.X = 500; durationTextBox.Y = 50; durationTextBox.Text = playbackDurationProperty.GetValue(Application).ToString(); } if(!Screen.ScreenControls.ContainsKey("SetSpeedButton")){ var setSpeedButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "SetSpeedButton"); Screen.Children.Add(setSpeedButton); setSpeedButton.Text = "Set Speed"; setSpeedButton.Width = 175; setSpeedButton.X = 750; setSpeedButton.Y = 0; setSpeedButton.OnClick = "SetSpeedButton_OnClick"; } //Speed ControlTextBox speedTextBox; if(!Screen.ScreenControls.ContainsKey("SpeedTextBox")){ speedTextBox = (ControlTextBox)ControlFactory.CreateControl(ControlKind.TextBox, "SpeedTextBox"); Screen.Children.Add(speedTextBox); speedTextBox.X = 750; speedTextBox.Y = 50; } else { speedTextBox = Screen.ScreenControls["SpeedTextBox"] as ControlTextBox; } speedTextBox.Text = playbackSpeedProperty.GetValue(Application).ToString(); if(!Screen.ScreenControls.ContainsKey("EnablePlaybackButton")){ var enablePlaybackButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "EnablePlaybackButton"); Screen.Children.Add(enablePlaybackButton); enablePlaybackButton.Text = "Enable Playback"; enablePlaybackButton.Width = 175; enablePlaybackButton.X = 0; enablePlaybackButton.Y = 100; enablePlaybackButton.OnClick = "EnablePlaybackButton_OnClick"; } if(!Screen.ScreenControls.ContainsKey("DisablePlaybackButton")){ var disablePlaybackButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "DisablePlaybackButton"); Screen.Children.Add(disablePlaybackButton); disablePlaybackButton.Text = "Disable Playback"; disablePlaybackButton.Width = 175; disablePlaybackButton.X = 200; disablePlaybackButton.Y = 100; disablePlaybackButton.OnClick = "DisablePlaybackButton_OnClick"; } if(!Screen.ScreenControls.ContainsKey("StartPlaybackButton")){ var startPlaybackButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "StartPlaybackButton"); Screen.Children.Add(startPlaybackButton); startPlaybackButton.Text = "Start Playback"; startPlaybackButton.Width = 175; startPlaybackButton.X = 0; startPlaybackButton.Y = 150; startPlaybackButton.OnClick = "StartPlaybackButton_OnClick"; } if(!Screen.ScreenControls.ContainsKey("StopPlaybackButton")){ var stopPlaybackButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "StopPlaybackButton"); Screen.Children.Add(stopPlaybackButton); stopPlaybackButton.Text = "Stop Playback"; stopPlaybackButton.Width = 175; stopPlaybackButton.X = 200; stopPlaybackButton.Y = 150; stopPlaybackButton.OnClick = "StopPlaybackButton_OnClick"; } if(!Screen.ScreenControls.ContainsKey("LoopPlaybackListBox")){ var loopPlaybackListBox = (ControlListBox)ControlFactory.CreateControl(ControlKind.ListBox, "LoopPlaybackListBox"); Screen.Children.Add(loopPlaybackListBox); loopPlaybackListBox.Items = new string[]{"Loop"}; loopPlaybackListBox.Width = 175; loopPlaybackListBox.Height = 50; loopPlaybackListBox.X = 400; loopPlaybackListBox.Y = 150; loopPlaybackListBox.OnSelectionChange = "LoopPlaybackListBox_OnSelectionChange"; } else { var loopPlaybackListBox = Screen.ScreenControls["LoopPlaybackListBox"] as ControlListBox; loopPlaybackListBox.SelectedItems = new string[]{}; } if(!Screen.ScreenControls.ContainsKey("GetInfoButton")){ var getInfoButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "GetInfoButton"); Screen.Children.Add(getInfoButton); getInfoButton.Text = "Get Info"; getInfoButton.X = 400; getInfoButton.Y = 100; getInfoButton.OnClick = "GetInfoButton_OnClick"; } if(!Screen.ScreenControls.ContainsKey("SetTimerMsButton")){ var setTimerMsButton = (ControlButton)ControlFactory.CreateControl(ControlKind.Button, "SetTimerMsButton"); Screen.Children.Add(setTimerMsButton); setTimerMsButton.Text = "Set Timer ms"; setTimerMsButton.Width = 175; setTimerMsButton.X = 600; setTimerMsButton.Y = 100; setTimerMsButton.OnClick = "SetTimerMsButton_OnClick"; } //Timer Milliseconds - Defaults to 250 milliseconds. //Set to a higher number to refresh less often which is good for low bandwidth connections ControlTextBox timerMsTextBox; if(!Screen.ScreenControls.ContainsKey("TimerMsTextBox")){ timerMsTextBox = (ControlTextBox)ControlFactory.CreateControl(ControlKind.TextBox, "TimerMsTextBox"); Screen.Children.Add(timerMsTextBox); timerMsTextBox.X = 600; timerMsTextBox.Y = 150; } else { timerMsTextBox = Screen.ScreenControls["TimerMsTextBox"] as ControlTextBox; } timerMsTextBox.Text = playbackTimerInterval.ToString(); if(!Screen.ScreenControls.ContainsKey("CPUSparkChart")){ var cpuSparkChart = (ControlSparkChart)ControlFactory.CreateControl(ControlKind.SparkChart, "CPUSparkChart"); Screen.Children.Add(cpuSparkChart); cpuSparkChart.X = 0; cpuSparkChart.Y = 300; cpuSparkChart.Width = 1024; cpuSparkChart.Height = 200; cpuSparkChart.SourceTag = "localhost.{Diagnostics}.Sys.CPU Usage Total"; } #endregion Controls } public void OnScreenInvisible() { } public void Dispose() { } //This gets called every time the playbackTimer ticks (defaults to every 250 ms) //This updates the playback position to a new position or stop playback if it reaches the end private void PlaybackTimerCallback(EventTimer timer, object userData) { var position = (DateTime)playbackPositionProperty.GetValue(Application); var speed = (TimeSpan)playbackSpeedProperty.GetValue(Application); var duration = (TimeSpan)playbackDurationProperty.GetValue(Application); var start = (DateTime)playbackStartProperty.GetValue(Application); var end = start + duration; double speedRatio = ((double)playbackTimerInterval / (double)1000.0); var increment = TimeSpan.FromMilliseconds(speedRatio * speed.TotalMilliseconds); //Uncomment the line below to show debugging info //Log.Info($"Speed: {speed} Ratio: {speedRatio} Inc: {increment} Pos: {position} NewPos: {position + increment} End: {end}"); if((position + increment) <= end) { playbackPositionProperty.SetValue(Application, position + increment); } else if(loopPlayback == true) { //Log.Info("Looping playback"); playbackPositionProperty.SetValue(Application, start); } else { //Playback has reached the end StopPlayback(); } } public void GetInfoButton_OnClick(object sender, EventArgs eventArgs) { GetPlaybackInfo(); } //Print the playback parameters to the log public void GetPlaybackInfo() { Log.Info($"Mode = {playbackModeProperty.GetValue(Application)}, Start = {playbackStartProperty.GetValue(Application)}, Position = {playbackPositionProperty.GetValue(Application)}, Duration = {playbackDurationProperty.GetValue(Application)}, Speed = {playbackSpeedProperty.GetValue(Application)}"); } public void SetTimerMsButton_OnClick(object sender, EventArgs eventArgs) { int interval; var timerMsTextBox = Screen.ScreenControls["TimerMsTextBox"] as ControlTextBox; if(int.TryParse(timerMsTextBox.Text, out interval)){ playbackTimerInterval = interval; } else { Log.Info($"Could not parse timer milliseconds {timerMsTextBox.Text}"); } } public void SetStartButton_OnClick(object sender, EventArgs eventArgs) { var playbackStartDateTimePicker = Screen.ScreenControls["PlaybackStartDateTimePicker"] as ControlDateTimePicker; playbackStartProperty.SetValue(Application, playbackStartDateTimePicker.DateTime); } public void SetPositionButton_OnClick(object sender, EventArgs eventArgs) { var playbackPositionDateTimePicker = Screen.ScreenControls["PlaybackPositionDateTimePicker"] as ControlDateTimePicker; playbackPositionProperty.SetValue(Application, playbackPositionDateTimePicker.DateTime); } public void SetDurationButton_OnClick(object sender, EventArgs eventArgs) { var durationTextBox = Screen.ScreenControls["DurationTextBox"] as ControlTextBox; TimeSpan duration; if(TimeSpan.TryParse(durationTextBox.Text, out duration)){ playbackDurationProperty.SetValue(Application, duration); } else { Log.Info($"Could not parse duration {durationTextBox.Text}"); } } public void SetSpeedButton_OnClick(object sender, EventArgs eventArgs) { var speedTextBox = Screen.ScreenControls["SpeedTextBox"] as ControlTextBox; TimeSpan speed; if(TimeSpan.TryParse(speedTextBox.Text, out speed)){ playbackSpeedProperty.SetValue(Application, speed); } else { Log.Info($"Could not parse speed {speedTextBox.Text}"); } } public void EnablePlaybackButton_OnClick(object sender, EventArgs eventArgs) { playbackModeProperty.SetValue(Application, 0); } public void DisablePlaybackButton_OnClick(object sender, EventArgs eventArgs) { playbackModeProperty.SetValue(Application, 1); } public void StartPlaybackButton_OnClick(object sender, EventArgs eventArgs) { StartPlayback(); } public void StartPlayback() { if (playbackTimer == null) { // initialize timer playbackTimer = new EventTimer( callback: PlaybackTimerCallback, dueTime: playbackTimerInitialTime, period: playbackTimerInterval); } else { // reset timer playbackTimer.Change( dueTime: playbackTimerInitialTime, period: playbackTimerInterval); } } public void StopPlaybackButton_OnClick(object sender, EventArgs eventArgs) { StopPlayback(); } public void StopPlayback() { if (playbackTimer != null) { // pause timer playbackTimer.Change( dueTime: EventTimer.Infinite, period: EventTimer.Infinite); } } public void LoopPlaybackListBox_OnSelectionChange(object sender, string[] selectedItems) { var selectedItem = selectedItems.FirstOrDefault(); loopPlayback = selectedItem == "Loop"; } } }