A pure Python implementation of NetworkTables, used for robot communications in the FIRST Robotics Competition.
75
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.
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
"""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
"""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
"""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
"""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
NT_PERSISTENT = 0x01 # Entry persists across restarts
# Usage in setFlags/clearFlags
entry.setFlags(NT_PERSISTENT) # Make persistent
entry.clearFlags(NT_PERSISTENT) # Remove persistencefrom 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")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}")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/')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')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()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")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()Install with Tessl CLI
npx tessl i tessl/pypi-pynetworktablesdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10