using LabViewHelper; using NationalInstruments.LabVIEW.Interop; using OpenTap; using OpenTap.Addin.Annotation; using OpenTap.Addin.Util; using System; using System.Collections.Concurrent; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Xml.Serialization; using ViHelper; namespace AddInPlugin { public class LvlibpData { public string path { get; set; } public DateTime lastUpdateTime { get; set; } public string[] names { get; private set; } private ConcurrentDictionary inCache = new ConcurrentDictionary(); private ConcurrentDictionary outCache = new ConcurrentDictionary(); public LvlibpData(DateTime lastUpdateTime, string[] names) { this.lastUpdateTime = lastUpdateTime; this.names = names; } public void GetIO(string viName, out ViVariable[] inVars, out ViVariable[] outVars) { if (!inCache.ContainsKey(viName) || !outCache.ContainsKey(viName)) { LabViHelper.GetIOTypeByLvlibp(path, viName, out inVars, out outVars); inCache[viName] = inVars; outCache[viName] = outVars; } else { inVars = inCache[viName]; outVars = outCache[viName]; } } } public class LvlibpLoader { static readonly ConcurrentDictionary Cache = new ConcurrentDictionary(); public static void PreLoad() { try { LvlibpLoader.GetLibpNames("test.lvlibp", out _); } catch { } } private static LvlibpData GetCache(string path) { path = path.ToLower(); //if (!File.Exists(path)) //{ // return null; //} DateTime updateTime = File.GetLastWriteTime(path); if (!Cache.ContainsKey(path) || Cache[path].lastUpdateTime != updateTime) { LabViewRunner.GetLibpNames(new LVPath(path), out var names, out ErrorCluster error); Cache[path] = new LvlibpData(updateTime, names) { path = path }; } return Cache[path]; } public static void GetLibpNames(string path, out string[] names) { var cache = GetCache(path); names = cache?.names; } public static void GetViIO(string path, string viName, out ViVariable[] inVars, out ViVariable[] outVars) { inVars = new ViVariable[0]; outVars = new ViVariable[0]; var cache = GetCache(path); cache?.GetIO(viName, out inVars, out outVars); } } [Prototype] [Display("LvlibpStep", Description: "ÔËÐÐlvlibp")] public class LvlibpStep : VariableTestStep { #region Settings private string filePath; [Obsolete] // [Display("·¾¶", Order: 0.0, Description: "¾ø¶Ô·¾¶.")] [FilePath(FilePathAttribute.BehaviorChoice.Open, fileExtension: "Labview|*.lvlibp")] public string FilePath { get => filePath; set { Set(ref filePath, value); } } private LocationString fileLocation = new LocationString(); [Display("·¾¶", Order: 0.0, Description: "¾ø¶Ô·¾¶.")] [FilePath(FilePathAttribute.BehaviorChoice.Open, fileExtension: "Labview|*.lvlibp")] public LocationString FileLocation { get => fileLocation; set { Set(ref fileLocation, value); } } protected override void OnRootChanged(TestPlan old, TestPlan plan) { try { if (!string.IsNullOrEmpty(FilePath)) { FileLocation.AbsoluteLocation = FilePath; FilePath = null; } FileLocation.Refresh(Root.Path); FileLocation.PropertyChanged += FileLocation_PropertyChanged; if (!FileLocation.GetLocation(Root.Path, out string path)) { return; } //LabViewRunner.GetIO(new LVPath(ViPath), 0, out Cluster[] inputs, out Cluster[] outputs, out type[] iTypes, out type[] oTypes, out var viError); //LabViewRunner.GetLibpNames(new LVPath(path), out string[] names, out ErrorCluster error); LvlibpLoader.GetLibpNames(path, out string[] names); NameDatasource = new ObservableCollection(names); LoadVi(); LoadException = null; } catch (Exception ex) { LoadException = ex; //Log.Error("ViStep load vi error. {0}", ex); } } private ObservableCollection nameDatasource; [XmlIgnore] public ObservableCollection NameDatasource { get => nameDatasource; set { Set(ref nameDatasource, value); } } private string viName; [Display("VI", Order: 0.0, Description: "VIÃû³Æ.")] [DynamicSelect(nameof(NameDatasource))] public string ViName { get => viName; set { Set(ref viName, value); LoadVi(); } } private bool showWindow; [Display("ÏÔʾ´°¿Ú", Order: 0.0)] public bool ShowWindow { get => showWindow; set { Set(ref showWindow, value); } } #endregion private Exception loadException; [XmlIgnore] public Exception LoadException { get => loadException; set { Set(ref loadException, value); } } public LvlibpStep() { // ToDo: Set default values for properties / settings. //Rules.Add(() => !string.IsNullOrWhiteSpace(FilePath), "·¾¶²»ÄÜΪ¿Õ", FilePath); Rules.Add(() => FileLocation.GetLocation(Root.Path, out _), "Îļþ¼ÓÔØÊ§°Ü", nameof(FileLocation)); Rules.Add(() => LoadException == null, () => $"VI¼ÓÔØÊ§°Ü:{LoadException}", nameof(FileLocation)); } private void FileLocation_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { Load(); } private void ConcatVariable(MethodVariable mv, MethodVariable[] source) { MethodVariables.Add(mv); var preview = source?.FirstOrDefault(v => v.Name == mv.Name && !string.IsNullOrEmpty(v.ValueStr)); if (preview != null) { mv.ValueStr = preview.ValueStr; } } private void LoadVi() { try { if (!FileLocation.GetLocation(Root?.Path, out string path)) { return; } //LabViewRunner.GetIO(new LVPath(ViPath), 0, out Cluster[] inputs, out Cluster[] outputs, out type[] iTypes, out type[] oTypes, out var viError); //LabViHelper.GetIOTypeByLvlibp(path, ViName, out var inVariables, out var outVariables); LvlibpLoader.GetViIO(path, viName, out var inVariables, out var outVariables); var last = MethodVariables?.ToArray(); MethodVariables.Clear(); foreach (var inv in inVariables) { var newOne = new MethodVariable { Name = inv.Name, Type = inv.Type, TypeName = inv.Type.ToString(), Direction = VariableDirection.In, ValueStr = inv.Type == typeof(string) ? $"\"{inv.Data?.ToString()}\"" : inv.Data?.ToString() }; ConcatVariable(newOne, last); } foreach (var onv in outVariables) { var newOne = new MethodVariable { Name = onv.Name, Type = onv.Type, TypeName = onv.Type.ToString(), Direction = VariableDirection.Out }; ConcatVariable(newOne, last); } LoadException = null; } catch (Exception ex) { LoadException = ex; //Log.Error("ViStep load vi error. {0}", ex); } } private void Load() { try { if (!FileLocation.GetLocation(Root?.Path, out string path)) { return; } //LabViewRunner.GetIO(new LVPath(ViPath), 0, out Cluster[] inputs, out Cluster[] outputs, out type[] iTypes, out type[] oTypes, out var viError); LabViewRunner.GetLibpNames(new LVPath(path), out string[] names, out var outVariables); NameDatasource = new ObservableCollection(names); LoadException = null; } catch (Exception ex) { LoadException = ex; //Log.Error("ViStep load vi error. {0}", ex); } } public override void PrePlanRun() { // ToDo: Optionally add any setup code this step needs to run before the testplan starts base.PrePlanRun(); } /// /// ת»»²ÎÊý /// private void ResolveVariables() { foreach (var m in MethodVariables) { m.Value = PlanRun.Resolve(this, m.ValueStr, m.Type); } } /// /// ÔËÐк¯Êý /// private void RunMethod() { if (!FileLocation.GetLocation(Root?.Path, out string path)) { return; } ResolveVariables(); var ins = MethodVariables.Where(m => m.Direction == VariableDirection.In && m.Value != null) .Select(m => new LabViewHelper.Cluster { name = m.Name, variant__32Data = new LVVariant(m.Value) }).ToArray(); LabViewRunner.RunLibpByName2(new LVPath(path), ViName, 0, ShowWindow, ins, out var outs, out ErrorCluster err); if (err.status) { Verdict = Verdict.Error; return; } foreach (var ov in outs) { foreach (var m in MethodVariables) { if (ov.name == m.Name) { m.Value = ov.variant__32Data.value; break; } } } } protected override void RunDetail() { try { // ToDo: Add test case code here //RunChildSteps(); //If step has child steps. RunMethod(); UpdateVariableToRuntime(); this.Verdict = Verdict.Pass; } catch (Exception ex) { Log.Error("ViStep Run error. {0}", ex); this.Verdict = Verdict.Error; } } public override void PostPlanRun() { // ToDo: Optionally add any cleanup code this step needs to run after the entire testplan has finished base.PostPlanRun(); } } }