225 lines
11 KiB
C#
225 lines
11 KiB
C#
using Aurora;
|
|
using Aurora.Api;
|
|
using Aurora.Api.Devices;
|
|
using Aurora.Util.HislogPlus;
|
|
using Aurora.View;
|
|
using AuroraLaser;
|
|
using CoreUnit.Control.UserControl.Canvas;
|
|
using CoreUnit.Scanner.UserControl.ScannerCanvas;
|
|
using DB.Recipe;
|
|
using GUI;
|
|
using Hermes;
|
|
using ILSOS_PrismaticScanner.Alarm;
|
|
using ILSOS_PrismaticScanner.Device;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Reactive.Linq;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Markup;
|
|
using System.Windows.Media;
|
|
using VisionCommon;
|
|
using WeldingCommon;
|
|
using WeldingCommon.Alarm;
|
|
using WeldingCommon.Data;
|
|
using WeldingCommon.Devices;
|
|
using WeldingCommon.RMS;
|
|
using WeldingCommon.Settings;
|
|
using WeldingCommon.Utils;
|
|
using WeldingCommon.Utils.Diff;
|
|
using static AuroraPLC.PLCBase;
|
|
using static ILSOS_PrismaticScanner.Device.PLCControllerPrismaticScanner;
|
|
|
|
namespace ILSOS_PrismaticScanner.Recipes
|
|
{
|
|
public class RMSHandlerForScanner : RMSHandler
|
|
{
|
|
private const string RecipeNo = "RecipeNo";
|
|
//$"{nameof(param.MarkSpeed)}_{parameterNo}"
|
|
|
|
private PLCControllerPrismaticScanner _plc;
|
|
private SettingRmsDataList _RmsSetting;
|
|
public override void RegistryDeviceHandler(IAuroraEnvironment aurora)
|
|
{
|
|
base.RegistryDeviceHandler(aurora);
|
|
_plc = aurora.DeviceManager[CommonDeviceIds.PLCDevice] as PLCControllerPrismaticScanner;
|
|
_RmsSetting = aurora.SettingEntry[CommonSettingIds.RmsDatas] as SettingRmsDataList;
|
|
|
|
// Aurora에서 제공하는 이벤트를 체인으로 사용하면 동작(Aurora가 저장 후 LASA가 저장하는)에 대한 우선순위가 보장이 안되기 때문에
|
|
aurora.EventObservable.AsObservable(CommonEventIds.EVENT_CHANGE_RECIPE_INFO)
|
|
.ObserveOnDispatcher()
|
|
.Select(param => (RecipeInfo)param.Param)
|
|
.Subscribe(OnUpdateCurrentActivatedRecipe);
|
|
}
|
|
|
|
private void OnUpdateCurrentActivatedRecipe(RecipeInfo info)
|
|
{
|
|
RecipeHelper.ReloadRecipe(info.Name);
|
|
UploadActivatedRecipeParameter();
|
|
}
|
|
|
|
private bool TrySetReportData(string key, double value)
|
|
{
|
|
var data = getReportData(key);
|
|
if (data == null) {
|
|
Log.E($"RMS 데이터 항목을 찾을 수 없음: {key}");
|
|
MessageUtil.ShowToast($"RMS 설정 항목 누락: {key}", Log);
|
|
_aurora.AlarmService.SetAlarm(AlarmCode.RMS_PAGE_SETTING_NULL);
|
|
return false;
|
|
}
|
|
data.Value = value;
|
|
return true;
|
|
}
|
|
|
|
private void UploadActivatedRecipeParameter()
|
|
{
|
|
try {
|
|
// PC에 저장된 데이터를 PLC에 전달
|
|
for (int i = 0; i < 4; i++) {
|
|
if (!ApplyParamToReport(ScannerCanvasUserCtrl.ScannerParams[i], i))
|
|
return;
|
|
}
|
|
|
|
//Write Parameter
|
|
UploadRmsParameter();
|
|
}
|
|
catch (Exception ex) {
|
|
Log.E($"UploadActivatedRecipeParameter 예외: {ex.Message}");
|
|
MessageUtil.ShowToast($"RMS 파라미터 업로드 중 오류 발생", Log);
|
|
_aurora.AlarmService.SetAlarm(AlarmCode.RMS_PAGE_SETTING_NULL);
|
|
}
|
|
}
|
|
|
|
// Server(PLC) => Client(Local PC)
|
|
public override void OnParameterReadRequest(EventMessage message)
|
|
{
|
|
Task.Run(() => {
|
|
if (_setting.IgnoreRMS) {
|
|
MessageUtil.ShowToast($"Not Used RMS Recipe", Log);
|
|
_aurora.AlarmService.SetAlarm(AlarmCode.RMS_NOT_USED_OPTION);
|
|
return;
|
|
}
|
|
|
|
// Read Parameter
|
|
if (UpdateRmsParameter() != E1.OK) {
|
|
MessageUtil.ShowToast($"RMS Parameter Read Fail", Log);
|
|
_aurora.AlarmService.SetAlarm(AlarmCode.RMS_RECIPE_EDIT_REQUEST_RESPONSE_TIMEOUT);
|
|
return;
|
|
}
|
|
|
|
// RMS Recipe Check
|
|
var recipeNoData = getReportData(RecipeNo);
|
|
if (recipeNoData == null) {
|
|
MessageUtil.ShowToast($"RMS 설정 항목 누락: {RecipeNo}", Log);
|
|
_aurora.AlarmService.SetAlarm(AlarmCode.RMS_PAGE_SETTING_NULL);
|
|
return;
|
|
}
|
|
int recipeId = recipeNoData.readValue(-1);
|
|
var recipe = _recipeEntry.Recipes().FirstOrDefault(x => x.Id == recipeId);
|
|
if (recipe == null) {
|
|
MessageUtil.ShowToast($"{recipeId}번 레시피 없음", Log);
|
|
_aurora.AlarmService.SetAlarm(AlarmCode.RMS_RECIPE_EDIT_REQUEST_RESPONSE_TIMEOUT);
|
|
return;
|
|
}
|
|
|
|
var RecipeBeforeChanged = RecipeHelper.getRecipeInfo(recipe.Name);
|
|
|
|
// Recipe Load
|
|
Application.Current.Dispatcher.Invoke(() => {
|
|
RecipeHelper.ReloadRecipe(recipe.Name);
|
|
});
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
if (!ApplyReportToParam(ScannerCanvasUserCtrl.ScannerParams[i], i))
|
|
return;
|
|
}
|
|
|
|
// PLC에서 받은 데이터를 저장 후 다시 로드
|
|
Application.Current.Dispatcher.Invoke(() => {
|
|
RecipeHelper.SaveRecipe(recipe.Name);
|
|
});
|
|
|
|
var ChangedRecipe = RecipeHelper.getRecipeInfo(recipe.Name);
|
|
|
|
var diffs = new ObservableCollection<PropertyDiff>();
|
|
for (int i = 0; i < 4; i++) {
|
|
CompareHelper.Fill(RecipeBeforeChanged.ReadOnlyScanParams[i], ChangedRecipe.ReadOnlyScanParams[i], diffs,
|
|
new CompareHelper.FieldSpec<ScannerParam>("Draw Speed", x => x.MarkSpeed),
|
|
new CompareHelper.FieldSpec<ScannerParam>("Jump Speed", x => x.JumpSpeed),
|
|
new CompareHelper.FieldSpec<ScannerParam>("Power#1", x => x.LaserPower1),
|
|
new CompareHelper.FieldSpec<ScannerParam>("Power#2", x => x.LaserPower2),
|
|
new CompareHelper.FieldSpec<ScannerParam>(nameof(ScannerParam.RampingStartPower), x => x.RampingStartPower),
|
|
new CompareHelper.FieldSpec<ScannerParam>(nameof(ScannerParam.RampingStartDist), x => x.RampingStartDist),
|
|
new CompareHelper.FieldSpec<ScannerParam>(nameof(ScannerParam.RampingEndPower), x => x.RampingEndPower),
|
|
new CompareHelper.FieldSpec<ScannerParam>(nameof(ScannerParam.RampingEndDist), x => x.RampingEndDist)
|
|
);
|
|
if (diffs.Count > 0) {
|
|
Log.FuncI($"ScanParameter{i+1} Recipe Changed");
|
|
_aurora.RecipeManager.RchHandler().AppendChangedItem(recipe.Name + $"-ScanParam{i+1}", diffs);
|
|
foreach (var diff in diffs)
|
|
Log.V($"{diff.ToString()}");
|
|
}
|
|
}
|
|
|
|
// Activated Recipe를 자동으로 변경 >> ActivedRecipe Change Event를 통해서 써주기까지 함
|
|
/// <Method 참조 cref="WeldingCommon.Views.UCScannerObjectTeachingViewModel.OnActivatedRecipe"/>
|
|
var preActivatedRecipe = _aurora.RecipeManager.ActivatedRecipe();
|
|
_aurora.RecipeManager.ActivateRecipe(recipe.Id, "RMS Request");
|
|
MessageUtil.ShowToast($"RMS Change Recipe Parameter & Activated Recipe ( {preActivatedRecipe.Id} -> {recipe.Id} )", Log);
|
|
|
|
// Complete
|
|
if (!ReportChangeConfirm()) {
|
|
MessageUtil.ShowToast($"RMS Change Recipe Ack Timeout", Log);
|
|
_aurora.AlarmService.SetAlarm(AlarmCode.RMS_RECIPE_EDIT_REQUEST_RESPONSE_TIMEOUT);
|
|
return;
|
|
}
|
|
|
|
MessageUtil.ShowToast($"Complete OnParameterReadRequest", Log);
|
|
});
|
|
}
|
|
|
|
private bool ApplyReportToParam(ScannerParam param, int parameterNo)
|
|
{
|
|
try {
|
|
// Report -> 모델 (readValue)
|
|
param.MarkSpeed = getReportData($"{nameof(param.MarkSpeed)}_{parameterNo}").readValue(param.MarkSpeed);
|
|
param.JumpSpeed = getReportData($"{nameof(param.JumpSpeed)}_{parameterNo}").readValue(param.JumpSpeed);
|
|
param.LaserPower1 = getReportData($"{nameof(param.LaserPower1)}_{parameterNo}").readValue(param.LaserPower1);
|
|
param.LaserPower2 = getReportData($"{nameof(param.LaserPower2)}_{parameterNo}").readValue(param.LaserPower2);
|
|
param.RampingStartPower = getReportData($"{nameof(param.RampingStartPower)}_{parameterNo}").readValue(param.RampingStartPower);
|
|
param.RampingStartDist = getReportData($"{nameof(param.RampingStartDist)}_{parameterNo}").readValue(param.RampingStartDist);
|
|
param.RampingEndPower = getReportData($"{nameof(param.RampingEndPower)}_{parameterNo}").readValue(param.RampingEndPower);
|
|
param.RampingEndDist = getReportData($"{nameof(param.RampingEndDist)}_{parameterNo}").readValue(param.RampingEndDist);
|
|
return true;
|
|
}
|
|
catch (Exception ex) {
|
|
Log.E($"ApplyReportToParam[{parameterNo}] 예외: {ex.Message}");
|
|
MessageUtil.ShowToast($"RMS 파라미터 읽기 중 오류 발생 (param={parameterNo})", Log);
|
|
_aurora.AlarmService.SetAlarm(AlarmCode.RMS_PAGE_SETTING_NULL);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private bool ApplyParamToReport(ScannerParam param, int parameterNo)
|
|
{
|
|
// 모델 -> Report (Value = )
|
|
if (!TrySetReportData($"RecipeNo", _aurora.RecipeManager.ActivatedRecipe().Id)) return false;
|
|
if (!TrySetReportData($"{nameof(param.MarkSpeed)}_{parameterNo}", param.MarkSpeed)) return false;
|
|
if (!TrySetReportData($"{nameof(param.JumpSpeed)}_{parameterNo}", param.JumpSpeed)) return false;
|
|
if (!TrySetReportData($"{nameof(param.LaserPower1)}_{parameterNo}", param.LaserPower1)) return false;
|
|
if (!TrySetReportData($"{nameof(param.LaserPower2)}_{parameterNo}", param.LaserPower2)) return false;
|
|
if (!TrySetReportData($"{nameof(param.RampingStartPower)}_{parameterNo}", param.RampingStartPower)) return false;
|
|
if (!TrySetReportData($"{nameof(param.RampingStartDist)}_{parameterNo}", param.RampingStartDist)) return false;
|
|
if (!TrySetReportData($"{nameof(param.RampingEndPower)}_{parameterNo}", param.RampingEndPower)) return false;
|
|
if (!TrySetReportData($"{nameof(param.RampingEndDist)}_{parameterNo}", param.RampingEndDist)) return false;
|
|
return true;
|
|
}
|
|
}
|
|
}
|