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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Plugins/Drivers/CNC.Fanuc.H/DeviceFanuc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class DeviceFanuc : IDriver

public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -894,4 +895,4 @@ private enum LanguageType
土耳其语 = 17
}
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/CNC.Fanuc/DeviceFanuc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class DeviceFanuc : IDriver

public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -1074,4 +1075,4 @@ public async Task<RpcResponse> WriteAsync(string requestId, string method, Drive

#endregion 读写方法
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/CNC.MTConnect/DeviceMTClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class DeviceMTClient : IDriver
private EntityClient? _mClient;
public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -117,4 +118,4 @@ public async Task<RpcResponse> WriteAsync(string requestId, string method, Drive

#endregion 读写方法
}
}
}
28 changes: 26 additions & 2 deletions Plugins/Drivers/Mock.TcpClient/DeviceTcpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class DeviceTcpClient : IDriver

public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -92,7 +93,30 @@ private void Client_DataReceived(object? sender, Message e)
{
//如果收到的数据校验正确,则放在内存中
if (e.Data.Length == 8 && e.Data[0] == 0x08)
_latestRcvData = e.Data;
_latestRcvData = e.Data

var dataArgs = new DataReportEventArgs
{
DeviceId = DeviceId,
VariableName = "接收到数据",
Address = "",
Value = e.Data,
Timestamp = DateTime.Now,
StatusType = VaribaleStatusTypeEnum.Good,
Message = ""
};
// 在后台线程中异步处理,避免阻塞调用方
_ = Task.Run(async () =>
{
try
{
await OnDataReceived.Invoke(this, dataArgs);
}
catch (Exception ex)
{
_logger.LogError(ex, $"触发式数据上报失败: {dataArgs.VariableName}");
}
});
}

/// <summary>
Expand Down Expand Up @@ -232,4 +256,4 @@ public enum ConnectionType
Long,
Short
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/OPC.DaClient/DeviceDaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ internal class DeviceDaClient : IDriver

public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -217,4 +218,4 @@ public async Task<RpcResponse> WriteAsync(string requestId, string method, Drive

#endregion 读写方法
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/OPC.UaClient/DeviceUaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class DeviceUaClient : IDriver
private OpcUaClientHelper? _opcUaClient;
public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -160,4 +161,4 @@ public async Task<RpcResponse> WriteAsync(string requestId, string method, Drive
return rpcResponse;
}
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/Other.Toledo/DeviceToledo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class DeviceToledo : IDriver

public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -386,4 +387,4 @@ public enum ConnectionType
Long,
Short
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/PLC.AllenBradley/DeviceAllenBradley.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class DeviceAllenBradley : IDriver

public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -188,4 +189,4 @@ public async Task<RpcResponse> WriteAsync(string requestId, string method, Drive

#endregion 读写方法
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/PLC.MelsecMc/DeviceMelsecMc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class DeviceMelsecMc : IDriver

public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -391,4 +392,4 @@ public async Task<RpcResponse> WriteAsync(string requestId, string method, Drive

#endregion 读写方法
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/PLC.ModBusMaster/DeviceModBusMaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class DeviceModBusMaster : IDriver

public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -1081,4 +1082,4 @@ private DriverReturnValueModel AnalyzeAddress(DriverAddressIoArgModel ioArg, out

#endregion 私有方法
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/PLC.OmronFins/DeviceOmronFins.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class DeviceOmronFins : IDriver
private OmronFinsClient? _plc;
public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -219,4 +220,4 @@ public async Task<RpcResponse> WriteAsync(string requestId, string method, Drive

#endregion 读写方法
}
}
}
3 changes: 2 additions & 1 deletion Plugins/Drivers/PLC.SiemensS7/DeviceSiemensS7.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class DeviceSiemensS7 : IDriver

public ILogger _logger { get; set; }
private readonly string _device;
public event Func<object, DataReportEventArgs, Task>? OnDataReceived;

#region 配置参数

Expand Down Expand Up @@ -419,4 +420,4 @@ private string GetString(DataTypeEnum dataType, byte[] strBytes)

#endregion 私有方法
}
}
}
132 changes: 131 additions & 1 deletion Plugins/Plugin/DeviceThread.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public DeviceThread(Device device, IDriver driver, string projectId, MessageServ
_mqttServer = mqttServer;
MethodDelegates = new Dictionary<string, Func<DriverAddressIoArgModel, DriverReturnValueModel>>();

// 订阅驱动数据上报事件
Driver.OnDataReceived += OnDriverDataReceived;

// 将带有 MethodAttribute 的方法转换为委托,存入字典,提升调用效率
foreach (var methodInfo in Driver.GetType().GetMethods().Where(x => x.GetCustomAttribute(typeof(MethodAttribute)) != null))
{
Expand Down Expand Up @@ -78,6 +81,131 @@ public DeviceThread(Device device, IDriver driver, string projectId, MessageServ
}
}

/// <summary>
/// 处理驱动主动上报的数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async Task OnDriverDataReceived(object sender, DataReportEventArgs e)
{
try
{
// 根据变量名或地址查找对应的DeviceVariable
var deviceVariable = Device.DeviceVariables?.FirstOrDefault(v =>
v.Name == e.VariableName ||
v.DeviceAddress == e.Address ||
(!string.IsNullOrEmpty(e.Address) && v.DeviceAddress == e.Address));

if (deviceVariable == null)
{
_logger.LogWarning($"未找到对应的设备变量: {e.VariableName}, 地址: {e.Address}");
return;
}

// 创建返回值模型
var ret = new DriverReturnValueModel
{
Value = e.Value,
StatusType = e.StatusType,
Timestamp = e.Timestamp,
Message = e.Message,
VarId = deviceVariable.ID
};

// 将原始值加入队列(保存最近3次)
deviceVariable.EnqueueVariable(ret.Value);

// 表达式计算(如果配置了)
if (ret.StatusType == VaribaleStatusTypeEnum.Good && !string.IsNullOrWhiteSpace(deviceVariable.Expressions?.Trim()))
{
var expressionText = DealMysqlStr(deviceVariable.Expressions)
.Replace("raw",
deviceVariable.Values[0] is bool
? $"Convert.ToBoolean(\"{deviceVariable.Values[0]}\")"
: deviceVariable.Values[0]?.ToString())
.Replace("$v",
deviceVariable.Values[0] is bool
? $"Convert.ToBoolean(\"{deviceVariable.Values[0]}\")"
: deviceVariable.Values[0]?.ToString())
.Replace("$pv",
deviceVariable.Values[1] is bool
? $"Convert.ToBoolean(\"{deviceVariable.Values[1]}\")"
: deviceVariable.Values[1]?.ToString())
.Replace("$ppv",
deviceVariable.Values[2] is bool
? $"Convert.ToBoolean(\"{deviceVariable.Values[2]}\")"
: deviceVariable.Values[2]?.ToString());

try
{
ret.CookedValue = _interpreter!.Eval(expressionText);
}
catch (Exception ex)
{
ret.Message = $"表达式错误:{expressionText}";
ret.StatusType = VaribaleStatusTypeEnum.ExpressionError;
_logger.LogError(ex, $"表达式计算失败: {expressionText}");
}
}
else
{
ret.CookedValue = ret.Value;
}

// 将计算后的值加入队列
deviceVariable.EnqueueCookedVariable(ret.CookedValue);

// 更新设备变量的状态
deviceVariable.Value = ret.Value;
deviceVariable.CookedValue = ret.CookedValue;
deviceVariable.StatusType = ret.StatusType;
deviceVariable.Timestamp = ret.Timestamp;
deviceVariable.Message = ret.Message;

// 发布到MQTT(用于前端展示)
if (JsonConvert.SerializeObject(deviceVariable.Values[1]) != JsonConvert.SerializeObject(deviceVariable.Values[0]) ||
JsonConvert.SerializeObject(deviceVariable.CookedValues[1]) != JsonConvert.SerializeObject(deviceVariable.CookedValues[0]))
{
var msgInternal = new InjectedMqttApplicationMessage(
new MqttApplicationMessage()
{
Topic = $"internal/v1/gateway/telemetry/{Device.DeviceName}/{deviceVariable.Name}",
PayloadSegment = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ret))
});
_mqttServer.InjectApplicationMessage(msgInternal);
}

// 如果变量配置为上传,则发布遥测数据
if (deviceVariable.IsUpload && ret.StatusType == VaribaleStatusTypeEnum.Good)
{
var deviceName = string.IsNullOrWhiteSpace(deviceVariable.Alias) ? Device.DeviceName : deviceVariable.Alias;
var sendModel = new Dictionary<string, List<PayLoad>>
{
{
deviceName,
new List<PayLoad>
{
new PayLoad
{
Values = new Dictionary<string, object> { { deviceVariable.Name, ret.CookedValue } },
TS = (long)(DateTime.UtcNow - _tsStartDt).TotalMilliseconds,
DeviceStatus = DeviceStatusTypeEnum.Good
}
}
}
};

await _messageService.PublishTelemetryAsync(deviceName, Device, sendModel);
}

_logger.LogDebug($"处理驱动上报数据: {deviceVariable.Name} = {ret.CookedValue}");
}
catch (Exception ex)
{
_logger.LogError(ex, $"处理驱动上报数据失败: {e.VariableName}");
}
}

private async Task CreateThreadAsync(CancellationToken token)
{
try
Expand Down Expand Up @@ -390,6 +518,8 @@ public void StopThread()
}
}
_messageService.OnExcRpc -= MyMqttClient_OnExcRpc;
// 取消订阅驱动数据上报事件
Driver.OnDataReceived -= OnDriverDataReceived;
_tokenSource.Cancel();
Driver.Close();
}
Expand All @@ -413,4 +543,4 @@ private string DealMysqlStr(string expression)
.Replace("&quot;", "\"");
}
}
}
}
Loading