Telnet KCL is a text-based protocol that lets you send commands to a Fanuc robot controller. It requires no paid option and is available on all controllers and ROBOGUIDE.

## Key features

- **Program control**: Run, pause, hold, continue, abort programs
- **Variable access**: Read and write system variables
- **I/O control**: Set output ports, simulate and unsimulate inputs
- **Alarm management**: Reset alarms and errors
- **Debugging**: Add breakpoints, step through code line by line
- **Custom commands**: Send any raw KCL command

## Prerequisites

Telnet must be enabled on your robot controller. See [Enable Telnet on your robot](/fanuc/documentation/telnet-enable-on-robot) for setup instructions.

## Quick example

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

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

      // Set connection parameters
      ConnectionParameters parameters = new ConnectionParameters("192.168.0.1");
      parameters.Telnet.Enable = true;
      parameters.Telnet.TelnetKclPassword = "TELNET_PASS";

      // Connect to the robot
      robot.Connect(parameters);

      /**/
      // Reset alarms
      robot.Telnet.Reset();

      // Run a program
      robot.Telnet.Run("MyProgram");
      robot.Telnet.Pause("MyProgram");
      robot.Telnet.Hold("MyProgram");
      robot.Telnet.Continue("MyProgram");
      robot.Telnet.Abort("MyProgram", force: true);

      // Set a variable
      robot.Telnet.SetVariable("$RMT_MASTER", 1);

      // Set an output port (example: DOUT port 2 = 0)
      robot.Telnet.SetPort(KCLPorts.DOUT, 2, 0);

      // Simulate an input port (example: DIN port 3 = 1)
      robot.Telnet.Simulate(KCLPorts.DIN, 3, 1);
      robot.Telnet.Unsimulate(KCLPorts.DIN, 3);
      /**/
    }

  }
```

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

robot = FanucRobot()
parameters = ConnectionParameters("192.168.0.1")
parameters.telnet.enable = True
parameters.telnet.telnet_kcl_password = "TELNET_PASS"
robot.connect(parameters)

##
# Reset alarms
robot.telnet.reset()

# Run a program
robot.telnet.run("MyProgram")
robot.telnet.pause("MyProgram")
robot.telnet.hold("MyProgram")
robot.telnet.continue_("MyProgram")
robot.telnet.abort("MyProgram", force=True)

# Set a variable
robot.telnet.set_variable("$RMT_MASTER", 1)

# Set an output port (DOUT port 2 = 0)
robot.telnet.set_port("DOUT", 2, 0)

# Simulate an input port (DIN port 3 = 1)
robot.telnet.simulate("DIN", 3, 1)
robot.telnet.unsimulate("DIN", 3)
##
```

## Connection

**C# : TelnetConnection**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Telnet;

public class TelnetConnection
{
    static void Main()
    {
        /**/
        // Via FanucRobot
        var robot = new FanucRobot();
        var parameters = new ConnectionParameters("192.168.0.1");
        parameters.Telnet.Enable = true;
        parameters.Telnet.TelnetKclPassword = "your_password";
        robot.Connect(parameters);

        // Or standalone
        var telnet = new TelnetClient();
        telnet.Connect("192.168.0.1", "your_password");
        /**/
    }
}
```

**Python : TelnetConnection**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot
from underautomation.fanuc.connection_parameters import ConnectionParameters
from underautomation.fanuc.telnet.telnet_client import TelnetClient

##
# Via FanucRobot
robot = FanucRobot()
parameters = ConnectionParameters("192.168.0.1")
parameters.telnet.enable = True
parameters.telnet.telnet_kcl_password = "your_password"
robot.connect(parameters)

# Or standalone
telnet = TelnetClient()
telnet.connect("192.168.0.1", "your_password")
##
```

For ROBOGUIDE, pass the workcell folder path instead of an IP address. The SDK reads `services.txt` to find the correct Telnet port.

## Events

The Telnet client raises events for real-time monitoring:

- `MessageReceived` : Fired when a message is received from the controller
- `RawDataReceived` : Raw byte data from the TCP socket
- `ErrorOccured` : Connection or communication errors
- `CommandSent` / `CommandReceived` : Track sent and received KCL commands
- `TpCoordinatesReceived` : Teach pendant coordinate system changes

## Check if Telnet is available

Via FTP, you can check if Telnet is available on the controller:

**C# : TelnetFeatures**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Common.Files.Diagnosis;

public class TelnetFeatures
{
    static void Main()
    {
        FanucRobot robot = new FanucRobot();
        var parameters = new ConnectionParameters("192.168.0.1");
        parameters.Ftp.Enable = true;
        parameters.Ftp.FtpUser = "";
        parameters.Ftp.FtpPassword = "";
        robot.Connect(parameters);

        /**/
        Features features = robot.Ftp.GetSummaryDiagnostic().Features;
        bool isTelnetAvailable = features.HasTelnet;
        /**/
    }
}
```

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

robot = FanucRobot()
parameters = ConnectionParameters("192.168.0.1")
parameters.ftp.enable = True
parameters.ftp.ftp_user = ""
parameters.ftp.ftp_password = ""
robot.connect(parameters)

##
features = robot.ftp.get_summary_diagnostic().features
is_telnet_available = features.has_telnet
##
```

## Limitations

- **Text-based protocol**: Slower than binary protocols like SNPX for bulk data operations
- **Sequential commands**: Commands are sent one at a time over a single TCP connection
- **No bulk register read**: Variable reading is done by name, not by index. Use SNPX, FTP or CGTP for reading registers in bulk

## Next steps

- [Program control](/fanuc/documentation/telnet-program-control) : Run, pause, abort programs
- [Variables & I/O](/fanuc/documentation/telnet-variables-io) : Read/write variables and control ports
- [Debugging & breakpoints](/fanuc/documentation/telnet-debugging) : Step-by-step debugging

## API reference

**Members of Telnet.TelnetClient**
```csharp
public class TelnetClient : TelnetClientBase {
    // Create a new instance of a robot communication
    public TelnetClient()

    // Connect to a robot
    public void Connect(string ip, string telnetKclPassword)
}
```

**Members of Telnet.Internal.TelnetClientBase**
```csharp
public abstract class TelnetClientBase : KclClientBase {
    protected TelnetClientBase()

    // Occurs when a KCL command is received.
    public event EventHandler<KclCommandReceived> CommandReceived

    // Occurs when a command is sent.
    public event EventHandler<CommandSentEventArgs> CommandSent

    // Is Telnet client connected
    public bool Connected { get; }

    // Disconnect Telnet client from robot
    public void Disconnect()

    // Occurs when an error occurs in the KCL client.
    public event EventHandler<KclClientErrorEventArgs> ErrorOccured

    // Connect robot IP address or host name
    public string IP { get; }

    // Controller language (default is English)
    public Languages Language { get; set; }

    // Occurs when a message is received.
    public event EventHandler<MessageReceivedEventArgs> MessageReceived

    // Checks the actual connection status via an active socket polling
    public bool PollAndGetUpdatedConnectedState()

    // Occurs when raw data is received.
    public event EventHandler<RawDataReceivedEventArgs> RawDataReceived

    // Sends a KCL command in Unsafe mode. When used through the CGTP KCL client, success or failure cannot be determined from the result.
    protected override T SendKclUnsafe<T>(string command) where T : Result, new()

    // Sends a KCL command and returns the parsed result.
    protected override T SendKcl<T>(string command) where T : Result, new()

    // Occurs when data is received and its content can successfully be parsed as a string message.
    public event EventHandler<RawDataReceivedEventArgs> StringDataReceived

    // Gets the current Teach Pendant coordinate system.
    public TpCoordinates TpCoordinates { get; }

    // Occurs when TP coordinates are received.
    public event EventHandler<TpCoordinatesReceivedEventArgs> TpCoordinatesReceived
}
```