Skip to content

tofupilot/csharp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TofuPilot C# Client

License: MIT .NET Tests

The official C# client for TofuPilot. Integrate your hardware test runs into one app with just a few lines of C#.

Installation

Add a project reference:

dotnet add reference path/to/TofuPilot.csproj

Quick Start

using TofuPilot;
using TofuPilot.Models.Requests;

var client = new TofuPilot(apiKey: Environment.GetEnvironmentVariable("TOFUPILOT_API_KEY")!);

var run = await client.Runs.CreateAsync(new RunCreateRequest
{
    ProcedureId = "your-procedure-id",
    SerialNumber = "SN001",
    PartNumber = "PN001",
    Outcome = RunCreateOutcome.Pass,
    StartedAt = DateTime.UtcNow.AddMinutes(-5),
    EndedAt = DateTime.UtcNow,
});

Console.WriteLine($"Run created: {run.Id}");

All async methods support CancellationToken:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
var run = await client.Runs.CreateAsync(request, cts.Token);

Authentication

Set your API key as an environment variable:

export TOFUPILOT_API_KEY="your-api-key"

Or pass it directly:

var client = new TofuPilot(apiKey: "your-api-key");

To point to a different server (e.g. self-hosted):

var client = new TofuPilot(
    apiKey: "your-api-key",
    serverUrl: "https://your-instance.com/api"
);

Custom certificates

using System.Security.Cryptography.X509Certificates;
using TofuPilot.Utils;

var handler = new HttpClientHandler();
handler.ClientCertificates.Add(new X509Certificate2("client.pfx", "password"));

var client = new TofuPilot(
    apiKey: "your-api-key",
    client: new TofuPilotHttpClient(handler)
);

Available Resources

Resource Operations
client.Runs List, Create, Get, Delete, Update
client.Units List, Create, Get, Delete, Update, AddChild, RemoveChild
client.Parts List, Create, Get, Delete, Update
client.Parts.Revisions Create, Get, Delete, Update
client.Procedures List, Create, Get, Delete, Update
client.Procedures.Versions Create, Get, Delete
client.Batches List, Create, Get, Delete, Update
client.Stations List, Create, Get, GetCurrent, Remove, Update
client.Attachments Initialize, Finalize, Delete
client.User List

Usage Examples

Create a run with measurements

var run = await client.Runs.CreateAsync(new RunCreateRequest
{
    ProcedureId = procedureId,
    SerialNumber = "SN-001",
    PartNumber = "PCB-V1",
    Outcome = RunCreateOutcome.Pass,
    StartedAt = DateTime.UtcNow.AddMinutes(-5),
    EndedAt = DateTime.UtcNow,
    Phases = new List<RunCreatePhases>
    {
        new()
        {
            Name = "Voltage Test",
            Outcome = RunCreatePhasesOutcome.Pass,
            StartedAt = DateTime.UtcNow.AddMinutes(-5),
            EndedAt = DateTime.UtcNow,
            Measurements = new List<RunCreateMeasurements>
            {
                new()
                {
                    Name = "Output Voltage",
                    Outcome = RunCreateMeasurementsOutcome.Pass,
                    MeasuredValue = 3.3,
                    Units = new RunCreateUnits { Value = "V" },
                    Validators = new List<RunCreateValidators>
                    {
                        new() { Operator = ">=", ExpectedValue = RunCreateExpectedValue.CreateNumber(3.0) },
                        new() { Operator = "<=", ExpectedValue = RunCreateExpectedValue.CreateNumber(3.6) },
                    },
                },
            },
        },
    },
});

List and filter runs

var result = await client.Runs.ListAsync(
    partNumbers: new List<string> { "PCB-V1" },
    outcomes: new List<RunListQueryParamOutcome> { RunListQueryParamOutcome.Pass },
    limit: 10
);

foreach (var run in result.Data)
    Console.WriteLine($"{run.Id}{run.Unit.SerialNumber}");

Manage units and sub-units

// Create part and revision
await client.Parts.CreateAsync(new PartCreateRequest { Number = "PCB-V1", Name = "Main Board" });
await client.Parts.Revisions.CreateAsync("PCB-V1", new PartCreateRevisionRequestBody { Number = "REV-A" });

// Create units
await client.Units.CreateAsync(new UnitCreateRequest
{
    SerialNumber = "PARENT-001",
    PartNumber = "PCB-V1",
    RevisionNumber = "REV-A",
});
await client.Units.CreateAsync(new UnitCreateRequest
{
    SerialNumber = "CHILD-001",
    PartNumber = "PCB-V1",
    RevisionNumber = "REV-A",
});

// Link parent-child
await client.Units.AddChildAsync("PARENT-001", new UnitAddChildRequestBody
{
    ChildSerialNumber = "CHILD-001",
});

Upload and download attachments

// Upload a file (one line)
var attachmentId = await client.Attachments.UploadAsync("report.pdf");

// Link to a run
await client.Runs.UpdateAsync(runId, new RunUpdateRequestBody
{
    Attachments = new List<string> { attachmentId },
});

// Download an attachment
await client.Attachments.DownloadAsync(downloadUrl, "local-copy.pdf");

Error Handling

API errors throw typed exceptions:

using TofuPilot.Models.Errors;

try
{
    await client.Runs.GetAsync("nonexistent-id");
}
catch (NotFoundException ex)
{
    Console.WriteLine($"Not found: {ex.Message}");
}
catch (BadRequestException ex)
{
    Console.WriteLine($"Bad request: {ex.Message}");
}
catch (ApiException ex)
{
    Console.WriteLine($"API error {ex.StatusCode}: {ex.Body}");
}
Exception Status Code
BadRequestException 400
UnauthorizedException 401
ForbiddenException 403
NotFoundException 404
ConflictException 409
UnprocessableContentException 422
InternalServerErrorException 500
ApiException Any other

Running Tests

cd clients/csharp/tests
# Create .env.local with your API key and URL:
# TOFUPILOT_URL=http://localhost:3000
# TOFUPILOT_API_KEY_USER=your-api-key
dotnet test

Documentation

Acknowledgments

This package builds on the original C# client created by @Hylaean (versions 1.x).

License

MIT

About

Upload hardware test data to TofuPilot from C#.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages