Compare commits

..

No commits in common. "c054439c1992746f0878b7775e96281706f84a89" and "172a273b9018956add00c989518f486ed8da1ade" have entirely different histories.

5 changed files with 13 additions and 101 deletions

View File

@ -1651,18 +1651,10 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
} }
#endregion #endregion
#region 260820 260811 초기화 제거 (원복: 아래 3줄 주석을 풀면 260811 무조건판으로 돌아간다) #region 260811 정지 시 에코 워드 0 초기화 (원복 시 이 region 삭제)
// PLC측 확정(2026-08-20): PLC 는 PC 에코 워드가 0이면 레이저 출사 신호를 내지 않는다. _PLC.WriteWord(eWordOutput.PC_RECIPE_NO, 0);
// 그런데 bit15 가접 운전은 페이지마다 정지하므로, 여기서 0을 쓰면 페이지마다 0/0 창이 열린다. _PLC.WriteWord(eWordOutput.PC_PAGE_NO, 0);
// PC 는 다음 PLC_PAGE_CHANGE_REQ 를 받아야만 재에코하므로(CheckPageNo) 그 창 동안 PLC 는 Log.I($"[OnSeqActionStop] 에코 워드 0 초기화 (PC_RECIPE_NO/PC_PAGE_NO)");
// 유효값을 못 본다 — 2026-08-20 로그에서 15 사이클 전부 이 경로를 탔다.
// 0 초기화는 SeqStatusMonitor.UpdateStatus() 가 Auto OFF 시에만 담당한다(위 260806 주석과 동일 규칙).
// 여기서 중복으로 쓰면 bit15 Resume 이 의존하는 보존값도 함께 깨진다.
// ※ 남은 창: SeqStatusMonitor 는 Auto OFF 하강엣지에 0을 쓰고 끝이라, Auto 복귀 후 첫 REQ 까지
// 0/0 이 latch 된다(2026-08-20 10:24:47~10:43:17). 그 구간 재에코는 별건으로 검토한다.
//_PLC.WriteWord(eWordOutput.PC_RECIPE_NO, 0);
//_PLC.WriteWord(eWordOutput.PC_PAGE_NO, 0);
//Log.I($"[OnSeqActionStop] 에코 워드 0 초기화 (PC_RECIPE_NO/PC_PAGE_NO)");
#endregion #endregion

View File

@ -109,10 +109,8 @@ namespace ILSOS_PrismaticRD_PTOP.Views
CMD_VisibleChanged = new DelegateCommand(VisibleChanged); CMD_VisibleChanged = new DelegateCommand(VisibleChanged);
// 260813: 자동시작 요청 출처를 넘긴다 — OnAutoRunStartRequest 는 버튼/PLC 이벤트 공용 진입점이라 CMD_RunSequenceAutoRun = new DelegateCommand(OnAutoRunStartRequest); // 260511 이곳 시퀸스
// 진입부 로그가 출처를 단정하면 안 된다(기존 문구가 버튼 클릭도 "AUTO_REQ"로 찍었다). CMD_StopSequenceAutoRun = new DelegateCommand(OnStopSequenceAutoRun);
CMD_RunSequenceAutoRun = new DelegateCommand(o => OnAutoRunStartRequest("Button")); // 260511 이곳 시퀸스
CMD_StopSequenceAutoRun = new DelegateCommand(OnStopSequenceAutoRun); // 260813: 정지 시 에코 워드 0 초기화 재적용(조건부) — ResumeMode/M70515 구간만 보존, SeqAutoRunPTOP.OnSeqActionStop 260813 region
CMD_Reset = new DelegateCommand(PerformCmdReset); CMD_Reset = new DelegateCommand(PerformCmdReset);
CMD_AutoRunResume = new DelegateCommand(OnAutoRunResume); CMD_AutoRunResume = new DelegateCommand(OnAutoRunResume);
@ -123,7 +121,7 @@ namespace ILSOS_PrismaticRD_PTOP.Views
//이벤트로 AUTORUN 스타트 요청에 대한 메소드 실행 오면 그때 동작함. 시퀸스 돔 //이벤트로 AUTORUN 스타트 요청에 대한 메소드 실행 오면 그때 동작함. 시퀸스 돔
_Aurora.EventObservable.AsObservable(CommonEventIds.EVENT_AUTO_RUN_START_REQUEST) _Aurora.EventObservable.AsObservable(CommonEventIds.EVENT_AUTO_RUN_START_REQUEST)
.ObserveOnDispatcher() .ObserveOnDispatcher()
.Subscribe(x => OnAutoRunStartRequest("PLC_AUTO_REQ")); // 260813: 출처 명시(발행처는 PLCController.MonitorPlcInterfaceMap 뿐) .Subscribe(x => OnAutoRunStartRequest());
// Stop 요청 시 정지 로직 실행 // Stop 요청 시 정지 로직 실행
_Aurora.EventObservable.AsObservable(CommonEventIds.EVENT_AUTO_RUN_STOP_REQUEST) _Aurora.EventObservable.AsObservable(CommonEventIds.EVENT_AUTO_RUN_STOP_REQUEST)
@ -210,25 +208,6 @@ namespace ILSOS_PrismaticRD_PTOP.Views
// 음극/양극 어느 쪽이 줘도 트리거 (AutoRun이 두 극을 함께 쓰는 구조와 동일) // 음극/양극 어느 쪽이 줘도 트리거 (AutoRun이 두 극을 함께 쓰는 구조와 동일)
bool bit15 = _Plc.ReadBit(eBitInput.PLC_WELD_READY_REQ).data; bool bit15 = _Plc.ReadBit(eBitInput.PLC_WELD_READY_REQ).data;
IsModeChangeActive = bit15; // bit15 살아있을 때만 [AutoRun Resume] 버튼 표시 IsModeChangeActive = bit15; // bit15 살아있을 때만 [AutoRun Resume] 버튼 표시
#region 260820 bit15 구간 Recipe/Page 를 Recipe 작업 화면에도 표시 (원복: 이 region 삭제)
// 팝업은 상승엣지 1회라 [확인] 을 누르면 값이 사라진다. 현장 소음 속에서 작업자가
// 몇 번 레시피 몇 페이지였는지 잊는다는 요청으로, Recipe 작업 화면 상단에도 같은 값을 띄운다.
// · 트리거: 팝업과 같은 bit15. 단 팝업은 엣지 1회, 표시는 ON 구간 내내 레벨 유지.
// · 값: 팝업이 읽는 두 워드 그대로(PLC 원본 입력). PC 에코(PC_*)가 아니다.
// 공용(WeldingCommon)은 Status 만 읽고 PTOP 을 참조하지 않는다 — 타 설비는 값이 없어 자동 미표시.
// 분석: docs/분석/2026/08/20/RecipePage_현장표시_레이아웃_분석.md
if (bit15)
{
Status.PlcGuideRecipeNo = _Plc.ReadWord(eWordInput.PLC_RECIPE_NO).data;
Status.PlcGuidePageNo = _Plc.ReadWord(eWordInput.PLC_PAGE_NO).data;
}
else if (Status.PlcGuideRecipeNo != null)
{
Status.PlcGuideRecipeNo = null;
Status.PlcGuidePageNo = null;
}
#endregion
if (bit15 && !_prevBit15 && !_isPopupOpen) if (bit15 && !_prevBit15 && !_isPopupOpen)
{ {
short r = _Plc.ReadWord(eWordInput.PLC_RECIPE_NO).data; short r = _Plc.ReadWord(eWordInput.PLC_RECIPE_NO).data;
@ -313,9 +292,7 @@ namespace ILSOS_PrismaticRD_PTOP.Views
// 이어하기는 전용 [AutoRun Resume] 버튼(OnAutoRunResume) 경로라 이 가드와 무관.) // 이어하기는 전용 [AutoRun Resume] 버튼(OnAutoRunResume) 경로라 이 가드와 무관.)
if (_Plc != null && !_Plc.IsSimul && _Plc.ReadBit(eBitInput.PLC_WELD_READY_REQ).data) if (_Plc != null && !_Plc.IsSimul && _Plc.ReadBit(eBitInput.PLC_WELD_READY_REQ).data)
{ {
// 260813: 출처를 같이 남긴다. 이 메서드는 [운전 시작] 버튼과 PLC 이벤트가 공용으로 쓰는 Log.I("[Bit15] bit15 ON 중 → AUTO_REQ 자동시작 무시 (Manual 유지)");
// 진입점이라, 여기서 "AUTO_REQ"로 단정하면 버튼 클릭도 PLC 신호로 오독된다.
Log.I($"[Bit15] bit15 ON 중 → 자동시작 요청 무시 (요청출처:{obj ?? "unknown"}, Manual 유지)");
return; return;
} }
@ -451,6 +428,9 @@ namespace ILSOS_PrismaticRD_PTOP.Views
//if (_SeqAutoRun.RunState == SequenceRunState.Running) //if (_SeqAutoRun.RunState == SequenceRunState.Running)
// _SeqAutoRun.Stop(); // _SeqAutoRun.Stop();
if (_SeqAutoRunPTOP.RunState == SequenceRunState.Running) if (_SeqAutoRunPTOP.RunState == SequenceRunState.Running)
_SeqAutoRunPTOP.Stop(); _SeqAutoRunPTOP.Stop();

View File

@ -52,15 +52,5 @@ namespace WeldingCommon
} }
public static bool RMSUse { get; set; } = false; public static bool RMSUse { get; set; } = false;
#region 260820 PLC 지시 Recipe/Page (원복: 이 region 삭제)
// 설비별 시퀀스/VM 이 값을 넣고, 공용 Recipe 작업 화면이 읽어서 상단 띠에 표시한다.
// PTOP: UCMainAutoRunViewModel.OnMonitoring() 에서 bit15(M70515) ON 구간에만 대입, OFF 면 null.
// 여기에 두는 이유 — 공용 화면이 설비(PTOP)를 참조하지 않게 하려면 의존 방향을 뒤집어야 한다.
// 값을 넣지 않는 설비는 계속 null 이므로 분기문 없이 자동으로 미표시된다.
// ※ null = 표시 안 함. 0 은 "PLC 가 0을 줬다"는 유효한 상태라 null 과 구분한다.
public static short? PlcGuideRecipeNo { get; set; }
public static short? PlcGuidePageNo { get; set; }
#endregion
} }
} }

View File

@ -18,35 +18,13 @@
<behavior:InvokeCommandAction Command="{Binding CMD_VisibleChanged}" CommandParameter="{Binding IsVisible, ElementName=uc}"/> <behavior:InvokeCommandAction Command="{Binding CMD_VisibleChanged}" CommandParameter="{Binding IsVisible, ElementName=uc}"/>
</behavior:PropertyChangedTrigger> </behavior:PropertyChangedTrigger>
</behavior:Interaction.Triggers>--> </behavior:Interaction.Triggers>-->
<!-- 260820 PLC 지시 Recipe/Page 띠에서 사용 (원복: 이 Resources 블록 삭제) -->
<UserControl.Resources>
<view:BoolConverter x:Key="convTrueVisible" TrueValue="Visible" FalseValue="Collapsed"/>
</UserControl.Resources>
<Grid IsEnabled="{Binding IsManualStatus}"> <Grid IsEnabled="{Binding IsManualStatus}">
<Grid.RowDefinitions>
<!-- 260820: Height="Auto" 라 띠가 Collapsed 면 높이 0 → 평소 화면은 종전과 동일하다 -->
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="300"></ColumnDefinition> <ColumnDefinition Width="300"></ColumnDefinition>
<ColumnDefinition Width="4*"></ColumnDefinition> <ColumnDefinition Width="4*"></ColumnDefinition>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<local:UCScannerObjectTeachingControlBox Grid.Column="0" Margin="0 0 0 0" DataContext="{Binding DataContext.ScannerObjectTeachingControlBoxViewModel, ElementName=uc}"></local:UCScannerObjectTeachingControlBox>
<!-- 260820 PLC 지시 Recipe/Page 띠 (원복: 이 Border 와 위 RowDefinitions 제거, 아래 Grid.Row 속성 제거) <WindowsFormsHost Grid.Column="1">
bit15(M70515) ON 구간에만 표시된다. 값은 PLC 원본 워드이고 PC 에코가 아니다.
DataContext 는 바깥 VM(UCScannerObjectTeachingViewModel) 이라 ControlBox VM 을 경유해 바인딩한다.
분석: docs/분석/2026/08/20/RecipePage_현장표시_레이아웃_분석.md -->
<Border Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Background="#2E7D46" BorderBrush="#7ED492" BorderThickness="0 0 0 2" Padding="12 7"
Visibility="{Binding ScannerObjectTeachingControlBoxViewModel.IsPlcGuideVisible, Converter={StaticResource convTrueVisible}}">
<TextBlock Text="{Binding ScannerObjectTeachingControlBoxViewModel.PlcGuideText}"
FontSize="22" FontWeight="Bold" Foreground="White"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<local:UCScannerObjectTeachingControlBox Grid.Row="1" Grid.Column="0" Margin="0 0 0 0" DataContext="{Binding DataContext.ScannerObjectTeachingControlBoxViewModel, ElementName=uc}"></local:UCScannerObjectTeachingControlBox>
<WindowsFormsHost Grid.Row="1" Grid.Column="1">
<lasa:MainPage x:Name="MainPageView" IsMdiContainer="False" TopLevel="False" /> <lasa:MainPage x:Name="MainPageView" IsMdiContainer="False" TopLevel="False" />
</WindowsFormsHost> </WindowsFormsHost>
</Grid> </Grid>

View File

@ -82,32 +82,6 @@ namespace WeldingCommon.Views
private bool _IsObjectSelectAll; private bool _IsObjectSelectAll;
public bool IsObjectSelectAll { get => _IsObjectSelectAll; set => SetProperty(ref _IsObjectSelectAll, value); } public bool IsObjectSelectAll { get => _IsObjectSelectAll; set => SetProperty(ref _IsObjectSelectAll, value); }
#region 260820 PLC 지시 Recipe/Page 표시 (원복: 이 region + OnMonitoring 의 SyncPlcGuide() 호출 삭제)
// 값은 설비별로 Status 에 들어온다(PTOP: bit15 구간에만). 공용은 Status 만 읽으므로 설비 의존이 없다.
// 바인딩은 UCScannerObjectTeaching.xaml 상단 띠 — 그 화면의 DataContext(바깥 VM)가
// ScannerObjectTeachingControlBoxViewModel 을 공개하고 있어 여기 프로퍼티를 그대로 쓴다.
// (바깥 VM 에는 폴링 타이머가 없고 이 VM 에는 100ms 타이머가 이미 돌고 있어 재활용한다)
private bool _IsPlcGuideVisible;
public bool IsPlcGuideVisible { get => _IsPlcGuideVisible; set => SetProperty(ref _IsPlcGuideVisible, value); }
private string _PlcGuideText = string.Empty;
public string PlcGuideText { get => _PlcGuideText; set => SetProperty(ref _PlcGuideText, value); }
private void SyncPlcGuide()
{
var recipeNo = Status.PlcGuideRecipeNo;
var pageNo = Status.PlcGuidePageNo;
if (recipeNo == null || pageNo == null) {
IsPlcGuideVisible = false;
return;
}
PlcGuideText = $"RECIPE {recipeNo} PAGE {pageNo}";
IsPlcGuideVisible = true;
}
#endregion
// 레시피별 Laser 방향 발진 차단 체크 (Recipe_Laser_Interlock.json) — 변경 시 즉시 활성 레시피에 저장 // 레시피별 Laser 방향 발진 차단 체크 (Recipe_Laser_Interlock.json) — 변경 시 즉시 활성 레시피에 저장
private bool _IsFrontInterlock; private bool _IsFrontInterlock;
public bool IsFrontInterlock public bool IsFrontInterlock
@ -271,8 +245,6 @@ namespace WeldingCommon.Views
private void OnMonitoring(object sender, EventArgs e) private void OnMonitoring(object sender, EventArgs e)
{ {
// 260820: 아래 IO 블록은 미연결 시 return 하므로, PLC 지시 표시는 반드시 그 앞에서 갱신한다.
SyncPlcGuide();
// [기존 소스 보존] Laser 디바이스 기반 Pilot 상태 (DO 3=GuideLaserEnable) — 일부 Laser 미구현 시 항상 false // [기존 소스 보존] Laser 디바이스 기반 Pilot 상태 (DO 3=GuideLaserEnable) — 일부 Laser 미구현 시 항상 false
//if (_Laser.GetPilotLaserStatus()) { //if (_Laser.GetPilotLaserStatus()) {