This article documents the IReportConverter_v2 interface — the standard contract that every file-based WATS converter must implement. Understanding this interface is the foundation for building any custom converter.
Namespace
using Virinco.WATS.Interface;
Interface definition
/// <summary>
/// Standard interface for WATS file-based converters.
/// Implement this interface on your converter class.
/// </summary>
public interface IReportConverter_v2
{
/// <summary>
/// Converter parameters exposed in the WATS Client configurator UI.
/// Keys become parameter names; values are the defaults shown to the user.
/// The WATS Client merges saved values over these defaults at runtime.
/// </summary>
Dictionary<string, string> ConverterParameters { get; }
/// <summary>
/// Called by the WATS Client Service for every file that matches the
/// converter's file filter.
/// </summary>
/// <param name="api">
/// A connected TDM API instance. Use it to create UUT/UUR reports and
/// to submit reports if needed (multi-UUT files).
/// </param>
/// <param name="file">
/// Read-only stream of the source file being converted.
/// Do NOT close or dispose this stream — WATS Client owns it.
/// </param>
/// <returns>
/// The completed report. WATS Client submits it automatically.
/// Return null ONLY if you called api.Submit() yourself (multi-UUT files).
/// </returns>
Report? ImportReport(TDM api, Stream file);
/// <summary>
/// Called after the report is submitted (or after an error).
/// Use this to delete temporary files or release any resources held since
/// ImportReport was called.
/// </summary>
void CleanUp();
}
Constructor patterns
WATS Client instantiates your converter class via its constructor. Two patterns are supported:
Parameterless constructor (simple)
public class MyConverter : IReportConverter_v2
{
public Dictionary<string, string> ConverterParameters { get; } = new()
{
["defaultOperationType"] = "Final Test",
};
// No constructor needed if using auto-property initializer
}
Parameterized constructor (recommended)
Declare a constructor that accepts IDictionary<string, string>. The WATS Client passes the saved values from converters.xml. This lets you validate and cache parameters at startup rather than reading them on every file.
public class MyConverter : IReportConverter_v2
{
private readonly string _operationType;
private readonly char _delimiter;
/// <summary>
/// Constructor called by WATS Client at service startup.
/// </summary>
/// <param name="args">
/// Parameters from converters.xml, merged with defaults from
/// <see cref="ConverterParameters"/>. Always use TryGetValue —
/// keys absent from the saved config fall back to defaults.
/// </param>
public MyConverter(IDictionary<string, string> args)
{
_operationType = args.TryGetValue("defaultOperationType", out var op)
? op : "Final Test";
_delimiter = args.TryGetValue("csvDelimiter", out var d) && d.Length > 0
? d[0] : ',';
}
// ConverterParameters defines the defaults shown in the configurator UI.
// WATS Client merges saved values over these before passing them to the ctor.
public Dictionary<string, string> ConverterParameters { get; } = new()
{
["defaultOperationType"] = "Final Test",
["csvDelimiter"] = ",",
};
public Report? ImportReport(TDM api, Stream file) { /* ... */ return null; }
public void CleanUp() { }
}
ConverterParameters
Parameters defined here appear as editable fields in the WATS Client configurator. Use them for settings that vary between deployments: operation type codes, file delimiters, fallback values, etc.
- Keys must be valid XML attribute names (no spaces, no special characters).
- Values are always strings — parse to the required type in the constructor or in
ImportReport. - Saved values in
converters.xmlare merged over the defaults at runtime.
// Example: parameters for a production converter
public Dictionary<string, string> ConverterParameters { get; } = new()
{
["operationTypeCode"] = "50", // WATS process code
["csvDelimiter"] = ",", // file-specific delimiter
["defaultRevision"] = "A", // fallback revision
["skipHeaderRows"] = "1", // number of header rows to skip
};
ImportReport
The core method. Called once per file. Key rules:
- Never construct
UUTReportdirectly — always useapi.CreateUUTReport(). - Never close or dispose the
filestream. - Return the completed report. WATS Client calls
api.Submit(report)for you. - Return
nullonly if you calledapi.Submit()yourself (e.g., multi-UUT files). - Throw an exception to signal a parse error — the file will move to the
Error\folder.
public Report? ImportReport(TDM api, Stream file)
{
// Parse file
using var reader = new StreamReader(file);
var content = reader.ReadToEnd();
// Create UUT — NEVER new UUTReport()
UUTReport uut = api.CreateUUTReport(
operatorName: "",
partNumber: "PN-001",
revision: "A",
serialNumber: "SN-001",
operationType: "Final Test", // must exist in WATS
sequenceFileName: "",
sequenceFileVersion: ""
);
uut.StartDateTimeUTC = DateTime.UtcNow;
uut.ExecutionTime = 42.5; // seconds
uut.Status = UUTStatusType.Passed;
return uut; // WATS Client submits it
}
CleanUp
Called after every file, whether it succeeded or failed. Use it to:
- Reset per-file state (if you store parsed data as fields)
- Delete temporary files created during parsing
- Release file handles (other than the
filestream)
private string? _tempFilePath;
public void CleanUp()
{
if (_tempFilePath != null && File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
_tempFilePath = null;
}
Multi-UUT files
If one source file contains data for multiple UUTs, submit each one individually and return null:
public Report? ImportReport(TDM api, Stream file)
{
var allUuts = ParseMultipleUUTs(file);
foreach (var data in allUuts)
{
UUTReport uut = api.CreateUUTReport(
operatorName: data.Operator, partNumber: data.PN,
revision: data.Rev, serialNumber: data.SN,
operationType: data.Process, sequenceFileName: "", sequenceFileVersion: "");
uut.StartDateTimeUTC = data.StartTime;
uut.Status = data.Passed ? UUTStatusType.Passed : UUTStatusType.Failed;
api.Submit(uut); // submit each UUT individually
}
return null; // tell WATS Client: "already submitted"
}
NuGet package reference
<PackageReference Include="Virinco.WATS.ClientAPI" Version="7.*">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
PrivateAssets=all means the package is compile-only. The DLL is not copied to your output folder because the WATS Client Service provides its own copy at runtime.
Comments
0 comments
Please sign in to leave a comment.