The SDK includes offline file parsers for reading and editing Fanuc controller files without a network connection. Download files from the robot via FTP, then parse them locally.

## Variable files (.va)

Parse any variable file (.va) into a hierarchical list of typed variables:

**C# : OfflineFileParsingVariable**
```csharp
using UnderAutomation.Fanuc.Common.Files.Variables;
using UnderAutomation.Fanuc.Common.Files;
using UnderAutomation.Fanuc.Common;

public class OfflineFileParsingVariable
{
    static void Main()
    {
        /**/
        // Parse a variable file
        GenericVariableFile vaFile = FanucFileReaders.VariableReader.ReadFile("C:/backup/numreg.va", Languages.English);

        // Browse variables
        foreach (var variable in vaFile.Variables)
        {
            Console.WriteLine($"{variable.Name} = {variable.Value} [{variable.Type}]");
        }

        // Re-generate the .va file
        vaFile.GenerateVa("C:/backup/numreg_modified.va");
        /**/
    }
}
```

**Python : OfflineFileParsingVariable**
```python
from underautomation.fanuc.ftp.fanuc_file_readers import FanucFileReaders

##
# Parse a variable file
va_file = FanucFileReaders.variable_reader.read_file("C:/backup/numreg.va")

# Browse variables
for variable in va_file.variables:
    print(f"{variable.name} = {variable.value} [{variable.type}]")

# Edit a variable value
va_file.variables[0].value = "42"

# Re-generate the .va file
va_file.generate_va("C:/backup/numreg_modified.va")
##
```

This works with all .va files: `numreg.va`, `posreg.va`, `strreg.va`, `sysvars.va`, `sysmotn.va`, etc.

## Error log (errall.ls)

**C# : OfflineFileParsingReaders**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Ftp;

public class OfflineFileParsingReaders
{
    static void Main()
    {
        /**/
        // Error log
        var errors = FanucFileReaders.ErrorListReader.ReadFile("C:/backup/errall.ls", Languages.English);
        foreach (var error in errors.Items)
        {
            Console.WriteLine($"{error.OccurringTime} [{error.ErrorCode}] {error.Message}");
        }

        // I/O state
        var ioState = FanucFileReaders.IOStateReader.ReadFile("C:/backup/iostate.dg", Languages.English);

        // Safety status
        var safety = FanucFileReaders.SafetyStatusReader.ReadFile("C:/backup/safety.dg", Languages.English);

        // Current position
        var currentPos = FanucFileReaders.CurrentPositionReader.ReadFile("C:/backup/curpos.dg", Languages.English);
        /**/
    }
}
```

**Python : OfflineFileParsingReaders**
```python
from underautomation.fanuc.ftp.fanuc_file_readers import FanucFileReaders

##
# Error log
errors = FanucFileReaders.error_list_reader.read_file("C:/backup/errall.ls")
for error in errors.errors:
    print(f"{error.date_time} [{error.severity}] {error.message}")

# I/O state
io_state = FanucFileReaders.io_state_reader.read_file("C:/backup/iostate.dg")

# Safety status
safety = FanucFileReaders.safety_status_reader.read_file("C:/backup/safety.dg")

# Current position
current_pos = FanucFileReaders.current_position_reader.read_file("C:/backup/curpos.dg")
##
```


## Workflow: FTP download + offline parse

A common pattern is to download files via FTP and parse them locally:

**C# : OfflineFileParsingWorkflow**
```csharp
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Ftp;

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

        /**/
        // Download a file from the robot
        robot.Ftp.DirectFileHandling.DownloadFileFromController("numreg.va", "md:/numreg.va");

        // Parse offline
        var vaFile = FanucFileReaders.VariableReader.ReadFile("numreg.va", Languages.English);

        // Or use the built-in helpers
        var numRegs = robot.Ftp.KnownVariableFiles.GetNumregFile();
        var posRegs = robot.Ftp.KnownVariableFiles.GetPosregFile();
        /**/
    }
}
```

**Python : OfflineFileParsingWorkflow**
```python
from underautomation.fanuc.fanuc_robot import FanucRobot
from underautomation.fanuc.ftp.fanuc_file_readers import FanucFileReaders

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

##
# Download a file from the robot
data = robot.ftp.download_file_as_bytes("md:/numreg.va")
with open("numreg.va", "wb") as f:
    f.write(data)

# Parse offline
va_file = FanucFileReaders.variable_reader.read_file("numreg.va")

# Or use the built-in helpers
num_regs = robot.ftp.known_variable_files.get_numeric_registers()
pos_regs = robot.ftp.known_variable_files.get_position_registers()
##
```

## Complete example

**C# : OfflineFileParsing**
```csharp
using UnderAutomation.Fanuc.Common;
using UnderAutomation.Fanuc.Common.Files;
using UnderAutomation.Fanuc.Common.Files.Variables;

public class OfflineFileParsing
{
  static void Main()
  {
    /**/
    // Parse a variable file and extract a hierarchical list of variables
    GenericVariableFile vaFile = FanucFileReaders.VariableReader.ReadFile("C:/path/to/variable.va", Languages.English);
    foreach (var variable in vaFile.Variables)
      Console.WriteLine($"{variable.Name} = {variable.Value} [{variable.Type}]");

    // Edit and regenerate the variable file
    vaFile.GenerateVa("C:/path/to/variable_modified.va\"");

    // Parse several types of files 
    FanucFileReaders.ErrorListReader.ReadFile("C:/path/to/errall.ls", Languages.English);
    FanucFileReaders.IOStateReader.ReadFile("C:/path/to/iostate.dg", Languages.English);
    FanucFileReaders.SafetyStatusReader.ReadFile("C:/path/to/safety.dg", Languages.English);
    FanucFileReaders.CurrentPositionReader.ReadFile("C:/path/to/curpos.dg", Languages.English);
    /**/
  }

}
```

**Python : OfflineFileParsing**
```python
from underautomation.fanuc.ftp.fanuc_file_readers import FanucFileReaders

##
# Parse a variable file
va_file = FanucFileReaders.variable_reader.read_file("C:/backup/numreg.va")
for variable in va_file.variables:
    print(f"{variable.name} = {variable.value} [{variable.type}]")

# Edit and regenerate the variable file
va_file.variables[0].value = "42"
va_file.generate_va("C:/backup/numreg_modified.va")

# Parse error log
errors = FanucFileReaders.error_list_reader.read_file("C:/backup/errall.ls")

# Parse I/O state
io_state = FanucFileReaders.io_state_reader.read_file("C:/backup/iostate.dg")

# Parse safety status
safety = FanucFileReaders.safety_status_reader.read_file("C:/backup/safety.dg")

# Parse current position
current_pos = FanucFileReaders.current_position_reader.read_file("C:/backup/curpos.dg")
##
```

## API reference

**Members of Common.Files.Variables.GenericVariableFile**
```csharp
public class GenericVariableFile : IGenericVariableType, IFanucContent {
    public GenericVariableFile()

    public override bool Equals(object obj)

    // Generates a .va file and writes it to the specified stream
    public void GenerateVa(Stream stream)

    // Generates a .va file and writes it to the specified path
    public void GenerateVa(string pathToVa)

    // Generates the content of a .va variable file as a string.
    public string GeneratedVa()

    // Gets a variable by name (case-insensitive)
    public GenericVariable GetField(string name)

    public override int GetHashCode()

    // File name
    public string Name { get; }

    // Parent container
    public IGenericVariableType Parent { get; set; }

    public override string ToString()

    // Variables declared in this file
    public GenericVariable[] Variables { get; }
}
```

**Members of Common.Files.FanucFileReaders**
```csharp
public static class FanucFileReaders {
    // Decode current position file curpos.dg
    public static readonly DiagnosisReader<CurrentPosition, CurrentPositionReader> CurrentPositionReader

    // Helper to read error files like errall.ls
    public static readonly ErrorListReader ErrorListReader

    // Decode IO Status file iostate.dg
    public static readonly DiagnosisReader<IOState, IOStateParser> IOStateReader

    // Decode task and program states prgstate.dg
    public static readonly DiagnosisReader<ProgramStates, ProgramStatesParser> ProgramStates

    // Read any file by path on disc, recognize it by name and decode it
    public static IFanucContent ReadFile(Stream fileStream, string fileName, Languages language)

    // Read any file by path on disc, recognize it by name and decode it
    public static IFanucContent ReadFile(string fileName, Languages language)

    // Get the collection of all parsers
    public static IFileReader<IFanucContent>[] Readers { get; }

    // Decode IO Status file iostate.dg
    public static readonly DiagnosisReader<SafetyStatus, SafetyStatusParser> SafetyStatusReader

    // Helper to read summary diagnosis file summary.dg
    public static readonly SummaryDiagnosisReader SummaryDiagnosticReader

    // Helper to read variable files *.va
    public static readonly VariableReader VariableReader
}
```