CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pynetworktables

A pure Python implementation of NetworkTables, used for robot communications in the FIRST Robotics Competition.

75

1.01x
Overview
Eval results
Files

persistence-data.mddocs/

Persistence and Data Management

Data persistence across restarts, entry management, and bulk operations. Critical for maintaining configuration and state information between robot sessions, enabling seamless transitions and preserving important settings.

Capabilities

Persistent Entry Management

Control which entries persist across NetworkTables restarts.

def setPersistent(key: str):
    """
    Make an entry persistent across NetworkTables restarts.
    
    Parameters:
    - key: str. Entry key to make persistent
    """

def clearPersistent(key: str):
    """
    Remove persistence from an entry.
    
    Parameters:
    - key: str. Entry key to make non-persistent
    """

def isPersistent(key: str) -> bool:
    """
    Check if an entry is persistent.
    
    Parameters:
    - key: str. Entry key to check
    
    Returns:
        bool: True if entry is persistent, False otherwise
    """

File-Based Persistence

Save and load NetworkTables data to/from files.

def savePersistent(filename: str):
    """
    Save all persistent entries to a file.
    
    Parameters:
    - filename: str. File path to save persistent data to
    """

def loadPersistent(filename: str):
    """
    Load persistent entries from a file.
    
    Parameters:
    - filename: str. File path to load persistent data from
    """

def saveEntries(filename: str, prefix: str):
    """
    Save entries matching a prefix to a file.
    
    Parameters:
    - filename: str. File path to save entries to
    - prefix: str. Entry prefix to match (e.g., "/SmartDashboard/")
    """

def loadEntries(filename: str, prefix: str):
    """
    Load entries from a file with a specific prefix.
    
    Parameters:
    - filename: str. File path to load entries from  
    - prefix: str. Prefix to prepend to loaded entries
    """

Entry Flag Management

Manage entry flags for various behaviors including persistence.

def setFlags(key: str, flags: int):
    """
    Set flags for an entry.
    
    Parameters:
    - key: str. Entry key
    - flags: int. Bitmask of flags to set (e.g., NT_PERSISTENT)
    """

def clearFlags(key: str, flags: int):
    """
    Clear flags for an entry.
    
    Parameters:
    - key: str. Entry key
    - flags: int. Bitmask of flags to clear
    """

def getFlags(key: str) -> int:
    """
    Get flags for an entry.
    
    Parameters:
    - key: str. Entry key
    
    Returns:
        int: Bitmask of entry flags
    """

Bulk Entry Operations

Perform operations on multiple entries at once.

def deleteAllEntries():
    """Delete all entries in this NetworkTables instance."""

def getEntries(prefix: str, types: int = 0) -> List[NetworkTableEntry]:
    """
    Get all entries with names starting with the given prefix.
    
    Parameters:
    - prefix: str. Path prefix to match (e.g., "/Config/")
    - types: int. Bitmask of entry types to include (default: 0 for all types)
    
    Returns:
        List[NetworkTableEntry]: List of matching entries
    """

def getEntryInfo(prefix: str, types: int = 0) -> List[tuple]:
    """
    Get information about entries matching the prefix.
    
    Parameters:
    - prefix: str. Path prefix to match
    - types: int. Bitmask of entry types to include (default: 0 for all types)
    
    Returns:
        List[tuple]: List of (name, type, flags) tuples for matching entries
    """

Entry Deletion

Delete individual entries from NetworkTables.

class NetworkTable:
    def delete(key: str):
        """
        Delete an entry from the table.
        
        Parameters:
        - key: str. Entry key to delete
        """

class NetworkTableEntry:
    def delete() -> bool:
        """
        Delete this entry from NetworkTables.
        
        Returns:
            bool: True if entry was deleted, False if it didn't exist
        """

Entry Flag Constants

# Entry flag constants
NT_PERSISTENT = 0x01  # Entry persists across restarts

# Usage in setFlags/clearFlags
entry.setFlags(NT_PERSISTENT)  # Make persistent
entry.clearFlags(NT_PERSISTENT)  # Remove persistence

Usage Examples

Basic Persistence Configuration

from networktables import NetworkTables

# Initialize connection
NetworkTables.initialize(server='roborio-1234-frc.local')
sd = NetworkTables.getTable('SmartDashboard')

# Set configuration values and make them persistent
sd.putNumber('maxSpeed', 2.5)
sd.setPersistent('maxSpeed')

sd.putString('autonomousMode', 'defense')
sd.setPersistent('autonomousMode')

sd.putBoolean('compressorEnabled', True)
sd.setPersistent('compressorEnabled')

# Check persistence status
if sd.isPersistent('maxSpeed'):
    print("Max speed will survive robot restart")

File-Based Persistence

from networktables import NetworkTables

# Save all persistent values to file
try:
    NetworkTables.savePersistent('robot_config.ini')
    print("Configuration saved successfully")
except Exception as e:
    print(f"Failed to save configuration: {e}")

# Load persistent values from file on startup
try:
    NetworkTables.loadPersistent('robot_config.ini')
    print("Configuration loaded successfully")
except Exception as e:
    print(f"Failed to load configuration: {e}")

Selective Data Export/Import

from networktables import NetworkTables

# Save only SmartDashboard data
NetworkTables.saveEntries('dashboard_data.ini', '/SmartDashboard/')

# Save only Vision processing data  
NetworkTables.saveEntries('vision_config.ini', '/Vision/')

# Load data with different prefix (data migration)
NetworkTables.loadEntries('old_config.ini', '/LegacyConfig/')

Configuration Management Class

from networktables import NetworkTables

class RobotConfig:
    def __init__(self, config_file='robot_config.ini'):
        self.config_file = config_file
        self.config_table = NetworkTables.getTable('Config')
        
    def load_defaults(self):
        """Load default configuration values."""
        defaults = {
            'maxSpeed': 1.0,
            'autonomousMode': 'defense',
            'compressorEnabled': True,
            'visionProcessingEnabled': False,
            'pidGains': [0.1, 0.0, 0.01]
        }
        
        for key, value in defaults.items():
            # Set defaults without overwriting existing values
            if isinstance(value, bool):
                self.config_table.setDefaultBoolean(key, value)
            elif isinstance(value, (int, float)):
                self.config_table.setDefaultNumber(key, value)
            elif isinstance(value, str):
                self.config_table.setDefaultString(key, value)
            elif isinstance(value, list):
                self.config_table.setDefaultValue(key, value)
            
            # Make all config values persistent
            self.config_table.setPersistent(key)
    
    def save_config(self):
        """Save configuration to file."""
        try:
            NetworkTables.saveEntries(self.config_file, '/Config/')
            print(f"Configuration saved to {self.config_file}")
            return True
        except Exception as e:
            print(f"Failed to save config: {e}")
            return False
    
    def load_config(self):
        """Load configuration from file."""
        try:
            NetworkTables.loadEntries(self.config_file, '/Config/')
            print(f"Configuration loaded from {self.config_file}")
            return True
        except Exception as e:
            print(f"Failed to load config: {e}")
            return False
    
    def get_config_value(self, key, default=None):
        """Get a configuration value with type detection."""
        entry = self.config_table.getEntry(key)
        if not entry.exists():
            return default
            
        entry_type = entry.getType()
        if entry_type == NetworkTables.EntryTypes.BOOLEAN:
            return entry.getBoolean(default)
        elif entry_type == NetworkTables.EntryTypes.DOUBLE:
            return entry.getDouble(default)
        elif entry_type == NetworkTables.EntryTypes.STRING:
            return entry.getString(default)
        else:
            return entry.value

# Usage
config = RobotConfig()
config.load_defaults()
config.load_config()  # Load saved values

# Access configuration
max_speed = config.get_config_value('maxSpeed', 1.0)
auto_mode = config.get_config_value('autonomousMode', 'defense')

Entry Cleanup and Management

from networktables import NetworkTables

def cleanup_old_entries():
    """Remove old or temporary entries."""
    # Get all entries with "temp" prefix
    temp_entries = NetworkTables.getEntries('/temp/')
    
    print(f"Cleaning up {len(temp_entries)} temporary entries")
    for entry in temp_entries:
        entry.delete()
    
    # Remove specific old entries
    old_keys = ['/SmartDashboard/oldValue1', '/SmartDashboard/oldValue2']
    for key in old_keys:
        entry = NetworkTables.getEntry(key)
        if entry.exists():
            entry.delete()
            print(f"Deleted old entry: {key}")

def list_persistent_entries():
    """List all persistent entries for debugging."""
    all_entries = NetworkTables.getEntries('/')
    persistent_entries = []
    
    for entry in all_entries:
        if entry.isPersistent():
            persistent_entries.append(entry.getName())
    
    print("Persistent entries:")
    for name in sorted(persistent_entries):
        print(f"  {name}")
    
    return persistent_entries

# Usage
cleanup_old_entries()
list_persistent_entries()

Advanced Flag Management

from networktables import NetworkTables

# Direct flag management using NetworkTable
sd = NetworkTables.getTable('SmartDashboard')

# Set multiple flags at once
flags = NetworkTables.EntryFlags.PERSISTENT
sd.setFlags('importantValue', flags)

# Check current flags
current_flags = sd.getFlags('importantValue')
if current_flags & NetworkTables.EntryFlags.PERSISTENT:
    print("Value is persistent")

# Clear specific flags
sd.clearFlags('importantValue', NetworkTables.EntryFlags.PERSISTENT)

# Using entry-level flag management
entry = NetworkTables.getEntry('/SmartDashboard/criticalData')
entry.setFlags(NetworkTables.EntryFlags.PERSISTENT)

if entry.isPersistent():
    print("Entry is persistent")

Bulk Data Operations

from networktables import NetworkTables

def backup_all_data(backup_file='nt_backup.ini'):
    """Backup all NetworkTables data."""
    try:
        # Save everything by using root prefix
        NetworkTables.saveEntries(backup_file, '/')
        print(f"All data backed up to {backup_file}")
        return True
    except Exception as e:
        print(f"Backup failed: {e}")
        return False

def restore_from_backup(backup_file='nt_backup.ini'):
    """Restore data from backup file."""
    try:
        # Clear existing data first (optional)
        NetworkTables.deleteAllEntries()
        
        # Load from backup
        NetworkTables.loadEntries(backup_file, '/')
        print(f"Data restored from {backup_file}")
        return True
    except Exception as e:
        print(f"Restore failed: {e}")
        return False

def migrate_data_structure():
    """Migrate data from old structure to new structure."""
    # Get old entries
    old_entries = NetworkTables.getEntries('/OldConfig/')
    
    # Migrate to new location
    for entry in old_entries:
        old_name = entry.getName()
        new_name = old_name.replace('/OldConfig/', '/Config/')
        
        # Copy value to new location
        new_entry = NetworkTables.getEntry(new_name)
        new_entry.setValue(entry.value)
        
        # Copy persistence
        if entry.isPersistent():
            new_entry.setPersistent()
        
        # Delete old entry
        entry.delete()
        
        print(f"Migrated {old_name} -> {new_name}")

# Usage
backup_all_data()
migrate_data_structure() 
restore_from_backup()

Best Practices

  1. Use persistence sparingly: Only make truly configuration-related values persistent
  2. Regular backups: Save important data periodically, not just on shutdown
  3. Error handling: Always handle file I/O errors gracefully
  4. Data validation: Validate loaded data before using it
  5. Cleanup: Remove temporary entries to keep NetworkTables clean
  6. Migration support: Plan for data structure changes over time

Install with Tessl CLI

npx tessl i tessl/pypi-pynetworktables

docs

entry-interface.md

index.md

instance-management.md

integration-utilities.md

listeners-events.md

persistence-data.md

table-operations.md

tile.json