PlcsAi 1.2.0
dotnet add package PlcsAi --version 1.2.0
NuGet\Install-Package PlcsAi -Version 1.2.0
<PackageReference Include="PlcsAi" Version="1.2.0" />
<PackageVersion Include="PlcsAi" Version="1.2.0" />
<PackageReference Include="PlcsAi" />
paket add PlcsAi --version 1.2.0
#r "nuget: PlcsAi, 1.2.0"
#:package PlcsAi@1.2.0
#addin nuget:?package=PlcsAi&version=1.2.0
#tool nuget:?package=PlcsAi&version=1.2.0
PlcsAi — .NET SDK for the PLCs.ai API
Interpret PLC code from your own tools. Official C# client for the
PLCs.ai API. Targets .NET Standard 2.0+ and .NET 8;
async-first, with IAsyncEnumerable<T> streaming.
Install
dotnet add package PlcsAi
Quickstart
using PlcsAi;
using var client = new PlcsClient("plck_live_…"); // or set PLCS_API_KEY
var result = await client.InterpretAsync(
projectId: "prj_…",
prompt: "Why is the filler at line 2 not advancing past Starting?");
Console.WriteLine(result.Answer);
Console.WriteLine(string.Join(", ", result.Citations));
Console.WriteLine(result.RequestId); // quote this in a support request
Streaming
await foreach (var ev in client.InterpretStreamAsync("prj_…", "…"))
{
if (ev.Type == "token") Console.Write(ev.Text);
else if (ev.Type == "done") Console.WriteLine($"\nusage: {ev.Usage}");
}
Conversations, analyses, ingest, embed tokens
var conv = await client.CreateConversationAsync("prj_…", "Line 2 stoppage");
await client.SendMessageAsync(conv.ConversationId, "And why now?");
var job = await client.StartAnalysisAsync("prj_…");
var done = await client.WaitForAnalysisAsync(job.AnalysisId);
await client.IngestProjectAsync(File.ReadAllBytes("Conveyor.L5X"), "Conveyor.L5X");
var token = await client.MintEmbedTokenAsync("prj_…"); // read-only, for the iframe
Billing consent (enterprise per-project orgs)
If your org is billed per project, creating a new project over the API
requires acknowledging the charge. Without it you get a 402 carrying the cost;
disclose it, then retry with acknowledgeBilling: true:
try
{
await client.IngestProjectAsync(File.ReadAllBytes("NewLine.L5X"), "NewLine.L5X");
}
catch (PlcsApiException e) when (e.Error == "billing_setup_required")
{
Console.WriteLine("Set up billing in the PLCs desktop app first.");
}
catch (PlcsApiException e) when (e.Error == "billing_acknowledgement_required")
{
Console.WriteLine($"This adds a billable project (~${e.Billing!.PricePerProjectCents / 100.0:0.00}). Confirming…");
await client.IngestProjectAsync(File.ReadAllBytes("NewLine.L5X"), "NewLine.L5X", acknowledgeBilling: true);
}
This applies only to enterprise per-project orgs creating a new project — other org types and re-uploads/new versions are unaffected.
Projects: list, read source, live values
var page = await client.ListProjectsAsync(limit: 50);
foreach (var p in page.Projects) Console.WriteLine($"{p.ProjectId} {p.Name} {p.Vendor}");
var detail = await client.GetProjectAsync("prj_…"); // metadata + AnalysisStatus
var src = await client.GetSourceAsync("prj_…", "scl"); // parsed | scl | ladder (needs code_read)
byte[] rawBytes = await client.DownloadSourceAsync("prj_…"); // original L5X / ZIP bytes
var values = await client.GetHmiValuesAsync("prj_…"); // needs hmi_view; Live=false when no DCA session
var history = await client.GetHmiHistoryAsync("prj_…", "Motor1.Speed");
Exports (async): PLC file & PDF report
var job = await client.ExportPlcAsync("prj_…"); // or ExportPdfAsync(...)
var done = await client.WaitForExportAsync(job.ExportId);
byte[] artifact = await client.DownloadExportAsync(done.ExportId); // L5X / ZIP / PDF bytes
File.WriteAllBytes(done.Filename!, artifact);
Save a new version (code_write)
var res = await client.CommitVersionAsync("prj_…", File.ReadAllBytes("Conveyor_edited.L5X"), "Conveyor.L5X");
Console.WriteLine($"{res.Resolution} {res.VersionId}"); // add_version, or identical_file (no-op)
Generate code (ai_generate — proposes, never deploys)
var proposal = await client.GenerateAsync("prj_…", "Add a 5-second start-up delay timer.");
Console.WriteLine(proposal.GeneratedCode);
foreach (var block in proposal.CodeBlocks) Console.WriteLine($"{block.Language}: {block.Content}");
// To persist, commit the edited file via client.CommitVersionAsync(...) (code_write).
What the client handles for you
- Auth — sends
Authorization: Bearer …on every request. - Idempotency — auto-generates a stable
Idempotency-Keyper write (reused across retries). - Retries — retries only on retryable errors, respecting
Retry-After. - Streaming — parses SSE into
StreamEvents overIAsyncEnumerable<T>. RequestId— surfaced on every result.
Errors
Non-2xx responses throw PlcsApiException with StatusCode, Error,
UserMessage, SuggestedAction, IsRetryable, and RequestId.
Development
dotnet test
Releasing (maintainers)
Published to NuGet as PlcsAi. Bump <Version> in src/PlcsAi/PlcsAi.csproj, then:
dotnet pack src/PlcsAi -c Release
dotnet nuget push src/PlcsAi/bin/Release/PlcsAi.<version>.nupkg --source nuget.org --api-key $NUGET_API_KEY
| Product | Versions 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 was computed. 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 was computed. 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. |
-
.NETStandard 2.0
- Microsoft.Bcl.AsyncInterfaces (>= 8.0.0)
- System.Text.Json (>= 8.0.5)
-
net8.0
- System.Text.Json (>= 8.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.