Files
GenericTeProgramLibrary/Source/Program/GUI/View/ManualControlWindow.xaml.cs
2025-10-24 15:18:11 -07:00

729 lines
28 KiB
C#

/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Xml.XPath;
using MeasurementManagerLib;
using NLog;
using ProgramGui.GUI.ViewModel;
using ProgramLib.GUI.Model;
using Raytheon.Common.Coe;
using Raytheon.Instruments;
using Raytheon.Instruments.PowerSupply;
namespace ProgramLib.GUI.View
{
/// <summary>
/// Interaction logic for ManualControlWindow.xaml
/// </summary>
internal partial class ManualControlWindow : Window
{
public ManualWindowViewModel _manualWindowViewModel;
public LiveDataWindow LiveDataWindow { get; set; }
private ILogger _logger;
private Message _currentMsg;
private Dictionary<string, MessageXmlDocument> _xmlDocs = new Dictionary<string, MessageXmlDocument>();
private Dictionary<string, CoeMessageDataModel> _fieldNameToCoeMessageDataDict = new Dictionary<string, CoeMessageDataModel>();
private ManualGuiPowerSupplyReadThread _powerSupplyReadThread;
private CancellationTokenSource _coeSendMessageTaskCancellationSource = new CancellationTokenSource();
public ManualControlWindow()
{
InitializeComponent();
_logger = LogManager.GetCurrentClassLogger();
Uri iconUri = new Uri($"pack://application:,,,/{GetType().Assembly.GetName().Name};component/Resources/Icons/app.ico");
this.Icon = BitmapFrame.Create(iconUri);
WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
_manualWindowViewModel = new ManualWindowViewModel();
DataContext = _manualWindowViewModel;
_manualWindowViewModel._poweredModuleDataItems = new ObservableCollection<PowerModuleDataModel>();
_manualWindowViewModel._powerModuleComboBoxDataItems = new ObservableCollection<PowerModuleDataModel>();
}
~ManualControlWindow()
{
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() ...");
_coeSendMessageTaskCancellationSource.Cancel();
if (_powerSupplyReadThread != null)
{
_powerSupplyReadThread.Quit();
_powerSupplyReadThread.WaitForExit();
}
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
if (_powerSupplyReadThread != null)
{
_powerSupplyReadThread.Quit();
_powerSupplyReadThread.WaitForExit();
_powerSupplyReadThread = null;
}
this.Hide();
if (LiveDataWindow != null)
{
LiveDataWindow.Show();
LiveDataWindow = null;
}
}
private void btnMax_Click(object sender, RoutedEventArgs e)
{
if (this.WindowState == WindowState.Maximized)
{
this.WindowState = WindowState.Normal;
imgMax.Source = new BitmapImage(new System.Uri($"pack://application:,,,/{GetType().Assembly.GetName().Name};component/Resources/Images/Title_Bar_Buttons/maximize.png"));
}
else
{
this.WindowState = WindowState.Maximized;
imgMax.Source = new BitmapImage(new System.Uri($"pack://application:,,,/{GetType().Assembly.GetName().Name};component/Resources/Images/Title_Bar_Buttons/restore.png"));
}
}
private void btnMin_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
private void Window_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
TextBox textBox = Keyboard.FocusedElement as TextBox;
// unfocus text box if click outside of textbox
if (textBox != null)
{
// Kill logical focus
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(textBox), null);
// Kill keyboard focus
Keyboard.ClearFocus();
}
DragMove();
}
private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
TextBox textBox = Keyboard.FocusedElement as TextBox;
// unfocus text box if enter key is pressed
if (textBox != null)
{
if (e.Key == Key.Return)
{
if (e.Key == Key.Enter)
{
// Kill logical focus
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(textBox), null);
// Kill keyboard focus
Keyboard.ClearFocus();
}
}
}
}
private void TextBox_GotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
{
TextBox tb = (TextBox)sender;
tb.Dispatcher.BeginInvoke(new Action(() => tb.SelectAll()));
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)sender;
tb.SelectAll();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
poppulatePowerSupplyTab();
poppulateDiscreteTab();
poppulateCoeTab();
}
catch (Exception ex)
{
_logger.Error(ex.Message + "\r\n" + ex.StackTrace);
}
}
private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (this.Visibility == Visibility.Visible)
{
List<string> moduleList = Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.GetPowerModuleList();
foreach (string module in moduleList)
{
PowerModuleDataModel powerData = GetPowerModuleDataFromDatagridDataItems(module);
PowerModuleDataModel powerData2 = GetPowerModuleDataFromComboBoxDataItems(module);
if (powerData != null && !Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.IsPowerSupplyOn(module))
{
// update datagrid
_manualWindowViewModel._poweredModuleDataItems.Remove(powerData);
if (powerData2 != null)
powerData2.PowerLed = _manualWindowViewModel._imageToResourcePathDict[ManualWindowViewModel.Images.LED_OFF];
}
else if (Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.IsPowerSupplyOn(module))
{
// update datagrid
_manualWindowViewModel._poweredModuleDataItems.Add(powerData);
if (powerData2 != null)
powerData2.PowerLed = _manualWindowViewModel._imageToResourcePathDict[ManualWindowViewModel.Images.LED_ON];
}
}
if (powerModuleCb.SelectedItem != null)
{
string powerModule = ((PowerModuleDataModel)powerModuleCb.SelectedItem).Name;
if (Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.IsPowerSupplyOn(powerModule))
{
powerOnBtn.Content = "Power Off";
}
else
powerOnBtn.Content = "Power On";
}
}
}
/// <summary>
/// Populate power supply tab
/// </summary>
private void poppulatePowerSupplyTab()
{
string sectionName = "MANUAL_CONTROL_GUI.POWER_MODULES";
List<string> keys = Program.Instance().ProgramSpecificConfig.ReadAllKeys(sectionName);
try
{
List<string> moduleList = Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.GetPowerModuleList();
foreach (string module in moduleList)
{
PowerModuleDataModel data = new PowerModuleDataModel();
data.PowerLed = _manualWindowViewModel._imageToResourcePathDict[ManualWindowViewModel.Images.LED_OFF];
if (Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.IsPowerSupplyOn(module))
{
data.PowerLed = _manualWindowViewModel._imageToResourcePathDict[ManualWindowViewModel.Images.LED_ON];
}
data.Name = module;
data.ExpectedVoltage = Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.GetVoltageSetpoint(module).ToString("0.00");
_manualWindowViewModel._powerModuleComboBoxDataItems.Add(data);
}
}
catch (MalMeasurementManagerNullReferenceException ex)
{
_logger.Warn(ex.Message + "\r\n" + ex.StackTrace);
}
}
private void powerOnBtn_Click(object sender, RoutedEventArgs e)
{
bool success = true;
if (Program.Instance().IsUutPwrOn)
{
MessageBox.Show("Power to UUT is currently on. Please turn off power to UUT before manually controlling the power modules.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
try
{
((Button)sender).IsEnabled = false;
_manualWindowViewModel.GetPoweredModuleDataItemsSem().WaitOne();
string moduleName = ((PowerModuleDataModel)powerModuleCb.SelectedValue).Name;
PowerData data = Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.ReadPowerData(moduleName);
if (data.Voltage > 0.0)
{
Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.OutputDisable(moduleName);
}
string text = ((Button)sender).Content.ToString();
if (Regex.IsMatch(text, "power on", RegexOptions.IgnoreCase))
{
double voltageSetpoint = 0.0;
double ovp = 0.0;
double ocp = 0.0;
if (!Double.TryParse(voltageSetpointTb.Text, out voltageSetpoint))
{
MessageBox.Show("Voltage setpoint is invalid.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
success = false;
}
if (success)
{
if (!Double.TryParse(ovpTb.Text, out ovp))
{
MessageBox.Show("OVP is invalid.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
success = false;
}
}
if (success)
{
if (!Double.TryParse(ocpTb.Text, out ocp))
{
MessageBox.Show("OCP is invalid.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
success = false;
}
}
if (success)
{
Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.SetOverVoltageProtection(moduleName, ovp);
Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.SetVoltageSetpoint(moduleName, voltageSetpoint);
Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.SetOverCurrentProtection(moduleName, ocp);
Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.OutputEnable(moduleName);
((Button)sender).Content = "Power Off";
if (_powerSupplyReadThread == null)
{
_powerSupplyReadThread = new ManualGuiPowerSupplyReadThread();
_powerSupplyReadThread.Start();
}
}
}
else
{
Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.OutputDisable(moduleName);
((Button)sender).Content = "Power On";
}
}
catch (Exception ex)
{
_logger.Error(ex.Message + "\r\n" + ex.StackTrace);
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
_manualWindowViewModel.GetPoweredModuleDataItemsSem().Release();
((Button)sender).IsEnabled = true;
}
}
}
private void powerModuleCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string moduleName = ((PowerModuleDataModel)((ComboBox)sender).SelectedValue).Name;
double voltageSetpoint = 0.0;
double ovp = 0.0;
double ocp = 0.0;
voltageSetpoint = Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.GetVoltageSetpoint(moduleName);
ovp = Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.GetOverVoltageProtection(moduleName);
ocp = Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.GetOverCurrentProtection(moduleName);
voltageSetpointTb.Text = voltageSetpoint.ToString("0.00");
ovpTb.Text = ovp.ToString("0.00");
ocpTb.Text = ocp.ToString("0.00");
if (Program.Instance().MalMeasurementLibManager.PowerSupplyMeasurementManager.IsPowerSupplyOn(moduleName))
{
powerOnBtn.Content = "Power Off";
}
else
powerOnBtn.Content = "Power On";
}
private void voltageSetpointTb_LostFocus(object sender, RoutedEventArgs e)
{
double voltageSetpoint = 0.0;
if (Double.TryParse(((TextBox)sender).Text, out voltageSetpoint) && powerModuleCb.SelectedItem != null)
{
string moduleName = ((PowerModuleDataModel)powerModuleCb.SelectedValue).Name;
PowerModuleDataModel data = GetPowerModuleDataFromComboBoxDataItems(moduleName);
string currentVoltageSetpoint = data.ExpectedVoltage;
if (voltageSetpoint.ToString("0.00") != currentVoltageSetpoint)
{
data.ExpectedVoltage = voltageSetpoint.ToString("0.00");
double ovp = voltageSetpoint + 0.5;
ovpTb.Text = ovp.ToString("0.00");
}
}
}
/// <summary>
/// Get power module data from ComboBox
/// </summary>
public PowerModuleDataModel GetPowerModuleDataFromComboBoxDataItems(string powerModuleName)
{
PowerModuleDataModel data = null;
foreach (PowerModuleDataModel item in _manualWindowViewModel._powerModuleComboBoxDataItems)
{
if (item.Name == powerModuleName)
data = item;
}
return data;
}
/// <summary>
/// Get power module data from datagrid
/// </summary>
public PowerModuleDataModel GetPowerModuleDataFromDatagridDataItems(string powerModuleName)
{
PowerModuleDataModel data = null;
foreach (PowerModuleDataModel item in _manualWindowViewModel._poweredModuleDataItems)
{
if (item.Name == powerModuleName)
data = item;
}
return data;
}
/// <summary>
/// Populate Discrete tab
/// </summary>
private void poppulateDiscreteTab()
{
try
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in Program.Instance().MalMeasurementLibManager.DioMeasurementManager.SignalNameToChannelInfoMap)
{
if (item.Value.ioType == IODatatypes.IOType.DigitalInput)
{
inputDiscretesCb.Items.Add(item.Key);
}
else
outputDiscretesCb.Items.Add(item.Key);
}
}
catch (MalMeasurementManagerNullReferenceException ex)
{
_logger.Warn(ex.Message + "\r\n" + ex.StackTrace);
}
}
private void inputDiscreteReadBtn_Click(object sender, RoutedEventArgs e)
{
try
{
if (inputDiscretesCb.SelectedItem != null)
{
if (Program.Instance().MalMeasurementLibManager != null && Program.Instance().MalMeasurementLibManager.DioMeasurementManager != null)
{
IODatatypes.BitState state = Program.Instance().MalMeasurementLibManager.DioMeasurementManager.GetInputSignalState(inputDiscretesCb.SelectedValue.ToString());
inputDiscreteStatusTb.Text = state.ToString();
}
}
else
{
MessageBox.Show("Please select an input signal.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
_logger.Error(ex.Message + "\r\n" + ex.StackTrace);
}
}
private void outputDiscreteWriteBtn_Click(object sender, RoutedEventArgs e)
{
bool success = true;
try
{
if (outputDiscretesCb.SelectedItem == null)
{
MessageBox.Show("Please select an output signal.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
success = false;
}
if (success)
{
if (outputDiscreteStateCb.SelectedItem == null)
{
MessageBox.Show("Please select an output signal state.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
success = false;
}
}
if (success)
{
if (Program.Instance().MalMeasurementLibManager != null && Program.Instance().MalMeasurementLibManager.DioMeasurementManager != null)
{
IODatatypes.BitState state;
if (Enum.TryParse(outputDiscreteStateCb.SelectedValue.ToString(), out state))
{
Program.Instance().MalMeasurementLibManager.DioMeasurementManager.SetOutputSignalState(outputDiscretesCb.SelectedValue.ToString(), state);
}
}
}
}
catch (Exception ex)
{
_logger.Error(ex.Message + "\r\n" + ex.StackTrace);
}
}
/// <summary>
/// Populate COE tab
/// </summary>
private void poppulateCoeTab()
{
try
{
ICollection<object> coeDeviceList = Program.Instance().InstrumentManager.GetInstruments(typeof(CoeComm));
foreach (CoeComm coeDevice in coeDeviceList)
{
coeDeviceCb.Items.Add(Path.GetFileName(coeDevice.Name));
}
}
catch (MalMeasurementManagerNullReferenceException ex)
{
_logger.Warn(ex.Message + "\r\n" + ex.StackTrace);
}
}
private void coeDeviceCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
xmlFileCb.Items.Clear();
var xmlDocObject = Program.Instance().MalMeasurementLibManager.CoeMeasurementManager.GetXmlDocs(coeDeviceCb.SelectedValue.ToString());
if (xmlDocObject != null && xmlDocObject.GetType() == _xmlDocs.GetType())
{
_xmlDocs = (Dictionary<string, MessageXmlDocument>)xmlDocObject;
foreach (KeyValuePair<string, MessageXmlDocument> item in _xmlDocs)
{
xmlFileCb.Items.Add(Path.GetFileName(item.Key));
}
}
}
private void xmlFileCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
coeMessagesCb.Items.Clear();
_manualWindowViewModel._coeMessageDataItems.Clear();
string coeXmlFolderPath = Path.GetDirectoryName(_xmlDocs.First().Key.ToString());
string coeXmlFilePath = Path.Combine(coeXmlFolderPath, ((ComboBox)sender).SelectedValue.ToString());
XPathNavigator Node = _xmlDocs[coeXmlFilePath].CreateNavigator();
XPathNodeIterator Nodeset = Node.Select("interface/message/name");
while (Nodeset.MoveNext())
{
coeMessagesCb.Items.Add(Nodeset.Current.Value);
}
}
private void coeMessagesCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (((ComboBox)sender).SelectedItem != null)
{
string coeXmlFolderPath = Path.GetDirectoryName(_xmlDocs.First().Key.ToString());
string coeXmlFilePath = Path.Combine(coeXmlFolderPath, xmlFileCb.SelectedValue.ToString());
_currentMsg = new Message(((ComboBox)sender).SelectedValue.ToString(), _xmlDocs[coeXmlFilePath]);
_currentMsg.Default();
List<MessageData> visibleData = new List<MessageData>();
visibleData.AddRange(_currentMsg.MessageDataArray);
_manualWindowViewModel._coeMessageDataItems.Clear();
_fieldNameToCoeMessageDataDict.Clear();
CoeMessageDataModel coeMessage;
foreach (MessageData messageData in visibleData)
{
coeMessage = new CoeMessageDataModel(messageData.FieldName, messageData.FieldValue, messageData.FieldType);
if (!String.IsNullOrEmpty(messageData.FormattedValue) && Regex.IsMatch(messageData.FormattedValue, @"^0x.+", RegexOptions.IgnoreCase))
{
coeMessage.Value = messageData.FormattedValue;
}
_fieldNameToCoeMessageDataDict[messageData.FieldName] = coeMessage;
if (messageData.FieldName[0] == '$')
{
coeMessage.IsFocusable = Boolean.FalseString;
}
// add data item to TreeView control
_manualWindowViewModel._coeMessageDataItems.Add(coeMessage);
ProcessChildMessage(messageData.MessageArray, coeMessage);
}
}
}
/// <summary>
/// Process child message
/// </summary>
private void ProcessChildMessage(MessageData[] messageArray, CoeMessageDataModel coeMessageParent)
{
if (messageArray != null && messageArray.Count() > 0)
{
coeMessageParent.SubItems = new ObservableCollection<CoeMessageDataModel>();
foreach (var message in messageArray)
{
string simpliedFiledName = message.FieldName;
Match regexMatch = Regex.Match(message.FieldName, @"([^\\.]+)$", RegexOptions.IgnoreCase);
if (regexMatch.Success)
{
simpliedFiledName = regexMatch.Groups[1].Value;
}
CoeMessageDataModel coeMessage = new CoeMessageDataModel(simpliedFiledName, message.FieldValue, message.FieldType);
_fieldNameToCoeMessageDataDict[message.FieldName] = coeMessage;
if (String.IsNullOrEmpty(message.FieldValue))
{
coeMessage.IsFocusable = Boolean.FalseString;
}
coeMessageParent.SubItems.Add(coeMessage);
ProcessChildMessage(message.MessageArray, coeMessage);
}
}
}
private void coeSendBtn_Click(object sender, RoutedEventArgs e)
{
if (_currentMsg != null)
{
string text = ((Button)sender).Content.ToString();
if (Regex.IsMatch(text, "send", RegexOptions.IgnoreCase))
{
var parms = GetParameters(_currentMsg.MessageDataArray);
int rateHz = -1;
if (int.TryParse(coeSendRate.Text, out rateHz))
{
int minRateHz = 1;
int maxRateHz = 60;
if (rateHz < minRateHz || rateHz > maxRateHz)
{
MessageBox.Show($"Rate {rateHz} Hz is out of range. Must be between {minRateHz} and {maxRateHz} Hz");
}
else
{
_coeSendMessageTaskCancellationSource = new CancellationTokenSource();
string instr = coeDeviceCb.SelectedValue.ToString();
Task.Factory.StartNew(() => SendCoeMessageTask(instr, _currentMsg.Name, parms, rateHz));
((Button)sender).Content = "Stop";
}
}
else
{
try
{
Program.Instance().MalMeasurementLibManager.CoeMeasurementManager.SendMessage(coeDeviceCb.SelectedValue.ToString(), _currentMsg.Name, parms);
}
catch (Exception ex)
{
_logger.Error(ex.Message + "\r\n" + ex.StackTrace);
}
}
}
else
{
_coeSendMessageTaskCancellationSource.Cancel();
((Button)sender).Content = "Send";
}
}
}
/// <summary>
/// Send COE message periodically
/// </summary>
private async void SendCoeMessageTask(string instr, string msgName, List<KeyValuePair<string, string>> parms, int rateHz)
{
_logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() is running...");
int sleepIntervalMs = 1000 / rateHz;
try
{
while (!_coeSendMessageTaskCancellationSource.Token.IsCancellationRequested)
{
Program.Instance().MalMeasurementLibManager.CoeMeasurementManager.SendMessage(instr, msgName, parms);
await Task.Delay(sleepIntervalMs);
}
}
catch (Exception ex)
{
_logger.Error(ex.Message + "\r\n" + ex.StackTrace);
}
_logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() is exiting...");
}
/// <summary>
/// Get parameters in the message
/// </summary>
private List<KeyValuePair<string, string>> GetParameters(MessageData[] array)
{
if (array == null || array.Length == 0)
return null;
List<KeyValuePair<string, string>> parms = new List<KeyValuePair<string, string>>();
foreach (var item in array.Where(m => !m.FieldName.StartsWith("$")))
{
if (_fieldNameToCoeMessageDataDict.ContainsKey(item.FieldName))
{
parms.Add(new KeyValuePair<string, string>(item.FieldName, _fieldNameToCoeMessageDataDict[item.FieldName].Value));
}
if (item.MessageArray != null && item.MessageArray.Any())
{
var innerParams = GetParameters(item.MessageArray);
if (innerParams != null)
{
parms.AddRange(innerParams);
}
}
}
return parms;
}
}
}