Compare commits
11 Commits
10.11.34.0
...
10.11.42.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b663d9e01 | ||
|
|
6c95c6209f | ||
|
|
4d223d2622 | ||
|
|
e8d7e91b64 | ||
|
|
8175f541ec | ||
|
|
0adbdb926b | ||
|
|
42adee9980 | ||
|
|
427a7404bc | ||
|
|
3658199e0a | ||
|
|
82eedee50a | ||
|
|
6a18fc3e06 |
@@ -4,9 +4,9 @@
|
||||
|
||||
<div class="tg-table h-100">
|
||||
|
||||
<Table TItem="TItem" IsBordered="true" IsStriped="true" TableSize="TableSize.Compact" IsMultipleSelect="IsMultipleSelect" @ref="Instance" SearchTemplate="SearchTemplate"
|
||||
<Table TItem="TItem" IsBordered="true" IsStriped="true" TableSize="TableSize.Compact" SelectedRows=SelectedRows SelectedRowsChanged=privateSelectedRowsChanged IsMultipleSelect="IsMultipleSelect" @ref="Instance" SearchTemplate="SearchTemplate"
|
||||
DataService="DataService" CreateItemCallback="CreateItemCallback!"
|
||||
IsPagination="IsPagination" PageItemsSource="PageItemsSource" IsFixedHeader="IsFixedHeader" IndentSize=24 RowHeight=RowHeight ShowSearchText="ShowSearchText" ShowSearchButton="ShowSearchButton" BeforeShowEditDialogCallback="BeforeShowEditDialogCallback!"
|
||||
IsPagination="IsPagination" PageItemsSource="PageItemsSource" IsFixedHeader="IsFixedHeader" IndentSize=24 RowHeight=RowHeight ShowSearchText="ShowSearchText" ShowSearchButton="ShowSearchButton" DisableEditButtonCallback="DisableEditButtonCallback" DisableDeleteButtonCallback="DisableDeleteButtonCallback" BeforeShowEditDialogCallback=" BeforeShowEditDialogCallback!"
|
||||
IsTree="IsTree" OnTreeExpand="OnTreeExpand!" TreeNodeConverter="TreeNodeConverter!" TreeIcon="fa-solid fa-circle-chevron-right" TreeExpandIcon="fa-solid fa-circle-chevron-right fa-rotate-90" IsAutoQueryFirstRender=IsAutoQueryFirstRender
|
||||
ShowDefaultButtons="ShowDefaultButtons" ShowAdvancedSearch="ShowAdvancedSearch" ShowResetButton=ShowResetButton
|
||||
ShowEmpty="ShowEmpty" EmptyText="@EmptyText" EmptyImage="@($"{WebsiteConst.DefaultResourceUrl}images/empty.svg")" SortString="@SortString" EditDialogSize="EditDialogSize"
|
||||
@@ -14,7 +14,7 @@
|
||||
ShowSkeleton="true" ShowLoading="ShowLoading" ShowSearch="ShowSearch" SearchModel=@SearchModel ShowLineNo
|
||||
SearchMode=SearchMode ShowExportPdfButton=ShowExportPdfButton ExportButtonText=@ExportButtonText
|
||||
ShowExportButton=@ShowExportButton Items=Items ClickToSelect=ClickToSelect ScrollMode=ScrollMode
|
||||
ShowExportCsvButton=@ShowExportCsvButton SelectedRowsChanged=SelectedRowsChanged ShowCardView=ShowCardView
|
||||
ShowExportCsvButton=@ShowExportCsvButton ShowCardView=ShowCardView
|
||||
FixedExtendButtonsColumn=FixedExtendButtonsColumn FixedMultipleColumn=FixedMultipleColumn FixedDetailRowHeaderColumn=FixedDetailRowHeaderColumn FixedLineNoColumn=FixedLineNoColumn
|
||||
IsAutoRefresh=IsAutoRefresh AutoRefreshInterval=AutoRefreshInterval
|
||||
AllowDragColumn=@AllowDragColumn Height=@Height ShowRefresh=ShowRefresh
|
||||
@@ -29,7 +29,7 @@
|
||||
ShowMultiFilterHeader=ShowMultiFilterHeader
|
||||
ShowFilterHeader=ShowFilterHeader
|
||||
ShowColumnList=ShowColumnList ExtendButtonColumnWidth="@ExtendButtonColumnWidth"
|
||||
CustomerSearchModel="CustomerSearchModel" SelectedRows="SelectedRows" ModelEqualityComparer="ModelEqualityComparer!"
|
||||
CustomerSearchModel="CustomerSearchModel" ModelEqualityComparer="ModelEqualityComparer!"
|
||||
ShowExtendEditButtonCallback="ShowExtendEditButtonCallback!" ShowExtendDeleteButtonCallback="ShowExtendDeleteButtonCallback!"
|
||||
DisableExtendEditButton="DisableExtendEditButton!" DisableExtendDeleteButton="DisableExtendDeleteButton!"
|
||||
DisableExtendEditButtonCallback="DisableExtendEditButtonCallback!" DisableExtendDeleteButtonCallback="DisableExtendDeleteButtonCallback!"
|
||||
|
||||
@@ -13,6 +13,24 @@ namespace ThingsGateway.Admin.Razor;
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
public partial class AdminTable<TItem> where TItem : class, new()
|
||||
{
|
||||
/// <inheritdoc cref="Table{TItem}.SelectedRowsChanged"/>
|
||||
[Parameter]
|
||||
public EventCallback<List<TItem>> SelectedRowsChanged { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.SelectedRows"/>
|
||||
[Parameter]
|
||||
public List<TItem> SelectedRows { get; set; } = new();
|
||||
|
||||
private async Task privateSelectedRowsChanged(List<TItem> items)
|
||||
{
|
||||
SelectedRows = items;
|
||||
if (SelectedRowsChanged.HasDelegate)
|
||||
await SelectedRowsChanged.InvokeAsync(items);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.DoubleClickToEdit"/>
|
||||
[Parameter]
|
||||
public bool DoubleClickToEdit { get; set; } = false;
|
||||
@@ -210,14 +228,6 @@ public partial class AdminTable<TItem> where TItem : class, new()
|
||||
[Parameter]
|
||||
public RenderFragment<TItem>? SearchTemplate { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.SelectedRows"/>
|
||||
[Parameter]
|
||||
public List<TItem>? SelectedRows { get; set; } = new List<TItem>();
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.SelectedRowsChanged"/>
|
||||
[Parameter]
|
||||
public EventCallback<List<TItem>> SelectedRowsChanged { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.SetRowClassFormatter"/>
|
||||
[Parameter]
|
||||
public Func<TItem, string?>? SetRowClassFormatter { get; set; }
|
||||
@@ -266,6 +276,15 @@ public partial class AdminTable<TItem> where TItem : class, new()
|
||||
[Parameter]
|
||||
public bool ShowExportButton { get; set; } = false;
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.DisableEditButtonCallback"/>
|
||||
public Func<List<TItem>, bool> DisableEditButtonCallback { get; set; } = (list) =>
|
||||
list.Count != 1;
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.DisableDeleteButtonCallback"/>
|
||||
[Parameter]
|
||||
public Func<List<TItem>, bool> DisableDeleteButtonCallback { get; set; } = (list) =>
|
||||
list.Count <= 0;
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.ShowExportCsvButton"/>
|
||||
[Parameter]
|
||||
public bool ShowExportCsvButton { get; set; } = false;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor.TableExport" Version="9.2.6" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
<PackageReference Include="BootstrapBlazor" Version="9.10.0" />
|
||||
<PackageReference Include="BootstrapBlazor" Version="9.10.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@namespace ThingsGateway.Razor
|
||||
@typeparam TItem
|
||||
|
||||
<Table TItem="TItem" IsBordered="true" IsStriped="true" IsMultipleSelect="IsMultipleSelect" @ref="Instance" TableSize=TableSize SearchTemplate=SearchTemplate
|
||||
<Table TItem="TItem" IsBordered="true" IsStriped="true" IsMultipleSelect="IsMultipleSelect" @ref="Instance" TableSize=TableSize SearchTemplate=SearchTemplate SelectedRows=SelectedRows SelectedRowsChanged=privateSelectedRowsChanged
|
||||
IsPagination="IsPagination" PageItemsSource="PageItemsSource" IsFixedHeader="IsFixedHeader" IndentSize=24 RowHeight=RowHeight ShowSearchText="ShowSearchText"
|
||||
IsTree="IsTree" OnTreeExpand="OnTreeExpand!" TreeNodeConverter="TreeNodeConverter!" TreeIcon="fa-solid fa-circle-chevron-right" TreeExpandIcon="fa-solid fa-circle-chevron-right fa-rotate-90" IsAutoQueryFirstRender=IsAutoQueryFirstRender
|
||||
ShowDefaultButtons="ShowDefaultButtons" ShowAdvancedSearch="ShowAdvancedSearch" ShowResetButton=ShowResetButton
|
||||
@@ -10,7 +10,7 @@
|
||||
ShowSkeleton="true" ShowLoading="ShowLoading" ShowSearch="ShowSearch" SearchModel=@SearchModel ShowLineNo
|
||||
SearchMode=SearchMode ShowExportPdfButton=ShowExportPdfButton
|
||||
ShowExportButton=@ShowExportButton Items=Items ClickToSelect=ClickToSelect ScrollMode=ScrollMode
|
||||
ShowExportCsvButton=@ShowExportCsvButton SelectedRowsChanged=SelectedRowsChanged ShowCardView=ShowCardView
|
||||
ShowExportCsvButton=@ShowExportCsvButton ShowCardView=ShowCardView
|
||||
FixedExtendButtonsColumn IsAutoRefresh=IsAutoRefresh AutoRefreshInterval=AutoRefreshInterval
|
||||
AllowDragColumn=@AllowDragColumn Height=@Height ShowRefresh=ShowRefresh
|
||||
AllowResizing=@AllowResizing ExportButtonDropdownTemplate=ExportButtonDropdownTemplate
|
||||
@@ -24,7 +24,7 @@
|
||||
ShowMultiFilterHeader=ShowMultiFilterHeader
|
||||
ShowFilterHeader=ShowFilterHeader
|
||||
ShowColumnList=ShowColumnList ExtendButtonColumnWidth="@ExtendButtonColumnWidth"
|
||||
CustomerSearchModel="CustomerSearchModel" SelectedRows="SelectedRows" ModelEqualityComparer="ModelEqualityComparer!"
|
||||
CustomerSearchModel="CustomerSearchModel" ModelEqualityComparer="ModelEqualityComparer!"
|
||||
ShowExtendEditButtonCallback="ShowExtendEditButtonCallback!" ShowExtendDeleteButtonCallback="ShowExtendDeleteButtonCallback!"
|
||||
DisableExtendEditButton="DisableExtendEditButton!" DisableExtendDeleteButton="DisableExtendDeleteButton!"
|
||||
DisableExtendEditButtonCallback="DisableExtendEditButtonCallback!" DisableExtendDeleteButtonCallback="DisableExtendDeleteButtonCallback!"
|
||||
|
||||
@@ -13,6 +13,23 @@ namespace ThingsGateway.Razor;
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
public partial class DefaultTable<TItem> where TItem : class, new()
|
||||
{
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.SelectedRowsChanged"/>
|
||||
[Parameter]
|
||||
public EventCallback<List<TItem>> SelectedRowsChanged { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.SelectedRows"/>
|
||||
[Parameter]
|
||||
public List<TItem> SelectedRows { get; set; } = new();
|
||||
|
||||
private async Task privateSelectedRowsChanged(List<TItem> items)
|
||||
{
|
||||
SelectedRows = items;
|
||||
if (SelectedRowsChanged.HasDelegate)
|
||||
await SelectedRowsChanged.InvokeAsync(items);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.AllowDragColumn"/>
|
||||
[Parameter]
|
||||
public bool AllowDragColumn { get; set; } = false;
|
||||
@@ -186,14 +203,6 @@ public partial class DefaultTable<TItem> where TItem : class, new()
|
||||
[Parameter]
|
||||
public RenderFragment<TItem>? SearchTemplate { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.SelectedRows"/>
|
||||
[Parameter]
|
||||
public List<TItem>? SelectedRows { get; set; } = new List<TItem>();
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.SelectedRowsChanged"/>
|
||||
[Parameter]
|
||||
public EventCallback<List<TItem>> SelectedRowsChanged { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Table{TItem}.SetRowClassFormatter"/>
|
||||
[Parameter]
|
||||
public Func<TItem, string?>? SetRowClassFormatter { get; set; }
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<PackageReference Include="CsvHelper" Version="33.1.0" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.1.9" />
|
||||
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="23.9.1" />
|
||||
<PackageReference Include="Oscar.Data.SqlClient" Version="4.2.23" />
|
||||
<PackageReference Include="Oscar.Data.SqlClient" Version="4.2.25" />
|
||||
<PackageReference Include="System.Data.Common" Version="4.3.0" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.1" />
|
||||
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<PluginVersion>10.11.34</PluginVersion>
|
||||
<ProPluginVersion>10.11.34</ProPluginVersion>
|
||||
<DefaultVersion>10.11.34</DefaultVersion>
|
||||
<AuthenticationVersion>10.11.4</AuthenticationVersion>
|
||||
<PluginVersion>10.11.42</PluginVersion>
|
||||
<ProPluginVersion>10.11.42</ProPluginVersion>
|
||||
<DefaultVersion>10.11.42</DefaultVersion>
|
||||
<AuthenticationVersion>10.11.5</AuthenticationVersion>
|
||||
<SourceGeneratorVersion>10.11.4</SourceGeneratorVersion>
|
||||
<NET8Version>8.0.20</NET8Version>
|
||||
<NET9Version>9.0.9</NET9Version>
|
||||
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
|
||||
<IsTrimmable>false</IsTrimmable>
|
||||
<ManagementProPluginVersion>10.11.22</ManagementProPluginVersion>
|
||||
<ManagementPluginVersion>10.11.22</ManagementPluginVersion>
|
||||
<ManagementProPluginVersion>10.11.36</ManagementProPluginVersion>
|
||||
<ManagementPluginVersion>10.11.36</ManagementPluginVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -37,6 +37,7 @@ public static class ChannelOptionsExtensions
|
||||
for (int i = 0; i < funcs.Count; i++)
|
||||
{
|
||||
var func = funcs[i];
|
||||
if (func == null) continue;
|
||||
await func.Invoke(clientChannel, e, i == funcs.Count - 1).ConfigureAwait(false);
|
||||
if (e.Handled)
|
||||
{
|
||||
@@ -65,6 +66,7 @@ public static class ChannelOptionsExtensions
|
||||
for (int i = 0; i < funcs.Count; i++)
|
||||
{
|
||||
var func = funcs[i];
|
||||
if (func == null) continue;
|
||||
var handled = await func.Invoke(clientChannel, i == funcs.Count - 1).ConfigureAwait(false);
|
||||
if (handled)
|
||||
{
|
||||
@@ -99,16 +101,16 @@ public static class ChannelOptionsExtensions
|
||||
switch (channelType)
|
||||
{
|
||||
case ChannelTypeEnum.TcpClient:
|
||||
return config.GetTcpClientWithIPHost(channelOptions);
|
||||
return config.GetTcpClient(channelOptions);
|
||||
|
||||
case ChannelTypeEnum.TcpService:
|
||||
return config.GetTcpServiceWithBindIPHost(channelOptions);
|
||||
return config.GetTcpService(channelOptions);
|
||||
|
||||
case ChannelTypeEnum.SerialPort:
|
||||
return config.GetSerialPortWithOption(channelOptions);
|
||||
return config.GetSerialPort(channelOptions);
|
||||
|
||||
case ChannelTypeEnum.UdpSession:
|
||||
return config.GetUdpSessionWithIPHost(channelOptions);
|
||||
return config.GetUdpSession(channelOptions);
|
||||
case ChannelTypeEnum.Other:
|
||||
channelOptions.Config = config;
|
||||
OtherChannel otherChannel = new OtherChannel(channelOptions);
|
||||
@@ -123,13 +125,12 @@ public static class ChannelOptionsExtensions
|
||||
/// <param name="config">配置</param>
|
||||
/// <param name="channelOptions">串口配置</param>
|
||||
/// <returns></returns>
|
||||
public static SerialPortChannel GetSerialPortWithOption(this TouchSocketConfig config, IChannelOptions channelOptions)
|
||||
public static SerialPortChannel GetSerialPort(this TouchSocketConfig config, IChannelOptions channelOptions)
|
||||
{
|
||||
var serialPortOption = channelOptions.Map<SerialPortOption>();
|
||||
serialPortOption.ThrowIfNull(nameof(SerialPortOption));
|
||||
channelOptions.Config = config;
|
||||
config.SetSerialPortOption(serialPortOption);
|
||||
|
||||
//载入配置
|
||||
SerialPortChannel serialPortChannel = new SerialPortChannel(channelOptions);
|
||||
return serialPortChannel;
|
||||
@@ -142,7 +143,7 @@ public static class ChannelOptionsExtensions
|
||||
/// <param name="channelOptions">通道配置</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static TcpClientChannel GetTcpClientWithIPHost(this TouchSocketConfig config, IChannelOptions channelOptions)
|
||||
public static TcpClientChannel GetTcpClient(this TouchSocketConfig config, IChannelOptions channelOptions)
|
||||
{
|
||||
var remoteUrl = channelOptions.RemoteUrl;
|
||||
var bindUrl = channelOptions.BindUrl;
|
||||
@@ -164,7 +165,7 @@ public static class ChannelOptionsExtensions
|
||||
/// <param name="channelOptions">通道配置</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static IChannel GetTcpServiceWithBindIPHost(this TouchSocketConfig config, IChannelOptions channelOptions)
|
||||
public static IChannel GetTcpService(this TouchSocketConfig config, IChannelOptions channelOptions)
|
||||
{
|
||||
var bindUrl = channelOptions.BindUrl;
|
||||
bindUrl.ThrowIfNull(nameof(bindUrl));
|
||||
@@ -192,7 +193,7 @@ public static class ChannelOptionsExtensions
|
||||
/// <param name="channelOptions">通道配置</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static UdpSessionChannel GetUdpSessionWithIPHost(this TouchSocketConfig config, IChannelOptions channelOptions)
|
||||
public static UdpSessionChannel GetUdpSession(this TouchSocketConfig config, IChannelOptions channelOptions)
|
||||
{
|
||||
var remoteUrl = channelOptions.RemoteUrl;
|
||||
var bindUrl = channelOptions.BindUrl;
|
||||
|
||||
@@ -19,6 +19,11 @@ namespace ThingsGateway.Foundation;
|
||||
/// </summary>
|
||||
public class OtherChannel : SetupConfigObject, IClientChannel
|
||||
{
|
||||
~OtherChannel()
|
||||
{
|
||||
this.SafeDispose();
|
||||
}
|
||||
|
||||
private SingleStreamDataHandlingAdapter m_dataHandlingAdapter;
|
||||
public DataHandlingAdapter ReadOnlyDataHandlingAdapter => m_dataHandlingAdapter;
|
||||
|
||||
|
||||
@@ -19,6 +19,10 @@ namespace ThingsGateway.Foundation;
|
||||
/// </summary>
|
||||
public class SerialPortChannel : SerialPortClient, IClientChannel
|
||||
{
|
||||
~SerialPortChannel()
|
||||
{
|
||||
this.SafeDispose();
|
||||
}
|
||||
public SerialPortChannel(IChannelOptions channelOptions)
|
||||
{
|
||||
ChannelOptions = channelOptions;
|
||||
|
||||
@@ -17,6 +17,10 @@ namespace ThingsGateway.Foundation;
|
||||
/// </summary>
|
||||
public class TcpClientChannel : TcpClient, IClientChannel
|
||||
{
|
||||
~TcpClientChannel()
|
||||
{
|
||||
this.SafeDispose();
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public TcpClientChannel(IChannelOptions channelOptions)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,11 @@ namespace ThingsGateway.Foundation;
|
||||
/// <typeparam name="TClient"></typeparam>
|
||||
public abstract class TcpServiceChannelBase<TClient> : TcpService<TClient>, ITcpService<TClient> where TClient : TcpSessionClientChannel, new()
|
||||
{
|
||||
|
||||
~TcpServiceChannelBase()
|
||||
{
|
||||
this.SafeDispose();
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentList<IDevice> Collects { get; } = new();
|
||||
|
||||
|
||||
@@ -17,6 +17,10 @@ namespace ThingsGateway.Foundation;
|
||||
/// </summary>
|
||||
public class TcpSessionClientChannel : TcpSessionClient, IClientChannel
|
||||
{
|
||||
~TcpSessionClientChannel()
|
||||
{
|
||||
this.SafeDispose();
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public TcpSessionClientChannel()
|
||||
{
|
||||
|
||||
@@ -17,6 +17,10 @@ namespace ThingsGateway.Foundation;
|
||||
/// </summary>
|
||||
public class UdpSessionChannel : UdpSession, IClientChannel
|
||||
{
|
||||
~UdpSessionChannel()
|
||||
{
|
||||
this.SafeDispose();
|
||||
}
|
||||
private readonly WaitLock _connectLock = new WaitLock(nameof(UdpSessionChannel));
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -629,7 +629,7 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
|
||||
DataTypeEnum.UInt32 => await ReadUInt32Async(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Int64 => await ReadInt64Async(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.UInt64 => await ReadUInt64Async(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Single => await ReadSingleAsync(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Float => await ReadSingleAsync(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Double => await ReadDoubleAsync(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Decimal => await ReadDecimalAsync(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
_ => new OperResult<Array>(string.Format(AppResource.DataTypeNotSupported, dataType)),
|
||||
@@ -655,7 +655,7 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
|
||||
DataTypeEnum.UInt32 => await WriteAsync(address, jArray.ToObject<UInt32[]>().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Int64 => await WriteAsync(address, jArray.ToObject<Int64[]>().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.UInt64 => await WriteAsync(address, jArray.ToObject<UInt64[]>().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Single => await WriteAsync(address, jArray.ToObject<Single[]>().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Float => await WriteAsync(address, jArray.ToObject<Single[]>().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Double => await WriteAsync(address, jArray.ToObject<Double[]>().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Decimal => await WriteAsync(address, jArray.ToObject<Decimal[]>().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
|
||||
_ => new OperResult(string.Format(AppResource.DataTypeNotSupported, dataType)),
|
||||
@@ -674,7 +674,7 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
|
||||
DataTypeEnum.UInt32 => await WriteAsync(address, value.ToObject<UInt32>(), bitConverter, cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Int64 => await WriteAsync(address, value.ToObject<Int64>(), bitConverter, cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.UInt64 => await WriteAsync(address, value.ToObject<UInt64>(), bitConverter, cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Single => await WriteAsync(address, value.ToObject<Single>(), bitConverter, cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Float => await WriteAsync(address, value.ToObject<Single>(), bitConverter, cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Double => await WriteAsync(address, value.ToObject<Double>(), bitConverter, cancellationToken).ConfigureAwait(false),
|
||||
DataTypeEnum.Decimal => await WriteAsync(address, value.ToObject<Decimal>(), bitConverter, cancellationToken).ConfigureAwait(false),
|
||||
_ => new OperResult(string.Format(AppResource.DataTypeNotSupported, dataType)),
|
||||
@@ -864,7 +864,7 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
|
||||
public virtual ValueTask<OperResult> WriteAsync(string address, float value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
|
||||
return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.Single, cancellationToken);
|
||||
return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.Float, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -937,7 +937,7 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
|
||||
public virtual ValueTask<OperResult> WriteAsync(string address, ReadOnlyMemory<float> value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
|
||||
return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.Single, cancellationToken);
|
||||
return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.Float, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -45,12 +45,16 @@ public enum DataTypeEnum
|
||||
/// <inheritdoc/>
|
||||
UInt64,
|
||||
|
||||
/// <inheritdoc/>
|
||||
Single,
|
||||
/// <summary>
|
||||
/// 大部分人并不认识Single,但都认识Float
|
||||
/// </summary>
|
||||
Float,
|
||||
|
||||
/// <inheritdoc/>
|
||||
Double,
|
||||
|
||||
/// <inheritdoc/>
|
||||
Decimal,
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public static class DataTypeExtensions
|
||||
DataTypeEnum.UInt32 => 4,
|
||||
DataTypeEnum.Int64 => 8,
|
||||
DataTypeEnum.UInt64 => 8,
|
||||
DataTypeEnum.Single => 4,
|
||||
DataTypeEnum.Float => 4,
|
||||
DataTypeEnum.Double => 8,
|
||||
DataTypeEnum.Decimal => 16,
|
||||
_ => 0,
|
||||
@@ -57,7 +57,7 @@ public static class DataTypeExtensions
|
||||
TypeCode.UInt32 => DataTypeEnum.UInt32,
|
||||
TypeCode.Int64 => DataTypeEnum.Int64,
|
||||
TypeCode.UInt64 => DataTypeEnum.UInt64,
|
||||
TypeCode.Single => DataTypeEnum.Single,
|
||||
TypeCode.Single => DataTypeEnum.Float,
|
||||
TypeCode.Double => DataTypeEnum.Double,
|
||||
TypeCode.Decimal => DataTypeEnum.Decimal,
|
||||
_ => DataTypeEnum.Object,
|
||||
@@ -82,7 +82,7 @@ public static class DataTypeExtensions
|
||||
DataTypeEnum.UInt32 => typeof(uint),
|
||||
DataTypeEnum.Int64 => typeof(long),
|
||||
DataTypeEnum.UInt64 => typeof(ulong),
|
||||
DataTypeEnum.Single => typeof(float),
|
||||
DataTypeEnum.Float => typeof(float),
|
||||
DataTypeEnum.Double => typeof(double),
|
||||
DataTypeEnum.Decimal => typeof(decimal),
|
||||
_ => typeof(object),
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="$(NET9Version)" />
|
||||
<PackageReference Include="TouchSocket" Version="4.0.0-beta.25" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="4.0.0-beta.25" />
|
||||
<PackageReference Include="TouchSocket" Version="4.0.0-beta.27" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="4.0.0-beta.27" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -56,7 +56,7 @@ public static class ThingsGatewayBitConverterExtension
|
||||
case DataTypeEnum.UInt64:
|
||||
return byteConverter.GetBytes(value.ToObject<UInt64[]>());
|
||||
|
||||
case DataTypeEnum.Single:
|
||||
case DataTypeEnum.Float:
|
||||
return byteConverter.GetBytes(value.ToObject<Single[]>());
|
||||
|
||||
case DataTypeEnum.Double:
|
||||
@@ -107,7 +107,7 @@ public static class ThingsGatewayBitConverterExtension
|
||||
case DataTypeEnum.UInt64:
|
||||
return byteConverter.GetBytes(value.ToObject<UInt64>());
|
||||
|
||||
case DataTypeEnum.Single:
|
||||
case DataTypeEnum.Float:
|
||||
return byteConverter.GetBytes(value.ToObject<Single>());
|
||||
|
||||
case DataTypeEnum.Double:
|
||||
@@ -333,7 +333,7 @@ public static class ThingsGatewayBitConverterExtension
|
||||
return true;
|
||||
}
|
||||
|
||||
case DataTypeEnum.Single:
|
||||
case DataTypeEnum.Float:
|
||||
if (arrayLength > 1)
|
||||
{
|
||||
var newVal = byteConverter.ToSingle(buffer, index, arrayLength);
|
||||
|
||||
@@ -55,7 +55,15 @@ public abstract partial class CollectBase : DriverBase
|
||||
/// 特殊方法
|
||||
/// </summary>
|
||||
public List<DriverMethodInfo>? DriverMethodInfos { get; private set; }
|
||||
|
||||
protected virtual bool IsRuntimeSourceValid(VariableRuntime a)
|
||||
{
|
||||
//筛选特殊变量地址
|
||||
//1、DeviceStatus
|
||||
return !a.RegisterAddress.Equals(nameof(DeviceRuntime.DeviceStatus), StringComparison.OrdinalIgnoreCase) &&
|
||||
!a.RegisterAddress.Equals("Script", StringComparison.OrdinalIgnoreCase) &&
|
||||
!a.RegisterAddress.Equals("ScriptRead", StringComparison.OrdinalIgnoreCase)
|
||||
;
|
||||
}
|
||||
public override async Task AfterVariablesChangedAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
LogMessage?.LogInformation("Refresh variable");
|
||||
@@ -84,21 +92,13 @@ public abstract partial class CollectBase : DriverBase
|
||||
&& string.IsNullOrEmpty(it.OtherMethod)
|
||||
&& !string.IsNullOrEmpty(it.RegisterAddress));
|
||||
|
||||
//筛选特殊变量地址
|
||||
//1、DeviceStatus
|
||||
Func<VariableRuntime, bool> source = (a =>
|
||||
{
|
||||
return !a.RegisterAddress.Equals(nameof(DeviceRuntime.DeviceStatus), StringComparison.OrdinalIgnoreCase) &&
|
||||
!a.RegisterAddress.Equals("Script", StringComparison.OrdinalIgnoreCase) &&
|
||||
!a.RegisterAddress.Equals("ScriptRead", StringComparison.OrdinalIgnoreCase)
|
||||
;
|
||||
});
|
||||
|
||||
var now = DateTime.Now;
|
||||
#pragma warning disable CA1851
|
||||
try
|
||||
{
|
||||
|
||||
currentDevice.VariableScriptReads = tags.Where(a => !source(a)).Select(a =>
|
||||
currentDevice.VariableScriptReads = tags.Where(a => !IsRuntimeSourceValid(a)).Select(a =>
|
||||
{
|
||||
var data = new VariableScriptRead();
|
||||
data.VariableRuntime = a;
|
||||
@@ -111,9 +111,9 @@ public abstract partial class CollectBase : DriverBase
|
||||
// 如果出现异常,记录日志并初始化 VariableSourceReads 属性为新实例
|
||||
currentDevice.VariableScriptReads = new();
|
||||
LogMessage?.LogWarning(ex, string.Format(AppResource.VariablePackError, ex.Message));
|
||||
tags.Where(a => !source(a)).ForEach(a => a.SetValue(null, now, isOnline: false));
|
||||
tags.Where(a => !IsRuntimeSourceValid(a)).ForEach(a => a.SetValue(null, now, isOnline: false));
|
||||
}
|
||||
var variableReads = tags.Where(source).ToList();
|
||||
var variableReads = tags.Where(IsRuntimeSourceValid).ToList();
|
||||
try
|
||||
{
|
||||
// 将打包后的结果存储在当前设备的 VariableSourceReads 属性中
|
||||
@@ -482,6 +482,7 @@ public abstract partial class CollectBase : DriverBase
|
||||
|
||||
protected virtual Task TestOnline(object? state, CancellationToken cancellationToken)
|
||||
{
|
||||
CurrentDevice.SetDeviceStatus(TimerX.Now, false, null);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://thingsgateway.cn/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ThingsGateway.Gateway.Application;
|
||||
|
||||
/// <summary>
|
||||
/// 插件配置项
|
||||
/// <br></br>
|
||||
/// 使用<see cref="DynamicPropertyAttribute"/> 标识所需的配置属性
|
||||
/// </summary>
|
||||
public class MempryDevicePropertyBase : CollectPropertyBase
|
||||
{
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// <para></para>
|
||||
/// 采集插件,继承实现不同PLC通讯
|
||||
/// <para></para>
|
||||
/// </summary>
|
||||
public class MempryDevice : CollectBase
|
||||
{
|
||||
private MempryDevicePropertyBase _driverPropertyBase = new MempryDevicePropertyBase();
|
||||
public override CollectPropertyBase CollectProperties => _driverPropertyBase;
|
||||
|
||||
#if !Management
|
||||
|
||||
/// <summary>
|
||||
/// 是否连接成功
|
||||
/// </summary>
|
||||
public override bool IsConnected()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override Task<List<VariableSourceRead>> ProtectedLoadSourceReadAsync(List<VariableRuntime> deviceVariables)
|
||||
{
|
||||
return Task.FromResult(new List<VariableSourceRead>());
|
||||
}
|
||||
|
||||
protected override bool IsRuntimeSourceValid(VariableRuntime a)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -409,7 +409,7 @@ internal sealed class DeviceThreadManage : IAsyncDisposable, IDeviceThreadManage
|
||||
// 查找具有指定设备ID的驱动程序对象
|
||||
if (Drivers.TryRemove(deviceId, out var driver))
|
||||
{
|
||||
driver.CurrentDevice.SetDeviceStatus(now, false, "Communication connection has been removed");
|
||||
driver.CurrentDevice.SetDeviceStatus(now, true, "Communication connection has been removed");
|
||||
if (IsCollectChannel == true)
|
||||
{
|
||||
foreach (var a in driver.IdVariableRuntimes)
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="5.0.1" />
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.3" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="4.0.0-beta.25" />
|
||||
<!--<PackageReference Include="TouchSocket.WebApi.Swagger" Version="4.0.0-beta.25" />-->
|
||||
<PackageReference Include="TouchSocket.WebApi" Version="4.0.0-beta.25" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="4.0.0-beta.27" />
|
||||
<!--<PackageReference Include="TouchSocket.WebApi.Swagger" Version="4.0.0-beta.27" />-->
|
||||
<PackageReference Include="TouchSocket.WebApi" Version="4.0.0-beta.27" />
|
||||
<PackageReference Include="ThingsGateway.Authentication" Version="$(AuthenticationVersion)" />
|
||||
<!--<ProjectReference Include="..\..\PluginPro\ThingsGateway.Authentication\ThingsGateway.Authentication.csproj" />-->
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
}
|
||||
/*切换高度*/
|
||||
.quickactions-list.is-open {
|
||||
height: 300px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.quickactions-header {
|
||||
|
||||
@@ -76,18 +76,34 @@ public partial class DeviceRuntimeInfo1 : IDisposable
|
||||
{
|
||||
return;
|
||||
}
|
||||
await DialogService.Show(new DialogOption()
|
||||
{
|
||||
IsScrolling = false,
|
||||
ShowMaximizeButton = true,
|
||||
Size = Size.ExtraExtraLarge,
|
||||
Title = DeviceRuntime.Name,
|
||||
Component = BootstrapDynamicComponent.CreateComponent(driver, new Dictionary<string, object?>()
|
||||
var renderFragment = BootstrapDynamicComponent.CreateComponent(driver, new Dictionary<string, object?>()
|
||||
{
|
||||
{nameof(IDriverUIBase.Driver),DeviceRuntime.Driver},
|
||||
})
|
||||
});
|
||||
}).Render();
|
||||
if (renderFragment != null)
|
||||
{
|
||||
var option = new WinBoxOption()
|
||||
{
|
||||
Title = DeviceRuntime.Name,
|
||||
ContentTemplate = renderFragment,
|
||||
Max = false,
|
||||
Width = "80%",
|
||||
Height = "80%",
|
||||
Top = "0%",
|
||||
Left = "10%",
|
||||
Background = "var(--bb-primary-color)",
|
||||
Overflow = true
|
||||
};
|
||||
await WinBoxService.Show(option);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private WinBoxService? WinBoxService { get; set; }
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
[Inject]
|
||||
|
||||
@@ -48,8 +48,22 @@ public partial class GatewayMonitorPage
|
||||
}
|
||||
else
|
||||
{
|
||||
VariableRuntimes = deviceRuntime.Driver?.IdVariableRuntimes?.Where(a => a.Value != null)
|
||||
if (deviceRuntime.Driver == null)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(2000);
|
||||
VariableRuntimes = deviceRuntime.Driver?.IdVariableRuntimes?.Where(a => a.Value != null)
|
||||
.Select(a => a.Value) ?? Enumerable.Empty<VariableRuntime>();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
VariableRuntimes = deviceRuntime.Driver?.IdVariableRuntimes?.Where(a => a.Value != null)
|
||||
.Select(a => a.Value) ?? Enumerable.Empty<VariableRuntime>();
|
||||
}
|
||||
|
||||
}
|
||||
ChannelRuntimes = Enumerable.Repeat(deviceRuntime.ChannelRuntime, 1);
|
||||
DeviceRuntimes = Enumerable.Repeat(deviceRuntime, 1);
|
||||
|
||||
@@ -28,15 +28,7 @@ public partial class VariableRuntimeInfo : IDisposable
|
||||
|
||||
[Parameter]
|
||||
public IEnumerable<VariableRuntime>? Items { get; set; } = Enumerable.Empty<VariableRuntime>();
|
||||
private IEnumerable<VariableRuntime>? _previousItemsRef;
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (!ReferenceEquals(_previousItemsRef, Items))
|
||||
{
|
||||
_previousItemsRef = Items;
|
||||
await Refresh(null);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
private static void BeforeShowEditDialogCallback(ITableEditDialogOption<VariableRuntime> tableEditDialogOption)
|
||||
|
||||
@@ -13,7 +13,11 @@ using BenchmarkConsoleApp;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Diagnosers;
|
||||
|
||||
using HslCommunication.ModBus;
|
||||
|
||||
using Longbow.Modbus;
|
||||
using Longbow.TcpSocket;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using System.IO.Pipelines;
|
||||
using System.Net.Sockets;
|
||||
@@ -31,9 +35,10 @@ namespace ThingsGateway.Foundation;
|
||||
[MemoryDiagnoser]
|
||||
public class ModbusBenchmark : IDisposable
|
||||
{
|
||||
private readonly List<IModbusClient> _lgbModbusClients = [];
|
||||
private List<ModbusMaster> thingsgatewaymodbuss = new();
|
||||
private List<IModbusMaster> nmodbuss = new();
|
||||
private List<ModbusTcpNet> modbusTcpNets = new();
|
||||
//private List<ModbusTcpNet> modbusTcpNets = new();
|
||||
private List<ModbusTcpMaster> modbusTcpMasters = new();
|
||||
private PipeOptions GetNoDelayPipeOptions()
|
||||
{
|
||||
@@ -54,7 +59,7 @@ public class ModbusBenchmark : IDisposable
|
||||
// ReceivePipeOptions = GetNoDelayPipeOptions(),
|
||||
// SendPipeOptions = GetNoDelayPipeOptions(),
|
||||
//}).SetNoDelay(true);
|
||||
var clientChannel = clientConfig.GetTcpClientWithIPHost(new ChannelOptions() { RemoteUrl = "127.0.0.1:502", MaxConcurrentCount = 10 });
|
||||
var clientChannel = clientConfig.GetTcpClient(new ChannelOptions() { RemoteUrl = "127.0.0.1:502", MaxConcurrentCount = 10 });
|
||||
var thingsgatewaymodbus = new ModbusMaster()
|
||||
{
|
||||
//modbus协议格式
|
||||
@@ -77,15 +82,15 @@ public class ModbusBenchmark : IDisposable
|
||||
nmodbus.ReadHoldingRegistersAsync(1, 0, 100).GetFalseAwaitResult();
|
||||
nmodbuss.Add(nmodbus);
|
||||
}
|
||||
for (int i = 0; i < Program.ClientCount; i++)
|
||||
{
|
||||
ModbusTcpNet modbusTcpNet = new();
|
||||
modbusTcpNet.IpAddress = "127.0.0.1";
|
||||
modbusTcpNet.Port = 502;
|
||||
modbusTcpNet.ConnectServer();
|
||||
modbusTcpNet.ReadAsync("0", 100).GetFalseAwaitResult();
|
||||
modbusTcpNets.Add(modbusTcpNet);
|
||||
}
|
||||
//for (int i = 0; i < Program.ClientCount; i++)
|
||||
//{
|
||||
// ModbusTcpNet modbusTcpNet = new();
|
||||
// modbusTcpNet.IpAddress = "127.0.0.1";
|
||||
// modbusTcpNet.Port = 502;
|
||||
// modbusTcpNet.ConnectServer();
|
||||
// modbusTcpNet.ReadAsync("0", 100).GetFalseAwaitResult();
|
||||
// modbusTcpNets.Add(modbusTcpNet);
|
||||
//}
|
||||
|
||||
for (int i = 0; i < Program.ClientCount; i++)
|
||||
{
|
||||
@@ -96,12 +101,50 @@ public class ModbusBenchmark : IDisposable
|
||||
client.ReadHoldingRegistersAsync(0, 100).GetFalseAwaitResult();
|
||||
modbusTcpMasters.Add(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
var sc = new ServiceCollection();
|
||||
sc.AddTcpSocketFactory();
|
||||
sc.AddModbusFactory();
|
||||
|
||||
var provider = sc.BuildServiceProvider();
|
||||
var factory = provider.GetRequiredService<IModbusFactory>();
|
||||
|
||||
for (int i = 0; i < Program.ClientCount; i++)
|
||||
{
|
||||
var client = factory.GetOrCreateTcpMaster();
|
||||
client.ConnectAsync("127.0.0.1", 502).GetAwaiter().GetResult();
|
||||
client.ReadHoldingRegistersAsync(0x01, 0x00, 10).GetAwaiter().GetResult();
|
||||
|
||||
_lgbModbusClients.Add(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
[Benchmark]
|
||||
public async Task LongbowModbus()
|
||||
{
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (var _lgbModbusClient in _lgbModbusClients)
|
||||
{
|
||||
|
||||
for (int i = 0; i < Program.TaskNumberOfItems; i++)
|
||||
{
|
||||
tasks.Add(Task.Run(async () =>
|
||||
{
|
||||
for (int i = 0; i < Program.NumberOfItems; i++)
|
||||
{
|
||||
var task = await _lgbModbusClient.ReadHoldingRegistersAsync(1, 0, 100);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
[Benchmark]
|
||||
public async Task ThingsGateway()
|
||||
{
|
||||
ModbusAddress addr = new ModbusAddress() { FunctionCode = 3, StartAddress = 0, Length = 100 };
|
||||
//ModbusAddress addr = new ModbusAddress() { FunctionCode = 3, StartAddress = 0, Length = 100 };
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (var thingsgatewaymodbus in thingsgatewaymodbuss)
|
||||
{
|
||||
@@ -112,11 +155,12 @@ public class ModbusBenchmark : IDisposable
|
||||
{
|
||||
for (int i = 0; i < Program.NumberOfItems; i++)
|
||||
{
|
||||
var result = await thingsgatewaymodbus.ModbusReadAsync(addr);
|
||||
var result = await thingsgatewaymodbus.ModbusReadAsync(new ModbusAddress() { FunctionCode = 3, StartAddress = 0, Length = 100 });
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
throw new Exception(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + result.ToString());
|
||||
}
|
||||
var data = TouchSocketBitConverter.ConvertValues<byte, ushort>(result.Content.Span, EndianType.Little);
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -139,6 +183,7 @@ public class ModbusBenchmark : IDisposable
|
||||
for (int i = 0; i < Program.NumberOfItems; i++)
|
||||
{
|
||||
var result = await modbusTcpMaster.ReadHoldingRegistersAsync(0, 100);
|
||||
var data = TouchSocketBitConverter.ConvertValues<byte, ushort>(result.Data.Span, EndianType.Little);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
throw new Exception(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + result.ToString());
|
||||
@@ -199,9 +244,12 @@ public class ModbusBenchmark : IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
thingsgatewaymodbuss?.ForEach(a => a.Channel.SafeDispose());
|
||||
thingsgatewaymodbuss?.ForEach(a => a.SafeDispose());
|
||||
nmodbuss?.ForEach(a => a.SafeDispose());
|
||||
modbusTcpNets?.ForEach(a => a.SafeDispose());
|
||||
//modbusTcpNets?.ForEach(a => a.SafeDispose());
|
||||
_lgbModbusClients?.ForEach(a => a.DisposeAsync().GetAwaiter().GetResult());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class S7Benchmark : IDisposable
|
||||
ReceivePipeOptions = GetNoDelayPipeOptions(),
|
||||
SendPipeOptions = GetNoDelayPipeOptions(),
|
||||
}).SetNoDelay(true);
|
||||
var clientChannel = clientConfig.GetTcpClientWithIPHost(new ChannelOptions() { RemoteUrl = "127.0.0.1:102" });
|
||||
var clientChannel = clientConfig.GetTcpClient(new ChannelOptions() { RemoteUrl = "127.0.0.1:102" });
|
||||
var siemensS7 = new SiemensS7Master()
|
||||
{
|
||||
//modbus协议格式
|
||||
|
||||
@@ -49,10 +49,10 @@ namespace BenchmarkConsoleApp
|
||||
ManualConfig.Create(DefaultConfig.Instance)
|
||||
.WithOptions(ConfigOptions.DisableOptimizationsValidator)
|
||||
);
|
||||
// BenchmarkRunner.Run<S7Benchmark>(
|
||||
//ManualConfig.Create(DefaultConfig.Instance)
|
||||
//.WithOptions(ConfigOptions.DisableOptimizationsValidator)
|
||||
//);
|
||||
// BenchmarkRunner.Run<S7Benchmark>(
|
||||
//ManualConfig.Create(DefaultConfig.Instance)
|
||||
//.WithOptions(ConfigOptions.DisableOptimizationsValidator)
|
||||
//);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,13 +42,14 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.15.2" />
|
||||
<PackageReference Include="HslCommunication" Version="12.3.3" />
|
||||
<PackageReference Include="HslCommunication" Version="12.5.0" />
|
||||
<PackageReference Include="Longbow.Modbus" Version="9.0.4" />
|
||||
<PackageReference Include="NModbus" Version="3.0.81" />
|
||||
<PackageReference Include="NModbus.Serial" Version="3.0.81" />
|
||||
<PackageReference Include="S7netplus" Version="0.20.0" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="10.11.33" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.SiemensS7" Version="10.11.33" />
|
||||
<PackageReference Include="TouchSocket.Modbus" Version="4.0.0-beta.25" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="$(DefaultVersion)" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.SiemensS7" Version="$(DefaultVersion)" />
|
||||
<PackageReference Include="TouchSocket.Modbus" Version="4.0.0-beta.27" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -186,7 +186,7 @@ public class Dlt645_2007Send : ISendMessage
|
||||
}
|
||||
|
||||
var lenSpan = writerLenAnchor.Rewind(ref byteBlock, out var length);
|
||||
lenSpan.WriteValue<byte>((byte)(length - 1));//数据域长度
|
||||
lenSpan.WriteValue<byte>((byte)(length));//数据域长度
|
||||
|
||||
int num = 0;
|
||||
for (int index = 0; index < byteBlock.WrittenCount - SendHeadCodeIndex; ++index)
|
||||
|
||||
@@ -69,7 +69,6 @@ public class ModbusRtuSend : ISendMessage
|
||||
else if (wf == 15 || wf == 16)
|
||||
{
|
||||
var data = ModbusAddress.MasterWriteDatas.ArrayExpandToLengthEven().Span;
|
||||
WriterExtension.WriteValue(ref byteBlock, (ushort)(data.Length + 7), EndianType.Big);
|
||||
WriterExtension.WriteValue(ref byteBlock, (byte)ModbusAddress.Station);
|
||||
WriterExtension.WriteValue(ref byteBlock, (byte)ModbusAddress.WriteFunctionCode);
|
||||
WriterExtension.WriteValue(ref byteBlock, (ushort)ModbusAddress.StartAddress, EndianType.Big);
|
||||
|
||||
@@ -126,7 +126,7 @@ public partial class MainLayout : IDisposable
|
||||
if (context is TabItem tabItem)
|
||||
{
|
||||
await WinboxRender(tabItem.ChildContent, tabItem.Text);
|
||||
await _tab.RemoveTab(tabItem);
|
||||
//await _tab.RemoveTab(tabItem);
|
||||
}
|
||||
}
|
||||
[Inject]
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
<!--<Import Project="targets\Pro3.targets" Condition=" '$(SolutionName)' == 'ThingsGatewayPro' " />
|
||||
<Import Project="targets\Pro5.targets" Condition=" '$(SolutionName)' == 'ThingsGatewayPro' " />-->
|
||||
<!--<Import Project="targets\Pro6.targets" Condition=" '$(SolutionName)' == 'ThingsGatewayPro' AND '$(Configuration)' != 'Debug'" />-->
|
||||
<Import Project="targets\Pro7.targets" Condition=" '$(SolutionName)' == 'ThingsGatewayPro' AND '$(Configuration)' != 'Debug'" />
|
||||
<!--nuget包解压复制文件,上下文动态加载,Pro插件-->
|
||||
<Import Project="targets\Pro7.targets" Condition=" '$(SolutionName)' != 'ThingsGatewayPro' OR '$(Configuration)' != 'Debug'" />
|
||||
|
||||
<!--打包复制-->
|
||||
<Import Project="targets\PluginPublish.targets" />
|
||||
|
||||
Reference in New Issue
Block a user