Workplace...S640Stream : New evaluation, Green/yellow progress bar, Interval 400ms, ver. 3.1.19

This commit is contained in:
Milan Hanajik 2023-05-26 10:31:02 +02:00
parent 5b9156d670
commit b4f41a2f1f
7 changed files with 210 additions and 103 deletions

View File

@ -0,0 +1,28 @@
using System.Drawing;
using System.Windows.Forms;
namespace Workplace.CheckItems
{
public class MyProgressBar : ProgressBar
{
public int ColorId = 0;
public MyProgressBar()
{
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
Rectangle rec = e.ClipRectangle;
rec.Width = (int)(rec.Width * ((double)Value / Maximum)) - 4;
if(ProgressBarRenderer.IsSupported)
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, e.ClipRectangle);
rec.Height = rec.Height - 4;
Brush brush = (ColorId == 1) ? Brushes.Yellow : (ColorId == 2) ? Brushes.Red : Brushes.Green;
e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);
}
}
}

View File

@ -35,6 +35,7 @@
this.descriptionMaterialuLabel = new System.Windows.Forms.Label();
this.pcbNumberTextBox = new System.Windows.Forms.TextBox();
this.pcbNumberLabel = new System.Windows.Forms.Label();
this.pcbNumberProgressBar = new MyProgressBar();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
@ -95,10 +96,18 @@
this.pcbNumberLabel.TabIndex = 8;
this.pcbNumberLabel.Text = "PCB Number";
//
// pcbNumberProgressBar
//
this.pcbNumberProgressBar.Location = new System.Drawing.Point(241, 65);
this.pcbNumberProgressBar.Name = "pcbNumberProgressBar";
this.pcbNumberProgressBar.Size = new System.Drawing.Size(227, 19);
this.pcbNumberProgressBar.TabIndex = 9;
//
// S640Stream
//
this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 24F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.pcbNumberProgressBar);
this.Controls.Add(this.pcbNumberLabel);
this.Controls.Add(this.pcbNumberTextBox);
this.Controls.Add(this.descriptionMaterialuLabel);
@ -123,5 +132,6 @@
private System.Windows.Forms.Label descriptionMaterialuLabel;
private System.Windows.Forms.TextBox pcbNumberTextBox;
private System.Windows.Forms.Label pcbNumberLabel;
private MyProgressBar pcbNumberProgressBar;
}
}

View File

@ -1,19 +1,23 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
/// Copyright (c) 2020-2023 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Windows.Forms;
using log4net;
using SharedDatabase.Entities;
using System.Drawing;
namespace Workplace.CheckItems
{
public partial class S640Stream : UserControl, IDevice, ICheckItem
{
const Int64 MaxDropoutTime = 500; /// ms
const Int64 MinHoldTime = 2500; /// ms
const Int64 MinBreakTime = 10000; /// ms
private static readonly ILog log = LogManager.GetLogger(typeof(S640Stream));
public override string ToString()
@ -21,6 +25,7 @@ namespace Workplace.CheckItems
return string.Format("S640Stream: {0} {1}", IxPolozky, Part.Name);
}
///
/// Check item related variables
///
@ -44,29 +49,36 @@ namespace Workplace.CheckItems
///
SerialPort serialPort; /// Used in DebugMode.Normal
const int FramesBufferSize = 32; /// 8 sec @ 4 Hz
S640.DatastreamFrame[] optoData;
int optoDataIx;
string partOfTelegram; /// Data unprocessed by ReadDatastream(...), contains incomplete frame
Int64 currentRawVolumeUnwrapped;
Int64 currentRawTimeUnwrapped;
S640.DatastreamFrame frame = new S640.DatastreamFrame();
char[] pcbNrStr = new char[12];
char[] radioAddrStr = new char[10];
///
Int64 validPcbNumber;
Int64 validRadioAddress;
Int64 firstValidTime;
Int64 lastValidTime;
///
Int64 currentPcbNr;
Int64 currentRadioAddr;
///
/// PCB Number and Radio address from data stream
///
public Int64 PcbNumber;
public Int64 RadioAddress;
///
IList<S640.PcbnrRadioaddrWeight> prwList;
Int64 lastPcbNumber;
Int64 lastNonzeroPcbNumber;
Int64 lastSentNonzeroPcbNumber;
S640Stream()
{
InitializeComponent();
BlackListedCodes = new List<string>();
prwList = new List<S640.PcbnrRadioaddrWeight>();
}
/// <summary> Empty implementation, might be overriden in derived classes </summary>
@ -90,18 +102,16 @@ namespace Workplace.CheckItems
public void Initialize()
{
partOfTelegram = string.Empty;
currentRawVolumeUnwrapped = 0;
currentRawTimeUnwrapped = 0;
validPcbNumber = (long)-1;
validRadioAddress = (long)-1;
firstValidTime = 0;
lastValidTime = 0;
partOfTelegram = string.Empty;
/// Allocate memory for opto-data from iPerl
optoData = new S640.DatastreamFrame[FramesBufferSize];
for (int i = 0; i < FramesBufferSize; i++)
{
optoData[i] = new S640.DatastreamFrame { DateTime = DateTime.MinValue };
}
optoDataIx = 0;
sendPcbNr = false;
lastSentNonzeroPcbNumber = (long)-1;
/// Prepare serial port
string comPortName = string.Format("COM{0}", Program.LocalSettings.ScaleSerialPort);
@ -112,64 +122,84 @@ namespace Workplace.CheckItems
log.FatalFormat("{0} initialized: {1}", Name, this);
}
public void ClearCode() { }
public void SubmitCode(string code) { }
bool hasFocus;
bool sendLastPcbNr;
bool sendPcbNr;
private void setFocusButton_Click(object sender, EventArgs e)
{
if (!hasFocus && !sendLastPcbNr && PcbNumber != 0 && PcbNumber != lastNonzeroPcbNumber)
setFocusButton.Text = ">";
if (!hasFocus && !sendPcbNr && PcbNumber != 0 && PcbNumber != lastSentNonzeroPcbNumber)
{
lastNonzeroPcbNumber = PcbNumber;
sendLastPcbNr = true;
sendPcbNr = true;
}
hasFocus = true;
setFocusButton.Text = ">";
parent.OnFocusPressed(this, new FocusPressedEventArgs(IxPolozky, Part.CodeLocation));
parent.OnFocusPressed(this, new FocusPressedEventArgs(IxPolozky, Part.CodeLocation));
}
public void ResetFocus()
{
hasFocus = false;
setFocusButton.Text = "";
hasFocus = false;
}
public void SetFocus()
{
if (!hasFocus && !sendLastPcbNr && PcbNumber != 0 && PcbNumber != lastNonzeroPcbNumber)
setFocusButton.Text = ">";
if (!hasFocus && !sendPcbNr && PcbNumber != 0 && PcbNumber != lastSentNonzeroPcbNumber)
{
lastNonzeroPcbNumber = PcbNumber;
sendLastPcbNr = true;
sendPcbNr = true;
}
hasFocus = true;
setFocusButton.Text = ">";
}
public void RunDeviceBefore()
{
lastPcbNumber = PcbNumber;
ReadDatastream();
ProcessBuffer_UpdatePcbNrAndRA();
pcbNumberTextBox.Text = (PcbNumber != 0) ? PcbNumber.ToString() : string.Empty; /// Always displayed
//if (sendLastPcbNr)
//{
// sendLastPcbNr = false;
// parent.OnBarcodeReceived(this, new BarcodeReceivedEventArgs(lastNonzeroPcbNumber.ToString(), IxPolozky,
// Part.CodeLocation, PartError.None));
//}
//
//if (hasFocus && PcbNumber != 0 && PcbNumber != lastNonzeroPcbNumber)
if (PcbNumber != 0 && PcbNumber != lastNonzeroPcbNumber)
/// Send if required
if (sendPcbNr)
{
lastNonzeroPcbNumber = PcbNumber;
parent.OnBarcodeReceived(this, new BarcodeReceivedEventArgs(PcbNumber.ToString(), IxPolozky,
Part.CodeLocation, PartError.None));
lastSentNonzeroPcbNumber = PcbNumber;
sendPcbNr = false;
if (PcbNumber > 0)
{
parent.OnBarcodeReceived(this,
new BarcodeReceivedEventArgs(PcbNumber.ToString(), IxPolozky, Part.CodeLocation, PartError.None));
}
}
ReadDatastream();
if (hasFocus && PcbNumber != 0 && PcbNumber != lastSentNonzeroPcbNumber)
{
/// This control owned focus and the PcbNumber became valid
sendPcbNr = true;
}
/// Send if required
if (sendPcbNr)
{
lastSentNonzeroPcbNumber = PcbNumber;
sendPcbNr = false;
if (PcbNumber > 0)
{
parent.OnBarcodeReceived(this,
new BarcodeReceivedEventArgs(PcbNumber.ToString(), IxPolozky, Part.CodeLocation, PartError.None));
}
}
/// Update UI
pcbNumberTextBox.Text = (currentPcbNr > 0) ? currentPcbNr.ToString() : string.Empty; /// Always displayed
///
int denominator = (currentPcbNr == (Int64)(-1)) ? (int)MinBreakTime : (int)MinHoldTime;
int numerator = Math.Min(Math.Max(0,
Convert.ToInt32((currentPcbNr == (Int64)(-1)) ? MinBreakTime - lastValidTime + firstValidTime : lastValidTime - firstValidTime)),
denominator);
pcbNumberProgressBar.Value = (currentPcbNr != 0) ? (100 * numerator / denominator) : 0;
pcbNumberProgressBar.ColorId = (currentPcbNr > 0) ? 0 : 1;
}
public void RunDeviceAfter() { }
@ -238,7 +268,7 @@ namespace Workplace.CheckItems
{
/// No CR+LF found =>stop processing => wait for more characters in the buffer in the next invocation
partOfTelegram = allRcvd;
return;
break;
}
else if (pos < S640.DatastreamFrame.FrameLength - 2)
{
@ -247,24 +277,79 @@ namespace Workplace.CheckItems
}
else
{
bool frameOk = optoData[optoDataIx].UpdateFromString(allRcvd.Substring(pos - S640.DatastreamFrame.FrameLength + 2, S640.DatastreamFrame.FrameLength),
ref currentRawVolumeUnwrapped, ref currentRawTimeUnwrapped);
bool frameOk = frame.UpdateFromString(allRcvd.Substring(pos - S640.DatastreamFrame.FrameLength + 2,
S640.DatastreamFrame.FrameLength),
ref currentRawVolumeUnwrapped,
ref currentRawTimeUnwrapped);
if (frameOk)
{
/// Frame OK => Move to the next frame
optoDataIx++;
if (optoDataIx >= FramesBufferSize) optoDataIx = 0;
}
else
{
/// Invalid frame => Invalidate it (age it)
optoData[optoDataIx].DateTime = DateTime.MinValue;
Array.Copy(frame.Data, 0, pcbNrStr, 0, 12);
Array.Copy(frame.Data, 12, radioAddrStr, 0, 10);
if (Int64.TryParse(new string(pcbNrStr), out currentPcbNr) && Int64.TryParse(new string(radioAddrStr), out currentRadioAddr)
&& currentPcbNr != 0 && currentRadioAddr != 0)
{
if (currentRawTimeUnwrapped - lastValidTime <= MaxDropoutTime &&
currentPcbNr == validPcbNumber &&
currentRadioAddr == validRadioAddress &&
currentPcbNr != lastSentNonzeroPcbNumber)
{
/// No datastream dropout and data have not changed: extend the validity time
lastValidTime = currentRawTimeUnwrapped;
if ((lastValidTime - firstValidTime) >= MinHoldTime)
{
PcbNumber = validPcbNumber;
RadioAddress = validRadioAddress;
}
}
else if (currentPcbNr != lastSentNonzeroPcbNumber)
{
/// Either a datastream dropout or data changed: consider this frame to be the first one for evaluation
validPcbNumber = currentPcbNr;
validRadioAddress = currentRadioAddr;
firstValidTime = currentRawTimeUnwrapped;
lastValidTime = currentRawTimeUnwrapped;
PcbNumber = 0;
RadioAddress = 0;
}
}
}
allRcvd = allRcvd.Substring(pos + 2);
}
}
}
if (receivedBytes == 0 || currentPcbNr == lastSentNonzeroPcbNumber || currentPcbNr == (long)-1)
{
/// No data received (= dropout, but no new data)
currentPcbNr = (long)-1;
currentRadioAddr = (long)-1;
if (currentPcbNr == validPcbNumber && currentRadioAddr == validRadioAddress)
{
/// Next time
lastValidTime = lastValidTime + (long)Const.Interval;
}
else
{
/// First time
firstValidTime = lastValidTime + (long)Const.Interval;
lastValidTime = firstValidTime;
validPcbNumber = currentPcbNr;
validRadioAddress = currentRadioAddr;
PcbNumber = 0;
RadioAddress = 0;
}
if ((lastValidTime - firstValidTime) >= MinBreakTime)
{
PcbNumber = validPcbNumber;
RadioAddress = validRadioAddress;
}
}
}
catch (Exception e)
{
@ -275,42 +360,5 @@ namespace Workplace.CheckItems
}
}
}
void ProcessBuffer_UpdatePcbNrAndRA()
{
DateTime now = DateTime.Now;
char[] pcbNrStr = new char[12];
char[] radioAddrStr = new char[10];
Int64 pcbNr;
Int64 radioAddr;
prwList.Clear();
for (int i = 0; i < FramesBufferSize; i++)
{
double age = (now - optoData[i].DateTime).TotalSeconds;
if (age < 5)
{
Array.Copy(optoData[i].Data, 0, pcbNrStr, 0, 12);
Array.Copy(optoData[i].Data, 12, radioAddrStr, 0, 10);
if (Int64.TryParse(new string(pcbNrStr), out pcbNr) && Int64.TryParse(new string(radioAddrStr), out radioAddr))
{
S640.PcbnrRadioaddrWeight.Accumulate(prwList, pcbNr, radioAddr, 5 - age);
}
}
}
if (prwList.Count > 0)
{
prwList = prwList.OrderByDescending(x => x.Weight).ToList();
PcbNumber = prwList[0].PcbNr;
RadioAddress = prwList[0].RadioAddr;
}
else
{
PcbNumber = 0;
RadioAddress = 0;
}
}
}
}

9
Workplace/Const.cs Normal file
View File

@ -0,0 +1,9 @@
using System;
namespace Workplace
{
public static class Const
{
public const int Interval = 400; /// ms
}
}

View File

@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Workplace")]
[assembly: AssemblyCopyright("Copyright © 2015-2021")]
[assembly: AssemblyCopyright("Copyright © 2015-2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.1.17.0")]
[assembly: AssemblyFileVersion("3.1.17.0")]
[assembly: AssemblyVersion("3.1.19.0")]
[assembly: AssemblyFileVersion("3.1.19.0")]

View File

@ -95,6 +95,9 @@
<Compile Include="CheckItems\Keyboard.Designer.cs">
<DependentUpon>Keyboard.cs</DependentUpon>
</Compile>
<Compile Include="CheckItems\MyProgressBar.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="CheckItems\OkNok.cs">
<SubType>UserControl</SubType>
</Compile>
@ -122,6 +125,7 @@
<Compile Include="CheckItems\SNGeneratorPrinter.Designer.cs">
<DependentUpon>SNGeneratorPrinter.cs</DependentUpon>
</Compile>
<Compile Include="Const.cs" />
<Compile Include="Enums.cs" />
<Compile Include="Forms\SettingsDlg.cs">
<SubType>Form</SubType>

View File

@ -189,7 +189,7 @@ namespace Workplace
/// Timer for regular 1 second ticks
runDeviceTimer = new System.Windows.Forms.Timer();
runDeviceTimer.Interval = 1000; // ms
runDeviceTimer.Interval = Const.Interval;
runDeviceTimer.Tick += new EventHandler(runDeviceTimer_Tick);
runDeviceTimer.Start();
@ -1315,9 +1315,17 @@ namespace Workplace
k.ClearCode();
k.ResetFocus();
}
if (komponenty.Count > 0)
if (komponenty.Count >= 1)
{
komponenty[0].SetFocus();
if (komponenty.Count >= 2 && komponenty[0] is CheckItems.SNGeneratorPrinter
&& komponenty[0].Part.CodeForm == (sbyte)CodeForm.SNGenerator)
{
komponenty[1].SetFocus();
}
else
{
komponenty[0].SetFocus();
}
}
if ((recordProcessing != null) && !wasAlreadyTested && componentsSaved)