Files
KinginfoGateway/src/Gateway/ThingsGateway.Gateway.Application/Model/VariableRunTime.cs
2025-07-31 00:40:03 +08:00

236 lines
7.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
using Newtonsoft.Json.Linq;
using ThingsGateway.Gateway.Application.Extensions;
using ThingsGateway.NewLife.DictionaryExtensions;
using ThingsGateway.NewLife.Json.Extension;
namespace ThingsGateway.Gateway.Application;
/// <summary>
/// 变量运行态
/// </summary>
public partial class VariableRuntime : Variable, IVariable, IDisposable
{
private DateTime? prepareAlarmEventTime;
private DateTime? prepareFinishEventTime;
private EventTypeEnum? eventType;
private AlarmTypeEnum? alarmType { get; set; }
private int index;
private int sortCode;
private DateTime changeTime = DateTime.UnixEpoch.ToLocalTime();
private DateTime alarmTime;
private DateTime eventTime;
private DateTime collectTime = DateTime.UnixEpoch.ToLocalTime();
private bool _isOnline;
private bool _isOnlineChanged;
private bool _valueInited;
private string alarmLimit;
private string alarmText;
private string alarmCode;
private string _lastErrorMessage;
private string recoveryCode;
private object _value;
private object lastSetValue;
private object rawValue;
private DeviceRuntime? deviceRuntime;
private IVariableSource? variableSource;
private VariableMethod? variableMethod;
private IThingsGatewayBitConverter? thingsGatewayBitConverter;
/// <summary>
/// 设置变量值与时间/质量戳
/// </summary>
/// <param name="value"></param>
/// <param name="dateTime"></param>
/// <param name="isOnline"></param>
public OperResult SetValue(object value, DateTime dateTime, bool isOnline = true)
{
IsOnline = isOnline;
RawValue = value;
if (IsOnline == false)
{
Set(value, dateTime);
return new();
}
if (!string.IsNullOrEmpty(ReadExpressions))
{
try
{
var data = ReadExpressions.GetExpressionsResult(RawValue, DeviceRuntime?.Driver?.LogMessage);
Set(data, dateTime);
}
catch (Exception ex)
{
IsOnline = false;
Set(null, dateTime);
var oldMessage = _lastErrorMessage;
if (ex.StackTrace != null)
{
string stachTrace = string.Join(Environment.NewLine, ex.StackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Take(3));
_lastErrorMessage = $"{Name} Conversion expression failed{ex.Message}{Environment.NewLine}{stachTrace}";
}
else
{
_lastErrorMessage = $"{Name} Conversion expression failed{ex.Message}{Environment.NewLine}";
}
if (oldMessage != _lastErrorMessage)
{
DeviceRuntime?.Driver?.LogMessage?.LogWarning(_lastErrorMessage);
}
return new($"{Name} Conversion expression failed", ex);
}
}
else
{
Set(value, dateTime);
}
return new();
}
/// <summary>
/// 设置变量值与时间/质量戳
/// </summary>
/// <param name="dateTime"></param>
public void SetNoChangedValue(DateTime dateTime)
{
DateTime time = dateTime != default ? dateTime : DateTime.Now;
if (!IsOnline)
{
SetValue(RawValue, time, true);
}
else
{
CollectTime = time;
GlobalData.VariableCollectChange(this);
}
}
private void Set(object data, DateTime dateTime)
{
DateTime time = dateTime != default ? dateTime : DateTime.Now;
CollectTime = time;
bool changed = false;
if (data == null)
{
if (IsOnline)
{
changed = (_value != null);
}
}
else
{
if (data is JToken jToken)
{
data = jToken.GetObjectFromJToken();
}
//判断变化插件传入的Value可能是基础类型也有可能是class比较器无法识别是否变化这里json处理序列化比较
//检查IComparable
if (!data.Equals(_value))
{
if (data is IComparable)
{
changed = true;
}
else
{
if (_value != null)
changed = data.ToSystemTextJsonString(false) != _value.ToSystemTextJsonString(false);
else
changed = true;
}
}
else
{
changed = false;
}
}
if (changed || _isOnlineChanged == true)
{
ChangeTime = time;
LastSetValue = _value;
ValueInited = true;
if (_isOnline == true)
{
_value = data;
}
GlobalData.VariableValueChange(this);
}
GlobalData.VariableCollectChange(this);
}
public void Init(DeviceRuntime deviceRuntime)
{
GlobalData.AlarmEnableIdVariables.Remove(Id);
if (GlobalData.RealAlarmIdVariables.TryRemove(Id, out var oldAlarm))
{
oldAlarm.EventType = EventTypeEnum.Finish;
oldAlarm.EventTime = DateTime.Now;
GlobalData.AlarmChange(this.AdaptAlarmVariable());
}
DeviceRuntime?.VariableRuntimes?.Remove(Name);
DeviceRuntime = deviceRuntime;
DeviceRuntime?.VariableRuntimes?.TryAdd(Name, this);
GlobalData.IdVariables.Remove(Id);
GlobalData.IdVariables.TryAdd(Id, this);
if (AlarmEnable)
{
GlobalData.AlarmEnableIdVariables.TryAdd(Id, this);
}
}
public void Dispose()
{
DeviceRuntime?.VariableRuntimes?.Remove(Name);
GlobalData.IdVariables.Remove(Id);
GlobalData.AlarmEnableIdVariables.Remove(Id);
if (GlobalData.RealAlarmIdVariables.TryRemove(Id, out var oldAlarm))
{
oldAlarm.EventType = EventTypeEnum.Finish;
oldAlarm.EventTime = DateTime.Now;
GlobalData.AlarmChange(this.AdaptAlarmVariable());
}
GC.SuppressFinalize(this);
}
/// <inheritdoc/>
public async ValueTask<IOperResult> RpcAsync(string value, string executive = "brower", CancellationToken cancellationToken = default)
{
var data = await GlobalData.RpcService.InvokeDeviceMethodAsync(executive, new Dictionary<string, Dictionary<string, string>>()
{
{ DeviceName, new Dictionary<string, string>() { { Name,value} } }
}, cancellationToken).ConfigureAwait(false);
return data.FirstOrDefault().Value.FirstOrDefault().Value;
}
public void SetErrorMessage(string lastErrorMessage)
{
_lastErrorMessage = lastErrorMessage;
}
}