release:6.0.3.38

This commit is contained in:
Diego2098
2024-06-23 00:01:26 +08:00
parent 711dfd4da9
commit cab082166b
24 changed files with 464 additions and 259 deletions

View File

@@ -8,7 +8,9 @@
// QQ群605534569
//------------------------------------------------------------------------------
using HslCommunication.ModBus;
using BenchmarkConsoleApp;
using BenchmarkDotNet.Attributes;
using ThingsGateway.Foundation.Modbus;
@@ -23,12 +25,9 @@ namespace ThingsGateway.Foundation;
public class ModbusCompare : IDisposable
{
public static int TaskNumberOfItems = 100;
public static int NumberOfItems = 100;
private ModbusMaster thingsgatewaymodbus;
private IModbusMaster nmodbus;
private ModbusTcpMaster modbusTcpMaster;
private ModbusTcpNet hslmodbus;
public ModbusCompare()
{
@@ -51,18 +50,17 @@ public class ModbusCompare : IDisposable
TcpClient client = new TcpClient("127.0.0.1", 502);
var factory = new NModbus.ModbusFactory();
nmodbus = factory.CreateMaster(client);
hslmodbus = new("127.0.0.1");
hslmodbus.ConnectServer();
}
[Benchmark]
public async Task TouchSocket()
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < TaskNumberOfItems; i++)
for (int i = 0; i < Program.TaskNumberOfItems; i++)
{
tasks.Add(Task.Run(async () =>
{
for (int i = 0; i < NumberOfItems; i++)
for (int i = 0; i < Program.NumberOfItems; i++)
{
var result = await modbusTcpMaster.ReadHoldingRegistersAsync(1, 0, 100, 3000, CancellationToken.None);
}
@@ -72,14 +70,15 @@ public class ModbusCompare : IDisposable
await Task.WhenAll(tasks);
}
[Benchmark]
public async Task ThingsGateway()
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < TaskNumberOfItems; i++)
for (int i = 0; i < Program.TaskNumberOfItems; i++)
{
tasks.Add(Task.Run(async () =>
{
for (int i = 0; i < NumberOfItems; i++)
for (int i = 0; i < Program.NumberOfItems; i++)
{
var result = await thingsgatewaymodbus.ReadAsync("40001", 100);
if (!result.IsSuccess)
@@ -92,14 +91,15 @@ public class ModbusCompare : IDisposable
await Task.WhenAll(tasks);
}
[Benchmark]
public async Task NModbus4()
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < TaskNumberOfItems; i++)
for (int i = 0; i < Program.TaskNumberOfItems; i++)
{
tasks.Add(Task.Run(async () =>
{
for (int i = 0; i < NumberOfItems; i++)
for (int i = 0; i < Program.NumberOfItems; i++)
{
var result = await nmodbus.ReadHoldingRegistersAsync(1, 0, 100);
}
@@ -108,32 +108,11 @@ public class ModbusCompare : IDisposable
await Task.WhenAll(tasks);
}
public async Task HslCommunication()
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < TaskNumberOfItems; i++)
{
tasks.Add(Task.Run(async () =>
{
for (int i = 0; i < NumberOfItems; i++)
{
var result = await hslmodbus.ReadAsync("0", 100);
if (!result.IsSuccess)
{
throw new Exception(result.Message);
}
}
}));
}
await Task.WhenAll(tasks);
}
public void Dispose()
{
thingsgatewaymodbus.Channel.SafeDispose();
thingsgatewaymodbus.SafeDispose();
modbusTcpMaster.SafeDispose();
nmodbus.SafeDispose();
hslmodbus.SafeDispose();
}
}
}

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>12.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
<PackageReference Include="MemoryPack" Version="1.10.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="NModbus" Version="3.0.81" />
<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="6.0.3.38" />
<PackageReference Include="TouchSocket.Modbus" Version="2.1.0-alpha.21" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34009.444
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkConsoleApp", "BenchmarkConsoleApp.csproj", "{B7F4BC07-5E95-47D8-BBB5-E707289049A7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B7F4BC07-5E95-47D8-BBB5-E707289049A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7F4BC07-5E95-47D8-BBB5-E707289049A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7F4BC07-5E95-47D8-BBB5-E707289049A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7F4BC07-5E95-47D8-BBB5-E707289049A7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AA6BD673-862A-414D-9598-DAE66B56552C}
EndGlobalSection
EndGlobal

161
benchmark/ConsoleAction.cs Normal file
View File

@@ -0,0 +1,161 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://kimdiego2098.github.io/
// QQ群605534569
//------------------------------------------------------------------------------
using TouchSocket.Core;
namespace ThingsGateway.Foundation;
/// <summary>
/// 控制台行为
/// </summary>
internal readonly struct VAction
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="action"></param>
/// <param name="description"></param>
/// <param name="fullOrder"></param>
public VAction(string description, string fullOrder, Func<Task> action)
{
this.FullOrder = fullOrder;
this.Action = action ?? throw new ArgumentNullException(nameof(action));
this.Description = description ?? throw new ArgumentNullException(nameof(description));
}
public Func<Task> Action { get; }
public string Description { get; }
public string FullOrder { get; }
}
/// <summary>
/// 控制台行为
/// </summary>
public sealed class ConsoleAction
{
private readonly Dictionary<string, VAction> m_actions = new Dictionary<string, VAction>();
/// <summary>
/// 构造函数
/// </summary>
/// <param name="helpOrder">帮助信息指令,如:"h|help|?"</param>
public ConsoleAction(string helpOrder = "h|help|?")
{
this.HelpOrder = helpOrder;
this.Add(helpOrder, "帮助信息", this.ShowAll);
}
/// <summary>
/// 执行异常
/// </summary>
public event Action<Exception> OnException;
/// <summary>
/// 帮助信息指令
/// </summary>
public string HelpOrder { get; private set; }
/// <summary>
/// 添加
/// </summary>
/// <param name="order">指令,多个指令用“|”分割</param>
/// <param name="description">描述</param>
/// <param name="action"></param>
public void Add(string order, string description, Action action)
{
Task Run()
{
action.Invoke();
return EasyTask.CompletedTask;
}
this.Add(order, description, Run);
}
/// <summary>
/// 添加
/// </summary>
/// <param name="order">指令,多个指令用“|”分割</param>
/// <param name="description">描述</param>
/// <param name="action"></param>
public void Add(string order, string description, Func<Task> action)
{
var orders = order.ToLower().Split('|');
foreach (var item in orders)
{
this.m_actions.Add(item, new VAction(description, order, action));
}
}
/// <summary>
/// 执行,返回值仅表示是否有这个指令,异常获取请使用<see cref="OnException"/>
/// </summary>
/// <param name="order"></param>
/// <returns></returns>
public async Task<bool> RunAsync(string order)
{
if (this.m_actions.TryGetValue(order.ToLower(), out var vAction))
{
try
{
await vAction.Action.Invoke().ConfigureFalseAwait();
}
catch (Exception ex)
{
OnException?.Invoke(ex);
}
return true;
}
else
{
return false;
}
}
/// <summary>
/// 运行
/// </summary>
public async Task RunCommandLineAsync()
{
while (true)
{
var str = Console.ReadLine();
if (!await this.RunAsync(str).ConfigureFalseAwait())
{
Console.WriteLine($"没有这个指令。");
}
}
}
/// <summary>
/// 显示所有注册指令
/// </summary>
public void ShowAll()
{
var max = this.m_actions.Values.Max(a => a.FullOrder.Length) + 8;
var s = new List<string>();
foreach (var item in this.m_actions)
{
if (!s.Contains(item.Value.FullOrder.ToLower()))
{
s.Add(item.Value.FullOrder.ToLower());
Console.Write($"[{item.Value.FullOrder}]");
for (var i = 0; i < max - item.Value.FullOrder.Length; i++)
{
Console.Write("-");
}
Console.WriteLine(item.Value.Description);
}
}
}
}

137
benchmark/Program.cs Normal file
View File

@@ -0,0 +1,137 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using BenchmarkDotNet.Running;
using System.Diagnostics;
using ThingsGateway.Foundation;
namespace BenchmarkConsoleApp
{
internal class Program
{
private static int ClientCount = 10;
public static int TaskNumberOfItems = 10;
public static int NumberOfItems = 1000;
private static async Task Main(string[] args)
{
Console.WriteLine("开始测试前请先启动ModbusSlave建议使用本项目自带的ThingsGateway.Debug.Photino软件开启");
//Console.WriteLine("输入客户端数量");
//ClientCount = Console.ReadLine().ToInt(1);
//Console.WriteLine("输入并发任务数量");
//TaskNumberOfItems = Console.ReadLine().ToInt(1);
//Console.WriteLine("输入每个任务执行读取次数");
//NumberOfItems = Console.ReadLine().ToInt(1);
Console.WriteLine($"多客户端({ClientCount}),多线程({TaskNumberOfItems})并发读取({NumberOfItems})测试,共{ClientCount * TaskNumberOfItems * NumberOfItems}次");
var consoleAction = new ConsoleAction();
consoleAction.Add("0", "基准测试", () =>
{
BenchmarkRunner.Run(typeof(Program).Assembly);
});
consoleAction.Add("1", "单独测试 ThingsGateway", async () => { await ThingsGateway(); });
consoleAction.Add("2", "单独测试 NModbus4", async () => { await NModbus4(); });
consoleAction.Add("3", "单独测试 TouchSocket", async () => { await TouchSocket(); });
consoleAction.ShowAll();
while (true)
{
await consoleAction.RunAsync(Console.ReadLine());
}
}
private static async Task ThingsGateway()
{
try
{
Console.WriteLine(" ThingsGateway 测试已开始");
Stopwatch stopwatch = new();
stopwatch.Start();
List<Task> tasks = new List<Task>();
for (int i = 0; i < ClientCount; i++)
{
tasks.Add(Task.Run(async () =>
{
ModbusCompare modbusBenchmarker = new();
await modbusBenchmarker.ThingsGateway();
modbusBenchmarker.Dispose();
}));
}
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($" ThingsGateway 耗时:{stopwatch.ElapsedMilliseconds}");
}
catch (Exception ex)
{
Console.WriteLine($" ThingsGateway 发生错误:{ex.Message}");
}
}
private static async Task TouchSocket()
{
try
{
Console.WriteLine(" TouchSocket 测试已开始");
Stopwatch stopwatch = new();
stopwatch.Start();
List<Task> tasks = new List<Task>();
for (int i = 0; i < ClientCount; i++)
{
tasks.Add(Task.Run(async () =>
{
ModbusCompare modbusBenchmarker = new();
await modbusBenchmarker.TouchSocket();
modbusBenchmarker.Dispose();
}));
}
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($" TouchSocket 耗时:{stopwatch.ElapsedMilliseconds}");
}
catch (Exception ex)
{
Console.WriteLine($" TouchSocket 发生错误:{ex.Message}");
}
}
private static async Task NModbus4()
{
try
{
Console.WriteLine(" NModbus4 测试已开始");
Stopwatch stopwatch = new();
stopwatch.Start();
List<Task> tasks = new List<Task>();
for (int i = 0; i < ClientCount; i++)
{
tasks.Add(Task.Run(async () =>
{
ModbusCompare modbusBenchmarker = new();
await modbusBenchmarker.NModbus4();
modbusBenchmarker.Dispose();
}));
}
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($" NModbus4 耗时:{stopwatch.ElapsedMilliseconds}");
}
catch (Exception ex)
{
Console.WriteLine($" NModbus4 发生错误:{ex.Message}");
}
}
}
}

View File

@@ -16,10 +16,5 @@
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DebugType>none</DebugType>
</PropertyGroup>
<ItemGroup>
<None Include="$(SolutionDir)..\README.md" Pack="true" PackagePath="\" />
<None Include="$(SolutionDir)..\LICENSE" Pack="true" PackagePath="\" />
<None Include="$(SolutionDir)..\icon.png" Pack="true" PackagePath="\" />
<None Include="$(SolutionDir)Directory.Build.props" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>

View File

@@ -21,4 +21,10 @@
<ItemGroup>
<None Include="$(SolutionDir)PackNuget.props" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<None Include="$(SolutionDir)..\README.md" Pack="true" PackagePath="\" />
<None Include="$(SolutionDir)..\LICENSE" Pack="true" PackagePath="\" />
<None Include="$(SolutionDir)..\icon.png" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>

View File

@@ -7,9 +7,9 @@
<PackageReference Include="MiniExcel" Version="1.32.1" />
<PackageReference Include="Rougamo.Fody" Version="3.0.0" />
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.158" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.159" />
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="BootstrapBlazor" Version="8.6.2" />
<PackageReference Include="BootstrapBlazor" Version="8.6.3" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>

View File

@@ -11,8 +11,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.6" />
<PackageReference Include="TouchSocket" Version="2.1.0-alpha.20" />
<PackageReference Include="TouchSocket.SerialPorts" Version="2.1.0-alpha.20" />
<PackageReference Include="TouchSocket" Version="2.1.0-alpha.21" />
<PackageReference Include="TouchSocket.SerialPorts" Version="2.1.0-alpha.21" />
<ProjectReference Include="$(SolutionDir)\ThingsGateway.NewLife.X\ThingsGateway.NewLife.X.csproj" />
</ItemGroup>

View File

@@ -33,6 +33,17 @@ public static class PluginServiceUtil
return true;
}
/// <summary>
/// 插件是否支持平台
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static bool HasDynamicProperty(object model)
{
var type = model.GetType();
return type.GetRuntimeProperties().Any(a => a.GetCustomAttribute<DynamicPropertyAttribute>(false) != null);
}
/// <summary>
/// 通过实体赋值到字典中
/// </summary>

View File

@@ -6,7 +6,7 @@
<PackageReference Include="SqlSugar.TDengineCore" Version="4.18.0" />
<PackageReference Include="Rougamo.Fody" Version="3.0.0" />
<PackageReference Include="CS-Script" Version="4.8.16" />
<PackageReference Include="TouchSocket.Dmtp" Version="2.1.0-alpha.20" />
<PackageReference Include="TouchSocket.Dmtp" Version="2.1.0-alpha.21" />
</ItemGroup>
<ItemGroup>

View File

@@ -150,7 +150,8 @@ public abstract partial class DevicePage : IDisposable
{
try
{
var result = device.PluginPropertyModel.ValidateForm?.Validate() != false;
var result = (!PluginServiceUtil.HasDynamicProperty(device.PluginPropertyModel.Value)) || (device.PluginPropertyModel.ValidateForm?.Validate() != false);
if (result == false)
{
return false;

View File

@@ -103,7 +103,7 @@ public partial class VariablePage : IDisposable
variable.VariablePropertyModels ??= new();
foreach (var item in variable.VariablePropertyModels)
{
var result = item.Value.ValidateForm?.Validate() != false;
var result = (!PluginServiceUtil.HasDynamicProperty(item.Value.Value)) || (item.Value.ValidateForm?.Validate() != false);
if (result == false)
{
return false;

View File

@@ -10,7 +10,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="8.6.2" />
<PackageReference Include="BootstrapBlazor" Version="8.6.3" />
<PackageReference Include="BootstrapBlazor.FontAwesome" Version="8.0.4" />
</ItemGroup>

View File

@@ -18,14 +18,14 @@
<!--<PlatformTarget>x86</PlatformTarget>-->
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
  <AllowedReferenceRelatedFileExtensions>
    <!-- 阻止默认的 XML 和 PDB 文件复制到 RELEASE 的输出目录. 只有*.allowedextension 扩展名的文件可以被包含, 当然这个扩展的文件并不存在.-->
    .allowedextension
</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>
<PropertyGroup Condition="'$(SolutionName)'=='ThingsGateway - Admin'">
<DefineConstants>Admin</DefineConstants>
</PropertyGroup>
@@ -37,7 +37,7 @@
<ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'">
<ProjectReference Include="$(SolutionDir)\pro\ThingsGateway.Gateway.ProRazor\ThingsGateway.Gateway.ProRazor.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(SolutionName)' != 'ThingsGateway - Admin'">
<ProjectReference Include="$(SolutionDir)\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj" />
</ItemGroup>
@@ -81,4 +81,10 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="$(SolutionDir)..\README.md" Pack="true" PackagePath="\" />
<None Include="$(SolutionDir)..\LICENSE" Pack="true" PackagePath="\" />
<None Include="$(SolutionDir)..\icon.png" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>6.0.3.35</Version>
<Version>6.0.3.38</Version>
</PropertyGroup>
<ItemGroup>

View File

@@ -8,143 +8,13 @@
// QQ群605534569
//------------------------------------------------------------------------------
using System.Diagnostics;
namespace ThingsGateway.Foundation;
internal class Program
{
private static int ClientCount = 100;
private static async Task Main(string[] args)
{
Console.WriteLine("开始测试前请先启动ModbusSlave建议使用本项目自带的ThingsGateway.Debug.Photino软件开启或者ModbusSim");
Console.WriteLine($"输入任意键,开始多客户端({ClientCount}),多线程({ModbusCompare.TaskNumberOfItems})并发读取({ModbusCompare.NumberOfItems})测试,共{ClientCount * ModbusCompare.TaskNumberOfItems * ModbusCompare.NumberOfItems}次");
Console.ReadKey();
await ThingsGateway();
await NModbus4();
await TouchSocket();
await HslCommunication();
Console.ReadLine();
//await ModbusMasterTest.Test();
//S7MatserTest.Test();
}
private static async Task ThingsGateway()
{
try
{
Console.WriteLine("输入任意键,开始 ThingsGateway 测试");
Console.ReadKey();
Console.WriteLine(" ThingsGateway 测试已开始");
Stopwatch stopwatch = new();
stopwatch.Start();
List<Task> tasks = new List<Task>();
for (int i = 0; i < ClientCount; i++)
{
tasks.Add(Task.Run(async () =>
{
ModbusCompare modbusBenchmarker = new();
await modbusBenchmarker.ThingsGateway();
modbusBenchmarker.Dispose();
}));
}
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($" ThingsGateway 耗时:{stopwatch.ElapsedMilliseconds}");
}
catch (Exception ex)
{
Console.WriteLine($" ThingsGateway 发生错误:{ex.Message}");
}
}
private static async Task TouchSocket()
{
try
{
Console.WriteLine("输入任意键,开始 TouchSocket 测试");
Console.ReadKey();
Console.WriteLine(" TouchSocket 测试已开始");
Stopwatch stopwatch = new();
stopwatch.Start();
List<Task> tasks = new List<Task>();
for (int i = 0; i < ClientCount; i++)
{
tasks.Add(Task.Run(async () =>
{
ModbusCompare modbusBenchmarker = new();
await modbusBenchmarker.TouchSocket();
modbusBenchmarker.Dispose();
}));
}
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($" TouchSocket 耗时:{stopwatch.ElapsedMilliseconds}");
}
catch (Exception ex)
{
Console.WriteLine($" TouchSocket 发生错误:{ex.Message}");
}
}
private static async Task NModbus4()
{
try
{
Console.WriteLine("输入任意键,开始 NModbus4 测试");
Console.ReadKey();
Console.WriteLine(" NModbus4 测试已开始");
Stopwatch stopwatch = new();
stopwatch.Start();
List<Task> tasks = new List<Task>();
for (int i = 0; i < ClientCount; i++)
{
tasks.Add(Task.Run(async () =>
{
ModbusCompare modbusBenchmarker = new();
await modbusBenchmarker.NModbus4();
modbusBenchmarker.Dispose();
}));
}
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($" NModbus4 耗时:{stopwatch.ElapsedMilliseconds}");
}
catch (Exception ex)
{
Console.WriteLine($" NModbus4 发生错误:{ex.Message}");
}
}
private static async Task HslCommunication()
{
try
{
Console.WriteLine("输入任意键,开始 HslCommunication 测试");
Console.ReadKey();
Console.WriteLine(" HslCommunication 测试已开始");
Stopwatch stopwatch = new();
stopwatch.Start();
List<Task> tasks = new List<Task>();
for (int i = 0; i < ClientCount; i++)
{
tasks.Add(Task.Run(async () =>
{
ModbusCompare modbusBenchmarker = new();
await modbusBenchmarker.HslCommunication();
modbusBenchmarker.Dispose();
}));
}
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($" HslCommunication 耗时:{stopwatch.ElapsedMilliseconds}");
}
catch (Exception ex)
{
Console.WriteLine($" HslCommunication 发生错误:{ex.Message}");
}
await ModbusMasterTest.Test();
await S7MasterTest.Test();
}
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using ThingsGateway.Foundation.Json.Extension;
using ThingsGateway.Foundation.Modbus;
using ThingsGateway.Foundation.SiemensS7;
using TouchSocket.Core;

View File

@@ -8,10 +8,10 @@
<ItemGroup>
<PackageReference Include="HslCommunication" Version="12.0.2" />
<PackageReference Include="NModbus" Version="3.0.81" />
<PackageReference Include="ThingsGateway.Foundation.SiemensS7" Version="6.0.3.35" />
<PackageReference Include="ThingsGateway.Foundation.SiemensS7" Version="6.0.3.38" />
<PackageReference Include="ThingsGateway.Foundation.Variable" Version="8.5.0" />
<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="6.0.3.35" />
<PackageReference Include="TouchSocket.Modbus" Version="2.1.0-alpha.20" />
<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="6.0.3.38" />
<PackageReference Include="TouchSocket.Modbus" Version="2.1.0-alpha.21" />
</ItemGroup>

View File

@@ -243,18 +243,18 @@ public class ModbusSlave : ProtocolBase, ITcpService, IDtuClient
if (ModbusType == ModbusTypeEnum.ModbusRtu)
{
var sendData = DataTransUtil.SpliceArray(modbusServerMessage.Bytes.Slice(0, 2).ToArray(), new byte[] { (byte)coreData.Length }, coreData);
await ReturnData(client, e, sendData);
ReturnData(client, e, sendData);
}
else
{
var sendData = DataTransUtil.SpliceArray(modbusServerMessage.Bytes.Slice(0, 8).ToArray(), new byte[] { (byte)coreData.Length }, coreData);
sendData[5] = (byte)(sendData.Length - 6);
await ReturnData(client, e, sendData);
ReturnData(client, e, sendData);
}
}
else
{
await WriteError(this.ModbusType, client, modbusServerMessage, e);//返回错误码
WriteError(this.ModbusType, client, modbusServerMessage, e);//返回错误码
}
}
else//写入
@@ -268,21 +268,21 @@ public class ModbusSlave : ProtocolBase, ITcpService, IDtuClient
// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
if ((await this.WriteData(modbusServerMessage.ModbusAddress, modbusServerMessage.Content, this.ThingsGatewayBitConverter, client).ConfigureAwait(false)).IsSuccess)
{
await WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
if (this.IsWriteMemory)
{
var result = this.Write(modbusServerMessage.ModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
if (result.IsSuccess)
await WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
else
await WriteError(this.ModbusType, client, modbusServerMessage, e);
WriteError(this.ModbusType, client, modbusServerMessage, e);
}
else
await WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
}
else
{
await WriteError(this.ModbusType, client, modbusServerMessage, e);
WriteError(this.ModbusType, client, modbusServerMessage, e);
}
}
else
@@ -291,11 +291,11 @@ public class ModbusSlave : ProtocolBase, ITcpService, IDtuClient
var result = this.Write(modbusServerMessage.ModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
if (result.IsSuccess)
{
await WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
}
else
{
await WriteError(this.ModbusType, client, modbusServerMessage, e);
WriteError(this.ModbusType, client, modbusServerMessage, e);
}
}
}
@@ -310,16 +310,16 @@ public class ModbusSlave : ProtocolBase, ITcpService, IDtuClient
{
var result = this.Write(modbusServerMessage.ModbusAddress.ToString(), coreData);
if (result.IsSuccess)
await WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
else
await WriteError(this.ModbusType, client, modbusServerMessage, e);
WriteError(this.ModbusType, client, modbusServerMessage, e);
}
else
await WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
}
else
{
await WriteError(this.ModbusType, client, modbusServerMessage, e);
WriteError(this.ModbusType, client, modbusServerMessage, e);
}
}
else
@@ -327,11 +327,11 @@ public class ModbusSlave : ProtocolBase, ITcpService, IDtuClient
var result = this.Write(modbusServerMessage.ModbusAddress.ToString(), coreData);
if (result.IsSuccess)
{
await WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
WriteSuccess(this.ModbusType, client, modbusServerMessage, e);
}
else
{
await WriteError(this.ModbusType, client, modbusServerMessage, e);
WriteError(this.ModbusType, client, modbusServerMessage, e);
}
}
}
@@ -339,33 +339,36 @@ public class ModbusSlave : ProtocolBase, ITcpService, IDtuClient
}
}
private async Task ReturnData(IClientChannel client, ReceivedDataEventArgs e, byte[] sendData)
private void ReturnData(IClientChannel client, ReceivedDataEventArgs e, byte[] sendData)
{
if (SendDelayTime > 0)
await Task.Delay(SendDelayTime).ConfigureAwait(false);
if (client is IUdpClientSender udpClientSender)
if (ModbusType == ModbusTypeEnum.ModbusRtu)
await udpClientSender.SendAsync(((UdpReceivedDataEventArgs)e).EndPoint, new SendMessage(sendData));
_ = Task.Run(async () =>
{
if (SendDelayTime > 0)
await Task.Delay(SendDelayTime).ConfigureAwait(false);
if (client is IUdpClientSender udpClientSender)
if (ModbusType == ModbusTypeEnum.ModbusRtu)
await udpClientSender.SendAsync(((UdpReceivedDataEventArgs)e).EndPoint, new SendMessage(sendData));
else
await udpClientSender.SendAsync(((UdpReceivedDataEventArgs)e).EndPoint, sendData);
else
await udpClientSender.SendAsync(((UdpReceivedDataEventArgs)e).EndPoint, sendData);
else
if (ModbusType == ModbusTypeEnum.ModbusRtu)
await client.SendAsync(new SendMessage(sendData));
else
await client.SendAsync(sendData);
if (ModbusType == ModbusTypeEnum.ModbusRtu)
await client.SendAsync(new SendMessage(sendData));
else
await client.SendAsync(sendData);
});
}
/// <summary>
/// 返回错误码
/// </summary>
private async Task WriteError(ModbusTypeEnum modbusType, IClientChannel client, IModbusServerMessage modbusServerMessage, ReceivedDataEventArgs e)
private void WriteError(ModbusTypeEnum modbusType, IClientChannel client, IModbusServerMessage modbusServerMessage, ReceivedDataEventArgs e)
{
if (modbusType == ModbusTypeEnum.ModbusRtu)
{
var sendData = DataTransUtil
.SpliceArray(modbusServerMessage.Bytes.Slice(0, 2).ToArray(), new byte[] { (byte)1 });//01 lllegal function
sendData[1] = (byte)(sendData[1] + 128);
await ReturnData(client, e, sendData);
ReturnData(client, e, sendData);
}
else
{
@@ -373,25 +376,25 @@ public class ModbusSlave : ProtocolBase, ITcpService, IDtuClient
.SpliceArray(modbusServerMessage.Bytes.Slice(0, 8).ToArray(), new byte[] { (byte)1 });//01 lllegal function
sendData[5] = (byte)(sendData.Length - 6);
sendData[7] = (byte)(sendData[7] + 128);
await ReturnData(client, e, sendData);
ReturnData(client, e, sendData);
}
}
/// <summary>
/// 返回成功
/// </summary>
internal async Task WriteSuccess(ModbusTypeEnum modbusType, IClientChannel client, IModbusServerMessage modbusServerMessage, ReceivedDataEventArgs e)
internal void WriteSuccess(ModbusTypeEnum modbusType, IClientChannel client, IModbusServerMessage modbusServerMessage, ReceivedDataEventArgs e)
{
if (modbusType == ModbusTypeEnum.ModbusRtu)
{
var sendData = modbusServerMessage.Bytes.Slice(0, 6).ToArray();
await ReturnData(client, e, sendData);
ReturnData(client, e, sendData);
}
else
{
var sendData = modbusServerMessage.Bytes.Slice(0, 12).ToArray();
sendData[5] = (byte)(sendData.Length - 6);
await ReturnData(client, e, sendData);
ReturnData(client, e, sendData);
}
}

View File

@@ -21,11 +21,6 @@ namespace ThingsGateway.Foundation.SiemensS7;
/// </summary>
public class SiemensAddress
{
/// <summary>
/// 地址
/// </summary>
public string Address { get; set; }
/// <summary>
/// bit位偏移
/// </summary>
@@ -51,21 +46,18 @@ public class SiemensAddress
/// </summary>
public int Length { get; set; }
/// <summary>
/// <inheritdoc cref="Address"/>
/// </summary>
public int AddressStart => Address.ToInt();
public int AddressStart { get; set; }
/// <inheritdoc />
public override string ToString()
{
if (DataCode == (byte)S7Area.TM)
{
return $"T{Address}{(IsString ? ";" : ";W=false;")}";
return $"T{AddressStart}{(IsString ? ";" : ";W=false;")}";
}
if (DataCode == (byte)S7Area.CT)
{
return $"C{Address}{(IsString ? ";" : ";W=false;")}";
return $"C{AddressStart}{(IsString ? ";" : ";W=false;")}";
}
if (DataCode == (byte)S7Area.AI)
@@ -93,7 +85,7 @@ public class SiemensAddress
return $"M{GetStringAddress(AddressStart)}{(IsString ? ";" : ";W=false;")}";
}
return DataCode == (byte)S7Area.DB ? $"DB{DbBlock}.{GetStringAddress(AddressStart)}{(IsString ? ";" : ";W=false;")}" : Address.ToString() + (IsString ? ";" : ";W=false;");
return DataCode == (byte)S7Area.DB ? $"DB{DbBlock}.{GetStringAddress(AddressStart)}{(IsString ? ";" : ";W=false;")}" : AddressStart.ToString() + (IsString ? ";" : ";W=false;");
}
private static string GetStringAddress(int addressStart)
@@ -174,12 +166,12 @@ public class SiemensAddress
s7AddressData.DataCode = (byte)S7Area.AI;
if (strArr[index].StartsWith("AIX") || strArr[index].StartsWith("AIB") || strArr[index].StartsWith("AIW") || strArr[index].StartsWith("AID"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(3)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(3));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(3));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(2));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
}
@@ -188,12 +180,12 @@ public class SiemensAddress
s7AddressData.DataCode = (byte)S7Area.AQ;
if (strArr[index].StartsWith("AQX") || strArr[index].StartsWith("AQB") || strArr[index].StartsWith("AQW") || strArr[index].StartsWith("AQD"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(3)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(3));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(3));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(2));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
}
@@ -202,12 +194,12 @@ public class SiemensAddress
s7AddressData.DataCode = (byte)S7Area.PE;
if (strArr[index].StartsWith("IX") || strArr[index].StartsWith("IB") || strArr[index].StartsWith("IW") || strArr[index].StartsWith("ID"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(2));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(1));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
}
@@ -216,12 +208,12 @@ public class SiemensAddress
s7AddressData.DataCode = (byte)S7Area.PA;
if (strArr[index].StartsWith("QX") || strArr[index].StartsWith("QB") || strArr[index].StartsWith("QW") || strArr[index].StartsWith("QD"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(2));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(1));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
}
@@ -230,12 +222,12 @@ public class SiemensAddress
s7AddressData.DataCode = (byte)S7Area.MK;
if (strArr[index].StartsWith("MX") || strArr[index].StartsWith("MB") || strArr[index].StartsWith("MW") || strArr[index].StartsWith("MD"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(2));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(1));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
}
@@ -250,19 +242,19 @@ public class SiemensAddress
address1 = address1.Substring(3);
}
s7AddressData.Address = GetAddressStart(address1).ToString();
s7AddressData.AddressStart = GetAddressStart(address1);
s7AddressData.BitCode = GetBitCode(address1);
}
else if (strArr[index][0] == 'T')
{
s7AddressData.DataCode = (byte)S7Area.TM;
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1), true).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(1), true);
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
else if (strArr[index][0] == 'C')
{
s7AddressData.DataCode = (byte)S7Area.CT;
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1), true).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(1), true);
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
else if (strArr[index][0] == 'V')
@@ -271,12 +263,12 @@ public class SiemensAddress
s7AddressData.DbBlock = 1;
if (strArr[index].StartsWith("VB") || strArr[index].StartsWith("VW") || strArr[index].StartsWith("VD") || strArr[index].StartsWith("VX"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(2));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1)).ToString();
s7AddressData.AddressStart = GetAddressStart(strArr[index].Substring(1));
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
}

View File

@@ -262,7 +262,7 @@ public partial class SiemensS7Master : ProtocolBase
channel.Close();
return;
}
PduLength = ThingsGatewayBitConverter.ToUInt16(result2.Content, 0);
PduLength = ThingsGatewayBitConverter.ToUInt16(result2.Content, 0) - 28;
Logger?.LogInformation($"PduLength{PduLength}");
PduLength = PduLength < 200 ? 200 : PduLength;
}

View File

@@ -8,12 +8,8 @@
// QQ群605534569
//------------------------------------------------------------------------------
using System;
using ThingsGateway.Foundation.Extension.Generic;
using TouchSocket.Core;
namespace ThingsGateway.Foundation.SiemensS7;
/// <inheritdoc/>
@@ -40,11 +36,11 @@ public partial class SiemensS7Master : ProtocolBase
num1 += num2;
if (from.DataCode == (byte)S7WordLength.Timer || from.DataCode == (byte)S7WordLength.Counter)
{
from.Address += num2 / 2;
from.AddressStart += num2 / 2;
}
else
{
from.Address += num2 * 8;
from.AddressStart += num2 * 8;
}
}
return listBytes;
@@ -88,7 +84,7 @@ public partial class SiemensS7Master : ProtocolBase
var result1 = SiemensHelper.GetWriteByteCommand(address, data);
bytes.Add(result1);
index += length2;
address.Address += length2 * 8;
address.AddressStart += length2 * 8;
}
return bytes;
}

View File

@@ -49,5 +49,9 @@
</ItemGroup>
<ItemGroup>
<None Include="$(SolutionDir)..\README.md" Pack="true" PackagePath="\" />
<None Include="$(SolutionDir)..\LICENSE" Pack="true" PackagePath="\" />
<None Include="$(SolutionDir)..\icon.png" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>