初步添加插件驱动调试页面
This commit is contained in:
@@ -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")]
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
63
src/Plugins/ThingsGateway.Modbus/SerialClientPage.razor
Normal file
63
src/Plugins/ThingsGateway.Modbus/SerialClientPage.razor
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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服务
|
||||
|
86
src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor
Normal file
86
src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor
Normal 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);
|
||||
}
|
||||
}
|
27
src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor.cs
Normal file
27
src/ThingsGateway.Web.Page/Page/PluginDebugPage.razor.cs
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user