Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions NET/AdsMapperCli/AdsMapperCli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<StartupObject>AdsMapperCli.Program</StartupObject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.*" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.*" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.*" />
<PackageReference Include="System.Text.Json" Version="8.*" />
</ItemGroup>

<ItemGroup>
Expand Down
37 changes: 37 additions & 0 deletions NET/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,43 @@ The following types of changes exist:
- **Fixed** for any bug fixes.
- **Security** in case of vulnerabilities.

## 2026 New Year, Version 5.2.0
### Removed
- Removed Support for .NET Framework 4.7.1 (But still .NET Standard 2.0.)
- Removed Dependency to Mbc.Hdf5Utils Nuget package. The code is now part of Mbc.Pcs.Net.DataRecorder.

### Added
- Support for .NET 10.0.
- Add Automatic recconection behavior in PlcAdsConnectionService

### Changed
- Update to Beckhoff.TwinCAT.Ads version 6.2.521

### Fixed
- fixed deadlock in PlcAdsConnectionService
- fixed handling PlcAdsStateReader when stop is called before start

## 2025 Summer, Version 5.1.0
### Feature
- It is now possible to write Structs with the `CommandInputBuilder` and the `PrimitiveCommandArgumentHandler`. Actually it results in multiple write commands to the PLC. So each struct and it fields will be recursively written to the PLC also in recursive structs. The fields in the struct has to be flagged with the `{attribute 'PlcCommandInput'}`. The Struct values must in c# be of type of `CommandInputBuilder`.
```C#
ICommandInput inputStructValues = CommandInputBuilder.FromDictionary(new Dictionary<string, object>()
{
["StructValue1"] = 123,
["StructValue1"] = 3333,
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate key in dictionary example. "StructValue1" appears twice in the dictionary with different values (123 and 3333). This will cause a runtime error. The second occurrence should likely be "StructValue2".

Suggested change
["StructValue1"] = 3333,
["StructValue2"] = 3333,

Copilot uses AI. Check for mistakes.
});

ICommandInput input = CommandInputBuilder.FromDictionary(new Dictionary<string, object>()
{
["value1"] = (byte)123,
["stAbc"] = inputStructValues,
["alue2"] = (byte)222,
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in dictionary key. The key is "alue2" but should likely be "value2" (missing leading 'v').

Suggested change
["alue2"] = (byte)222,
["value2"] = (byte)222,

Copilot uses AI. Check for mistakes.
});
```

### Bugfix
- Remove double write of `PrimitiveCommandArgumentHandler` in WriteInputData

## 2025 Spring, Version 5.0.0
- See PR #8
- All packages are now on Version 5.0.0
Expand Down
5 changes: 4 additions & 1 deletion NET/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,15 @@ limitations under the License.
<CodeAnalysisRuleSet>$(MSBuildProjectDirectory)\..\Build\Mbc.CodeAnalysis.ruleset</CodeAnalysisRuleSet>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisLevel>latest</AnalysisLevel>
<_SkipUpgradeNetAnalyzersNuGetWarning>true</_SkipUpgradeNetAnalyzersNuGetWarning>
</PropertyGroup>
<ItemGroup>
<!-- Mark Analyzers as Private so it will not result in a dependency in the nuget -->
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.*">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.*" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.*" >
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion NET/Mbc.Ads.Helper.ReadType/Mbc.Ads.Helper.ReadType.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion NET/Mbc.Ads.Mapper.Test/AdsBinaryAccesorFactoryTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using FakeItEasy;
using FluentAssertions;
using AwesomeAssertions;
using System;
using System.Text;
using TwinCAT.PlcOpen;
Expand Down
3 changes: 1 addition & 2 deletions NET/Mbc.Ads.Mapper.Test/AdsMapperTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
// Licensed under the Apache License, Version 2.0
//-----------------------------------------------------------------------------

using FluentAssertions;
using AwesomeAssertions;
using System;
using System.Diagnostics;
using Xunit;
using Xunit.Abstractions;

namespace Mbc.Ads.Mapper.Test
{
Expand Down
4 changes: 2 additions & 2 deletions NET/Mbc.Ads.Mapper.Test/AdsMapperTestFakePlcData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private IAdsSymbolInfo CreateFakeIAdsSymbolInfo()

fakeMembers.Add(CreateFakeStringMember("sPlcVersion", 82, StringMarshaler.DefaultEncoding, 10, 11));
fakeMembers.Add(CreateFakeStringMember("sUtf7String", 93, StringMarshaler.DefaultEncoding, 6, 7));
fakeMembers.Add(CreateFakeStringMember("wsUnicodeString", 100, StringMarshaler.UTF16, 6, 14));
fakeMembers.Add(CreateFakeStringMember("wsUnicodeString", 100, StringMarshaler.UTF16.Encoding, 6, 14));

return fakeSymbolInfo;
}
Expand Down Expand Up @@ -238,7 +238,7 @@ private byte[] CreateAdsStream()
writer.Write(str2); // offset 93

var str3 = new byte[14];
StringMarshaler.UTF16.GetBytes("ÄÖö@Ü8", 0, 6, str3, 0);
StringMarshaler.UTF16.Encoding.GetBytes("ÄÖö@Ü8", 0, 6, str3, 0);
writer.Write(str3); // offset 100

// Write Motor Object
Expand Down
2 changes: 1 addition & 1 deletion NET/Mbc.Ads.Mapper.Test/AdsSymbolReaderTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using FakeItEasy;
using FluentAssertions;
using AwesomeAssertions;
using TwinCAT.Ads;
using Xunit;

Expand Down
2 changes: 1 addition & 1 deletion NET/Mbc.Ads.Mapper.Test/DataObjectAccessorTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using FluentAssertions;
using AwesomeAssertions;
using System.Linq;
using Xunit;

Expand Down
44 changes: 0 additions & 44 deletions NET/Mbc.Ads.Mapper.Test/MarshallingPerformanceTest.cs

This file was deleted.

31 changes: 9 additions & 22 deletions NET/Mbc.Ads.Mapper.Test/Mbc.Ads.Mapper.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- common nuget configuration see Directory.Build.props-->
<TargetFrameworks>net471;net8.0</TargetFrameworks>
<TargetFrameworks>net10.0;net8.0</TargetFrameworks>
<Product>Mbc.Ads.Mapper.Test</Product>

<GeneratePackageOnBuild>false</GeneratePackageOnBuild>

<OutputType>Exe</OutputType>

<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<UseAppHost>true</UseAppHost>
</PropertyGroup>
<PropertyGroup>
<NoWarn>NU1702;CS7022</NoWarn>
Expand All @@ -18,29 +17,17 @@
<ProjectReference Include="..\Mbc.Ads.Mapper\Mbc.Ads.Mapper.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PackageReference Include="coverlet.collector" Version="10.*">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FakeItEasy">
<Version>8.3.0</Version>
</PackageReference>
<PackageReference Include="FluentAssertions">
<Version>7.0.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit">
<Version>2.9.2</Version>
</PackageReference>
<PackageReference Include="xunit.analyzers" Version="1.17.0">
<PrivateAssets>all</PrivateAssets>
<PackageReference Include="FakeItEasy" Version="9.*" />
<PackageReference Include="AwesomeAssertions" Version="9.*" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.*" />
<PackageReference Include="xunit.v3" Version="3.*" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.*">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio">
<Version>2.8.2</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion NET/Mbc.Ads.Mapper.Test/Reflection/FastInvokeTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using FluentAssertions;
using AwesomeAssertions;
using Mbc.Ads.Mapper.Reflection;
using Xunit;

Expand Down
2 changes: 1 addition & 1 deletion NET/Mbc.Ads.Mapper.Test/ReflectionHelperTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0
//-----------------------------------------------------------------------------

using FluentAssertions;
using AwesomeAssertions;
using System;
using System.Linq;
using System.Linq.Expressions;
Expand Down
4 changes: 2 additions & 2 deletions NET/Mbc.Ads.Mapper/Mbc.Ads.Mapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- common nuget configuration see Directory.Build.props-->
<TargetFrameworks>netstandard2.0;net471;net8.0</TargetFrameworks>
<Version>5.0.0.0</Version>
<TargetFrameworks>net10.0;net8.0;netstandard2.0</TargetFrameworks>
<Version>5.2.0</Version>

<Product>Mbc.Ads.Mapper</Product>

Expand Down
2 changes: 1 addition & 1 deletion NET/Mbc.Ads.Utils.Test/AdsConvertTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using FluentAssertions;
using AwesomeAssertions;
using System;
using System.Globalization;
using Xunit;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using FakeItEasy;
using FluentAssertions;
using AwesomeAssertions;
using Mbc.Ads.Utils.Connection;
using System.Threading;
using TwinCAT.Ads;
Expand Down
25 changes: 7 additions & 18 deletions NET/Mbc.Ads.Utils.Test/Mbc.Ads.Utils.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- common nuget configuration see Directory.Build.props-->
<TargetFrameworks>net471;net8.0</TargetFrameworks>
<TargetFrameworks>net10.0;net8.0</TargetFrameworks>
<Product>Mbc.Utils.Test</Product>

<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
Expand All @@ -12,27 +12,16 @@
<ProjectReference Include="..\Mbc.Ads.Utils\Mbc.Ads.Utils.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PackageReference Include="coverlet.collector" Version="10.*">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FakeItEasy">
<Version>8.3.0</Version>
</PackageReference>
<PackageReference Include="FluentAssertions">
<Version>7.0.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit">
<Version>2.9.2</Version>
</PackageReference>
<PackageReference Include="xunit.analyzers" Version="1.17.0">
<PrivateAssets>all</PrivateAssets>
<PackageReference Include="FakeItEasy" Version="9.*" />
<PackageReference Include="AwesomeAssertions" Version="9.*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.*" />
<PackageReference Include="xunit.v3" Version="3.*" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.*">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio">
<Version>2.8.2</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
Expand Down
8 changes: 4 additions & 4 deletions NET/Mbc.Ads.Utils/Mbc.Ads.Utils.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- common nuget configuration see Directory.Build.props-->
<TargetFrameworks>netstandard2.0;net471;net8.0</TargetFrameworks>
<Version>5.0.0.0</Version>
<TargetFrameworks>net10.0;net8.0;netstandard2.0</TargetFrameworks>
<Version>5.2.0</Version>

<Product>Mbc.Ads.Utils</Product>

</PropertyGroup>
<ItemGroup>
<PackageReference Include="Beckhoff.TwinCAT.Ads" Version="6.1.332" />
<PackageReference Include="Castle.Core" Version="5.1.1" />
<PackageReference Include="Beckhoff.TwinCAT.Ads" Version="6.2.521" />
<PackageReference Include="Castle.Core" Version="5.2.1" />
</ItemGroup>
</Project>
43 changes: 43 additions & 0 deletions NET/Mbc.Benchmark.Test/Ads/Mapper/MarshallingPerformanceTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using BenchmarkDotNet.Attributes;
using System.Buffers.Binary;
using TwinCAT.TypeSystem;

namespace Mbc.Ads.Mapper;

/// <summary>
/// Benchmark different ways to unmarshal binary values to managed type.
///
/// | Method | Mean | Error | StdDev |
/// |------------------------------- |-----------:|----------:|----------:|
/// | TwinCAT_PrimitiveTypeMarshaler | 177.543 ns | 0.4423 ns | 0.3693 ns |
/// | DotNet_BinaryPrimitives | 15.457 ns | 0.3524 ns | 0.7199 ns |
/// | Custom_UnsafeReader | 2.017 ns | 0.0911 ns | 0.1619 ns |
///
/// </summary>
[SimpleJob(BenchmarkDotNet.Jobs.RuntimeMoniker.Net47)]
public class MarshallingPerformanceTest
{
private readonly byte[] _data = new byte[4];
private int _value;

[Benchmark]
public void TwinCAT_PrimitiveTypeMarshaler()
{
PrimitiveTypeMarshaler.Default.Unmarshal<int>(_data, out _value);
}

[Benchmark]
public void DotNet_BinaryPrimitives()
{
_value = BinaryPrimitives.ReadInt32LittleEndian(_data);
}

[Benchmark]
public unsafe void Custom_UnsafeReader()
{
fixed (byte* p = _data)
{
_value = *(int*)p;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using BenchmarkDotNet.Running;
using Mbc.Ads.Mapper.Test;
using Mbc.Ads.Mapper;
using Mbc.Pcs.Net.State;

/* Works only without debugging in release configuration. */

BenchmarkRunner.Run<PlcHeartBeatTimerBenchmark>();
BenchmarkRunner.Run<MarshallingPerformanceTest>();
Loading