using Aurora; using Aurora.Api; using Aurora.Api.Manager; using DB; using DB.Recipe; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Windows; using VisionCommon; using WeldingCommon.Sequences; namespace WeldingCommon.Utils { public static class RecipeHelper { // ═══ [진단계측 2026-08-04] 시작 ═══════════════════════════════════════ // 원본 1줄 : public static (int id, string name) SelectedRecipe; // 대상(SelectedRecipe)이 바뀌는 순간을 잡기 위해 필드 → 프로퍼티로 전환. // 외부에서의 읽기/쓰기 방식은 동일하다(대입 4곳, 나머지는 .name/.id 읽기뿐). // 원복 : 아래 블록 전체를 위 원본 1줄로 되돌린다. static (int id, string name) _SelectedRecipe; public static (int id, string name) SelectedRecipe { get { return _SelectedRecipe; } set { var old = _SelectedRecipe; _SelectedRecipe = value; RecipeTrace.Mark("대상변경 SELECTED", $"[{old.id}][{old.name}] → [{value.id}][{value.name}]"); } } // ═══ [진단계측 2026-08-04] 끝 ═════════════════════════════════════════ static IRecipeManager mRecipeManager = Application.Current.AuroraEnv().RecipeManager; static string GetTeachingEditorFullPath(string recipeName) { var recipePath = ConfigurationManager.AppSettings.Get("DATA_PATH"); var fullPath = Path.Combine( recipePath, RecipeExIds.RECIPE_DIR, recipeName, RecipeExIds.TEACHING_EDITOR_RECIPE); var dir = Path.GetDirectoryName(fullPath); if (!Directory.Exists(dir)) { Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); } return fullPath; } public static void SaveRecipe(string recipeName, bool includeModel = true) { // ═══ [진단계측 2026-08-04] 시작 ═══════════════════════════════════ // 원본 1줄 : CommonHelper.GetMainPage().SaveRecipe(GetTeachingEditorFullPath(recipeName), includeModel); // 저장 전/후를 모두 찍어 무엇이 무엇으로 바뀌었는지 확인한다. 저장 자체는 막지 않는다. // 원복 : 이 블록 전체를 위 원본 1줄로 되돌린다. var targetPath = GetTeachingEditorFullPath(recipeName); var snap = RecipeTrace.BeforeSave(recipeName, targetPath); CommonHelper.GetMainPage().SaveRecipe(targetPath, includeModel); RecipeTrace.AfterSave(snap); // ═══ [진단계측 2026-08-04] 끝 ═════════════════════════════════════ } public static void OnSaveRecipeForEditing() { if (string.IsNullOrWhiteSpace(SelectedRecipe.name)) { return; } SaveRecipe(SelectedRecipe.name); if (SelectedRecipe.name == mRecipeManager.ActivatedRecipe().Name) { CommonHelper.UpdateAutoRunPage(); } } public static void UpdateAutorunRecipe() { if (string.IsNullOrWhiteSpace(SelectedRecipe.name)) { return; } if (SelectedRecipe.name == mRecipeManager.ActivatedRecipe().Name) { CommonHelper.UpdateAutoRunPage(); } } public static void ReloadRecipe(string recipeName) { // ═══ [진단계측 2026-08-04] 시작 ═══════════════════════════════════ // 원본 3줄 (try 블록 안의 3줄이 원본 그대로다) : // var camConfig = VisionEnv.AuroraEnv.DeviceManager.GetDeviceConfig(eCamId.CAM1.ToString()) as CamConfig; // CommonHelper.GetMainPage().UpdateDefaultField(camConfig.ChildImage.ChildBufRowCols); // CommonHelper.GetMainPage().ReloadRecipe(GetTeachingEditorFullPath(recipeName)); // 내용 전환의 성공/실패/무동작을 구분해 기록한다. 동작은 그대로다. // 원복 : try/catch 와 Mark 호출을 걷어내고 위 원본 3줄만 남긴다. var before = RecipeTrace.MemFingerprint(); RecipeTrace.Mark("내용변경 RELOAD 진입", $"요청=[{recipeName}] 지문(전)={before}"); try { var camConfig = VisionEnv.AuroraEnv.DeviceManager.GetDeviceConfig(eCamId.CAM1.ToString()) as CamConfig; CommonHelper.GetMainPage().UpdateDefaultField(camConfig.ChildImage.ChildBufRowCols); CommonHelper.GetMainPage().ReloadRecipe(GetTeachingEditorFullPath(recipeName)); var after = RecipeTrace.MemFingerprint(); RecipeTrace.Mark(before == after ? "RELOAD 완료(내용무변화!)" : "RELOAD 완료", $"요청=[{recipeName}] 지문(후)={after}"); } catch (System.Exception ex) { RecipeTrace.Mark("*** RELOAD 실패 ***", $"요청=[{recipeName}] {ex.GetType().Name}: {ex.Message}"); throw; // 기존 동작 보존 — 예외 전파는 그대로 } // ═══ [진단계측 2026-08-04] 끝 ═════════════════════════════════════ } public static RecipeWeldingLines getRecipeInfo(string recipeName) => CommonHelper.GetMainPage().getRecipeInfo(GetTeachingEditorFullPath(recipeName)); public static void OnActiveReloaded() { var activeRecipe = mRecipeManager.ActivatedRecipe(); SelectedRecipe = (activeRecipe.Id, activeRecipe.Name); ReloadRecipe(activeRecipe.Name); } public static void OnActiveRecipe(int recipeId, string recipeName) { mRecipeManager.ActivateRecipe(recipeId, recipeName); } public static string SearchRecipeItem(int recipeID) { string recipeName = string.Empty; var listRecipe = mRecipeManager.Recipes(); // Find the recipe with the matching ID var recipe = listRecipe.FirstOrDefault(r => r.Id == recipeID); // If a recipe is found, assign its name to recipeName if (recipe != null) { recipeName = recipe.Name; } return recipeName; } //LASA는 Recipe를 1개만 사용 할 수 있음 //TechingRecipe -> ActiavatedReicpe(AutoRun) -> TeachingRecipe //AutoRun 완료 후 다시 Teching 중인 Recipe로 Rollback 해줘야 함 public static void RollbackRecipe() { Application.Current.Dispatcher.InvokeAsync(() => { ReloadRecipe(SelectedRecipe.name); }); } public static bool OnChangeRecipe(int RecipeID) { IList recipes = mRecipeManager.Recipes(); //list 에서 정보 얻을 수 있는것을 찾아보자 return true; } } }