/****************************************************************************** ** Copyright (c) 2006-2018 Unified Automation GmbH All rights reserved. ** ** Software License Agreement ("SLA") Version 2.7 ** ** Unless explicitly acquired and licensed from Licensor under another ** license, the contents of this file are subject to the Software License ** Agreement ("SLA") Version 2.7, or subsequent versions ** as allowed by the SLA, and You may not copy or use this file in either ** source code or executable form, except in compliance with the terms and ** conditions of the SLA. ** ** All software distributed under the SLA is provided strictly on an ** "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, ** AND LICENSOR HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT ** LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR ** PURPOSE, QUIET ENJOYMENT, OR NON-INFRINGEMENT. See the SLA for specific ** language governing rights and limitations under the SLA. ** ** Project: .NET based OPC UA Client Server SDK ** ** Description: OPC Unified Architecture Software Development Kit. ** ** The complete license agreement can be found here: ** http://unifiedautomation.com/License/SLA/2.7/ ******************************************************************************/ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.IO; using System.Reflection; using UnifiedAutomation.UaBase; using UnifiedAutomation.UaServer; namespace acdp { internal class XMLNodeManager : BaseNodeManager { /// /// Gets or sets the index of the instance namespace. /// /// /// The index of the instance namespace. /// public ushort InstanceNamespaceIndex { get; set; } /// /// Gets or sets the index of the type namespace. /// /// /// The index of the type namespace. /// public ushort TypeNamespaceIndex { get; set; } /// /// Called when the node manager is started. /// public override void Startup() { try { Console.WriteLine("Starting XMLNodeManager."); base.Startup(); // save the namespaces used by this node manager. InstanceNamespaceIndex = AddNamespaceUri("http://www.acdp.at/DI_test/"); TypeNamespaceIndex = AddNamespaceUri("http://www.acdp.at/DI_test/"); // load the model. Console.WriteLine("Loading XML Models."); ImportUaNodeset(new FileInfo("../../Model/Opc.Ua.Di.NodeSet2.xml")); ImportUaNodeset(new FileInfo("../../Model/di_test.xml")); // initialize the underlying system. //m_system.Initialize(); SetVariableConfiguration(new NodeId(6010, 2), NodeHandleType.ExternalPush, null); /* // Create a Folder for Controllers CreateObjectSettings settings = new CreateObjectSettings() { ParentNodeId = ObjectIds.ObjectsFolder, ReferenceTypeId = ReferenceTypeIds.Organizes, RequestedNodeId = new NodeId("Controllers", InstanceNamespaceIndex), BrowseName = new QualifiedName("Controllers", InstanceNamespaceIndex), TypeDefinitionId = ObjectTypeIds.FolderType }; CreateObject(Server.DefaultRequestContext, settings); // Create controllers from configuration foreach (BlockConfiguration block in m_system.GetBlocks()) { // set type definition NodeId NodeId typeDefinitionId = ObjectTypeIds.BaseObjectType; if (block.Type == BlockType.AirConditioner) { typeDefinitionId = new NodeId(yourorganisation.BA.ObjectTypes.AirConditionerControllerType, TypeNamespaceIndex); } else if (block.Type == BlockType.Furnace) { typeDefinitionId = new NodeId(yourorganisation.BA.ObjectTypes.FurnaceControllerType, TypeNamespaceIndex); } // create object. settings = new CreateObjectSettings() { ParentNodeId = new NodeId("Controllers", InstanceNamespaceIndex), ReferenceTypeId = ReferenceTypeIds.Organizes, RequestedNodeId = new NodeId(block.Name, InstanceNamespaceIndex), BrowseName = new QualifiedName(block.Name, TypeNamespaceIndex), TypeDefinitionId = typeDefinitionId }; CreateObject(Server.DefaultRequestContext, settings); /// [Snippet EURange] // Set NodeHandleType to ExternalPolled foreach (BlockProperty property in block.Properties) { // the node was already created when the controller object was instantiated. // this call links the node to the underlying system data. VariableNode variable = SetVariableConfiguration( new NodeId(block.Name, InstanceNamespaceIndex), new QualifiedName(property.Name, TypeNamespaceIndex), NodeHandleType.ExternalPolled, new SystemAddress() { Address = block.Address, Offset = property.Offset }); // Add information about expected range if (variable != null) { // in-memory nodes must be locked before updates. // reads do not require locks for simple types and references. // value reads require a lock. lock (InMemoryNodeLock) { variable.AccessLevel = (property.Writeable) ? AccessLevels.CurrentReadOrWrite : AccessLevels.CurrentRead; } if (property.Range != null) { SetVariableDefaultValue( variable.NodeId, new QualifiedName(BrowseNames.EURange), new Variant(property.Range)); } } } /// [Snippet EURange] } */ } catch (Exception e) { Console.WriteLine("Failed to start Lesson3aNodeManager. " + e.Message); } } /// /// Called when the node manager is stopped. /// public override void Shutdown() { try { Console.WriteLine("Stopping Lesson3aNodeManager."); // TBD base.Shutdown(); } catch (Exception e) { Console.WriteLine("Failed to stop Lesson3aNodeManager. " + e.Message); ; } } /// /// Reads the attributes. /// /// [Read] protected override void Read( RequestContext context, TransactionHandle transaction, IList operationHandles, IList settings) { for (int ii = 0; ii < operationHandles.Count; ii++) { DataValue dv = null; //// the data passed to CreateVariable is returned as the UserData in the handle. //SystemAddress address = operationHandles[ii].NodeHandle.UserData as SystemAddress; //if (address != null) //{ // // read the data from the underlying system. // object value = m_system.Read(address.Address, address.Offset); // if (value != null) // { // dv = new DataValue(new Variant(value, null), DateTime.UtcNow); // // apply any index range or encoding. // if (!String.IsNullOrEmpty(settings[ii].IndexRange) || !QualifiedName.IsNull(settings[ii].DataEncoding)) // { // dv = ApplyIndexRangeAndEncoding( // operationHandles[ii].NodeHandle, // dv, // settings[ii].IndexRange, // settings[ii].DataEncoding); // } // } //} Console.WriteLine($"Read NodeId: {operationHandles[ii].NodeId}"); dv = new DataValue(new Variant(1234.56), DateTime.UtcNow); // set an error if not found. if (dv == null) { dv = new DataValue(new StatusCode(StatusCodes.BadNodeIdUnknown)); } // return the data to the caller. ((ReadCompleteEventHandler)transaction.Callback)( operationHandles[ii], transaction.CallbackData, dv, false); } } /// [Read] /// /// Write the attributes /// /// [Write] protected override void Write( RequestContext context, TransactionHandle transaction, IList operationHandles, IList settings) { for (int ii = 0; ii < operationHandles.Count; ii++) { StatusCode error = StatusCodes.Good; // the data passed to CreateVariable is returned as the UserData in the handle. //SystemAddress address = operationHandles[ii].NodeHandle.UserData as SystemAddress; //if (address != null) //{ // if (!String.IsNullOrEmpty(settings[ii].IndexRange)) // { // error = StatusCodes.BadIndexRangeInvalid; // } // else if (!m_system.Write(address.Address, address.Offset, settings[ii].Value.Value)) // { // Console.WriteLine($"Write Value: {settings[ii].Value.Value}, NodeId: {operationHandles[ii].NodeId}"); // //error = StatusCodes.BadUserAccessDenied; // } //} //else //{ // error = StatusCodes.BadNodeIdUnknown; //} Console.WriteLine($"Write Value: {settings[ii].Value.Value}, NodeId: {operationHandles[ii].NodeId}"); // return the data to the caller. ((WriteCompleteEventHandler)transaction.Callback)( operationHandles[ii], transaction.CallbackData, error, false); } } /// [Write] #region Constructor /// /// Initializes a new instance of the class. /// /// [Create system in constructor] public XMLNodeManager(ServerManager server) : base(server) { // m_system = new UnderlyingSystem(); } /// [Create system in constructor] #endregion #region IDisposable /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing) { // TBD } } #endregion #region SystemAddress Class private class SystemAddress { public int Address; public int Offset; } #endregion #region Private Methods #endregion /// [Add system] #region Private Fields //private UnderlyingSystem m_system; #endregion /// [Add system] } }