修复S7服务轮询问题
This commit is contained in:
@@ -11,6 +11,7 @@ using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using DMS.Core.Events;
|
||||
|
||||
namespace DMS.Application.Services;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using DMS.Application.DTOs.Events;
|
||||
using DMS.Application.Events;
|
||||
using DMS.Application.Interfaces;
|
||||
using DMS.Core.Events;
|
||||
|
||||
namespace DMS.Application.Services;
|
||||
|
||||
@@ -60,11 +62,26 @@ public class EventService : IEventService
|
||||
#endregion
|
||||
|
||||
#region 变量事件
|
||||
/// <summary>
|
||||
/// 变量值改变事件
|
||||
/// </summary>
|
||||
public event EventHandler<VariableChangedEventArgs> OnVariableChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 触发变量值改变事件
|
||||
/// </summary>
|
||||
/// <param name="sender">事件发送者</param>
|
||||
/// <param name="e">变量值改变事件参数</param>
|
||||
public void RaiseVariableChanged(object sender, VariableChangedEventArgs e)
|
||||
{
|
||||
OnVariableChanged?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 变量值改变事件
|
||||
/// </summary>
|
||||
public event EventHandler<VariableValueChangedEventArgs> VariableValueChanged;
|
||||
public event EventHandler<VariableValueChangedEventArgs> OnVariableValueChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 触发变量值改变事件
|
||||
@@ -73,7 +90,7 @@ public class EventService : IEventService
|
||||
/// <param name="e">变量值改变事件参数</param>
|
||||
public void RaiseVariableValueChanged(object sender, VariableValueChangedEventArgs e)
|
||||
{
|
||||
VariableValueChanged?.Invoke(sender, e);
|
||||
OnVariableValueChanged?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using DMS.Application.DTOs;
|
||||
using DMS.Application.DTOs.Events;
|
||||
using DMS.Core.Events;
|
||||
using DMS.Core.Models;
|
||||
|
||||
namespace DMS.Application.Services;
|
||||
@@ -56,16 +57,4 @@ public interface IVariableManagementService
|
||||
/// 在内存中删除变量
|
||||
/// </summary>
|
||||
void RemoveVariableFromMemory(int variableId, ConcurrentDictionary<int, VariableTableDto> variableTables);
|
||||
|
||||
void VariableValueChanged(VariableValueChangedEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 当变量数据发生变化时触发
|
||||
/// </summary>
|
||||
event EventHandler<VariableChangedEventArgs> OnVariableChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 当变量数据发生变化时触发
|
||||
/// </summary>
|
||||
event EventHandler<VariableValueChangedEventArgs> OnVariableValueChanged;
|
||||
}
|
||||
@@ -50,14 +50,13 @@ public class DataProcessingService : BackgroundService, IDataProcessingService
|
||||
/// 将一个变量数据项异步推入处理队列。
|
||||
/// </summary>
|
||||
/// <param name="data">要入队的变量数据。</param>
|
||||
public async ValueTask EnqueueAsync(VariableDto data)
|
||||
public async ValueTask EnqueueAsync(VariableContext context)
|
||||
{
|
||||
if (data == null)
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var context = new VariableContext(data);
|
||||
// 将数据项写入 Channel,供后台服务处理。
|
||||
await _queue.Writer.WriteAsync(context);
|
||||
}
|
||||
|
||||
34
DMS.Application/Services/Processors/TriggerProcessor.cs
Normal file
34
DMS.Application/Services/Processors/TriggerProcessor.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using DMS.Application.Interfaces;
|
||||
using DMS.Application.Models;
|
||||
using DMS.Application.Services.Triggers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace DMS.Application.Services.Processors;
|
||||
|
||||
public class TriggerProcessor : IVariableProcessor
|
||||
{
|
||||
private readonly ITriggerEvaluationService _triggerEvaluationService;
|
||||
private readonly ILogger<TriggerProcessor> _logger;
|
||||
|
||||
public TriggerProcessor(ITriggerEvaluationService triggerEvaluationService, ILogger<TriggerProcessor> logger)
|
||||
{
|
||||
_triggerEvaluationService = triggerEvaluationService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task ProcessAsync(VariableContext context)
|
||||
{
|
||||
// try
|
||||
// {
|
||||
// // 调用触发器评估服务来评估与变量关联的所有激活状态的触发器
|
||||
// await _triggerEvaluationService.EvaluateTriggersAsync(context.Data.Id, context.Data.DataValue);
|
||||
//
|
||||
// _logger.LogDebug("触发器评估完成,变量 ID: {VariableId}", context.Data.Id);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// _logger.LogError(ex, "评估变量 {VariableId} 的触发器时发生错误", context.Data.Id);
|
||||
// // 不抛出异常,避免影响其他处理器
|
||||
// }
|
||||
}
|
||||
}
|
||||
29
DMS.Application/Services/Processors/UpdateViewProcessor.cs
Normal file
29
DMS.Application/Services/Processors/UpdateViewProcessor.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using DMS.Application.Interfaces;
|
||||
using DMS.Application.Models;
|
||||
using DMS.Core.Events;
|
||||
|
||||
namespace DMS.Application.Services.Processors;
|
||||
|
||||
public class UpdateViewProcessor: IVariableProcessor
|
||||
{
|
||||
private readonly IEventService _eventService;
|
||||
|
||||
public UpdateViewProcessor(IEventService eventService)
|
||||
{
|
||||
_eventService = eventService;
|
||||
}
|
||||
|
||||
public async Task ProcessAsync(VariableContext context)
|
||||
{
|
||||
// 触发变量值变更事件
|
||||
var eventArgs = new VariableValueChangedEventArgs(
|
||||
context.Data.Id,
|
||||
context.Data.Name,
|
||||
context.Data.DataValue,
|
||||
context.NewValue.ToString()??"",
|
||||
DateTime.Now);
|
||||
|
||||
_eventService.RaiseVariableValueChanged(this,eventArgs);
|
||||
|
||||
}
|
||||
}
|
||||
136
DMS.Application/Services/Processors/ValueConvertProcessor.cs
Normal file
136
DMS.Application/Services/Processors/ValueConvertProcessor.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System.Globalization;
|
||||
using DMS.Application.DTOs;
|
||||
using DMS.Application.Interfaces;
|
||||
using DMS.Application.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace DMS.Application.Services.Processors;
|
||||
|
||||
public class ValueConvertProcessor : IVariableProcessor
|
||||
{
|
||||
private readonly ILogger<ValueConvertProcessor> _logger;
|
||||
|
||||
public ValueConvertProcessor(ILogger<ValueConvertProcessor> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
public async Task ProcessAsync(VariableContext context)
|
||||
{
|
||||
var oldValue = context.Data.DataValue;
|
||||
ConvertS7ValueToStringAndNumeric(context.Data, context.NewValue);
|
||||
context.Data.UpdatedAt = DateTime.Now;
|
||||
// 如何值没有变化则中断处理
|
||||
if (context.Data.DataValue!=oldValue)
|
||||
{
|
||||
context.IsHandled = true;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 将从 S7 读取的对象值转换为字符串表示和数值表示
|
||||
/// </summary>
|
||||
/// <param name="variable">关联的变量 DTO</param>
|
||||
/// <param name="value">从 S7 读取的原始对象值</param>
|
||||
/// <returns>(字符串表示, 数值表示)</returns>
|
||||
private void ConvertS7ValueToStringAndNumeric(VariableDto variable, object value)
|
||||
{
|
||||
if (value == null)
|
||||
return ;
|
||||
|
||||
// 首先根据 value 的实际运行时类型进行匹配和转换
|
||||
string directConversion = null;
|
||||
double numericValue = 0.0;
|
||||
bool numericParsed = false;
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case double d:
|
||||
directConversion = d.ToString("G17", CultureInfo.InvariantCulture);
|
||||
numericValue = d;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case float f:
|
||||
directConversion = f.ToString("G9", CultureInfo.InvariantCulture);
|
||||
numericValue = f;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case int i:
|
||||
directConversion = i.ToString(CultureInfo.InvariantCulture);
|
||||
numericValue = i;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case uint ui:
|
||||
directConversion = ui.ToString(CultureInfo.InvariantCulture);
|
||||
numericValue = ui;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case short s:
|
||||
directConversion = s.ToString(CultureInfo.InvariantCulture);
|
||||
numericValue = s;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case ushort us:
|
||||
directConversion = us.ToString(CultureInfo.InvariantCulture);
|
||||
numericValue = us;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case byte b:
|
||||
directConversion = b.ToString(CultureInfo.InvariantCulture);
|
||||
numericValue = b;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case sbyte sb:
|
||||
directConversion = sb.ToString(CultureInfo.InvariantCulture);
|
||||
numericValue = sb;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case long l:
|
||||
directConversion = l.ToString(CultureInfo.InvariantCulture);
|
||||
numericValue = l;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case ulong ul:
|
||||
directConversion = ul.ToString(CultureInfo.InvariantCulture);
|
||||
numericValue = ul;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case bool boolValue:
|
||||
directConversion = boolValue.ToString().ToLowerInvariant();
|
||||
numericValue = boolValue ? 1.0 : 0.0;
|
||||
numericParsed = true;
|
||||
break;
|
||||
case string str:
|
||||
directConversion = str;
|
||||
// 尝试从字符串解析数值
|
||||
if (double.TryParse(str, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsedFromStr))
|
||||
{
|
||||
numericValue = parsedFromStr;
|
||||
numericParsed = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// 对于未预期的类型,记录日志
|
||||
_logger.LogWarning($"变量 {variable.Name} 读取到未预期的数据类型: {value.GetType().Name}, 值: {value}");
|
||||
directConversion = value.ToString() ?? string.Empty;
|
||||
// 尝试从 ToString() 结果解析数值
|
||||
if (double.TryParse(directConversion, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsedFromObj))
|
||||
{
|
||||
numericValue = parsedFromObj;
|
||||
numericParsed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 如果直接转换成功,直接返回
|
||||
|
||||
// 如果直接转换未能解析数值,并且变量有明确的 DataType,可以尝试更精细的解析
|
||||
// (这部分逻辑在上面的 switch 中已经处理了大部分情况,这里作为后备)
|
||||
// 在这个实现中,我们主要依赖于 value 的实际类型进行转换,因为这通常更可靠。
|
||||
// 如果需要,可以根据 variable.DataType 添加额外的解析逻辑。
|
||||
|
||||
// 返回最终结果
|
||||
variable.DataValue = directConversion ?? value.ToString() ?? string.Empty;
|
||||
variable.NumericValue = numericValue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,14 +1,8 @@
|
||||
using AutoMapper;
|
||||
using System.Collections.Concurrent;
|
||||
using DMS.Application.DTOs;
|
||||
using DMS.Application.DTOs.Events;
|
||||
using DMS.Core.Models;
|
||||
using DMS.Application.Interfaces;
|
||||
using DMS.Core.Interfaces;
|
||||
using DMS.Core.Enums;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using DMS.Core.Events;
|
||||
|
||||
namespace DMS.Application.Services;
|
||||
|
||||
@@ -18,24 +12,18 @@ namespace DMS.Application.Services;
|
||||
public class VariableManagementService : IVariableManagementService
|
||||
{
|
||||
private readonly IVariableAppService _variableAppService;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly IAppDataStorageService _appDataStorageService;
|
||||
private readonly IDataProcessingService _dataProcessingService;
|
||||
|
||||
/// <summary>
|
||||
/// 当变量数据发生变化时触发
|
||||
/// </summary>
|
||||
public event EventHandler<VariableChangedEventArgs> OnVariableChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 当变量数据发生变化时触发
|
||||
/// </summary>
|
||||
public event EventHandler<VariableValueChangedEventArgs> OnVariableValueChanged;
|
||||
|
||||
public VariableManagementService(IVariableAppService variableAppService,
|
||||
IEventService eventService,
|
||||
IAppDataStorageService appDataStorageService,
|
||||
IDataProcessingService dataProcessingService)
|
||||
{
|
||||
_variableAppService = variableAppService;
|
||||
_eventService = eventService;
|
||||
_appDataStorageService = appDataStorageService;
|
||||
_dataProcessingService = dataProcessingService;
|
||||
}
|
||||
@@ -111,7 +99,7 @@ public class VariableManagementService : IVariableManagementService
|
||||
|
||||
if (_appDataStorageService.Variables.TryAdd(variableDto.Id, variableDto))
|
||||
{
|
||||
OnVariableChanged?.Invoke(
|
||||
_eventService.RaiseVariableChanged(
|
||||
this, new VariableChangedEventArgs(DataChangeType.Added, variableDto, variableTableDto));
|
||||
}
|
||||
}
|
||||
@@ -129,7 +117,7 @@ public class VariableManagementService : IVariableManagementService
|
||||
}
|
||||
|
||||
_appDataStorageService.Variables.AddOrUpdate(variableDto.Id, variableDto, (key, oldValue) => variableDto);
|
||||
OnVariableChanged?.Invoke(
|
||||
_eventService.RaiseVariableChanged(
|
||||
this, new VariableChangedEventArgs(DataChangeType.Updated, variableDto, variableTableDto));
|
||||
}
|
||||
|
||||
@@ -147,14 +135,8 @@ public class VariableManagementService : IVariableManagementService
|
||||
variableTable.Variables.Remove(variableDto);
|
||||
}
|
||||
|
||||
OnVariableChanged?.Invoke(
|
||||
_eventService.RaiseVariableChanged(
|
||||
this, new VariableChangedEventArgs(DataChangeType.Deleted, variableDto, variableTableDto));
|
||||
}
|
||||
}
|
||||
|
||||
public void VariableValueChanged(VariableValueChangedEventArgs eventArgs)
|
||||
{
|
||||
// 触发事件,通知DataEventService等监听者
|
||||
OnVariableValueChanged?.Invoke(this, eventArgs);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user