You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

337 lines
9.9 KiB

using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using Housing.Login;
using Housing.Models;
using Housing.Services;
namespace Housing;
public partial class MainWindow : Window
{
private const string BarcodeRequiredMessage = "PCB_Barcode를 입력하고 Enter를 눌러주세요.";
private const string BoardReadyMessage = "Enter를 누르면 보드 연결 테스트를 시작합니다.";
private const string DefaultOutputValue = "0.00";
private StartupLoginWindowResult _loginResult = new();
private InspectionJudgementSettings _inspectionSettings;
private bool _isStartupLoginShown;
private bool _isBoardTestRunning;
public MainWindow()
{
_inspectionSettings = InspectionSettingsStore.Load(GetInspectionSettingsIniPath());
InitializeComponent();
ApplyInspectionSettingsToTextBoxes();
ApplyLoginResult();
ResetScreen();
}
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
if (_isStartupLoginShown)
{
return;
}
_isStartupLoginShown = true;
if (!ShowLoginPopup())
{
Close();
}
}
private void BarcodeTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (string.IsNullOrWhiteSpace(BarcodeTextBox.Text))
{
IcSnOutputTextBox.Clear();
ResultOutputTextBox.Text = BarcodeRequiredMessage;
return;
}
ResultOutputTextBox.Text = BoardReadyMessage;
}
private async void BarcodeTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Enter && e.Key != Key.Return)
{
return;
}
e.Handled = true;
await RunBoardSequenceAsync();
}
public async Task OnEquipmentStartButtonPressedAsync()
{
await RunBoardSequenceAsync();
}
private async Task RunBoardSequenceAsync()
{
if (_isBoardTestRunning)
{
return;
}
if (string.IsNullOrWhiteSpace(BarcodeTextBox.Text))
{
ResultOutputTextBox.Text = BarcodeRequiredMessage;
FocusBarcodeInput();
return;
}
if (!TryApplyInspectionSettingsFromTextBoxes())
{
return;
}
try
{
_isBoardTestRunning = true;
SetInputEnabled(false);
ResultOutputTextBox.Text =
"보드 테스트 시작\r\n" +
"1. 시료 연결 확인\r\n" +
"2. IC_SN 읽기\r\n" +
"3. CAL DEFAULT 조건 설정\r\n" +
"4. 계측 장비에서 V/A 읽기";
var boardSettings = BoardHardwareSettings.Load(GetHardwareIniPath());
var equipmentSettings = EquipmentMeasurementSettings.Load(GetHardwareIniPath());
var service = new BoardTestService(boardSettings, equipmentSettings);
var measurement = await service.RunAsync();
IcSnOutputTextBox.Text = measurement.IcSn;
VOutputTextBox.Text = FormatDecimal(measurement.Voltage);
AOutputTextBox.Text = FormatDecimal(measurement.Current);
var resultCode = _inspectionSettings.IsPass(measurement.Voltage, measurement.Current) ? "OK" : "NG";
ResultOutputTextBox.Text = $"{resultCode}\r\n{measurement.RawLog}";
await SaveCurrentResultAsync(resultCode);
}
catch (Exception ex)
{
ResultOutputTextBox.Text = $"보드 테스트 실패: {ex.Message}";
}
finally
{
_isBoardTestRunning = false;
SetInputEnabled(true);
FocusBarcodeInput();
}
}
private void LogoutButton_Click(object sender, RoutedEventArgs e)
{
ResetScreen();
_loginResult = new StartupLoginWindowResult();
OperatorTextBlock.Text = "-";
LogoutButton.Visibility = Visibility.Collapsed;
if (!ShowLoginPopup())
{
Close();
}
}
private bool ShowLoginPopup()
{
var loginWindow = new StartupLoginWindow
{
Owner = this
};
if (loginWindow.ShowDialog() != true)
{
return false;
}
_loginResult = loginWindow.Result;
ApplyLoginResult();
ResetScreen();
return true;
}
private void ApplyLoginResult()
{
OperatorTextBlock.Text = string.IsNullOrWhiteSpace(_loginResult.Operator) ? "-" : _loginResult.Operator;
LogoutButton.Visibility = string.IsNullOrWhiteSpace(_loginResult.Operator)
? Visibility.Collapsed
: Visibility.Visible;
}
private void ResetScreen()
{
BarcodeTextBox.Clear();
IcSnOutputTextBox.Clear();
VOutputTextBox.Text = DefaultOutputValue;
AOutputTextBox.Text = DefaultOutputValue;
ResultOutputTextBox.Text = BarcodeRequiredMessage;
FocusBarcodeInput();
}
private void SetInputEnabled(bool isEnabled)
{
BarcodeTextBox.IsEnabled = isEnabled;
VMinTextBox.IsEnabled = isEnabled;
VMaxTextBox.IsEnabled = isEnabled;
AMinTextBox.IsEnabled = isEnabled;
AMaxTextBox.IsEnabled = isEnabled;
LogoutButton.IsEnabled = isEnabled;
}
private void FocusBarcodeInput()
{
Dispatcher.BeginInvoke(new Action(() =>
{
BarcodeTextBox.Focus();
Keyboard.Focus(BarcodeTextBox);
BarcodeTextBox.SelectAll();
}), DispatcherPriority.Input);
}
private async Task SaveCurrentResultAsync(string resultCode)
{
try
{
var repository = new HousingAssemblyRepository(DatabaseSettings.Load(GetDatabaseIniPath()));
var record = CreateCurrentRecord(resultCode);
await repository.InsertAsync(record);
ResultOutputTextBox.Text += "\r\nDB 저장 완료";
}
catch (Exception ex)
{
ResultOutputTextBox.Text += $"\r\nDB 저장 실패: {ex.Message}";
}
}
private HousingAssemblyRecord CreateCurrentRecord(string resultCode)
{
var barcode = BarcodeTextBox.Text.Trim();
var icSn = IcSnOutputTextBox.Text.Trim();
if (string.IsNullOrWhiteSpace(icSn))
{
icSn = barcode;
IcSnOutputTextBox.Text = icSn;
}
return new HousingAssemblyRecord
{
IcSn = icSn,
PcbBarcode = barcode,
Maker = _loginResult.Maker,
Model = _loginResult.Model,
Variant1 = _loginResult.Variant1,
Variant2 = _loginResult.Variant2,
Operator = _loginResult.Operator,
Password = _loginResult.Password,
ProductionDate = DateTime.Now,
Line = _loginResult.LineNo,
LotNo = _loginResult.LotNo,
JigNo = _loginResult.JigNo,
PtVol1 = ParseDecimal(VOutputTextBox.Text),
PtCurrent1 = ParseDecimal(AOutputTextBox.Text),
Result = resultCode
};
}
private void ApplyInspectionSettingsToTextBoxes()
{
VMinTextBox.Text = FormatDecimal(_inspectionSettings.VMin);
VMaxTextBox.Text = FormatDecimal(_inspectionSettings.VMax);
AMinTextBox.Text = FormatDecimal(_inspectionSettings.AMin);
AMaxTextBox.Text = FormatDecimal(_inspectionSettings.AMax);
}
private bool TryApplyInspectionSettingsFromTextBoxes()
{
if (!TryReadRangeValue(VMinTextBox, "V 최소값", out var vMin) ||
!TryReadRangeValue(VMaxTextBox, "V 최대값", out var vMax) ||
!TryReadRangeValue(AMinTextBox, "A 최소값", out var aMin) ||
!TryReadRangeValue(AMaxTextBox, "A 최대값", out var aMax))
{
return false;
}
if (vMin > vMax)
{
MessageBox.Show(this, "V 최소값은 최대값보다 클 수 없습니다.", "판정 범위", MessageBoxButton.OK, MessageBoxImage.Warning);
VMinTextBox.Focus();
return false;
}
if (aMin > aMax)
{
MessageBox.Show(this, "A 최소값은 최대값보다 클 수 없습니다.", "판정 범위", MessageBoxButton.OK, MessageBoxImage.Warning);
AMinTextBox.Focus();
return false;
}
_inspectionSettings = new InspectionJudgementSettings
{
VMin = vMin,
VMax = vMax,
AMin = aMin,
AMax = aMax
};
InspectionSettingsStore.Save(GetInspectionSettingsIniPath(), _inspectionSettings);
return true;
}
private bool TryReadRangeValue(TextBox textBox, string fieldName, out decimal value)
{
if (decimal.TryParse(textBox.Text, NumberStyles.Number, CultureInfo.InvariantCulture, out value))
{
return true;
}
if (decimal.TryParse(textBox.Text, out value))
{
return true;
}
MessageBox.Show(this, $"{fieldName}은 숫자로 입력하세요.", "판정 범위", MessageBoxButton.OK, MessageBoxImage.Warning);
textBox.Focus();
return false;
}
private static decimal ParseDecimal(string value)
{
return decimal.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out var result)
? result
: 0m;
}
private static string FormatDecimal(decimal value)
{
return value.ToString("0.00", CultureInfo.InvariantCulture);
}
private static string GetDatabaseIniPath()
{
return Path.Combine(AppContext.BaseDirectory, "Database.ini");
}
private static string GetHardwareIniPath()
{
return Path.Combine(AppContext.BaseDirectory, "Hardware.ini");
}
private static string GetInspectionSettingsIniPath()
{
return Path.Combine(AppContext.BaseDirectory, "InspectionSettings.ini");
}
}