Beispiel #1
0
        public void SaveNodestateCollectionAsNodeSet2(ISystemContext context, NodeStateCollection nsc, Stream stream,
                                                      bool filterSingleNodeIds, bool addRootItem = false, NodeState rootItem = null)
        {
            Opc.Ua.Export.UANodeSet nodeSet = new Opc.Ua.Export.UANodeSet();
            nodeSet.LastModified          = DateTime.UtcNow;
            nodeSet.LastModifiedSpecified = true;

            //
            // Because the pain of so many wasted hours is so great:
            // This function realizes a "write Nodeset2.xml" functionality, hwich
            // seems to not work out-of-the-box by the existing OPC UA .dll
            // (see "SaveNodestateCollectionAsNodeSet2tryout", .dll is an old version
            //  because auf .net Framework 4.7.2)
            //
            // This function "fakes" this export.
            // Remark: the call of nodeSet.Export() shift the namespace-index.
            // For multiple hours I tried to initialize the namespace-index better,
            // or to figure out, which is the correct exported node for "AASROOT".
            // It was not possible. So, a very bad hack is used.
            //

            //// nodeSet.NamespaceUris = new[] { "http://opcfoundation.org/UA/" };
            //// var l = new List<string>();
            //// l.Add("http://opcfoundation.org/UA/");
            //// l.AddRange(NamespaceUris);
            //// nodeSet.NamespaceUris = l.ToArray();

            Utils.Trace(Utils.TraceMasks.Operation, "Exporting {0} nodes ..", nsc.Count);
            int i = 0;

            foreach (var n in nsc)
            {
                nodeSet.Export(context, n);
                if ((i++) % 500 == 0)
                {
                    Utils.Trace(Utils.TraceMasks.Operation, "  .. exported already {0} nodes ..", nodeSet.Items.Length);
                }
            }

            if (filterSingleNodeIds)
            {
                Utils.Trace(Utils.TraceMasks.Operation, "Filtering single node ids..");

                // MIHO: There might be DOUBLE nodeIds in the the set!!!!!!!!!! WTF!!!!!!!!!!!!!
                // Brutally eliminate them
                var nodup = new List <Opc.Ua.Export.UANode>();

#if __old_implementation
                foreach (var it in nodeSet.Items)
                {
                    var found = false;
                    foreach (var it2 in nodup)
                    {
                        if (it.NodeId == it2.NodeId)
                        {
                            found = true;
                        }
                    }
                    if (found)
                    {
                        continue;
                    }
                    nodup.Add(it);
                }
#else
                var visitedNodeIds = new Dictionary <string, int>();

                foreach (var it in nodeSet.Items)
                {
                    if (visitedNodeIds.ContainsKey(it.NodeId))
                    {
                        continue;
                    }
                    visitedNodeIds.Add(it.NodeId, 1);

                    // try to remove double references
                    if (it.References != null)
                    {
                        var newrefs = new List <Opc.Ua.Export.Reference>();
                        foreach (var oldref in it.References)
                        {
                            // trivial
                            if (oldref == null)
                            {
                                continue;
                            }

                            // brute force check if already there
                            var found = false;
                            foreach (var nr in newrefs)
                            {
                                if (oldref.ReferenceType == nr.ReferenceType &&
                                    oldref.IsForward == nr.IsForward &&
                                    oldref.Value == nr.Value)
                                {
                                    found = true;
                                    break;
                                }
                            }

                            // if not, add
                            if (!found)
                            {
                                newrefs.Add(oldref);
                            }
                        }
                        // only change when necessary (reduce the impact)
                        if (it.References.Length != newrefs.Count)
                        {
                            it.References = newrefs.ToArray();
                        }
                    }

                    nodup.Add(it);
                }
#endif

                if (addRootItem)
                {
                    // manually a root item
                    // lessons learnt: not required; do not use!

                    Utils.Trace(Utils.TraceMasks.Operation, "Adding root item..");

                    var rootItemSt = "ns=2;i=95"; // weird default
                    if (rootItem != null)
                    {
                        // Bad hack, apoligizes
                        var ni = new NodeId(
                            value: rootItem.NodeId.Identifier,
                            namespaceIndex: (ushort)((rootItem.NodeId.NamespaceIndex) - 1));
                        rootItemSt = ni.Format();
                    }

                    var ri = new Opc.Ua.Export.UAObject()
                    {
                        BrowseName  = "Objects",
                        DisplayName = new[] {
                            new Opc.Ua.Export.LocalizedText()
                            {
                                Locale = "en", Value = "Objects"
                            }
                        },
                        NodeId     = "ns=0;i=85",
                        References = new[]
                        {
                            //// It would have been nice to use symbols, but this did not work;
                            //// Opc.Ua.ReferenceTypeIds.HierarchicalReferences.Format() -> "ns=2;i=95"
                            //// Opc.Ua.ReferenceTypeIds.HasTypeDefinition.Format() -> FoldersType!! */ /* "i=68" ??

                            new Opc.Ua.Export.Reference()
                            {
                                ReferenceType = "i=33", Value = rootItemSt
                            },
                            new Opc.Ua.Export.Reference()
                            {
                                ReferenceType = "i=40",
                                Value         = "i=61"
                            }
                        },
                    };

                    nodup.Add(ri);
                }

                nodeSet.Items = nodup.ToArray();
            }

            //
            // write
            //

            Utils.Trace(Utils.TraceMasks.Operation, "Writing stream ..");
            nodeSet.Write(stream);
        }