File ConsoleControl.xaml.cs¶
File List > PGRControls > ConsoleControl.xaml.cs
Go to the documentation of this file
//=============================================================================
// Copyright (c) 2026 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the license agreement you entered into
// with FLIR Integrated Imaging Solutions, Inc. (FLIR)
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Collections.ObjectModel;
using SpinnakerNET;
using SpinnakerNET.GenApi;
using SpinnakerNET.GUI.WPFControls;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using System.Text.RegularExpressions;
namespace SpinnakerNET.GUI
{
namespace WPFControls
{
public sealed partial class ConsoleControl : BaseClass
{
#region Fields
public ObservableCollection<Color>myColors;
private readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(ConsoleControl));
private EventLogger _eventLogger;
private bool _enableLogging = false;
string consoleInput = string.Empty;
bool echoInput = false;
bool _autoScroll = true;
string _txNodeName = "";
string _rxNodeName = "";
IManagedCamera _camera;
IValue _txNode;
IInteger _integerNode;
IFloat _floatNode;
IString _stringNode;
Dictionary<string, DeviceEventHandler>_specificEventHandlers;
List<DeviceEventHandler>_generalHandlers;
ObservableCollection<string>consoleOutput =
new ObservableCollection<string>(){"Welcome to SpinConsole Control"};
bool _eventCleanedUp = false;
#endregion
#region Properties
public string ConsoleInput
{
get
{
return consoleInput;
}
set
{
consoleInput = value;
NotifyPropertyChanged("ConsoleInput");
}
}
public ObservableCollection<string>ConsoleOutput
{
get
{
return consoleOutput;
}
set
{
consoleOutput = value;
NotifyPropertyChanged("ConsoleOutput");
}
}
public bool LoggingEnabled
{
get
{
return _enableLogging;
}
set
{
_enableLogging = value;
NotifyPropertyChanged("LoggingEnabled");
NotifyPropertyChanged("LoggingNotEnabled");
}
}
public bool LoggingNotEnabled
{
get
{
return !_enableLogging;
}
}
public bool AutoScroll
{
get
{
return _autoScroll;
}
set
{
_autoScroll = value;
NotifyPropertyChanged("AutoScroll");
}
}
public bool EchoInput
{
get
{
return echoInput;
}
set
{
echoInput = value;
NotifyPropertyChanged("EchoInput");
}
}
public string TxNodeName
{
get
{
return _txNodeName;
}
set
{
_txNodeName = value;
NotifyPropertyChanged("TxNodeName");
}
}
public string RxNodeName
{
get
{
return _rxNodeName;
}
set
{
_rxNodeName = value;
NotifyPropertyChanged("RxNodeName");
}
}
#endregion
public ConsoleControl()
{
InitializeComponent();
// Populate color combobox
myColors = new ObservableCollection<Color>();
Type colors = typeof (System.Drawing.Color);
PropertyInfo[] colorInfo = colors.GetProperties(BindingFlags.Public | BindingFlags.Static);
foreach(PropertyInfo info in colorInfo)
{
mycbo.Items.Add(info.Name);
}
// Set datacontext
DataContext = this;
Loaded += ConsoleControl_Loaded;
_specificEventHandlers = new Dictionary<string, DeviceEventHandler>();
_generalHandlers = new List<DeviceEventHandler>();
}
#region Public Methods
public void Connect(IManagedCamera cam)
{
_camera = cam;
_nodeMap = cam.GetNodeMap();
if (string.IsNullOrWhiteSpace(_serialNumber))
{
_serialNumber = RetrieveSerialNumber(_nodeMap);
}
// Use Dispatcher to catch the closing event
Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
}
public override void Disconnect()
{
UnregisterEvents();
if (_eventLogger != null)
{
_eventLogger.ShutDownLogger();
}
_camera = null;
_nodeMap = null;
}
private bool EnableEvent(string eventName)
{
// Retrieve EventNotification Node
IEnum enumEventNotification = _nodeMap.GetNode<IEnum>("EventNotification");
// Retrieve EventSelector Node
IEnum enumEventSelector = _nodeMap.GetNode<IEnum>("EventSelector");
for (uint i = 0; i < enumEventSelector.Entries.Length; i++)
{
// Get current enum entry node
EnumEntry enumEntry = enumEventSelector.Entries[i];
if (!CheckNodeAccessibility(enumEntry))
{
// Go to next entry node
continue;
}
// Enable Event
// Set Selector Entry
if (!string.IsNullOrEmpty(eventName) && !eventName.Contains(enumEntry.Symbolic))
{
// Toggling a specific event and its not this entry
continue;
}
try
{
if (!enumEventSelector.IsWritable)
{
continue;
}
enumEventSelector.Value = enumEntry.Value;
// Enable ChunkData for corresponding entry
if (enumEventNotification.IsWritable)
{
enumEventNotification.Value = 1;
Console.Out.WriteLine(enumEventSelector.Value.String + " : enabled");
}
else
{
Console.Out.WriteLine(enumEventSelector.Value.String + " : not writable");
}
}
catch (SpinnakerException ex)
{
Console.Out.WriteLine("Spinnaker Error: " + ex.Message);
}
catch (Exception ex)
{
Console.Out.WriteLine("Error: " + ex.Message);
}
}
return true;
}
private static string SanitizeFileNameComponent(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return "camera";
}
string sanitized = value;
foreach (char invalidChar in Path.GetInvalidFileNameChars())
{
sanitized = sanitized.Replace(invalidChar, '_');
}
sanitized = sanitized.Replace("..", "_").Trim('_', ' ');
if (string.IsNullOrWhiteSpace(sanitized))
{
sanitized = "camera";
}
return sanitized;
}
private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
{
Disconnect();
}
public override void Connect(INodeMap nodemap, string nodename, string label = "")
{
throw new NotImplementedException("See Connect(IManagedCamera cam)");
}
public override void Refresh()
{
}
#endregion
#region UI Event Handlers
private void Button_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.SaveFileDialog fileDlg = new System.Windows.Forms.SaveFileDialog();
fileDlg.Filter = "Log file Path (*.txt,*.log)|*.txt;*.log";
fileDlg.Title = "Select log file to save";
fileDlg.DefaultExt = ".txt";
System.Windows.Forms.DialogResult result = fileDlg.ShowDialog();
if (result != System.Windows.Forms.DialogResult.OK)
{
return;
}
else
{
txt_logPath.Text = fileDlg.FileName;
LoggingEnabled = true;
}
}
private void btn_enableLogging_Click(object sender, RoutedEventArgs e)
{
if ((bool) btn_enableLogging.IsChecked)
{
if (txt_logPath.Text.Length == 0)
{
// Using device serial number as path
string safeSerial = SanitizeFileNameComponent(_serialNumber);
string filename = "SN" + safeSerial + "_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".txt";
txt_logPath.Text = filename;
}
if (_eventLogger != null)
{
_eventLogger.ShutDownLogger();
}
try
{
_eventLogger = new EventLogger(txt_logPath.Text);
}
catch (Exception ex)
{
_eventLogger = null;
btn_enableLogging.IsChecked = false;
MessageBox.Show(
ex.Message, "Error creating log file", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
void ConsoleControl_Loaded(object sender, RoutedEventArgs e)
{
InputBlock.KeyDown += InputBlock_KeyDown;
InputBlock.Focus();
}
void InputBlock_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
ConsoleInput = InputBlock.Text;
// Update Tx node
UpdateNodeValue(ConsoleInput);
// Clear input field
ResetInput();
InputBlock.Focus();
e.Handled = true;
}
}
private void Clear_Click(object sender, RoutedEventArgs e)
{
Clear();
}
private void Copy_Click(object sender, RoutedEventArgs e)
{
Copy();
}
private void chk_txNode_Click(object sender, RoutedEventArgs e)
{
if ((bool) chk_txNode.IsChecked)
{
if (string.IsNullOrEmpty(txt_txNode.Text))
{
MessageBox.Show(
"Please make sure a valid TxNode name was entered.",
"Invalid TxNode",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
chk_txNode.IsChecked = false;
e.Handled = true;
return;
}
if (_camera == null)
{
MessageBox.Show(
"Please make sure a valid device was connected.",
"Not Connected",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
chk_txNode.IsChecked = false;
e.Handled = true;
return;
}
try
{
if (!SetTxNode(TxNodeName))
{
chk_txNode.IsChecked = false;
e.Handled = true;
return;
}
}
catch (Exception ex)
{
MessageBox.Show(
ex.Message, "Problem registering event", MessageBoxButton.OK, MessageBoxImage.Error);
chk_txNode.IsChecked = false;
e.Handled = true;
return;
}
}
}
private void chk_rxNode_Click(object sender, RoutedEventArgs e)
{
if ((bool) chk_rxNode.IsChecked)
{
if (_camera == null)
{
MessageBox.Show(
"Please make sure a valid device was connected.",
"Not Connected",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
chk_rxNode.IsChecked = false;
e.Handled = true;
return;
}
try
{
// Try enabling event
if (!EnableEvent(RxNodeName))
{
MessageBox.Show(
string.Format("There was a problem enabling {0} on device.", RxNodeName),
"Error",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
chk_rxNode.IsChecked = false;
e.Handled = true;
return;
}
// Register event
if (string.IsNullOrEmpty(RxNodeName))
{
if (_generalHandlers.Count == 1)
{
MessageBox.Show(
"There was already a general event handler registered.",
"Error",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
chk_rxNode.IsChecked = false;
e.Handled = true;
return;
}
DeviceEventHandler handler = new DeviceEventHandler();
handler.OnMessageReceived += OnMessageReceived;
// General handler
_camera.RegisterEventHandler(handler);
_generalHandlers.Add(handler);
}
else
{
if (_specificEventHandlers.ContainsKey(RxNodeName))
{
// Handler for this event already exist
MessageBox.Show(
string.Format("{0} was already been monitored.", txt_rxNode.Text),
"Error",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
}
else
{
DeviceEventHandler handler = new DeviceEventHandler();
handler.OnMessageReceived += OnMessageReceived;
#pragma warning disable CS0618
_camera.RegisterEventHandler(handler, RxNodeName);
#pragma warning restore CS0618
_specificEventHandlers.Add(RxNodeName, handler);
}
}
}
catch (Exception ex)
{
MessageBox.Show(
ex.Message,
"Problem registering device event",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
chk_rxNode.IsChecked = false;
e.Handled = true;
return;
}
}
else
{
UnregisterEvents();
}
}
#endregion
#region DeviceEvent Related
public void Clear()
{
ConsoleOutput.Clear();
}
public void Copy()
{
try
{
StringBuilder sb = new StringBuilder();
foreach(string message in ConsoleOutput)
{
sb.Append(message);
sb.AppendLine();
}
Clipboard.SetText(sb.ToString());
}
catch (Exception ex)
{
// log.Error("Error copying text to clipboard.", ex);
throw new Exception(string.Format("Error copying text to clipboard. {0}", ex.Message));
}
}
internal void ResetInput()
{
if (EchoInput)
{
// Echo input
ConsoleOutput.Add(">" + ConsoleInput);
if (LoggingEnabled)
{
try
{
_eventLogger.LogMessage(">" + ConsoleInput);
}
catch (Exception ex)
{
log.Warn("There was a problem logging console message to file.", ex);
}
}
}
if (AutoScroll)
{
Scroller.ScrollToBottom();
}
ConsoleInput = String.Empty;
}
internal void AppendMessage(string message)
{
ConsoleOutput.Add(message);
if (AutoScroll)
{
Scroller.ScrollToBottom();
}
}
void OnMessageReceived(string message)
{
if (LoggingEnabled)
{
try
{
var result = Regex.Split(message, "\r\n|\r|\n");
foreach(string msg in result)
{
_eventLogger.LogMessage(msg);
}
}
catch (Exception ex)
{
log.Warn("There was a problem logging console message to file.", ex);
}
}
AppendMessage(message);
}
private void UnregisterEvents()
{
if (_camera == null)
{
return;
}
if (_eventCleanedUp)
{
return;
}
try
{
// Unregister
foreach(DeviceEventHandler handler in _specificEventHandlers.Values)
{
_camera.UnregisterEventHandler(handler);
}
foreach(DeviceEventHandler handler in _generalHandlers)
{
_camera.UnregisterEventHandler(handler);
}
}
catch (Exception)
{
}
_specificEventHandlers.Clear();
_generalHandlers.Clear();
_eventCleanedUp = true;
}
private void UpdateNodeValue(string input)
{
if (_nodeType == typeof (Integer) || _nodeType == typeof (IntReg))
{
try
{
if (_integerNode != null && _integerNode.IsWritable)
{
long convertedInput = 0;
if (long.TryParse(input, out convertedInput))
{
_integerNode.Value = convertedInput;
}
else
{
throw new Exception(string.Format(
"Node {0}: can't convert string {1} to long", _propertyToControl, input));
}
}
else
{
log.Debug(string.Format("{0} node is currently not writable.", _propertyToControl));
}
}
catch (Exception ex)
{
throw new Exception(string.Format("Problem updating node value. {0}", ex.Message));
}
}
else if (_nodeType == typeof (StringNode) || _nodeType == typeof (StringReg))
{
try
{
if (_stringNode != null && _stringNode.IsWritable)
{
// Write new value back to node
_stringNode.Value = input;
}
else
{
log.Debug(string.Format(
"{1}{0} node is currently not writable.", _propertyToControl, FormattedSerialNumber));
}
}
catch (Exception ex)
{
log.Warn(
string.Format("{1}Problem updating node value. {0}", ex.Message, FormattedSerialNumber));
}
}
else if (_nodeType == typeof (Float))
{
try
{
if (_floatNode != null && _floatNode.IsWritable)
{
float convertedInput = 0;
if (float.TryParse(input, out convertedInput))
{
_floatNode.Value = convertedInput;
}
else
{
// Abort updating node's value
// show old value on screen
log.Error(string.Format(
"Node {0}: can't convert string {1} to long", _propertyToControl, input));
}
}
else
{
log.Error(string.Format(
"{1}{0} node is currently not writable.", _propertyToControl, FormattedSerialNumber));
}
}
catch (Exception ex)
{
log.Error(string.Format("Problem updating node value. {0}", ex.Message));
}
}
}
public bool SetTxNode(string nodeName)
{
_txNode = _nodeMap.GetNode<IValue>(nodeName);
if (_txNode == null)
{
MessageBox.Show(
string.Format("Feature \"{0}\" not found on device.", nodeName),
"Error connecting to Tx Node",
MessageBoxButton.OK,
MessageBoxImage.Error);
return false;
}
_propertyToControl = nodeName;
_nodeType = _txNode.GetType();
if (_nodeType == typeof (Float))
{
try
{
if (_floatNode == null)
{
_floatNode = _nodeMap.GetNode<IFloat>(nodeName);
}
}
catch (System.Exception ex)
{
MessageBox.Show(
ex.Message, "Error connecting to Tx Node", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
}
if (_nodeType == typeof (StringNode) || _nodeType == typeof (StringReg))
{
try
{
if (_stringNode == null)
{
_stringNode = _nodeMap.GetNode<IString>(nodeName);
}
}
catch (System.Exception ex)
{
MessageBox.Show(
ex.Message, "Error connecting to Tx Node", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
}
else if (_nodeType == typeof (Integer) || _nodeType == typeof (IntReg))
{
try
{
if (_integerNode == null)
{
_integerNode = _nodeMap.GetNode<IInteger>(nodeName);
}
}
catch (System.Exception ex)
{
MessageBox.Show(
ex.Message, "Error connecting to Tx Node", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
}
else
{
// Unhandled node type detected
Console.Out.WriteLine("Unexpected control type!");
MessageBox.Show(
"Unexpected control type. Please choose another node.",
"Error connecting to node",
MessageBoxButton.OK,
MessageBoxImage.Error);
return false;
}
return true;
}
#endregion
#region HELPERS
private bool CheckNodeAccessibility(INode node)
{
return (node.IsReadable || node.IsWritable);
}
private void InputBlock_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
try
{
if (Scroller != null)
{
// Set scroller size to make vertical scroll bar show up
Scroller.Height = Scroller.ActualHeight;
}
}
catch (Exception)
{
}
}
private void InputBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
try
{
// Setting height to NaN so Scroller will auto resize with parent
Scroller.Height = double.NaN;
}
catch (Exception)
{
}
}
#endregion
}
#pragma warning disable CS0618
internal class DeviceEventHandler : ManagedDeviceEventHandler
#pragma warning restore CS0618
{
public delegate void MessageReceived(string message);
public event MessageReceived OnMessageReceived;
unsafe protected override void OnDeviceEvent(string eventName)
{
try
{
int payloadSize = (int) this.GetEventPayloadDataSize();
UnmanagedMemoryStream stream = new UnmanagedMemoryStream(GetDeviceEventPayloadData(), payloadSize);
BinaryReader reader = new BinaryReader(stream);
string message = new string(reader.ReadChars(payloadSize));
reader.Close();
if (!string.IsNullOrEmpty(message) && OnMessageReceived != null)
{
Application.Current.Dispatcher.BeginInvoke(
(Action)(() => {
// Append callback message to console
OnMessageReceived(message);
}),
System.Windows.Threading.DispatcherPriority.Background,
null);
}
}
catch (Exception ex)
{
Console.Out.WriteLine(ex.Message);
}
}
}
internal class EventLogger
{
private StreamWriter _logger;
private bool _closed = false;
public EventLogger(string path)
{
_logger = new StreamWriter(path, true);
}
~EventLogger()
{
_logger.Close();
}
public void ShutDownLogger()
{
if (_closed)
{
return;
}
_logger.Close();
_closed = true;
}
public void LogMessage(string message)
{
_logger.WriteLine(message);
_logger.Flush();
}
}
}
}