AAComm

AAComm is a C# .NET API for PC-to-Controller communications, supporting a wide range of .NET targets and Windows platforms.

Overview

AAComm provides a robust interface for communicating with motion controllers from .NET applications. It is designed for both high-level and low-level control, supporting multiple communication channels and controller types.

  • Supported platforms: Windows 10 or later (Windows 7 SP1 or later on the .NET Framework 4.8 build)
  • Supported frameworks: .NET Framework 4.8, .NET 8, .NET 10; class libraries can target .NET Standard 2.0
  • Required files: AAComm.dll plus the bundled server matching your framework — .NET Framework 4.8: the aacommserver\ folder (the AACommServer.exe WPF host with its full closure); .NET 8 and .NET 10: AACommServerNative.exe (self-contained native host, win-x64). The NuGet package copies the right one to your output automatically — do not hand-assemble a partial server file set (a net48 server under a net8 consumer crashes on launch). No Linux/macOS sidecar ships yet: a non-Windows .NET 8/10 consumer must supply its own host-native AACS build and pass its full path to StartAACommServer — the copied AACommServerNative.exe is the Windows artifact, not a host-native server.
  • Documentation: API documentation is available via IntelliSense (XML doc comments included with the package).

Managed firmware simulation

For ChannelType.Simulation, set ConnectionData.SimExePath and, when known, its ControllerType. When the caller has no known identity or explicit supply, the server reads the sibling sim.info product ID before its first probe. It writes an explicit vbus_v from the verified product supply table: 308.941 V for AGD155/AGD155-EC, 310.497 V for AGD156-EC, 48.057 V for AGD101-EC, and 47.998 V for AGD200/AGC300, AGD301/AGC301 and AGM800/AGM800-EC.

An explicit vbus_v in SimMotorProfile takes precedence over that nominal value; the other profile keys are retained. A blank profile gets the generic PMSM motor with the selected product's supply. An unknown product requires a profile with an explicit finite positive supply, such as vbus_v=325.123. Missing, malformed, non-finite or non-positive supplies are refused before the simulator launches. There is no generic48V or firmware-default fallback. The normal controller-type check remains in force.

Server-side profile editors can call AACommServerCore.Comms.SimProfileWriter.DefaultText(double) with an explicit voltage, or Resolve / Write with a known product ID and an optional caller voltage. Existing explicit profile values take precedence. The parameterless DefaultText() refuses because it has no supply identity.

Motor profile keys use the firmware's ASCII space/tab syntax. Physical lines are limited to254UTF-8 bytes so the firmware's fixed buffer cannot expose a hidden second record. An initial explicit global supply is also written as a headerless seed, ensuring every possible axis has a supply even when the firmware interprets a group header differently for different axis counts. Other profile content is retained.

The simulator package must retain its complete starter.par beside its executable. Before a fresh managed launch the server derives the selected motor's complete agito.par from that template in the actual memory folder, including its encoder resolution, pole pairs and operating settings. The physical motor.txt is written there too. An existing runtime parameter file and sibling user program are preserved; an ephemeral connection receives a fresh configuration that is removed with its scratch folder. Opening the channel sends no firmware requests: normal Load() restores the runtime file, including deliberately saved motor type zero and custom gains.

To explicitly reconfigure a disconnected persistent simulation, call AAComm.Services.SimParameterFile.Configure(exePath, motorProfile, memoryFolder, productId). This replaces motor.txt and agito.par while retaining other memory files. Supply a known product or an explicit valid bus voltage. Missing, empty, duplicate or incomplete starter settings and invalid active encoder values are refused before replacing saved parameters. Parameter generation accepts canonical [global], [all] and [A] through [L] motor sections, including lowercase axis letters. The two files are replaced separately; after a filesystem error, complete a successful reconfiguration before launching the simulation.

System Requirements

  • Microsoft Windows 10 or later; Windows 7 SP1 or later for the .NET Framework 4.8 build
  • .NET Framework 4.8, .NET 8 or .NET 10
  • Visual Studio 2022 or later (other IDEs may be used, but are not officially supported)

Installation

Install the NuGet package from nuget.org:

dotnet add package Agito.AAComm

Or via the NuGet Package Manager in Visual Studio.

Note:
The bundled server is copied to your output directory automatically by the NuGet package — the aacommserver\ folder for .NET Framework consumers, AACommServerNative.exe for .NET 8 and .NET 10 consumers. For a manual (non-NuGet) deployment, copy that complete server payload as-is; never mix the net48 server into a net8 output.

Getting Started

  1. Create a new C# project.
  2. Add the Agito.AAComm NuGet package.
  3. For Windows: build — the bundled server lands in your output directory and CommAPI.StartAACommServer() resolves it from there; or pass an explicit executable path.
  4. For non-Windows: Specify the full path to a host-native AACommServer build when starting the server (no non-Windows sidecar is packaged — the copied AACommServerNative.exe is win-x64 only).

Usage Example

Below is a minimal example demonstrating how to start the AAComm server, connect to a controller, and send/receive messages:

using AAComm;
using AAComm.Services;
using AAComm.Shared;

ConnectResult aacs = CommAPI.StartAACommServer();
Console.WriteLine($"AACommServer start: {aacs}");

var api = new CommAPI();
var cd = new ConnectionData
{
    CommChannelType = ChannelType.Ethernet,
    ET_IP_1 = 172, ET_IP_2 = 1, ET_IP_3 = 1, ET_IP_4 = 101,
};

var res = api.Connect(cd);
Console.WriteLine($"Connect Result: {res}");

if (res != ConnectResult.Success)
{
    res = api.Connect(cd, true);
    Console.WriteLine($"FORCE Connect Result: {res}");

    if (res != ConnectResult.Success)
    {
        OnExit();
        return;
    }
}

var msgRes = api.SendReceive(new AACommMessage("APos"));
Console.WriteLine($"SYNC: APos = {msgRes.MsgReceived}");

ArrayDownloadResult download = api.DownloadArray(
    "BPVAJList",
    firstIndex: 1,
    values: new double[] { 197, 8, 1, 1000, -200, 3000, -4000 });
Console.WriteLine(
    $"{download.Transport}: {download.AppliedCount}/{download.ReceivedCount}, " +
    $"failed index={download.FirstFailedIndex}, stream error={download.StreamError}");

api.Send(new AACommMessage(OnReceive, "APos"));
//wait for async response at OnReceive callback

OnExit();
api.Disconnect();

void OnExit()
{
    Console.WriteLine("press any key to exit");
    Console.ReadKey();
    api.CloseAACommServer();
}

void OnReceive(object sender, AACommEventArgs e)
{
    Console.WriteLine($"ASYNC: APos = {e.MsgReceived}");
}

API Documentation

API documentation is available via IntelliSense. XML doc comments are included with the NuGet package.

Release Notes

See CHANGELOG.md for detailed release notes and version history.

License

This software is licensed under the MIT License. See the NuGet package metadata for details.


For further information, consult the included documentation or contact Agito support.

Connection-bound operations

Capture api.CaptureSession() once for a multi-request operation. A null handle means no connection is available. Keep that handle for every request and observe ConnectionClosed; disconnecting invalidates it even when the next connection uses the same endpoint. SendReceive never moves an old request or cleanup operation to the replacement connection. Readiness and operation results belong to the captured connection.

Central-i master metadata discovery reads the live Identity[62] preload API bit0x200 before selecting a keyword cache. Capable and legacy metadata use separate cache variants under the existing product/version/build key. A failed capability inquiry does not imply an unsupported controller. Standalone controllers retain their existing discovery path.

Coherent hardware event-table observation

AAComm.Services.Events.EventTableStatusReader reads live status and retained errors for one axis on its captured connection. Create a new reader after reconnect. ReadAsync requires the verified-table Identity capability and matching LONG32 metadata, reads the specified 37 values in order (one Ethernet bulk or sequential inquiries), and accepts only equal even publication generations. It retries once immediately, with two seconds per attempt and a four-second host deadline. Unavailable results contain no cached status. The result invalidates its status when its connection closes.

State, counts, session, CRCs, source/configuration generations, remote capabilities and retained error provenance are typed. CaptureAgeAtPublicationMilliseconds and freshness flags describe publication time; a small retained age is not current remote-health proof. Polling never acknowledges an error. Slow links may miss Running during a finite burst and subsequently observe terminal Complete. Explicit arm and final completion inquiries remain mandatory.

Cancellation stops the host wait and abandons unsent inquiries. An already sent read drains its reply on its original connection; cancellation sends no remote Abort and does not establish that motion or events stopped.

Explicit verified event lifecycle

EventTableClient (Services/Events/verified-event-tables.md) provides immutable table preparation, fenced readback, explicit verified Load/Arm/Complete and Abort/acknowledgement cleanup on one captured session. It retains ambiguous ownership across cancellation or connection loss; replacement-origin recovery is unavailable without server retirement proof. AAMotion exposes the same client through MotionController.CreateEventTableClient(axis).