mirror of
https://github.com/ThingsGateway/ThingsGateway.git
synced 2026-10-25 18:00:12 +08:00
更新批量写入方法,注意rpc入口参数变化,mqtt等RPC接口参数变化
This commit is contained in:
@@ -89,13 +89,8 @@ public class RpcControler : IDynamicApiController
|
||||
[Description("写入变量")]
|
||||
public async Task<Dictionary<string, OperResult>> WriteDeviceMethods(Dictionary<string, string> objs)
|
||||
{
|
||||
Dictionary<string, OperResult> operResultDict = new();
|
||||
foreach (KeyValuePair<string, string> obj in objs)
|
||||
{
|
||||
var result = await RpcCore.InvokeDeviceMethodAsync($"WebApi-{UserManager.UserAccount}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}", obj);
|
||||
operResultDict.Add(obj.Key, result);
|
||||
}
|
||||
return operResultDict;
|
||||
var result = await RpcCore.InvokeDeviceMethodAsync($"WebApi-{UserManager.UserAccount}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}", objs);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,10 @@ public abstract class CollectBase : DriverBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract bool IsSupportRequest { get; }
|
||||
/// <summary>
|
||||
/// 一般底层驱动,也有可能为null
|
||||
/// </summary>
|
||||
protected abstract IReadWriteDevice PLC { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据转换器
|
||||
@@ -177,10 +181,22 @@ public abstract class CollectBase : DriverBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入变量值
|
||||
/// 批量写入变量值,需返回变量名称/结果
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token);
|
||||
public virtual async Task<Dictionary<string, OperResult>> WriteValuesAsync(Dictionary<DeviceVariableRunTime, JToken> writeInfoLists, CancellationToken token)
|
||||
{
|
||||
if (PLC == null)
|
||||
throw new("未初始化成功");
|
||||
Dictionary<string, OperResult> operResults = new();
|
||||
foreach (var writeInfo in writeInfoLists)
|
||||
{
|
||||
var result = await PLC.WriteAsync(writeInfo.Key.VariableAddress, writeInfo.Key.DataType, writeInfo.Value.ToString(), token);
|
||||
await Task.Delay(10, token); //防止密集写入
|
||||
operResults.Add(writeInfo.Key.Name, result);
|
||||
}
|
||||
return operResults;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化
|
||||
|
||||
@@ -48,92 +48,172 @@ public class RpcSingletonService : ISingleton
|
||||
/// 反向RPC入口方法
|
||||
/// </summary>
|
||||
/// <param name="sourceDes">触发该方法的源说明</param>
|
||||
/// <param name="item">指定键为变量名称,值为附带方法参数或写入值</param>
|
||||
/// <param name="items">指定键为变量名称,值为附带方法参数或写入值</param>
|
||||
/// <param name="isBlazor">如果是true,不检查<see cref="MemoryVariable.RpcWriteEnable"/>字段</param>
|
||||
/// <param name="token"><see cref="CancellationToken"/> 取消源</param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult> InvokeDeviceMethodAsync(string sourceDes, KeyValuePair<string, string> item, bool isBlazor = false, CancellationToken token = default)
|
||||
public async Task<Dictionary<string, OperResult>> InvokeDeviceMethodAsync(string sourceDes, Dictionary<string, string> items, bool isBlazor = false, CancellationToken token = default)
|
||||
{
|
||||
//避免并发过高,这里延时10ms
|
||||
await Task.Delay(10, token);
|
||||
OperResult data = new();
|
||||
var tag = _globalDeviceData.AllVariables.FirstOrDefault(it => it.Name == item.Key);
|
||||
if (tag == null) return new OperResult("不存在变量:" + item.Key);
|
||||
if (tag.ProtectTypeEnum == ProtectTypeEnum.ReadOnly) return new OperResult("只读变量");
|
||||
if (!tag.RpcWriteEnable && !isBlazor) return new OperResult("不允许远程写入");
|
||||
|
||||
if (tag.IsMemoryVariable == true)
|
||||
Dictionary<CollectDeviceCore, Dictionary<DeviceVariableRunTime, JToken>> WriteVariables = new();
|
||||
Dictionary<CollectDeviceCore, Dictionary<DeviceVariableRunTime, string>> WriteMethods = new();
|
||||
Dictionary<string, OperResult> results = new();
|
||||
foreach (var item in items)
|
||||
{
|
||||
return tag.SetValue(item.Value);
|
||||
}
|
||||
var dev = _collectDeviceHostService.CollectDeviceCores.FirstOrDefault(it => it.Device.Id == tag.DeviceId);
|
||||
if (dev == null) return new OperResult("系统错误,不存在对应采集设备,请稍候重试");
|
||||
if (dev.Device.DeviceStatus == DeviceStatusEnum.OffLine) return new OperResult("设备已离线");
|
||||
if (dev.Device.DeviceStatus == DeviceStatusEnum.Pause) return new OperResult("设备已暂停");
|
||||
if (string.IsNullOrEmpty(tag.OtherMethod))
|
||||
{
|
||||
//写入变量
|
||||
JToken tagValue;
|
||||
try
|
||||
{
|
||||
tagValue = JToken.Parse(item.Value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
tagValue = JToken.Parse("\"" + item.Value + "\"");
|
||||
}
|
||||
|
||||
data = await dev.InVokeWriteAsync(tag, tagValue, token);
|
||||
_logQueues.Enqueue(
|
||||
new RpcLog()
|
||||
OperResult data = new();
|
||||
var tag = _globalDeviceData.AllVariables.FirstOrDefault(it => it.Name == item.Key);
|
||||
if (tag == null)
|
||||
results.Add(item.Key, new("不存在变量:" + item.Key));
|
||||
if (tag.ProtectTypeEnum == ProtectTypeEnum.ReadOnly)
|
||||
results.Add(item.Key, new("只读变量:" + item.Key));
|
||||
if (!tag.RpcWriteEnable && !isBlazor)
|
||||
results.Add(item.Key, new("不允许远程写入:" + item.Key));
|
||||
|
||||
if (tag.IsMemoryVariable == true)
|
||||
{
|
||||
results.Add(item.Key, tag.SetValue(item.Value));
|
||||
}
|
||||
var dev = _collectDeviceHostService.CollectDeviceCores.FirstOrDefault(it => it.Device.Id == tag.DeviceId);
|
||||
if (dev == null)
|
||||
results.Add(item.Key, new OperResult("系统错误,不存在对应采集设备,请稍候重试"));
|
||||
if (dev.Device.DeviceStatus == DeviceStatusEnum.OffLine)
|
||||
results.Add(item.Key, new OperResult("设备已离线"));
|
||||
if (dev.Device.DeviceStatus == DeviceStatusEnum.Pause)
|
||||
results.Add(item.Key, new OperResult("设备已暂停"));
|
||||
|
||||
if (!results.ContainsKey(item.Key))
|
||||
{
|
||||
if (string.IsNullOrEmpty(tag.OtherMethod))
|
||||
{
|
||||
LogTime = SysDateTimeExtensions.CurrentDateTime,
|
||||
OperateMessage = data.Exception,
|
||||
IsSuccess = data.IsSuccess,
|
||||
OperateMethod = WriteVariable,
|
||||
OperateObject = tag.Name,
|
||||
OperateSource = sourceDes,
|
||||
ParamJson = item.Value,
|
||||
ResultJson = data.Message
|
||||
//写入变量
|
||||
JToken tagValue;
|
||||
try
|
||||
{
|
||||
tagValue = JToken.Parse(item.Value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
tagValue = JToken.Parse("\"" + item.Value + "\"");
|
||||
}
|
||||
if (WriteVariables.ContainsKey(dev))
|
||||
{
|
||||
|
||||
WriteVariables[dev].Add(tag, tagValue);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteVariables.Add(dev, new());
|
||||
WriteVariables[dev].Add(tag, tagValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WriteMethods.ContainsKey(dev))
|
||||
{
|
||||
|
||||
WriteMethods[dev].Add(tag, item.Value);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteVariables.Add(dev, new());
|
||||
WriteVariables[dev].Add(tag, item.Value);
|
||||
}
|
||||
}
|
||||
);
|
||||
if (!data.IsSuccess)
|
||||
{
|
||||
_logger.LogWarning($"写入变量[{tag.Name}]失败:{data.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
foreach (var item in WriteVariables)
|
||||
{
|
||||
//执行变量附带的方法
|
||||
var method = dev.DeviceVariableMethodSources.FirstOrDefault(it => it.DeviceVariable == tag);
|
||||
try
|
||||
{
|
||||
data = await dev.InvokeMethodAsync(method, false, item.Value, token);
|
||||
var result = await item.Key.InVokeWriteAsync(item.Value, token);
|
||||
foreach (var resultItem in result)
|
||||
{
|
||||
string operObj;
|
||||
string parJson;
|
||||
if (resultItem.Key.IsNullOrEmpty())
|
||||
{
|
||||
operObj = items.Select(x => x.Key).ToJsonString();
|
||||
parJson = items.Select(x => x.Value).ToJsonString();
|
||||
}
|
||||
else
|
||||
{
|
||||
operObj = resultItem.Key;
|
||||
parJson = items[resultItem.Key];
|
||||
|
||||
}
|
||||
_logQueues.Enqueue(
|
||||
new RpcLog()
|
||||
{
|
||||
LogTime = SysDateTimeExtensions.CurrentDateTime,
|
||||
OperateMessage = resultItem.Value.Exception,
|
||||
IsSuccess = resultItem.Value.IsSuccess,
|
||||
OperateMethod = WriteVariable,
|
||||
OperateObject = operObj,
|
||||
OperateSource = sourceDes,
|
||||
ParamJson = parJson,
|
||||
ResultJson = resultItem.Value.Message
|
||||
}
|
||||
);
|
||||
if (!resultItem.Value.IsSuccess)
|
||||
{
|
||||
_logger.LogWarning($"写入变量[{resultItem.Key}]失败:{resultItem.Value.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
results.AddRange(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
data = new OperResult<string>(ex);
|
||||
}
|
||||
_logQueues.Enqueue(
|
||||
new RpcLog()
|
||||
{
|
||||
LogTime = SysDateTimeExtensions.CurrentDateTime,
|
||||
OperateMessage = data.Exception,
|
||||
IsSuccess = data.IsSuccess,
|
||||
OperateMethod = tag.OtherMethod,
|
||||
OperateObject = tag.Name,
|
||||
OperateSource = sourceDes,
|
||||
ParamJson = item.Value?.ToString(),
|
||||
ResultJson = data.Message
|
||||
}
|
||||
);
|
||||
if (!data.IsSuccess)
|
||||
{
|
||||
_logger.LogWarning($"执行变量[{tag.Name}]方法[{tag.OtherMethod}]失败:{data.Message}");
|
||||
_logger.LogWarning($"写入变量异常:{ex.Message + Environment.NewLine + ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
return data;
|
||||
foreach (var item in WriteMethods)
|
||||
{
|
||||
foreach (var writeMethod in item.Value)
|
||||
{
|
||||
|
||||
//执行变量附带的方法
|
||||
var method = item.Key.DeviceVariableMethodSources.FirstOrDefault(it => it.DeviceVariable == writeMethod.Key);
|
||||
OperResult<string> result;
|
||||
try
|
||||
{
|
||||
result = await item.Key.InvokeMethodAsync(method, false, writeMethod.Value, token);
|
||||
results.Add(writeMethod.Key.Name, result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = new OperResult<string>(ex);
|
||||
results.Add(writeMethod.Key.Name, result);
|
||||
}
|
||||
_logQueues.Enqueue(
|
||||
new RpcLog()
|
||||
{
|
||||
LogTime = SysDateTimeExtensions.CurrentDateTime,
|
||||
OperateMessage = result.Exception,
|
||||
IsSuccess = result.IsSuccess,
|
||||
OperateMethod = writeMethod.Key.OtherMethod,
|
||||
OperateObject = writeMethod.Key.Name,
|
||||
OperateSource = sourceDes,
|
||||
ParamJson = writeMethod.Value?.ToString(),
|
||||
ResultJson = result.Message
|
||||
}
|
||||
);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
_logger.LogWarning($"执行变量[{writeMethod.Key.Name}]方法[{writeMethod.Key.OtherMethod}]失败:{result.Message}");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task RpcLogInsertAsync()
|
||||
{
|
||||
|
||||
@@ -1855,6 +1855,11 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Application.CollectBase.PLC">
|
||||
<summary>
|
||||
一般底层驱动,也有可能为null
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Application.CollectBase.ThingsGatewayBitConverter">
|
||||
<summary>
|
||||
数据转换器
|
||||
@@ -1906,9 +1911,9 @@
|
||||
采集驱动读取
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.CollectBase.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<member name="M:ThingsGateway.Application.CollectBase.WriteValuesAsync(System.Collections.Generic.Dictionary{ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
写入变量值
|
||||
批量写入变量值,需返回变量名称/结果
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
@@ -2242,12 +2247,12 @@
|
||||
<member name="M:ThingsGateway.Application.RpcSingletonService.#ctor(Microsoft.Extensions.Logging.ILogger{ThingsGateway.Application.RpcSingletonService})">
|
||||
<inheritdoc cref="T:ThingsGateway.Application.RpcSingletonService"/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.RpcSingletonService.InvokeDeviceMethodAsync(System.String,System.Collections.Generic.KeyValuePair{System.String,System.String},System.Boolean,System.Threading.CancellationToken)">
|
||||
<member name="M:ThingsGateway.Application.RpcSingletonService.InvokeDeviceMethodAsync(System.String,System.Collections.Generic.Dictionary{System.String,System.String},System.Boolean,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
反向RPC入口方法
|
||||
</summary>
|
||||
<param name="sourceDes">触发该方法的源说明</param>
|
||||
<param name="item">指定键为变量名称,值为附带方法参数或写入值</param>
|
||||
<param name="items">指定键为变量名称,值为附带方法参数或写入值</param>
|
||||
<param name="isBlazor">如果是true,不检查<see cref="P:ThingsGateway.Application.MemoryVariable.RpcWriteEnable"/>字段</param>
|
||||
<param name="token"><see cref="T:System.Threading.CancellationToken"/> 取消源</param>
|
||||
<returns></returns>
|
||||
@@ -3505,7 +3510,7 @@
|
||||
执行特殊方法
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.CollectDeviceCore.InVokeWriteAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<member name="M:ThingsGateway.Application.CollectDeviceCore.InVokeWriteAsync(System.Collections.Generic.Dictionary{ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
执行变量写入
|
||||
</summary>
|
||||
|
||||
@@ -712,46 +712,46 @@ public class CollectDeviceCore
|
||||
/// 执行变量写入
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal async Task<OperResult> InVokeWriteAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
|
||||
internal async Task<Dictionary<string, OperResult>> InVokeWriteAsync(Dictionary<DeviceVariableRunTime, JToken> writeInfoLists, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
await easyLock.WaitAsync();
|
||||
if (IsShareChannel) _driver.InitDataAdapter();
|
||||
Dictionary<string, OperResult> results = new();
|
||||
foreach (var deviceVariable in writeInfoLists.Keys)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(deviceVariable.WriteExpressions))
|
||||
{
|
||||
var jToken = writeInfoLists[deviceVariable];
|
||||
object rawdata;
|
||||
if (jToken is JValue jValue)
|
||||
{
|
||||
rawdata = jValue.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
rawdata = jToken.ToString();
|
||||
}
|
||||
object data;
|
||||
try
|
||||
{
|
||||
data = deviceVariable.WriteExpressions.GetExpressionsResult(rawdata);
|
||||
writeInfoLists[deviceVariable] = JToken.FromObject(data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
results.Add(deviceVariable.Name, new OperResult(deviceVariable.Name + " 转换写入表达式失败:" + ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(deviceVariable.WriteExpressions))
|
||||
{
|
||||
var jToken = value;
|
||||
object rawdata;
|
||||
if (jToken is JValue jValue)
|
||||
{
|
||||
rawdata = jValue.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
rawdata = jToken.ToString();
|
||||
}
|
||||
object data;
|
||||
try
|
||||
{
|
||||
data = deviceVariable.WriteExpressions.GetExpressionsResult(rawdata);
|
||||
var result = await _driver.WriteValueAsync(deviceVariable, JToken.FromObject(data), token);
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(deviceVariable.Name + " 转换写入表达式失败:" + ex.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await _driver.WriteValueAsync(deviceVariable, value, token);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (new OperResult(ex));
|
||||
var result = await _driver.WriteValuesAsync(writeInfoLists.
|
||||
Where(a => !results.Any(b => b.Key == a.Key.Name)).
|
||||
ToDictionary(item => item.Key, item => item.Value),
|
||||
token);
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -759,6 +759,8 @@ public class CollectDeviceCore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 执行轮询特殊方法,并设置变量值
|
||||
/// </summary>
|
||||
|
||||
@@ -149,10 +149,18 @@ public partial class DeviceVariableRunTimePage
|
||||
private EventCallback<string> WriteValueAsync;
|
||||
private async Task OnWriteValueAsync(DeviceVariableRunTime tag, string value)
|
||||
{
|
||||
var data = await RpcCore?.InvokeDeviceMethodAsync($"BLAZOR-{UserResoures.CurrentUser.Account}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}", new KeyValuePair<string, string>(tag.Name, value), true);
|
||||
if (!data.IsSuccess)
|
||||
var data = await RpcCore?.InvokeDeviceMethodAsync($"BLAZOR-{UserResoures.CurrentUser.Account}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}",
|
||||
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
|
||||
{ tag.Name, value}
|
||||
}
|
||||
|
||||
, true);
|
||||
if (data.Count > 0 && !data.FirstOrDefault().Value.IsSuccess)
|
||||
{
|
||||
throw new(data.Message);
|
||||
throw new(data.FirstOrDefault().Value.Message);
|
||||
}
|
||||
}
|
||||
private async Task WriteAsync(DeviceVariableRunTime collectVariableRunTime)
|
||||
|
||||
+6
-4
@@ -66,7 +66,8 @@ public class ModbusAddress : DeviceAddressBase
|
||||
Length = result.Content.Length;
|
||||
AddressStart = result.Content.AddressStart;
|
||||
ReadFunction = result.Content.ReadFunction;
|
||||
Station = result.Content.Station;
|
||||
if (result.Content.Station > 0)
|
||||
Station = result.Content.Station;
|
||||
WriteFunction = result.Content.WriteFunction;
|
||||
}
|
||||
}
|
||||
@@ -81,9 +82,10 @@ public class ModbusAddress : DeviceAddressBase
|
||||
|
||||
try
|
||||
{
|
||||
ModbusAddress modbusAddress = new ModbusAddress();
|
||||
|
||||
modbusAddress.Length = length;
|
||||
ModbusAddress modbusAddress = new()
|
||||
{
|
||||
Length = length
|
||||
};
|
||||
if (address.IndexOf(';') < 0)
|
||||
{
|
||||
Address(address);
|
||||
|
||||
+71
-27
@@ -301,50 +301,94 @@ public class OPCDAClient : DisposableObject
|
||||
return OPCNode?.ToString();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 写入值
|
||||
/// 批量写入值
|
||||
/// </summary>
|
||||
/// <param name="valueName">写入</param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public OperResult WriteItem(string valueName, JToken value)
|
||||
public Dictionary<string, OperResult> WriteItem(Dictionary<string, JToken> writeInfos)
|
||||
{
|
||||
Dictionary<string, OperResult> results = new();
|
||||
if (PrivateConnect())
|
||||
{
|
||||
try
|
||||
{
|
||||
var group = Groups.FirstOrDefault(it => it.OpcItems.Any(a => a.ItemID == valueName));
|
||||
if (group == null)
|
||||
return new OperResult("不存在该变量" + valueName);
|
||||
var item = group.OpcItems.Where(it => it.ItemID == valueName).FirstOrDefault();
|
||||
int[] serverHandle = new int[1] { item.ServerHandle };
|
||||
int[] PErrors = new int[1];
|
||||
var jtoken = value;
|
||||
var rank = jtoken.CalculateActualValueRank();
|
||||
object rawWriteValue;
|
||||
switch (rank)
|
||||
var valueGroup = writeInfos.GroupBy(itemId =>
|
||||
{
|
||||
var group = Groups.FirstOrDefault(it => it.OpcItems.Any(a => a.ItemID == itemId.Key));
|
||||
return group;
|
||||
}).ToList();
|
||||
|
||||
|
||||
|
||||
|
||||
foreach (var item1 in valueGroup)
|
||||
{
|
||||
case -1:
|
||||
rawWriteValue = ((JValue)jtoken).Value;
|
||||
break;
|
||||
default:
|
||||
var jarray = ((JArray)jtoken);
|
||||
rawWriteValue = jarray.Select(j => (object)j).ToArray();
|
||||
break;
|
||||
if (item1.Key == null)
|
||||
{
|
||||
foreach (var item2 in item1)
|
||||
{
|
||||
results.Add(item2.Key, new OperResult("不存在该变量" + item2.Key));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<int> ServerHandles = new();
|
||||
List<object> Values = new();
|
||||
foreach (var item2 in item1)
|
||||
{
|
||||
var opcItem = item1.Key.OpcItems.Where(it => it.ItemID == item2.Key).FirstOrDefault();
|
||||
ServerHandles.Add(opcItem.ServerHandle);
|
||||
var jtoken = item2.Value;
|
||||
var rank = jtoken.CalculateActualValueRank();
|
||||
object rawWriteValue;
|
||||
switch (rank)
|
||||
{
|
||||
case -1:
|
||||
rawWriteValue = ((JValue)jtoken).Value;
|
||||
break;
|
||||
default:
|
||||
var jarray = ((JArray)jtoken);
|
||||
rawWriteValue = jarray.Select(j => (object)j).ToArray();
|
||||
break;
|
||||
}
|
||||
|
||||
Values.Add(rawWriteValue);
|
||||
|
||||
}
|
||||
|
||||
var result = item1.Key.Write(Values.ToArray(), ServerHandles.ToArray(), out var PErrors);
|
||||
var data = item1.ToList();
|
||||
for (int i = 0; i < data.Count; i++)
|
||||
{
|
||||
results.Add(data[i].Key, PErrors[i] == 0 ? OperResult.CreateSuccessResult() : new OperResult("错误代码:" + PErrors[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object[] Value = new object[1] { rawWriteValue };
|
||||
var result = group.Write(Value, serverHandle, out PErrors);
|
||||
return result;
|
||||
return results;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex.Message);
|
||||
var keys = writeInfos.Keys.ToList();
|
||||
foreach (var item in keys)
|
||||
{
|
||||
results.AddOrUpdate(item, new(ex));
|
||||
}
|
||||
return results;
|
||||
|
||||
}
|
||||
}
|
||||
return new OperResult();
|
||||
else
|
||||
{
|
||||
var keys = writeInfos.Keys.ToList();
|
||||
foreach (var item in keys)
|
||||
{
|
||||
results.AddOrUpdate(item, new("未初始化连接"));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
|
||||
+2
-4
@@ -520,12 +520,10 @@
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ToString">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.WriteItem(System.String,Newtonsoft.Json.Linq.JToken)">
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.WriteItem(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken})">
|
||||
<summary>
|
||||
写入值
|
||||
批量写入值
|
||||
</summary>
|
||||
<param name="valueName">写入</param>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Dispose(System.Boolean)">
|
||||
|
||||
+41
-23
@@ -521,29 +521,33 @@ public class OPCUAClient : DisposableObject
|
||||
/// <summary>
|
||||
/// 异步写opc标签
|
||||
/// </summary>
|
||||
public async Task<OperResult> WriteNodeAsync(string tag, JToken value, CancellationToken token = default)
|
||||
public async Task<Dictionary<string, OperResult>> WriteNodeAsync(Dictionary<string, JToken> writeInfoLists, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, OperResult> results = new();
|
||||
try
|
||||
{
|
||||
WriteValue valueToWrite = new()
|
||||
WriteValueCollection valuesToWrite = new();
|
||||
foreach (var item in writeInfoLists)
|
||||
{
|
||||
NodeId = new NodeId(tag),
|
||||
AttributeId = Attributes.Value,
|
||||
};
|
||||
var variableNode = (VariableNode)ReadNode(tag.ToString(), false);
|
||||
await typeSystem.LoadType(variableNode.DataType, true, true);
|
||||
var dataValue = JsonUtils.Decode(
|
||||
m_session.MessageContext,
|
||||
variableNode.DataType,
|
||||
TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable),
|
||||
value.CalculateActualValueRank(),
|
||||
value
|
||||
);
|
||||
valueToWrite.Value = dataValue;
|
||||
WriteValueCollection valuesToWrite = new()
|
||||
{
|
||||
valueToWrite
|
||||
};
|
||||
WriteValue valueToWrite = new()
|
||||
{
|
||||
NodeId = new NodeId(item.Key),
|
||||
AttributeId = Attributes.Value,
|
||||
};
|
||||
var variableNode = (VariableNode)ReadNode(item.Key, false);
|
||||
await typeSystem.LoadType(variableNode.DataType, true, true);
|
||||
var dataValue = JsonUtils.Decode(
|
||||
m_session.MessageContext,
|
||||
variableNode.DataType,
|
||||
TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable),
|
||||
item.Value.CalculateActualValueRank(),
|
||||
item.Value
|
||||
);
|
||||
valueToWrite.Value = dataValue;
|
||||
|
||||
valuesToWrite.Add(valueToWrite);
|
||||
}
|
||||
|
||||
|
||||
var result = await m_session.WriteAsync(
|
||||
requestHeader: null,
|
||||
@@ -551,15 +555,29 @@ public class OPCUAClient : DisposableObject
|
||||
|
||||
ClientBase.ValidateResponse(result.Results, valuesToWrite);
|
||||
ClientBase.ValidateDiagnosticInfos(result.DiagnosticInfos, valuesToWrite);
|
||||
if (!StatusCode.IsGood(result.Results[0]))
|
||||
|
||||
|
||||
var keys = writeInfoLists.Keys.ToList();
|
||||
for (int i = 0; i < keys.Count; i++)
|
||||
{
|
||||
return new OperResult(result.Results[0].ToString());
|
||||
if (!StatusCode.IsGood(result.Results[i]))
|
||||
results.Add(keys[i], new(result.Results[i].ToString()));
|
||||
else
|
||||
{
|
||||
results.Add(keys[i], OperResult.CreateSuccessResult());
|
||||
}
|
||||
}
|
||||
return OperResult.CreateSuccessResult();
|
||||
|
||||
return results;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
var keys = writeInfoLists.Keys.ToList();
|
||||
foreach (var item in keys)
|
||||
{
|
||||
results.Add(item, new(ex));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -375,7 +375,7 @@
|
||||
从服务器读取值
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.WriteNodeAsync(System.String,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.WriteNodeAsync(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
异步写opc标签
|
||||
</summary>
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
using ThingsGateway.Foundation.Serial;
|
||||
@@ -22,6 +20,8 @@ namespace ThingsGateway.Modbus;
|
||||
public class ModbusRtu : CollectBase
|
||||
{
|
||||
private readonly ModbusRtuProperty driverPropertys = new();
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu _plc;
|
||||
/// <inheritdoc/>
|
||||
public override Type DriverDebugUIType => typeof(ModbusRtuDebugDriverPage);
|
||||
@@ -74,12 +74,6 @@ public class ModbusRtu : CollectBase
|
||||
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
|
||||
{
|
||||
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Init(CollectDeviceRunTime device, object client = null)
|
||||
{
|
||||
|
||||
+3
-7
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
@@ -22,6 +20,8 @@ public class ModbusRtuOverTcp : CollectBase
|
||||
{
|
||||
|
||||
private readonly ModbusRtuOverTcpProperty driverPropertys = new();
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp _plc;
|
||||
/// <inheritdoc/>
|
||||
public override Type DriverDebugUIType => typeof(ModbusRtuOverTcpDebugDriverPage);
|
||||
@@ -61,11 +61,7 @@ public class ModbusRtuOverTcp : CollectBase
|
||||
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
|
||||
{
|
||||
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
+3
-7
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
@@ -22,6 +20,8 @@ namespace ThingsGateway.Modbus;
|
||||
public class ModbusRtuOverUdp : CollectBase
|
||||
{
|
||||
private readonly ModbusRtuOverUdpProperty driverPropertys = new();
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp _plc;
|
||||
/// <inheritdoc/>
|
||||
public override Type DriverDebugUIType => typeof(ModbusRtuOverUdpDebugDriverPage);
|
||||
@@ -65,11 +65,7 @@ public class ModbusRtuOverUdp : CollectBase
|
||||
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
|
||||
{
|
||||
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -201,16 +201,25 @@ public class ModbusServer : UpLoadBase
|
||||
if (Enum.TryParse<DataTypeEnum>(type, out DataTypeEnum result))
|
||||
{
|
||||
var resultTask1 = RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusServer)}-{CurDevice.Name}-{client.IP + ":" + client.Port}",
|
||||
new(tag.Value.Name, thingsGatewayBitConverter.GetDynamicDataFormBytes(addressStr ?? string.Empty, result.GetSystemType(), bytes).ToString()));
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
{tag.Value.Name, thingsGatewayBitConverter.GetDynamicDataFormBytes(addressStr ?? string.Empty, result.GetSystemType(), bytes).ToString()},
|
||||
}
|
||||
|
||||
);
|
||||
var result1 = resultTask1.ConfigureAwait(true).GetAwaiter().GetResult();
|
||||
return result1;
|
||||
return result1.FirstOrDefault().Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var resultTask1 = RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusServer)}-{CurDevice.Name}-{client.IP + ":" + client.Port}",
|
||||
new(tag.Value.Name, thingsGatewayBitConverter.GetDynamicDataFormBytes(addressStr ?? string.Empty, tag.Value.DataType, bytes).ToString()));
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
{tag.Value.Name, thingsGatewayBitConverter.GetDynamicDataFormBytes(addressStr ?? string.Empty, result.GetSystemType(), bytes).ToString()},
|
||||
}
|
||||
);
|
||||
var result1 = resultTask1.ConfigureAwait(true).GetAwaiter().GetResult();
|
||||
return result1;
|
||||
return result1.FirstOrDefault().Value;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
@@ -22,6 +20,8 @@ namespace ThingsGateway.Modbus;
|
||||
/// </summary>
|
||||
public class ModbusTcp : CollectBase
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp _plc;
|
||||
|
||||
private readonly ModbusTcpProperty driverPropertys = new();
|
||||
@@ -67,11 +67,7 @@ public class ModbusTcp : CollectBase
|
||||
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
|
||||
{
|
||||
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
@@ -21,6 +19,8 @@ namespace ThingsGateway.Modbus;
|
||||
/// <inheritdoc/>
|
||||
public class ModbusUdp : CollectBase
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp _plc;
|
||||
|
||||
private readonly ModbusUdpProperty driverPropertys = new();
|
||||
@@ -66,11 +66,7 @@ public class ModbusUdp : CollectBase
|
||||
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
|
||||
{
|
||||
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
<member name="T:ThingsGateway.Modbus.ModbusRtuOverTcp">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtuOverTcp.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtuOverTcp.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -34,9 +37,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtuOverTcp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtuOverTcp.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtuOverTcp.Dispose(System.Boolean)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -116,6 +116,9 @@
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtuOverUdp.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtuOverUdp.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -143,9 +146,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtuOverUdp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtuOverUdp.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtuOverUdp.Dispose(System.Boolean)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -168,6 +168,9 @@
|
||||
<member name="T:ThingsGateway.Modbus.ModbusRtu">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtu.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtu.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -200,9 +203,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtu.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtu.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtu.Init(ThingsGateway.Application.CollectDeviceRunTime,System.Object)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -400,6 +400,9 @@
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusTcp.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusTcp.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -427,9 +430,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusTcp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusTcp.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusTcp.Dispose(System.Boolean)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -507,6 +507,9 @@
|
||||
<member name="T:ThingsGateway.Modbus.ModbusUdp">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusUdp.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusUdp.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -534,9 +537,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusUdp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusUdp.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Modbus.ModbusUdp.Dispose(System.Boolean)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
|
||||
@@ -340,9 +340,7 @@ GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
|
||||
&& driverPropertys.DeviceRpcEnable;
|
||||
if (rpcEnable == true)
|
||||
{
|
||||
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + rpcrequestid, item);
|
||||
|
||||
results.Add(item.Key, result);
|
||||
|
||||
}
|
||||
else
|
||||
@@ -356,6 +354,12 @@ GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
|
||||
results.Add(item.Key, new("不存在该变量"));
|
||||
}
|
||||
}
|
||||
|
||||
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + rpcrequestid, nameValue
|
||||
.Where(a => !results.Any(b => b.Key == a.Key))
|
||||
.ToDictionary(a => a.Key, a => a.Value));
|
||||
|
||||
results.AddRange(result);
|
||||
rpcResponse = new()
|
||||
{
|
||||
DeviceId = rpcdevicename,
|
||||
|
||||
@@ -405,40 +405,48 @@ public class MqttClient : UpLoadBase
|
||||
return;
|
||||
if (arg.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic)
|
||||
return;
|
||||
var rpcData = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
|
||||
if (rpcData == null)
|
||||
var rpcDatas = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
|
||||
if (rpcDatas == null)
|
||||
return;
|
||||
|
||||
MqttRpcResult mqttRpcResult = new();
|
||||
MqttRpcResult mqttRpcResult = new() { RpcId = rpcDatas.RpcId, Success = true };
|
||||
try
|
||||
{
|
||||
var nv = rpcData.Adapt<KeyValuePair<string, string>>();
|
||||
var tag = _uploadVariables.FirstOrDefault(a => a.Name == nv.Key);
|
||||
if (tag != null)
|
||||
foreach (var rpcData in rpcDatas.WriteInfos)
|
||||
{
|
||||
var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
|
||||
if (rpcEnable == true)
|
||||
|
||||
var tag = _uploadVariables.FirstOrDefault(a => a.Name == rpcData.Key);
|
||||
if (tag != null)
|
||||
{
|
||||
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + arg.ClientId, nv);
|
||||
|
||||
mqttRpcResult = new() { Message = result.Message, RpcId = rpcData.RpcId, Success = result.IsSuccess };
|
||||
var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
|
||||
if (rpcEnable == true)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult.Success = false;
|
||||
mqttRpcResult.Message.Add(rpcData.Key, new("权限不足,变量不支持写入"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult = new() { Message = "权限不足,变量不支持写入", RpcId = rpcData.RpcId, Success = false };
|
||||
mqttRpcResult.Success = false;
|
||||
mqttRpcResult.Message.Add(rpcData.Key, new("不存在该变量"));
|
||||
}
|
||||
}
|
||||
|
||||
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + arg.ClientId,
|
||||
rpcDatas.WriteInfos.Where(
|
||||
a => !mqttRpcResult.Message.Any(b => b.Key == a.Key)).ToDictionary(a => a.Key, a => a.Value));
|
||||
|
||||
mqttRpcResult.Message.AddRange(result);
|
||||
mqttRpcResult.Success = !mqttRpcResult.Message.Any(a => !a.Value.IsSuccess);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult = new() { Message = "不存在该变量", RpcId = rpcData.RpcId, Success = false };
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage?.LogWarning(ex, ToString());
|
||||
mqttRpcResult = new() { Message = "Failed", RpcId = rpcData.RpcId, Success = false };
|
||||
}
|
||||
try
|
||||
{
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
namespace ThingsGateway.Mqtt;
|
||||
|
||||
/// <summary>
|
||||
@@ -22,13 +26,9 @@ public class MqttRpcNameVaueWithId
|
||||
/// </summary>
|
||||
public string RpcId { get; set; }
|
||||
/// <summary>
|
||||
/// 通常是变量名称
|
||||
/// "WriteInfos":{"test":"1"}
|
||||
/// </summary>
|
||||
public string Key { get; set; }
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
public Dictionary<string, string> WriteInfos { get; set; } = new();
|
||||
}
|
||||
/// <summary>
|
||||
/// MqttRpc输出
|
||||
@@ -42,7 +42,7 @@ public class MqttRpcResult
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
public Dictionary<string, OperResult> Message { get; set; } = new();
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
|
||||
@@ -260,41 +260,46 @@ public class MqttServer : UpLoadBase
|
||||
return;
|
||||
if (arg.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic)
|
||||
return;
|
||||
var rpcData = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
|
||||
if (rpcData == null)
|
||||
var rpcDatas = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
|
||||
if (rpcDatas == null)
|
||||
return;
|
||||
MqttRpcResult mqttRpcResult = new();
|
||||
MqttRpcResult mqttRpcResult = new() { RpcId = rpcDatas.RpcId, Success = true };
|
||||
try
|
||||
{
|
||||
var nv = rpcData.Adapt<KeyValuePair<string, string>>();
|
||||
var tag = _uploadVariables.FirstOrDefault(a => a.Name == nv.Key);
|
||||
if (tag != null)
|
||||
foreach (var rpcData in rpcDatas.WriteInfos)
|
||||
{
|
||||
var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
|
||||
if (rpcEnable == true)
|
||||
|
||||
var tag = _uploadVariables.FirstOrDefault(a => a.Name == rpcData.Key);
|
||||
if (tag != null)
|
||||
{
|
||||
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + IdWithName[arg.ClientId], nv);
|
||||
|
||||
mqttRpcResult = new() { Message = result.Message, RpcId = rpcData.RpcId, Success = result.IsSuccess };
|
||||
var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
|
||||
if (rpcEnable == true)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult.Success = false;
|
||||
mqttRpcResult.Message.Add(rpcData.Key, new("权限不足,变量不支持写入"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult = new() { Message = "权限不足,变量不支持写入", RpcId = rpcData.RpcId, Success = false };
|
||||
mqttRpcResult.Success = false;
|
||||
mqttRpcResult.Message.Add(rpcData.Key, new("不存在该变量"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult = new() { Message = "不存在该变量", RpcId = rpcData.RpcId, Success = false };
|
||||
}
|
||||
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + arg.ClientId,
|
||||
rpcDatas.WriteInfos.Where(
|
||||
a => !mqttRpcResult.Message.Any(b => b.Key == a.Key)).ToDictionary(a => a.Key, a => a.Value));
|
||||
|
||||
mqttRpcResult.Message.AddRange(result);
|
||||
mqttRpcResult.Success = !mqttRpcResult.Message.Any(a => !a.Value.IsSuccess);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage?.LogWarning(ex, ToString());
|
||||
mqttRpcResult = new() { Message = "Failed", RpcId = rpcData.RpcId, Success = false };
|
||||
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -302,7 +307,7 @@ public class MqttServer : UpLoadBase
|
||||
.WithTopic($"{driverPropertys.RpcSubTopic}")
|
||||
.WithPayload(mqttRpcResult.ToJson()).Build();
|
||||
await _mqttServer.InjectApplicationMessage(
|
||||
new InjectedMqttApplicationMessage(variableMessage));
|
||||
new InjectedMqttApplicationMessage(variableMessage));
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -294,14 +294,9 @@
|
||||
标识
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Mqtt.MqttRpcNameVaueWithId.Key">
|
||||
<member name="P:ThingsGateway.Mqtt.MqttRpcNameVaueWithId.WriteInfos">
|
||||
<summary>
|
||||
通常是变量名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Mqtt.MqttRpcNameVaueWithId.Value">
|
||||
<summary>
|
||||
值
|
||||
"WriteInfos":{"test":"1"}
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Mqtt.MqttRpcResult">
|
||||
|
||||
@@ -35,7 +35,7 @@ public class OPCDAClient : CollectBase
|
||||
{
|
||||
internal CollectDeviceRunTime Device;
|
||||
|
||||
internal ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient PLC = null;
|
||||
internal ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient _plc = null;
|
||||
|
||||
private readonly OPCDAClientProperty driverPropertys = new();
|
||||
private ConcurrentList<DeviceVariableRunTime> _deviceVariables = new();
|
||||
@@ -50,17 +50,20 @@ public class OPCDAClient : CollectBase
|
||||
/// <inheritdoc/>
|
||||
public override ThingsGatewayBitConverter ThingsGatewayBitConverter { get; } = new(EndianType.Little);
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => null;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task AfterStopAsync()
|
||||
{
|
||||
PLC?.Disconnect();
|
||||
_plc?.Disconnect();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task BeforStartAsync(CancellationToken token)
|
||||
{
|
||||
PLC.Connect();
|
||||
_plc.Connect();
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -69,14 +72,14 @@ public class OPCDAClient : CollectBase
|
||||
{
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override bool IsConnected() => PLC?.IsConnected == true;
|
||||
public override bool IsConnected() => _plc?.IsConnected == true;
|
||||
/// <inheritdoc/>
|
||||
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
|
||||
{
|
||||
_deviceVariables = new(deviceVariables);
|
||||
if (deviceVariables.Count > 0)
|
||||
{
|
||||
var result = PLC.AddItemsWithSave(deviceVariables.Select(a => a.VariableAddress).ToList());
|
||||
var result = _plc.AddItemsWithSave(deviceVariables.Select(a => a.VariableAddress).ToList());
|
||||
var sourVars = result?.Select(
|
||||
it =>
|
||||
{
|
||||
@@ -98,26 +101,31 @@ public class OPCDAClient : CollectBase
|
||||
public override async Task<OperResult<byte[]>> ReadSourceAsync(DeviceVariableSourceRead deviceVariableSourceRead, CancellationToken token)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
var result = PLC.ReadItemsWithGroup(deviceVariableSourceRead.Address);
|
||||
var result = _plc.ReadItemsWithGroup(deviceVariableSourceRead.Address);
|
||||
return result.Copy<byte[]>();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
|
||||
public override Task<Dictionary<string, OperResult>> WriteValuesAsync(Dictionary<DeviceVariableRunTime, JToken> writeInfoLists, CancellationToken token)
|
||||
{
|
||||
var result = PLC.WriteItem(deviceVariable.VariableAddress, value);
|
||||
return Task.FromResult(result);
|
||||
var result = _plc.WriteItem(writeInfoLists.ToDictionary(a => a.Key.VariableAddress, a => a.Value));
|
||||
return Task.FromResult(result.ToDictionary(a =>
|
||||
{
|
||||
return writeInfoLists.Keys.FirstOrDefault(b => b.VariableAddress == a.Key).Name;
|
||||
}, a => a.Value));
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (PLC != null)
|
||||
PLC.DataChangedHandler -= DataChangedHandler;
|
||||
PLC?.Disconnect();
|
||||
PLC?.SafeDispose();
|
||||
PLC = null;
|
||||
if (_plc != null)
|
||||
_plc.DataChangedHandler -= DataChangedHandler;
|
||||
_plc?.Disconnect();
|
||||
_plc?.SafeDispose();
|
||||
_plc = null;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
@@ -134,12 +142,12 @@ public class OPCDAClient : CollectBase
|
||||
ActiveSubscribe = driverPropertys.ActiveSubscribe,
|
||||
CheckRate = driverPropertys.CheckRate
|
||||
};
|
||||
if (PLC == null)
|
||||
if (_plc == null)
|
||||
{
|
||||
PLC = new(LogMessage);
|
||||
PLC.DataChangedHandler += DataChangedHandler;
|
||||
_plc = new(LogMessage);
|
||||
_plc.DataChangedHandler += DataChangedHandler;
|
||||
}
|
||||
PLC.Init(opcNode);
|
||||
_plc.Init(opcNode);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
+10
-4
@@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Components;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ThingsGateway.Admin.Blazor.Core;
|
||||
@@ -147,14 +148,19 @@ public partial class OPCDAClientDebugDriverPage : IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = _plc.WriteItem(defalutDebugDriverPage.Address, defalutDebugDriverPage.WriteValue);
|
||||
if (data.IsSuccess)
|
||||
var data = _plc.WriteItem(
|
||||
new()
|
||||
{
|
||||
{defalutDebugDriverPage.Address, defalutDebugDriverPage.WriteValue }
|
||||
}
|
||||
);
|
||||
if (data.Values.FirstOrDefault().IsSuccess)
|
||||
{
|
||||
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - 写入" + data.Message));
|
||||
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - 写入" + data.Values.FirstOrDefault().Message));
|
||||
}
|
||||
else
|
||||
{
|
||||
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Message));
|
||||
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Values.FirstOrDefault().Message));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
<member name="P:ThingsGateway.OPCDA.OPCDAClient.ThingsGatewayBitConverter">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.OPCDA.OPCDAClient.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.OPCDA.OPCDAClient.AfterStopAsync">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -58,7 +61,7 @@
|
||||
<member name="M:ThingsGateway.OPCDA.OPCDAClient.ReadSourceAsync(ThingsGateway.Application.DeviceVariableSourceRead,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.OPCDA.OPCDAClient.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<member name="M:ThingsGateway.OPCDA.OPCDAClient.WriteValuesAsync(System.Collections.Generic.Dictionary{ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.OPCDA.OPCDAClient.Dispose(System.Boolean)">
|
||||
|
||||
@@ -36,7 +36,13 @@ namespace ThingsGateway.OPCUA;
|
||||
/// </summary>
|
||||
public class OPCUAClient : CollectBase
|
||||
{
|
||||
internal Foundation.Adapter.OPCUA.OPCUAClient _plc = null;
|
||||
internal CollectDeviceRunTime Device;
|
||||
readonly PeriodicTimer _periodicTimer = new(TimeSpan.FromSeconds(60));
|
||||
private readonly OPCUAClientProperty driverPropertys = new();
|
||||
|
||||
private List<DeviceVariableRunTime> _deviceVariables = new();
|
||||
|
||||
/// <summary>
|
||||
/// OPCUA客户端
|
||||
/// </summary>
|
||||
@@ -45,33 +51,6 @@ public class OPCUAClient : CollectBase
|
||||
_ = RunTimerAsync();
|
||||
}
|
||||
|
||||
private async Task RunTimerAsync()
|
||||
{
|
||||
while (await _periodicTimer.WaitForNextTickAsync())
|
||||
{
|
||||
if (PLC != null && PLC.Session == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
await PLC.ConnectAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.Exception(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal CollectDeviceRunTime Device;
|
||||
|
||||
internal Foundation.Adapter.OPCUA.OPCUAClient PLC = null;
|
||||
|
||||
private List<DeviceVariableRunTime> _deviceVariables = new();
|
||||
|
||||
private readonly OPCUAClientProperty driverPropertys = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Type DriverDebugUIType => typeof(OPCUAClientDebugDriverPage);
|
||||
|
||||
@@ -83,18 +62,23 @@ public class OPCUAClient : CollectBase
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ThingsGatewayBitConverter ThingsGatewayBitConverter { get; } = new(EndianType.Little);
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => null;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task AfterStopAsync()
|
||||
{
|
||||
PLC?.Disconnect();
|
||||
_plc?.Disconnect();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task BeforStartAsync(CancellationToken token)
|
||||
{
|
||||
await PLC?.ConnectAsync();
|
||||
await _plc?.ConnectAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void InitDataAdapter()
|
||||
{
|
||||
@@ -104,14 +88,14 @@ public class OPCUAClient : CollectBase
|
||||
public override bool IsConnected()
|
||||
{
|
||||
|
||||
return PLC.Connected;
|
||||
return _plc.Connected;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
|
||||
{
|
||||
_deviceVariables = deviceVariables;
|
||||
PLC.Variables.AddRange(deviceVariables.Select(a => a.VariableAddress).ToList());
|
||||
_plc.Variables.AddRange(deviceVariables.Select(a => a.VariableAddress).ToList());
|
||||
var dataLists = deviceVariables.ChunkTrivialBetter(driverPropertys.GroupSize);
|
||||
var dataResult = new List<DeviceVariableSourceRead>();
|
||||
foreach (var variable in dataLists)
|
||||
@@ -131,7 +115,7 @@ public class OPCUAClient : CollectBase
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult<byte[]>> ReadSourceAsync(DeviceVariableSourceRead deviceVariableSourceRead, CancellationToken token)
|
||||
{
|
||||
var result = await PLC.ReadJTokenValueAsync(deviceVariableSourceRead.DeviceVariables.Select(a => a.VariableAddress).ToArray(), token);
|
||||
var result = await _plc.ReadJTokenValueAsync(deviceVariableSourceRead.DeviceVariables.Select(a => a.VariableAddress).ToArray(), token);
|
||||
foreach (var data in result)
|
||||
{
|
||||
if (!token.IsCancellationRequested)
|
||||
@@ -184,26 +168,33 @@ public class OPCUAClient : CollectBase
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
|
||||
public override async Task<Dictionary<string, OperResult>> WriteValuesAsync(Dictionary<DeviceVariableRunTime, JToken> writeInfoLists, CancellationToken token)
|
||||
{
|
||||
var result = await PLC.WriteNodeAsync(deviceVariable.VariableAddress, value, token);
|
||||
return result;
|
||||
var result = await _plc.WriteNodeAsync(writeInfoLists.ToDictionary(a => a.Key.VariableAddress, a => a.Value), token);
|
||||
return result.ToDictionary(a =>
|
||||
{
|
||||
return writeInfoLists.Keys.FirstOrDefault(b => b.VariableAddress == a.Key)?.Name;
|
||||
}
|
||||
, a => a.Value);
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_periodicTimer?.Dispose();
|
||||
if (PLC != null)
|
||||
if (_plc != null)
|
||||
{
|
||||
PLC.DataChangedHandler -= DataChangedHandler;
|
||||
PLC.Disconnect();
|
||||
PLC.SafeDispose();
|
||||
PLC = null;
|
||||
_plc.DataChangedHandler -= DataChangedHandler;
|
||||
_plc.Disconnect();
|
||||
_plc.SafeDispose();
|
||||
_plc = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Init(CollectDeviceRunTime device, object client = null)
|
||||
{
|
||||
@@ -220,13 +211,13 @@ public class OPCUAClient : CollectBase
|
||||
UserName = driverPropertys.UserName,
|
||||
Password = driverPropertys.Password
|
||||
};
|
||||
if (PLC == null)
|
||||
if (_plc == null)
|
||||
{
|
||||
PLC = new(LogMessage);
|
||||
PLC.DataChangedHandler += DataChangedHandler;
|
||||
_plc = new(LogMessage);
|
||||
_plc.DataChangedHandler += DataChangedHandler;
|
||||
}
|
||||
|
||||
PLC.OPCNode = opcNode;
|
||||
_plc.OPCNode = opcNode;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -252,7 +243,7 @@ public class OPCUAClient : CollectBase
|
||||
return;
|
||||
}
|
||||
//尝试固定点位的数据类型
|
||||
var type = TypeInfo.GetSystemType(TypeInfo.GetBuiltInType(data.variableNode.DataType, PLC.Session.SystemContext.TypeTable), data.variableNode.ValueRank);
|
||||
var type = TypeInfo.GetSystemType(TypeInfo.GetBuiltInType(data.variableNode.DataType, _plc.Session.SystemContext.TypeTable), data.variableNode.ValueRank);
|
||||
|
||||
var itemReads = _deviceVariables.Where(it => it.VariableAddress == data.variableNode.NodeId).ToList();
|
||||
|
||||
@@ -296,4 +287,23 @@ public class OPCUAClient : CollectBase
|
||||
LogMessage?.LogWarning(ex, ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunTimerAsync()
|
||||
{
|
||||
while (await _periodicTimer.WaitForNextTickAsync())
|
||||
{
|
||||
if (_plc != null && _plc.Session == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _plc.ConnectAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.Exception(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -21,6 +21,7 @@ using Newtonsoft.Json.Linq;
|
||||
using Opc.Ua;
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ThingsGateway.Admin.Blazor.Core;
|
||||
@@ -157,14 +158,19 @@ public partial class OPCUAClientDebugDriverPage
|
||||
{
|
||||
if (_plc.Connected)
|
||||
{
|
||||
var data = await _plc.WriteNodeAsync(defalutDebugDriverPage.Address, JToken.Parse(defalutDebugDriverPage.WriteValue));
|
||||
if (data.IsSuccess)
|
||||
var data = await _plc.WriteNodeAsync(
|
||||
new()
|
||||
{
|
||||
{ defalutDebugDriverPage.Address, JToken.Parse(defalutDebugDriverPage.WriteValue)}
|
||||
}
|
||||
);
|
||||
if (data.Values.FirstOrDefault().IsSuccess)
|
||||
{
|
||||
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + " - 写入成功"));
|
||||
}
|
||||
else
|
||||
{
|
||||
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + " - 写入失败 " + data.Message));
|
||||
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + " - 写入失败 " + data.Values.FirstOrDefault().Message));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+10
-4
@@ -490,16 +490,22 @@ src.IsOnline ? StatusCodes.Good : StatusCodes.Bad);
|
||||
//仅当指定了值时才将值写入
|
||||
if (variable.Value != null)
|
||||
{
|
||||
var nv = new KeyValuePair<string, string>(variable.SymbolicName, value?.ToString());
|
||||
|
||||
var result = _rpcCore.InvokeDeviceMethodAsync("OPCUASERVER-" + context1?.OperationContext?.Session?.Identity?.DisplayName, nv).ConfigureAwait(true).GetAwaiter().GetResult();
|
||||
if (result.IsSuccess)
|
||||
var result = _rpcCore.InvokeDeviceMethodAsync("OPCUASERVER-" + context1?.OperationContext?.Session?.Identity?.DisplayName,
|
||||
new()
|
||||
{
|
||||
{ variable.SymbolicName, value?.ToString() }
|
||||
}
|
||||
|
||||
|
||||
).ConfigureAwait(true).GetAwaiter().GetResult();
|
||||
if (result.Values.FirstOrDefault().IsSuccess)
|
||||
{
|
||||
return StatusCodes.Good;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(StatusCodes.BadWaitingForResponse, result.Message);
|
||||
return new(StatusCodes.BadWaitingForResponse, result.Values.FirstOrDefault().Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
<member name="P:ThingsGateway.OPCUA.OPCUAClient.ThingsGatewayBitConverter">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.OPCUA.OPCUAClient.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.OPCUA.OPCUAClient.AfterStopAsync">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -68,7 +71,7 @@
|
||||
<member name="M:ThingsGateway.OPCUA.OPCUAClient.ReadSourceAsync(ThingsGateway.Application.DeviceVariableSourceRead,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.OPCUA.OPCUAClient.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<member name="M:ThingsGateway.OPCUA.OPCUAClient.WriteValuesAsync(System.Collections.Generic.Dictionary{ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.OPCUA.OPCUAClient.Dispose(System.Boolean)">
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@@ -31,6 +29,8 @@ public abstract class Siemens : CollectBase
|
||||
/// PLC
|
||||
/// </summary>
|
||||
protected SiemensS7PLC _plc;
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
/// <summary>
|
||||
/// SiemensProperty
|
||||
/// </summary>
|
||||
@@ -124,11 +124,7 @@ public abstract class Siemens : CollectBase
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
|
||||
{
|
||||
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -88,6 +88,9 @@
|
||||
PLC
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Siemens.Siemens.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Siemens.Siemens.driverPropertys">
|
||||
<summary>
|
||||
SiemensProperty
|
||||
@@ -138,9 +141,6 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Siemens.Siemens.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Siemens.Siemens.Dispose(System.Boolean)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
|
||||
Reference in New Issue
Block a user