2026-06-05 13:44:39 +09:00

332 lines
12 KiB
C#

using Aurora;
using Aurora.Api;
using Aurora.Util.HislogPlus;
using Aurora.View;
using AuroraLaser;
using DB;
using Hermes.Functional;
using ILSOS_PrismaticGun.Alarm;
using ILSOS_PrismaticGun.Device;
using ILSOS_PrismaticGun.Device.ACS;
using ILSOS_PrismaticGun.Process;
using ILSOS_PrismaticGun.Process.Services.History;
using ILSOS_PrismaticGun.Sequences.SubSequence.PLCInterface;
using ILSOS_PrismaticGun.Tools;
using ILSOS_PrismaticGun.WeldingCanvas;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents;
using WeldingCommon;
using WeldingCommon.Devices;
using WeldingCommon.Popup;
using WeldingCommon.Sequences.Main;
using WeldingCommon.Settings;
using WeldingCommon.Utils;
using static ILSOS_PrismaticGun.Device.PLCControllerPrismaticGun;
namespace ILSOS_PrismaticGun
{
public class ProcessManager
{
private static ProcessManager _Instance;
public static ProcessManager Instance {
get {
if (_Instance is null) {
_Instance = new ProcessManager();
}
return _Instance;
}
}
private static DualLogger _Log = new DualLogger();
private IAuroraEnvironment _env;
private PLCControllerPrismaticGun _plc;
private Laser _laser;
public PalletInfo PalletInStageA { get; set; }
public PalletInfo PalletInStageB { get; set; }
public IHistoryReader<WeldingDataForPrismaticGun> HistoryReader { get; private set; }
private IHistoryWriter<WeldingDataForPrismaticGun> _historyWriter;
private static CsvLogger CsvLogStageA;
private static CsvLogger CsvLogStageB;
private object _lock = new object();
public bool StopRequest {
get {
lock(_lock)
return _StopRequest;
}
private set {
lock(_lock)
_StopRequest = value;
}
}
private bool _StopRequest;
public ProcessManager()
{
_Log.AddLogger("ProcessManager", "StageA");
_Log.AddLogger("ProcessManager", "StageB");
}
public void Init(IAuroraEnvironment env)
{
_env = env;
_plc = env.DeviceManager[CommonDeviceIds.PLCDevice] as PLCControllerPrismaticGun;
_laser = env.DeviceManager[CommonDeviceIds.Laser] as Laser;
env.EventObservable.AsObservable(CommonEventIds.EVENT_AUTO_RUN_START_REQUEST)
.ObserveOnDispatcher()
.Subscribe(x => {
AutoRunStart();
_Log.W("PLC Request Auto Run");
});
// PLC Stop - 상태감시 필요 (Cycle Stop)
env.EventObservable.AsObservable(CommonEventIds.EVENT_AUTO_RUN_STOP_REQUEST)
.ObserveOnDispatcher()
.Subscribe(x => {
_Log.E("PLC Request Auto Run Cycle Stop!!!!");
CycleStop();
});
// Cell History
var historyServ = new CellHistoryService<WeldingDataForPrismaticGun>(maxCount: 50, pumpMs: 100);
_historyWriter = historyServ as IHistoryWriter<WeldingDataForPrismaticGun>;
HistoryReader = historyServ as IHistoryReader<WeldingDataForPrismaticGun>;
var setting = _env.SettingEntry[CommonSettingIds.SystemParameter] as SystemParameter;
CsvLogStageA = new CsvLogger(Path.Combine(setting.CellHistoryFolderPath, "StageA"), "StageA_CellInfo");
CsvLogStageB = new CsvLogger(Path.Combine(setting.CellHistoryFolderPath, "StageB"), "StageB_CellInfo");
// Pallet Register
RegistrySerializer.Init();
LoadRegistryData();
}
private void SaveRegistryData(eStage stage, PalletInfo cell)
{
if (cell.WeldingStage is eStage.A)
RegistrySerializer.SaveToRegistry("PalletInStageA", cell);
else
RegistrySerializer.SaveToRegistry("PalletInStageB", cell);
Thread.Sleep(50);
}
private void LoadRegistryData()
{
PalletInStageA = RegistrySerializer.LoadFromRegistry<PalletInfo>("PalletInStageA");
PalletInStageA.WeldingStage = eStage.A;
PalletInStageB = RegistrySerializer.LoadFromRegistry<PalletInfo>("PalletInStageB");
PalletInStageB.WeldingStage = eStage.B;
}
public bool LoadingComplete(PalletInfo cell)
{
cell.SetState(ePalletState.LoadingComp);
if (Status.EquipmentStatus == eEqpStatus.Auto)
SaveRegistryData(cell.WeldingStage, cell);
_Log.W($"{cell.ToString()} Load Complete", cell.WeldingStage);
return true;
}
public void WeldingStart(PalletInfo cell)
{
// 저장은 하지 않는다. 웰딩중에 끊기면 배출함
cell.SetState(ePalletState.Welding);
cell.weldingData.WeldingStartTime = DateTime.Now;
if (Status.EquipmentStatus == eEqpStatus.Auto)
SaveRegistryData(cell.WeldingStage, cell);
_Log.W($"{cell.ToString()} Welding Start", cell.WeldingStage);
}
public bool WeldingComplete(PalletInfo cell)
{
// 메뉴얼은 카운팅이 안됨
if (cell.weldingData.TotalProduct < uint.MaxValue && cell.weldingData.IsLaserOn)
cell.weldingData.TotalProduct++;
if (cell.weldingData.TodayProduct < uint.MaxValue && cell.weldingData.IsLaserOn)
cell.weldingData.TodayProduct++;
cell.SetState(ePalletState.WeldingComp);
cell.weldingData.WeldingEndTime = DateTime.Now;
if (Status.EquipmentStatus == eEqpStatus.Auto)
SaveRegistryData(cell.WeldingStage, cell);
// 히스토리 파일 저장
if (cell.WeldingStage is eStage.A)
CsvLogStageA.WriteLineCellData(cell);
else
CsvLogStageB.WriteLineCellData(cell);
_Log.W($"{cell.ToString()} Welding Complete", cell.WeldingStage);
return true;
}
public bool UnloadingComplete(PalletInfo cell)
{
cell.SetState(ePalletState.UnloadingComp);
if (Status.EquipmentStatus == eEqpStatus.Auto)
SaveRegistryData(cell.WeldingStage, cell);
// 일단 메뉴얼도 히스토리로 남기도록 함
_historyWriter.Append(cell.WeldingStage, cell.weldingData.Clone() as WeldingDataForPrismaticGun);
_Log.W($"{cell.ToString()} Unload Complete", cell.WeldingStage);
return true;
}
public bool PalletClear(eStage stage)
{
if(stage is eStage.A) {
PalletInStageA.Clear();
SaveRegistryData(stage, PalletInStageA);
} else {
PalletInStageB.Clear();
SaveRegistryData(stage, PalletInStageB);
}
return true;
}
#region Welding Enable >> Stage 두개 다 사용못하는 경우 알람 발생을 하기위한 플래그.. 이렇게 하면 복잡한데 일단 필요
private bool _enableLaserUse = true;
public bool IsEnableLaserUse()
{
lock (_lock) {
return _enableLaserUse;
}
}
public void EnableLaserUse(bool enable)
{
lock (_lock) {
_enableLaserUse = enable;
}
}
#endregion
#region Cycle Stop을 하기 위한 동작
private bool autoStartStageA = false;
private bool autoStartStageB = false;
internal void SetAutoPrepare(eStage stage, bool on)
{
lock (_lock)
{
if (stage is eStage.A)
autoStartStageA = on;
else
autoStartStageB = on;
_Log.I($"Stage {Enum.GetName(typeof(eStage), stage)} [Prepare > {on}]", stage);
if (!autoStartStageA && !autoStartStageB)
{
_plc.WriteBit(eBitOutput.PC_AUTO_STATUS, false);
_plc.WriteBit(eBitOutput.PC_AUTO_COMPLETE, false);
_plc.WriteBit(eBitOutput.PC_MANUAL_COMPLETE, true);
Status.SetStatus(eEqpStatus.Manual);
_laser.LaserOff();
_Log.W($"Run Stop >> Laser Off && Manual Change");
}
}
}
internal bool IsAutoPrepare()
{
lock (_lock) {
if (autoStartStageA && autoStartStageB) {
_plc.WriteBit(eBitOutput.PC_AUTO_STATUS, true);
_plc.WriteBit(eBitOutput.PC_AUTO_COMPLETE, true);
_plc.WriteBit(eBitOutput.PC_MANUAL_COMPLETE, false);
Status.SetStatus(eEqpStatus.Auto);
_Log.W($"Run Prepare OK");
return true;
}
}
return false;
}
#endregion
internal void AutoStart(bool on)
{
if (on) {
if (_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageA].RunState == SequenceRunState.Running)
_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageA].Stop();
if (_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageB].RunState == SequenceRunState.Running)
_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageB].Stop();
StopRequest = false;
EnableLaserUse(true);
_laser.LaserOn();
_Log.W($"Laser On Start!!!");
_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageA].Start();
_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageB].Start();
_Log.W($"Auto Sequence Start");
} else {
if (_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageA].RunState == SequenceRunState.Running)
_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageA].Stop();
if (_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageB].RunState == SequenceRunState.Running)
_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageB].Stop();
_laser.LaserOff();
_Log.W($"Auto Sequence Stop");
}
}
public async void AutoRunStart()
{
bool shouldStop = await TimerMessageBox.ShowAsync(Application.Current.MainWindow, "자동 시작", "자동 운전을 시작하시겠습니까?", true, 5000);
if (!shouldStop)
return;
AutoStart(true);
}
internal void CycleStop()
{
// 용접중이면, 정지 신호만 주고 정상 시퀀스 종료를 준다
if (PalletInStageA.palletState == ePalletState.Welding) {
_Log.E($"{PalletInStageA.ToString()} CycleStop OK!! State is welding", eStage.A);
StopRequest = true;
}
// 용접중이 아니면, 그냥 시퀀스 종료 시킨다.
else {
if (_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageA].RunState == SequenceRunState.Running){
_Log.E($"{PalletInStageA.ToString()} Stop !! not Welding State", eStage.A);
_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageA].Stop();
}
}
// 용접중이면, 정지 신호만 주고 정상 시퀀스 종료를 준다
if (PalletInStageB.palletState == ePalletState.Welding) {
_Log.E($"{PalletInStageB.ToString()} CycleStop OK!! State is welding", eStage.B);
StopRequest = true;
}
// 용접중이 아니면, 그냥 시퀀스 종료 시킨다.
else {
if (_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageB].RunState == SequenceRunState.Running){
_Log.E($"{PalletInStageB.ToString()} Stop !! not Welding State", eStage.B);
_env.SequenceEntry[SequenceIds.SeqAutoRunPrismaticGunStageB].Stop();
}
}
}
}
}