GS1 EPC Tag Data Translation (TDT 2.2 / TDS 2.3) library for RAIN RFID. Cross-platform: .NET, .NET MAUI, Android, iOS, macCatalyst. Supports encoding/decoding of SGTIN, SSCC, SGLN, GRAI, GIAI, GSRN, GDTI, SGCN, ITIP, GID, CPI, ADI, USDOD and Digital Link URIs. Includes TDS 2.3 '+' and '++' schemes with custom hostname encoding. Converts between binary, hex, tag URI, pure identity URI, and legacy formats.
$ dotnet add package TagDataTranslationEncode and decode GS1 EPC identifiers for RAIN (UHF) RFID tags. Convert between GTIN, SSCC, SGLN, and 50+ other formats — from barcode to EPC hex and back.
Implements the GS1 EPC Tag Data Standard (TDS) 2.3 and Tag Data Translation (TDT) 2.2 specifications. Used in production for RFID tag programming, inventory systems, and supply chain applications.
Try it online: https://www.mimasu.nl/tag-data-translation/try-online
TryTranslate API for high-throughput tag programming and reading| Platform | Package | Status |
|---|---|---|
| .NET 8/9/10 |
| NuGet |
| Available |
| .NET MAUI (Android) | NuGet | Available (3.0.0+) |
| .NET MAUI (iOS) | NuGet | Available (3.0.0+) |
| .NET MAUI (macCatalyst) | NuGet | Available (3.0.0+) |
| JavaScript/TypeScript | npm | Available (3.0.0+) |
| Python | PyPI | Available (3.0.0+) |
| iOS (Swift) | Swift Package Manager | Available (3.0.0+) |
| Android (Kotlin/Java) | GitHub Packages | Available (3.0.0+) |
| Flutter (Dart) | pub.dev | Available (3.0.0+) |
| Scheme | Formats |
|---|---|
| SGTIN | SGTIN-96, SGTIN-198, SGTIN+, SGTIN++ |
| SSCC | SSCC-96, SSCC+, SSCC++ |
| SGLN | SGLN-96, SGLN-195, SGLN+, SGLN++ |
| GRAI | GRAI-96, GRAI-170, GRAI+, GRAI++ |
| GIAI | GIAI-96, GIAI-202, GIAI+, GIAI++ |
| GSRN | GSRN-96, GSRN+, GSRN++ |
| GSRNP | GSRNP-96, GSRNP+, GSRNP++ |
| GDTI | GDTI-96, GDTI-113, GDTI-174, GDTI+, GDTI++ |
| SGCN | SGCN-96, SGCN+, SGCN++ |
| ITIP | ITIP-110, ITIP-212, ITIP+, ITIP++ |
| GID | GID-96 |
| CPI | CPI-96, CPI-var, CPI+, CPI++ |
| ADI | ADI-var |
| USDOD | USDOD-96 |
| DSGTIN | DSGTIN+, DSGTIN++ |
'++' schemes (TDS 2.3) support lossless encoding of custom hostnames in EPC binary, enabling round-trip translation with branded Digital Link URIs like https://coca-cola.com/01/... instead of https://id.gs1.org/01/....
dotnet add package TagDataTranslation
Or via Package Manager:
Install-Package TagDataTranslation
The NuGet package includes targets for .NET 8.0/9.0/10.0, Android, iOS, and macCatalyst. .NET MAUI projects will automatically resolve the correct platform target.
git clone https://github.com/dannyhaak/TagDataTranslation.git
cd TagDataTranslation
dotnet build src/TagDataTranslation/TagDataTranslation.csproj
dotnet workload install maui)using TagDataTranslation;
var engine = new TDTEngine();
string epcIdentifier = "gtin=00037000302414;serial=10419703";
string parameterList = "filter=3;gs1companyprefixlength=7;tagLength=96";
string binary = engine.Translate(epcIdentifier, parameterList, "BINARY");
string hex = engine.BinaryToHex(binary);
// hex = "30340242201d8840009efdf7"
var engine = new TDTEngine();
string binary = engine.HexToBinary("30340242201d8840009efdf7");
string parameterList = "tagLength=96";
string legacy = engine.Translate(binary, parameterList, "LEGACY");
// legacy = "gtin=00037000302414;serial=10419703"
var engine = new TDTEngine();
var result = engine.TranslateDetails("30340242201d8840009efdf7", "tagLength=96", "TAG_ENCODING");
Console.WriteLine($"Pure Identity: {result.Fields["pureIdentityURI"]}");
Console.WriteLine($"Tag URI: {result.Fields["tagURI"]}");
Console.WriteLine($"GTIN: {result.Fields["gtin"]}");
Console.WriteLine($"Serial: {result.Fields["serial"]}");
using TagDataTranslation.DigitalLink;
var components = new DigitalLinkComponents
{
Domain = "id.gs1.org",
PrimaryKey = ("01", "00037000302414"), // AI 01 = GTIN
KeyQualifiers = new List<(string, string)>
{
("21", "10419703") // AI 21 = Serial
}
};
string digitalLink = DigitalLinkGenerator.Generate(components);
// https://id.gs1.org/01/00037000302414/21/10419703
if (DigitalLinkParser.TryParse("https://id.gs1.org/01/00037000302414/21/10419703", out var components))
{
Console.WriteLine($"GTIN: {components.PrimaryKey.Value}");
// GTIN: 00037000302414
}
var engine = new TDTEngine();
var result = engine.GetPrefixLength("0037000302414");
Console.WriteLine($"Prefix: {result.Prefix}, Length: {result.Length}");
// Prefix: 0037000, Length: 7
var engine = new TDTEngine();
if (engine.LoadErrors.Count > 0)
{
foreach (var error in engine.LoadErrors)
{
Console.WriteLine(error);
}
}
public string Translate(string epcIdentifier, string parameterList, string outputFormat)
Translates an EPC identifier from one representation to another.
| Parameter | Description |
|---|---|
epcIdentifier | The EPC to convert (binary string, hex, URI, or legacy format) |
parameterList | Semicolon-delimited key=value pairs (e.g., filter=3;gs1companyprefixlength=7;tagLength=96) |
outputFormat | Target format: BINARY, LEGACY, LEGACY_AI, TAG_ENCODING, PURE_IDENTITY |
Returns: The converted EPC as a string.
public TranslateResult TranslateDetails(string epcIdentifier, string parameterList, string outputFormat)
Same as Translate, but returns a TranslateResult object containing all extracted fields.
public bool TryTranslate(string epcIdentifier, string parameterList, string outputFormat, out string? result, out string? errorCode)
Translates an EPC identifier without throwing exceptions. Ideal for high-throughput scenarios.
if (engine.TryTranslate(epcIdentifier, parameterList, "BINARY", out var result, out var errorCode))
{
Console.WriteLine($"Success: {result}");
}
else
{
Console.WriteLine($"Failed: {errorCode}");
}
public bool TryTranslateDetails(string epcIdentifier, string parameterList, string outputFormat, out TranslateResult? result, out string? errorCode)
Same as TryTranslate, but returns a TranslateResult object on success.
public PrefixLengthResult GetPrefixLength(string input)
Looks up the GS1 Company Prefix length for a given identifier.
public Dictionary<int, string> GetFilterValueTable(string scheme)
Returns the filter value descriptions for a scheme (e.g., "SGTIN" returns {0: "All Others", 1: "POS Item", ...}).
public IReadOnlyList<string> LoadErrors { get; }
Contains any errors encountered while loading scheme files. Inspect this after construction to debug missing or malformed schemes.
public string HexToBinary(string hex) // Convert hex to binary string
public string BinaryToHex(string binary) // Convert binary string to hex
TDTTranslationException is thrown with one of these codes:
| Code | Description |
|---|---|
TDTFileNotFound | Scheme definition file not found |
TDTFieldBelowMinimum | Numeric field below minimum value |
TDTFieldAboveMaximum | Numeric field above maximum value |
TDTFieldOutsideCharacterSet | Field contains invalid characters |
TDTUndefinedField | Required field is missing |
TDTSchemeNotFound | No matching scheme found |
TDTLevelNotFound | No matching level found |
TDTOptionNotFound | No matching option found |
TDTLookupFailed | External table lookup failed |
TDTNumericOverflow | Numeric overflow occurred |
Benchmarked on Apple M1 Pro, .NET 8.0 (BenchmarkDotNet):
| Operation | Mean | Allocated |
|---|---|---|
| SGTIN-96 encode (GTIN → binary) | 7.8 us | 9.9 KB |
| SGTIN-96 decode (binary → GTIN) | 7.7 us | 9.2 KB |
| SGTIN++ encode (with hostname) | 24.3 us | 75.3 KB |
| SGTIN++ decode (with hostname) | 5.0 us | 7.8 KB |
| HexToBinary (96-bit) | 99 ns | 480 B |
| BinaryToHex (96-bit) | 54 ns | 192 B |
The engine uses compiled regex caching, pre-sorted scheme data, and lookup tables for hex/binary conversion. The TDTEngine constructor loads all schemes once; subsequent Translate() calls benefit from cached patterns and pre-computed data structures.
Run benchmarks yourself:
dotnet run -c Release --project test/TagDataTranslation.Benchmarks
See the examples/ directory for platform-specific sample projects:
examples/ConsoleApp/ -- .NET console applicationexamples/MauiApp/ -- .NET MAUI cross-platform app (Android, iOS, macCatalyst)examples/NodeApp/ -- Node.js application (via WebAssembly)dotnet build src/TagDataTranslation/TagDataTranslation.csproj
dotnet test test/TagDataTranslation.Tests/TagDataTranslation.Tests.csproj
dotnet pack src/TagDataTranslation/TagDataTranslation.csproj -c Release -o ./artifacts
To publish to NuGet.org:
dotnet nuget push ./artifacts/TagDataTranslation.*.nupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json
| Version | Changes |
|---|---|
| 3.0.0 | Cross-platform SDKs: npm (WASM), Python (pythonnet), Swift (NativeAOT), Android (NativeAOT), Flutter (dart:ffi), .NET MAUI (Android, iOS, macCatalyst); performance optimizations (regex caching, lookup tables, pre-sorted fields); BSL 1.1 licensing |
| 2.3.0 | TDS 2.3 support with 12 new '++' schemes for custom hostname encoding in Digital Link URIs |
| 2.1.0 | Added TryTranslate/TryTranslateDetails for exception-free high-throughput translation |
| 2.0.1 | Multi-targeting support for .NET 8.0, 9.0, and 10.0 |
| 2.0.0 | TDT 2.2 with JSON schemes, Digital Link support, new schemes (DSGTIN+, GDTI-113, etc.) |
| 1.1.5 | Updated GCP prefix file, ITIP encoding fixes |
| 1.0.0 | Initial release with TDT 1.6/1.11 support |
This library is licensed under the Business Source License 1.1 (BSL 1.1).
See LICENSING.md for full details.
The included JSON and XSD artifacts are (c) GS1 (https://www.gs1.org/standards/epc-rfid/tdt).