diff --git a/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusRtu/ModbusRtu.cs b/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusRtu/ModbusRtu.cs index d446fe3b7..cc3385f39 100644 --- a/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusRtu/ModbusRtu.cs +++ b/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusRtu/ModbusRtu.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System.ComponentModel; +using System.Threading; using System.Threading.Tasks; using ThingsGateway.Foundation.Serial; @@ -18,10 +19,13 @@ namespace ThingsGateway.Foundation.Adapter.Modbus waitingClient = SerialClient.GetTGWaitingClient(new()); } private IWaitingClient waitingClient; - + [Description("Crc校验")] public bool Crc16CheckEnable { get; set; } + [Description("帧前时间")] public int FrameTime { get; set; } - + [Description("组包缓存时间")] + public double CacheTimeout { get; set; } = 1; + [Description("站号")] public byte Station { get; set; } = 1; public override async Task> ReadAsync(string address, int length, CancellationToken token = default) { @@ -71,7 +75,7 @@ namespace ThingsGateway.Foundation.Adapter.Modbus { DataHandleAdapter = new(); DataHandleAdapter.Crc16CheckEnable = Crc16CheckEnable; - DataHandleAdapter.Crc16CheckEnable = Crc16CheckEnable; + DataHandleAdapter.CacheTimeout = TimeSpan.FromSeconds(CacheTimeout); SerialClient.SetDataHandlingAdapter(DataHandleAdapter); } public override async Task WriteAsync(string address, byte[] value, CancellationToken token = default) diff --git a/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusRtuOverTcp/ModbusRtuOverTcp.cs b/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusRtuOverTcp/ModbusRtuOverTcp.cs index dddbf03ae..ab81e972a 100644 --- a/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusRtuOverTcp/ModbusRtuOverTcp.cs +++ b/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusRtuOverTcp/ModbusRtuOverTcp.cs @@ -20,6 +20,7 @@ namespace ThingsGateway.Foundation.Adapter.Modbus public byte Station { get; set; } = 1; public int FrameTime { get; set; } + public double CacheTimeout { get; set; } = 1; private async Task SendThenReturnAsync(OperResult commandResult, CancellationToken token) { try @@ -68,6 +69,7 @@ namespace ThingsGateway.Foundation.Adapter.Modbus { DataHandleAdapter = new(); DataHandleAdapter.Crc16CheckEnable = Crc16CheckEnable; + DataHandleAdapter.CacheTimeout = TimeSpan.FromSeconds(CacheTimeout); TGTcpClient.SetDataHandlingAdapter(DataHandleAdapter); } public override async Task WriteAsync(string address, byte[] value, CancellationToken token = default) diff --git a/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusTcp/ModbusTcp.cs b/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusTcp/ModbusTcp.cs index 7528f6b91..fe65ae55f 100644 --- a/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusTcp/ModbusTcp.cs +++ b/src/Plugins/ThingsGateway.Foundation.Adapter.Modbus/Modbus/ModbusTcp/ModbusTcp.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System.ComponentModel; +using System.Threading; using System.Threading.Tasks; using TouchSocket.Resources; @@ -16,10 +17,16 @@ namespace ThingsGateway.Foundation.Adapter.Modbus waitingClient = TGTcpClient.GetTGWaitingClient(new()); } private IWaitingClient waitingClient; + + [Description("检测事务标识符")] public bool IsCheckMessageId { get; set; } + [Description("站号")] public byte Station { get; set; } = 1; + [Description("帧前时间")] public int FrameTime { get; set; } + [Description("组包缓存时间")] + public double CacheTimeout { get; set; } = 1; private async Task SendThenReturnAsync(OperResult commandResult, CancellationToken token) { try @@ -69,6 +76,7 @@ namespace ThingsGateway.Foundation.Adapter.Modbus { DataHandleAdapter = new(); DataHandleAdapter.IsCheckMessageId = IsCheckMessageId; + DataHandleAdapter.CacheTimeout = TimeSpan.FromSeconds(CacheTimeout); TGTcpClient.SetDataHandlingAdapter(DataHandleAdapter); } public override async Task WriteAsync(string address, byte[] value, CancellationToken token = default) diff --git a/src/Plugins/ThingsGateway.Foundation.Adapter.Siemens/Siemens/SiemensS7PLC.cs b/src/Plugins/ThingsGateway.Foundation.Adapter.Siemens/Siemens/SiemensS7PLC.cs index a2d12c3b1..1f729ca51 100644 --- a/src/Plugins/ThingsGateway.Foundation.Adapter.Siemens/Siemens/SiemensS7PLC.cs +++ b/src/Plugins/ThingsGateway.Foundation.Adapter.Siemens/Siemens/SiemensS7PLC.cs @@ -302,13 +302,13 @@ namespace ThingsGateway.Foundation.Adapter.Siemens var result1 = SendThenResponse(ISO_CR); if (!result1.IsSuccess) { - Logger?.Error(client.GetIPPort() + "ISO初始化失败"); + Logger?.Error(client.IP + ":" + client.Port + "ISO初始化失败"); return; } var result2 = SendThenResponse(S7_PN); if (!result2.IsSuccess) { - Logger?.Error(client.GetIPPort() + "初始化失败"); + Logger?.Error(client.IP + ":" + client.Port + "初始化失败"); return; } pdu_length = ThingsGatewayBitConverter.ToUInt16(result2.Content.SelectLast(2), 0); diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusRtu.cs b/src/Plugins/ThingsGateway.Modbus/ModbusRtu.cs index 97e454dcd..d46339dcc 100644 --- a/src/Plugins/ThingsGateway.Modbus/ModbusRtu.cs +++ b/src/Plugins/ThingsGateway.Modbus/ModbusRtu.cs @@ -83,6 +83,7 @@ public class ModbusRtu : CollectBase, IDisposable _plc = new((SerialClient)client); _plc.Crc16CheckEnable = driverPropertys.Crc16CheckEnable; _plc.FrameTime = driverPropertys.FrameTime; + _plc.CacheTimeout = driverPropertys.CacheTimeout; _plc.DataFormat = driverPropertys.DataFormat; _plc.Station = driverPropertys.Station; _plc.TimeOut = driverPropertys.TimeOut; @@ -109,7 +110,8 @@ public class ModbusRtuProperty : CollectDriverPropertyBase [DeviceProperty("帧前时间", "某些设备性能较弱,报文间需要间隔较长时间")] public int FrameTime { get; set; } = 0; - + [DeviceProperty("组包缓存超时", "某些设备性能较弱,报文间需要间隔较长时间,可以设置更长的组包缓存,默认1s")] + public double CacheTimeout { get; set; } = 1; [DeviceProperty("共享链路", "")] public override bool IsShareChannel { get; set; } = false; diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusRtuDebugDriverPage.razor b/src/Plugins/ThingsGateway.Modbus/ModbusRtuDebugDriverPage.razor index e9fb7937b..7fc02c395 100644 --- a/src/Plugins/ThingsGateway.Modbus/ModbusRtuDebugDriverPage.razor +++ b/src/Plugins/ThingsGateway.Modbus/ModbusRtuDebugDriverPage.razor @@ -1,32 +1,145 @@ @using BlazorComponent; @using Microsoft.AspNetCore.Components.Web; +@using Microsoft.JSInterop; +@using ThingsGateway.Core; @using ThingsGateway.Foundation.Adapter.Modbus; @using ThingsGateway.Foundation; +@using ThingsGateway.Foundation.Extension; +@using ThingsGateway.Foundation.Serial; @using ThingsGateway.Web.Foundation; @using Masa.Blazor @inherits DriverDebugUIBase - - - @nameof(ModbusRtu)未完成 - - - + +@if (_plc != null) +{ + + + x.Crc16CheckEnable)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.Crc16CheckEnable> + x.FrameTime)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.FrameTime> + x.CacheTimeout)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout> - + x.Station)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.Station> + x.TimeOut)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.TimeOut> + u.des) + ItemValue=@(u =>(DataFormat)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + +} + + + + + + + + + u.des) + ItemValue=@(u =>(DataTypeEnum)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + 读取 + + + + 写入 + + + + + + + + + + + + 输出日志 + + + + + + { + await DownDeviceMessageExport(Messages.Select(a=>a.message)); + } + )> + mdi-export + + + + 导出 + + + + + @{ + var item = Messages; + + + +
+ @itemMessage.message +
+ +
+
+
+ } +
+
-
+ + @code { private SerialClientPage serialClientPage; - protected override void OnInitialized() + private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu _plc { + get + { + return plc as ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu; + } + } + protected override void OnAfterRender(bool firstRender) + { + if (firstRender) + { + serialClientPage.LogAction = LogOut; + //载入配置 + plc = new ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu((SerialClient)serialClientPage.GetSerialClient()); + StateHasChanged(); + } + + base.OnAfterRender(firstRender); } - + public override void Dispose() + { + plc.SafeDispose(); + serialClientPage.SafeDispose(); + base.Dispose(); + } + public override string ToString() + { + return nameof(ModbusRtu); + } } \ No newline at end of file diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverTcp.cs b/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverTcp.cs index dbf9868b4..d10814af6 100644 --- a/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverTcp.cs +++ b/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverTcp.cs @@ -16,7 +16,7 @@ public class ModbusRtuOverTcp : CollectBase, IDisposable } public override CollectDriverPropertyBase DriverPropertys => driverPropertys; public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; } - + public override Type DriverDebugUIType => typeof(ModbusRtuOverTcpDebugDriverPage); public override void AfterStop() { _plc?.Disconnect(); @@ -69,6 +69,7 @@ public class ModbusRtuOverTcp : CollectBase, IDisposable _plc = new((TGTcpClient)client); _plc.Crc16CheckEnable = driverPropertys.Crc16CheckEnable; _plc.FrameTime = driverPropertys.FrameTime; + _plc.CacheTimeout = driverPropertys.CacheTimeout; _plc.DataFormat = driverPropertys.DataFormat; _plc.ConnectTimeOut = driverPropertys.ConnectTimeOut; _plc.Station = driverPropertys.Station; @@ -104,7 +105,8 @@ public class ModbusRtuOverTcpProperty : CollectDriverPropertyBase [DeviceProperty("帧前时间", "某些设备性能较弱,报文间需要间隔较长时间")] public int FrameTime { get; set; } = 0; - + [DeviceProperty("组包缓存超时", "某些设备性能较弱,报文间需要间隔较长时间,可以设置更长的组包缓存,默认1s")] + public double CacheTimeout { get; set; } = 1; [DeviceProperty("共享链路", "")] public override bool IsShareChannel { get; set; } = false; public override ShareChannelEnum ShareChannel => ShareChannelEnum.TcpClient; diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverTcpDebugDriverPage.razor b/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverTcpDebugDriverPage.razor new file mode 100644 index 000000000..a3353fcc0 --- /dev/null +++ b/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverTcpDebugDriverPage.razor @@ -0,0 +1,145 @@ +@using BlazorComponent; +@using Microsoft.AspNetCore.Components.Web; +@using Microsoft.JSInterop; +@using ThingsGateway.Core; +@using ThingsGateway.Foundation.Adapter.Modbus; +@using ThingsGateway.Foundation; +@using ThingsGateway.Foundation.Extension; +@using ThingsGateway.Foundation.Serial; +@using ThingsGateway.Web.Foundation; +@using Masa.Blazor +@inherits DriverDebugUIBase + +@if (_plc != null) +{ + + + x.Crc16CheckEnable)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.Crc16CheckEnable> + x.FrameTime)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.FrameTime> + x.CacheTimeout)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout> + + x.Station)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.Station> + x.TimeOut)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.TimeOut> + u.des) + ItemValue=@(u =>(DataFormat)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + +} + + + + + + + + + u.des) + ItemValue=@(u =>(DataTypeEnum)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + 读取 + + + + 写入 + + + + + + + + + + + + 输出日志 + + + + + + { + await DownDeviceMessageExport(Messages.Select(a=>a.message)); + } + )> + mdi-export + + + + 导出 + + + + + @{ + var item = Messages; + + + +
+ @itemMessage.message +
+ +
+
+
+ } +
+
+ +
+ +
+ + +@code +{ + private TcpClientPage tcpClientPage; + private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp _plc + { + get + { + return plc as ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp; + } + } + + protected override void OnAfterRender(bool firstRender) + { + if (firstRender) + { + tcpClientPage.LogAction = LogOut; + //载入配置 + plc = new ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp((TGTcpClient)tcpClientPage.GetTGTcpClient()); + StateHasChanged(); + } + + base.OnAfterRender(firstRender); + } + + + public override void Dispose() + { + plc.SafeDispose(); + tcpClientPage.SafeDispose(); + base.Dispose(); + } + public override string ToString() + { + return nameof(ModbusRtuOverTcp); + } +} \ No newline at end of file diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverUdp.cs b/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverUdp.cs index ff4182faa..ea311678f 100644 --- a/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverUdp.cs +++ b/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverUdp.cs @@ -14,6 +14,7 @@ public class ModbusRtuOverUdp : CollectBase public ModbusRtuOverUdp(IServiceScopeFactory scopeFactory) : base(scopeFactory) { } + public override Type DriverDebugUIType => typeof(ModbusRtuOverUdpDebugDriverPage); public override CollectDriverPropertyBase DriverPropertys => driverPropertys; diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverUdpDebugDriverPage.razor b/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverUdpDebugDriverPage.razor new file mode 100644 index 000000000..1b9bcad65 --- /dev/null +++ b/src/Plugins/ThingsGateway.Modbus/ModbusRtuOverUdpDebugDriverPage.razor @@ -0,0 +1,144 @@ +@using BlazorComponent; +@using Microsoft.AspNetCore.Components.Web; +@using Microsoft.JSInterop; +@using ThingsGateway.Core; +@using ThingsGateway.Foundation.Adapter.Modbus; +@using ThingsGateway.Foundation; +@using ThingsGateway.Foundation.Extension; +@using ThingsGateway.Foundation.Serial; +@using ThingsGateway.Web.Foundation; +@using Masa.Blazor +@inherits DriverDebugUIBase + +@if (_plc != null) +{ + + + x.Crc16CheckEnable)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.Crc16CheckEnable> + x.FrameTime)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.FrameTime> + + x.Station)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.Station> + x.TimeOut)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.TimeOut> + u.des) + ItemValue=@(u =>(DataFormat)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + +} + + + + + + + + + u.des) + ItemValue=@(u =>(DataTypeEnum)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + 读取 + + + + 写入 + + + + + + + + + + + + 输出日志 + + + + + + { + await DownDeviceMessageExport(Messages.Select(a=>a.message)); + } + )> + mdi-export + + + + 导出 + + + + + @{ + var item = Messages; + + + +
+ @itemMessage.message +
+ +
+
+
+ } +
+
+ +
+ +
+ + +@code +{ + private UdpSessionPage udpClientPage; + private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp _plc + { + get + { + return plc as ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp; + } + } + + protected override void OnAfterRender(bool firstRender) + { + if (firstRender) + { + udpClientPage.LogAction = LogOut; + //载入配置 + plc = new ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp((TGUdpSession)udpClientPage.GetTGUdpSession()); + StateHasChanged(); + } + + base.OnAfterRender(firstRender); + } + + + public override void Dispose() + { + plc.SafeDispose(); + udpClientPage.SafeDispose(); + base.Dispose(); + } + public override string ToString() + { + return nameof(ModbusRtuOverUdp); + } +} \ No newline at end of file diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusServer.cs b/src/Plugins/ThingsGateway.Modbus/ModbusServer.cs index caeaf06fa..b60798984 100644 --- a/src/Plugins/ThingsGateway.Modbus/ModbusServer.cs +++ b/src/Plugins/ThingsGateway.Modbus/ModbusServer.cs @@ -29,6 +29,7 @@ public class ModbusServer : UpLoadBase public override UpDriverPropertyBase DriverPropertys => driverPropertys; public override List UploadVariables => _ModbusTags?.Values.ToList(); public override VariablePropertyBase VariablePropertys => variablePropertys; + public override Type DriverDebugUIType => typeof(ModbusServerDebugDriverPage); public override async Task BeforStartAsync() { @@ -149,12 +150,12 @@ public class ModbusServer : UpLoadBase if (tag.Value == null) return OperResult.CreateSuccessResult(); var enable = tag.Value.VariablePropertys[curDevice.Id].FirstOrDefault(a => a.PropertyName == nameof(variablePropertys.VariableRpcEnable))?.Value.ToBoolean() == true && driverPropertys.DeviceRpcEnable; if (!enable) return new OperResult("不允许写入"); - var result = await rpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusServer)}-{curDevice.Name}-{client.GetIPPort()}", - new() - { - Name = tag.Value.Name, - Value = thingsGatewayBitConverter.GetDynamicData(tag.Value.DataType, bytes).ToString() - }); + var result = await rpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusServer)}-{curDevice.Name}-{client.IP + ":" + client.Port}", + new() + { + Name = tag.Value.Name, + Value = thingsGatewayBitConverter.GetDynamicData(tag.Value.DataType, bytes).ToString() + }); return result; } catch (Exception ex) diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusServerDebugDriverPage.razor b/src/Plugins/ThingsGateway.Modbus/ModbusServerDebugDriverPage.razor new file mode 100644 index 000000000..5c1da4ac6 --- /dev/null +++ b/src/Plugins/ThingsGateway.Modbus/ModbusServerDebugDriverPage.razor @@ -0,0 +1,143 @@ +@using BlazorComponent; +@using Microsoft.AspNetCore.Components.Web; +@using Microsoft.JSInterop; +@using ThingsGateway.Core; +@using ThingsGateway.Foundation.Adapter.Modbus; +@using ThingsGateway.Foundation; +@using ThingsGateway.Foundation.Extension; +@using ThingsGateway.Foundation.Serial; +@using ThingsGateway.Web.Foundation; +@using Masa.Blazor +@inherits DriverDebugUIBase + +@if (_plc != null) +{ + + + x.MulStation)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.MulStation> + + x.Station)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.Station> + x.TimeOut)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.TimeOut> + u.des) + ItemValue=@(u =>(DataFormat)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + +} + + + + + + + + + u.des) + ItemValue=@(u =>(DataTypeEnum)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + 读取 + + + + 写入 + + + + + + + + + + + + 输出日志 + + + + + + { + await DownDeviceMessageExport(Messages.Select(a=>a.message)); + } + )> + mdi-export + + + + 导出 + + + + + @{ + var item = Messages; + + + +
+ @itemMessage.message +
+ +
+
+
+ } +
+
+ +
+ +
+ + +@code +{ + private TcpServerPage tcpServerPage; + private ThingsGateway.Foundation.Adapter.Modbus.ModbusServer _plc + { + get + { + return plc as ThingsGateway.Foundation.Adapter.Modbus.ModbusServer; + } + } + + protected override void OnAfterRender(bool firstRender) + { + if (firstRender) + { + tcpServerPage.LogAction = LogOut; + //载入配置 + plc = new ThingsGateway.Foundation.Adapter.Modbus.ModbusServer((TcpService)tcpServerPage.GetTGTcpServer()); + StateHasChanged(); + } + + base.OnAfterRender(firstRender); + } + + + public override void Dispose() + { + plc.SafeDispose(); + tcpServerPage.SafeDispose(); + base.Dispose(); + } + public override string ToString() + { + return nameof(ModbusServer); + } +} \ No newline at end of file diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusTcp.cs b/src/Plugins/ThingsGateway.Modbus/ModbusTcp.cs index fbe49ba19..ce0cea582 100644 --- a/src/Plugins/ThingsGateway.Modbus/ModbusTcp.cs +++ b/src/Plugins/ThingsGateway.Modbus/ModbusTcp.cs @@ -16,6 +16,7 @@ public class ModbusTcp : CollectBase } public override CollectDriverPropertyBase DriverPropertys => driverPropertys; + public override Type DriverDebugUIType => typeof(ModbusTcpDebugDriverPage); public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; } @@ -70,6 +71,7 @@ public class ModbusTcp : CollectBase _plc = new((TGTcpClient)client); _plc.DataFormat = driverPropertys.DataFormat; _plc.FrameTime = driverPropertys.FrameTime; + _plc.CacheTimeout = driverPropertys.CacheTimeout; _plc.ConnectTimeOut = driverPropertys.ConnectTimeOut; _plc.Station = driverPropertys.Station; _plc.TimeOut = driverPropertys.TimeOut; @@ -97,7 +99,8 @@ public class ModbusTcpProperty : CollectDriverPropertyBase [DeviceProperty("帧前时间", "某些设备性能较弱,报文间需要间隔较长时间")] public int FrameTime { get; set; } = 0; - + [DeviceProperty("组包缓存超时", "某些设备性能较弱,报文间需要间隔较长时间,可以设置更长的组包缓存,默认1s")] + public double CacheTimeout { get; set; } = 1; [DeviceProperty("默认解析顺序", "")] public DataFormat DataFormat { get; set; } diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusTcpDebugDriverPage.razor b/src/Plugins/ThingsGateway.Modbus/ModbusTcpDebugDriverPage.razor new file mode 100644 index 000000000..4f4f33d4b --- /dev/null +++ b/src/Plugins/ThingsGateway.Modbus/ModbusTcpDebugDriverPage.razor @@ -0,0 +1,145 @@ +@using BlazorComponent; +@using Microsoft.AspNetCore.Components.Web; +@using Microsoft.JSInterop; +@using ThingsGateway.Core; +@using ThingsGateway.Foundation.Adapter.Modbus; +@using ThingsGateway.Foundation; +@using ThingsGateway.Foundation.Extension; +@using ThingsGateway.Foundation.Serial; +@using ThingsGateway.Web.Foundation; +@using Masa.Blazor +@inherits DriverDebugUIBase + +@if (_plc != null) +{ + + + x.IsCheckMessageId)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.IsCheckMessageId> + x.FrameTime)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.FrameTime> + x.CacheTimeout)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout> + + x.Station)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.Station> + x.TimeOut)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.TimeOut> + u.des) + ItemValue=@(u =>(DataFormat)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + +} + + + + + + + + + u.des) + ItemValue=@(u =>(DataTypeEnum)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + 读取 + + + + 写入 + + + + + + + + + + + + 输出日志 + + + + + + { + await DownDeviceMessageExport(Messages.Select(a=>a.message)); + } + )> + mdi-export + + + + 导出 + + + + + @{ + var item = Messages; + + + +
+ @itemMessage.message +
+ +
+
+
+ } +
+
+ +
+ +
+ + +@code +{ + private TcpClientPage tcpClientPage; + private ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp _plc + { + get + { + return plc as ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp; + } + } + + protected override void OnAfterRender(bool firstRender) + { + if (firstRender) + { + tcpClientPage.LogAction = LogOut; + //载入配置 + plc = new ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp((TGTcpClient)tcpClientPage.GetTGTcpClient()); + StateHasChanged(); + } + + base.OnAfterRender(firstRender); + } + + + public override void Dispose() + { + plc.SafeDispose(); + tcpClientPage.SafeDispose(); + base.Dispose(); + } + public override string ToString() + { + return nameof(ModbusTcp); + } +} \ No newline at end of file diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusUdp.cs b/src/Plugins/ThingsGateway.Modbus/ModbusUdp.cs index a913b98fa..bf9bac786 100644 --- a/src/Plugins/ThingsGateway.Modbus/ModbusUdp.cs +++ b/src/Plugins/ThingsGateway.Modbus/ModbusUdp.cs @@ -19,6 +19,7 @@ public class ModbusUdp : CollectBase public override CollectDriverPropertyBase DriverPropertys => driverPropertys; public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; } + public override Type DriverDebugUIType => typeof(ModbusUdpDebugDriverPage); public override void AfterStop() { diff --git a/src/Plugins/ThingsGateway.Modbus/ModbusUdpDebugDriverPage.razor b/src/Plugins/ThingsGateway.Modbus/ModbusUdpDebugDriverPage.razor new file mode 100644 index 000000000..6f8057b2b --- /dev/null +++ b/src/Plugins/ThingsGateway.Modbus/ModbusUdpDebugDriverPage.razor @@ -0,0 +1,144 @@ +@using BlazorComponent; +@using Microsoft.AspNetCore.Components.Web; +@using Microsoft.JSInterop; +@using ThingsGateway.Core; +@using ThingsGateway.Foundation.Adapter.Modbus; +@using ThingsGateway.Foundation; +@using ThingsGateway.Foundation.Extension; +@using ThingsGateway.Foundation.Serial; +@using ThingsGateway.Web.Foundation; +@using Masa.Blazor +@inherits DriverDebugUIBase + +@if (_plc != null) +{ + + + x.IsCheckMessageId)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.IsCheckMessageId> + x.FrameTime)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.FrameTime> + + x.Station)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.Station> + x.TimeOut)) Dense Outlined HideDetails="@("auto")" @bind-Value=@_plc.TimeOut> + u.des) + ItemValue=@(u =>(DataFormat)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + +} + + + + + + + + + u.des) + ItemValue=@(u =>(DataTypeEnum)u.value) + HideDetails=@("auto") Height="30" + Dense> + + + + 读取 + + + + 写入 + + + + + + + + + + + + 输出日志 + + + + + + { + await DownDeviceMessageExport(Messages.Select(a=>a.message)); + } + )> + mdi-export + + + + 导出 + + + + + @{ + var item = Messages; + + + +
+ @itemMessage.message +
+ +
+
+
+ } +
+
+ +
+ +
+ + +@code +{ + private UdpSessionPage udpClientPage; + private ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp _plc + { + get + { + return plc as ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp; + } + } + + protected override void OnAfterRender(bool firstRender) + { + if (firstRender) + { + udpClientPage.LogAction = LogOut; + //载入配置 + plc = new ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp((TGUdpSession)udpClientPage.GetTGUdpSession()); + StateHasChanged(); + } + + base.OnAfterRender(firstRender); + } + + + public override void Dispose() + { + plc.SafeDispose(); + udpClientPage.SafeDispose(); + base.Dispose(); + } + public override string ToString() + { + return nameof(ModbusUdp); + } +} \ No newline at end of file diff --git a/src/Plugins/ThingsGateway.Modbus/SerialClientPage.razor b/src/Plugins/ThingsGateway.Modbus/SerialClientPage.razor index 064a86b45..0b309ae11 100644 --- a/src/Plugins/ThingsGateway.Modbus/SerialClientPage.razor +++ b/src/Plugins/ThingsGateway.Modbus/SerialClientPage.razor @@ -2,18 +2,18 @@ @using Microsoft.AspNetCore.Components.Web; @using System.IO.Ports; @using ThingsGateway.Core; -@using ThingsGateway.Foundation.Adapter.Modbus; @using ThingsGateway.Foundation; @using ThingsGateway.Foundation.Serial; @using ThingsGateway.Web.Foundation; @using Masa.Blazor - +@implements IDisposable + x.PortName)) Dense Outlined HideDetails="@("auto")" @bind-Value=@serialProperty.PortName /> + x.BaudRate)) Dense Outlined HideDetails="@("auto")" @bind-Value=@serialProperty.BaudRate /> x.DataBits)) Dense Outlined HideDetails="@("auto")" @bind-Value=@serialProperty.DataBits /> - x.BaudRate)) Dense Outlined HideDetails="@("auto")" @bind-Value=@serialProperty.BaudRate /> - u.des) @@ -21,7 +21,7 @@ HideDetails=@("auto") Height="30" Dense> - u.des) @@ -31,28 +31,53 @@ { - serialClient.Close(); + GetSerialClient().Close(); await GetSerialClient().OpenAsync(); } ) Color="primary"> 连接 - + + { + GetSerialClient().Close(); + } + ) Color="red"> + 断开 + + @code { + public void Dispose() + { + serialClient.SafeDispose(); + } private SerialProperty serialProperty = new SerialProperty(); private SerialClient serialClient { get; set; } = new(); private TouchSocketConfig config; + public Action LogAction; protected override void OnInitialized() { config = new TouchSocketConfig(); + var logMessage = new TouchSocket.Core.LoggerGroup(); + logMessage.AddLogger(new EasyLogger(LogOut)); + config.ConfigureContainer(a => a.RegisterSingleton(logMessage)); + serialClient = config.Container.Resolve(); + base.OnInitialized(); + } + private void LogOut(string str) + { + LogAction?.Invoke(str); } public SerialClient GetSerialClient() { + config = new TouchSocketConfig(); + var logMessage = new TouchSocket.Core.LoggerGroup(); + logMessage.AddLogger(new EasyLogger(LogOut)); + config.ConfigureContainer(a => a.RegisterSingleton(logMessage)); config.SetSerialProperty(serialProperty).SetBufferLength(300); //载入配置 serialClient.Setup(config); diff --git a/src/Plugins/ThingsGateway.Modbus/TcpClientPage.razor b/src/Plugins/ThingsGateway.Modbus/TcpClientPage.razor new file mode 100644 index 000000000..77d71516b --- /dev/null +++ b/src/Plugins/ThingsGateway.Modbus/TcpClientPage.razor @@ -0,0 +1,76 @@ +@using BlazorComponent; +@using Microsoft.AspNetCore.Components.Web; +@using System.IO.Ports; +@using System.Collections.Concurrent; +@using ThingsGateway.Core; +@using ThingsGateway.Foundation; +@using ThingsGateway.Foundation.Serial; +@using ThingsGateway.Web.Foundation; +@using Masa.Blazor +@implements IDisposable + + + + + + + { + tgTcpClient.Close(); + await GetTGTcpClient().ConnectAsync(); + } + ) Color="primary"> + 连接 + + + { + tgTcpClient.Close(); + } + ) Color="red"> + 断开 + + + + + + +@code +{ + public void Dispose() + { + tgTcpClient.SafeDispose(); + } + private string ip="127.0.0.1"; + private int port=502; + private TGTcpClient tgTcpClient { get; set; } = new(); + private TouchSocketConfig config; + public Action LogAction; + + private void LogOut(string str) + { + LogAction?.Invoke(str); + } + protected override void OnInitialized() + { + config = new TouchSocketConfig(); + var logMessage = new TouchSocket.Core.LoggerGroup(); + logMessage.AddLogger(new EasyLogger(LogOut)); + config.ConfigureContainer(a => a.RegisterSingleton(logMessage)); + config.SetRemoteIPHost(new IPHost(ip + ":" + port)).SetBufferLength(300); + tgTcpClient = config.Container.Resolve(); + base.OnInitialized(); + + } + public TGTcpClient GetTGTcpClient() + { + config = new TouchSocketConfig(); + var logMessage = new TouchSocket.Core.LoggerGroup(); + logMessage.AddLogger(new EasyLogger(LogOut)); + config.ConfigureContainer(a => a.RegisterSingleton(logMessage)); + config.SetRemoteIPHost(new IPHost(ip + ":" + port)).SetBufferLength(300); + //载入配置 + tgTcpClient.Setup(config); + return tgTcpClient; + } + + +} \ No newline at end of file diff --git a/src/Plugins/ThingsGateway.Modbus/TcpServerPage.razor b/src/Plugins/ThingsGateway.Modbus/TcpServerPage.razor new file mode 100644 index 000000000..c6996430f --- /dev/null +++ b/src/Plugins/ThingsGateway.Modbus/TcpServerPage.razor @@ -0,0 +1,78 @@ +@using BlazorComponent; +@using Microsoft.AspNetCore.Components.Web; +@using System.IO.Ports; +@using System.Collections.Concurrent; +@using ThingsGateway.Core; +@using ThingsGateway.Foundation; +@using ThingsGateway.Foundation.Serial; +@using ThingsGateway.Web.Foundation; +@using Masa.Blazor +@implements IDisposable + + + + + + + { + tgTcpServer.Stop(); + GetTGTcpServer().Start(); + } + ) Color="primary"> + 连接 + + + { + tgTcpServer.Stop(); + } + ) Color="red"> + 断开 + + + + + + +@code +{ + public void Dispose() + { + tgTcpServer.SafeDispose(); + } + private string ip = "127.0.0.1"; + private int port = 502; + private TcpService tgTcpServer { get; set; } = new(); + private TouchSocketConfig config; + public Action LogAction; + + private void LogOut(string str) + { + LogAction?.Invoke(str); + } + protected override void OnInitialized() + { + config = new TouchSocketConfig(); + var logMessage = new TouchSocket.Core.LoggerGroup(); + logMessage.AddLogger(new EasyLogger(LogOut)); + config.ConfigureContainer(a => a.RegisterSingleton(logMessage)); + config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) }); + config.SetBufferLength(300); + tgTcpServer = config.Container.Resolve(); + base.OnInitialized(); + + } + public TcpService GetTGTcpServer() + { + config = new TouchSocketConfig(); + var logMessage = new TouchSocket.Core.LoggerGroup(); + logMessage.AddLogger(new EasyLogger(LogOut)); + config.ConfigureContainer(a => a.RegisterSingleton(logMessage)); + config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) }); + config.SetBufferLength(300); + //载入配置 + tgTcpServer.Setup(config); + return tgTcpServer; + } + + +} \ No newline at end of file diff --git a/src/Plugins/ThingsGateway.Modbus/UdpSessionPage.razor b/src/Plugins/ThingsGateway.Modbus/UdpSessionPage.razor new file mode 100644 index 000000000..01d44cb5b --- /dev/null +++ b/src/Plugins/ThingsGateway.Modbus/UdpSessionPage.razor @@ -0,0 +1,78 @@ +@using BlazorComponent; +@using Microsoft.AspNetCore.Components.Web; +@using System.IO.Ports; +@using System.Collections.Concurrent; +@using ThingsGateway.Core; +@using ThingsGateway.Foundation; +@using ThingsGateway.Foundation.Serial; +@using ThingsGateway.Web.Foundation; +@using Masa.Blazor +@implements IDisposable + + + + + + + { + tgUdpSession.Stop(); + GetTGUdpSession().Start(); + } + ) Color="primary"> + 连接 + + + { + tgUdpSession.Stop(); + } + ) Color="red"> + 断开 + + + + + + +@code +{ + public void Dispose() + { + tgUdpSession.SafeDispose(); + } + private string ip = "127.0.0.1"; + private int port = 502; + private TGUdpSession tgUdpSession { get; set; } = new(); + private TouchSocketConfig config; + public Action LogAction; + + private void LogOut(string str) + { + LogAction?.Invoke(str); + } + protected override void OnInitialized() + { + config = new TouchSocketConfig(); + var logMessage = new TouchSocket.Core.LoggerGroup(); + logMessage.AddLogger(new EasyLogger(LogOut)); + config.ConfigureContainer(a => a.RegisterSingleton(logMessage)); + config.SetRemoteIPHost(new IPHost(ip + ":" + port)).SetBufferLength(300); + config.SetBindIPHost(new IPHost(0)); + tgUdpSession = config.Container.Resolve(); + base.OnInitialized(); + + } + public TGUdpSession GetTGUdpSession() + { + config = new TouchSocketConfig(); + var logMessage = new TouchSocket.Core.LoggerGroup(); + logMessage.AddLogger(new EasyLogger(LogOut)); + config.ConfigureContainer(a => a.RegisterSingleton(logMessage)); + config.SetRemoteIPHost(new IPHost(ip + ":" + port)).SetBufferLength(300); + config.SetBindIPHost(new IPHost(0)); + //载入配置 + tgUdpSession.Setup(config); + return tgUdpSession; + } + + +} \ No newline at end of file diff --git a/src/ThingsGateway.Foundation/Foundation/BaseClient/ReadWriteDevicesBase.cs b/src/ThingsGateway.Foundation/Foundation/BaseClient/ReadWriteDevicesBase.cs index b03d4e506..515a6df1d 100644 --- a/src/ThingsGateway.Foundation/Foundation/BaseClient/ReadWriteDevicesBase.cs +++ b/src/ThingsGateway.Foundation/Foundation/BaseClient/ReadWriteDevicesBase.cs @@ -1,4 +1,6 @@ -namespace ThingsGateway.Foundation +using System.ComponentModel; + +namespace ThingsGateway.Foundation { /// /// 读写设备基类 @@ -6,6 +8,7 @@ public abstract class ReadWriteDevicesBase : DisposableObject, IReadWriteDevice { /// + [Description("数据转换")] public DataFormat DataFormat { get @@ -23,6 +26,7 @@ /// public IThingsGatewayBitConverter ThingsGatewayBitConverter { get; protected set; } = new ThingsGatewayBitConverter(EndianType.Big); /// + [Description("读写超时")] public ushort TimeOut { get; set; } = 3000; /// public ushort RegisterByteLength { get; set; } = 1; diff --git a/src/ThingsGateway.Foundation/Foundation/BaseClient/ReadWriteDevicesTcpClientBase.cs b/src/ThingsGateway.Foundation/Foundation/BaseClient/ReadWriteDevicesTcpClientBase.cs index d5cc17f4e..20a2b6d04 100644 --- a/src/ThingsGateway.Foundation/Foundation/BaseClient/ReadWriteDevicesTcpClientBase.cs +++ b/src/ThingsGateway.Foundation/Foundation/BaseClient/ReadWriteDevicesTcpClientBase.cs @@ -88,23 +88,23 @@ private void Connected(ITcpClient client, MsgEventArgs e) { - Logger?.Debug(client.GetIPPort() + "连接成功"); + Logger?.Debug(client.RemoteIPHost.ToString() + "连接成功"); } private void Connecting(ITcpClient client, ConnectingEventArgs e) { - Logger?.Debug(client.GetIPPort() + "正在连接"); + Logger?.Debug(client.RemoteIPHost.ToString() + "正在连接"); SetDataAdapter(); } private void Disconnected(ITcpClientBase client, DisconnectEventArgs e) { - Logger?.Debug(client.GetIPPort() + "断开连接-" + e.Message); + Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message); } private void Disconnecting(ITcpClientBase client, DisconnectEventArgs e) { - Logger?.Debug(client.GetIPPort() + "正在主动断开连接-" + e.Message); + Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message); } } } \ No newline at end of file diff --git a/src/ThingsGateway.Foundation/Foundation/BaseServer/ReadWriteDevicesTcpServerBase.cs b/src/ThingsGateway.Foundation/Foundation/BaseServer/ReadWriteDevicesTcpServerBase.cs index 653e00842..ee505ba31 100644 --- a/src/ThingsGateway.Foundation/Foundation/BaseServer/ReadWriteDevicesTcpServerBase.cs +++ b/src/ThingsGateway.Foundation/Foundation/BaseServer/ReadWriteDevicesTcpServerBase.cs @@ -71,23 +71,23 @@ namespace ThingsGateway.Foundation private void Connected(SocketClient client, TouchSocketEventArgs e) { - Logger?.Debug(client.GetIPPort() + "连接成功"); + Logger?.Debug(client.IP + ":" + client.Port + "连接成功"); } private void Connecting(SocketClient client, OperationEventArgs e) { - Logger?.Debug(client.GetIPPort() + "正在连接"); + Logger?.Debug(client.IP + ":" + client.Port + "正在连接"); SetDataAdapter(client); } private void Disconnected(ITcpClientBase client, DisconnectEventArgs e) { - Logger?.Debug(client.GetIPPort() + "断开连接-" + e.Message); + Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message); } private void Disconnecting(ITcpClientBase client, DisconnectEventArgs e) { - Logger?.Debug(client.GetIPPort() + "正在主动断开连接-" + e.Message); + Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message); } private async void Received(SocketClient client, ByteBlock byteBlock, IRequestInfo requestInfo) diff --git a/src/ThingsGateway.Foundation/Foundation/DataHandleAdapter/ReadWriteDevicesTcpDataHandleAdapter.cs b/src/ThingsGateway.Foundation/Foundation/DataHandleAdapter/ReadWriteDevicesTcpDataHandleAdapter.cs index 5eeb6bb02..783d84457 100644 --- a/src/ThingsGateway.Foundation/Foundation/DataHandleAdapter/ReadWriteDevicesTcpDataHandleAdapter.cs +++ b/src/ThingsGateway.Foundation/Foundation/DataHandleAdapter/ReadWriteDevicesTcpDataHandleAdapter.cs @@ -41,7 +41,7 @@ protected override FilterResult Filter(ByteBlock byteBlock, bool beCached, ref TRequest request, ref int tempCapacity) { var allBytes = byteBlock.ToArray(0, byteBlock.Len); - Client.Logger?.Trace("报文-" + Client.GetIPPort().ToString() + "-" + ThingsGateway.Foundation.Resources.Resource.Received + ":" + allBytes.ToHexString(" ")); + Client.Logger?.Trace("报文-" + Client.IP + ":" + Client.Port + "-" + ThingsGateway.Foundation.Resources.Resource.Received + ":" + allBytes.ToHexString(" ")); //if (Request?.SendBytes == null) //{ @@ -111,7 +111,7 @@ { byteBlock.Pos = byteBlock.Len; request.ReceivedBytes = allBytes; - Client.Logger?.Warning(Client.GetIPPort().ToString() + unpackbytes.Message); + Client.Logger?.Warning(Client.IP + ":" + Client.Port.ToString() + unpackbytes.Message); return FilterResult.Success; } } @@ -135,7 +135,7 @@ Request = GetInstance(); Request.SendBytes = bytes; GoSend(bytes, 0, bytes.Length); - Client.Logger?.Trace("报文-" + Client.GetIPPort().ToString() + "-" + ThingsGateway.Foundation.Resources.Resource.Send + ":" + Request.SendBytes.ToHexString(" ")); + Client.Logger?.Trace("报文-" + Client.IP + ":" + Client.Port.ToString() + "-" + ThingsGateway.Foundation.Resources.Resource.Send + ":" + Request.SendBytes.ToHexString(" ")); } /// diff --git a/src/ThingsGateway.Foundation/TouchSocketEx/TGTcpClient.cs b/src/ThingsGateway.Foundation/TouchSocketEx/TGTcpClient.cs index 47fbd68c0..2b9e5b0d2 100644 --- a/src/ThingsGateway.Foundation/TouchSocketEx/TGTcpClient.cs +++ b/src/ThingsGateway.Foundation/TouchSocketEx/TGTcpClient.cs @@ -531,6 +531,8 @@ namespace TouchSocket.Sockets ConnectingEventArgs args = new ConnectingEventArgs(this.MainSocket); this.PrivateOnConnecting(args); { + this.CanSend = true; + this.LoadSocketAndReadIpPort(); #if (NET6_0_OR_GREATER) var nowTime = DateTime.UtcNow; using CancellationTokenSource cancellationTokenSource = new(); @@ -580,8 +582,6 @@ namespace TouchSocket.Sockets if (this.MainSocket.Connected) { - this.CanSend = true; - this.LoadSocketAndReadIpPort(); if (this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty) is DelaySenderOption senderOption) { diff --git a/src/ThingsGateway.Web.Foundation/Plugin/DriverDebugUIBase.cs b/src/ThingsGateway.Web.Foundation/Plugin/DriverDebugUIBase.cs index 9e0482616..85423810b 100644 --- a/src/ThingsGateway.Web.Foundation/Plugin/DriverDebugUIBase.cs +++ b/src/ThingsGateway.Web.Foundation/Plugin/DriverDebugUIBase.cs @@ -1,12 +1,141 @@ using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; + +using System.IO; +using System.Timers; + +using ThingsGateway.Foundation; + +using TouchSocket.Core; namespace ThingsGateway.Web.Foundation; /// /// 调试UI /// -public abstract class DriverDebugUIBase : ComponentBase +public abstract class DriverDebugUIBase : ComponentBase, IDisposable { + /// + protected IReadWriteDevice plc; + /// + protected bool isDownExport; + /// + protected string address = "40001"; + /// + protected DataTypeEnum dataTypeEnum = DataTypeEnum.Int16; + /// + protected int length = 1; + /// + protected string writeValue = "1"; + /// + protected ConcurrentList<(long id, bool? isRed, string message)> Messages = new(); + /// + [Inject] + protected IJSRuntime JS { get; set; } + private System.Timers.Timer DelayTimer; + /// + protected override void OnInitialized() + { + DelayTimer = new System.Timers.Timer(1000); + DelayTimer.Elapsed += timer_Elapsed; + DelayTimer.AutoReset = true; + DelayTimer.Start(); + base.OnInitialized(); + } + + private async void timer_Elapsed(object sender, ElapsedEventArgs e) + { + await InvokeAsync(StateHasChanged); + } + + /// + public virtual void Dispose() + { + DelayTimer?.Dispose(); + + } + /// + /// 导出 + /// + /// + /// + protected async Task DownDeviceMessageExport(IEnumerable values) + { + try + { + isDownExport = true; + StateHasChanged(); + var memoryStream = new MemoryStream(); + StreamWriter writer = new StreamWriter(memoryStream); + foreach (var item in values) + { + writer.WriteLine(item); + } + + writer.Flush(); + memoryStream.Seek(0, SeekOrigin.Begin); + using var streamRef = new DotNetStreamReference(stream: memoryStream); + await JS.InvokeVoidAsync("downloadFileFromStream", $"报文导出{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}.txt", streamRef); + } + finally + { + isDownExport = false; + } + } + + /// + protected void LogOut(string str) + { + Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), null, str)); + if (Messages.Count > 2500) + { + Messages.RemoveRange(0, 2000); + } + } + /// + public async Task Read() + { + var data = await plc.ReadAsync(address, length); + if (data.IsSuccess) + { + try + { + var byteConverter = ByteConverterHelper.GetTransByAddress(ref address, plc.ThingsGatewayBitConverter, out int length, out BcdFormat bcdFormat); + var value = plc.ThingsGatewayBitConverter.GetDynamicData(dataTypeEnum.GetNetType(), data.Content).ToString(); + Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), false, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 对应类型值:" + value + " - 原始字节:" + data.Content.ToHexString(" "))); + } + catch (Exception ex) + { + Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 操作成功,但转换数据类型失败 - 原因:" + ex.Message + " - 原始字节:" + data.Content.ToHexString(" "))); + } + } + else + { + Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message)); + } + } + + /// + public async Task Write() + { + try + { + var byteConverter = ByteConverterHelper.GetTransByAddress(ref address, plc.ThingsGatewayBitConverter, out int length, out BcdFormat bcdFormat); + var data = await plc.WriteAsync(dataTypeEnum.GetNetType(), address, writeValue, dataTypeEnum == DataTypeEnum.Bcd); + if (data.IsSuccess) + { + Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), false, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message)); + } + else + { + Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message)); + } + } + catch (Exception ex) + { + Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + "写入前失败:" + ex.Message)); + } + } } diff --git a/src/ThingsGateway.Web.Foundation/Services/PluginInfo/DriverPluginService.cs b/src/ThingsGateway.Web.Foundation/Services/PluginInfo/DriverPluginService.cs index 6a4048d70..5410ccf26 100644 --- a/src/ThingsGateway.Web.Foundation/Services/PluginInfo/DriverPluginService.cs +++ b/src/ThingsGateway.Web.Foundation/Services/PluginInfo/DriverPluginService.cs @@ -82,6 +82,31 @@ namespace ThingsGateway.Web.Foundation var data = GetCacheList(); return data.FirstOrDefault(it => it.Id == Id); } + /// + public List GetDriverPluginChildrenList() + { + var data = GetCacheList(); + var driverPluginCategories = data.GroupBy(a => a.FileName).Select(it => + { + var childrens = new List(); + foreach (var item in it) + { + childrens.Add(new DriverPluginCategory + { + Id = item.Id, + Name = item.AssembleName, + } + ); + } + return new DriverPluginCategory + { + Id = YitIdHelper.NextId(), + Name = it.Key, + Children = childrens, + }; + }); + return driverPluginCategories.ToList(); + } /// public List GetDriverPluginChildrenList(DriverEnum driverTypeEnum) diff --git a/src/ThingsGateway.Web.Foundation/Services/PluginInfo/IDriverPluginService.cs b/src/ThingsGateway.Web.Foundation/Services/PluginInfo/IDriverPluginService.cs index f1caa3b48..e151353b9 100644 --- a/src/ThingsGateway.Web.Foundation/Services/PluginInfo/IDriverPluginService.cs +++ b/src/ThingsGateway.Web.Foundation/Services/PluginInfo/IDriverPluginService.cs @@ -30,6 +30,12 @@ namespace ThingsGateway.Web.Foundation /// /// List GetDriverPluginChildrenList(DriverEnum driverTypeEnum); + /// + /// 获取插件树 + /// + /// + List GetDriverPluginChildrenList(); + /// /// 根据ID获取名称 /// diff --git a/src/ThingsGateway.Web.Foundation/Wokers/HardwareInfo/HardwareInfoService.cs b/src/ThingsGateway.Web.Foundation/Wokers/HardwareInfo/HardwareInfoService.cs index a1c25a17f..4e91481ba 100644 --- a/src/ThingsGateway.Web.Foundation/Wokers/HardwareInfo/HardwareInfoService.cs +++ b/src/ThingsGateway.Web.Foundation/Wokers/HardwareInfo/HardwareInfoService.cs @@ -31,9 +31,9 @@ namespace ThingsGateway.Web.Foundation { hardwareInfo = new(); } - catch(Exception ex) + catch (Exception ex) { - _logger.LogError(ex,"初始化硬件信息失败"); + _logger.LogError(ex, "初始化硬件信息失败"); } _ = Task.Run(async () => { diff --git a/src/ThingsGateway.Web.Page/Page/CollectDevicePage.razor b/src/ThingsGateway.Web.Page/Page/CollectDevicePage.razor index d4b00cc2f..4f3a7c55b 100644 --- a/src/ThingsGateway.Web.Page/Page/CollectDevicePage.razor +++ b/src/ThingsGateway.Web.Page/Page/CollectDevicePage.razor @@ -166,6 +166,7 @@ } @code { + [Inject] public JsInitVariables JsInitVariables { get; set; } = default!; [Inject] IJSRuntime JS { get; set; } bool isDownExport; @@ -178,7 +179,7 @@ using var memoryStream = await CollectDeviceService.ExportFileAsync(); memoryStream.Seek(0, SeekOrigin.Begin); using var streamRef = new DotNetStreamReference(stream: memoryStream); - await JS.InvokeVoidAsync("downloadFileFromStream", $"采集设备导出{DateTime.UtcNow.ToString("MM-dd-HH-mm-ss")}.xlsx", streamRef); + await JS.InvokeVoidAsync("downloadFileFromStream", $"采集设备导出{DateTime.UtcNow.Add(JsInitVariables.TimezoneOffset).ToString("MM-dd-HH-mm-ss")}.xlsx", streamRef); } finally { diff --git a/src/ThingsGateway.Web.Page/Page/CollectVariablePage.razor b/src/ThingsGateway.Web.Page/Page/CollectVariablePage.razor index 3dfea2e24..d690898b8 100644 --- a/src/ThingsGateway.Web.Page/Page/CollectVariablePage.razor +++ b/src/ThingsGateway.Web.Page/Page/CollectVariablePage.razor @@ -121,6 +121,7 @@ } @code { + [Inject] public JsInitVariables JsInitVariables { get; set; } = default!; [Inject] IJSRuntime JS { get; set; } bool isDownExport; @@ -133,7 +134,7 @@ using var memoryStream = await VariableService.ExportFileAsync(); memoryStream.Seek(0, SeekOrigin.Begin); using var streamRef = new DotNetStreamReference(stream: memoryStream); - await JS.InvokeVoidAsync("downloadFileFromStream", $"变量导出{DateTime.UtcNow.ToString("MM-dd-HH-mm-ss")}.xlsx", streamRef); + await JS.InvokeVoidAsync("downloadFileFromStream", $"变量导出{DateTime.UtcNow.Add(JsInitVariables.TimezoneOffset).ToString("MM-dd-HH-mm-ss")}.xlsx", streamRef); } finally { diff --git a/src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor b/src/ThingsGateway.Web.Page/Page/DriverDebugPage.razor similarity index 77% rename from src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor rename to src/ThingsGateway.Web.Page/Page/DriverDebugPage.razor index 1ee979a16..96ffe20fb 100644 --- a/src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor +++ b/src/ThingsGateway.Web.Page/Page/DriverDebugPage.razor @@ -15,10 +15,9 @@ @inject UserResoures UserResoures @inject ICollectDeviceService CollectDeviceService @layout MainLayout - - - - + + + @@ -37,17 +36,33 @@ - - + + + + + + { + IsShowTreeView=!IsShowTreeView; + } + ) Color="primary" Icon> + mdi-menu + + + @_importRef?.ToString() + + + @if (_importRender != null) { @_importRender } - - + + + @code { + bool IsShowTreeView = true; class PluginDebugUIInput { public string PluginName { get; set; } @@ -68,8 +83,7 @@ protected override void OnInitialized() { - DriverPlugins = DriverPluginService.GetDriverPluginChildrenList(DriverEnum.Collect); - + DriverPlugins = DriverPluginService.GetDriverPluginChildrenList(); base.OnInitialized(); } async Task ImportVaiable(long driverId) diff --git a/src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor.cs b/src/ThingsGateway.Web.Page/Page/DriverDebugPage.razor.cs similarity index 90% rename from src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor.cs rename to src/ThingsGateway.Web.Page/Page/DriverDebugPage.razor.cs index b5cfb8250..eb48c45c4 100644 --- a/src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor.cs +++ b/src/ThingsGateway.Web.Page/Page/DriverDebugPage.razor.cs @@ -1,8 +1,6 @@ -using SqlSugar; - namespace ThingsGateway.Web.Page { - public partial class PluginDebugPage + public partial class DriverDebugPage { [CascadingParameter] diff --git a/src/ThingsGateway.Web.Page/Page/UploadDevicePage.razor b/src/ThingsGateway.Web.Page/Page/UploadDevicePage.razor index ba0f74bc5..5b215315f 100644 --- a/src/ThingsGateway.Web.Page/Page/UploadDevicePage.razor +++ b/src/ThingsGateway.Web.Page/Page/UploadDevicePage.razor @@ -154,6 +154,7 @@ } @code { + [Inject] public JsInitVariables JsInitVariables { get; set; } = default!; [Inject] IJSRuntime JS { get; set; } bool isDownExport; @@ -166,7 +167,7 @@ using var memoryStream = await UploadDeviceService.ExportFileAsync(); memoryStream.Seek(0, SeekOrigin.Begin); using var streamRef = new DotNetStreamReference(stream: memoryStream); - await JS.InvokeVoidAsync("downloadFileFromStream", $"上传设备导出{DateTime.UtcNow.ToString("MM-dd-HH-mm-ss")}.xlsx", streamRef); + await JS.InvokeVoidAsync("downloadFileFromStream", $"上传设备导出{DateTime.UtcNow.Add(JsInitVariables.TimezoneOffset).ToString("MM-dd-HH-mm-ss")}.xlsx", streamRef); } finally {