Dahlke.EtherCAT.Diagnostics 0.11.0

dotnet add package Dahlke.EtherCAT.Diagnostics --version 0.11.0
                    
NuGet\Install-Package Dahlke.EtherCAT.Diagnostics -Version 0.11.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Dahlke.EtherCAT.Diagnostics" Version="0.11.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Dahlke.EtherCAT.Diagnostics" Version="0.11.0" />
                    
Directory.Packages.props
<PackageReference Include="Dahlke.EtherCAT.Diagnostics" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Dahlke.EtherCAT.Diagnostics --version 0.11.0
                    
#r "nuget: Dahlke.EtherCAT.Diagnostics, 0.11.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Dahlke.EtherCAT.Diagnostics@0.11.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Dahlke.EtherCAT.Diagnostics&version=0.11.0
                    
Install as a Cake Addin
#tool nuget:?package=Dahlke.EtherCAT.Diagnostics&version=0.11.0
                    
Install as a Cake Tool

Dahlke.EtherCAT.Diagnostics

EtherCAT master and slave diagnostics over TwinCAT ADS: topology, slave and port state, CRC and frame error counters, sync-unit faults, CoE object reads and writes, and a change-event stream.

It reads through raw ADS index groups rather than the symbol API, because that is the only way to reach an EtherCAT master — there are no PLC symbols for any of this. The raw channel comes from Dahlke.TwinCAT.Ads, so you get its connection pooling, reconnection and simulation for free.

dotnet add package Dahlke.EtherCAT.Diagnostics

Quick start

builder.Services.AddTwinCatAds(builder.Configuration);      // the raw channel factory
builder.Services.AddEtherCatDiagnostics();                  // client, cache, polling monitor

You must also supply two application concerns this library deliberately does not invent:

builder.Services.AddSingleton<IEtherCatOptionsSource, MyOptionsSource>();      // which masters to poll
builder.Services.AddSingleton<IEtherCatDiagnosticsHandler, MyHandler>();       // where events go

Then read the bus:

public sealed class TopologyEndpoint(IEtherCatClient client)
{
    public async Task<string> DescribeAsync(CancellationToken ct)
    {
        var masters = await client.GetMastersAsync("192.168.1.10.1.1", ct);
        var master  = masters[0];

        var state  = await client.GetMasterStateAsync(master.AmsNetId, ct);
        var slaves = await client.GetConfiguredSlavesAsync(master.AmsNetId, ct);
        var frames = await client.GetFrameStatisticsAsync(master.AmsNetId, ct);

        return $"{master.Name}: {state?.State}, {slaves?.Count} slaves, "
             + $"{frames?.CyclicLostFrames} cyclic frames lost";
    }
}

What it gives you

IEtherCatClient One-shot reads: masters, master state, configured vs. scanned slaves, per-slave detail, error counters, sync units, CoE objects, and a CiA-402 drive's decoded statusword. Counters are resettable and CoE objects are writable.
IEtherCatCache The last snapshot the monitor took, so a request path never has to touch the bus.
IEtherCatMonitor The polling loop, registered as a hosted service. Re-arm a CRC notification with ClearCrcNotification.
IEtherCatEvent The change stream — slave present/absent, slave and master state changes, CRC threshold exceeded, sync-unit fault, diagnostics degraded.

Configured vs. scanned matters. GetConfiguredSlavesAsync returns what the project says should be on the bus; GetScannedSlavesAsync returns what is actually answering. The difference is the diagnosis.

Nullable returns are the contract, not an oversight. A master that is not reachable yields null rather than throwing, so a dashboard polling six masters is not taken down by one unplugged cable.

Parameterising a slave over CoE

ReadCoeObjectAsync and WriteCoeObjectAsync reach a slave's object dictionary. Both address it by ADS port (the slave's fixed address), not by the index offset the diagnostic reads use, and both are strictly on-demand — a slave with no mailbox never answers, so neither belongs in a polling loop.

var write = await client.WriteCoeObjectAsync(
    master.AmsNetId, physicalAddress: 1004,
    index: 0x8010, subIndex: 0x11,
    data: BitConverter.GetBytes((ushort)2500),   // little-endian, exactly as wide as the object
    timeoutMs: 3000, ct);

if (!write.Succeeded && write.Reason == CoeFailureReason.SdoAbort)
    logger.LogWarning("drive refused it: {Error}", write.Error);   // e.g. SDO abort 0x06010002: …

A refusal is a result, not an exception, and the slave's own reason is the point. Reason separates a slave with no mailbox from an object that is not in its dictionary from an SdoAbort — and an abort carries the device's verbatim code in AbortCode (0x06010002 read-only object, 0x06090030 value out of range, 0x08000021 local control), with the ETG.1000-6 description in Error. During commissioning that code is the difference between "fix the value" and "put the drive back in remote".

Three things this deliberately does not do: it does not read the value back (a device may clamp, round, or store to a shadow copy pending a save to 0x1010), it does not encode CoE data types for you, and it does not suppress the raw channel's retry — so a write that gets no answer can reach the slave twice. That is safe for a parameter store and wrong for an object whose write is a command; set RawChannels:RetryCount to 0 in a host that writes those.

Reading a drive's CiA-402 state

ReadCia402StatusAsync reads object 0x6041 and hands back the decoded drive state instead of two bytes:

var status = await client.ReadCia402StatusAsync(
    master.AmsNetId, physicalAddress: 1004, timeoutMs: 3000, ct);

if (status.Succeeded && status.Status!.Value.State == Cia402State.Fault)
    logger.LogWarning("drive is faulted: 0x{Word:X4}", status.Statusword);

It is a convenience over ReadCoeObjectAsync and nothing more — same ADS-port addressing, same on-demand-only rule, same retry, and the CoE read's whole failure vocabulary (Reason, AbortCode, Error) forwarded untouched. The decoding itself lives in Dahlke.EtherCAT.Cia402, which this package depends on and which depends on nothing: use it directly if you already have the word.

Two cases worth knowing. A successful read can carry Cia402State.Unknown — that is the drive reporting a word the CiA-402 state table does not name, which is an answer, so read Statusword when it happens. And a slave that answers fewer than two bytes is reported as a failure rather than decoded, because inventing the high byte would fabricate the remote and target-reached flags.

Nothing here checks that the slave is a drive at all: 0x6041 on a non-drive either does not exist (ObjectNotFound, or an abort) or means something else, and reading 0x1000 first to find out would double the round trips for every caller.

Turning the polling off

AddEtherCatDiagnostics(startMonitor: false) registers everything but does not run the loop. There is no internal enable flag, and this is why: a REST controller is activated by its framework before whatever feature gate would have turned the request away, so its dependencies have to resolve either way. Registering without polling lets the surface exist while the bus is left alone. Not calling AddEtherCatDiagnostics at all is the other way to turn it off, and the right one when nothing references the library.

Testing without hardware

Because the transport is Dahlke.TwinCAT.Ads's raw channel, its simulation applies — seed raw index-group responses and exercise this library with no PLC and no TwinCAT installation. See the raw-channel simulation section of the repository README.

Apache-2.0.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Dahlke.EtherCAT.Diagnostics:

Package Downloads
OpenEC.Monitor.Ads

Optional read-only TwinCAT master (ADS) enrichment for the OpenEC.Monitor EtherCAT SDK.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.11.0 122 8/27/2026
0.10.0 287 8/15/2026
0.9.1 248 8/5/2026
0.9.0 106 8/4/2026