feat: [대면적 MOTF] 레시피 저장/로드 및 페이지 자동 생성 기반 구현 (26.04.10)
- [Line.cs] LargeMOTFPositionX/Y 프로퍼티 추가 ([XmlSerializable]) - [DrawingLayer.cs] LargeMOTFOffsetX/Y 프로퍼티 추가 ([XmlSerializable]) - [RecipeWeldingLines.cs] UseLargeMOTF, LargeMOTFPageCount 프로퍼티 추가 ([XmlSerializable]) - Load() 에 XmlUtil.ParseProperties() 추가하여 로드 시 반영 - [MainPage.cs] - UpdateLargeMOTFPosition() 추가: 저장 직전 Layer별 마지막 Line PF2를 LargeMOTFPositionX/Y에 자동 SET - OnRecipeReloaded 이벤트 추가: 레시피 로드 완료 시 콜백 - GenerateFlippedPages() 추가: EndSet 시 Page3(P2 Y플립), Page4(P1 Y플립) 자동 생성 - [UCScannerObjectTeachingViewModel.cs] - OnSaved(): UpdateLargeMOTFPosition, UseLargeMOTF/LargeMOTFPageCount 저장 직전 반영 - OnChanged(), Reloaded(): 레시피 로드 시 IsUseLargeMOTF, LargeMOTFPageCount UI 반영 - 생성자: OnRecipeReloaded 이벤트 등록하여 프로그램 시작 시 UI 반영 - [UCScannerObjectTeachingControlBoxViewModel.cs] - PerformCmdLargeMOTFEndSet(): LargeMOTFOffsetX 계산 후 GenerateFlippedPages() 호출 - OnRecipeReloaded 시 LargeMOTFOffsetX UI 반영 (Layer[1] 기준)
This commit is contained in:
parent
5b686c503a
commit
f5d68248c9
@ -1 +0,0 @@
|
||||
,DESKTOP-CN4O63O/User,DESKTOP-CN4O63O,09.04.2026 15:52,file:///C:/Users/User/AppData/Roaming/LibreOffice/4;
|
||||
Binary file not shown.
@ -40,6 +40,9 @@ namespace ILSOS_PrismaticScanner
|
||||
public const string SeqAlarmMonitor = "SeqAlarmMonitor";
|
||||
public const string SeqStatusMonitor = "SeqStatusMonitor";
|
||||
|
||||
// 26.04.09 NDY - ACS MOTF AutoRun - > SeqAutoRun은 CommonSequenceIds에 존재함.
|
||||
public const string SeqAutoRunACS = "SeqAutoRunACS";
|
||||
|
||||
}
|
||||
|
||||
public class StreamMessageNames
|
||||
|
||||
@ -64,6 +64,9 @@ namespace ILSOS_PrismaticScanner
|
||||
private SequenceBuilder _SeqAutoRunPrismaticScanner_Builder;
|
||||
private SequenceBuilder _SeqAutoRunComponentWeld_Builder;
|
||||
private SequenceBuilder _SeqAlarmMonitor_Builder;
|
||||
#region 26.04.09 NDY - ACS MOTF AutoRun Sequence Builder
|
||||
private SequenceBuilder _SeqAutoRunPrismaticScannerACS_Builder;
|
||||
#endregion
|
||||
|
||||
|
||||
public override void BuildMainStatusView(MainStatusBuilder builder)
|
||||
@ -265,28 +268,30 @@ namespace ILSOS_PrismaticScanner
|
||||
// Common Sequences register
|
||||
SequenceManager.RegisterSequence(AuroraEnv, register);
|
||||
base.RegisterSequences(register);
|
||||
|
||||
var equipSetting = AuroraEnv.SettingEntry[AuroraSettings.Equipment] as EquipmentInfo;
|
||||
register(SequenceIds.SeqStreamTest, SeqStreamTest.Builder());
|
||||
|
||||
// Event Q Test 추가
|
||||
var seqEventQTest = new SeqEventQTest();
|
||||
register(SequenceIds.SeqEventQTest, seqEventQTest.Builder());
|
||||
|
||||
var seqAutoRunPrismaticScanner = new SeqAutoRunPrismaticScanner();
|
||||
var seqAutoRunComponentWeld = new SeqAutoRunComponentWeld();
|
||||
var seqAlarmMonitor = new SeqAlarmMonitor();
|
||||
|
||||
_SeqAutoRunPrismaticScanner_Builder = seqAutoRunPrismaticScanner.Builder();
|
||||
_SeqAutoRunComponentWeld_Builder = seqAutoRunComponentWeld.Builder();
|
||||
_SeqAlarmMonitor_Builder = seqAlarmMonitor.Builder();
|
||||
|
||||
register(SequenceIds.SeqAutoRun, _SeqAutoRunPrismaticScanner_Builder);
|
||||
register(SequenceIds.SeqAutoRunComponentWeld, _SeqAutoRunComponentWeld_Builder);
|
||||
register(SequenceIds.SeqAlarmMonitor, _SeqAlarmMonitor_Builder);
|
||||
register(SequenceIds.SeqStatusMonitor, SeqStatusMonitor.Builder());
|
||||
|
||||
// SequenceManager.RegisterSequence(AuroraEnv, register);
|
||||
|
||||
#region 26.04.09 NDY - ACS MOTF AutoRun Sequence 등록
|
||||
// 기존 SeqAutoRun(SeqAutoRunPrismaticScanner)은 건드리지 않고
|
||||
// ACS MOTF 전용 시퀀스를 별도 Builder로 등록
|
||||
var seqAutoRunPrismaticScannerACS = new SeqAutoRunPrismaticScannerACS();
|
||||
_SeqAutoRunPrismaticScannerACS_Builder = seqAutoRunPrismaticScannerACS.Builder();
|
||||
register(SequenceIds.SeqAutoRunACS, _SeqAutoRunPrismaticScannerACS_Builder);
|
||||
#endregion
|
||||
}
|
||||
|
||||
public override void RegisterSettings(SettingRegister register) {
|
||||
@ -384,13 +389,13 @@ namespace ILSOS_PrismaticScanner
|
||||
manager.RegisterMainMenu(calibration);
|
||||
|
||||
// Monitoring
|
||||
#region 26 04 06 주석처리 PLCBitMonitoring PLCWordMonitoring IOInterfaceView (o) PLCInterfaceView (원래부터 주석처리)
|
||||
//var monitoring = new MainMenu(CommonViewIds.Monitoring, MenuIcon.GetMenuIcon(eMenuIcon.MONITORING), PermissionLevel.NONE, true);
|
||||
////manual.AddSubMenu(CommonViewIds.PLCInterfaceView, new UCPLCInterfaceView(AuroraEnv, CommonDeviceIds.PLCDevice));
|
||||
//monitoring.AddSubMenu(CommonViewIds.PLCBitMonitoring, new UCPLCBit() { DataContext = PLCStatic.GetInstanceBitVM(AuroraEnv, CommonDeviceIds.PLCDevice, ePLCNetType.MXComponent, PLCBase.ePLCDevice.M) });
|
||||
//monitoring.AddSubMenu(CommonViewIds.PLCWordMonitoring, new UCPLCWord() { DataContext = PLCStatic.GetInstanceWordVM(AuroraEnv, CommonDeviceIds.PLCDevice, ePLCNetType.MXComponent, PLCBase.ePLCDevice.D) });
|
||||
//monitoring.AddSubMenu(CommonViewIds.IOInterfaceView, new UCIOInterfaceView(AuroraEnv, CommonDeviceIds.IODevice));
|
||||
//manager.RegisterMainMenu(monitoring);
|
||||
#region 26 04 06 주석처리 PLCBitMonitoring PLCWordMonitoring IOInterfaceView (o) PLCInterfaceView (원래부터 주석처리) - 04.10 잠시 추가
|
||||
var monitoring = new MainMenu(CommonViewIds.Monitoring, MenuIcon.GetMenuIcon(eMenuIcon.MONITORING), PermissionLevel.NONE, true);
|
||||
//manual.AddSubMenu(CommonViewIds.PLCInterfaceView, new UCPLCInterfaceView(AuroraEnv, CommonDeviceIds.PLCDevice));
|
||||
monitoring.AddSubMenu(CommonViewIds.PLCBitMonitoring, new UCPLCBit() { DataContext = PLCStatic.GetInstanceBitVM(AuroraEnv, CommonDeviceIds.PLCDevice, ePLCNetType.MXComponent, PLCBase.ePLCDevice.M) });
|
||||
monitoring.AddSubMenu(CommonViewIds.PLCWordMonitoring, new UCPLCWord() { DataContext = PLCStatic.GetInstanceWordVM(AuroraEnv, CommonDeviceIds.PLCDevice, ePLCNetType.MXComponent, PLCBase.ePLCDevice.D) });
|
||||
monitoring.AddSubMenu(CommonViewIds.IOInterfaceView, new UCIOInterfaceView(AuroraEnv, CommonDeviceIds.IODevice));
|
||||
manager.RegisterMainMenu(monitoring);
|
||||
#endregion
|
||||
|
||||
// Device
|
||||
|
||||
@ -110,6 +110,7 @@
|
||||
<Compile Include="Sequences\Monitoring\SeqStatusMonitor.cs" />
|
||||
<Compile Include="Sequences\SeqAutoRunComponentWeld.cs" />
|
||||
<Compile Include="Sequences\SeqAutoRunPrismaticScanner.cs" />
|
||||
<Compile Include="Sequences\SeqAutoRunPrismaticScannerACS.cs" />
|
||||
<Compile Include="Sequences\SeqEventQTest.cs" />
|
||||
<Compile Include="Sequences\SeqStreamTest.cs" />
|
||||
<Compile Include="Sequences\SequenceContextEx.cs" />
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,12 @@ namespace ILSOS_PrismaticScanner.Sequences
|
||||
SeqTeachingRun _SeqTeachingRun;
|
||||
SeqComponentTeachingRun _SeqComponentTeachingRun;
|
||||
|
||||
#region 26.04.09 NDY - ACS MOTF AutoRun Sequence
|
||||
// 기존 SeqAutoRunPrismaticScanner와 별개로 추가
|
||||
// ACS 모션(Stage X 등) + 갈바노 스캐너 MOTF 자동운전 전용
|
||||
SeqAutoRunPrismaticScannerACS _SeqAutoRunPrismaticScannerACS;
|
||||
#endregion
|
||||
|
||||
private static Dictionary<string, SequenceBuilder> mapSequenceBuilders = new Dictionary<string, SequenceBuilder>();
|
||||
|
||||
static SequenceManager()
|
||||
@ -56,12 +62,17 @@ namespace ILSOS_PrismaticScanner.Sequences
|
||||
|
||||
private void ChangeRunState(ISequenceEntry sequenceEntry, string sequenceId, bool isRunning, object param = null)
|
||||
{
|
||||
if (isRunning) {
|
||||
if (sequenceEntry[sequenceId].RunState != SequenceRunState.Running) {
|
||||
if (isRunning)
|
||||
{
|
||||
if (sequenceEntry[sequenceId].RunState != SequenceRunState.Running)
|
||||
{
|
||||
sequenceEntry[sequenceId].Start(param);
|
||||
}
|
||||
} else {
|
||||
if (sequenceEntry[sequenceId].RunState == SequenceRunState.Running) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sequenceEntry[sequenceId].RunState == SequenceRunState.Running)
|
||||
{
|
||||
sequenceEntry[sequenceId].Stop();
|
||||
}
|
||||
}
|
||||
@ -84,66 +95,87 @@ namespace ILSOS_PrismaticScanner.Sequences
|
||||
//register(CommonSequenceIds.DeviceMonitor, DeviceMonitoring.Builder());
|
||||
base.Register(aurora, register);
|
||||
|
||||
if (_SeqMarkGrid == null) {
|
||||
if (_SeqMarkGrid == null)
|
||||
{
|
||||
_SeqMarkGrid = new SeqMarkGrid();
|
||||
}
|
||||
register(CommonSequenceIds.SeqMarkGrid, _SeqMarkGrid.Builder());
|
||||
|
||||
if (_SeqScannerCalibration == null) {
|
||||
if (_SeqScannerCalibration == null)
|
||||
{
|
||||
_SeqScannerCalibration = new SeqScannerCalibration();
|
||||
}
|
||||
register(CommonSequenceIds.SeqScannerCalibration, _SeqScannerCalibration.Builder());
|
||||
|
||||
if (_SeqReceiveCellInfo == null) {
|
||||
if (_SeqReceiveCellInfo == null)
|
||||
{
|
||||
_SeqReceiveCellInfo = new SeqReceiveCellInfo();
|
||||
}
|
||||
register(CommonSequenceIds.SeqReceiveCellInfo, _SeqReceiveCellInfo.Builder());
|
||||
|
||||
if (_SeqReportCellResult == null) {
|
||||
if (_SeqReportCellResult == null)
|
||||
{
|
||||
_SeqReportCellResult = new SeqReportCellResult();
|
||||
}
|
||||
register(CommonSequenceIds.SeqReportCellResult, _SeqReportCellResult.Builder());
|
||||
|
||||
if (_SeqScoutFlyingVision == null) {
|
||||
if (_SeqScoutFlyingVision == null)
|
||||
{
|
||||
_SeqScoutFlyingVision = new SeqScoutFlyingVision();
|
||||
}
|
||||
register(CommonSequenceIds.SeqScoutFlyingVision, _SeqScoutFlyingVision.Builder());
|
||||
|
||||
if (_SeqScoutNormal == null) {
|
||||
if (_SeqScoutNormal == null)
|
||||
{
|
||||
_SeqScoutNormal = new SeqScoutNormal();
|
||||
}
|
||||
register(CommonSequenceIds.SeqScoutNormal, _SeqScoutNormal.Builder());
|
||||
|
||||
|
||||
if (_SeqExecutePlcBitInterface == null) {
|
||||
if (_SeqExecutePlcBitInterface == null)
|
||||
{
|
||||
_SeqExecutePlcBitInterface = new SeqExecutePlcBitInterface();
|
||||
}
|
||||
register(CommonSequenceIds.SeqExecutePlcBitInterface, _SeqExecutePlcBitInterface.Builder());
|
||||
|
||||
if (_SeqExecutePlcBitInterfaceForStatusChange == null) {
|
||||
if (_SeqExecutePlcBitInterfaceForStatusChange == null)
|
||||
{
|
||||
_SeqExecutePlcBitInterfaceForStatusChange = new SeqExecutePlcBitInterface();
|
||||
}
|
||||
register(CommonSequenceIds.SeqExecutePlcBitInterfaceForStatusChange, _SeqExecutePlcBitInterfaceForStatusChange.Builder());
|
||||
|
||||
if (_SeqCheckWeldingComplete == null) {
|
||||
if (_SeqCheckWeldingComplete == null)
|
||||
{
|
||||
_SeqCheckWeldingComplete = new SeqCheckWeldingComplete();
|
||||
}
|
||||
register(CommonSequenceIds.SeqCheckWeldingComplete, _SeqCheckWeldingComplete.Builder());
|
||||
|
||||
if (_SeqTeachingRun == null) {
|
||||
if (_SeqTeachingRun == null)
|
||||
{
|
||||
_SeqTeachingRun = new SeqTeachingRun();
|
||||
}
|
||||
register(CommonSequenceIds.SeqTeachingRun, _SeqTeachingRun.Builder());
|
||||
|
||||
if (_SeqComponentTeachingRun == null) {
|
||||
if (_SeqComponentTeachingRun == null)
|
||||
{
|
||||
_SeqComponentTeachingRun = new SeqComponentTeachingRun();
|
||||
}
|
||||
register(CommonSequenceIds.SeqComponentTeachingRun, _SeqComponentTeachingRun.Builder());
|
||||
|
||||
if (_SeqWaitWeldOrChangePage == null) {
|
||||
if (_SeqWaitWeldOrChangePage == null)
|
||||
{
|
||||
_SeqWaitWeldOrChangePage = new SeqWaitWeldOrChangePage();
|
||||
}
|
||||
register(CommonSequenceIds.SeqWaitWeldOrChangePage, _SeqWaitWeldOrChangePage.Builder());
|
||||
|
||||
#region 26.04.09 NDY - ACS MOTF AutoRun Sequence 등록
|
||||
// 기존 SeqAutoRun(SeqAutoRunPrismaticScanner)은 건드리지 않고
|
||||
// ACS MOTF 전용 시퀀스를 별도 ID(SeqAutoRunACS)로 등록
|
||||
if (_SeqAutoRunPrismaticScannerACS == null)
|
||||
{
|
||||
_SeqAutoRunPrismaticScannerACS = new SeqAutoRunPrismaticScannerACS();
|
||||
}
|
||||
register(SequenceIds.SeqAutoRunACS, _SeqAutoRunPrismaticScannerACS.Builder());
|
||||
#endregion
|
||||
}
|
||||
|
||||
// MainProcess Sequence
|
||||
@ -161,9 +193,13 @@ namespace ILSOS_PrismaticScanner.Sequences
|
||||
public static SequenceBuilder GetSeqBuilder_SeqTeachingRun() { return Instance._SeqTeachingRun.Builder(); }
|
||||
public static SequenceBuilder GetSeqBuilder_SeqComponentTeachingRun() { return Instance._SeqComponentTeachingRun.Builder(); }
|
||||
|
||||
#region 26.04.09 NDY - ACS MOTF AutoRun Sequence GetSeqBuilder
|
||||
public static SequenceBuilder GetSeqBuilder_SeqAutoRunPrismaticScannerACS() { return Instance._SeqAutoRunPrismaticScannerACS.Builder(); }
|
||||
#endregion
|
||||
|
||||
public virtual void Terminate()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,13 +53,35 @@
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<GroupBox Grid.Row="0" Header="Manual Control" Margin="0 0 0 0">
|
||||
<Grid Height="50" Margin="0 0 0 0">
|
||||
<Grid Height="100" Margin="0 0 0 0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="1*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0" Margin="3 0 3 2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="auto" FontWeight="Bold" Style="{StaticResource StButtonAccentPurple}" Command="{Binding CMD_RunSequenceAutoRun}" Content="Run AutoRun" IsEnabled="{Binding IsSequenceRunning_AutoRun, Converter={StaticResource convReverse}}"/>
|
||||
<Button Grid.Column="1" Margin="3 0 3 2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="auto" FontWeight="Bold" Style="{StaticResource StButtonAccentPurple}" Command="{Binding CMD_StopSequenceAutoRun}" Content="Stop" IsEnabled="{Binding IsSequenceRunning_AutoRun}"/>
|
||||
<Button Grid.Row="0" Grid.Column="0" Margin="3 0 3 2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="auto" FontWeight="Bold" Style="{StaticResource StButtonAccentPurple}" Command="{Binding CMD_RunSequenceAutoRun}" Content="Run AutoRun" IsEnabled="{Binding IsSequenceRunning_AutoRun, Converter={StaticResource convReverse}}"/>
|
||||
<Button Grid.Row="0" Grid.Column="1" Margin="3 0 3 2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="auto" FontWeight="Bold" Style="{StaticResource StButtonAccentPurple}" Command="{Binding CMD_StopSequenceAutoRun}" Content="Stop" IsEnabled="{Binding IsSequenceRunning_AutoRun}"/>
|
||||
|
||||
<GridSplitter HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Height="2" ToolTip="구분선 -> 상단 기존 동작 / 하단 추가된 시퀸스 테스트 버튼"></GridSplitter>
|
||||
<!-- 26.04.10 NDY AUTORUN ACS 시퀸스 테스트 버튼 -->
|
||||
<Button Grid.Row="2" Grid.Column="0" Margin="3 0 3 2"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Height="auto" FontWeight="Bold"
|
||||
Style="{StaticResource StButtonAccentPurple}"
|
||||
Command="{Binding CMD_StartMOTF}"
|
||||
Content="Run MOTF"
|
||||
IsEnabled="{Binding IsSequenceRunning_AutoRun, Converter={StaticResource convReverse}}"/>
|
||||
<Button Grid.Row="2" Grid.Column="1" Margin="3 0 3 2"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Height="auto" FontWeight="Bold"
|
||||
Style="{StaticResource StButtonAccentPurple}"
|
||||
Command="{Binding CMD_StopMOTF}"
|
||||
Content="Stop"
|
||||
IsEnabled="{Binding IsSequenceRunning_AutoRun}"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<GroupBox Grid.Row="1" Header="Equipment Status" Margin="0 5 0 0">
|
||||
|
||||
@ -43,6 +43,11 @@ namespace ILSOS_PrismaticScanner.Views
|
||||
public ICommand CMD_StopSequenceAutoRun { get; }
|
||||
public ICommand CMD_Reset { get; } // Totoal Product, Today Product
|
||||
|
||||
#region 26.04.10 NDY - MOTF AutoRun Command
|
||||
public ICommand CMD_StartMOTF { get; }
|
||||
public ICommand CMD_StopMOTF { get; }
|
||||
#endregion
|
||||
|
||||
private readonly IRecipeManager _RecipeManager;
|
||||
private readonly ISettingEntry _SettingEntry;
|
||||
private readonly IAlarmService _AlarmService;
|
||||
@ -56,6 +61,12 @@ namespace ILSOS_PrismaticScanner.Views
|
||||
private ISequence _SeqPlcInterface;
|
||||
|
||||
private ISequence _SeqQTest;
|
||||
|
||||
#region 26.04.10 NDY - MOTF AutoRun Sequence
|
||||
// 기존 _SeqAutoRun과 별개로 MOTF 전용 시퀀스 참조
|
||||
private ISequence _SeqMOTF;
|
||||
#endregion
|
||||
|
||||
public bool IsSequenceRunning_AutoRun { get => _IsSequenceRunning_AutoRun; set => SetProperty(ref _IsSequenceRunning_AutoRun, value); }
|
||||
private bool _IsSequenceRunning_AutoRun;
|
||||
|
||||
@ -87,6 +98,12 @@ namespace ILSOS_PrismaticScanner.Views
|
||||
|
||||
// Q Test
|
||||
_SeqQTest = _Aurora.SequenceEntry[SequenceIds.SeqEventQTest];
|
||||
|
||||
#region 26.04.10 NDY - MOTF AutoRun Sequence 참조
|
||||
// 기존 SeqAutoRun과 별개로 MOTF 전용 시퀀스 ID로 참조
|
||||
_SeqMOTF = _Aurora.SequenceEntry[SequenceIds.SeqAutoRunACS];
|
||||
#endregion
|
||||
|
||||
InitVariable();
|
||||
|
||||
CMD_VisibleChanged = new DelegateCommand(VisibleChanged);
|
||||
@ -95,6 +112,12 @@ namespace ILSOS_PrismaticScanner.Views
|
||||
CMD_StopSequenceAutoRun = new DelegateCommand(OnStopSequenceAutoRun);
|
||||
CMD_Reset = new DelegateCommand(PerformCmdReset);
|
||||
|
||||
#region 26.04.10 NDY - MOTF AutoRun Command 등록
|
||||
// 기존 CMD_RunSequenceAutoRun / CMD_StopSequenceAutoRun 패턴과 동일
|
||||
CMD_StartMOTF = new DelegateCommand(OnMOTFStartRequest);
|
||||
CMD_StopMOTF = new DelegateCommand(OnStopMOTF);
|
||||
#endregion
|
||||
|
||||
_MonitorTimer = new DispatcherTimer();
|
||||
_MonitorTimer.Tick += OnMonitoring;
|
||||
_MonitorTimer.Interval = TimeSpan.FromMilliseconds(100);
|
||||
@ -150,6 +173,7 @@ namespace ILSOS_PrismaticScanner.Views
|
||||
// Page UI 업데이트
|
||||
RecipeHelper.UpdateAutorunRecipe();
|
||||
}
|
||||
|
||||
private void VisibleChanged(object obj)
|
||||
{
|
||||
bool visible = (bool)obj;
|
||||
@ -271,6 +295,54 @@ namespace ILSOS_PrismaticScanner.Views
|
||||
_Scanner.SelectCorrectionTable(1);
|
||||
}
|
||||
|
||||
#region 26.04.10 NDY - MOTF AutoRun 실행 / 정지
|
||||
// 기존 OnAutoRunStartRequest / OnStopSequenceAutoRun 패턴과 동일
|
||||
// 테스트 버튼용이므로 TimerMessageBox 확인 다이얼로그는 생략
|
||||
|
||||
private void OnMOTFStartRequest(object obj = null)
|
||||
{
|
||||
// 기존 AutoRun 인터락 조건 동일하게 적용
|
||||
if (_SeqMOTF.RunState == SequenceRunState.Running) {
|
||||
MessageUtil.ShowWarningToast("이미 MOTF 시퀀스가 Start 상태입니다.", Log);
|
||||
return;
|
||||
}
|
||||
|
||||
// 자동으로 Activated Recipe로 변경
|
||||
OnUpdateCurrentActivatedRecipe(null);
|
||||
|
||||
Status.GetProcessingWeldingData().AutoRunStartTime = DateTime.Now;
|
||||
Status.SetStatus(eEqpStatus.Auto);
|
||||
|
||||
var param = new SeqAutoRunPrismaticScannerACS_InitParam();
|
||||
_SeqMOTF.Start(param, OnCompleteMOTF);
|
||||
|
||||
Log.I("MOTF Sequence Started");
|
||||
}
|
||||
|
||||
private void OnCompleteMOTF(SequenceActionResult res)
|
||||
{
|
||||
// 기존 OnCompleteAutoRun 패턴과 동일
|
||||
if (res != null) {
|
||||
if (res.Param is SeqAutoRunPrismaticScannerACS_OutParam result && result.Success == true) {
|
||||
MessageUtil.ShowSuccessToast("Success MOTF Sequence");
|
||||
return;
|
||||
}
|
||||
}
|
||||
MessageUtil.ShowWarningToast("Fail MOTF Sequence");
|
||||
}
|
||||
|
||||
private void OnStopMOTF(object obj = null)
|
||||
{
|
||||
// 기존 OnStopSequenceAutoRun 패턴과 동일
|
||||
if (_SeqMOTF.RunState == SequenceRunState.Idle) {
|
||||
return;
|
||||
}
|
||||
|
||||
_SeqMOTF.Stop();
|
||||
Log.I("MOTF Sequence Stopped");
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void PerformCmdReset(object commandParameter)
|
||||
{
|
||||
// SystemParameter를 저장하기 전에는 반드시 업데이트를 해주어야 한다.
|
||||
@ -317,4 +389,4 @@ namespace ILSOS_PrismaticScanner.Views
|
||||
keyboardInput,
|
||||
ClickInput
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
using CoreUnit.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
@ -31,9 +32,12 @@ namespace CoreUnit.Control.UserControl.Canvas
|
||||
}
|
||||
|
||||
#region 26.04.09
|
||||
// 26.04.09 NDY [대면적 MOTF] 페이지 레벨 Offset 파라미터 추가
|
||||
// 26.04.09 NDY [대면적 MOTF] 페이지 레벨 Offset 파라미터 추가 - 26.04.10 XmlSerializable 어트리뷰트 추가
|
||||
[XmlSerializable]
|
||||
public double LargeMOTFOffsetX { get; set; } = 0.0;
|
||||
[XmlSerializable]
|
||||
public double LargeMOTFOffsetY { get; set; } = 0.0;
|
||||
|
||||
#endregion
|
||||
|
||||
public DrawingLayer(int no, string name, Color color, float width)
|
||||
|
||||
@ -23,8 +23,10 @@ namespace DB.Recipe
|
||||
{
|
||||
|
||||
#region 26.04.09 NDY
|
||||
// 26.04.09 NDY [대면적 MOTF] 레시피 레벨 파라미터 추가
|
||||
// 26.04.09 NDY [대면적 MOTF] 레시피 레벨 파라미터 추가 - 04.10 [XmlSerializable] 추가함.
|
||||
[XmlSerializable]
|
||||
public bool UseLargeMOTF { get; set; } = false;
|
||||
[XmlSerializable]
|
||||
public int LargeMOTFPageCount { get; set; } = 1;
|
||||
#endregion
|
||||
|
||||
@ -90,8 +92,11 @@ namespace DB.Recipe
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadWeldingParam(xmlElement);
|
||||
Model.Load(xmlElement);
|
||||
#region 26.04.10 NDY [대면적 MOTF] 레시피 레벨 파라미터 로드
|
||||
CoreUnit.Common.XmlUtil.ParseProperties(xmlElement, this);
|
||||
#endregion
|
||||
LoadWeldingParam(xmlElement); // WeldingParameters만 로드
|
||||
Model.Load(xmlElement); // DrawingObjects만 로드
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -13,6 +13,7 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -34,6 +35,135 @@ namespace GUI
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
#region 26.04.10 NDY에 추가함.
|
||||
// MainPage.cs에 추가
|
||||
public void UpdateLargeMOTFPosition()
|
||||
{
|
||||
foreach (ICanvasLayer layer in ScannerCanvasCtrlTeaching.Model.Layers)
|
||||
{
|
||||
var lines = layer.Objects
|
||||
.OfType<Line>()
|
||||
.OrderBy(l => l.No)
|
||||
.ToList();
|
||||
if (lines.Count == 0) continue;
|
||||
|
||||
float motfX = lines.Last().PF2.X;
|
||||
float motfY = lines.Last().PF2.Y;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
line.LargeMOTFPositionX = motfX;
|
||||
line.LargeMOTFPositionY = motfY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateFlippedPages(double largeMOTFOffsetX)
|
||||
{
|
||||
try
|
||||
{
|
||||
var model = ScannerCanvasCtrlTeaching.Model;
|
||||
var layers = model.Layers;
|
||||
|
||||
Debug.WriteLine($"[GenerateFlippedPages] 시작 - Layer 수: {layers.Count()}");
|
||||
|
||||
if (layers.Count() < 2)
|
||||
{
|
||||
Debug.WriteLine("[GenerateFlippedPages] Layer 2개 미만 - 종료");
|
||||
return;
|
||||
}
|
||||
|
||||
// 기존 Layer[2], Layer[3] 삭제
|
||||
while (layers.Count() > 2)
|
||||
{
|
||||
Debug.WriteLine($"[GenerateFlippedPages] Layer 삭제 - 현재 수: {layers.Count()}");
|
||||
model.DeleteLayer(layers.Count() - 1);
|
||||
}
|
||||
Debug.WriteLine($"[GenerateFlippedPages] 삭제 후 Layer 수: {layers.Count()}");
|
||||
|
||||
var p1Lines = layers[0].Objects.OfType<Line>().OrderBy(l => l.No).ToList();
|
||||
var p2Lines = layers[1].Objects.OfType<Line>().OrderBy(l => l.No).ToList();
|
||||
Debug.WriteLine($"[GenerateFlippedPages] P1 Line 수: {p1Lines.Count}, P2 Line 수: {p2Lines.Count}");
|
||||
|
||||
if (p1Lines.Count == 0 || p2Lines.Count == 0)
|
||||
{
|
||||
Debug.WriteLine("[GenerateFlippedPages] Line 없음 - 종료");
|
||||
return;
|
||||
}
|
||||
|
||||
float flipYforP3 = p2Lines.Last().PF2.Y;
|
||||
float flipYforP4 = p1Lines.First().PF1.Y;
|
||||
Debug.WriteLine($"[GenerateFlippedPages] flipYforP3={flipYforP3:F3}, flipYforP4={flipYforP4:F3}");
|
||||
|
||||
// Page3 생성 = Page2 Y플립
|
||||
model.CreateLayer();
|
||||
Debug.WriteLine($"[GenerateFlippedPages] CreateLayer(P3) 후 Layer 수: {layers.Count()}");
|
||||
|
||||
if (layers.Count() < 3)
|
||||
{
|
||||
Debug.WriteLine("[GenerateFlippedPages] P3 Layer 생성 실패 - 종료");
|
||||
return;
|
||||
}
|
||||
|
||||
var layer2 = layers[2] as DrawingLayer;
|
||||
if (layer2 == null)
|
||||
{
|
||||
Debug.WriteLine("[GenerateFlippedPages] layer2 캐스팅 실패 - 종료");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var srcLine in p2Lines)
|
||||
{
|
||||
var newLine = new Line();
|
||||
newLine.Copy(srcLine);
|
||||
newLine.PF1 = new System.Drawing.PointF(
|
||||
srcLine.PF1.X, 2 * flipYforP3 - srcLine.PF1.Y);
|
||||
newLine.PF2 = new System.Drawing.PointF(
|
||||
srcLine.PF2.X, 2 * flipYforP3 - srcLine.PF2.Y);
|
||||
layer2.AddObject(newLine);
|
||||
}
|
||||
Debug.WriteLine($"[GenerateFlippedPages] P3 Line {p2Lines.Count}개 추가 완료");
|
||||
|
||||
// Page4 생성 = Page1 Y플립
|
||||
model.CreateLayer();
|
||||
Debug.WriteLine($"[GenerateFlippedPages] CreateLayer(P4) 후 Layer 수: {layers.Count()}");
|
||||
|
||||
if (layers.Count() < 4)
|
||||
{
|
||||
Debug.WriteLine("[GenerateFlippedPages] P4 Layer 생성 실패 - 종료");
|
||||
return;
|
||||
}
|
||||
|
||||
var layer3 = layers[3] as DrawingLayer;
|
||||
if (layer3 == null)
|
||||
{
|
||||
Debug.WriteLine("[GenerateFlippedPages] layer3 캐스팅 실패 - 종료");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var srcLine in p1Lines)
|
||||
{
|
||||
var newLine = new Line();
|
||||
newLine.Copy(srcLine);
|
||||
newLine.PF1 = new System.Drawing.PointF(
|
||||
srcLine.PF1.X, 2 * flipYforP4 - srcLine.PF1.Y);
|
||||
newLine.PF2 = new System.Drawing.PointF(
|
||||
srcLine.PF2.X, 2 * flipYforP4 - srcLine.PF2.Y);
|
||||
layer3.AddObject(newLine);
|
||||
}
|
||||
Debug.WriteLine($"[GenerateFlippedPages] P4 Line {p1Lines.Count}개 추가 완료");
|
||||
|
||||
UpdateWeldingLinesRecipe();
|
||||
Debug.WriteLine($"[GenerateFlippedPages] 완료 - OffsetX={largeMOTFOffsetX:F3}");
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[GenerateFlippedPages] 예외 발생: {ex.Message}");
|
||||
Debug.WriteLine($"[GenerateFlippedPages] StackTrace: {ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 2.메인화면: 다이얼로그 및 페이지 초기화 함수
|
||||
|
||||
private void ClearDisplayedError()
|
||||
@ -457,6 +587,7 @@ namespace GUI
|
||||
UtilUnit.logUnit.SetLog(LogUnit.eLogType.ALARM, MethodBase.GetCurrentMethod().Name, ex.Message);
|
||||
}
|
||||
}
|
||||
public event Action OnRecipeReloaded; // 26.04.10 추가 MainPage에 콜백추가를 위한 액션
|
||||
public void ReloadRecipe(string fullpath)
|
||||
{
|
||||
ScannerCanvasCtrlTeaching.Canvas.CommandEscape();
|
||||
@ -467,12 +598,17 @@ namespace GUI
|
||||
|
||||
UpdateWeldingLinesRecipe();
|
||||
|
||||
// 26.04.10 NDY [대면적 MOTF]
|
||||
OnRecipeReloaded?.Invoke();
|
||||
|
||||
|
||||
//// Page 불러온 후, 실행되지 않아도 됨. 왜냐하면, 어차피 SelectedIndex 쪽으로 빠짐.
|
||||
//SaveAndLoadFieldScanFromLasaDb();
|
||||
//ChangeScoutImage();
|
||||
}
|
||||
#endregion
|
||||
|
||||
// 26.04.10 확인용 --- MainPage의 레시피 정보를 Get 하는 메소드
|
||||
public RecipeWeldingLines getRecipeInfo(string fullpath)
|
||||
{
|
||||
var recipe = new RecipeWeldingLines();
|
||||
|
||||
@ -294,6 +294,18 @@ namespace WeldingCommon.Views
|
||||
}
|
||||
|
||||
// 26.04.09 NDY [대면적 MOTF] End Set 커맨드 구현
|
||||
//최종 구현하고자 하는 방향성
|
||||
//{
|
||||
// 1. Layer[0] (P1), Layer[1] (P2) 원본 확인
|
||||
// 2. Layer[2] 생성 = P3(P2 Y플립)
|
||||
// - 플립 기준Y = Layer[1] 마지막 Line PF2.Y
|
||||
// - P2의 Line들을 역순으로 복사 + Y좌표 플립
|
||||
// 3. Layer[3] 생성 = P4(P1 Y플립)
|
||||
// - 플립 기준Y = Layer[0] 첫 Line PF1.Y
|
||||
// - P1의 Line들을 역순으로 복사 + Y좌표 플립
|
||||
// 4. 기존 Layer[2],[3] 있으면 삭제 후 재생성
|
||||
// 5. MessageUtil로 결과 안내
|
||||
//}
|
||||
private void PerformCmdLargeMOTFEndSet(object obj)
|
||||
{
|
||||
var result = MessageUtil.ShowYesNoMessageDialog("Large MOTF End Set",
|
||||
@ -326,6 +338,9 @@ namespace WeldingCommon.Views
|
||||
Log.I($" - 계산된 Offset Y (Scanner): {LargeMOTFOffsetY:F3} mm");
|
||||
Log.I($" - 저장된 Layer: Page {mainPage.ScannerCanvasCtrlTeaching.Model.ActiveLayer.No + 1}");
|
||||
Log.I($" - TODO: 모션→스캐너 좌표 변환 방향/스케일 이정인 선임 확인 필요");
|
||||
|
||||
// 26.04.10 NDY [대면적 MOTF] 플립 페이지 자동 생성
|
||||
CommonHelper.GetMainPage().GenerateFlippedPages(LargeMOTFOffsetX);
|
||||
}
|
||||
private void GetPerformCmdStageXJogSpeed(object obj)
|
||||
{
|
||||
|
||||
@ -67,9 +67,22 @@ namespace WeldingCommon.Views
|
||||
|
||||
_Aurora.EventObservable.AsObservable(CommonEventIds.EVENT_EQUIPMENT_STATUS_CHANGE)
|
||||
.Subscribe(x => OnChangedEquipmentStatus());
|
||||
#region 26.04.10 NDY [대면적 MOTF] 프로그램 시작 시 UI 반영
|
||||
CommonHelper.GetMainPage().OnRecipeReloaded += () =>
|
||||
{
|
||||
ScannerObjectTeachingControlBoxViewModel.IsUseLargeMOTF
|
||||
= DB.Dao.WeldingLinesRecipe.UseLargeMOTF;
|
||||
ScannerObjectTeachingControlBoxViewModel.LargeMOTFPageCount
|
||||
= DB.Dao.WeldingLinesRecipe.LargeMOTFPageCount;
|
||||
};
|
||||
#endregion
|
||||
|
||||
RecipeHelper.OnActiveReloaded();
|
||||
|
||||
|
||||
|
||||
CommonHelper.UpdateAutoRunPage();
|
||||
|
||||
}
|
||||
|
||||
private object OnChangedEquipmentStatus()
|
||||
@ -165,12 +178,26 @@ namespace WeldingCommon.Views
|
||||
RecipeHelper.SelectedRecipe = recipe;
|
||||
RecipeHelper.ReloadRecipe(recipe.name);
|
||||
_RecipeBeforeChanged = RecipeHelper.getRecipeInfo(recipe.name);
|
||||
|
||||
#region 26.04.10 NDY [대면적 MOTF] 레시피 로드 시 UI 반영
|
||||
ScannerObjectTeachingControlBoxViewModel.IsUseLargeMOTF
|
||||
= DB.Dao.WeldingLinesRecipe.UseLargeMOTF;
|
||||
ScannerObjectTeachingControlBoxViewModel.LargeMOTFPageCount
|
||||
= DB.Dao.WeldingLinesRecipe.LargeMOTFPageCount;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public void Reloaded((int id, string name) recipe)
|
||||
{
|
||||
RecipeHelper.SelectedRecipe = recipe;
|
||||
RecipeHelper.ReloadRecipe(recipe.name);
|
||||
|
||||
// 26.04.10 NDY [대면적 MOTF] 레시피 로드 시 UI 반영
|
||||
ScannerObjectTeachingControlBoxViewModel.IsUseLargeMOTF
|
||||
= DB.Dao.WeldingLinesRecipe.UseLargeMOTF;
|
||||
ScannerObjectTeachingControlBoxViewModel.LargeMOTFPageCount
|
||||
= DB.Dao.WeldingLinesRecipe.LargeMOTFPageCount;
|
||||
}
|
||||
|
||||
public void OnModelSelectChanged(string modelName)
|
||||
@ -198,13 +225,35 @@ namespace WeldingCommon.Views
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#region 26.04.10 찾음. ScannerCanvasCtrlTeaching.Model.Layers로 Layer 접근하고 각 Layer에서 DrawObject를 Get 할 수 있음. // 까먹을까봐 적어둠
|
||||
//MainPage.SaveRecipe()
|
||||
// → DB.Dao.WeldingLinesRecipe.Save() 전에
|
||||
// → ScannerCanvasCtrlTeaching.Model.Layers
|
||||
// → layer.Objects(List<IDrawObject>)
|
||||
// → Line.LargeMOTFPositionX/Y SET
|
||||
#endregion
|
||||
public void OnSaved(int id, string recipeName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(RecipeHelper.SelectedRecipe.name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#region 26.04.10 NDY [대면적 MOTF] 저장 직전 레시피에 반영
|
||||
DB.Dao.WeldingLinesRecipe.UseLargeMOTF
|
||||
= ScannerObjectTeachingControlBoxViewModel.IsUseLargeMOTF;
|
||||
DB.Dao.WeldingLinesRecipe.LargeMOTFPageCount
|
||||
= ScannerObjectTeachingControlBoxViewModel.LargeMOTFPageCount;
|
||||
#endregion
|
||||
#region 26.04.10 NDY [대면적 MOTF] 저장 직전 LargeMOTFPosition 자동 계산
|
||||
// 방법1 현재 viewmodel에 구현함.
|
||||
//UpdateLargeMOTFPosition();
|
||||
// 방법2 현재 MainPage.cs에 메소드 추가함. 그것을 호출하는 식
|
||||
|
||||
CommonHelper.GetMainPage().UpdateLargeMOTFPosition();
|
||||
|
||||
#endregion
|
||||
|
||||
RecipeHelper.SaveRecipe(RecipeHelper.SelectedRecipe.name);
|
||||
var ChangedRecipe = RecipeHelper.getRecipeInfo(RecipeHelper.SelectedRecipe.name);
|
||||
var diffs = new ObservableCollection<PropertyDiff>();
|
||||
@ -236,5 +285,36 @@ namespace WeldingCommon.Views
|
||||
}
|
||||
Log.I($"Saved Recipe : [{RecipeHelper.SelectedRecipe.name}]");
|
||||
}
|
||||
#region 26.04.10 NDY [대면적 MOTF] Layer별 마지막 Line의 PF2를 LargeMOTFPosition에 SET
|
||||
//주의사항:
|
||||
//ScannerCanvasCtrlTeaching이 MainPage 내부 필드라 internal 또는 private일 수 있습니다.접근이 안 되면 MainPage에 별도 메서드를 추가하는 방향으로 가야 합니다:
|
||||
|
||||
private void UpdateLargeMOTFPosition()
|
||||
{
|
||||
var model = CommonHelper.GetMainPage()
|
||||
.ScannerCanvasCtrlTeaching
|
||||
.Model;
|
||||
|
||||
foreach (ICanvasLayer layer in model.Layers)
|
||||
{
|
||||
var lines = layer.Objects
|
||||
.OfType<Line>()
|
||||
.OrderBy(l => l.No)
|
||||
.ToList();
|
||||
|
||||
if (lines.Count == 0) continue;
|
||||
|
||||
var lastLine = lines.Last();
|
||||
float motfX = lastLine.PF2.X;
|
||||
float motfY = lastLine.PF2.Y;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
line.LargeMOTFPositionX = motfX;
|
||||
line.LargeMOTFPositionY = motfY;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user