SNPX provides fast read and write access to all register types: numeric (R[]), position (PR[]), string (SR[]), and flags (F[]).

## Numeric registers (R[])

Numeric registers store floating-point, 32-bit integer, or 16-bit integer values.

**C# : SnpxRegistersNumeric**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Common;

public class SnpxRegistersNumeric
{
    static void Main()
    {
        FanucRobot robot = new FanucRobot();
        var parameters = new ConnectionParameters("192.168.0.1");
        parameters.Snpx.Enable = true;
        robot.Connect(parameters);

        /**/
        // Read R[1] as float (default)
        float value = robot.Snpx.NumericRegisters.Read(1);

        // Write R[1]
        robot.Snpx.NumericRegisters.Write(1, 123.45f);

        // Read as 32-bit integer
        int intValue = robot.Snpx.NumericRegistersInt32.Read(1);
        robot.Snpx.NumericRegistersInt32.Write(1, 999);

        // Read as 16-bit integer
        short shortValue = robot.Snpx.NumericRegistersInt16.Read(1);
        /**/
    }
}
```

**Python : SnpxRegistersNumeric**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot
from underautomation.fanuc.connection_parameters import ConnectionParameters

robot = FanucRobot()
parameters = ConnectionParameters("192.168.0.1")
parameters.snpx.enable = True
robot.connect(parameters)

##
# Read R[1] as float (default)
value = robot.snpx.numeric_registers.read(1)

# Write R[1]
robot.snpx.numeric_registers.write(1, 123.45)

# Read as 32-bit integer
int_value = robot.snpx.numeric_registers_int32.read(1)
robot.snpx.numeric_registers_int32.write(1, 999)

# Read as 16-bit integer
short_value = robot.snpx.numeric_registers_int16.read(1)
##
```

## Position registers (PR[])

Position registers store joint or Cartesian positions with tool and frame info.

**C# : SnpxRegistersPosition**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Common;

public class SnpxRegistersPosition
{
    static void Main()
    {
        FanucRobot robot = new FanucRobot();
        var parameters = new ConnectionParameters("192.168.0.1");
        parameters.Snpx.Enable = true;
        robot.Connect(parameters);

        /**/
        // Read PR[1]
        Position posReg = robot.Snpx.PositionRegisters.Read(1);

        // Access Cartesian values
        double x = posReg.CartesianPosition.X;
        short userFrame = posReg.UserFrame;
        short userTool = posReg.UserTool;

        // Access joint values
        double j1 = posReg.JointsPosition.J1;

        // Write Cartesian position to PR[1]
        robot.Snpx.PositionRegisters.Write(1, new CartesianPosition(100, 200, 300, 0, 90, 0));

        // Write joint position to PR[1]
        robot.Snpx.PositionRegisters.Write(1, new JointsPosition { J1 = 0, J2 = 0, J3 = 0, J4 = 0, J5 = 0, J6 = 45 });
        /**/
    }
}
```

**Python : SnpxRegistersPosition**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot
from underautomation.fanuc.connection_parameters import ConnectionParameters
from underautomation.fanuc.common.cartesian_position import CartesianPosition
from underautomation.fanuc.common.joints_position import JointsPosition

robot = FanucRobot()
parameters = ConnectionParameters("192.168.0.1")
parameters.snpx.enable = True
robot.connect(parameters)

##
# Read PR[1]
pos_reg = robot.snpx.position_registers.read(1)

# Access Cartesian values
x = pos_reg.cartesian_position.x
user_frame = pos_reg.user_frame
user_tool = pos_reg.user_tool

# Access joint values
j1 = pos_reg.joints_position.j1

# Write Cartesian position to PR[1]
robot.snpx.position_registers.write(1, CartesianPosition(100, 200, 300, 0, 90, 0))

# Write joint position to PR[1]
robot.snpx.position_registers.write(1, JointsPosition(j1=0, j2=0, j3=0, j4=0, j5=0, j6=45))
##
```

## String registers (SR[]) and flags (F[])

The default string length is 80 characters. You can change it with `StringRegisters.StringLength` (must be even, >= 2).

**C# : SnpxRegistersString**
```csharp
using UnderAutomation.Fanuc;

public class SnpxRegistersString
{
    static void Main()
    {
        FanucRobot robot = new FanucRobot();
        var parameters = new ConnectionParameters("192.168.0.1");
        parameters.Snpx.Enable = true;
        robot.Connect(parameters);

        /**/
        // Read SR[1]
        string text = robot.Snpx.StringRegisters.Read(1);

        // Write SR[1]
        robot.Snpx.StringRegisters.Write(1, "Hello, Robot!");

        // Read F[1]
        bool flag = robot.Snpx.Flags.Read(1);

        // Write F[1]
        robot.Snpx.Flags.Write(1, true);
        /**/
    }
}
```

**Python : SnpxRegistersString**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot
from underautomation.fanuc.connection_parameters import ConnectionParameters

robot = FanucRobot()
parameters = ConnectionParameters("192.168.0.1")
parameters.snpx.enable = True
robot.connect(parameters)

##
# Read SR[1]
text = robot.snpx.string_registers.read(1)

# Write SR[1]
robot.snpx.string_registers.write(1, "Hello, Robot!")

# Read F[1]
flag = robot.snpx.flags.read(1)

# Write F[1]
robot.snpx.flags.write(1, True)
##
```

## Complete example

**C# : SnpxRegisters**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Common;

public class SnpxRegisters
{
  public static void Main()
  {
    // Create a FanucRobot instance
    FanucRobot robot = new FanucRobot();

    // Set SNPX connection parameters (example values)
    ConnectionParameters parameters = new ConnectionParameters("192.168.0.1");
    parameters.Snpx.Enable = true;

    // Connect with SNPX enabled
    robot.Connect(parameters);

    /**/
    // 1) Numeric Registers: Read & Write
    ReadWriteNumericRegisters(robot);

    // 2) Position Registers: Read & Write
    ReadWritePositionRegisters(robot);

    // 3) String Registers: Read & Write
    ReadWriteStringRegisters(robot);
    /**/
  }

  private static void ReadWriteNumericRegisters(FanucRobot robot)
  {
    // Read numeric register R[1]
    float numReg1 = robot.Snpx.NumericRegisters.Read(1);
    Console.WriteLine($"📊 R[1] = {numReg1}");

    // Write numeric register R[1]
    robot.Snpx.NumericRegisters.Write(1, 123.45f);
    Console.WriteLine("✅ Wrote 123.45 to R[1]");
  }

  private static void ReadWritePositionRegisters(FanucRobot robot)
  {
    // Read position register PR[1]
    Position posReg1 = robot.Snpx.PositionRegisters.Read(1);
    Console.WriteLine("\n🤖 Current PR[1]:");
    Console.WriteLine($"   UserFrame = {posReg1.UserFrame}");
    Console.WriteLine($"   UserTool = {posReg1.UserTool}");

    // If the register is Cartesian
    if (posReg1.CartesianPosition != null)
    {
      Console.WriteLine("   CartesianPosition:");
      Console.WriteLine($"      X = {posReg1.CartesianPosition.X}");
      Console.WriteLine($"      Y = {posReg1.CartesianPosition.Y}");
      Console.WriteLine($"      Z = {posReg1.CartesianPosition.Z}");
      Console.WriteLine($"      W = {posReg1.CartesianPosition.W}");
      Console.WriteLine($"      P = {posReg1.CartesianPosition.P}");
      Console.WriteLine($"      R = {posReg1.CartesianPosition.R}");
      Console.WriteLine("      Configuration :");
      Console.WriteLine($"         ArmFrontBack = {posReg1.CartesianPosition.Configuration.ArmFrontBack}");
      Console.WriteLine($"         ArmLeftRight = {posReg1.CartesianPosition.Configuration.ArmLeftRight}");
      Console.WriteLine($"         ArmUpDown = {posReg1.CartesianPosition.Configuration.ArmUpDown}");
      Console.WriteLine($"         WristFlip = {posReg1.CartesianPosition.Configuration.WristFlip}");
    }

    // If the register is Joint-based
    if (posReg1.JointsPosition != null)
    {
      Console.WriteLine("   JointsPosition:");
      Console.WriteLine($"      J1 = {posReg1.JointsPosition.J1}");
      Console.WriteLine($"      J2 = {posReg1.JointsPosition.J2}");
      Console.WriteLine($"      J3 = {posReg1.JointsPosition.J3}");
      Console.WriteLine($"      J4 = {posReg1.JointsPosition.J4}");
      Console.WriteLine($"      J5 = {posReg1.JointsPosition.J5}");
      Console.WriteLine($"      J6 = {posReg1.JointsPosition.J6}");
    }

    // Write a Cartesian position to PR[1]
    Console.WriteLine("\n✅ Writing Cartesian position to PR[1]...");
    robot.Snpx.PositionRegisters.Write(1, new CartesianPosition(x: 0.1f, y: 0.2f, z: 0.3f, w: 0.4f, p: 0.5f, r: 0.6f));

    // Write a Joint position to PR[1]
    Console.WriteLine("✅ Writing Joint position to PR[1]...");
    robot.Snpx.PositionRegisters.Write(1, new JointsPosition { J1 = 0, J2 = 0, J3 = 0, J4 = 0, J5 = 0, J6 = 45 });
  }

  private static void ReadWriteStringRegisters(FanucRobot robot)
  {
    // Read string register SR[1]
    string strReg1 = robot.Snpx.StringRegisters.Read(1);
    Console.WriteLine($"\n💬 SR[1] = '{strReg1}'");

    // Write string register SR[1]
    robot.Snpx.StringRegisters.Write(1, "Hello, Robot!");
    Console.WriteLine("✅ Wrote 'Hello, Robot!' to SR[1]");
  }
}
```

**Python : SnpxRegisters**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot
from underautomation.fanuc.connection_parameters import ConnectionParameters
from underautomation.fanuc.common.cartesian_position import CartesianPosition
from underautomation.fanuc.common.joints_position import JointsPosition

# Create a robot instance
robot = FanucRobot()

# Configure connection parameters
parameters = ConnectionParameters("192.168.0.1")
parameters.snpx.enable = True

# Connect to the robot
robot.connect(parameters)

##
# --- Numeric Registers (R[]) ---

# Read R[1]
num_reg1 = robot.snpx.numeric_registers.read(1)
print(f"R[1] = {num_reg1}")

# Write R[1]
robot.snpx.numeric_registers.write(1, 123.45)

# --- Position Registers (PR[]) ---

# Read PR[1]
pos_reg1 = robot.snpx.position_registers.read(1)
print(f"PR[1] UserFrame={pos_reg1.user_frame}, UserTool={pos_reg1.user_tool}")

# Access Cartesian values
if pos_reg1.cartesian_position is not None:
    print(f"  X={pos_reg1.cartesian_position.x}")
    print(f"  Y={pos_reg1.cartesian_position.y}")
    print(f"  Z={pos_reg1.cartesian_position.z}")

# Access joint values
if pos_reg1.joints_position is not None:
    print(f"  J1={pos_reg1.joints_position.j1}")

# Write Cartesian position to PR[1]
robot.snpx.position_registers.write(1, CartesianPosition(100, 200, 300, 0, 90, 0))

# Write Joint position to PR[1]
joints = JointsPosition()
joints.j1 = 0
joints.j2 = 0
joints.j3 = 0
joints.j4 = 0
joints.j5 = 0
joints.j6 = 45
robot.snpx.position_registers.write(1, joints)

# --- String Registers (SR[]) ---

# Read SR[1]
str_reg1 = robot.snpx.string_registers.read(1)
print(f"SR[1] = '{str_reg1}'")

# Write SR[1]
robot.snpx.string_registers.write(1, "Hello, Robot!")

# --- Flag Registers (F[]) ---

# Read F[1]
flag1 = robot.snpx.flags.read(1)
print(f"F[1] = {flag1}")

# Write F[1]
robot.snpx.flags.write(1, True)
##
```

## API reference

**Members of Snpx.Internal.NumericRegisters**
```csharp
public class NumericRegisters : NumericRegistersBase<float, NumericRegistersBatchAssignment> {
    // Creates a batch assignment for reading multiple numeric registers.
    public NumericRegistersBatchAssignment CreateBatchAssignment(int startIndex, int count)

    // Reads a value from the client at the specified memory offset.
    protected override float ReadFromClient(int offset, int index)

    // Writes a value to the robot at the specified offset.
    protected override void WriteInClient(int offset, int index, float value)
}
```

**Members of Snpx.Internal.PositionRegisters**
```csharp
public class PositionRegisters : SnpxWritableAssignableIndexableElements<Position, PositionRegistersBatchAssignment> {
    // Creates a batch assignment for reading multiple position registers.
    public PositionRegistersBatchAssignment CreateBatchAssignment(int startIndex, int count)

    protected override string GetAssignmentName(int index)

    protected override int GetAssignmentSize(int index)

    protected override string GetAssignmentTarget(int index)

    // Reads the position at the specified register index.
    public Position Read(int index)

    // Reads a value from the client at the specified memory offset.
    protected override Position ReadFromClient(int offset, int index)

    // Writes a Cartesian position to the specified position register.
    public void Write(int index, CartesianPosition cartesianPosition)

    // Writes an extended Cartesian position to the specified position register.
    public void Write(int index, ExtendedCartesianPosition extendedCartesianPosition)

    // Writes a joints position to the specified position register.
    public void Write(int index, JointsPosition jointsPosition)

    // Writes a value to the robot at the specified offset.
    protected override void WriteInClient(int offset, int index, Position value)
}
```

**Members of Common.Position**
```csharp
public class Position {
    // Default constructor
    public Position()

    // Constructor with user frame, tool, joints and cartesian position
    public Position(short userFrame, short userTool, JointsPosition jointsPosition, ExtendedCartesianPosition cartesianPosition)

    // Cartesian position with extended axes
    public ExtendedCartesianPosition CartesianPosition { get; set; }

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Joint values in degrees
    public JointsPosition JointsPosition { get; set; }

    public override string ToString()

    // User frame index
    public short UserFrame { get; set; }

    // User tool index
    public short UserTool { get; set; }
}
```

**Members of Common.JointsPosition**
```csharp
public class JointsPosition {
    // Default constructor
    public JointsPosition()

    // Constructor with 6 joint values in degrees
    public JointsPosition(double j1Deg, double j2Deg, double j3Deg, double j4Deg, double j5Deg, double j6Deg)

    // Constructor with 9 joint values in degrees
    public JointsPosition(double j1Deg, double j2Deg, double j3Deg, double j4Deg, double j5Deg, double j6Deg, double j7Deg, double j8Deg, double j9Deg)

    // Constructor from an array of joint values in degrees
    public JointsPosition(double[] values)

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Check if joints position is near to expected joints position with a tolerance value
    public static bool IsNear(JointsPosition j1, JointsPosition j2, double degreesTolerance)

    // Gets or sets the joint value at the specified index
    public double this[int i] { get; set; }

    // Joint 1 in degrees
    public double J1 { get; set; }

    // Joint 2 in degrees
    public double J2 { get; set; }

    // Joint 3 in degrees
    public double J3 { get; set; }

    // Joint 4 in degrees
    public double J4 { get; set; }

    // Joint 5 in degrees
    public double J5 { get; set; }

    // Joint 6 in degrees
    public double J6 { get; set; }

    // Joint 7 in degrees
    public double J7 { get; set; }

    // Joint 8 in degrees
    public double J8 { get; set; }

    // Joint 9 in degrees
    public double J9 { get; set; }

    public override string ToString()

    // Numeric values for each joints
    public double[] Values { get; }
}
```

**Members of Common.ExtendedCartesianPosition**
```csharp
public class ExtendedCartesianPosition : CartesianPosition {
    // Default constructor
    public ExtendedCartesianPosition()

    // Constructor with position, rotations, and extended axes
    public ExtendedCartesianPosition(double x, double y, double z, double w, double p, double r, double e1, double e2, double e3)

    // Extended axis 1 value
    public double E1 { get; set; }

    // Extended axis 2 value
    public double E2 { get; set; }

    // Extended axis 3 value
    public double E3 { get; set; }

    public override bool Equals(object obj)

    public override int GetHashCode()

    public override string ToString()
}
```

**Members of Common.CartesianPosition**
```csharp
public class CartesianPosition : XYZPosition {
    // Default constructor
    public CartesianPosition()

    // Constructor with position and rotations
    public CartesianPosition(double x, double y, double z, double w, double p, double r)

    // Constructor with position, rotations and configuration
    public CartesianPosition(double x, double y, double z, double w, double p, double r, Configuration configuration)

    // Copy constructor
    public CartesianPosition(CartesianPosition position)

    // Constructor from an XYZ position with rotations
    public CartesianPosition(XYZPosition position, double w, double p, double r)

    // Position configuration
    public Configuration Configuration { get; }

    public override bool Equals(object obj)

    // Create a CartesianPosition with unknow configuration from a homogeneous rotation and translation 4x4 matrix
    public static CartesianPosition FromHomogeneousMatrix(double[,] R)

    public override int GetHashCode()

    // Check if two Cartesian positions are near each other within specified tolerances
    public static bool IsNear(CartesianPosition a, CartesianPosition b, double mmTolerance, double degreesTolerance)

    // Normalize an angle to the range ]-180, 180]
    public static double NormalizeAngle(double angle)

    // Normalize the W, P, R angles to the range ]-180, 180]
    public static void NormalizeAngles(CartesianPosition pose)

    // P rotation in degrees (Ry)
    public double P { get; set; }

    // R rotation in degrees (Rz)
    public double R { get; set; }

    // Convert position to a homogeneous rotation and translation 4x4 matrix
    public double[,] ToHomogeneousMatrix()

    public override string ToString()

    // W rotation in degrees (Rx)
    public double W { get; set; }
}
```