tbf/Workplace/WorkplaceDlg.cs

1936 lines
76 KiB
C#

///
/// Copyright (c) 2016-2022 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using log4net;
using NHibernate;
using SharedDatabase;
using SharedDatabase.Entities;
using SharedDatabase.Forms;
using Workplace.Resources;
namespace Workplace
{
public partial class WorkplaceDlg : Form
{
static readonly ILog log = LogManager.GetLogger(typeof(WorkplaceDlg));
[DllImport("User32.dll")] public static extern Int32 SetForegroundWindow(int hWnd);
public const int NrGeneratorIx = 0; /// BaseNr1 and CurrentNr1 are used to generate and print serial numbers
const int ErrorBeepFrequency = 500; /// Hz
const int ErrorBeepDuration = 1000; /// ms
public int ExtraBatteryLifetime; /// In months, default = 0
ISession dbSession;
public IList<OrderInfo> AllOrders; /// All orders including the finished ones
IList<OrderInfo> orders; /// New and active orders from the database
IList<Process> workflows; /// Workflows from the database
WPlaceRegistrationMgmt wplaceRegistration;
Timer runDeviceTimer; /// Timer for regular 1 second ticks
DateTime lastActivity; /// Timestamp of the last users activity (OnBarcodeReceived, OnFocusPressed, etc.)
DateTime lastLoginTime; /// Timestamp of the last user login
bool isLoggedOut;
/// This object processes records (=files) from a thirdparty program and extract reference part codes
RecordProcessing.RecordProcessing recordProcessing;
/// Currently displayed process and workstep
public OrderInfo CurrentOrder; /// Currently used order
public Process CurrentWorkflow; /// Currently used process
public Workstep CurrentWorkstep; /// Currently used workstep
IList<Workstep> workstepsOfTheCurrentWorkflow;
/// ix=0, orderNr=1
string[] predefinedOrders = new[] { Strings.none };
/// Previous workstep verification
Workstep verifiedWorkstep;
Part verifiedPart; /// Applicable when verifyReferencePart == false
bool verifyReferencePart;
/// Items to be scanned/filled in
IList<ICheckItem> komponenty;
IList<ICheckItem> palety;
bool isSNPrinting { get { return komponenty != null && komponenty.Count == 1 && komponenty[0] is CheckItems.SNGeneratorPrinter; } }
bool loadedOnce;
bool supressUINotifications;
PartError errorFlag;
public WorkplaceDlg()
{
try
{
string culture = Program.LocalSettings.Language.Replace('_', '-');
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture);
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(culture);
}
catch (Exception exc)
{
string msg = exc.Message;
MessageBox.Show("Selected language is not supported.\nUsing English.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en");
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");
}
var form = new Common.Forms.ModelessForm(Strings.Loading_configuration_from_a_database);
new System.Threading.Thread(() => Application.Run(form)).Start();
InitializeComponent();
supressUINotifications = true;
ManageCheckGroupBox(batchesCheckBox, batchesGroupBox);
wplaceRegistration = new WPlaceRegistrationMgmt();
komponenty = new List<ICheckItem>();
palety = new List<ICheckItem>();
do
{
dbSession = null;
orders = null;
AllOrders = null;
workflows = null;
try
{
dbSession = TracingDB.CreateSession(Program.LocalSettings.ConnectionString);
orders = ReadOrders(dbSession);
AllOrders = ReadOrders(dbSession, false);
workflows = ReadReleasedActiveProcesses(dbSession);
}
catch (Exception exc)
{
DialogResult rslt = MessageBox.Show(Strings.Opening_database_failed +
Environment.NewLine + Environment.NewLine +
exc.Message +
Environment.NewLine + Environment.NewLine +
Strings.Do_you_want_to_change_settings,
Strings.Warning,
MessageBoxButtons.YesNo,
MessageBoxIcon.Exclamation);
if (rslt != DialogResult.Yes)
{
Common.Forms.ModelessForm.CloseForm();
throw new Common.QuitAppException(Strings.Opening_database_failed);
}
}
if (dbSession == null || orders == null ||
AllOrders == null || workflows == null)
{
var dr = Configure();
if (dr != DialogResult.OK)
{
Common.Forms.ModelessForm.CloseForm();
throw new Common.QuitAppException(Strings.Opening_database_failed);
}
}
}
while (dbSession == null || orders == null ||
AllOrders == null || workflows == null);
BarcodeReceivedHandler += delegate(object sndr, BarcodeReceivedEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<BarcodeReceivedEventArgs>(BarcodeReceived), sndr, args); }
else { BarcodeReceived(sndr, args); }
};
FocusPressedHandler += delegate(object sndr, FocusPressedEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<FocusPressedEventArgs>(FocusPressed), sndr, args); }
else { FocusPressed(sndr, args); }
};
ColorFlashHandler += delegate(object sender, ColorFlashEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<ColorFlashEventArgs>(OnColorFlash), sender, args); }
else OnColorFlash(sender, args);
};
workplaceTextBox.Text = Program.LocalSettings.WorkplaceId;
workerTextBox.Text = Common.GlobalData.GetCurrentUserName();
lastLoginTime = DateTime.Now;
isLoggedOut = false;
ResetIdleTime();
/// Timer for regular 1 second ticks
runDeviceTimer = new System.Windows.Forms.Timer();
runDeviceTimer.Interval = 1000; // ms
runDeviceTimer.Tick += new EventHandler(runDeviceTimer_Tick);
runDeviceTimer.Start();
///
/// Activate processing of records (log files) created by a thirdparty program
///
if (Program.LocalSettings.RecordProcessing == RecordProcessing.RecordType.CommTest)
{
recordProcessing = new RecordProcessing.RecordProcessing(RecordProcessing.RecordType.CommTest,
RecordProcessing.RecordPostproc.None,
"C:\\iPerl\\LogFiles\\CommTester", true, "*.log");
}
else
{
recordProcessing = null;
}
if (recordProcessing != null)
{
recordProcessing.SubmitRecordHandler += delegate(object sender, RecordProcessing.SubmitRecordEventArgs args)
{
if (InvokeRequired)
{
Invoke(new EventHandler<RecordProcessing.SubmitRecordEventArgs>(SubmitRecordFromThirdpartyTester), sender, args);
}
else
{
SubmitRecordFromThirdpartyTester(sender, args);
}
};
}
}
/// <summary>
/// Submits a reference part code from a record from a 3-rd party program
/// </summary>
/// <param name="sender"></param>
/// <param name="args">Argument containing the reference part s/n</param>
void SubmitRecordFromThirdpartyTester(object sender, RecordProcessing.SubmitRecordEventArgs args)
{
if ((komponenty != null) && (komponenty.Count >= 1))
{
if (komponenty.Count >= 2) this.Activate(); /// Activate this window if there is 2nd code to scan
komponenty[0].SubmitCode(args.Record.SN); /// Submit the reference part code
//this.BringToFront(); /// 1 Tested: Brings window to the top only, does not activate the window
this.WindowState = FormWindowState.Minimized; /// 2 Works OK !!!
this.Show();
this.WindowState = FormWindowState.Normal;
//SetForegroundWindow(Handle.ToInt32()); /// 3 Should work as well
//this.Activate(); /// 4 Tested: Does not activate the window
//this.Focus();
}
}
private void WorkplaceDlg_Load(object sender, EventArgs e)
{
Localize();
CurrentOrder = null;
CurrentWorkflow = null;
CurrentWorkstep = null;
UpdateOrderCombo(orders, string.Empty);
workstepComboBox.Text = Program.LocalSettings.LastWorkstep;
if (UpdateWorkflowCombo(workflows, Program.LocalSettings.LastWorkflow))
{
if (UpdateWorkstepCombo(CurrentWorkflow, Program.LocalSettings.LastWorkstep))
{
UpdateItems();
}
}
Common.Forms.ModelessForm.CloseForm();
loadedOnce = true;
supressUINotifications = false;
orderComboBox.Focus();
}
void Localize()
{
orderLabel.Text = string.Format("{0}:", Strings.Order);
workflowLabel.Text = string.Format("{0}:", Strings.Workflow);
workstepLabel.Text = string.Format("{0}:", Strings.Workflow_step);
workerLabel.Text = string.Format("{0}:", Strings.Production_operator);
workplaceLabel.Text = string.Format("{0}:", Strings.Workplace);
logoutButton.Text = Strings.Exchange_of_operator;
configureButton.Text = Strings.Configure;
groupBox2.Text = Strings.Codes_of_components;
batchesCheckBox.Text = Strings.Codes_of_batches;
clearButton.Text = Strings.New_codes;
resetErrorStateButton.Text = Strings.Clear_errors;
failedCheckBox.Text = Strings.Failure;
saveAllCodesButton.Text = Strings.Save;
completedGroupBox.Text = Strings.Completed;
targetGroupBox.Text = Strings.Target;
}
/// <summary>
/// Read released-active processes from the database.
/// </summary>
/// <param name="session">Production tracing DB session</param>
/// <returns>A list of processes (success) or null (failure)</returns>
private IList<Process> ReadReleasedActiveProcesses(ISession session)
{
try
{
return session.QueryOver<Process>()
.Where(x => (x.ReleaseStatus == ReleaseStatus.In_preparation ||
x.ReleaseStatus == ReleaseStatus.ToBeApproved ||
x.ReleaseStatus == ReleaseStatus.ReleasedActive ||
x.ReleaseStatus == ReleaseStatus.Released))
.OrderBy(x => x.Name).Asc
.List();
}
catch (Exception exc)
{
log.ErrorFormat("Failed to load processes from the tracing DB: {0}", exc.Message);
return null;
}
}
IList<OrderInfo> ReadOrders(ISession session, bool newOrActiveOrdersOnly = true)
{
try
{
if (newOrActiveOrdersOnly)
{
var list = session.QueryOver<OrderInfo>()
.Where(x => (x.POState == (sbyte)OrderState.New || x.POState == (sbyte)OrderState.Active))
.OrderBy(x => x.POName).Asc
.List<OrderInfo>();
for (int i = list.Count - 1; i >= 0; i--)
{
int orderNr;
if (!int.TryParse(list[i].POName, out orderNr) || orderNr - 1 < predefinedOrders.Length)
{
list.RemoveAt(i);
}
}
return list;
}
else
{
return session.QueryOver<OrderInfo>()
.OrderBy(x => x.POName).Asc
.List<OrderInfo>();
}
}
catch (Exception exc)
{
log.ErrorFormat("Failed to load processes from the tracing DB: {0}", exc.Message);
return null;
}
}
/// <summary>
/// Updates target and completed pieces count and returns
/// true when target pieces count was reached.
/// </summary>
/// <returns>true when target pieces count reached</returns>
public bool UpdatePiecesCount()
{
if (CurrentOrder == null || predefinedOrders.Contains(orderComboBox.Text))
{
targetGroupBox.Visible = false;
targetLabel.Text = "0";
completedGroupBox.Visible = false;
completedLabel.Text = "0";
completedGroupBox.BackColor = SystemColors.Control;
completedGroupBox.ForeColor = SystemColors.ControlText;
return false;
}
else
{
targetGroupBox.Visible = true;
targetLabel.Text = CurrentOrder.PiecesCount.ToString();
if (CurrentWorkflow != null && CurrentWorkstep != null)
{
try
{
var pieces = dbSession.QueryOver<ReferenceRecord>()
.Where(x => x.POName == CurrentOrder.POName)
.And(x => x.Workflow == CurrentWorkflow.Name)
.List<ReferenceRecord>();
completedGroupBox.Visible = true;
completedLabel.Text = pieces.Count.ToString();
bool targetReached = pieces.Count >= CurrentOrder.PiecesCount;
completedGroupBox.BackColor = targetReached ? Color.Green : SystemColors.Control;
completedGroupBox.ForeColor = targetReached ? Color.White : SystemColors.ControlText;
return targetReached;
}
catch (Exception exc)
{
completedGroupBox.Visible = true;
completedLabel.Text = Strings.unknown;
completedGroupBox.BackColor = SystemColors.Control;
completedGroupBox.ForeColor = SystemColors.ControlText;
log.ErrorFormat("Unable to read ReferenceRecords: o={0} w={1} s={2}: {3}",
CurrentOrder.POName, CurrentWorkflow.Name, CurrentWorkstep.Name, exc.Message);
return false;
}
}
else
{
completedGroupBox.Visible = false;
completedLabel.Text = "0";
completedGroupBox.BackColor = SystemColors.Control;
completedGroupBox.ForeColor = SystemColors.ControlText;
return false;
}
}
}
void UpdateOrderCombo(IList<OrderInfo> orders, string preferredOrderName)
{
bool anyChange = (orders == null) || (predefinedOrders.Length + orders.Count != orderComboBox.Items.Count);
if (!anyChange)
{
for (int i = 0; i < orders.Count; i++)
{
if (orderComboBox.Items[i].ToString() != orders[i].POName)
{
anyChange = true;
break;
}
}
}
if (!anyChange) return;
int selectedIndex = -1;
orderComboBox.Items.Clear();
if (orders != null)
{
for (int i = 0; i < predefinedOrders.Length; i++)
{
orderComboBox.Items.Add(predefinedOrders[i]);
if (predefinedOrders[i] == preferredOrderName)
{
selectedIndex = i;
CurrentOrder = AllOrders.FirstOrDefault<OrderInfo>(x => x.POName == (i + 1).ToString("D7"));
}
}
for (int i = 0; i < orders.Count; i++)
{
orderComboBox.Items.Add(orders[i]);
if (orders[i].POName == preferredOrderName)
{
selectedIndex = predefinedOrders.Length + i;
CurrentOrder = orders[i];
}
}
}
orderComboBox.SelectedIndex = selectedIndex;
UpdatePiecesCount();
}
/// <summary>
/// Redraw processes in process combo box. Try to keep Program.LocalSettings.LastProcess selected.
/// In case of a change in ReleaseActive processes in the DB it may not be possible to keep this selection.
/// In such case function returns null.
/// When process selection changes, 'processComboBox_SelectedIndexChanged' is invoked.
/// </summary>
/// <returns>true = list of processes changed</returns>
bool UpdateWorkflowCombo(IList<Process> workflows, string preferredWorkflowName)
{
if (workflows == null || workflows.Count == 0)
{
supressUINotifications = true;
workflowComboBox.Items.Clear();
workflowComboBox.Text = string.Empty;
supressUINotifications = false;
bool wflowChgnd = (CurrentWorkflow != null);
CurrentWorkflow = null;
return wflowChgnd;
}
Process preferredWorkflow = workflows.FirstOrDefault<Process>(x => x.Name == preferredWorkflowName);
supressUINotifications = true;
workflowComboBox.Items.Clear();
for (int i = 0; i < workflows.Count; i++)
{
workflowComboBox.Items.Add(workflows[i].Name);
}
workflowComboBox.Text = (preferredWorkflow != null) ? preferredWorkflowName : string.Empty;
supressUINotifications = false;
bool workflowChanged = CurrentWorkflow != preferredWorkflow;
CurrentWorkflow = preferredWorkflow;
return workflowChanged;
}
private void workflowComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (supressUINotifications) return;
CurrentWorkflow = workflows.FirstOrDefault<Process>(x => x.Name == workflowComboBox.Text);
if (UpdateWorkstepCombo(CurrentWorkflow, workstepComboBox.Text))
{
UpdateItems();
ClearBatchNumbers();
Program.LocalSettings.LastWorkflow = CurrentWorkflow.Name;
Program.LocalSettings.LastWorkstep = CurrentWorkstep.Name;
}
}
/// <summary>
/// Updates workstep selection combo items and text. Clear it only if process == null.
/// If there is a valid 'oriWorkstepName', the combo box text is set and the selected workstep is returned.
/// Otherwise this function returns null.
/// </summary>
/// <param name="workflow">Process with worksteps to be used</param>
/// <param name="preferredWorkstepName">Originally selected workstep name</param>
/// <returns>New selected workstep or null</returns>
private bool UpdateWorkstepCombo(Process workflow, string preferredWorkstepName)
{
if (workflow == null || workflow.Worksteps == null || workflow.Worksteps.Count == 0)
{
supressUINotifications = true;
workstepComboBox.Items.Clear();
workstepComboBox.Text = string.Empty;
supressUINotifications = false;
bool wstepChgnd = (CurrentWorkstep != null);
CurrentWorkstep = null;
return wstepChgnd;
}
/// Todo: Select closes workstep
Workstep prefferedWorkstep = workflow.Worksteps.FirstOrDefault(x => x.Name == preferredWorkstepName);
supressUINotifications = true;
workstepComboBox.Items.Clear();
for (int i = 0; i < workflow.Worksteps.Count; i++)
{
workstepComboBox.Items.Add(workflow.Worksteps[i].Name);
}
workstepComboBox.Text = (prefferedWorkstep != null) ? preferredWorkstepName : string.Empty;
supressUINotifications = false;
bool workstepChanged = CurrentWorkstep != prefferedWorkstep;
CurrentWorkstep = prefferedWorkstep;
return workstepChanged;
}
private void workstepComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (supressUINotifications) return;
var oriWorkstep = CurrentWorkstep;
CurrentWorkstep = CurrentWorkflow == null
? null
: CurrentWorkflow.Worksteps.FirstOrDefault<Workstep>(x => x.Name == workstepComboBox.Text);
if (CurrentWorkstep != oriWorkstep)
{
UpdateItems();
ClearBatchNumbers();
Program.LocalSettings.LastWorkstep = CurrentWorkstep.Name;
}
}
/// <summary>
/// Updates screen items (polozky) and currentProcess, currentWorkstep variables.
/// If either process or workstep is null, the screen is icleared.
/// </summary>
/// <param name="process">Process to be used (drawn)</param>
/// <param name="workstep">Workstep to be used (drawn)</param>
/// <returns>true = process or workstep changed, false = no change</returns>
void UpdateItems()
{
if (recordProcessing != null) recordProcessing.StopProcessing();
workstepsOfTheCurrentWorkflow = CurrentWorkflow != null ? CurrentWorkflow.Worksteps : new List<Workstep>();
verifiedWorkstep = null; /// Disable any verification
RedrawItems();
if (CurrentOrder != null)
{
completedGroupBox.Visible = targetGroupBox.Visible = true;
UpdatePiecesCount();
}
else
{
completedGroupBox.Visible = targetGroupBox.Visible = false;
}
if (CurrentWorkflow != null)
{
LoadCodesFromDictionary(CurrentWorkflow.Name, palety);
}
ScanVerificationInfo svi = TracingDB.AnalyzeProcess(dbSession, CurrentWorkflow, CurrentWorkstep);
if (svi != null)
{
verifiedWorkstep = svi.Workstep;
verifiedPart = svi.Part;
verifyReferencePart = svi.VerifyReferencePart;
}
UpdateTitle(); /// Show acrive verification
wplaceRegistration.UpdateRegistration(dbSession,
Program.LocalSettings.WorkplaceId,
Common.GlobalData.CurrentUser.UserName,
"1.2.3.4",
(CurrentWorkflow != null) ? CurrentWorkflow.Name : string.Empty,
(CurrentWorkstep != null) ? CurrentWorkstep.Name : string.Empty,
DateTime.Now + new TimeSpan(8, 0, 0));
if (recordProcessing != null) recordProcessing.StartProcessing();
}
/// <summary>
/// Update main window title after AnalyzeProcesses()
/// </summary>
void UpdateTitle()
{
string title = string.Format("{0} ver. {1} ({2})", Strings.Workplace, Program.Version, Program.LocalSettings.WorkplaceId);
if (verifiedWorkstep != null && verifiedPart != null)
{
title += string.Format(Strings.previous_workflow_step_0_verified_component_1, verifiedWorkstep.Name, verifiedPart.Name);
}
Text = title;
}
/// <summary>
/// Redraw items (polozky) of the currentProcess and currentWorkstep
/// or clear them if there is no current process or workstep.
/// </summary>
void RedrawItems()
{
///
/// Remove existing items (polozky)
///
foreach (var k in komponenty) if (k is IDevice) (k as IDevice).StopDevice();
foreach (var p in palety) if (p is IDevice) (p as IDevice).StopDevice();
komponenty.Clear();
palety.Clear();
flowLayoutPanel1.Controls.Clear();
flowLayoutPanel2.Controls.Clear();
ICheckItem polozka;
if (CurrentWorkstep != null)
{
/// Reference part
if (CurrentWorkstep.ReferencePart != null)
{
if (CurrentWorkstep.ReferencePart.CodeForm == (sbyte)CodeForm.Barcode ||
CurrentWorkstep.ReferencePart.CodeForm == (sbyte)CodeForm.QRCode)
{
polozka = new CheckItems.Barcode(this, CurrentWorkstep.ReferencePart);
polozka.IxPolozky = 1;
komponenty.Add(polozka);
flowLayoutPanel1.Controls.Add(polozka as UserControl);
OptionalySetBlackList(polozka);
}
else if (CurrentWorkstep.ReferencePart.CodeForm == (sbyte)CodeForm.SNGenerator)
{
polozka = new CheckItems.SNGeneratorPrinter(this, CurrentWorkstep.ReferencePart);
polozka.IxPolozky = 1;
komponenty.Add(polozka);
flowLayoutPanel1.Controls.Add(polozka as UserControl);
}
}
/// All other parts
foreach (var p in CurrentWorkstep.Parts)
{
if (komponenty.Count == 1 && p.CodeForm == (sbyte)CodeForm.SerialNr)
{
/// Complete serial number 'part' that is handled by PolozkaDouble => do not create any new control
continue;
}
switch ((CodeForm)p.CodeForm)
{
case CodeForm.SNGenerator:
polozka = new CheckItems.SNGeneratorPrinter(this, p);
break;
case CodeForm.Keyboard:
polozka = new CheckItems.Keyboard(this, p);
break;
case CodeForm.Scale:
RunWeightLimitsWizard(); /// Run wizard to determine weight limits before creating a scale CheckItem
CheckItems.Scale scale = new CheckItems.Scale(this, p);
try { scale.Initialize(); }
catch (Exception) { scale.BackColor = System.Drawing.Color.Red; }
scale.MinWeight = Program.LocalSettings.MinWeight / 1000;
scale.MaxWeight = Program.LocalSettings.MaxWeight / 1000;
polozka = scale;
break;
case CodeForm.DataStream:
CheckItems.S640Stream datastream = new CheckItems.S640Stream(this, p);
try { datastream.Initialize(); }
catch (Exception) { datastream.BackColor = System.Drawing.Color.Red; }
polozka = datastream;
break;
case CodeForm.Barcode:
case CodeForm.QRCode:
default:
polozka = new CheckItems.Barcode(this, p);
break;
}
if (p.CodeLocation == CodeLocation.OnPart)
{
polozka.IxPolozky = komponenty.Count + 1;
komponenty.Add(polozka);
flowLayoutPanel1.Controls.Add(polozka as UserControl);
}
else if (p.CodeLocation == CodeLocation.OnPallet)
{
polozka.IxPolozky = palety.Count + 100;
palety.Add(polozka);
flowLayoutPanel2.Controls.Add(polozka as UserControl);
}
OptionalySetBlackList(polozka);
}
InitializeSNGeneratorPrinter();
}
}
void RunWeightLimitsWizard()
{
while (true)
{
var dr = MessageBox.Show(Strings.Do_you_want_to_use_the_last + Environment.NewLine
+ string.Format(Strings.weight_limits_0g_1g_Q, Program.LocalSettings.MinWeight, Program.LocalSettings.MaxWeight)
+ Environment.NewLine + Program.LocalSettings.WeightOptionsWay,
string.Empty,
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (dr == DialogResult.Yes) return; /// Use the last weight limits stored in Program.LocalSettings
/// Ask how the new weight limits should be determined
var dlg1 = new Forms.WeightLimitsWayDlg();
dlg1.ShowDialog();
switch (dlg1.Way)
{
case Forms.Way.Manually:
/// Enter weight limits manually
var dlg2 = new Forms.WeightLimitsDlg(Program.LocalSettings.MinWeight, Program.LocalSettings.MaxWeight);
if (dlg2.ShowDialog() == DialogResult.OK)
{
Program.LocalSettings.MinWeight = dlg2.MinWeight;
Program.LocalSettings.MaxWeight = dlg2.MaxWeight;
Program.LocalSettings.WeightOptionsWay = dlg2.WeightOptionsWay;
Program.LocalSettings.Save();
}
return;
case Forms.Way.Wizard:
/// Use a wizard to determine the weight limits
var dlg3 = new Forms.WeightLimitsWizardDlg(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\WizardDirTree");
if (dlg3.ShowDialog() == DialogResult.OK)
{
Program.LocalSettings.MinWeight = dlg3.MinWeight;
Program.LocalSettings.MaxWeight = dlg3.MaxWeight;
Program.LocalSettings.WeightOptionsWay = dlg3.WeightOptionsWay;
Program.LocalSettings.Save();
return;
}
else
{
break;
}
case Forms.Way.Measurement:
default:
MessageBox.Show(Strings.Not_implemented_yet);
break;
}
}
}
void ClearBatchNumbers()
{
if (loadedOnce)
{
foreach (var p in palety)
{
p.ClearCode();
}
}
}
/// <summary>
/// Check local settings and optionally set the black list for polozka.
/// </summary>
/// <param name="polozka"></param>
void OptionalySetBlackList(ICheckItem polozka)
{
if (polozka.IxPolozky == Program.LocalSettings.BlackListIx1)
{
BlackList bl = BlackList.FromFile(Program.LocalSettings.BlackListFile1);
if (bl != null) polozka.BlackListedCodes = bl.Codes;
}
else if (polozka.IxPolozky == Program.LocalSettings.BlackListIx2)
{
BlackList bl = BlackList.FromFile(Program.LocalSettings.BlackListFile2);
if (bl != null) polozka.BlackListedCodes = bl.Codes;
}
else if (polozka.IxPolozky == Program.LocalSettings.BlackListIx3)
{
BlackList bl = BlackList.FromFile(Program.LocalSettings.BlackListFile3);
if (bl != null) polozka.BlackListedCodes = bl.Codes;
}
}
/// <summary>
/// Reset idle time measurement
/// </summary>
void ResetIdleTime()
{
lastActivity = DateTime.Now;
}
/// <summary>
/// Get idle time in seconds
/// </summary>
/// <returns>Idle time [s]</returns>
double GetIdleTimeSec()
{
TimeSpan ts = DateTime.Now - lastActivity;
return (int)ts.TotalSeconds;
}
/// <summary>
/// Get time in seconds sinc the last login
/// </summary>
/// <returns>Login time [s]</returns>
double GetLoginTimeSec()
{
TimeSpan ts = DateTime.Now - lastLoginTime;
return (int)ts.TotalSeconds;
}
static TimeSpan oneDay = new TimeSpan(1, 0, 0, 0);
static int logoutDetectionCounter = 0;
///
void runDeviceTimer_Tick(object sender, EventArgs args)
{
try
{
/// Before
foreach (var k in komponenty) if (k is IDevice) (k as IDevice).RunDeviceBefore();
foreach (var p in palety) if (p is IDevice) (p as IDevice).RunDeviceBefore();
/// After
foreach (var k in komponenty) if (k is IDevice) (k as IDevice).RunDeviceAfter();
foreach (var p in palety) if (p is IDevice) (p as IDevice).RunDeviceAfter();
if (++logoutDetectionCounter >= 30)
{
logoutDetectionCounter = 0;
LogoutDetection();
}
}
catch (Exception)
{
}
}
///
void LogoutDetection()
{
TimeSpan smallestTimeDiff = oneDay; /// Smallest time difference from logout times - initialized to one day
if (Program.LocalSettings.LogoutTime1.TimeOfDay != new TimeSpan(0))
{
/// Logout time 1 enabled
TimeSpan ts1 = DateTime.Now.TimeOfDay - Program.LocalSettings.LogoutTime1.TimeOfDay;
if (ts1 < new TimeSpan(0)) ts1 += oneDay;
if (ts1 < smallestTimeDiff) smallestTimeDiff = ts1;
}
if (Program.LocalSettings.LogoutTime2.TimeOfDay != new TimeSpan(0))
{
/// Logout time 2 enabled
TimeSpan ts2 = DateTime.Now.TimeOfDay - Program.LocalSettings.LogoutTime2.TimeOfDay;
if (ts2 < new TimeSpan(0)) ts2 += oneDay;
if (ts2 < smallestTimeDiff) smallestTimeDiff = ts2;
}
if (Program.LocalSettings.LogoutTime3.TimeOfDay != new TimeSpan(0))
{
/// Logout time 3 enabled
TimeSpan ts3 = DateTime.Now.TimeOfDay - Program.LocalSettings.LogoutTime3.TimeOfDay;
if (ts3 < new TimeSpan(0)) ts3 += oneDay;
if (ts3 < smallestTimeDiff) smallestTimeDiff = ts3;
}
int minTimeSec = (int)smallestTimeDiff.TotalSeconds;
if ((minTimeSec < 900) && !isLoggedOut && (GetIdleTimeSec() > 120) && (GetLoginTimeSec() > 2700))
{
logoutButton_Click(null, null);
}
}
public void OnBarcodeReceived(object sender, BarcodeReceivedEventArgs data)
{
ResetIdleTime();
if (BarcodeReceivedHandler == null) return;
try
{
BarcodeReceivedHandler(sender, data);
}
catch (Exception exc)
{
string msg = exc.Message;
// log.Error("BarcodeReceivedHandler(...) failed", e);
}
}
public event EventHandler<BarcodeReceivedEventArgs> BarcodeReceivedHandler;
///
public void BarcodeReceived(object sender, BarcodeReceivedEventArgs data)
{
foreach (var k in komponenty) k.ResetFocus();
foreach (var p in palety) p.ResetFocus();
if (data.Error == PartError.BlacklistedPart)
{
///
/// This is a blacklisted component (s/n in on a blacklist)
///
SetErrorFlag(PartError.BlacklistedPart, Color.DarkOrange);
MessageBox.Show(string.Format("{0}{1}{2}",
Strings.This_part_is_on_a_black_list,
Environment.NewLine,
Strings.Put_the_part_aside),
Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
ResetErrorFlag();
return;
}
else if (data.Error == PartError.WrongPart)
{
///
/// This is a wrong part (s/n does not satisfy criteria)
///
SetErrorFlag(PartError.WrongPart, Color.Red);
MessageBox.Show(Strings.Wrong_part, Strings.Warning, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
ResetErrorFlag();
return;
}
else if (data.Error == PartError.ValueOutOfRange)
{
///
/// Measured value is out of range
///
SetErrorFlag(PartError.ValueOutOfRange, Color.Red);
MessageBox.Show(Strings.Value_out_of_range, Strings.Warning, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
ResetErrorFlag();
return;
}
else if (data.Error == PartError.UnspecifiedError)
{
///
/// Measured value is out of range
///
SetErrorFlag(PartError.UnspecifiedError, Color.Red);
MessageBox.Show(Strings.Unspecified_error, Strings.Warning, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
ResetErrorFlag();
return;
}
else if (data.CodeLocation == CodeLocation.OnPart)
{
///
/// This is a uniqueue part code ==> process it
///
if (data.IxPolozky > 0 && data.IxPolozky < komponenty.Count)
{
///
/// This is not the last part ==> set focus onto the next part to be scanned
///
komponenty[data.IxPolozky].SetFocus();
return;
}
///
/// This is the last part with uniqueue code (on the left side of the screen)
///
if(IsAnyFieldEmpty())
{
///
/// At least one of fields is empty ==> error
///
SetErrorFlag(PartError.FieldEmpty, Color.Yellow);
MessageBox.Show(Strings.Some_fileds_are_empty_Fill_them_in_please,
Strings.Warning, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
ResetErrorFlag();
return;
}
if (errorFlag != PartError.None)
{
///
/// There is another error (see errorFlag)
///
SetErrorFlag(PartError.UnspecifiedError, Color.Red);
MessageBox.Show(Strings.Remove_errors_please,
Strings.Warning, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
ResetErrorFlag();
return;
}
///
/// Everything is OK so far ==> verify previous records
///
if (verifiedWorkstep != null && verifiedPart != null)
{
string verifiedCode = string.Empty;
for (int i = 0; i < komponenty.Count; i++)
{
if (komponenty[i].Part == verifiedPart)
{
verifiedCode = komponenty[i].ScannedCode;
break;
}
}
int codeIx = 1;
///
/// Find reference records with s/n of the part to be verified
///
IQueryOver<ReferenceRecord, ReferenceRecord> query = dbSession.QueryOver<ReferenceRecord>();
switch (codeIx)
{
default:
case 1: query = query.Where(rr => (rr.Code1 == verifiedCode)); break;
case 2: query = query.Where(rr => (rr.Code2 == verifiedCode)); break;
case 3: query = query.Where(rr => (rr.Code3 == verifiedCode)); break;
case 4: query = query.Where(rr => (rr.Code4 == verifiedCode)); break;
}
var refRecords = query.OrderBy(rr => rr.Timestamp).Desc.List();
bool verificationPassed = false;
if (refRecords.Count > 0 && refRecords[0].StepRecords != null)
{
foreach (var r in refRecords[0].StepRecords)
{
if (r.Workstep == verifiedWorkstep.Name)
{
/// This is the last good record from a verified workstep
verificationPassed = true;
break;
}
}
}
if (!verificationPassed)
{
SetErrorFlag(PartError.PrviousRecordMissing, Color.Blue);
MessageBox.Show(Strings.Record_from_the_previous_workflow_step_is_missing,
Strings.Warning,
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
ResetErrorFlag();
return;
}
}
#if false
saveAllCodesButton.Enabled = true;
saveAllCodesButton.Focus();
#else
SaveCodes();
#endif
}
}
void SaveCodes()
{
ResetIdleTime();
if (Program.LocalSettings.Mode == Mode.Test || komponenty.Count == 0)
{
ColorFlash(this, new ColorFlashEventArgs(true, Color.Green, Program.LocalSettings.OkFlashDuration, Strings.Test));
return;
}
if (IsAnyFieldEmpty())
{
SetErrorFlag(PartError.FieldEmpty, Color.Yellow);
MessageBox.Show(Strings.Some_fileds_are_empty_Fill_them_in_please,
Strings.Warning,
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
ResetErrorFlag();
return;
}
if (errorFlag != PartError.None)
{
MessageBox.Show(Strings.Remove_errors_please,
Strings.Warning,
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
return;
}
///
/// Save records to MySQL
///
int result = 0; /// OK (default)
bool wasAlreadyTested = false;
bool componentsSaved = true;
bool successfullySaved = false;
///
ITransaction transaction = dbSession.BeginTransaction();
try
{
CheckItems.SNGeneratorPrinter snGenerator = (komponenty[0] as CheckItems.SNGeneratorPrinter); /// null when there is no S/N generator
///
/// Handle serial number generators
///
if (snGenerator != null && komponenty[0].Part.CodeForm == (sbyte)CodeForm.SNGenerator)
{
if (CurrentOrder == null)
{
/// The 1st item is a S/N generator but no order is selected ==> Error
komponenty[0].ScannedCode = "ERROR";
throw new Exception("No order selected");
}
///
/// Negotiate and update the generated serial number
///
string generatedCode;
var orderInfoState = snGenerator.NegotiateSerialNr(CurrentOrder, CurrentWorkflow, CurrentWorkstep,
out generatedCode, true, dbSession);
if (orderInfoState == OrderProgress.InProgress || orderInfoState == OrderProgress.Overproduction)
{
komponenty[0].ScannedCode = generatedCode;
}
else if (orderInfoState == OrderProgress.Completed)
{
komponenty[0].ScannedCode = "END";
throw new Exception("END");
}
else //if (orderInfoState == OrderProgress.Error)
{
/// An unexpected error
throw new Exception("No order selected");
}
}
///
/// Select or create a reference record
///
var refRecords = dbSession.QueryOver<ReferenceRecord>()
.Where(x => x.Code1 == komponenty[0].ScannedCode)
.List();
/// Handle or prevent reference record duplicity
if (refRecords.Count > 1) throw new Exception("Unexpected error: two identical codes in the database");
else if (snGenerator != null && refRecords.Count == 1) throw new Exception("A duplicit code was generated");
ReferenceRecord refRecord = (refRecords.Count == 1) ? refRecords[0]
: new ReferenceRecord(CurrentOrder.POName, CurrentWorkflow.Name, komponenty[0].ScannedCode);
/// Handle case of a double check item - update refRecord.Code2
if (komponenty[0] is IDoubleCheckItem)
{
refRecord.Code2 = (komponenty[0] as IDoubleCheckItem).ScannedCode2;
}
/// Prepare new records
var records = new List<Record>();
var stepRecord = PrepareRecords(refRecord, result, records);
/// De-referene existing recors with the same part name, a more recent record exists now
foreach (var oriRecord in refRecord.Records)
{
var overridingRecord = records.FirstOrDefault(x => x.Name == oriRecord.Name);
if (overridingRecord != null)
{
oriRecord.ReferenceRecord = null;
dbSession.SaveOrUpdate(oriRecord);
}
}
/// Update the reference record
refRecord.StepRecords.Add(stepRecord);
foreach (var rcrd in records) refRecord.Records.Add(rcrd);
if (stepRecord.Timestamp > refRecord.Timestamp) refRecord.Timestamp = stepRecord.Timestamp;
dbSession.SaveOrUpdate(refRecord);
log.InfoFormat(" ReferenceRecord : {0}", refRecord);
/// Save new records
dbSession.SaveOrUpdate(stepRecord);
log.InfoFormat(" StepRecord : {0}", stepRecord);
foreach (var rcrd in records)
{
dbSession.SaveOrUpdate(rcrd);
log.InfoFormat(" Record : {0}", rcrd);
}
transaction.Commit();
successfullySaved = true;
}
catch (Exception exc)
{
componentsSaved = false;
log.ErrorFormat("MySQL database transaction rolled back, data not comitted: {0}", exc.Message);
transaction.Rollback();
}
/// In case of 'SNGeneratorPrinter' print a label after saving records successfully
if (komponenty[0].Part.CodeForm == (sbyte)CodeForm.SNGenerator && successfullySaved)
{
var matrix = new DataMatrix4Net.DataMatrix(komponenty[0].ScannedCode, DataMatrix4Net.SymbolSize.SquareAuto);
new Printers.DataMatrixAndTextPrintDoc(matrix.Matrix, komponenty[0].ScannedCode.Replace("4V", "\n")).Print();
}
/// Retrieve produced pieces count and compare with the target count
bool targetCountReached = UpdatePiecesCount();
if (wasAlreadyTested && !componentsSaved)
{
ColorFlash(this, new ColorFlashEventArgs(false, Color.Red, Program.LocalSettings.NokFlashDuration, Strings.PCB_was_tested_already, Strings.Components_were_not_saved_to_Oracle));
}
else if (wasAlreadyTested)
{
ColorFlash(this, new ColorFlashEventArgs(false, Color.Red, Program.LocalSettings.NokFlashDuration, Strings.PCB_was_tested_already));
}
else if (!componentsSaved)
{
ColorFlash(this, new ColorFlashEventArgs(false, Color.Red, Program.LocalSettings.NokFlashDuration, Strings.Components_were_not_saved_to_Oracle));
}
else if (targetCountReached)
{
ColorFlash(this, new ColorFlashEventArgs(false, Color.Yellow, Program.LocalSettings.NokFlashDuration, Strings.Target_count_reached));
}
else
{
ColorFlash(this, new ColorFlashEventArgs(true, Color.Green, Program.LocalSettings.OkFlashDuration));
}
UpdateAndSaveStoredCodesDictionary(CurrentWorkflow, palety);
///
/// Find out whether the process has been changed, prepare UI
///
orders = ReadOrders(dbSession);
UpdateOrderCombo(orders, orderComboBox.Text);
workflows = ReadReleasedActiveProcesses(dbSession);
if (UpdateWorkflowCombo(workflows, workflowComboBox.Text))
{
if (UpdateWorkstepCombo(CurrentWorkflow, workstepComboBox.Text))
{
UpdateItems();
}
}
///
/// Clear all components/items, set focus to the first field
///
foreach (var k in komponenty)
{
k.ClearCode();
k.ResetFocus();
}
if (komponenty.Count > 0)
{
komponenty[0].SetFocus();
}
if ((recordProcessing != null) && !wasAlreadyTested && componentsSaved)
{
/// Activate thirdparty program window
Utils.Activate(Program.LocalSettings.WindowClassNameToActivate);
}
}
/// <summary>
/// Prepare records and a step record with scanned/generated/collected information
/// </summary>
/// <param name="refRecord">Reference record</param>
/// <param name="result">Result: 0=OK, otherwise a non-zero error code</param>
/// <param name="records">List of records to be updated (initially an empty list)</param>
/// <returns>Step record</returns>
StepRecord PrepareRecords(ReferenceRecord refRecord, int result, IList<Record> records)
{
var stepRecord = new StepRecord(refRecord, CurrentWorkstep.Name, workplaceTextBox.Text, workerTextBox.Text, result);
int firstNoRefCompIx = (CurrentWorkstep.ReferencePart == null) ? 0 : (komponenty[0] is IDoubleCheckItem) ? 2 : 1;
for (int i = firstNoRefCompIx; i < komponenty.Count; i++)
{
if (komponenty[i] is CheckItems.S640Stream)
{
/// eRegister number from data stream ... update refRecord.Code2
refRecord.Code2 = komponenty[i].ScannedCode;
}
else
{
records.Add(new Record(refRecord, stepRecord, komponenty[i].Part.Name, komponenty[i].ScannedCode,
result, komponenty[i].Part.OraDBType));
}
}
for (int i = 0; i < palety.Count; i++)
{
records.Add(new Record(refRecord, stepRecord, palety[i].Part.Name, palety[i].ScannedCode,
result, komponenty[i].Part.OraDBType));
}
return stepRecord;
}
void SetErrorFlag(PartError errorCode, Color backColor)
{
if (errorFlag == PartError.None)
{
Console.Beep(ErrorBeepFrequency, ErrorBeepDuration);
errorFlag = errorCode;
BackColor = backColor;
saveAllCodesButton.Enabled = false;
failedCheckBox.Checked = true;
}
}
void ResetErrorFlag()
{
if (errorFlag != PartError.None)
{
errorFlag = PartError.None;
BackColor = SystemColors.Control;
saveAllCodesButton.Enabled = true;
failedCheckBox.Checked = false;
foreach (var k in komponenty) k.ClearCode(); ;
if (komponenty.Count > 0) komponenty[0].SetFocus();
}
}
private void resetErrorStateButton_Click(object sender, EventArgs e)
{
ResetErrorFlag();
}
public void OnFocusPressed(object sender, FocusPressedEventArgs data)
{
ResetIdleTime();
if (FocusPressedHandler == null) return;
try
{
FocusPressedHandler(sender, data);
}
catch (Exception)
{
// log.Error("FocusPressedHandler(...) failed", e);
}
}
public event EventHandler<FocusPressedEventArgs> FocusPressedHandler;
///
public void FocusPressed(object sender, FocusPressedEventArgs data)
{
foreach (var k in komponenty) k.ResetFocus();
foreach (var p in palety) p.ResetFocus();
if ((data.IxPolozky >= 1) && (data.IxPolozky <= komponenty.Count))
{
komponenty[data.IxPolozky - 1].SetFocus();
}
else if ((data.IxPolozky >= 100) && (data.IxPolozky - 100 < palety.Count))
{
palety[data.IxPolozky - 100].SetFocus();
}
}
private void clearButton_Click(object sender, EventArgs e)
{
ResetIdleTime();
foreach (var k in komponenty)
{
k.ClearCode();
k.ResetFocus();
}
foreach (var p in palety)
{
p.ResetFocus();
}
InitializeSNGeneratorPrinter();
}
void InitializeSNGeneratorPrinter()
{
if (komponenty.Count > 0 &&
komponenty[0] is CheckItems.SNGeneratorPrinter &&
komponenty[0].Part.CodeForm == (sbyte)CodeForm.SNGenerator &&
CurrentOrder != null)
{
string generatedCode;
var rslt = (komponenty[0] as CheckItems.SNGeneratorPrinter).NegotiateSerialNr(CurrentOrder, CurrentWorkflow, CurrentWorkstep, out generatedCode);
komponenty[0].ScannedCode = (rslt == OrderProgress.Error) ? "ERROR"
: (rslt == OrderProgress.Completed) ? "END"
: generatedCode;
}
if (komponenty.Count > 1 &&
komponenty[0] is CheckItems.SNGeneratorPrinter &&
komponenty[0].Part.CodeForm == (sbyte)CodeForm.SNGenerator)
{
komponenty[1].SetFocus();
}
else if (komponenty.Count > 0)
{
komponenty[0].SetFocus();
}
}
private void saveAllCodesButton_Click(object sender, EventArgs e)
{
if (isSNPrinting) saveAllCodesButton.Enabled = false;
SaveCodes();
}
/// <summary>
/// Update the dictionary of scanned codes of palettes and save it.
/// Dictionary contains pairs (process.Name, '~'-separated strings of scanned codes).
/// Update codes of parts with CodeType == CodeType.Silicon and shared between workflows as well.
/// </summary>
/// <param name="processName">Current workflow name</param>
/// <param name="palety">A list of palettes</param>
/// <returns>true = LocalSettings updated and saved</returns>
bool UpdateAndSaveStoredCodesDictionary(Process process, IList<ICheckItem> palety)
{
if (process == null || string.IsNullOrEmpty(process.Name) || palety == null || palety.Count == 0)
{
return false;
}
StringBuilder sbSilicon = new StringBuilder();
StringBuilder sb = new StringBuilder();
bool firstSilicon = true;
bool first = true;
foreach (var p in palety)
{
if (p.Part.CodeType == (sbyte)CodeType.Silicon)
{
if (!firstSilicon) sbSilicon.Append("~");
firstSilicon = false;
sbSilicon.Append(p.ScannedCode);
}
else
{
if (!first) sb.Append("~");
first = false;
sb.Append(p.ScannedCode);
}
}
string value = sb.ToString();
string key = process.Name;
string storedValue;
if (!Program.LocalSettings.LastData.TryGetValue(key, out storedValue))
{
Program.LocalSettings.LastData.Add(key, value);
Program.LocalSettings.LastSiliconData = sbSilicon.ToString();
Program.LocalSettings.Save();
return true;
}
else if (storedValue != value)
{
Program.LocalSettings.LastData[key] = value;
Program.LocalSettings.LastSiliconData = sbSilicon.ToString();
Program.LocalSettings.Save();
return true;
}
else if (sbSilicon.ToString() != Program.LocalSettings.LastSiliconData)
{
Program.LocalSettings.LastSiliconData = sbSilicon.ToString();
Program.LocalSettings.Save();
return true;
}
return false;
}
/// <summary>
/// Load codes of palettes from the dictionary.
/// Dictionary contains pairs (process.Name, '~'-separated strings of scanned codes).
/// </summary>
/// <param name="processName">Current process name</param>
/// <param name="palety">A list of palettes</param>
void LoadCodesFromDictionary(string processName, IList<ICheckItem> palety)
{
if (string.IsNullOrEmpty(processName) || palety == null) return;
string[] loadedCodes = new string[0];
string value;
if (Program.LocalSettings.LastData.TryGetValue(processName, out value))
{
loadedCodes = value.Split(new char[] { '~' });
}
string[] loadedSiliconCodes = new string[0];
try
{
#if !VER3
SiliconBatchNumbers.SiliconBatchNumbers sbn;
if (null != (sbn = SiliconBatchNumbers.SiliconBatchNumbers.Load("N:\\iPERL vyroba Stara Tura\\software\\sarze silikonu\\Cfg\\silicon.xml")) ||
null != (sbn = SiliconBatchNumbers.SiliconBatchNumbers.Load("N:\\iPERL vyroba Stara Tura\\software\\sarze silikonu\\Cfg\\silicon.backup.xml")))
{
/// silicon batch numbers loaded from silicon.backup.xml
loadedSiliconCodes = sbn.GetSiliconBatchNumbers(Program.LocalSettings.WorkplaceId);
}
else
#endif
{
loadedSiliconCodes = new string[0];
}
}
catch (Exception)
{
loadedSiliconCodes = new string[0];
}
int ix = 0;
int ixSilicon = 0;
for (int i = 0; i < palety.Count; i++)
{
if ((palety[i].Part.CodeType == (sbyte)CodeType.Silicon) && (ixSilicon < loadedSiliconCodes.Length))
{
palety[i].ScannedCode = loadedSiliconCodes[ixSilicon++];
}
if (!string.IsNullOrEmpty(palety[i].Part.DefaultCode))
{
palety[i].ScannedCode = palety[i].Part.DefaultCode;
ix++;
}
else if (ix < loadedCodes.Length)
{
palety[i].ScannedCode = loadedCodes[ix++];
}
else
{
palety[i].ClearCode();
}
}
}
/// <summary>
/// Returns true if any field is empty
/// </summary>
private bool IsAnyFieldEmpty()
{
foreach (var k in komponenty)
{
if (k.ScannedCode == string.Empty) return true;
}
foreach (var p in palety)
{
if (p.ScannedCode == string.Empty) return true;
}
return false;
}
/// <summary>
/// Clear fields in the left pane and set focus to the beginning
/// </summary>
private void ClearFieldsResetFocus()
{
foreach (var k in komponenty)
{
k.ClearCode();
k.ResetFocus();
}
foreach (var p in palety)
{
p.ResetFocus();
}
komponenty[0].SetFocus();
}
private void WorkplaceDlg_FormClosing(object sender, FormClosingEventArgs e)
{
bool anyChange = false;
UpdateAndSaveStoredCodesDictionary(CurrentWorkflow, palety);
if ((CurrentWorkflow != null) && (Program.LocalSettings.LastWorkflow != CurrentWorkflow.Name))
{
Program.LocalSettings.LastWorkflow = CurrentWorkflow.Name;
anyChange = true;
}
if ((CurrentWorkstep != null) && (Program.LocalSettings.LastWorkstep != CurrentWorkstep.Name))
{
Program.LocalSettings.LastWorkstep = CurrentWorkstep.Name;
anyChange = true;
}
if (anyChange) Program.LocalSettings.Save();
if (recordProcessing != null) recordProcessing.StopProcessing();
wplaceRegistration.UnregisterWorkplace(dbSession);
}
private void configureButton_Click(object sender, EventArgs e)
{
LoginAndConfigure();
}
private void LoginAndConfigure()
{
ResetIdleTime();
if (new LoginDlg(Program.SettingsAccessLevel).ShowDialog() == DialogResult.OK)
{
string oriWorkplace = Program.LocalSettings.WorkplaceId;
if (Configure() == DialogResult.OK)
{
orders = ReadOrders(dbSession);
UpdateOrderCombo(orders, orderComboBox.Text);
workflows = ReadReleasedActiveProcesses(dbSession);
UpdateWorkflowCombo(workflows, workflowComboBox.Text);
wplaceRegistration.UpdateRegistration(dbSession,
Program.LocalSettings.WorkplaceId,
Common.GlobalData.CurrentUser.UserName,
"1.2.3.4",
(CurrentWorkflow != null) ? CurrentWorkflow.Name : string.Empty,
(CurrentWorkstep != null) ? CurrentWorkstep.Name : string.Empty,
DateTime.Now + new TimeSpan(8, 0, 0));
}
}
}
/// <summary>
/// Show settings dialog, return DialogResult.OK when any option changed.
/// </summary>
/// <returns>true on any change in Program.LoclSettings</returns>
private DialogResult Configure()
{
var dlg = new Forms.SettingsDlg(Program.LocalSettings);
if (dlg.ShowDialog() == DialogResult.OK)
{
Program.LocalSettings.Save();
return DialogResult.OK;
}
else
{
return DialogResult.Cancel;
}
}
/// <summary>
/// Called from the state machine when an operation forces a modeless dialog close.
/// </summary>
public static void ColorFlash(object sender, ColorFlashEventArgs args)
{
if (ColorFlashHandler == null) return;
try { ColorFlashHandler(sender, args); }
catch (Exception) { }
}
public static event EventHandler<ColorFlashEventArgs> ColorFlashHandler;
private static System.Windows.Forms.Timer colorFlashDurationTimer;
void OnColorFlash(object sender, ColorFlashEventArgs args)
{
// start timer here
if (colorFlashDurationTimer == null)
{
colorFlashDurationTimer = new System.Windows.Forms.Timer();
colorFlashDurationTimer.Tick += (s, e) => { ColorFlashAction(); };
}
BackColor = args.Color;
if (args.Message1 != null) { label1.Text = args.Message1; }
if (args.Message2 != null) { label2.Text = args.Message2; }
colorFlashDurationTimer.Interval = args.Interval;
colorFlashDurationTimer.Start();
if (args.OK)
{
Console.Beep();
}
else
{
Console.Beep(ErrorBeepFrequency, ErrorBeepDuration);
}
}
// Specify what you want to happen when the Elapsed event is
// raised.
private void ColorFlashAction()
{
BackColor = SystemColors.Control;
label1.Text = string.Empty;
label2.Text = string.Empty;
colorFlashDurationTimer.Stop();
colorFlashDurationTimer.Enabled = false;
if (isSNPrinting)
{
saveAllCodesButton.Enabled = true;
saveAllCodesButton.Focus();
}
}
private void logoutButton_Click(object sender, EventArgs e)
{
workerTextBox.Text = string.Empty;
isLoggedOut = true;
///
/// User login
///
while (true)
{
DialogResult dr;
switch (Program.LocalSettings.LocalWorkplacesCount)
{
default:
case 1:
dr = new LoginDlg().ShowDialog();
break;
case 2:
dr = new DoubleLoginDlg(Program.LocalSettings.LocalWorkplace1, Program.LocalSettings.LocalWorkplace2).ShowDialog();
break;
case 3:
dr = new TripleLoginDlg(Program.LocalSettings.LocalWorkplace1, Program.LocalSettings.LocalWorkplace2, Program.LocalSettings.LocalWorkplace3).ShowDialog();
break;
}
if (dr == DialogResult.OK) break;
}
workerTextBox.Text = Common.GlobalData.GetCurrentUserName();
lastLoginTime = DateTime.Now;
isLoggedOut = false;
ClearBatchNumbers();
wplaceRegistration.UpdateRegistration(dbSession,
Program.LocalSettings.WorkplaceId,
Common.GlobalData.CurrentUser.UserName,
"1.2.3.4",
(CurrentWorkflow != null) ? CurrentWorkflow.Name : string.Empty,
(CurrentWorkstep != null) ? CurrentWorkstep.Name : string.Empty,
DateTime.Now + new TimeSpan(8, 0, 0));
}
private void refreshButton_Click(object sender, EventArgs e)
{
supressUINotifications = true;
orders = ReadOrders(dbSession);
UpdateOrderCombo(orders, orderComboBox.Text);
workflows = ReadReleasedActiveProcesses(dbSession);
if (UpdateWorkflowCombo(workflows, workflowComboBox.Text))
{
if (UpdateWorkstepCombo(CurrentWorkflow, workstepComboBox.Text))
{
UpdateItems();
}
}
}
private void ManageCheckGroupBox(CheckBox chk, GroupBox grp)
{
/// Make sure the CheckBox isn't in the GroupBox. This will only happen the first time.
if (chk.Parent == grp)
{
grp.Parent.Controls.Add(chk); /// Reparent the CheckBox so it's not in the GroupBox.
chk.Location = new Point(chk.Left + grp.Left, chk.Top + grp.Top); /// Adjust the CheckBox's location.
chk.BringToFront(); /// Move the CheckBox to the top of the stacking order.
}
/// Enable or disable the GroupBox.
grp.Enabled = chk.Checked;
}
private void batchesCheckBox_CheckedChanged(object sender, EventArgs e)
{
ManageCheckGroupBox(batchesCheckBox, batchesGroupBox);
}
private void orderComboBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '\r' && orderComboBox.Enabled)
{
/// Enter key was pressed, check whether orderComboBox contains a valid order number
orderComboBox_SelectedIndexChanged(sender, e);
}
}
private void orderComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
/// Check whether orderComboBox contains a valid order number
/// Check
for (int i = 0; i < predefinedOrders.Length; i++)
{
if (predefinedOrders[i] == orderComboBox.Text)
{
CurrentOrder = AllOrders.FirstOrDefault<OrderInfo>(x => x.POName == (i + 1).ToString("D7"));
/// The following replaces UpdatePiecesCount() call
targetGroupBox.Visible = false;
completedGroupBox.Visible = false;
completedGroupBox.BackColor = SystemColors.Control;
workflowComboBox.Enabled = true;
clearButton_Click(null, null);
return;
}
}
int orderNr;
OrderInfo order;
///
if (string.IsNullOrEmpty(orderComboBox.Text) ||
orderComboBox.Text.Length != 7 ||
!int.TryParse(orderComboBox.Text, out orderNr) ||
orderNr <= Cnst.MaxPredefinedOrderNr ||
(order = orders.FirstOrDefault(x => x.POName == orderComboBox.Text)) == null)
{
CurrentOrder = null;
workflowComboBox.Enabled = true;
}
else
{
CurrentOrder = order;
if (UpdateWorkflowCombo(workflows, order.Workflow))
{
if (UpdateWorkstepCombo(CurrentWorkflow, workplaceTextBox.Text))
{
UpdateItems();
ClearBatchNumbers();
}
}
workflowComboBox.Enabled = false;
InitializeSNGeneratorPrinter();
}
UpdatePiecesCount();
}
/// <summary>
/// Determine the next base number for the specified number generator
/// </summary>
/// <param name="allOrders">All orders (incl. OrderState.Finished ones)</param>
/// <param name="nrGeneratorIx">Number generator index (0 .. Cnst.NrGeneratorsCount - 1)</param>
/// <returns>Next base number</returns>
public int GetNextBaseNr(IList<OrderInfo> allOrders, int nrGeneratorIx)
{
int nextBaseNr = 0;
foreach (var o in allOrders)
{
int baseNr;
switch (nrGeneratorIx)
{
default:
case 0: baseNr = o.BaseNr1; break;
case 1: baseNr = o.BaseNr2; break;
case 2: baseNr = o.BaseNr3; break;
case 3: baseNr = o.BaseNr4; break;
case 4: baseNr = o.BaseNr5; break;
}
if (baseNr + o.PiecesCount + Cnst.ExtraPieces > nextBaseNr)
{
nextBaseNr = Math.Max(baseNr + o.PiecesCount + Cnst.ExtraPieces, Cnst.MinGeneratedNr);
}
}
return nextBaseNr;
}
private void orderComboBox_GotFocus(object sender, System.EventArgs e)
{
orderLabel.ForeColor = Color.White;
orderLabel.BackColor = Color.DarkBlue;
}
private void orderComboBox_LostFocus(object sender, System.EventArgs e)
{
orderLabel.ForeColor = SystemColors.ControlText;
orderLabel.BackColor = SystemColors.Control;
}
private void orderLabel_Click(object sender, EventArgs e)
{
orderComboBox.Focus();
}
}
}