internal static void HandleInitialData(string url, OpcInitialData initialData) { log.Debug("HandleInitialData entered"); OPCServerFolderBehaviorData folderExt = EntityCache <OPCServerFolderBehaviorData> .GetCache().AllEntities.FirstOrDefault(s => s.Url == url); Folder f = folderExt?.GetEntity() as Folder; if (f == null) { throw new Exception("No OPC server found with this URL"); } if (initialData.Nodes != null) { UpdateTagsInFolder(f.FolderID + ".tagdata", f.FolderID, url, initialData.Nodes); } string[] eventIds = FolderService.GetFolderEntities <OPCEvent>(f.FolderID).Select(e => e.Id).ToArray(); foreach (BaseTagValue value in initialData.Values) { // Record the value separately for each event, because they might update at different rates: foreach (string eventId in eventIds) { string key = eventId + "|" + value.Path; OPCEngine.mostRecentValues[key] = value; } } log.Debug("HandleInitialData complete"); }
public object GetValue(string name) { Log.Debug($"GetValue called on path {Path}"); if (Path == null || !Path.Contains(".")) { // If at the top, or at a server, the next part can't be a tag: string nextPath = (Path == null) ? name : $"{Path}.{name}"; return(new OPCDataProvider { Path = nextPath, Snapshot = this.Snapshot }); } string[] pathSplit = Path.Split(new char[] { '.' }, 2); // {Server Name}.{remaining.tag.path} Folder folder = opcServerOrm.Fetch().Select(ext => ext.GetEntity()).FirstOrDefault(f => f.EntityName == pathSplit[0]) as Folder; if (folder == null) { throw new Exception($"Could not find server named {pathSplit[0]}"); } string[] eventIds = FolderService.GetFolderEntities <OPCEvent>(folder.FolderID).Select(e => e.Id).ToArray(); BaseTagValue mostRecentTag = null; IDictionary <string, BaseTagValue> sourceDict = ((Snapshot as IDictionary <string, BaseTagValue>) ?? OPCEngine.mostRecentValues); foreach (string eventId in eventIds) { string key = $"{eventId}|{pathSplit[1]}.{name}"; BaseTagValue tag; if (sourceDict.TryGetValue(key, out tag)) { if (mostRecentTag == null || mostRecentTag.TimeStamp < tag.TimeStamp) { mostRecentTag = tag; } } } if (mostRecentTag != null) { return(TagValueUtils.GetObjectValueFromTag(mostRecentTag)); } // No current value found, so check folders to see whether this is a folder or a tag: Folder tagDataFolder = folder.GetSubFolder().FirstOrDefault(x => x.EntityName == "Tag Data"); if (tagDataFolder == null) { throw new Exception("Tag data folder not found"); } string[] parts = pathSplit[1].Split('.'); Folder currentFolder = tagDataFolder; for (int i = 0; i < parts.Length; ++i) { // descend for each part, arriving at the folder which should contain the named entity Folder nextFolder = currentFolder.GetSubFolder().FirstOrDefault(x => x.EntityName == parts[i]); if (nextFolder == null) { throw new Exception($"Folder '{parts[i]}' not found in folder '{currentFolder?.EntityName}'."); } currentFolder = nextFolder; } Folder namedFolder = FolderService.GetFolderEntities <Folder>(currentFolder.FolderID).FirstOrDefault(x => x.EntityName == name); if (namedFolder != null) { return new OPCDataProvider { Path = $"{this.Path}.{name}", Snapshot = this.Snapshot } } ; OPCTag namedTag = FolderService.GetFolderEntities <OPCTag>(currentFolder.FolderID).FirstOrDefault(x => x.EntityName == name); if (namedTag != null) { throw new Exception($"Tag '{name}' has no known value"); } else { throw new Exception($"No tag or folder '{name}' found in '{currentFolder.EntityName}'"); } }
private static void UpdateTagsInFolder(string folderId, string baseFolderId, string serverUrl, OpcNode[] opcNodes) { // get the set of tags + folders within this folder, so that missing ones can be removed: HashSet <string> oldTagNames = new HashSet <string>(FolderService.GetFolderEntities <OPCTag>(folderId).Select(x => x.EntityName)); HashSet <string> oldFolderNames = new HashSet <string>(FolderService.GetFolderEntities <Folder>(folderId).Select(x => x.EntityName)); foreach (OpcNode node in opcNodes) { if (ArrayUtilities.IsEmpty(node.Children)) { // create or update tag oldTagNames.Remove(node.Name); OPCTag tag = FolderService.GetFolderEntities <OPCTag>(folderId).FirstOrDefault(x => x.EntityName == node.Name) ?? new OPCTag(); tag.EntityName = node.Name; tag.EntityFolderID = folderId; tag.Path = node.FullPath; tag.TypeName = node.TypeName; tag.ServerUrl = serverUrl; tag.Store(); } else { oldFolderNames.Remove(node.Name); Folder sf = FolderService.GetFolderEntities <Folder>(folderId).FirstOrDefault(x => x.EntityName == node.Name); if (sf == null) { new Folder { EntityName = node.Name, EntityFolderID = folderId, FolderBehaviorType = typeof(DefaultFolderBehavior).FullName }.Store(); // create, then fetch to make sure id is present. sf = FolderService.GetFolderEntities <Folder>(folderId).FirstOrDefault(x => x.EntityName == node.Name); if (sf == null) { throw new Exception($"Folder {node.Name} could not be created in {folderId}."); } } UpdateTagsInFolder(sf.FolderID, baseFolderId, serverUrl, node.Children); } } foreach (string removedTag in oldTagNames) { OPCTag tag = FolderService.GetFolderEntities <OPCTag>(folderId).FirstOrDefault(x => x.EntityName == removedTag); if (tag != null) { // delete tag & matching flow constant: tag.Delete(); string flowConstantId = $"OPCTAG__{baseFolderId}__{tag.Path}"; new ORM <FlowConstant>().Delete(flowConstantId); } } foreach (string removedFolder in oldFolderNames) { Folder folder = FolderService.GetFolderEntities <Folder>(folderId).FirstOrDefault(x => x.EntityName == removedFolder); if (folder != null) { folder.Delete(); } } }