/******************************************************************************
** 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]
}
}