Files
AUTS_Desktop_Prod/AUTS_AOI/FrmMain.vb
MomoWen 027d0f8024 初始化提交
仓库转移到Gitea,初始化提交,可能丢失以前的git版本日志
2025-11-27 16:41:05 +08:00

542 lines
18 KiB
VB.net
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Imports System.Text
Imports System.Threading
Imports OpenCvSharp
Imports OpenCvSharp.Extensions
Imports UTS_Core.UTSModule.Test
Imports UTS_Core.UTSModule
Imports UTS_Core.UTSModule.Station
Public Class FrmMain
Implements IStatisticsObserver
Implements IProcessStation
Implements IProductionLine
Private _ftp As FtpService
Private _utsApp As UtsAppForm
Private _checkStatistics As Statistics
Private _snSqliteChar As Char = "|"c
Private _useCamera As Boolean
Private _doubleCarera As Boolean
Public Sub ProductionLineChanged() Implements IProductionLine.ProductionLineChanged
TssLblProductionLine.Text = CboProductionLines.Text
My.Settings.ProductionLine = CboProductionLines.Text
End Sub
Public Sub StationChanged() Implements IProcessStation.StationChanged
My.Settings.Project = _utsApp.ProcessStation.ParentProject.Name
My.Settings.ProcessStation = _utsApp.ProcessStation.Name
UpdateStation(_utsApp.ProcessStation.ParentProject.Name, _utsApp.ProcessStation.Name)
End Sub
Public Sub UpdateStation(projectName As String, stationName As String)
If String.IsNullOrWhiteSpace(projectName) OrElse
String.IsNullOrWhiteSpace(stationName) Then
TssLblStaion.Text = $"Invalid Station"
Else
TssLblStaion.Text = $"{projectName} - {stationName}"
End If
End Sub
Public Sub UpdateFailCount(failCount As Integer) Implements IStatisticsObserver.UpdateFailCount
TssLblFailCount.Text = $"Fail:{failCount:D4}"
End Sub
Public Sub UpdatePassCount(passCount As Integer) Implements IStatisticsObserver.UpdatePassCount
TssLblPassCount.Text = $"Pass:{passCount:D4}"
End Sub
Public Sub UpdateValidCount(validCount As Integer) Implements IStatisticsObserver.UpdateValidCount
TssLblValidCount.Text = $"Valid:{validCount:D4}"
End Sub
Public Sub UpdateInvalidCount(invalidCount As Integer) Implements IStatisticsObserver.UpdateInvalidCount
TssLblInvalidCount.Text = $"Invalid:{invalidCount:D4}"
End Sub
Public Sub UpdateSumCount(sumCount As Integer) Implements IStatisticsObserver.UpdateSumCount
TsLblCheckSum.Text = $"Sum:{sumCount:D4}"
End Sub
Public Sub UpdateYield(yield As Double) Implements IStatisticsObserver.UpdateYield
Select Case yield
Case > 90
TssLblYield.ForeColor = Color.DarkGreen
Case > 75
TssLblYield.ForeColor = Color.Green
Case > 60
TssLblYield.ForeColor = Color.Orange
Case > 40
TssLblYield.ForeColor = Color.OrangeRed
Case Else
TssLblYield.ForeColor = Color.Red
End Select
TssLblYield.Text = $"Yield:{yield:F2}%"
End Sub
Private Sub FrmMain_Load(sender As Object, e As EventArgs) Handles Me.Load
My.Application.SaveMySettingsOnExit = True
_checkStatistics = New Statistics()
_checkStatistics.AddStatisticsObserver(Me)
_utsApp = UtsAppForm.CreateSingleton()
Try
If _utsApp.IsInitialized = False Then
_utsApp.AddStatisticsObserver(Me)
_utsApp.Initialize(ProcessStation.StationTypeEnum.AOI)
_utsApp.LoadStation(My.Settings.Project, My.Settings.ProcessStation)
End If
Catch ex As Exception
MsgBox($"Initialize UTSForm Error:{ex.Message}")
Close()
Return
End Try
Try
_ftp = New FtpService(UtsRegistry.FtpHost, CInt(_utsApp.License.FtpPort), _utsApp.License.FtpUser, _utsApp.License.FtpPwd)
Catch ex As Exception
MsgBox($"Initialize FtpService Error:{ex.Message}")
Close()
Return
End Try
'初始化产线信息
CboProductionLines.Items.Clear()
CboProductionLines.Items.AddRange(_utsApp.ProductionLines.GetLineNames())
CboProductionLines.SelectedIndex = CboProductionLines.Items.IndexOf(My.Settings.ProductionLine)
_doubleCarera = My.Settings.DoubleCamera
If _doubleCarera Then
RdBtnDouble.Checked = True
Else
RdBtnSingle.Checked = True
End If
TsCboCameraFrame.Items.Clear()
For Each siz As Size In _cameraFrame
TsCboCameraFrame.Items.Add($"{siz.Width}*{siz.Height}")
Next
TsCboCameraFrame.SelectedIndex = My.Settings.CameraFrameIndex
RtxBarcodeSn.Clear()
InitImageControl()
Text = $"{Application.ProductName} {Application.ProductVersion}"
End Sub
Private Sub InitImageControl()
_imgControl(0) = PicCamera1
_imgControl(1) = PicCamera2
End Sub
Private Sub FrmMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
SaveLogFile()
My.Settings.CameraFrameIndex = _selectFrameSizeIndex
My.Settings.DoubleCamera = _doubleCarera
_utsApp.Dispose()
CloseForm()
End Sub
Private Sub CloseForm()
Text = $"Goodbye World."
For i As Double = 1 To 0 Step -0.05
Thread.Sleep(50)
Opacity = i
Next
End Sub
Private Sub RtxDUT_SN_KeyDown(sender As Object, e As KeyEventArgs) Handles RtxBarcodeSn.KeyDown
If e.KeyCode = Keys.Enter Then
If String.IsNullOrWhiteSpace(RtxBarcodeSn.Text) = False Then
My.Computer.Keyboard.SendKeys("|")
e.SuppressKeyPress = True
e.Handled = True
End If
ElseIf e.KeyCode = Keys.Space Then
CommitTestResult()
e.SuppressKeyPress = True
e.Handled = True
Console.WriteLine($"{ e.SuppressKeyPress} { e.Handled}")
End If
End Sub
Private Function UploadFileToFtp(localPath As String, remotePath As String) As Boolean
Try
_ftp.FtpUpload(remotePath, localPath)
Catch ex As Exception
MsgBox($"上传图像[{localPath}]失败:{ex.Message}")
'todo:添加本地缓存上传失败图像,定期上传
'记录本地位置上传文件位置写入FTP的缓存数据库
'服务新增ftp同步任务区分上传下载
'
'
'记录ftp命令
'只记录上传下载命令?
Return False
End Try
Return True
End Function
Private Function GetImageName(barCode As String, index As Integer) As String
Dim fileName As New StringBuilder
fileName.Append(_utsApp.ProcessStation.ParentProject.Name)
fileName.Append("_")
fileName.Append(_utsApp.ProcessStation.Name)
fileName.Append("_")
fileName.Append(barCode)
fileName.Append("_")
fileName.Append($"{Now:yyyyMMdd_HHmmss}")
fileName.Append("_")
fileName.Append($"{index}")
fileName.Append(".jpg")
Return fileName.ToString()
End Function
Private Function SaveImageToLocal(localPath As String, index As Integer) As Boolean
If _imgControl(index).Image Is Nothing Then
MsgBox($"未检测到Camera[{index}] Image,录入失败")
Return False
End If
Dim img As Image = CType(_imgControl(index).Image.Clone(), Image)
Try
img.Save(localPath, Imaging.ImageFormat.Jpeg)
Catch ex As Exception
MsgBox($"Save Camera[{index}] Image Error:{ex.Message}")
Return False
End Try
Return True
End Function
Private Sub BtnCommit_Click(sender As Object, e As EventArgs) Handles BtnCommit.Click
CommitTestResult()
End Sub
Private Sub CommitTestResult()
If _utsApp.ProcessStation Is Nothing Then
MsgBox($"请选择项目与测试站后再尝试录入!")
Return
End If
If String.IsNullOrWhiteSpace(CboProductionLines.Text) Then
MsgBox($"请选择生产线后再尝试录入!")
Return
End If
Dim barcodeString As String = RtxBarcodeSn.Text.ToUpper
If String.IsNullOrWhiteSpace(barcodeString) Then
MsgBox($"请输入合法的序列号!")
Return
End If
Dim barcodeList As String() = barcodeString.Split(New Char() {_snSqliteChar}, StringSplitOptions.RemoveEmptyEntries)
If barcodeList.Count() = 0 Then Return
For Each barcode As String In barcodeList
If barcode.Length <> 8 Then
MsgBox($"录入失败,条码[{barcode}]长度非法,请检查后重新录入!")
Return
End If
Static imgDirPath As String = $"{Application.StartupPath}\Img"
If IO.Directory.Exists(imgDirPath) = False Then IO.Directory.CreateDirectory(imgDirPath)
Dim imgFileName As String = GetImageName(barcode, 0)
Dim imgLocalPath As String = $"{imgDirPath}\{imgFileName}"
Dim imgRemotePath As String = $"/uts_Manager/AUTS/{_utsApp.License.VendorName}/AOI/{_utsApp.ProcessStation.ParentProject.Index}/{imgFileName}"
If SaveImageToLocal(imgLocalPath, 0) = False Then Return
If UploadFileToFtp(imgLocalPath, imgRemotePath) = False Then Return
Dim imgFileName2 As String = GetImageName(barcode, 1)
Dim imgRemotePath2 As String = ""
If _doubleCarera Then
Dim imgLocalPath2 As String = $"{imgDirPath}\{imgFileName2}"
If SaveImageToLocal(imgLocalPath2, 1) = False Then Return
imgRemotePath2 = $"/uts_Manager/AUTS/{_utsApp.License.VendorName}/AOI/{_utsApp.ProcessStation.ParentProject.Index}/{imgFileName2}"
If UploadFileToFtp(imgLocalPath2, imgRemotePath2) = False Then Return
End If
Try
FillTestResult(barcode, imgRemotePath, imgRemotePath2)
_utsApp.CommitTestResult()
_checkStatistics.AddPassCount()
AppendRecord(True, _utsApp.ProcessStation.ParentProject.Index, _utsApp.ProcessStation.StationID, _utsApp.TestResult.OrderID, _utsApp.TestResult.DUT_SN, "Pass")
LblResult.Text = $"{_utsApp.ProcessStation.ParentProject.Index:D2}-{_utsApp.ProcessStation.StationID:D2}-{_utsApp.TestResult.OrderID:D6}-{_utsApp.TestResult.DUT_SN} 录入成功"
LblResult.ForeColor = Color.Green
Catch ex As Exception
_checkStatistics.AddInvalidCount()
MsgBox($"测试结果录入失败:{ex.Message}")
LblResult.Text = $"{_utsApp.TestResult.DUT_SN} 录入失败"
LblResult.ForeColor = Color.Red
End Try
Next
TestResultCommitted()
End Sub
''' <summary>
''' 填充测试记录内容,每个应用程序这个部分有所差异
''' </summary>
Public Sub FillTestResult(barcodeSn As String, imgPath As String, imgPath2 As String)
_utsApp.TestResult.ResetTestResult()
'产线索引
Dim lineID As Integer = _utsApp.ProductionLines(CboProductionLines.Text).ID
_utsApp.TestResult.ProductionLineID = lineID
'测试开始时间
_utsApp.TestResult.StartTime = Now
_utsApp.TestResult.DUT_SN = barcodeSn
_utsApp.TestResult.TestResult = TestResult.TestResultEnum.Pass
_utsApp.TestResult.AddCustomRecord("ImagePath", imgPath)
_utsApp.TestResult.AddCustomRecord("ImagePath2", imgPath2)
End Sub
Public Sub TestResultCommitted()
RtxBarcodeSn.Focus()
RtxBarcodeSn.SelectAll()
End Sub
Private Sub TsChangeStation_Click(sender As Object, e As EventArgs) Handles TsChangeStation.Click
Try
Dim filed As New Dictionary(Of String, String) From {{"ImagePath", "varchar(128)"}, {"ImagePath2", "varchar(128)"}}
_utsApp.ChangeStation(filed)
Catch ex As Exception
MsgBox($"ChangeStation Error:{ex.Message}")
End Try
End Sub
''' <summary>
''' 添加提示信息
''' </summary>
''' <param name="checkResult">校验结果</param>
''' <param name="log">提示信息</param>
Private Sub AppendRecord(checkResult As Boolean, pid As Integer, sid As Integer, order As Integer, barcode As String, log As String)
Static recordMaxCount As Integer = 256
Static recordCount As Integer = 1
With RtxRecord
.Enabled = False
If recordCount >= recordMaxCount Then
SaveLogFile()
.Clear()
recordCount = 1
End If
.SelectionStart = .TextLength
.SelectionColor = Color.Black
.AppendText($"{recordCount:D4} ")
.SelectionStart = .TextLength
.SelectionColor = Color.DarkBlue
.AppendText($"{Now:MMdd_HH:mm:ss} ")
.SelectionStart = .TextLength
.SelectionColor = Color.Black
.AppendText($"{pid:D2}-")
.SelectionStart = .TextLength
.SelectionColor = Color.Black
.AppendText($"{sid:D2} ")
.SelectionStart = .TextLength
.SelectionColor = Color.DarkSeaGreen
.AppendText($"{order:D6} ")
.SelectionStart = .TextLength
.SelectionColor = Color.DarkOrange
.AppendText($"{barcode,8} ")
.SelectionStart = .TextLength
.SelectionColor = CType(IIf(checkResult, Color.Green, Color.Red), Color)
.AppendText($"{log}{vbNewLine}")
recordCount += 1
.ScrollToCaret()
.Enabled = True
End With
End Sub
Private Sub SaveLogFile()
Dim dirPath As String = $"{Application.StartupPath}\Log"
Dim filePath As String = $"{dirPath}\Log_{Now:yyyyMMdd_HHmmss}.txt"
If IO.Directory.Exists(dirPath) = False Then IO.Directory.CreateDirectory(dirPath)
RtxRecord.SaveFile(filePath, RichTextBoxStreamType.TextTextOleObjs)
End Sub
Private Sub CboProductionLines_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CboProductionLines.SelectedIndexChanged
ProductionLineChanged()
End Sub
#Region "相机"
Private ReadOnly _imgControl(1) As PictureBox
Private ReadOnly _camera(1) As VideoCapture
Private ReadOnly _frameChanged(1) As Boolean
Private _selectFrameSizeIndex As Integer
Private ReadOnly _cameraFrame() As Size = {New Size(640, 480), New Size(1280, 960), New Size(2048, 1536), New Size(2560, 1920), New Size(3200, 2400), New Size(3840, 2880)}
Private Sub UpdateText(w As Integer, h As Integer, fps As Double)
If InvokeRequired Then
Invoke(New Action(Sub()
Text = $"{Application.ProductName} {Application.ProductVersion} Camera : {w} * {h} : {CInt(fps)} Fps"
End Sub))
Else
Text = $"{Application.ProductName} {Application.ProductVersion} Camera : {w} * {h} : {CInt(fps)} Fps"
End If
End Sub
''' <summary>
''' 打开摄像头显示图像
''' </summary>
Private Sub OpenVideoThread(state As Object)
Dim index As Integer = CInt(state)
While _useCamera
Thread.Sleep(10)
If _doubleCarera = False AndAlso index = 1 Then
If _camera(index) IsNot Nothing Then
_camera(index).Release()
_camera(index).Dispose()
_camera(index) = Nothing
_imgControl(index).Image = Nothing
End If
Continue While
End If
If _camera(index) Is Nothing Then
_camera(index) = New VideoCapture(index) '打开默认的相机使用默认为0
'摄像头为4:3
If _selectFrameSizeIndex <> -1 Then
_camera(index).FrameWidth = _cameraFrame(_selectFrameSizeIndex).Width
_camera(index).FrameHeight = _cameraFrame(_selectFrameSizeIndex).Height
Else
_camera(index).FrameWidth = 2560
_camera(index).FrameHeight = 1920
End If
_camera(index).Fps = 30 '采集率FTP
_camera(index).Saturation = 60 '图像饱和度
_camera(index).Gain = 0 '图像增益
_camera(index).Contrast = 0 '对比度
_camera(index).Hue = 20 '色调
_camera(index).Brightness = 0
_camera(index).Exposure = 0 '曝光度
If _camera(index).IsOpened() = False Then
Thread.Sleep(1000)
Continue While
End If
UpdateText(_camera(index).FrameWidth, _camera(index).FrameHeight, _camera(index).Fps)
End If
If _frameChanged(index) Then
Console.WriteLine($"分辨率切换!")
_camera(index).Release()
_camera(index).Dispose()
_camera(index) = Nothing
_frameChanged(index) = False
Continue While
End If
Using src As New Mat
If _camera(index).Read(src) = False Then
Console.WriteLine($"图像为空!")
_camera(index).Release()
_camera(index).Dispose()
_camera(index) = Nothing
Continue While
End If
Cv2.Flip(src, src, FlipMode.XY) '反转图像
_imgControl(index).Image = src.ToBitmap
End Using
GC.Collect()
End While
End Sub
Private Sub FrmMain_Shown(sender As Object, e As EventArgs) Handles Me.Shown
_useCamera = True
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf OpenVideoThread), 0)
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf OpenVideoThread), 1)
End Sub
Private Sub TsCboCameraFrame_SelectedIndexChanged(sender As Object, e As EventArgs) Handles TsCboCameraFrame.SelectedIndexChanged
_frameChanged(0) = True
_frameChanged(1) = True
_selectFrameSizeIndex = TsCboCameraFrame.SelectedIndex
End Sub
Private Sub RdBtnDouble_CheckedChanged(sender As Object, e As EventArgs) Handles RdBtnDouble.CheckedChanged
_doubleCarera = RdBtnDouble.Checked
End Sub
Private Sub RtxRecord_TextChanged(sender As Object, e As EventArgs) Handles RtxRecord.TextChanged
End Sub
#End Region
End Class