Skip to content

Releases: underautomation/Fanuc.NET

v6.2.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 13:50

More robot models in ArmKinematicModels

The following models have been added to the ArmKinematicModels enum:

  • ARCMate100iDDC, ARCMate100iDFG, ARCMate100iD16SB441
  • ARCMate120iDFG
  • CR35iB, CR7iAL_2
  • CRX3iA, CRX5iA, CRX20iAL, CRX30iA, CRX10iALPaint
  • LR10iA10, LRMate1011AFoodClean, LRMate200iD7WE
  • M710iC20L, M710iD50M, M710iD70
  • M800iB60, M8006020B, M81019020B, M81027027B
  • M900iB700E, M910400F37B, M950iA500, M950iA500SE, M950500F28A
  • M1000iA, M1000550F46A, M410800F32C
  • R2000iC190S, R2000iC190SSE, R2000iC270FSE
  • R2000125F31E, R2000210F31E, R2000300F27E, R2000180F27E

Note: do not rely on the implicit integer values of ArmKinematicModels members. The enum is sorted alphabetically and new models may be inserted at any position in future releases, shifting the integer values of existing members. Always use the named members, not their numeric equivalents.

CRX inverse kinematics: analytical solver, no seed required

The CRX cobot inverse kinematics solver has been rewritten using a closed-form geometric approach. It now computes all valid joint solutions for a given Cartesian pose without requiring a seed position.

The seedJoints parameter has been removed from CrxKinematicsUtils.InverseKinematics. If your code was passing a seed, remove that argument.

The solver is now around 3x faster. The includeDuals parameter remains available to control whether dual solutions are included.

var dh = DhParameters.FromArmKinematicModel(ArmKinematicModels.CRX10iA);
var target = new CartesianPosition { X = 400, Y = 250, Z = 650, W = 0, P = 90, R = 0 };

// All solutions are returned, no seed needed
JointsPosition[] solutions = KinematicsUtils.InverseKinematics(target, dh);

// Or call the CRX-specific method directly
JointsPosition[] solutions = CrxKinematicsUtils.InverseKinematics(target, dh, includeDuals: true);

v6.1.0.0

Choose a tag to compare

@github-actions github-actions released this 12 Jul 21:02

Bug fixes

  • Fixed a missing namespace declaration on FtpExistsBehavior, which caused the type to be inaccessible when referenced from outside the assembly.
  • Fixed incorrect namespace references in RMI motion instruction classes, which prevented motion instructions from working correctly.

v6.0.0.0

Choose a tag to compare

@github-actions github-actions released this 12 Jul 18:08

RMI: complete API rewrite

The RMI client has been redesigned from scratch. The previous method-per-instruction API is replaced by an instruction object model that is easier to extend and closer to how the controller actually works.

Instruction pipeline

Each call to SendTpInstruction now returns an RmiInstructionResponse that you can poll or block on:

RmiInstructionResponse r = robot.Rmi.SendTpInstruction(new LinearMotionTpInstruction
{
    SpeedType = RmiLinearSpeedType.MmSec,
    Speed = 100,
    TermType = RmiTerminationType.Fine,
    Target = new CartesianPositionWithUserFrame(500, 200, 300, 0, 90, 0, 1, 0)
});

// Wait for the controller to confirm execution
r.WaitForCompletion();
Console.WriteLine(r.Status); // Completed or Error

The client manages the 8-slot controller buffer automatically. Instructions that exceed the limit are held in a local queue and sent as soon as a slot becomes free.

New instruction classes

All instruction types now have dedicated classes:

Class TP equivalent
LinearMotionTpInstruction L P[] mm/sec FINE
LinearRelativeTpInstruction L P[] mm/sec FINE INC
JointMotionTpInstruction J P[] % FINE
JointRelativeTpInstruction J P[] % FINE INC
CircularMotionTpInstruction C P[] P[] mm/sec FINE
CircularRelativeTpInstruction C P[] P[] mm/sec FINE INC
LinearMotionJRepTpInstruction L P[] mm/sec FINE (joint-angle target)
LinearRelativeJRepTpInstruction incremental, joint-angle target
JointMotionJRepTpInstruction J P[] % FINE (joint-angle target)
JointRelativeJRepTpInstruction incremental, joint-angle target
SplineMotionTpInstruction S P[] mm/sec CNT (requires MajorVersion >= 7)
SplineMotionJRepTpInstruction spline, joint-angle target
WaitDinTpInstruction WAIT DI[n] = ON/OFF
WaitTimeTpInstruction WAIT t(sec)
SetUFrameTpInstruction UFRAME_NUM = n
SetUToolTpInstruction UTOOL_NUM = n
SetPayloadTpInstruction PAYLOAD[n]
CallProgramTpInstruction CALL program

New admin methods

  • Initialize(groupMask, rtsa, pltzMode): starts RMI_MOVE with optional multi-group, singularity avoidance, and palletizing header support.
  • AutoSetNextSequenceId(): reads GetStatus() and re-synchronizes the local sequence counter when the controller checks sequence IDs.
  • GetExtendedStatus(): returns drive state, control mode, and speed clamp.
  • ReadNumericRegister / WriteNumericRegisterAsInteger / WriteNumericRegisterAsDouble: read and write numeric registers (R[]).
  • ReadVariable / WriteVariableAsInteger / WriteVariableAsDouble: read and write system variables.
  • SetPayloadValue(...): define payload mass and center of gravity for a schedule.
  • SetPayloadCompensation(...): define payload compensation.
  • SetPayloadSchedule(scheduleNumber): activate a payload schedule immediately (command, not instruction).
  • ReadIOPort / WriteIOPort: read and write any IO port type (DI, DO, AI, AO, GO, RO, FLAG, RI, UI, UO).
  • ClearCompletedInstructions() / ClearLocalQueuedInstructions(): manage the tracked instruction list.

New events

  • ConnectionTerminated: fired when the controller closes the session.
  • SystemFaultReceived: fired on a controller fault; argument is the faulted sequence ID.
  • RecordedCartesianPositionReceived / RecordedJointPositionReceived: fired when the RMI Position Record menu sends a position.

Hold state detection

IsInHoldState is now a property. The client sets it automatically when the controller returns status "HOLD" or error "invalid sequence ID". Call Reset() to exit the hold state.


FTP: FtpExistsBehavior on upload methods

UploadFileToController now accepts a FtpExistsBehavior parameter:

robot.Ftp.DirectFileHandling.UploadFileToController(
    @"C:\Programs\MyPrg.tp",
    "md:/MyPrg.tp",
    existsBehavior: FtpExistsBehavior.Skip);
Value Behavior
NoCheck Skip existence check. Use only when the file is guaranteed not to exist.
Skip Do nothing if the file already exists.
Overwrite Replace the file (default).
Append Resume a partial upload by checking the current file size.
AppendNoCheck Append without checking whether the file exists first.

CGTP: fix file download on some controllers

Fixed a bug where downloading files via CGTP could fail or return incomplete data on controllers that close the HTTP connection before sending the end-of-response marker. The response body is now fully buffered before the connection is released.

v5.5.0.0

Choose a tag to compare

@github-actions github-actions released this 04 May 16:59

CGTP: write position into a TP program

CgtpClient has a new SetProgramPosition method. It writes a Cartesian or joint position to a given position index (P[n]) inside a TP program. Only the first motion group is supported via CGTP.

// Cartesian position
var position = new Position(
    userFrame: 0,
    userTool: 1,
    jointsPosition: null,
    cartesianPosition: new ExtendedCartesianPosition(500, 200, 300, 0, 90, 0, 0, 0, 0)
);
robot.Cgtp.SetProgramPosition("MY_PROG", 1, position);

// Joint position
var jointPosition = new Position(
    userFrame: 0,
    userTool: 1,
    jointsPosition: new JointsPosition { J1 = 0, J2 = 0, J3 = 0, J4 = 0, J5 = -90, J6 = 0 },
    cartesianPosition: null
);
robot.Cgtp.SetProgramPosition("MY_PROG", 2, jointPosition);

FTP connection timeout

The FtpConnectParameters class has a new FtpTimeoutMs property. It controls the connection, read, and data transfer timeouts for all FTP operations. The default is 30,000 ms (30 seconds).

parameters.Ftp.Enable = true;
parameters.Ftp.FtpTimeoutMs = 10000; // 10 seconds

CGTP: record current position into a program

CgtpClient has a new SetProgramPositionToCurrentCartesianPosition method. It writes the robot's current Cartesian position to a given position index inside a TP program and returns the recorded position.

CartesianPosition pos = robot.Cgtp.SetProgramPositionToCurrentCartesianPosition("MY_PROG", 1);
Console.WriteLine($"Recorded: X={pos.X}, Y={pos.Y}, Z={pos.Z}");

v5.4.0.0

Choose a tag to compare

@github-actions github-actions released this 09 Apr 09:57

CGTP Source Code Editing and Program Listing

New CGTP methods for editing TP program source code directly on the controller, and listing programs. These features require firmware V9.10+ (source editing) or standard CGTP support (listing).

List programs

Retrieve all TP or Karel programs on the controller, filtered by type and sub-type.

// List all TP programs (all sub-types)
string[] tpPrograms = robot.Cgtp.ListTpPrograms();

// List programs with a specific type and sub-type
string[] macros = robot.Cgtp.ListPrograms(CgtpProgramType.Tp, CgtpProgramSubType.Macro);

Source code editing

Insert, replace, or delete lines in a TP program on the controller.

// Insert a new line before line 3
robot.Cgtp.InsertSourceLine("MY_PROGRAM", "L P[5] 100mm/sec FINE", 3);

// Replace line 5
robot.Cgtp.ReplaceSourceLine("MY_PROGRAM", "J P[1] 50% FINE", 5);

// Delete 2 lines starting at line 4
robot.Cgtp.DeleteSourceLines("MY_PROGRAM", 4, 2);

v5.3.0.0

Choose a tag to compare

@github-actions github-actions released this 07 Apr 11:43

CGTP : new features

  • Added WritePositionRegisterAsCartesian and WritePositionRegisterAsJoint to write position registers in Cartesian and Joint representations

SNPX : new features

  • SNPX is now thread safe, allowing multiple threads to access the same instance without conflicts. This enhancement improves performance and reliability in multi-threaded applications.

v5.2.0.0

Choose a tag to compare

@github-actions github-actions released this 03 Apr 16:34

Kinematics via CGTP

  • New InvertKinematics method: compute inverse kinematics on the controller, converting a Cartesian position to joint angles.
  • New ForwardKinematics method: compute forward kinematics on the controller, converting joint angles to a Cartesian position.
  • Both methods execute the computation on the controller itself, ensuring results match the robot's actual kinematic model.

Batch variable read/write via CGTP

  • New ReadBatchVariables(CgtpBatchVariables) method: read multiple variables from the controller in a single request.
  • New WriteBatchVariables(CgtpBatchVariables) method: write multiple variables to the controller in a single request.
  • New CgtpBatchVariables collection (implements IList<ICgtpBatchVariable>) with convenience methods to add variables:
    • AddNumericRegister(index), AddNumericRegisterAsInteger(index, value), AddNumericRegisterAsReal(index, value) for numeric registers R[].
    • AddStringRegister(index), AddStringRegisterWithValue(index, value) for string registers SR[].
    • AddPositionRegister(index), AddPositionRegisterAsCartesian(index, ...), AddPositionRegisterAsJoint(index, ...) for position registers PR[].
    • AddVariable(name, program) for any named variable.
  • New typed variable classes: CgtpNumericRegister, CgtpStringRegister, CgtpPositionRegister, CgtpVariable, all implementing ICgtpBatchVariable.
  • CgtpVariable exposes typed getters/setters: IntegerValue, RealValue, BooleanValue, StringValue, CartesianPositionValue, JointPositionValue, VectorValue, ConfigurationValue, StructureValue.
  • CgtpVariable.StructureValue returns a tree of CgtpStructureField for structured variables (FIELD/ARRAY nodes).
  • After a batch read, each variable exposes Exists, IsUninitialized, and IsReadOnly status properties.
  • CgtpBatchReadResult.Version returns the controller firmware version from the response.

File access and decoding via CGTP

  • New CgtpFileClient accessible via CgtpClient.Http: download and decode controller files over HTTP, without FTP.
  • CgtpClient.Http inherits from FileClientBase: all shared file-reading methods are available (GetSummaryDiagnostic(), GetAllErrorsList(), GetCurrentPosition(), GetIOState(), GetSafetyStatus(), GetProgramStates(), GetVariablesFromFile(), KnownVariableFiles).
  • BasePath property (default "MD") controls the root path used for file downloads.
  • DownloadAsBytes(fileName), DownloadAsString(fileName), and DownloadAsStream(fileName) to download raw files from the controller. HTML responses containing a <PRE> block are automatically unwrapped; binary files are returned as-is.
  • ListVariables() returns CgtpAsciiFileItem[] listing all variable files (binary and ASCII) from the controller.
  • ListTpPrograms() returns CgtpAsciiFileItem[] listing all TP program files (binary and ASCII) from the controller.
  • ListDiagnosticFiles() returns CgtpFileItem[] listing all diagnostic and error log files from the controller.
  • ListOtherFiles() returns CgtpFileItem[] listing all other files from the controller.
  • New data models: CgtpFileItem (with File and Comment properties) and CgtpAsciiFileItem (adds AsciiFile for the ASCII format variant).

Handle comments and user alarms via CGTP

  • Bulk read of numeric registers with comments and values via ReadNumericRegistersWithComment().
  • Bulk read of string registers with comments and values via ReadStringRegistersWithComment().
  • Bulk read of user alarm definitions (comment and severity) via ReadUserAlarms().
  • New unified GetComments(CgtpCommentType type) method to read all comments for any element type: numeric registers, position registers, string registers, user alarms, flags, and all I/O types (DI, DO, RI, RO, GI, GO, AI, AO).
  • New GetIoComments(CgtpCommentIoType type) method to read paired input/output comments for a given I/O type (Robot, Digital, Group, Analog).
  • SetComment(CgtpCommentType type, int index, string comment) to write the comment of any register or I/O port.
  • WriteNumericRegisterAsDouble() and WriteNumericRegisterAsInteger() to write numeric register values with explicit type control.
  • WriteStringRegister() to write a string register value.
  • SetUserAlarmSeverity() to set the severity level of a user alarm.
  • New enums CgtpCommentType and CgtpCommentIoType for strongly-typed comment operations.
  • New data models: StringRegisterWithComment, UserAlarmDefinition, IOComments.
  • HTTP Basic authentication support: new Login and Password properties on CgtpConnectParametersBase for controllers that require credentials.
  • CGTP also works on the standard HTTP port 80 by setting CgtpConnectParameters.Port = 80.

New KCL client over CGTP

  • New CgtpKclClient class accessible via CgtpClient.Kcl : execute KCL commands over the CGTP Web Server (HTTP), without a Telnet connection.
  • Full KCL command set available: Abort, AbortAll, ClearAll, ClearProgram, ClearVars, Continue, Hold, Pause, Reset, Run, SetPort, SetVariable, GetCurrentPose, GetVariable, Simulate, Unsimulate, UnsimulateAll, SendCustomCommand, GetTaskInformation, AddBreakpoint, RemoveBreakpoint, RemoveAllBreakpoints, GetBreakpoints, StepOn, StepOff.
  • New SendCustomCommandUnsafe() method to send any custom KCL command via the Comet CPKCL endpoint.
  • New abstract KclClientBase base class in UnderAutomation.Fanuc.Common.Kcl shared between TelnetClientBase and CgtpKclClient, ensuring a unified KCL API across both protocols.
  • CgtpClient.Kcl is never null and always uses the language configured on CgtpClient.

New Telnet Feature

  • New event StringDataReceived on TelnetClientBase to receive decoded string data from the controller, in addition to raw byte data. This is useful for handling text-based responses from any connected KCL client (CGTP, Telnet, ...) in a unified way.

Shared file reading foundation (FTP)

  • File reading, parsing, and variable decoding logic has been extracted from the FTP client into a shared foundation in UnderAutomation.Fanuc.Common.Files, laying the groundwork for future protocol-agnostic file access.
  • New FileClientBase abstract base class in UnderAutomation.Fanuc.Common.Files: centralizes methods such as GetSummaryDiagnostic(), GetAllErrorsList(), GetCurrentPosition(), GetIOState(), GetSafetyStatus(), GetProgramStates(), GetVariablesFromFile(), and the KnownVariableFiles property.
  • FtpClientBase now inherits from FileClientBase: all file-reading methods remain available on the FTP client with the same signatures.
  • FtpKnownVariableFiles has been replaced by the shared KnownVariableFiles class in UnderAutomation.Fanuc.Common.Files.
  • FanucFileReaders static helper (reading .va, .dg, .ls files) moved to UnderAutomation.Fanuc.Common.Files.
  • New FanucFileReaders.ReadFile(string path) static method to read and auto-detect any supported Fanuc file from disk.
  • New ParseResult() method in KCL GetVariableResult class to decode and get a structured representation of the variable (value, type, scope, ...).

Breaking changes

  • CgtpClient.Connect() signature changed: now accepts optional login and password parameters.
  • Namespace migration for shared KCL types: Result, BaseResult, KCLPorts, KclClientBase, and all KCL result classes (ProgramCommandResult, RunResult, SetVariableResult, GetVariableResult, SetPortResult, SimulateResult, UnsimulateResult, GetCurrentPoseResult, TaskInformationResult, BreakpointsResult, etc.) moved from UnderAutomation.Fanuc.Telnet to UnderAutomation.Fanuc.Common.Kcl.
  • Telnet-specific event types (RawDataReceivedEventArgs, TpCoordinates, MessageReceivedEventArgs, KclClientErrorEventArgs, CommandSentEventArgs, KclCommandReceived) remain in UnderAutomation.Fanuc.Telnet.
  • Namespace migration for shared position models: moved from UnderAutomation.Fanuc.Ftp.Variables to UnderAutomation.Fanuc.Common.
  • Affected types: CartesianPositionVariable, JointPositionVariable, PositionRegister, VectorVariable.
  • Namespace migration for file reading and variable decoding:
    • Diagnosis types (SummaryDiagnosis, CurrentPosition, IOState, SafetyStatus, ProgramStates, GroupPosition, Feature, etc.) moved from UnderAutomation.Fanuc.Ftp.Diagnosis to UnderAutomation.Fanuc.Common.Files.Diagnosis.
    • Error list types (ErrorList, ErrallSectionItem, ErrallSectionParser) moved from UnderAutomation.Fanuc.Ftp.Files.List to UnderAutomation.Fanuc.Common.Files.List.
    • Variable types (GenericVariableFile, GenericVariable, GenericField, GenericValue, ValueKind, ArrayElement, VariableFile, VariableFileList, etc.) moved from UnderAutomation.Fanuc.Ftp.Variables to UnderAutomation.Fanuc.Common.Files.Variables.
    • All autogenerated variable file readers and type definitions moved from UnderAutomation.Fanuc.Ftp.Autogenerated to UnderAutomation.Fanuc.Common.Files.Variables.Autogenerated.
    • File infrastructure types (FanucFileReaders, FileParser, FileReader, IFileReader, IFanucContent) moved from UnderAutomation.Fanuc.Ftp / UnderAutomation.Fanuc.Ftp.Internal to UnderAutomation.Fanuc.Common.Files.
  • TelnetClientBase now inherits from KclClientBase : all KCL methods remain available on the Telnet client with the same signatures.
  • CGTP enum/type naming has been aligned for clarity in public APIs (for example IoPortType and ProgramSubType naming in CGTP).

Improved

  • Improved robustness of value parsing for position and register data.
  • Improved CGTP error reporting with clearer messages in common failure scenarios.

v5.1.0.0

Choose a tag to compare

@github-actions github-actions released this 23 Mar 23:27

SNPX: Flag Comments Support

Added support for reading and writing Flag comments through SNPX.

CGTP: New Capabilities and Improvements

  • Enabled CGTP I/O operations in CgtpClientBase:
    • Read I/O values
    • Write I/O values
    • Read I/O simulation status
    • Simulate/unsimulate I/O
    • Read current Cartesian position (X, Y, Z, W, P, R coordinates and configuration) of a motion group
    • Read current joint angles (J1-J6) of a motion group

SNPX: Null-Terminated String Handling Fix

Improved string decoding by trimming trailing null terminators (\0) across SNPX string-related reads.

This prevents issues with null-terminated strings in scenarios such as:

  • String registers
  • Comments (including batch reads)
  • String system variables

v5.0.0.0

Choose a tag to compare

@github-actions github-actions released this 23 Mar 13:28

New CGTP Protocol Support

A new CGTP Web Server client has been added, providing access to the HTTP-based RPC interface available on FANUC controllers (default port: 3080).

This lightweight, firewall-friendly protocol complements the existing SNPX, RMI, Telnet, and FTP connections and is enabled by default when connecting.

Feature:

  • Create, delete, rename programs
  • Read and write program attributes: comment, owner, stack size, write-protection, ignore-pause flag, and sub-type
  • Run, abort, and pause programs
  • Select a program and set the cursor to a specific line
  • Change the active TP program
  • Read and write system and program variables by name
  • List files on the controller (MD: or other devices)
  • Read file contents as text

A CgtpClient class is available for direct use without a FanucRobot instance.


Connection Parameters Changes

  • Telnet and FTP are now disabled by default, enable them explicitly via ConnectionParameters.Telnet.Enable and ConnectionParameters.Ftp.Enable
  • CGTP is enabled by default, disable via ConnectionParameters.Cgtp.Enable = false

SNPX Fixes

  • Null terminators (\0) are now correctly trimmed from string values returned when reading string registers and string variables

SNPX String Registers Simplification

  • StringRegistersSpan has been removed from the public SDK API because it made SNPX usage harder to understand.
  • Use StringRegisters for string register read/write.
  • Important: StringRegisters.StringLength is static. Set it once before any string register read/write, and do not change it while the SDK is running.
  • Default value remains 80.

Examples:

using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Snpx.Internal;

var robot = new FanucRobot();
robot.Connect("192.168.0.10");

// Configure once before any SR[] read/write.
StringRegisters.StringLength = 100; // default size is 80

// Write and read a string register.
robot.Snpx.StringRegisters.Write(1, "HELLO FANUC");
string value = robot.Snpx.StringRegisters.Read(1);

v4.8.0.0

Choose a tag to compare

@github-actions github-actions released this 19 Mar 10:41

SNPX : Comments and Simulation Status

New feature : Comments

New Comments accessor allows reading and writing comments of registers, position registers, string registers and I/O signals via SNPX.

// Read the comment of R[1] (default 16 characters)
string comment = robot.Snpx.Comments.Read(CommentType.Register, 1);

// Read the comment of DI[3] with a custom length
string diComment = robot.Snpx.Comments.Read(CommentType.DI, 3);

// Write a comment to PR[5]
robot.Snpx.Comments.Write(CommentType.PositionRegister, 5, "My position");

Supported types: Register, PositionRegister, StringRegister, DI, DO, RI, RO, UI, UO, SI, SO, WI, WO, WSI, WSO, GI, GO, AI, AO.

New feature : Simulation Status

New SimulationStatus accessor allows reading and writing the simulation state of I/O signals via SNPX.

// Check if DI[1] is simulated
bool isSimulated = robot.Snpx.SimulationStatus.Read(SimulationType.DI, 1);

// Enable simulation on RO[2]
robot.Snpx.SimulationStatus.Write(SimulationType.RO, 2, true);

// Disable simulation on GI[5]
robot.Snpx.SimulationStatus.Write(SimulationType.GI, 5, false);

Supported types: DI, DO, RI, RO, WI, WO, WSI, WSO, GI, GO, AI, AO.

Telnet : Fix premature response finalization on non-English controllers

Fixed an issue where Telnet KCL commands (e.g. GetVariable, SetVariable) could fail on non-English controllers (Chinese, Japanese...) due to intermediate VT100 display-update frames being incorrectly interpreted as the end of a response.

On some controllers, status bar refresh frames (containing only ANSI escape sequences) arrive before the actual command response data. These empty frames were causing the result to be finalized prematurely, leading to missing or empty values.

A new mechanism now allows multi-frame results (GetVariableResult, SetVariableResult, BreakpointsResult) to defer finalization until meaningful data has actually been received.

SNPX : String registers span and fixes

New feature : String registers span

New StringRegistersSpan accessor allows reading and writing substrings of string registers (SR[]) with control over start index and length.

// Read 10 characters starting at position 4 from SR[1]
string value = robot.Snpx.StringRegistersSpan.Read(registerIndex: 1, stringLength: 10, stringStartIndex: 4);

// Write a substring into SR[2]
robot.Snpx.StringRegistersSpan.Write(registerIndex: 2, value: "Hello", stringLength: 10, stringStartIndex: 0);

Fix for writing empty strings

Allow SNPX to write empty strings to string variables and string registers. String encoding now uses fixed-length byte buffers, preventing issues with empty or odd-length strings.

Fix missing assignable elements

NumericRegistersInt16, NumericRegistersInt32, StringRegistersSpan and Flags are now correctly included in SNPX assignable elements, ensuring ClearAssignments() and GetAssignments() cover all element types.