OPC function change

This commit is contained in:
luosheng
2023-06-03 14:51:04 +08:00
parent 58e546681a
commit 63788a1fd4
15 changed files with 55 additions and 144 deletions

View File

@@ -14,14 +14,11 @@ namespace Modbus.Net.Opc
/// </summary> /// </summary>
/// <param name="tagGeter">如何通过BaseMachine和AddressUnit构造Opc的标签</param> /// <param name="tagGeter">如何通过BaseMachine和AddressUnit构造Opc的标签</param>
/// <param name="machine">调用这个编码器的设备</param> /// <param name="machine">调用这个编码器的设备</param>
/// <param name="seperator">每两个标签之间用什么符号隔开,默认为/</param>
public AddressFormaterOpc(Func<BaseMachine<TMachineKey, TUnitKey>, AddressUnit<TUnitKey>, string[]> tagGeter, public AddressFormaterOpc(Func<BaseMachine<TMachineKey, TUnitKey>, AddressUnit<TUnitKey>, string[]> tagGeter,
BaseMachine<TMachineKey, TUnitKey> machine, BaseMachine<TMachineKey, TUnitKey> machine)
char seperator = '/')
{ {
Machine = machine; Machine = machine;
TagGeter = tagGeter; TagGeter = tagGeter;
Seperator = seperator;
} }
/// <summary> /// <summary>
@@ -35,11 +32,6 @@ namespace Modbus.Net.Opc
/// </summary> /// </summary>
protected Func<BaseMachine<TMachineKey, TUnitKey>, AddressUnit<TUnitKey>, string[]> TagGeter { get; set; } protected Func<BaseMachine<TMachineKey, TUnitKey>, AddressUnit<TUnitKey>, string[]> TagGeter { get; set; }
/// <summary>
/// 分割符
/// </summary>
public char Seperator { get; protected set; }
/// <summary> /// <summary>
/// 编码地址 /// 编码地址
/// </summary> /// </summary>

View File

@@ -3,7 +3,9 @@ using Hylasoft.Opc.Da;
using Hylasoft.Opc.Ua; using Hylasoft.Opc.Ua;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using URL = Opc.URL;
namespace Modbus.Net.Opc namespace Modbus.Net.Opc
{ {
@@ -76,6 +78,13 @@ namespace Modbus.Net.Opc
/// <param name="serverUrl">Url address of Opc UA server</param> /// <param name="serverUrl">Url address of Opc UA server</param>
public MyDaClient(Uri serverUrl) : base(serverUrl) public MyDaClient(Uri serverUrl) : base(serverUrl)
{ {
var url = new URL(serverUrl.OriginalString)
{
Scheme = serverUrl.Scheme,
HostName = serverUrl.Host
};
typeof(DaClient).GetField("_url", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, url);
} }
/// <summary> /// <summary>
@@ -115,7 +124,7 @@ namespace Modbus.Net.Opc
/// <summary> /// <summary>
/// Tag of a node /// Tag of a node
/// </summary> /// </summary>
public string[] Tag { get; set; } public string Tag { get; set; }
/// <summary> /// <summary>
/// Tag splitter of a node /// Tag splitter of a node

View File

@@ -23,12 +23,17 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile> <PackageReadmeFile>README.md</PackageReadmeFile>
<SymbolPackageFormat>snupkg</SymbolPackageFormat> <SymbolPackageFormat>snupkg</SymbolPackageFormat>
<Platforms>AnyCPU;x86</Platforms>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>bin\Debug\Modbus.Net.Opc.xml</DocumentationFile> <DocumentationFile>bin\Debug\Modbus.Net.Opc.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<DocumentationFile>bin\Debug\Modbus.Net.Opc.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="H.Opc" Version="0.9.3" /> <PackageReference Include="H.Opc" Version="0.9.3" />
</ItemGroup> </ItemGroup>

View File

@@ -1,9 +1,6 @@
using Hylasoft.Opc.Common; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Modbus.Net.Opc namespace Modbus.Net.Opc
@@ -25,20 +22,13 @@ namespace Modbus.Net.Opc
/// </summary> /// </summary>
protected IClientExtend Client; protected IClientExtend Client;
/// <summary>
/// 是否开启正则匹配
/// </summary>
protected bool RegexOn { get; set; }
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="host">服务端url</param> /// <param name="host">服务端url</param>
/// <param name="isRegexOn">是否开启正则匹配</param> protected OpcConnector(string host)
protected OpcConnector(string host, bool isRegexOn)
{ {
ConnectionToken = host; ConnectionToken = host;
RegexOn = isRegexOn;
} }
/// <summary> /// <summary>
@@ -102,14 +92,11 @@ namespace Modbus.Net.Opc
{ {
if (message.IsRead) if (message.IsRead)
{ {
var split = message.Split;
var tag = message.Tag; var tag = message.Tag;
var rootDirectory = await Client.ExploreFolderAsync(""); if (tag != null)
var answerTag = await SearchTag(tag, split, 0, rootDirectory);
if (answerTag != null)
{ {
var result = await Client.ReadAsync<object>(answerTag); var result = await Client.ReadAsync<object>(tag);
logger.LogDebug($"Opc Machine {ConnectionToken} Read Opc tag {answerTag} for value {result.Value}"); logger.LogInformation($"Opc Machine {ConnectionToken} Read Opc tag {tag} for value {result.Value}");
return new OpcParamOut return new OpcParamOut
{ {
Success = true, Success = true,
@@ -125,17 +112,14 @@ namespace Modbus.Net.Opc
else else
{ {
var tag = message.Tag; var tag = message.Tag;
var split = message.Split;
var value = message.SetValue; var value = message.SetValue;
;
var rootDirectory = await Client.ExploreFolderAsync(""); if (tag != null)
var answerTag = await SearchTag(tag, split, 0, rootDirectory);
if (answerTag != null)
{ {
try try
{ {
await Client.WriteAsync(answerTag, value); await Client.WriteAsync(tag, value);
logger.LogDebug($"Opc Machine {ConnectionToken} Write Opc tag {answerTag} for value {value}"); logger.LogInformation($"Opc Machine {ConnectionToken} Write Opc tag {tag} for value {value}");
} }
catch (Exception e) catch (Exception e)
{ {
@@ -167,30 +151,6 @@ namespace Modbus.Net.Opc
} }
} }
/// <summary>
/// 搜索标签
/// </summary>
/// <param name="tags">标签</param>
/// <param name="split">分隔符</param>
/// <param name="deep">递归深度(第几级标签)</param>
/// <param name="nodes">当前搜索的节点</param>
/// <returns>搜索到的标签</returns>
private async Task<string> SearchTag(string[] tags, char split, int deep, IEnumerable<Node> nodes)
{
foreach (var node in nodes)
{
var currentTag = node.Tag.Substring(node.Tag.LastIndexOf(split) + 1);
if (RegexOn && Regex.IsMatch(currentTag, tags[deep]) || !RegexOn && currentTag == tags[deep])
{
if (deep == tags.Length - 1) return node.Tag;
var subDirectories = await Client.ExploreFolderAsync(node.Tag);
var answerTag = await SearchTag(tags, split, deep + 1, subDirectories);
if (answerTag != null) return answerTag;
}
}
return null;
}
private bool Connect() private bool Connect()
{ {
try try

View File

@@ -17,8 +17,7 @@ namespace Modbus.Net.Opc
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="host">Opc DA 服务地址</param> /// <param name="host">Opc DA 服务地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param> protected OpcDaConnector(string host) : base(host)
protected OpcDaConnector(string host, bool isRegexOn) : base(host, isRegexOn)
{ {
Client = new MyDaClient(new Uri(ConnectionToken)); Client = new MyDaClient(new Uri(ConnectionToken));
} }
@@ -27,13 +26,12 @@ namespace Modbus.Net.Opc
/// 根据服务地址生成DA单例 /// 根据服务地址生成DA单例
/// </summary> /// </summary>
/// <param name="host">Opc DA 服务地址</param> /// <param name="host">Opc DA 服务地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param>
/// <returns>Opc DA 连接器实例</returns> /// <returns>Opc DA 连接器实例</returns>
public static OpcDaConnector Instance(string host, bool isRegexOn) public static OpcDaConnector Instance(string host)
{ {
if (!_instances.ContainsKey(host)) if (!_instances.ContainsKey(host))
{ {
var connector = new OpcDaConnector(host, isRegexOn); var connector = new OpcDaConnector(host);
_instances.Add(host, connector); _instances.Add(host, connector);
} }
return _instances[host]; return _instances[host];

View File

@@ -9,17 +9,13 @@ namespace Modbus.Net.Opc
{ {
private readonly string _host; private readonly string _host;
private readonly bool _isRegexOn;
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="host">Opc DA服务地址</param> /// <param name="host">Opc DA服务地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param> public OpcDaProtocol(string host)
public OpcDaProtocol(string host, bool isRegexOn)
{ {
_host = host; _host = host;
_isRegexOn = isRegexOn;
} }
@@ -29,7 +25,7 @@ namespace Modbus.Net.Opc
/// <returns>是否连接成功</returns> /// <returns>是否连接成功</returns>
public override async Task<bool> ConnectAsync() public override async Task<bool> ConnectAsync()
{ {
ProtocolLinker = new OpcDaProtocolLinker(_host, _isRegexOn); ProtocolLinker = new OpcDaProtocolLinker(_host);
if (!await ProtocolLinker.ConnectAsync()) if (!await ProtocolLinker.ConnectAsync())
return false; return false;
return true; return true;

View File

@@ -8,8 +8,7 @@
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="isRegexOn">是否开启正则匹配</param> public OpcDaProtocolLinker() : this(ConfigurationReader.GetValueDirect("OpcDa", "Host"))
public OpcDaProtocolLinker(bool isRegexOn) : this(ConfigurationReader.GetValueDirect("OpcDa", "Host"), isRegexOn)
{ {
} }
@@ -17,10 +16,9 @@
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="host">Opc DA服务地址</param> /// <param name="host">Opc DA服务地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param> public OpcDaProtocolLinker(string host)
public OpcDaProtocolLinker(string host, bool isRegexOn)
{ {
BaseConnector = OpcDaConnector.Instance(host, isRegexOn); BaseConnector = OpcDaConnector.Instance(host);
} }
} }
} }

View File

@@ -16,14 +16,11 @@ namespace Modbus.Net.Opc
/// <param name="connectionType">连接类型</param> /// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param> /// <param name="connectionString">连接地址</param>
/// <param name="getAddresses">需要读写的地址</param> /// <param name="getAddresses">需要读写的地址</param>
/// <param name="isRegexOn">开启正则匹配</param> public OpcMachine(TKey id, OpcType connectionType, string connectionString, IEnumerable<AddressUnit<TUnitKey>> getAddresses)
public OpcMachine(TKey id, OpcType connectionType, string connectionString, IEnumerable<AddressUnit<TUnitKey>> getAddresses, bool isRegexOn = false)
: base(id, getAddresses, true) : base(id, getAddresses, true)
{ {
BaseUtility = new OpcUtility(connectionType, connectionString, isRegexOn); BaseUtility = new OpcUtility(connectionType, connectionString);
AddressFormater = new AddressFormaterOpc<TKey, TUnitKey>((machine, unit) => { return new string[] { unit.Area }; }, this); AddressFormater = new AddressFormaterOpc<TKey, TUnitKey>((machine, unit) => { return new string[] { unit.Area }; }, this);
((OpcUtility)BaseUtility).GetSeperator +=
() => ((AddressFormaterOpc<TKey, TUnitKey>)AddressFormater).Seperator;
AddressCombiner = new AddressCombinerSingle<TUnitKey>(); AddressCombiner = new AddressCombinerSingle<TUnitKey>();
AddressCombinerSet = new AddressCombinerSingle<TUnitKey>(); AddressCombinerSet = new AddressCombinerSingle<TUnitKey>();
} }

View File

@@ -26,22 +26,15 @@
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="tag">标签</param> /// <param name="tag">标签</param>
/// <param name="split">分隔符</param> public ReadRequestOpcInputStruct(string tag)
public ReadRequestOpcInputStruct(string[] tag, char split)
{ {
Tag = tag; Tag = tag;
Split = split;
} }
/// <summary> /// <summary>
/// 标签 /// 标签
/// </summary> /// </summary>
public string[] Tag { get; } public string Tag { get; }
/// <summary>
/// 分隔符
/// </summary>
public char Split { get; }
} }
/// <summary> /// <summary>
@@ -82,7 +75,6 @@
{ {
IsRead = true, IsRead = true,
Tag = r_message.Tag, Tag = r_message.Tag,
Split = r_message.Split
}; };
} }
@@ -111,24 +103,17 @@
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="tag">标签</param> /// <param name="tag">标签</param>
/// <param name="split">分隔符</param>
/// <param name="setValue">写入的数据</param> /// <param name="setValue">写入的数据</param>
public WriteRequestOpcInputStruct(string[] tag, char split, object setValue) public WriteRequestOpcInputStruct(string tag, object setValue)
{ {
Tag = tag; Tag = tag;
Split = split;
SetValue = setValue; SetValue = setValue;
} }
/// <summary> /// <summary>
/// 标签 /// 标签
/// </summary> /// </summary>
public string[] Tag { get; } public string Tag { get; }
/// <summary>
/// 分隔符
/// </summary>
public char Split { get; }
/// <summary> /// <summary>
/// 写入的数据 /// 写入的数据
@@ -174,7 +159,6 @@
{ {
IsRead = false, IsRead = false,
Tag = r_message.Tag, Tag = r_message.Tag,
Split = r_message.Split,
SetValue = r_message.SetValue SetValue = r_message.SetValue
}; };
} }

View File

@@ -17,8 +17,7 @@ namespace Modbus.Net.Opc
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="host">Opc UA 服务地址</param> /// <param name="host">Opc UA 服务地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param> protected OpcUaConnector(string host) : base(host)
protected OpcUaConnector(string host, bool isRegexOn) : base(host, isRegexOn)
{ {
Client = new MyUaClient(new Uri(ConnectionToken)); Client = new MyUaClient(new Uri(ConnectionToken));
} }
@@ -27,13 +26,12 @@ namespace Modbus.Net.Opc
/// 根据地址获取UA连接器单例 /// 根据地址获取UA连接器单例
/// </summary> /// </summary>
/// <param name="host">Opc UA服务地址</param> /// <param name="host">Opc UA服务地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param>
/// <returns>Opc UA实例</returns> /// <returns>Opc UA实例</returns>
public static OpcUaConnector Instance(string host, bool isRegexOn) public static OpcUaConnector Instance(string host)
{ {
if (!_instances.ContainsKey(host)) if (!_instances.ContainsKey(host))
{ {
var connector = new OpcUaConnector(host, isRegexOn); var connector = new OpcUaConnector(host);
_instances.Add(host, connector); _instances.Add(host, connector);
} }
return _instances[host]; return _instances[host];

View File

@@ -9,17 +9,13 @@ namespace Modbus.Net.Opc
{ {
private readonly string _host; private readonly string _host;
private readonly bool _isRegexOn;
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="host">Opc UA服务地址</param> /// <param name="host">Opc UA服务地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param> public OpcUaProtocol(string host)
public OpcUaProtocol(string host, bool isRegexOn)
{ {
_host = host; _host = host;
_isRegexOn = isRegexOn;
} }
/// <summary> /// <summary>
@@ -28,7 +24,7 @@ namespace Modbus.Net.Opc
/// <returns>是否连接成功</returns> /// <returns>是否连接成功</returns>
public override async Task<bool> ConnectAsync() public override async Task<bool> ConnectAsync()
{ {
ProtocolLinker = new OpcUaProtocolLinker(_host, _isRegexOn); ProtocolLinker = new OpcUaProtocolLinker(_host);
if (!await ProtocolLinker.ConnectAsync()) return false; if (!await ProtocolLinker.ConnectAsync()) return false;
return true; return true;
} }

View File

@@ -8,8 +8,7 @@
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="isRegexOn">是否开启正则匹配</param> public OpcUaProtocolLinker() : this(ConfigurationReader.GetValueDirect("OpcUa", "Host"))
public OpcUaProtocolLinker(bool isRegexOn) : this(ConfigurationReader.GetValueDirect("OpcUa", "Host"), isRegexOn)
{ {
} }
@@ -17,10 +16,9 @@
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="host">Opc UA服务地址</param> /// <param name="host">Opc UA服务地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param> public OpcUaProtocolLinker(string host)
public OpcUaProtocolLinker(string host, bool isRegexOn)
{ {
BaseConnector = OpcUaConnector.Instance(host, isRegexOn); BaseConnector = OpcUaConnector.Instance(host);
} }
} }
} }

View File

@@ -30,8 +30,6 @@ namespace Modbus.Net.Opc
private OpcType _opcType; private OpcType _opcType;
private bool IsRegexOn { get; set; }
/// <summary> /// <summary>
/// 协议类型 /// 协议类型
/// </summary> /// </summary>
@@ -46,35 +44,27 @@ namespace Modbus.Net.Opc
//Da协议 //Da协议
case OpcType.Da: case OpcType.Da:
{ {
Wrapper = new OpcDaProtocol(ConnectionString, IsRegexOn); Wrapper = new OpcDaProtocol(ConnectionString);
break; break;
} }
//Ua协议 //Ua协议
case OpcType.Ua: case OpcType.Ua:
{ {
Wrapper = new OpcUaProtocol(ConnectionString, IsRegexOn); Wrapper = new OpcUaProtocol(ConnectionString);
break; break;
} }
} }
} }
} }
/// <summary>
/// 获取分隔符
/// </summary>
/// <returns>分隔符</returns>
public delegate char GetSeperatorDelegate();
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="connectionType">连接类型</param> /// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param> /// <param name="connectionString">连接地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param> public OpcUtility(int connectionType, string connectionString) : base(0, 0)
public OpcUtility(int connectionType, string connectionString, bool isRegexOn = false) : base(0, 0)
{ {
ConnectionString = connectionString; ConnectionString = connectionString;
IsRegexOn = isRegexOn;
OpcType = (OpcType)connectionType; OpcType = (OpcType)connectionType;
AddressTranslator = new AddressTranslatorOpc(); AddressTranslator = new AddressTranslatorOpc();
} }
@@ -84,11 +74,9 @@ namespace Modbus.Net.Opc
/// </summary> /// </summary>
/// <param name="connectionType">连接类型</param> /// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param> /// <param name="connectionString">连接地址</param>
/// <param name="isRegexOn">是否开启正则匹配</param> public OpcUtility(OpcType connectionType, string connectionString) : base(0, 0)
public OpcUtility(OpcType connectionType, string connectionString, bool isRegexOn = false) : base(0, 0)
{ {
ConnectionString = connectionString; ConnectionString = connectionString;
IsRegexOn = isRegexOn;
OpcType = connectionType; OpcType = connectionType;
AddressTranslator = new AddressTranslatorOpc(); AddressTranslator = new AddressTranslatorOpc();
} }
@@ -98,11 +86,6 @@ namespace Modbus.Net.Opc
/// </summary> /// </summary>
public override Endian Endian => Endian.BigEndianLsb; public override Endian Endian => Endian.BigEndianLsb;
/// <summary>
/// 获取分隔符
/// </summary>
public event GetSeperatorDelegate GetSeperator;
/// <summary> /// <summary>
/// 设置连接方式(Opc忽略该函数) /// 设置连接方式(Opc忽略该函数)
/// </summary> /// </summary>
@@ -122,8 +105,7 @@ namespace Modbus.Net.Opc
{ {
try try
{ {
var split = GetSeperator?.Invoke() ?? '/'; var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress);
var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress.Split('\r'), split);
var readRequestOpcOutputStruct = var readRequestOpcOutputStruct =
await await
Wrapper.SendReceiveAsync<ReadRequestOpcOutputStruct>(Wrapper[typeof(ReadRequestOpcProtocol)], Wrapper.SendReceiveAsync<ReadRequestOpcOutputStruct>(Wrapper[typeof(ReadRequestOpcProtocol)],
@@ -159,9 +141,8 @@ namespace Modbus.Net.Opc
{ {
try try
{ {
var split = GetSeperator?.Invoke() ?? '/';
var writeRequestOpcInputStruct = var writeRequestOpcInputStruct =
new WriteRequestOpcInputStruct(startAddress.Split('\r'), split, setContents[0]); new WriteRequestOpcInputStruct(startAddress, setContents[0]);
var writeRequestOpcOutputStruct = var writeRequestOpcOutputStruct =
await await
Wrapper.SendReceiveAsync<WriteRequestOpcOutputStruct>(Wrapper[typeof(WriteRequestOpcProtocol)], Wrapper.SendReceiveAsync<WriteRequestOpcOutputStruct>(Wrapper[typeof(WriteRequestOpcProtocol)],

View File

@@ -1,5 +1,4 @@
using Quartz.Util; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@@ -9,7 +9,7 @@ namespace MachineJob
{ {
return (level, func, exception, parameters) => return (level, func, exception, parameters) =>
{ {
if (level >= Quartz.Logging.LogLevel.Info && func != null) if (func != null)
{ {
Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters); Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters);
} }