初步添加插件驱动调试页面

This commit is contained in:
2248356998 qq.com
2023-05-22 18:41:09 +08:00
parent 6154fb29f1
commit d426e280d9
11 changed files with 263 additions and 10 deletions

View File

@@ -123,21 +123,22 @@ namespace ThingsGateway.Foundation.Tests
stopwatch.Stop();
_output.WriteLine(address + "<22><>ʱ<EFBFBD><CAB1>" + stopwatch.Elapsed.TotalSeconds);
}
[Theory(DisplayName = "127.0.0.1:503")]
[Theory(DisplayName = "127.0.0.1:502")]
//[MemberData(nameof(RangeData), 3, 1, 10)]
[MemberData(nameof(RangeData), 4, 1, 10)]
public async Task ModbusRtuOverTcpReadTest(string address)
{
ModbusRtuOverTcpClient("127.0.0.1:503");
ModbusRtuOverTcpClient("127.0.0.1:502");
await ModbusRtuOverTcp.ConnectAsync();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var byteConverter = ByteConverterHelper.GetTransByAddress(ref address, ModbusRtuOverTcp.ThingsGatewayBitConverter, out int length, out BcdFormat bcdFormat);
stopwatch.Start();
var test = await ModbusRtuOverTcp.ReadAsync(address, 1);
stopwatch.Stop();
_output.WriteLine(address + "<22><>ʱ<EFBFBD><CAB1>" + stopwatch.Elapsed.TotalSeconds);
Assert.True(test.IsSuccess, test.Message);
var data = byteConverter.ToInt16(test.Content, 0);
_output.WriteLine(data.ToJson());
stopwatch.Stop();
_output.WriteLine(address + "<22><>ʱ<EFBFBD><CAB1>" + stopwatch.Elapsed.TotalSeconds);
}
[Theory(DisplayName = "127.0.0.1:512")]

View File

@@ -13,6 +13,8 @@ public class ModbusRtu : CollectBase, IDisposable
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu _plc;
private ModbusRtuProperty driverPropertys = new ModbusRtuProperty();
public override Type DriverDebugUIType => typeof(ModbusRtuDebugDriverPage);
public ModbusRtu(IServiceScopeFactory scopeFactory) : base(scopeFactory)
{

View File

@@ -0,0 +1,32 @@
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using ThingsGateway.Foundation.Adapter.Modbus;
@using ThingsGateway.Foundation;
@using ThingsGateway.Web.Foundation;
@using Masa.Blazor
@inherits DriverDebugUIBase
<MCard Class="ma-0">
<MCardTitle Class="indigo white--text text-h6">
@nameof(ModbusRtu)
</MCardTitle>
<MRow Class="pa-4"
Justify="JustifyTypes.SpaceBetween">
<SerialClientPage @ref=serialClientPage></SerialClientPage>
<MDivider Vertical></MDivider>
</MRow>
</MCard>
@code
{
private SerialClientPage serialClientPage;
protected override void OnInitialized()
{
}
}

View File

@@ -0,0 +1,63 @@
@using BlazorComponent;
@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
<MCard Class="ma-4" Flat Elevation="0">
<MRow Justify="JustifyTypes.SpaceBetween" Align="AlignTypes.Center">
<MTextField Class="mx-1" Label=@(serialProperty.Description(x => x.PortName)) Dense Outlined HideDetails="@("auto")" @bind-Value=@serialProperty.PortName />
<MTextField Class="mx-1" Label=@(serialProperty.Description(x => x.DataBits)) Dense Outlined HideDetails="@("auto")" @bind-Value=@serialProperty.DataBits />
<MTextField Class="mx-1" Label=@(serialProperty.Description(x => x.BaudRate)) Dense Outlined HideDetails="@("auto")" @bind-Value=@serialProperty.BaudRate />
<MSelect Class="mx-1" Style="max-width:100px" @bind-Value="serialProperty.Parity" Outlined Label="@(serialProperty.Description(x => x.Parity))"
Items=@(typeof(Parity).GetEnumList())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.des)
ItemValue=@(u =>(Parity)u.value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
<MSelect Class="mx-1" Style="max-width:100px" @bind-Value="serialProperty.StopBits" Outlined Label="@(serialProperty.Description(x => x.StopBits))"
Items=@(typeof(StopBits).GetEnumList())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.des)
ItemValue=@(u =>(StopBits)u.value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
<MButton Class="mx-1" OnClick=@(async() =>
{
serialClient.Close();
await GetSerialClient().OpenAsync();
}
) Color="primary">
连接
</MButton>
</MRow>
</MCard>
@code
{
private SerialProperty serialProperty = new SerialProperty();
private SerialClient serialClient { get; set; } = new();
private TouchSocketConfig config;
protected override void OnInitialized()
{
config = new TouchSocketConfig();
}
public SerialClient GetSerialClient()
{
config.SetSerialProperty(serialProperty).SetBufferLength(300);
//载入配置
serialClient.Setup(config);
return serialClient;
}
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<LangVersion>latestMajor</LangVersion>
@@ -17,6 +17,14 @@
</Target>
<ItemGroup>
<PackageReference Include="Masa.Blazor" Version="1.0.0-rc.2">
<IncludeAssets>Compile</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ThingsGateway.Web.Foundation\ThingsGateway.Web.Foundation.csproj">
<IncludeAssets>Compile</IncludeAssets>

View File

@@ -1,3 +1,4 @@
using System.ComponentModel;
using System.IO.Ports;
namespace ThingsGateway.Foundation.Serial
@@ -10,22 +11,27 @@ namespace ThingsGateway.Foundation.Serial
/// <summary>
/// COM
/// </summary>
[Description("COM<4F><4D>")]
public string PortName { get; set; } = "COM1";
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
[Description("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
public int BaudRate { get; set; } = 9600;
/// <summary>
/// <20><><EFBFBD><EFBFBD>λ
/// </summary>
[Description("<22><><EFBFBD><EFBFBD>λ")]
public int DataBits { get; set; } = 8;
/// <summary>
/// У<><D0A3>λ
/// </summary>
[Description("У<><D0A3>λ")]
public Parity Parity { get; set; } = Parity.None;
/// <summary>
/// ֹͣλ
/// </summary>
[Description("ֹͣλ")]
public StopBits StopBits { get; set; } = StopBits.One;
/// <summary>
/// <20>ַ<EFBFBD><D6B7><EFBFBD>תʵ<D7AA><CAB5><EFBFBD><EFBFBD><E0A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>谴˳<E8B0B4><CBB3>

View File

@@ -28,10 +28,7 @@ public abstract class CollectBase : DriverBase
/// 导入变量UI Type继承实现<see cref="DriverImportUIBase"/>后返回继承类的Type如果不存在返回null
/// </summary>
public virtual Type DriverImportUIType { get; }
/// <summary>
/// 调试UI Type继承实现<see cref="DriverDebugUIBase"/>后返回继承类的Type如果不存在返回null
/// </summary>
public virtual Type DriverDebugUIType { get; }
/// <summary>
/// 共享通道类型
/// </summary>

View File

@@ -42,6 +42,11 @@ namespace ThingsGateway.Web.Foundation
/// </summary>
public abstract DriverPropertyBase DriverPropertys { get; }
/// <summary>
/// 调试UI Type继承实现<see cref="DriverDebugUIBase"/>后返回继承类的Type如果不存在返回null
/// </summary>
public virtual Type DriverDebugUIType { get; }
/// <summary>
/// 是否输出日志
/// </summary>
@@ -54,6 +59,7 @@ namespace ThingsGateway.Web.Foundation
/// 报文信息
/// </summary>
public ConcurrentList<(long id, string message)> Messages { get; set; } = new();
/// <summary>
/// 是否连接成功
/// </summary>

View File

@@ -358,6 +358,31 @@ public class CollectDeviceWorker : BackgroundService
}
}
/// <summary>
/// 获取导入变量UI
/// </summary>
/// <param name="driverId"></param>
/// <returns></returns>
public Type GetDebugUI(long driverId)
{
using var serviceScope = _scopeFactory.CreateScope();
var driverPluginService = serviceScope.ServiceProvider.GetService<IDriverPluginService>();
var driverPlugin = driverPluginService.GetDriverPluginById(driverId);
var id = YitIdHelper.NextId();
try
{
var driver = (DriverBase)_pluginService.GetDriver(id, driverPlugin);
driver?.Dispose();
return driver.DriverDebugUIType;
}
finally
{
_pluginService.DeleteDriver(id, driverId);
}
}
#endregion
#region worker服务

View File

@@ -0,0 +1,86 @@
@page "/tgconfig/driverdebug"
@namespace ThingsGateway.Web.Page
@using System.Linq.Expressions;
@using BlazorComponent;
@using Furion.DataValidation;
@using Mapster;
@using Masa.Blazor.Presets;
@using System.IO;
@using TouchSocket.Core;
@inject IVariableService VariableService
@attribute [Authorize]
@inject MasaBlazor MasaBlazor
@attribute [RolePermission]
@inherits CultureComponentBase
@inject UserResoures UserResoures
@inject ICollectDeviceService CollectDeviceService
@layout MainLayout
<MRow>
<MCol Md=4 Cols="12">
<MCard Class="ma-2" Style="height: calc(100vh - 200px)">
<MCardTitle>
<MTextField Dense Style="max-width:200px;" HideDetails=@("auto") Class="mx-2 my-1" @bind-Value="_searchName" Outlined Label=@typeof(CollectDevice).GetDescription(nameof(CollectDevice.PluginId)) />
</MCardTitle>
<MTreeview Style="height: calc(100vh - 320px);overflow-y:auto" Dense TItem="DriverPluginCategory"
TKey="long" OpenOnClick ActiveChanged=@((async a=>
{
if(this._searchModel.PluginId!= a.FirstOrDefault())
{
this._searchModel.PluginId= a.FirstOrDefault();
await ImportVaiable(this._searchModel.PluginId);
}
}) )
Items="DriverPlugins" ItemText="r=>r.Name" ItemChildren="r=>r.Children"
Search="@_searchName"
Activatable ItemKey=@(r=>r.Id)>
</MTreeview>
</MCard>
</MCol>
<MCol Md=8 Cols="12">
<MCard Class="ma-2" Style="height: calc(100vh - 200px)">
@if (_importRender != null)
{
@_importRender
}
</MCard>
</MCol>
</MRow>
@code {
class PluginDebugUIInput
{
public string PluginName { get; set; }
public long PluginId { get; set; }
}
}
@code {
string _searchName;
List<DeviceTree> _deviceGroups = new();
PluginDebugUIInput _searchModel { get; set; } = new();
private BootstrapDynamicComponent _importComponent;
private RenderFragment _importRender;
private DriverDebugUIBase _importRef;
List<DriverPluginCategory> DriverPlugins;
[Inject]
IDriverPluginService DriverPluginService { get; set; }
protected override void OnInitialized()
{
DriverPlugins = DriverPluginService.GetDriverPluginChildrenList(DriverEnum.Collect);
base.OnInitialized();
}
async Task ImportVaiable(long driverId)
{
var driver = this.GetBackgroundService<CollectDeviceWorker>().GetDebugUI(driverId);
if (driver == null)
{
await PopupService.EnqueueSnackbarAsync("插件未实现调试页面", AlertTypes.Warning);
return;
}
_importComponent = new BootstrapDynamicComponent(driver);
_importRender = _importComponent.Render(a => _importRef = (DriverDebugUIBase)a);
}
}

View File

@@ -0,0 +1,27 @@
using SqlSugar;
namespace ThingsGateway.Web.Page
{
public partial class PluginDebugPage
{
[CascadingParameter]
MainLayout MainLayout { get; set; }
[Inject]
ResourceService ResourceService { get; set; }
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
}
[Inject]
IUploadDeviceService UploadDeviceService { get; set; }
protected override async Task OnParametersSetAsync()
{
await base.OnParametersSetAsync();
}
}
}