Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Moryx.Drivers.OpcUa/ApplicationConfigurationFactory.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) 2025, Phoenix Contact GmbH & Co. KG
// Licensed under the Apache License, Version 2.0

using Microsoft.Extensions.Logging;
using Moryx.Drivers.OpcUa.Exceptions;
using Opc.Ua;
using Opc.Ua.Configuration;

Expand Down Expand Up @@ -40,7 +42,7 @@ public virtual async Task<ApplicationConfiguration> Create(ILogger logger, strin
var haveAppCertificate = await application.CheckApplicationInstanceCertificate(false, 0);
if (!haveAppCertificate)
{
throw new Exception("Application instance certificate invalid!");
throw new InvalidCertificateException("Application instance certificate invalid!");
}
else
{
Expand Down
3 changes: 2 additions & 1 deletion src/Moryx.Drivers.OpcUa/DataValueResult.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Copyright (c) 2025, Phoenix Contact GmbH & Co. KG
// Licensed under the Apache License, Version 2.0

using Moryx.Tools;
using Opc.Ua;
using Moryx.Tools;

namespace Moryx.Drivers.OpcUa;

Expand Down
20 changes: 20 additions & 0 deletions src/Moryx.Drivers.OpcUa/Exceptions/InvalidCertificateException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) 2025, Phoenix Contact GmbH & Co. KG
// Licensed under the Apache License, Version 2.0

namespace Moryx.Drivers.OpcUa.Exceptions;

[Serializable]
internal class InvalidCertificateException : Exception
{
public InvalidCertificateException()
{
}

public InvalidCertificateException(string message) : base(message)
{
}

public InvalidCertificateException(string message, Exception innerException) : base(message, innerException)
{
}
}
1 change: 0 additions & 1 deletion src/Moryx.Drivers.OpcUa/IOpcUaDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using Moryx.AbstractionLayer.Drivers.InOut;
using Moryx.AbstractionLayer.Drivers.Message;
using Moryx.Drivers.OpcUa;

namespace Moryx.Drivers.OpcUa;

Expand Down
2 changes: 1 addition & 1 deletion src/Moryx.Drivers.OpcUa/Nodes/OpcUaDisplayNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public OpcUaDisplayNode()
/// <summary>
/// Id of the Opc Ua Node
/// </summary>
public string NodeId => _nodeId == null ? string.Empty : _nodeId.Format(CultureInfo.InvariantCulture);
public string NodeId => _nodeId == null ? string.Empty : _nodeId.Identifier.ToString();

/// <summary>
/// Display Name of the Opc Ua Node
Expand Down
35 changes: 30 additions & 5 deletions src/Moryx.Drivers.OpcUa/Nodes/OpcUaNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0

using System.Globalization;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
using Moryx.AbstractionLayer.Drivers;
using Moryx.AbstractionLayer.Drivers.Message;
Expand All @@ -21,6 +20,7 @@ public class OpcUaNode : IMessageChannel
{
private IOpcUaDriver _driver => (IOpcUaDriver)Driver;

private const int DefaultNamespaceLength = 5;
private readonly IModuleLogger _logger;

/// <inheritdoc/>
Expand Down Expand Up @@ -82,12 +82,34 @@ public event EventHandler<object> Received
}
}

/// <summary>
/// Converts a NodeId string into an expanded NodeId string that matches the OPC UA specification;
/// </summary>
public static string CreateExpandedNodeId(string nodeId)
{
var result = Regex.Replace(nodeId, ";ns=\\d+", "");
result = result.Trim();
var result = nodeId.Trim();
result = OpcUaNodeHelpers.NodeIdWithNamespaceIndexRegex().Replace(result, "");
result = RemoveNamespaceIndexZero(result);
return result;
}

private static string RemoveNamespaceIndexZero(string nodeId)
{
if (nodeId.StartsWith("ns=0;"))
{
return nodeId[DefaultNamespaceLength..];
}
return nodeId;
}

/// <summary>
/// Converts a NodeId into an expanded NodeId string that matches the OPC UA specification;
/// </summary>
public static string CreateExpandedNodeId(NodeId nodeId)
{
return CreateExpandedNodeId(nodeId.ToString());
}

internal MonitoredItem MonitoredItem { get; set; }

#region Constructors
Expand All @@ -98,17 +120,21 @@ private OpcUaNode(IOpcUaDriver driver, IModuleLogger logger)

}

/// <inheritdoc />
public OpcUaNode(IOpcUaDriver driver, IModuleLogger logger, string namespaceUri, string nodeIdValue)
: this(driver, logger)
{
NodeId = new ExpandedNodeId(nodeIdValue, namespaceUri);
}

/// <inheritdoc />
public OpcUaNode(IOpcUaDriver driver, IModuleLogger logger, ExpandedNodeId nodeId, NamespaceTable namespaceTable)
: this(driver, logger)
{
NodeId = new ExpandedNodeId(nodeId.Identifier, nodeId.NamespaceIndex, namespaceTable.GetString(nodeId.NamespaceIndex), nodeId.ServerIndex);
}

/// <inheritdoc />
public OpcUaNode(IOpcUaDriver driver, IModuleLogger logger, string identifier)
{
Driver = driver;
Expand All @@ -134,7 +160,7 @@ public void Send(object payload)
_logger?.Log(LogLevel.Error, "It is tried to read the value of node {NodeId}, but the node is no variable node", NodeId);
return;
}
_driver.WriteNode(this.Identifier, payload);
_driver.WriteNode(Identifier, payload);
}

/// <summary>
Expand All @@ -153,5 +179,4 @@ internal void ReceivedMessage(object payload)
{
_received?.Invoke(this, payload);
}

}
12 changes: 12 additions & 0 deletions src/Moryx.Drivers.OpcUa/Nodes/OpcUaNodeHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2025, Phoenix Contact GmbH & Co. KG
// Licensed under the Apache License, Version 2.0

using System.Text.RegularExpressions;

namespace Moryx.Drivers.OpcUa;

internal static partial class OpcUaNodeHelpers
{
[GeneratedRegex(";ns=\\d+")]
public static partial Regex NodeIdWithNamespaceIndexRegex();
}
Loading
Loading