Elatec.NET 0.4.0

dotnet add package Elatec.NET --version 0.4.0
NuGet\Install-Package Elatec.NET -Version 0.4.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="Elatec.NET" Version="0.4.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Elatec.NET --version 0.4.0
#r "nuget: Elatec.NET, 0.4.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.
// Install Elatec.NET as a Cake Addin
#addin nuget:?package=Elatec.NET&version=0.4.0

// Install Elatec.NET as a Cake Tool
#tool nuget:?package=Elatec.NET&version=0.4.0

Elatec.NET Codacy Badge

Elatec TWN4 SimpleProtocol Wrapper for .NET

Reader-Shop: https://www.elatec-shop.de/de/

DEV-Kit: https://www.elatec-rfid.com/int/twn4-dev-pack

Tested devices:

  • TWN4/B1.06/CCB4.51/PRS1.04/5 (TWN4 Multitec 2 Legic HF LF)
  • TWN4/B1.50/NCB4.51/PRS1.04/5 (TWN4 Multitec Legic 45)
  • TWN4/B1.06/CCF4.51/PRS1.04 (TWN4 Multitec)

Hint: Some readers may show unexpected behavior. Especially with Legic Capable "TWN4 Multitec (2) HF LF Legic". The reason is that some ISO14443 commands are executed by the internal legic chip.

Examples for the TWN4 - Legic reader "specialties":

  • SelectTag() is only supported by native readers without legic chip, SearchTag() must be used in order to select a Tag.
  • RATS command cannot be called manually on the Legic capable readers. Instead it is already executed internally when SearchTag() was called. This will be faced when trying to execute RATS with ISO14443-3_TXD. Use ISO14443A_GetAtsAsync() istead. The reader will deal with the right procedure.
  • MifareClassic_LoginAsync() needs the sectornumber. Elatec has a special calculating algorithm for the expected sectornumber. Every sector above sec32 (mifare 4k) is 4times bigger that the lower sectors. They expect the sectornumber also to be timed by 4. So the sectornumber 33 is (33 – 32) * 4 + 32 = 36 dec. Sector 38 is (38 – 32) * 4 + 32 = 56 dec and so on.

Demo Project: Elatec.Net.SampleApp

usage example:

using Elatec.NET;
using Elatec.NET.Cards;
using Elatec.NET.Cards.Mifare;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ElatecNetSampleApp
{  
    internal class Program
    {
        static async Task Main(string[] args)
        {
            var reader = TWN4ReaderDevice.Instance.FirstOrDefault();

            if (await reader.ConnectAsync())
            {
                BaseChip chip = new BaseChip();

                await reader.BeepAsync(100, 1500, 500, 100);
                chip = await reader.GetSingleChipAsync();

                Console.WriteLine("CardType: {0}, UID: {1}, Multitype: ", Enum.GetName(typeof(ChipType), chip.ChipType), chip.UIDHexString);

                switch (chip.ChipType)
                {
                    case ChipType.MIFARE:

                        await reader.PlayMelody(120, MySongs.OhWhenTheSaints);
                        await reader.LedBlinkAsync(Leds.Green, 500, 500);

                        MifareChip mifareChip = (MifareChip)chip;

                        Console.WriteLine("\nFound: {0}\n", mifareChip.SubType);

                        switch (mifareChip.SubType)
                        {
                            case MifareChipSubType.DESFireEV1_256:
                            case MifareChipSubType.DESFireEV1_2K:
                            case MifareChipSubType.DESFireEV1_4K:
                            case MifareChipSubType.DESFireEV1_8K:
                                if(reader.IsTWN4LegicReader)
                                {
                                    // undocumented in elatec's devkit (as customersupport said): if the reader is a TWN4 Multitec with LEGIC capabilities,
                                    // SelectTag is not working. Instead, a SearchTag must be used. The SelectTag is then executed internally.
                                    await reader.SearchTagAsync();
                                }
                                else
                                {
                                    await reader.ISO14443A_SelectTagAsync(chip.UID);
                                }

                                await reader.MifareDesfire_SelectApplicationAsync(0);
                                await reader.MifareDesfire_CreateApplicationAsync(
                                    DESFireAppAccessRights.KS_DEFAULT,
                                    DESFireKeyType.DF_KEY_AES,
                                    1,
                                    0x3060);

                                var appIDs = await reader.MifareDesfire_GetAppIDsAsync();

                                foreach(var appID in appIDs)
                                {
                                    Console.WriteLine("\nFound AppID(s): {0}\n", appID.ToString("X8"));
                                }
                                break;
                        }

                        break;

                    default:
                        Console.WriteLine("Chip Found: {0}", Enum.GetName(typeof(ChipType), chip.ChipType));
                        break;
                }
            }  
        }
    }


    static class MySongs
    {
        public static List<TWN4ReaderDevice.Tone> OhWhenTheSaints
        {
            get => new List<TWN4ReaderDevice.Tone>()
            {
                new TWN4ReaderDevice.Tone() { Value = 4,  Volume = 0, Pitch = NotePitch.PAUSE },
                new TWN4ReaderDevice.Tone() { Value = 4,  Pitch = NotePitch.C3 },
                new TWN4ReaderDevice.Tone() { Value = 4,  Pitch = NotePitch.E3 },
                new TWN4ReaderDevice.Tone() { Value = 4,  Pitch = NotePitch.F3 },

                new TWN4ReaderDevice.Tone() { Pitch = NotePitch.G3 },

                new TWN4ReaderDevice.Tone() { Value = 4,  Volume = 0, Pitch = NotePitch.PAUSE },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.C3 },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.E3 },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.F3 },

                new TWN4ReaderDevice.Tone() { Pitch = NotePitch.G3 },
                // 1
                new TWN4ReaderDevice.Tone() { Value = 4,  Volume = 0, Pitch = NotePitch.PAUSE },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.C3 },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.E3 },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.F3 },

                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.G3 },
                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.E3 },

                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.C3 },
                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.E3 },

                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.E3 },
                new TWN4ReaderDevice.Tone() { Value = 12, Pitch = NotePitch.D3 },
                // 2
                new TWN4ReaderDevice.Tone() { Value = 4,  Volume = 0, Pitch = NotePitch.PAUSE },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.E3 },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.E3 },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.D3 },

                new TWN4ReaderDevice.Tone() { Value = 12, Pitch = NotePitch.C3 },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.C3 },

                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.E3 },
                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.G3 },

                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.G3 },
                new TWN4ReaderDevice.Tone() { Value = 12, Pitch = NotePitch.F3 },
                // 3
                new TWN4ReaderDevice.Tone() { Value = 4,  Volume = 0, Pitch = NotePitch.PAUSE },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.F3 },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.E3 },
                new TWN4ReaderDevice.Tone() { Value = 4, Pitch = NotePitch.F3 },

                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.G3 },
                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.E3 },

                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.C3 },
                new TWN4ReaderDevice.Tone() { Value = 8, Pitch = NotePitch.D3 },

                new TWN4ReaderDevice.Tone() { Pitch = NotePitch.C3 }
                // 4
            };
        }
    }
}

Contributors ✨

<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/c3rebro"> <img src="https://avatars.githubusercontent.com/u/5468524?v=4?s=100" width="100px;" alt="Steven (c3rebro)"/><br />
<sub><b>Steven (c3rebro)</b></sub></a><br />
<a href="#code" title="Code">💻</a> <td align="center" valign="top" width="14.28%"> <a href="https://github.com/faiteanu"> <img src="https://avatars.githubusercontent.com/u/63024793?v=4?s=100" width="100px;" alt="Fabian Aiteanu"/><br />
<sub><b>Fabian Aiteanu</b></sub></a><br /> <a href="#code" title="Code">💻</a> </tr>
</tbody> </table>

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  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 was computed.  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. 
.NET Framework net46 is compatible.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.4.0 121 3/5/2024
0.3.0 97 2/23/2024
0.2.0 117 1/16/2024

v0.4 Added DisconnectAsync()
v0.3 Incompatible changes: changed bytepattern of CardType
v0.2 take legic capable reader "specialties" into account. See Readme.MD for further details