RMI provides access to user frames, tools, digital I/O, position registers, and controller status.

## Controller status

**C# : RmiFramesIoStatus**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Rmi;
using UnderAutomation.Fanuc.Rmi.Data;

public class RmiFramesIoStatus
{
    static void Main()
    {
        FanucRobot robot = new FanucRobot();
        robot.Connect("192.168.0.1");

        /**/
        // Controller status
        ControllerStatus status = robot.Rmi.GetStatus();
        Console.WriteLine($"Servo ready: {status.ServoReady}");
        Console.WriteLine($"TP mode: {status.TPMode}");

        // Admin commands
        robot.Rmi.SetOverride(50);
        robot.Rmi.Pause();
        robot.Rmi.Continue();
        robot.Rmi.Reset();
        robot.Rmi.Abort();

        // Read last error
        ControllerErrorText error = robot.Rmi.ReadError();
        /**/
    }
}
```

**Python : RmiFramesIoStatus**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot

robot = FanucRobot()
robot.connect("192.168.0.1")

##
# Controller status
status = robot.rmi.get_status()
print(f"Servo ready: {status.servo_ready}")
print(f"TP mode: {status.tp_mode}")

# Admin commands
robot.rmi.set_override(50)
robot.rmi.pause()
robot.rmi.continue_motion()
robot.rmi.reset()
robot.rmi.abort()

# Read last error
error = robot.rmi.read_error()
##
```

## Admin commands

## Position reading

**C# : RmiFramesIoPosition**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Rmi;
using UnderAutomation.Fanuc.Rmi.Data;

public class RmiFramesIoPosition
{
    static void Main()
    {
        FanucRobot robot = new FanucRobot();
        robot.Connect("192.168.0.1");

        /**/
        // Current Cartesian position
        var pos = robot.Rmi.ReadCartesianPosition();
        Console.WriteLine($"X={pos.Position.X}, Y={pos.Position.Y}, Z={pos.Position.Z}");

        // Current joint angles
        JointAnglesSample joints = robot.Rmi.ReadJointAngles();
        Console.WriteLine($"J1={joints.JointAngle.J1}, J2={joints.JointAngle.J2}");

        // TCP speed
        TcpSpeed speed = robot.Rmi.ReadTcpSpeed();
        Console.WriteLine($"TCP speed: {speed.Speed} mm/s");
        /**/
    }
}
```

**Python : RmiFramesIoPosition**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot

robot = FanucRobot()
robot.connect("192.168.0.1")

##
# Current Cartesian position
pos = robot.rmi.read_cartesian_position()
print(f"X={pos.position.x}, Y={pos.position.y}, Z={pos.position.z}")

# Current joint angles
joints = robot.rmi.read_joint_angles()
print(f"J1={joints.joint_angle.j1}, J2={joints.joint_angle.j2}")

# TCP speed
speed = robot.rmi.read_tcp_speed()
print(f"TCP speed: {speed.speed} mm/s")
##
```

## User frames and tools

**C# : RmiFramesIoFrames**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Rmi;
using UnderAutomation.Fanuc.Rmi.Data;

public class RmiFramesIoFrames
{
    static void Main()
    {
        FanucRobot robot = new FanucRobot();
        robot.Connect("192.168.0.1");

        /**/
        // Read current frame/tool numbers
        UFrameUToolNumbers current = robot.Rmi.GetUFrameUTool();
        Console.WriteLine($"UFrame: {current.UFrameNumber}, UTool: {current.UToolNumber}");

        // Set current frame/tool
        robot.Rmi.SetUFrameUTool(uframe: 1, utool: 2);

        // Read/write a user frame
        IndexedFrame frame = robot.Rmi.ReadUFrame(1);
        robot.Rmi.WriteUFrame(1, new Frame { X = 100, Y = 200, Z = 0 });

        // Read/write user tool
        IndexedFrame tool = robot.Rmi.ReadUTool(1);
        robot.Rmi.WriteUTool(1, new Frame { X = 0, Y = 0, Z = 150 });
        /**/
    }
}
```

**Python : RmiFramesIoFrames**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot

robot = FanucRobot()
robot.connect("192.168.0.1")

##
# Read current frame/tool numbers
current = robot.rmi.get_uframe_utool()
print(f"UFrame: {current.uframe_number}, UTool: {current.utool_number}")

# Set current frame/tool
robot.rmi.set_uframe_utool(uframe=1, utool=2)

# Read/write a user frame
frame = robot.rmi.read_uframe(1)
robot.rmi.write_uframe(1, {"x": 100, "y": 200, "z": 0})

# Read/write user tool
tool = robot.rmi.read_utool(1)
robot.rmi.write_utool(1, {"x": 0, "y": 0, "z": 150})
##
```

## Digital I/O

**C# : RmiFramesIoIo**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Rmi;
using UnderAutomation.Fanuc.Rmi.Data;

public class RmiFramesIoIo
{
    static void Main()
    {
        FanucRobot robot = new FanucRobot();
        robot.Connect("192.168.0.1");

        /**/
        // Read digital input
        DigitalInputValue din = robot.Rmi.ReadDIN(5);
        Console.WriteLine($"DI[5] = {din.PortValue}");

        // Write digital output
        robot.Rmi.WriteDOUT(1, OnOff.ON);
        robot.Rmi.WriteDOUT(1, OnOff.OFF);

        // Read a position register
        PositionRegisterData pr = robot.Rmi.ReadPositionRegister(1);
        Console.WriteLine($"PR[1]: X={pr.Position.X}");

        // Write a position register
        Frame newPos = new Frame { X = 500, Y = 200, Z = 300, W = 0, P = 90, R = 0 };
        MotionConfiguration config = new MotionConfiguration { UToolNumber = 1, UFrameNumber = 0 };
        robot.Rmi.WritePositionRegister(1, config, newPos);
        /**/
    }
}
```

**Python : RmiFramesIoIo**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot

robot = FanucRobot()
robot.connect("192.168.0.1")

##
# Read digital input
din = robot.rmi.read_din(5)
print(f"DI[5] = {din.port_value}")

# Write digital output
robot.rmi.write_dout(1, True)
robot.rmi.write_dout(1, False)

# Read a position register
pr = robot.rmi.read_position_register(1)
print(f"PR[1]: X={pr.position.x}")

# Write a position register
robot.rmi.write_position_register(1, {"utool_number": 1, "uframe_number": 0},
    {"x": 500, "y": 200, "z": 300, "w": 0, "p": 90, "r": 0})
##
```

## Position registers

## Complete example

**C# : RmiFramesIo**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Rmi.Data;

public class RmiFramesIo
{
  public static void Main()
  {
    FanucRobot robot = new FanucRobot();

    ConnectionParameters parameters = new ConnectionParameters("192.168.0.1");
    parameters.Rmi.Enable = true;

    robot.Connect(parameters);
    robot.Rmi.Initialize();

    /**/
    // --- Controller status ---
    ControllerStatus status = robot.Rmi.GetStatus();
    Console.WriteLine($"Servo ready: {status.ServoReady}");
    Console.WriteLine($"TP mode: {status.TPMode}");

    // --- Admin commands ---
    robot.Rmi.SetOverride(50);
    robot.Rmi.Pause();
    robot.Rmi.Continue();
    robot.Rmi.Reset();

    // --- Position reading ---
    var pos = robot.Rmi.ReadCartesianPosition();
    JointAnglesSample joints = robot.Rmi.ReadJointAngles();
    TcpSpeed speed = robot.Rmi.ReadTcpSpeed();

    // --- User frames and tools ---
    UFrameUToolNumbers current = robot.Rmi.GetUFrameUTool();
    robot.Rmi.SetUFrameUTool(uframe: 1, utool: 2);

    IndexedFrame frame = robot.Rmi.ReadUFrame(1);
    robot.Rmi.WriteUFrame(1, new Frame { X = 100, Y = 200, Z = 0 });

    IndexedFrame tool = robot.Rmi.ReadUTool(1);
    robot.Rmi.WriteUTool(1, new Frame { X = 0, Y = 0, Z = 150 });

    // --- Digital I/O ---
    DigitalInputValue din = robot.Rmi.ReadDIN(5);
    robot.Rmi.WriteDOUT(1, OnOff.ON);

    // --- Position registers ---
    PositionRegisterData pr = robot.Rmi.ReadPositionRegister(1);
    Frame newPos = new Frame { X = 500, Y = 200, Z = 300 };
    MotionConfiguration config = new MotionConfiguration { UToolNumber = 1, UFrameNumber = 0 };
    robot.Rmi.WritePositionRegister(1, config, newPos);
    /**/
  }
}
```

**Python : RmiFramesIo**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot
from underautomation.fanuc.connection_parameters import ConnectionParameters
from underautomation.fanuc.rmi.data.on_off import OnOff
from underautomation.fanuc.rmi.data.frame import Frame
from underautomation.fanuc.rmi.data.motion_configuration import MotionConfiguration

# Create a robot instance
robot = FanucRobot()

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

# Connect to the robot
robot.connect(parameters)
robot.rmi.initialize()

##
# --- Controller status ---
status = robot.rmi.get_status()
print(f"Servo ready: {status.servo_ready}")
print(f"TP mode: {status.tp_mode}")

# --- Admin commands ---
robot.rmi.set_override(50)
robot.rmi.pause()
robot.rmi.continue_()
robot.rmi.reset()

# --- Position reading ---
pos = robot.rmi.read_cartesian_position()
joints = robot.rmi.read_joint_angles()
speed = robot.rmi.read_tcp_speed()

# --- User frames and tools ---
current = robot.rmi.get_u_frame_u_tool()
robot.rmi.set_u_frame_u_tool(u_frame=1, u_tool=2)

frame = robot.rmi.read_u_frame(1)
new_frame = Frame()
new_frame.x = 100
new_frame.y = 200
new_frame.z = 0
robot.rmi.write_u_frame(1, new_frame)

tool = robot.rmi.read_u_tool(1)
new_tool = Frame()
new_tool.x = 0
new_tool.y = 0
new_tool.z = 150
robot.rmi.write_u_tool(1, new_tool)

# --- Digital I/O ---
din = robot.rmi.read_din(5)
robot.rmi.write_dout(1, OnOff.ON)

# --- Position registers ---
pr = robot.rmi.read_position_register(1)
new_pos = Frame()
new_pos.x = 500
new_pos.y = 200
new_pos.z = 300
config = MotionConfiguration()
config.u_tool_number = 1
config.u_frame_number = 0
robot.rmi.write_position_register(1, config, new_pos)
##
```

## API reference

**Members of Rmi.Data.ControllerStatus**
```csharp
public class ControllerStatus : RmiResponseBase {
    public ControllerStatus()

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Next valid SequenceID when sequence checking is enabled.
    public int NextSequenceId { get; set; }

    // Number of UFRAMEs configured.
    public byte NumberUFrame { get; set; }

    // Number of UTOOLs configured.
    public byte NumberUTool { get; set; }

    // RMI_MOVE program status (1 = aborted).
    public byte ProgramStatus { get; set; }

    // RMI motion runtime state (1 = running).
    public byte RMIMotionStatus { get; set; }

    // Servo ready state (1 = ready).
    public byte ServoReady { get; set; }

    // Single step mode flag (1 = on).
    public byte SingleStepMode { get; set; }

    // Teach pendant mode (0 = disabled/AUTO, 1 = enabled/TEACH).
    public byte TPMode { get; set; }

    public override string ToString()
}
```

**Members of Rmi.Data.ControllerErrorText**
```csharp
public class ControllerErrorText : RmiResponseBase {
    public ControllerErrorText()

    public override bool Equals(object obj)

    // Controller error text in the form XXXX-NNN.
    public string ErrorData { get; set; }

    public override int GetHashCode()

    public override string ToString()
}
```

**Members of Rmi.Data.UFrameUToolNumbers**
```csharp
public class UFrameUToolNumbers : RmiResponseBase {
    public UFrameUToolNumbers()

    public override bool Equals(object obj)

    public override int GetHashCode()

    public override string ToString()

    // Current user frame number.
    public byte UFrameNumber { get; set; }

    // Current user tool number.
    public byte UToolNumber { get; set; }
}
```

**Members of Rmi.Data.DigitalInputValue**
```csharp
public class DigitalInputValue : RmiResponseBase {
    public DigitalInputValue()

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Port number.
    public short PortNumber { get; set; }

    // Port value (0 = OFF, 1 = ON).
    public byte PortValue { get; set; }

    public override string ToString()
}
```

**Members of Rmi.Data.PositionRegisterData**
```csharp
public class PositionRegisterData : RmiResponseBase {
    public PositionRegisterData()

    // Configuration saved in the position register.
    public MotionConfiguration Configuration { get; set; }

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Position saved in the position register.
    public Frame Position { get; set; }

    // Register number.
    public short RegisterNumber { get; set; }

    public override string ToString()
}
```

**Members of Rmi.Data.CartesianPosition**
```csharp
public class CartesianPosition : RmiTimedResponse {
    public CartesianPosition()

    // Active configuration at sampling time.
    public MotionConfiguration Configuration { get; set; }

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Cartesian TCP position.
    public Frame Position { get; set; }

    public override string ToString()
}
```

**Members of Rmi.Data.TcpSpeed**
```csharp
public class TcpSpeed : RmiTimedResponse {
    public TcpSpeed()

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Current tool center point speed.
    public double Speed { get; set; }

    public override string ToString()
}
```