using Aurora; using Aurora.Api; using Hermes; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace VisionCommon { /// /// 현재 실행 중인 SW의 Recipe 구성에 맞게 /// 장비에 저장된 Recipe 파일을 업데이트 한다. /// public static class RecipeUpdater { private const string KEY_UNIT_RECIPES = nameof(VisionDef.UnitRecipes); private const string KEY_SUB_SYS_RECIPES = nameof(UnitRecipe.SubSysRecipes); private const string KEY_FOV_RECIPES = nameof(SubSysRecipe.FovRecipes); private const string KEY_ALIGN_RECIPES = nameof(SubSysRecipe.AlignRecipes); private static Logger _logger = new Logger(nameof(RecipeUpdater)); /// /// 레시피 업데이트를 실행한다. /// /// 레시피 또는 모델 /// 실행 결과 public static int Run(eRecipeModelType recipeModelType) { var recipeDirectories = RecipeUpdaterUtil.GetDataDirectories(recipeModelType); var updaters = GetRecipeUpdaters(); foreach (var recipeDir in recipeDirectories) { var recipeFilePath = Path.Combine(recipeDir, $"{VisionKeys.VisionRecipeKey}.json"); if (File.Exists(recipeFilePath)) { JToken machineRecipeOriginal = JsonManager.ParseFromFile(recipeFilePath); if (machineRecipeOriginal == null) { _logger.E($"Read recipe file error : {recipeFilePath}"); continue; } JToken machineRecipe = machineRecipeOriginal.DeepClone(); SetInitialVersion(machineRecipe); var machineRecipeVersion = GetRecipeVersion(machineRecipe); if (!IsUpdatable(machineRecipeVersion)) { continue; } var result = Update(machineRecipe, machineRecipeVersion, VisionDef.RECIPE_VERSION_CURRENT, updaters); if (result == E1.OK) { SaveBackupFile(machineRecipeOriginal, machineRecipeVersion, recipeDir); SaveUpdateFile(machineRecipe, recipeDir); } } } return E1.OK; } private static List GetRecipeUpdaters() { var updaters = new List(); Type targetType = typeof(Updater); Assembly assembly = Assembly.GetExecutingAssembly(); var types = assembly.GetTypes(); foreach (var type in types) { if (targetType.IsAssignableFrom(type)) { ConstructorInfo ctor = type.GetConstructor(new Type[] { }); if (ctor != null) { updaters.Add((Updater)ctor.Invoke(new object[] { })); } } } return updaters; } private static void SetInitialVersion(JToken machineRecipe) { var machineRecipeVersion = GetRecipeVersion(machineRecipe); if (machineRecipeVersion == 0) { SetRecipeVersion(machineRecipe, VisionDef.RECIPE_VERSION_INITIAL); } } private static bool IsUpdatable(double machineRecipeVersion) { return !MathUtil.Equals(machineRecipeVersion, VisionDef.RECIPE_VERSION_CURRENT, 0.01); } private static double GetRecipeVersion(JToken machineRecipe) { try { var versionToken = machineRecipe.SelectToken(nameof(VisionDef.Version)); if (versionToken != null) { return Math.Round(versionToken.ToObject(), 1); } } catch (Exception e) { _logger.E(e.Message); } return 0; } private static int SetRecipeVersion(JToken machineRecipe, double version) { try { var versionToken = machineRecipe.SelectToken(nameof(VisionDef.Version)); if (versionToken == null) { machineRecipe[nameof(VisionDef.Version)] = version; } else { versionToken.Replace(new JValue(Math.Round(version, 1))); } } catch (Exception e) { _logger.E(e.Message); return E1.GENERIC; } return E1.OK; } private static int Update(JToken machineRecipe, double machineRecipeVersion, double swVersion, List updaters) { if (machineRecipeVersion < VisionDef.RECIPE_VERSION_CURRENT) { return Upgrade(machineRecipe, machineRecipeVersion, VisionDef.RECIPE_VERSION_CURRENT, updaters); } else if (VisionDef.RECIPE_VERSION_CURRENT < machineRecipeVersion) { return Downgrade(machineRecipe, machineRecipeVersion, VisionDef.RECIPE_VERSION_CURRENT, updaters); } return E1.GENERIC; } private static int Upgrade(JToken machineRecipe, double machineRecipeVersion, double swVersion, List updaters) { for (double curVer = machineRecipeVersion; curVer < swVersion; curVer += 0.1) { double nextVer = curVer + 0.1; foreach (var updater in updaters) { updater.Update(machineRecipe, curVer, nextVer); } SetRecipeVersion(machineRecipe, nextVer); } return E1.OK; } private static int Downgrade(JToken machineRecipe, double machineRecipeVersion, double swVersion, List updaters) { for (double curVer = machineRecipeVersion; swVersion < curVer; curVer -= 0.1) { double nextVer = curVer - 0.1; foreach (var updater in updaters) { updater.Update(machineRecipe, curVer, nextVer); } SetRecipeVersion(machineRecipe, nextVer); } return E1.OK; } private static int SaveBackupFile( JToken machineRecipeOriginal, double machineRecipeVersion, string recipeDir) { string datetimeStr = DateTime.Now.ToString("yyyyMMdd_hhmmss"); string backupFileName = $"{VisionKeys.VisionRecipeKey}_{datetimeStr}_v{machineRecipeVersion}.json"; return JsonManager.SaveToFile( machineRecipeOriginal, Path.Combine(recipeDir, backupFileName)); } private static int SaveUpdateFile(JToken machineRecipe, string recipeDir) { return JsonManager.SaveToFile( machineRecipe, Path.Combine(recipeDir, $"{VisionKeys.VisionRecipeKey}.json")); } } }