1176 lines
49 KiB
C#
1176 lines
49 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Media;
|
|
using System.Windows.Threading;
|
|
using System.Xml.Linq;
|
|
using LaaPackages.Features.Cordonel.Models;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using Xylem.Common.CommonCore.Configuration;
|
|
using Xylem.Common.CommonCore.Consts;
|
|
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
|
|
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses;
|
|
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
|
|
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EventArgs;
|
|
using Xylem.Common.Utils.Logging;
|
|
using Xylem.Common.Utils.UserAccessCtrl;
|
|
using Control = System.Windows.Forms.Control;
|
|
using TextBox = System.Windows.Controls.TextBox;
|
|
using UserControl = System.Windows.Controls.UserControl;
|
|
|
|
namespace Xylem.Common.Production.ProductionUiCordonel
|
|
{
|
|
/// <summary>
|
|
/// Interaction logic for FinalTest.xaml
|
|
/// </summary>
|
|
public sealed partial class ProductionWindow
|
|
{
|
|
#region variables and properties
|
|
private readonly ILogger _logger;
|
|
// remind manually changed culture setting
|
|
private static readonly AssemblyName _assemblyName = Assembly.GetExecutingAssembly().GetName();
|
|
private static readonly String _assemblyExecRootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
private static readonly Version _version = _assemblyName.Version;
|
|
private readonly String _strAppNameVersion;
|
|
private RegisterLDAPUser _registerForm;
|
|
private Boolean _lockGenesisInfo;
|
|
private Int32 OrderAmount { get; set; }
|
|
private Int32 OrderCounter { get; set; }
|
|
private Int32 Slot { get; set; }
|
|
|
|
// maximum processing steps for calculation of progress bar
|
|
private Int32 _maxOverallProcessSteps;
|
|
private Int32 _maxSingleProcessSteps;
|
|
private ProcessController _processCtrl;
|
|
private DateTimeOffset _startTime;
|
|
private DispatcherTimer _timer;
|
|
private String _lastLoggingTextToAvoidRepetition;
|
|
private CordonelRequirements _productionRequirements;
|
|
private UserAccessWindow _userAccessWindow;
|
|
private readonly IProcessStateDef _processStateDef;
|
|
private readonly Boolean _autoStartFirstProductionProcess;
|
|
|
|
#endregion
|
|
/// <summary>
|
|
/// Ctor
|
|
/// </summary>
|
|
/// <param name="softwareName"></param>
|
|
/// <param name="projectName">take the identical window for different software, this is name displayed
|
|
/// in the header</param>
|
|
/// <param name="processStateDef">table for state definitions for the specific program which feeds the
|
|
/// state machine</param>
|
|
/// <param name="autoStartFirstProductionProcess">starts the state machine with the first production process
|
|
/// defined in the processStateDef with productionProcessNo == 0</param>
|
|
/// <remarks date="????" author="Roland Drabesch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2024-Jul-15" author="Thomas Wiedebusch">
|
|
/// - Additional info of Cordonel.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Jul-01" author="Thomas Wiedebusch">
|
|
/// - Auto start.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Sep-15" author="Thomas Wiedebusch">
|
|
/// - Order counter.
|
|
/// </remarks>
|
|
public ProductionWindow(String softwareName, String projectName, IProcessStateDef processStateDef,
|
|
Boolean autoStartFirstProductionProcess)
|
|
{
|
|
_logger = NLogHelper.CreateOrGetLogger(projectName);
|
|
_processStateDef = processStateDef;
|
|
_autoStartFirstProductionProcess = autoStartFirstProductionProcess;
|
|
String msg;
|
|
try
|
|
{
|
|
// returns true in DEBUG configuration
|
|
if (!Logic.SoftwareAccessHelper.Access.HasAccess(_assemblyName))
|
|
{
|
|
msg = $"{Properties.Resources.StrStartMessageSwLicenseExpired} {_version}";
|
|
_logger.Error(msg);
|
|
MessageBox.Show(msg, Properties.Resources.StrProcessStateError,
|
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
|
Close();
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
msg = Properties.Resources.StrErrorMsgMissingNetworkConnetction + " " + e.Message;
|
|
_logger.Error(msg);
|
|
MessageBox.Show(msg,
|
|
Properties.Resources.StrProcessStateError,
|
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
|
Close();
|
|
return;
|
|
}
|
|
|
|
InitializeComponent();
|
|
// Log version to files for debug purposes
|
|
_strAppNameVersion = $"{softwareName} {_version}";
|
|
_logger.Info(_strAppNameVersion);
|
|
|
|
Title = _strAppNameVersion;
|
|
|
|
//static labels
|
|
UpdateContentControl(lblSerialNumberTxt, Properties.Resources.StrLblSerialNumberTxt + ":");
|
|
UpdateContentControl(lblRadioAddressText, Properties.Resources.StrLblRadioAddressTxt + ":");
|
|
UpdateContentControl(lblOrderNumberText, Properties.Resources.StrLblOrderNumberTxt + ":");
|
|
UpdateContentControl(lblOrderCounterText, Properties.Resources.StrLblOrderCounterTxt + ":");
|
|
UpdateContentControl(lblMeterSizeText, Properties.Resources.StrLblMeterSizeTxt + ":");
|
|
UpdateContentControl(lblMeterLengthText, Properties.Resources.StrLblMeterLengthTxt + ":");
|
|
UpdateContentControl(lblSingleProcessText, Properties.Resources.StrLblSingleProcessText + ":");
|
|
UpdateContentControl(lblTotalProcessText, Properties.Resources.StrLblTotalProcessText + ":");
|
|
optionsMenu.Header = Properties.Resources.StrMenuOptionsText;
|
|
optionsMenuChangePassword.Header = Properties.Resources.StrMenuChangePasswordText;
|
|
hlpMenu.Header = Properties.Resources.StrMenuHelpText;
|
|
UpdateUi(lblApprovalText, "");
|
|
UpdateUi(lblTimeText, Properties.Resources.StrLblTimeText + ":");
|
|
|
|
// buttons
|
|
UpdateContentControl(btnStart, Properties.Resources.StrBtnStart);
|
|
UpdateContentControl(btnStop, Properties.Resources.StrBtnStop);
|
|
|
|
InitializeFormState();
|
|
}
|
|
|
|
//private ApplicationSettings Settings
|
|
//{
|
|
// get; set;
|
|
//}
|
|
|
|
/// <summary>
|
|
/// Initialize the FinalTest GUI:
|
|
/// - Read the configuration file for slot and port assignments and settings,
|
|
/// - Dispatch slots to slot combobox,
|
|
/// - Read setting from "ProductionUiConfig.json" file for GUI and slot setup,
|
|
/// - Create final process controller and install events,
|
|
/// - Create a dispatch timer to display the elapsed time of the process.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void Window_Initialized(Object sender, EventArgs e)
|
|
{
|
|
var configFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
|
nameof(Hardware.WaterMeter.Genesis), ProgramConfig.SerialConfigFileName);
|
|
|
|
if (!File.Exists(configFile))
|
|
{
|
|
var msg = Properties.Resources.StrErrorMsgMissingConfigurationFile;
|
|
MessageBox.Show(msg,
|
|
Properties.Resources.StrProcessStateError,
|
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
|
_logger.Error(msg);
|
|
throw new ApplicationException(msg);
|
|
}
|
|
var tr = new StreamReader(configFile);
|
|
var meterConfigList = JsonConvert.DeserializeObject<SlotConfig[]>(tr.ReadToEnd());
|
|
|
|
cbxSlotBox.Items.Clear();
|
|
if (meterConfigList != null)
|
|
{
|
|
foreach (var item in meterConfigList.OrderBy(s => s.Slot))
|
|
{
|
|
cbxSlotBox.Items.Add(item.Slot);
|
|
}
|
|
}
|
|
|
|
cbxSlotBox.SelectedIndex = 0;
|
|
UseSetting(true);
|
|
|
|
if (cbxSlotBox.SelectedItem == null || string.IsNullOrEmpty(cbxSlotBox.SelectedItem.ToString()) ||
|
|
!int.TryParse(cbxSlotBox.SelectedItem.ToString(), out var slot))
|
|
{
|
|
Slot = 1;
|
|
}
|
|
else
|
|
{
|
|
Slot = slot;
|
|
}
|
|
|
|
try
|
|
{
|
|
_processCtrl = new ProcessController(Slot, _processStateDef);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error(ex.Message);
|
|
MessageBox.Show(ex.Message,
|
|
Properties.Resources.StrProcessStateError,
|
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
|
throw new ApplicationException(ex.Message);
|
|
}
|
|
|
|
//install the process changed event handler for single processes
|
|
_processCtrl.OnProcessStateChanged += ProcessStateChanged_Handler;
|
|
_processCtrl.OnProcessLogRequest += ProcessLog_Handler;
|
|
_processCtrl.OnProcessProgressChanged += ProcessProgress_Handler;
|
|
_processCtrl.OnStateMachineStateChanged += StateMachineStateChanged_Handler;
|
|
_processCtrl.OnGuiMessageDispatcher += GuiMessageDispatcher_Handler;
|
|
|
|
_timer = new DispatcherTimer();
|
|
_timer.Tick += TmrProgressUpdate_Tick;
|
|
_timer.Interval = TimeSpan.FromMilliseconds(500);
|
|
|
|
UpdateStatusGrid();
|
|
}
|
|
|
|
private void Window_Closing(Object sender, CancelEventArgs e)
|
|
{
|
|
_userAccessWindow?.Close();
|
|
_processCtrl.OnProcessStateChanged -= ProcessStateChanged_Handler;
|
|
_processCtrl.OnProcessLogRequest -= ProcessLog_Handler;
|
|
_processCtrl.OnProcessProgressChanged -= ProcessProgress_Handler;
|
|
_processCtrl.OnStateMachineStateChanged -= StateMachineStateChanged_Handler;
|
|
_processCtrl.OnGuiMessageDispatcher -= GuiMessageDispatcher_Handler;
|
|
_userAccessWindow = null;
|
|
|
|
_processCtrl.Dispose();
|
|
_processCtrl = null;
|
|
_timer.Stop();
|
|
_timer.Tick -= TmrProgressUpdate_Tick;
|
|
_timer = null;
|
|
_registerForm = null;
|
|
}
|
|
private void UseSetting(Boolean setSlot = false)
|
|
{
|
|
//tblkAutodetectState.Text = "Off";
|
|
//if (Settings.AutoDetect)
|
|
//{
|
|
// tblkAutodetectState.Text = "On";
|
|
//}
|
|
if (setSlot)
|
|
{
|
|
//cbxSlotBox.SelectedValue = Settings.Slot;
|
|
cbxSlotBox.SelectedValue = 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enable/disable the controls
|
|
/// </summary>
|
|
/// <remarks date="????" author="Roland Drabesch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2024-Jul-15" author="Thomas Wiedebusch">
|
|
/// - Additional info of Cordonel.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Jul-01" author="Thomas Wiedebusch">
|
|
/// - Auto start.
|
|
/// </remarks>
|
|
private void InitializeFormState()
|
|
{
|
|
if (Software.IsRegistrationPending)
|
|
{
|
|
_registerForm = new RegisterLDAPUser();
|
|
_registerForm.OnCancellation += OnUserAccessControlCancellation;
|
|
UiElmEnable(optionsMenu, false, false);
|
|
}
|
|
else
|
|
{
|
|
UiElmEnable(optionsMenu, true);
|
|
UiElmEnable(optionsMenuChangePassword, Software.IsAutenticated);
|
|
UiElmEnable(optionsMenuLogout, Software.IsAutenticated);
|
|
UiElmEnable(optionsMenuLogin, !Software.IsAutenticated);
|
|
// Hide the [Start] button if autostart enabled
|
|
UiElmEnable(btnStart, Software.IsAutenticated, !_autoStartFirstProductionProcess);
|
|
UiElmEnable(btnStop, false);
|
|
UpdateContentControl(lblOperator, Software.IsAutenticated
|
|
? $"{Properties.Resources.StrLblOperatorNameText}: {Software.UserName}"
|
|
: $"{Properties.Resources.StrLblOperatorNameText}: ?");
|
|
// Start first production process if required, user is authenticated and state machine is idle
|
|
if (_autoStartFirstProductionProcess &&
|
|
Software.IsAutenticated &&
|
|
ProcessState.Idle == _processCtrl?.GetProcessState())
|
|
{
|
|
BtnStart_Click(this, null);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows the user access window with login form or password change form.
|
|
/// </summary>
|
|
/// <param name="visible"></param>
|
|
/// <param name="control">Windows forms control</param>
|
|
/// <param name="headerTxt"></param>
|
|
/// <remarks date="2025-Mar-25" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void ShowUserAccessWindow(Boolean visible = true, Control control = null, String headerTxt = "")
|
|
{
|
|
if (visible && control != null)
|
|
{
|
|
UiElmEnable(optionsMenu, false);
|
|
|
|
if (_userAccessWindow == null)
|
|
_userAccessWindow = new UserAccessWindow(control, headerTxt);
|
|
// View the user access window as container for the windows forms password change and login
|
|
_userAccessWindow.OnCloseWindow += OnUserAccessWindowClosed_Handler;
|
|
_userAccessWindow.ShowDialog();
|
|
}
|
|
else
|
|
{
|
|
if (_userAccessWindow != null)
|
|
{
|
|
_userAccessWindow.OnCloseWindow -= OnUserAccessWindowClosed_Handler;
|
|
try
|
|
{
|
|
_userAccessWindow.Close();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
//ignore
|
|
}
|
|
_userAccessWindow = null;
|
|
}
|
|
|
|
if (_registerForm != null)
|
|
_registerForm.OnCancellation -= OnUserAccessControlCancellation;
|
|
|
|
UiElmEnable(optionsMenu, true);
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Close event handler of the user access window with login form or password change form.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="eventArgs"></param>
|
|
/// <remarks date="2025-Mar-25" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void OnUserAccessWindowClosed_Handler(Object sender, EventArgs eventArgs)
|
|
{
|
|
ShowUserAccessWindow(false);
|
|
InitializeFormState();
|
|
}
|
|
|
|
private void UpdateUi(ContentControl c, String content, Brush color = null)
|
|
{
|
|
if (color == null)
|
|
color = Brushes.Black;
|
|
|
|
c.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
c.Content = content;
|
|
c.Foreground = color;
|
|
}));
|
|
}
|
|
|
|
private void UpdateUi(TextBox c, String content, Brush color = null)
|
|
{
|
|
if (color == null)
|
|
color = Brushes.Black;
|
|
|
|
c.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
c.Text = content;
|
|
c.Foreground = color;
|
|
}));
|
|
}
|
|
private void UpdateUi(TextBlock c, String content, Brush color = null)
|
|
{
|
|
if (color == null)
|
|
color = Brushes.Black;
|
|
|
|
c.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
c.Text = content;
|
|
c.Foreground = color;
|
|
}));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update the elapsed time as information
|
|
/// </summary>
|
|
/// <returns>information attached to process depending on region</returns>
|
|
/// <remarks date="2024-Jul-11" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void SetTimeDisplay()
|
|
{
|
|
var time = DateTimeOffset.UtcNow;
|
|
var timeSpan = time - _startTime;
|
|
UpdateContentControl(lblTimeValue, $@"{(UInt32)timeSpan.TotalMinutes}:{timeSpan.Seconds:00}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common routine for state change:
|
|
/// - Log state change,
|
|
/// - Execute stop procedure on error.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2020-Dec-12" author="Roland Drabesch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2024-Aug-30" author="Thomas Wiedebusch">
|
|
/// - Extended.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Apr-10" author="Thomas Wiedebusch">
|
|
/// - Extended.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Jun-30" author="Thomas Wiedebusch">
|
|
/// - Automatic start on idle if required.
|
|
/// </remarks>
|
|
private void StateMachineStateChanged_Handler(Object sender, ProcessStateArgs e)
|
|
{
|
|
_logger.Debug($"Slot:{Slot} - Final test state: {e.State}");
|
|
|
|
// Nothing to display
|
|
if (e.State == ProcessState.Idle)
|
|
{
|
|
// Update progress bars
|
|
ProcessProgress_Handler(this, new ProcessProgressArgs(0,
|
|
ProcessProgressArgs.ProcessProgressType.OverallProcessesSteps));
|
|
ProcessProgress_Handler(this, new ProcessProgressArgs(0,
|
|
ProcessProgressArgs.ProcessProgressType.ActualProcessSteps));
|
|
|
|
// Start first production process if required and user is authenticated
|
|
if (_autoStartFirstProductionProcess && Software.IsAutenticated)
|
|
{
|
|
BtnStart_Click(this, null);
|
|
}
|
|
}
|
|
// Stop all procedures
|
|
if (e.State == ProcessState.Stop)
|
|
{
|
|
_timer?.Stop();
|
|
UiElmEnable(btnStart, true, !_autoStartFirstProductionProcess);
|
|
UiElmEnable(btnStop, false);
|
|
// update progress bars
|
|
ProcessProgress_Handler(this, new ProcessProgressArgs(0,
|
|
ProcessProgressArgs.ProcessProgressType.OverallProcessesSteps));
|
|
ProcessProgress_Handler(this, new ProcessProgressArgs(0,
|
|
ProcessProgressArgs.ProcessProgressType.ActualProcessSteps));
|
|
}
|
|
// Repeat failed tests
|
|
if (e.State == ProcessState.RepeatFailedTests)
|
|
{
|
|
UiElmEnable(btnStart, false, !_autoStartFirstProductionProcess);
|
|
UiElmEnable(btnStop, true);
|
|
ProcessProgress_Handler(this, new ProcessProgressArgs(0,
|
|
ProcessProgressArgs.ProcessProgressType.ActualProcessSteps));
|
|
_timer?.Start();
|
|
}
|
|
// Stop time for manual operation and visual inspection as this is not part of the configuration
|
|
if (e.State == ProcessState.CheckOrderNumber)
|
|
{
|
|
_timer?.Stop();
|
|
}
|
|
// Prepare shipping
|
|
if (e.State == ProcessState.PrepareShippingMode)
|
|
{
|
|
_timer?.Stop();
|
|
UiElmEnable(btnStart, false, !_autoStartFirstProductionProcess);
|
|
UiElmEnable(btnStop, false);
|
|
}
|
|
// Prepare assembly line release
|
|
if (e.State == ProcessState.PrepareAssemblyLineRelease)
|
|
{
|
|
_timer?.Stop();
|
|
UiElmEnable(btnStart, false, !_autoStartFirstProductionProcess);
|
|
UiElmEnable(btnStop, false);
|
|
}
|
|
// Ready for shipping
|
|
if (e.State == ProcessState.ReadyForShipping)
|
|
{
|
|
// Create extended report including all steps and each register write, read and comparison
|
|
CreateFile(Properties.Resources.StrInfoSuccessShipping);
|
|
BtnStop_Click(this, null);
|
|
}
|
|
// Ready after assembly
|
|
if (e.State == ProcessState.AssemblyLineRelease)
|
|
{
|
|
// Create extended report including all steps and each register write, read and comparison
|
|
CreateFile(Properties.Resources.StrInfoSuccessAssembly);
|
|
BtnStop_Click(this, null);
|
|
}
|
|
// Print return report
|
|
if (e.State == ProcessState.PrintReturnReport)
|
|
{
|
|
PrintErrorNote();
|
|
BtnStop_Click(this, null);
|
|
}
|
|
// Print success report
|
|
if (e.State == ProcessState.PrintSuccessReport)
|
|
{
|
|
PrintSuccessNote();
|
|
BtnStop_Click(this, null);
|
|
}
|
|
// Enable display of Genesis information on new detected
|
|
if (e.State == ProcessState.ConnectCordonel)
|
|
{
|
|
_lockGenesisInfo = false;
|
|
}
|
|
// Enable timer with first automatic process
|
|
if (e.State == ProcessState.DetectCordonel)
|
|
{
|
|
if (_timer != null && !_timer.IsEnabled)
|
|
_startTime = DateTimeOffset.UtcNow;
|
|
_timer?.Start();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enable UI elements
|
|
/// </summary>
|
|
/// <param name="elm"></param>
|
|
/// <param name="isEnabled"></param>
|
|
/// <param name="isVisible"></param>
|
|
private void UiElmEnable(UIElement elm, Boolean isEnabled, Boolean isVisible = true)
|
|
{
|
|
elm.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
elm.Visibility = isVisible ? Visibility.Visible : Visibility.Hidden;
|
|
elm.IsEnabled = isEnabled;
|
|
|
|
}));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fill logging window with information
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="????" author="Roland Drabesch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2023-07-06" author="Thomas Wiedebusch">
|
|
/// - Changed to rich text edit with colored output.
|
|
/// </remarks>
|
|
/// <remarks date="2024-08-28" author="Thomas Wiedebusch">
|
|
/// - Avoid output of repeated text or useless empty text.
|
|
/// </remarks>
|
|
private void ProcessLog_Handler(Object sender, ProcessLogArgs e)
|
|
{
|
|
rtbLog.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
if (e != null)
|
|
{
|
|
try
|
|
{
|
|
// remove unacceptable spacing between the lines
|
|
rtbLog.Document.LineHeight = 1;
|
|
|
|
var color = e.Color ?? Brushes.Black;
|
|
var text = e.Data;
|
|
if (!string.IsNullOrEmpty(text) && !text.Equals(_lastLoggingTextToAvoidRepetition))
|
|
{
|
|
var tr = new TextRange(rtbLog.Document.ContentEnd, rtbLog.Document.ContentEnd)
|
|
{
|
|
Text = text
|
|
};
|
|
tr.ApplyPropertyValue(TextElement.ForegroundProperty, color);
|
|
rtbLog.ScrollToEnd();
|
|
rtbLog.AppendText(Environment.NewLine);
|
|
}
|
|
|
|
_lastLoggingTextToAvoidRepetition = text;
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|
|
));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispatch GUI messages
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2025-Sep-15" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void GuiMessageDispatcher_Handler(Object sender, GuiMessageArgs e)
|
|
{
|
|
if (e?.Obj is Int32 obj)
|
|
{
|
|
switch (e.GuiItem)
|
|
{
|
|
case GuiItem.OrderAmount:
|
|
OrderAmount = e.Obj != null ? obj : 0;
|
|
break;
|
|
case GuiItem.OrderCounter:
|
|
OrderCounter = e.Obj != null ? obj : 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set values for progress bar, maximum and actual for single process and overall process.
|
|
/// - Limit values to 0.0..100.0.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="????" author="Roland Drabesch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2024-07-18" author="Thomas Wiedebusch">
|
|
/// - Introduced multi line text with center alignment.
|
|
/// </remarks>
|
|
private void ProcessProgress_Handler(Object sender, ProcessProgressArgs e)
|
|
{
|
|
if (e.ProgressType == ProcessProgressArgs.ProcessProgressType.MaxOverallProcessSteps)
|
|
{
|
|
_maxOverallProcessSteps = e.Progress;
|
|
}
|
|
else if (e.ProgressType == ProcessProgressArgs.ProcessProgressType.MaxActualProcessSteps)
|
|
{
|
|
_maxSingleProcessSteps = e.Progress;
|
|
}
|
|
if (e.ProgressType == ProcessProgressArgs.ProcessProgressType.OverallProcessesSteps)
|
|
{
|
|
pbTotalProgress.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
// limit output to progress bar to 0..100 as integer for process bar
|
|
var progress = _maxOverallProcessSteps <= 0 ? 0.0 : e.Progress * 100.0 / _maxOverallProcessSteps;
|
|
progress = progress > 100.0 ? 100.0 : progress < 0.0 ? 0.0 : progress;
|
|
pbTotalProgress.Value = (Int32)progress;
|
|
UpdateContentControl(lblTotalProgressValue, $@"{progress:##0.0} %");
|
|
}
|
|
));
|
|
}
|
|
else if (e.ProgressType == ProcessProgressArgs.ProcessProgressType.ActualProcessSteps)
|
|
{
|
|
pbSubProgress.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
// limit output to progress bar to 0..100 as integer for process bar
|
|
var progress = _maxSingleProcessSteps <= 0 ? 0.0 : e.Progress * 100.0 / _maxSingleProcessSteps;
|
|
progress = progress > 100.0 ? 100.0 : progress < 0.0 ? 0.0 : progress;
|
|
pbSubProgress.Value = (Int32)progress;
|
|
UpdateContentControl(lblSubProgressValue, $@"{progress:##0.0} %");
|
|
}
|
|
));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Output message to control without access violation.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="????" author="Roland Drabesch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2023-07-11" author="Thomas Wiedebusch">
|
|
/// - Introduced multi line text with center alignment.
|
|
/// </remarks>
|
|
private static void UpdateContentControl(ContentControl ctl, String text)
|
|
{
|
|
ctl.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
ctl.Content = new TextBlock()
|
|
{
|
|
Text = text,
|
|
TextWrapping = TextWrapping.Wrap,
|
|
TextAlignment = TextAlignment.Center
|
|
};
|
|
}
|
|
));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Status grid update for all single processes
|
|
/// </summary>
|
|
private void UpdateStatusGrid()
|
|
{
|
|
var dt = new DataTable();
|
|
dt.Columns.Add(Properties.Resources.StrDataTableColumnProcess);
|
|
dt.Columns.Add(Properties.Resources.StrDataTableColumnState);
|
|
var i = 0;
|
|
if (_processCtrl?.Processes == null)
|
|
return;
|
|
foreach (var item in _processCtrl.Processes)
|
|
{
|
|
dt.Rows.Add();
|
|
dt.Rows[i][0] = item.ProcessName;
|
|
dt.Rows[i][1] = ProductionProcessStateHelper.GetTextFromProductionProcessState(item.SingleProcessState);
|
|
i++;
|
|
}
|
|
|
|
dgTotalProcess.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
dgTotalProcess.DataContext = dt;
|
|
}
|
|
));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispatch new user control to main screen
|
|
/// </summary>
|
|
/// <param name="uc"></param>
|
|
private void SetNewUserControl(UserControl uc)
|
|
{
|
|
dgTotalProcess.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
// remove last userControl
|
|
dpSubProcess.Children.Clear();
|
|
if (uc != null)
|
|
{
|
|
dpSubProcess.Children.Add(uc);
|
|
DockPanel.SetDock(uc, Dock.Top); // & Dock.Left);
|
|
}
|
|
}
|
|
));
|
|
}
|
|
|
|
#region TimerControls
|
|
/// <summary>
|
|
/// Handle timing depending updates.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2024-07-11" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void TmrProgressUpdate_Tick(Object sender, EventArgs e)
|
|
{
|
|
SetTimeDisplay();
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Update of status grid with information returned by user control.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="????" author="Roland Drabesch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2024-08-28" author="Thomas Wiedebusch">
|
|
/// - Activate new user control on start of process.
|
|
/// </remarks>
|
|
private void ProcessStateChanged_Handler(Object sender, SingleProcessStateArgs e)
|
|
{
|
|
if (sender is IProductionProcess productionProcess)
|
|
{
|
|
if (e.SingleProcessState == SingleProcessState.Running)
|
|
{
|
|
// Set new user control
|
|
SetNewUserControl(productionProcess.GetUserControl());
|
|
}
|
|
else
|
|
{
|
|
// remove user control on idle, skipped, abort or error
|
|
SetNewUserControl(null);
|
|
}
|
|
}
|
|
|
|
UpdateStatusGrid();
|
|
UpdateGuiWithProductInfos();
|
|
}
|
|
|
|
private void OnUserAccessControlCancellation(Control control)
|
|
{
|
|
OnUserAccessWindowClosed_Handler(this, null);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Set labels of device information and order number
|
|
/// </summary>
|
|
/// <remarks date="????" author="Roland Drabesch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2024-Jul-15" author="Thomas Wiedebusch">
|
|
/// - Additional info of Cordonel.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Jun-18" author="Thomas Wiedebusch">
|
|
/// - Lock display of OLD Genesis after connect until the Genesis has been detected.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Sep-15" author="Thomas Wiedebusch">
|
|
/// - Order counter.
|
|
/// </remarks>
|
|
private void UpdateGuiWithProductInfos()
|
|
{
|
|
var genesisMeter = _processCtrl?.GetGenesisMeter();
|
|
_productionRequirements = _processCtrl?.GetProductionRequirements();
|
|
|
|
if (genesisMeter == null )
|
|
return;
|
|
UpdateContentControl(lblOrderNumberValue,
|
|
genesisMeter.OrderNumber != 0 ? genesisMeter.OrderNumber.ToString() : "?");
|
|
|
|
UpdateContentControl(lblOrderCounterValue,
|
|
OrderAmount != 0 && genesisMeter.OrderNumber != 0 ? $"{OrderCounter} / " +
|
|
$"{OrderAmount} {Properties.Resources.StrLblPieces}" : "");
|
|
UpdateContentControl(lblOrderCounterText,
|
|
OrderAmount != 0 && genesisMeter.OrderNumber != 0 ? Properties.Resources.StrLblOrderCounterTxt + ":" : "");
|
|
|
|
if (_lockGenesisInfo)
|
|
return;
|
|
|
|
//UpdateContentControl(lblOrderNumberValue,
|
|
// genesisMeter.OrderNumber != 0 ? genesisMeter.OrderNumber.ToString() : "?");
|
|
|
|
//UpdateContentControl(lblOrderCounterValue,
|
|
// OrderAmount != 0 && genesisMeter.OrderNumber != 0 ? $"{OrderCounter} / " +
|
|
// $"{OrderAmount} {Properties.Resources.StrLblPieces}" : "");
|
|
//UpdateContentControl(lblOrderCounterText,
|
|
// OrderAmount != 0 && genesisMeter.OrderNumber != 0 ? Properties.Resources.StrLblOrderCounterTxt + ":" : "");
|
|
|
|
UpdateContentControl(lblRadioAddressValue,
|
|
genesisMeter.RadioAddress != 0 ? genesisMeter.RadioAddress.ToString() : "");
|
|
UpdateContentControl(lblRadioAddressText,
|
|
genesisMeter.RadioAddress != 0 ? Properties.Resources.StrLblRadioAddressTxt + ":" : "");
|
|
|
|
UpdateContentControl(lblFwValue,
|
|
!string.IsNullOrEmpty(genesisMeter.FwVersion) ? genesisMeter.FwVersion : "?");
|
|
|
|
UpdateContentControl(lblMeterSizeValue,
|
|
!string.IsNullOrEmpty(genesisMeter.MeterSize) ? genesisMeter.MeterSize : "?");
|
|
|
|
UpdateContentControl(lblMeterLengthValue,
|
|
!string.IsNullOrEmpty(genesisMeter.MeterLength) && !genesisMeter.MeterLength.Equals("?") ?
|
|
genesisMeter.MeterLength + " mm" : "?");
|
|
|
|
UpdateContentControl(lblInterfaceVersionValue,
|
|
!string.IsNullOrEmpty(genesisMeter.InterfaceInfo.InterfaceVersion) ?
|
|
genesisMeter.InterfaceInfo.InterfaceVersion : "?");
|
|
|
|
UpdateContentControl(lblLutValue,
|
|
!string.IsNullOrEmpty(genesisMeter.LutCrc) ? genesisMeter.LutCrc : "?");
|
|
|
|
UpdateContentControl(lblSerialNumberValue,
|
|
!string.IsNullOrEmpty(genesisMeter.CustomerSerialNumber) ? genesisMeter.CustomerSerialNumber : "?");
|
|
|
|
UpdateContentControl(lblRegionValue,
|
|
!string.IsNullOrEmpty(genesisMeter.Region) ? genesisMeter.Region : "?");
|
|
|
|
UpdateUi(lblPcbIdValue, !string.IsNullOrEmpty(genesisMeter.PcbId) ? genesisMeter.PcbId : "?");
|
|
|
|
var msg = "";
|
|
var color = Brushes.Black;
|
|
if (_productionRequirements?.IsSpecialActive != null && (Boolean)_productionRequirements.IsSpecialActive &&
|
|
_productionRequirements?.IsSpecialApproved != null && (Boolean)_productionRequirements.IsSpecialApproved)
|
|
{
|
|
msg = $"{Properties.Resources.StrLblSpecialRequirement} - Id.Ver: {_productionRequirements.SpecialId}." +
|
|
$"{_productionRequirements.SpecialVersion}";
|
|
color = Brushes.Red;
|
|
}
|
|
else if (_productionRequirements?.IsStandardActive != null && (Boolean)_productionRequirements.IsStandardActive &&
|
|
_productionRequirements?.IsStandardApproved != null && (Boolean)_productionRequirements.IsStandardApproved)
|
|
{
|
|
msg = $"{Properties.Resources.StrLblStandardRequirement} - Id.Ver: {_productionRequirements.StandardId}." +
|
|
$"{_productionRequirements.StandardVersion}";
|
|
}
|
|
|
|
UpdateUi(lblApprovalText, msg, color);
|
|
}
|
|
|
|
//private void BtnSwitchAutoDetect_Click(Object sender, RoutedEventArgs e)
|
|
//{
|
|
// //Settings.AutoDetect = !Settings.AutoDetect;
|
|
// //StoreSetting();
|
|
// //UseSetting();
|
|
//}
|
|
|
|
private void OnLogout_Click(Object sender, EventArgs e)
|
|
{
|
|
Software.Logout();
|
|
InitializeFormState();
|
|
}
|
|
|
|
private void OnLogin_Click(Object sender, EventArgs args)
|
|
{
|
|
ShowUserAccessWindow(true, new LoginForm(OnUserAccessControlCancellation),
|
|
Properties.Resources.StrLoginMsg);
|
|
}
|
|
|
|
private void OnChangePassword_Click(Object _, EventArgs _1)
|
|
{
|
|
ShowUserAccessWindow(true, new ChangePassword(OnUserAccessControlCancellation),
|
|
Properties.Resources.StrChangePasswordMsg);
|
|
}
|
|
|
|
private void CbxSlotBox_SelectionChanged(Object sender, SelectionChangedEventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
//private void StoreSetting()
|
|
//{
|
|
// Settings.Update("ProductionUiConfig.json");
|
|
//}
|
|
|
|
//private void BtnConnect_Click(Object sender, RoutedEventArgs e)
|
|
//{
|
|
// Settings.Slot = (Int32)cbxSlotBox.SelectedValue;
|
|
// StoreSetting();
|
|
//}
|
|
|
|
/// <summary>
|
|
/// Start assembly process
|
|
/// </summary>
|
|
/// <remarks date="????" author="Roland Drabesch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2025-Sep-15" author="Thomas Wiedebusch">
|
|
/// - Order counter.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Sep-16" author="Thomas Wiedebusch">
|
|
/// - Reset order number to avoid display glitch on changed PcbId.
|
|
/// </remarks>
|
|
private void BtnStart_Click(Object sender, RoutedEventArgs e)
|
|
{
|
|
UiElmEnable(btnStart, false, !_autoStartFirstProductionProcess);
|
|
UiElmEnable(btnStop, true);
|
|
|
|
_startTime = DateTimeOffset.UtcNow;
|
|
_timer?.Start();
|
|
// Avoid display of genesis info before the detect new meter has been executed
|
|
_lockGenesisInfo = true;
|
|
// Reset order amount until data from database has been collected
|
|
OrderAmount = 0;
|
|
// Reset order number to avoid display glitch on changed PcbId
|
|
var genesisMeter = _processCtrl?.GetGenesisMeter();
|
|
if (genesisMeter != null)
|
|
{
|
|
genesisMeter.OrderNumber = 0;
|
|
}
|
|
|
|
rtbLog.Dispatcher.Invoke(DispatcherPriority.Normal,
|
|
new Action(() =>
|
|
{
|
|
rtbLog.Document.Blocks.Clear();
|
|
}
|
|
));
|
|
|
|
// clear all visual fields as it may be a new pcbId
|
|
UpdateContentControl(lblOrderNumberValue, "?");
|
|
UpdateContentControl(lblRadioAddressValue, "");
|
|
UpdateContentControl(lblRadioAddressText, "");
|
|
UpdateContentControl(lblOrderCounterValue, "");
|
|
UpdateContentControl(lblOrderCounterText, "");
|
|
UpdateContentControl(lblFwValue, "?");
|
|
UpdateContentControl(lblMeterSizeValue, "?");
|
|
UpdateContentControl(lblInterfaceVersionValue, "?");
|
|
UpdateContentControl(lblMeterLengthValue, "?");
|
|
UpdateContentControl(lblLutValue, "?");
|
|
UpdateContentControl(lblSerialNumberValue, "?");
|
|
UpdateContentControl(lblRegionValue, "?");
|
|
UpdateUi(lblPcbIdValue, "?");
|
|
UpdateUi(lblApprovalText, "", Brushes.Black);
|
|
|
|
_processCtrl?.StartFirstProcess();
|
|
}
|
|
|
|
private void PrintErrorNote()
|
|
{
|
|
// Safe report to file
|
|
CreateFile(Properties.Resources.StrInstructionReturnPapers, true, true);
|
|
}
|
|
|
|
private void PrintSuccessNote()
|
|
{
|
|
// Safe report to file
|
|
var msg = "";
|
|
if (_strAppNameVersion.Contains(Properties.Resources.StrEolSoftwareNameVersion))
|
|
msg = Properties.Resources.StrInfoSuccessShipping;
|
|
else if (_strAppNameVersion.Contains(Properties.Resources.StrPickingSoftwareNameVersion))
|
|
msg = Properties.Resources.StrInfoSuccessAssembly;
|
|
|
|
CreateFile(msg, true, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Logging a file with all process information, building a compressed report for printout.
|
|
/// </summary>
|
|
/// <remarks date="2025-Apr-10" author="Thomas Wiedebusch">
|
|
/// - Reduced printout.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Jun-17" author="Thomas Wiedebusch">
|
|
/// - Base logging path taken from NLogHelper as log-path setting made in GTB.
|
|
/// </remarks>
|
|
private void CreateFile(String headerInfo, Boolean shortReport = false, Boolean printReport = false)
|
|
{
|
|
var sb = new StringBuilder();
|
|
var genesisMeter = _processCtrl.GetGenesisMeter();
|
|
|
|
sb.AppendLine("========================================================================");
|
|
sb.AppendLine(headerInfo);
|
|
sb.AppendLine("========================================================================");
|
|
sb.AppendLine(_strAppNameVersion);
|
|
sb.AppendLine("------------------------------------------------------------------------");
|
|
sb.AppendLine($"{Properties.Resources.StrDateTime}: {DateTime.Now}");
|
|
sb.AppendLine("------------------------------------------------------------------------");
|
|
sb.AppendLine($"PcbId: {genesisMeter.PcbId}");
|
|
sb.AppendLine($"{Properties.Resources.StrPrintOrderNumberTxt}: {genesisMeter.OrderNumber}");
|
|
sb.AppendLine($"{Properties.Resources.StrLblSerialNumberTxt}: {genesisMeter.CustomerSerialNumber}");
|
|
sb.AppendLine($"{Properties.Resources.StrLblOperatorNameText}: {Software.UserName}");
|
|
sb.AppendLine("------------------------------------------------------------------------");
|
|
|
|
try
|
|
{
|
|
var path = NLogHelper.GetApplicationDataPath();
|
|
if (string.IsNullOrEmpty(path))
|
|
{
|
|
path = NLogHelper.GetCurrentApplicationFolder();
|
|
}
|
|
var a = XElement.Load(path);
|
|
var baseLoggingPath = a.Elements().First(s => s.Name.LocalName == "variable").Attributes().First(s => s.Value == "BasePath").NextAttribute.Value;
|
|
|
|
var loggingPath = $"{baseLoggingPath}\\{DateTime.Now:yyyy-MM-dd}\\ProductionUiCordonel\\";
|
|
var fileName = $"{loggingPath}{DateTime.Now.ToString("yyyyMMddHHmmss")}_ExtendedReport_{genesisMeter.PcbId}.txt";
|
|
|
|
// Copy the header to the compressed string builder
|
|
var compressedSb = new StringBuilder();
|
|
if (shortReport)
|
|
{
|
|
compressedSb.Append(sb);
|
|
}
|
|
|
|
var rtbText = new TextRange(
|
|
rtbLog.Document.ContentStart,
|
|
rtbLog.Document.ContentEnd
|
|
);
|
|
sb.Append($"{rtbText.Text}");
|
|
// Write the complete report to the file
|
|
File.WriteAllText(fileName, sb.ToString());
|
|
|
|
// Reduce sb content to compress it for printout
|
|
if (shortReport)
|
|
{
|
|
fileName = $"{loggingPath}{DateTime.Now.ToString("yyyyMMddHHmmss")}" +
|
|
$"_ShortReport_{genesisMeter.PcbId}.txt";
|
|
var sr = new StringReader(rtbText.Text);
|
|
var srLine = sr.ReadLine();
|
|
while (srLine != null)
|
|
{
|
|
if (srLine.Contains(Properties.Resources.StrProcessStateError) ||
|
|
srLine.Contains(Properties.Resources.StrProcessStateDone) ||
|
|
srLine.Contains(Properties.Resources.StrProcessStateWarning) ||
|
|
srLine.Contains(Properties.Resources.StrProcessStateSkipped) ||
|
|
srLine.Contains(Properties.Resources.StrProcessStateAttention))
|
|
compressedSb.AppendLine(srLine);
|
|
srLine = sr.ReadLine();
|
|
}
|
|
|
|
// Returns the compressed file for error report printout
|
|
File.WriteAllText(fileName, compressedSb.ToString());
|
|
if (printReport)
|
|
{
|
|
Process.Start(fileName);
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e.Message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stop button as user interaction to kill the finalization process
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void BtnStop_Click(Object sender, RoutedEventArgs e)
|
|
{
|
|
//set the process state to the state machine
|
|
_processCtrl?.SetProcessState(ProcessState.Stop);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open requirement in Web-Browser.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void LblApprovalText_Click(Object sender, System.Windows.Input.MouseButtonEventArgs e)
|
|
{
|
|
var requirementId = 0;
|
|
var requirementWebPageLink = ServiceUrls.InspectCordonelRequirementInfoServiceUrl();
|
|
if (_productionRequirements?.SpecialId != null &&
|
|
_productionRequirements?.IsSpecialApproved != null &&
|
|
_productionRequirements.SpecialId != 0)
|
|
{
|
|
requirementId = (Int32)_productionRequirements.SpecialId;
|
|
requirementWebPageLink += $"SpecialRequirements#{requirementId}";
|
|
}
|
|
else if (_productionRequirements?.StandardId != null &&
|
|
_productionRequirements?.IsStandardApproved != null &&
|
|
_productionRequirements.StandardId != 0)
|
|
{
|
|
requirementId = (Int32)_productionRequirements.StandardId;
|
|
requirementWebPageLink += $"StandardRequirements#{requirementId}";
|
|
}
|
|
|
|
if (requirementId != 0)
|
|
{
|
|
Process.Start(requirementWebPageLink);
|
|
}
|
|
}
|
|
|
|
private void HlpMenu_Click(Object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
var filename = "";
|
|
if (_strAppNameVersion.Contains(Properties.Resources.StrEolSoftwareNameVersion))
|
|
{
|
|
if (Thread.CurrentThread.CurrentCulture.Name.Contains("de"))
|
|
{
|
|
filename = Path.Combine(_assemblyExecRootPath, "Docu", @"Handbuch Cordonel Versandfertigmachen (VFM).pdf");
|
|
}
|
|
else if (Thread.CurrentThread.CurrentCulture.Name.Contains("en"))
|
|
{
|
|
filename = Path.Combine(_assemblyExecRootPath, "Docu", @"Manual Cordonel End of Line Test (EOL).pdf");
|
|
}
|
|
}
|
|
else if (_strAppNameVersion.Contains(Properties.Resources.StrPickingSoftwareNameVersion))
|
|
{
|
|
if (Thread.CurrentThread.CurrentCulture.Name.Contains("de"))
|
|
{
|
|
filename = Path.Combine(_assemblyExecRootPath, "Docu", @"Handbuch Cordonel Montagelinie (MTL).pdf");
|
|
}
|
|
else if (Thread.CurrentThread.CurrentCulture.Name.Contains("en"))
|
|
{
|
|
filename = Path.Combine(_assemblyExecRootPath, "Docu", @"Manual Assembly Line (ABL).pdf");
|
|
}
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(filename))
|
|
{
|
|
Process.Start(filename);
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Console.WriteLine(exception.Message);
|
|
}
|
|
}
|
|
|
|
private void Window_Loaded(Object sender, RoutedEventArgs e)
|
|
{
|
|
if (!Software.IsAutenticated)
|
|
OnLogin_Click(this, null);
|
|
|
|
}
|
|
}
|
|
}
|