2026-04-14 20:44:08 +09:00

505 lines
22 KiB
C#

using Aurora;
using Aurora.Api;
using Aurora.View;
using AuroraLaser;
using AuroraLaserScanner;
using CoreUnit.Control.UserControl.Canvas;
using CoreUnit.Scanner.UserControl.ScannerCanvas;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Threading;
using WeldingCommon.Models;
using WeldingCommon.Sequences;
using WeldingCommon.Settings;
using WeldingCommon.Utils;
namespace WeldingCommon.Views
{
public class UCScannerLaserControlViewModel : NotifyPropertyChangedBase
{
private readonly Logger Log = new Logger("UCScannerLaserControlViewModel");
public ICommand CMD_VisibleChanged { get; }
public ICommand CMD_LaserShotOnPercent { get; }
public ICommand CMD_LaserShotOff { get; }
public ICommand CMD_ActivateOnTheFly { get; }
public ICommand CMD_DeactivateOnTheFly { get; }
public ICommand CMD_ResetEncoderValue { get; }
public ICommand CMD_SimulateEncoder { get; }
public ICommand CMD_SimulateEncoderXY { get; }
public ICommand CMD_LaserShotOnWatt { get; }
private readonly IAuroraEnvironment _Aurora;
private readonly LaserConfig _LaserConfig;
private readonly Scanner _Scanner; // 스캐너
private readonly Laser _Laser;
private readonly ScannerConfig _ScannerConfig;
private double _LaserPower1Percent;
public double LaserPower1Percent { get => _LaserPower1Percent; set => SetProperty(ref _LaserPower1Percent, value); }
private double _LaserPower2Percent;
public double LaserPower2Percent { get => _LaserPower2Percent; set => SetProperty(ref _LaserPower2Percent, value); }
private double _LaserPower1Watt;
public double LaserPower1Watt { get => _LaserPower1Watt; set => SetProperty(ref _LaserPower1Watt, value); }
private double _LaserPower2Watt;
public double LaserPower2Watt { get => _LaserPower2Watt; set => SetProperty(ref _LaserPower2Watt, value); }
private uint _LaserPeriod;
public uint LaserPeriod { get => _LaserPeriod; set => SetProperty(ref _LaserPeriod, value); }
private uint _LaserPulseWidth;
public uint LaserPulseWidth { get => _LaserPulseWidth; set => SetProperty(ref _LaserPulseWidth, value); }
private bool _IsUseLaserAutoOffChecked;
public bool IsUseLaserAutoOffChecked { get => _IsUseLaserAutoOffChecked; set => SetProperty(ref _IsUseLaserAutoOffChecked, value); }
private double _LaserOnTime;
public double LaserOnTime { get => _LaserOnTime; set => SetProperty(ref _LaserOnTime, value); }
// List1 or List2 를 Scanner 의 상태를 보고 check
private string _BusyStatus;
public string BusyStatus { get => _BusyStatus; set => SetProperty(ref _BusyStatus, value); }
private int _ListInterationCount;
public int ListInterationCount { get => _ListInterationCount; set => SetProperty(ref _ListInterationCount, value); }
private double _RotateCenterX;
public double RotateCenterX { get => _RotateCenterX; set => SetProperty(ref _RotateCenterX, value); }
private double _RotateCenterY;
public double RotateCenterY { get => _RotateCenterY; set => SetProperty(ref _RotateCenterY, value); }
private double _EncoderResolution;
public double EncoderResolution { get => _EncoderResolution; set => SetProperty(ref _EncoderResolution, value); }
private double _EncoderValueAxisX;
public double EncoderValueAxisX { get => _EncoderValueAxisX; set => SetProperty(ref _EncoderValueAxisX, value); }
private double _EncoderValueAxisY;
public double EncoderValueAxisY { get => _EncoderValueAxisY; set => SetProperty(ref _EncoderValueAxisY, value); }
private double _EncoderValueRotate;
public double EncoderValueRotate { get => _EncoderValueRotate; set => SetProperty(ref _EncoderValueRotate, value); }
private double _EncoderValueVelocity;
public double EncoderValueVelocity { get => _EncoderValueVelocity; set => SetProperty(ref _EncoderValueVelocity, value); }
private bool _IsFieldOutX;
public bool IsFieldOutX { get => _IsFieldOutX; set => SetProperty(ref _IsFieldOutX, value); }
private bool _IsFieldOutY;
public bool IsFieldOutY { get => _IsFieldOutY; set => SetProperty(ref _IsFieldOutY, value); }
private bool _IsUseMarkingOnTheFly;
public bool IsUseMarkingOnTheFly { get => _IsUseMarkingOnTheFly; set => SetProperty(ref _IsUseMarkingOnTheFly, value); }
private int _BeforeBusyList = 0;
private int _ListIterationCount = 0;
private DateTime _LastEncRecordTime = DateTime.Now;
private double _LastEncoderRecorded = 0;
private bool _ToggleSimulateEncoder = false; // 왜 있는지는 모르겠음.
private readonly DispatcherTimer _MonitorTimer;
private ISequence _SeqTeachingRun;
public UCScannerLaserControlViewModel(IAuroraEnvironment aurora, string scannerId, bool isUseMarkingOntheFly = false)
{
_Aurora = aurora;
_Scanner = _Aurora.DeviceManager[scannerId] as Scanner;
//_Laser = _Aurora.DeviceManager[CommonDeviceIds.Laser] as Laser;
//_LaserConfig = _Aurora.DeviceManager.GetDeviceConfig(_Laser.DeviceId) as AuroraLaser.LaserConfig;
_ScannerConfig = _Aurora.DeviceManager.GetDeviceConfig(scannerId) as ScannerConfig;
_SeqTeachingRun = _Aurora.SequenceEntry[CommonSequenceIds.SeqComponentTeachingRun];
IsUseMarkingOnTheFly = isUseMarkingOntheFly;
InitVariable();
CMD_VisibleChanged = new DelegateCommand(VisibleChanged);
CMD_LaserShotOnPercent = new DelegateCommand(PerformCmdLaserShotOnPercent); //레이저 온 퍼센트 적용
CMD_LaserShotOnWatt = new DelegateCommand(PerformCmdLaserShotOnWatt); // 레이저 온 와트 적용
CMD_LaserShotOff = new DelegateCommand(PerformCmdLaserShotOff); //레이저 끄기
CMD_ActivateOnTheFly = new DelegateCommand(PerformCmdActivateOnTheFly);
CMD_DeactivateOnTheFly = new DelegateCommand(PerformCmdDeactivateOnTheFly);
CMD_ResetEncoderValue = new DelegateCommand(PerformCmdResetEncoderValue);
CMD_SimulateEncoder = new DelegateCommand(PerformCmdSimulateEncoder);
CMD_SimulateEncoderXY = new DelegateCommand(PerformCmdSimulateEncoderXY);
_MonitorTimer = new DispatcherTimer();
_MonitorTimer.Tick += OnMonitoring;
_MonitorTimer.Interval = TimeSpan.FromMilliseconds(100);
}
private void InitVariable()
{
LaserPower1Percent = 10;
LaserPower2Percent = 0;
LaserPeriod = 1;
LaserPulseWidth = 1000000;
LaserPower1Watt = 300;
LaserPower2Watt = 0;
_LastEncRecordTime = DateTime.Now;
IsUseLaserAutoOffChecked = true;
}
private void VisibleChanged(object obj)
{
bool visible = (bool)obj;
if (visible) {
//Init_XYLimitPos();
_MonitorTimer.Start();
} else {
_MonitorTimer.Stop();
}
}
private void OnMonitoring(object sender, EventArgs e)
{
if (_Scanner.IsActivated == false) {
Log.D(string.Format("[OnMonitoring] Check Scanner device Connect. ScannerLaserControl view OnMonitoring Stop"));
MessageUtil.ShowWarningToast(string.Format("Check Scanner device Connect."));
_MonitorTimer.Stop();
}
double encoderX, encoderY;
if (_ScannerConfig.OnTheFlyCoordinate == eOntheFlyCoordinate.XY) {
_Scanner.GetEncoder(out encoderX, out encoderY, false);
} else {
_Scanner.GetEncoder(out encoderX, out encoderY, true);
}
TimeSpan encRecordTimeSpan = DateTime.Now.Subtract(_LastEncRecordTime);
_LastEncRecordTime = DateTime.Now;
// CBW Test용 임시 수정
//m_scannerUnit.GetEncoder(out encoderX, out encoderY, true);
EncoderValueAxisX = encoderX;
EncoderValueAxisY = encoderY;
//m_scannerUnit.GetEncoder(out encoderX, out encoderY, true);
//lbRotateEncoderValue.Text = (encoderX).ToString("f3");
EncoderValueRotate = 0;
EncoderValueVelocity = (encoderX - _LastEncoderRecorded) / (encRecordTimeSpan.TotalSeconds);
_LastEncoderRecorded = encoderX;
//// Field 초과 판단
uint markingInfo = 0;
markingInfo = _Scanner.GetMarkingInfo();
// x 범위 초과
if ((markingInfo & 0x0001) == 0x0001 || (markingInfo & 0x0002) == 0x0002) {
IsFieldOutX = true;
} else {
IsFieldOutX = false;
}
// y 범위 초과
if ((markingInfo & 0x0004) == 0x0004 || (markingInfo & 0x0008) == 0x0008) {
IsFieldOutY = true;
} else {
IsFieldOutY = false;
}
// 상태 파악 및 반복성 확인.
uint readStatus = _Scanner.ReadStatus();
string busyStatus;
uint IsList1Busy = readStatus & 16;
uint IsList2Busy = readStatus & 32;
if (IsList1Busy == 16) {
busyStatus = "List1";
if (_BeforeBusyList != 1) {
_ListIterationCount++;
}
_BeforeBusyList = 1;
} else if (IsList2Busy == 32) {
busyStatus = "List2";
if (_BeforeBusyList != 2) {
_ListIterationCount++;
}
_BeforeBusyList = 2;
} else {
busyStatus = "N/A";
}
BusyStatus = busyStatus;
ListInterationCount = _ListIterationCount;
}
private void PerformCmdLaserShotOnPercent(object obj)
{
if (IsUseLaserAutoOffChecked) {
if (_Scanner.GetBusyStatus()) {
MessageUtil.ShowWarningToast(string.Format("Laser, Scanner is busy."));
return;
}
//if (!_Laser.GetLaserReady()) {
// MessageUtil.ShowWarningToast(string.Format("Laser, Check Laser Ready status."));
// return;
//}
if (_SeqTeachingRun.RunState == SequenceRunState.Running) {
MessageUtil.ShowWarningToast(string.Format("이미 시퀀스가 Start 상태입니다.", "Laser On"), Log);
return;
}
var currentModelInfo = EquipmentSpecificModelUtil.GetCurrentRecipeEquipmentSpecificModel();
if (currentModelInfo.equipmentSpecificModel == null) {
MessageUtil.ShowWarningToast(string.Format("선택된 model 이 없습니다.", "Laser On"));
return;
}
var intervalTimeBlowOn = 0;
var intervalTimeBlowOff = 0;
if (currentModelInfo.equipmentSpecificModel.UseBlow) {
intervalTimeBlowOn = currentModelInfo.equipmentSpecificModel.IntervalTimeBlowOn;
intervalTimeBlowOff = currentModelInfo.equipmentSpecificModel.IntervalTimeBlowOff;
}
// Object를 만들어
var param = new SeqTeachingRun_InitParam() {
IsUseExternalObjects = true,
ExternalObjects = CreateDotForLaserOn(),
//UseStream = _EquipmentInfo.UseStream,
UseStream = currentModelInfo.equipmentSpecificModel.UseStream,
UseBlow = currentModelInfo.equipmentSpecificModel.UseBlow,
IntervalTimeBlowOn = intervalTimeBlowOn,
IntervalTimeBlowOff = intervalTimeBlowOff,
NeedSetLaserTiming = true,
};
_SeqTeachingRun.Start(param, OnCompleteMarkGrid);
} else {
LaserPowerCalParam powerCalParam = Status.AuroraEnv.SettingEntry[CommonSettingIds.LaserPowerCalParam] as LaserPowerCalParam;
float powerVolt1 = 0, powerVolt2 = 0;
powerCalParam.Initialize(powerCalParam.PowerCalibrationCenterBeamCSVFile, powerCalParam.PowerCalibrationRingBeamCSVFile);
powerVolt1 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower1Percent, (uint)LaserPowerCalParam.beamMode.Center) * 10;
powerVolt2 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower2Percent, (uint)LaserPowerCalParam.beamMode.Ring) * 10;
Thread.Sleep(50);
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, powerVolt1, eFunctionType.COMMAND);
_Scanner.WriteDA((uint)eAnalogPortOut.DA2, powerVolt2, eFunctionType.COMMAND);
_Scanner.SetLaserPulseCtrl(LaserPeriod * 1000, LaserPulseWidth);
//_Scanner.SetLaserTiming(LaserPeriod * 1000, LaserPulseWidth, LaserPulseWidth);
//_Scanner.SetStandby(LaserPeriod * 1000, LaserPulseWidth);
_Scanner.LaserSignalOn();
}
}
private void PerformCmdLaserShotOnWatt(object obj)
{
if (IsUseLaserAutoOffChecked) {
if (_Scanner.GetBusyStatus()) {
MessageUtil.ShowWarningToast(string.Format("Laser, Scanner is busy."));
return;
}
//if (!_Laser.GetLaserReady()) {
// MessageUtil.ShowWarningToast(string.Format("Laser, Check Laser Ready status."));
// return;
//}
if (_SeqTeachingRun.RunState == SequenceRunState.Running) {
MessageUtil.ShowWarningToast(string.Format("이미 시퀀스가 Start 상태입니다.", "Laser On"), Log);
return;
}
var currentModelInfo = EquipmentSpecificModelUtil.GetCurrentRecipeEquipmentSpecificModel();
if (currentModelInfo.equipmentSpecificModel == null) {
MessageUtil.ShowWarningToast(string.Format("선택된 model 이 없습니다.", "Laser On"));
return;
}
var intervalTimeBlowOn = 0;
var intervalTimeBlowOff = 0;
if (currentModelInfo.equipmentSpecificModel.UseBlow) {
intervalTimeBlowOn = currentModelInfo.equipmentSpecificModel.IntervalTimeBlowOn;
intervalTimeBlowOff = currentModelInfo.equipmentSpecificModel.IntervalTimeBlowOff;
}
// Object를 만들어
var param = new SeqTeachingRun_InitParam()
{
IsUseExternalObjects = true,
ExternalObjects = CreateDotForLaserOn(),
//UseStream = _EquipmentInfo.UseStream,
UseStream = currentModelInfo.equipmentSpecificModel.UseStream,
UseBlow = currentModelInfo.equipmentSpecificModel.UseBlow,
IntervalTimeBlowOn = intervalTimeBlowOn,
IntervalTimeBlowOff = intervalTimeBlowOff,
NeedSetLaserTiming = true,
};
_SeqTeachingRun.Start(param, OnCompleteMarkGrid);
} else {
LaserPowerCalParam powerCalParam = Status.AuroraEnv.SettingEntry[CommonSettingIds.LaserPowerCalParam] as LaserPowerCalParam;
float powerVolt1 = 0, powerVolt2 = 0;
powerCalParam.Initialize(powerCalParam.PowerCalibrationCenterBeamCSVFile, powerCalParam.PowerCalibrationRingBeamCSVFile);
powerVolt1 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower1Percent, (uint)LaserPowerCalParam.beamMode.Center) * 10;
powerVolt2 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower2Percent, (uint)LaserPowerCalParam.beamMode.Ring) * 10;
Thread.Sleep(50);
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, powerVolt1, eFunctionType.COMMAND);
_Scanner.WriteDA((uint)eAnalogPortOut.DA2, powerVolt2, eFunctionType.COMMAND);
_Scanner.SetLaserPulseCtrl(LaserPeriod * 1000, LaserPulseWidth);
//_Scanner.SetLaserTiming(LaserPeriod * 1000, LaserPulseWidth, LaserPulseWidth);
//_Scanner.SetStandby(LaserPeriod * 1000, LaserPulseWidth);
_Scanner.LaserSignalOn();
}
}
private void OnCompleteMarkGrid(SequenceActionResult res)
{
if (res != null) {
if (res.Param is SeqTeachingRun_OutParam result && result.Success == true) {
MessageUtil.ShowSuccessToast(string.Format("Success SeqMarkGrid"));
return;
}
}
MessageUtil.ShowWarningToast(string.Format("Fail SeqMarkGrid"));
}
private void PerformCmdLaserShotOff(object obj)
{
if (IsUseLaserAutoOffChecked) {
_Scanner.StopExecution();
} else {
_Scanner.LaserSignalOff();
}
_Scanner.SetStandby(10, 0);
}
private void PerformCmdResetEncoderValue(object obj)
{
try {
_Scanner.InitFly2D();
// CBW OTW 테스트를 위해 아래는 일단 주석처리
//m_scannerUnit.SetFlyX(m_scannerUnit.ScannerUnitParamObj.MarkingOnTheFlyEncoderResolutionX);
// list 반복 숫자 초기화
_ListIterationCount = 0;
} catch (Exception ex) {
MessageUtil.ShowErrorToast(string.Format($"{ex.Message}"));
}
}
private void PerformCmdActivateOnTheFly(object obj)
{
_Scanner.SetRotateCenter(RotateCenterX, RotateCenterY);
// list 1
_Scanner.SetStartList(eListNo.LIST1);
_Scanner.SetFlyRotate(EncoderResolution);
_Scanner.SetLaserTiming(10, 100, 100); // 아무거나
_Scanner.SetStandby(10, 0); // 아무거나
_Scanner.LaserOnList(LaserOnTime); // 1000이 1초
_Scanner.SetEndList();
// End - list1
_Scanner.ExecuteList(eListNo.LIST1);
}
private void PerformCmdDeactivateOnTheFly(object obj)
{
_Scanner.SetStartList(eListNo.LIST1);
_Scanner.Fly_Return(0, 0);
_Scanner.SetEndList();
_Scanner.ExecuteList(eListNo.LIST1);
}
private void PerformCmdSimulateEncoder(object obj)
{
if (_ToggleSimulateEncoder) {
_Scanner.SimulateEncoder(0);
_ToggleSimulateEncoder = false;
} else {
_ToggleSimulateEncoder = true;
_Scanner.SimulateEncoder(1);
}
}
private void PerformCmdSimulateEncoderXY(object obj)
{
if (_ToggleSimulateEncoder) {
_Scanner.SimulateEncoder(0);
_ToggleSimulateEncoder = false;
} else {
_ToggleSimulateEncoder = true;
_Scanner.SimulateEncoder(3);
}
}
private List<IDrawObject> CreateDotForLaserOn()
{
LaserPowerCalParam powerCalParam = Status.AuroraEnv.SettingEntry[CommonSettingIds.LaserPowerCalParam] as LaserPowerCalParam;
ScannerParam param = new ScannerParam();
param.LaserPower1 = (uint)(LaserPower1Percent / 100 * LaserPowerCalParam.MaxCenterPower);// = LaserPower1; // 변경 필요
param.LaserPower2 = (uint)(LaserPower2Percent / 100 * LaserPowerCalParam.MaxRingPower);// = LaserPower1; // 변경 필요
param.MarkSpeed = 200;
param.JumpSpeed = 1000;
param.SpotShotTime = LaserOnTime; // 변경 필요
param.LaserFrequency = 1000;
param.LaserPulseDuration = 1000;
param.MarkDelay = 200;
param.JumpDelay = 200;
param.PolygonDelay = 200;
ScannerCanvasUserCtrl.ScannerParams[127] = param;
Dot dot = new Dot();
_Scanner.GetXYPos(out double xPos, out double yPos);
dot.P1 = new UnitPoint(xPos, yPos);
dot.Enabled = true;
dot.Selected = true;
dot.ScannerParamNo = 127;
List<IDrawObject> drawObjects = new List<IDrawObject>();
drawObjects.Add(dot);
return drawObjects;
}
// 일단 이건 1 source 에서 가져옴. view 에서 주석처리 된 부분
//private void ApplyAnalogValue(object obj)
//{
// try {
// //DA1, DA2 Combobox 이벤트로 현재값을 AnalogVaule에 보여주고싶으나 해야될게많다..
// //일단 유저가 셋팅만 해서 쓰는 걸로하자..
// if (AnalogPortSelectedIndex == 0) {
// DA1PercentLaser = (float)AnalogValue;
// } else if (AnalogPortSelectedIndex == 1) {
// DA2PercentLaser = (float)AnalogValue;
// } else {
// MessageDialog.Show(Application.Current.MainWindow, "LaserManual", "Check AnalogPortIndex", MessageDialog.Type.Affirmative);
// }
// } catch (Exception ex) {
// Log.E(string.Format($"{ex.Message}"));
// }
//}
}
}