from skip import Schematic import os import shutil import logging logger = logging.getLogger('kicad_interface') class SchematicManager: """Core schematic operations using kicad-skip""" @staticmethod def create_schematic(name, metadata=None): """Create a new empty schematic from template""" try: # Determine template path (use template_with_symbols for component cloning support) template_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), '..', 'templates', 'template_with_symbols.kicad_sch' ) # Determine output path output_path = name if name.endswith('.kicad_sch') else f"{name}.kicad_sch" if os.path.exists(template_path): # Copy template to target location shutil.copy(template_path, output_path) logger.info(f"Created schematic from template: {output_path}") else: # Fallback: create minimal schematic logger.warning(f"Template not found at {template_path}, creating minimal schematic") with open(output_path, 'w') as f: f.write('(kicad_sch (version 20230121) (generator "KiCAD-MCP-Server")\n\n') f.write(' (uuid 00000000-0000-0000-0000-000000000000)\n\n') f.write(' (paper "A4")\n\n') f.write(' (lib_symbols\n )\n\n') f.write(' (sheet_instances\n (path "/" (page "1"))\n )\n') f.write(')\n') # Load the schematic sch = Schematic(output_path) logger.info(f"Loaded new schematic: {output_path}") return sch except Exception as e: logger.error(f"Error creating schematic: {e}") raise @staticmethod def load_schematic(file_path): """Load an existing schematic""" if not os.path.exists(file_path): logger.error(f"Schematic file not found at {file_path}") return None try: sch = Schematic(file_path) logger.info(f"Loaded schematic from: {file_path}") return sch except Exception as e: logger.error(f"Error loading schematic from {file_path}: {e}") return None @staticmethod def save_schematic(schematic, file_path): """Save a schematic to file""" try: # kicad-skip uses write method, not save schematic.write(file_path) logger.info(f"Saved schematic to: {file_path}") return True except Exception as e: logger.error(f"Error saving schematic to {file_path}: {e}") return False @staticmethod def get_schematic_metadata(schematic): """Extract metadata from schematic""" # kicad-skip doesn't expose a direct metadata object on Schematic. # We can return basic info like version and generator. metadata = { "version": schematic.version, "generator": schematic.generator, # Add other relevant properties if needed } logger.debug("Extracted schematic metadata") return metadata if __name__ == '__main__': # Example Usage (for testing) # Create a new schematic new_sch = SchematicManager.create_schematic("MyTestSchematic") # Save the schematic test_file = "test_schematic.kicad_sch" SchematicManager.save_schematic(new_sch, test_file) # Load the schematic loaded_sch = SchematicManager.load_schematic(test_file) if loaded_sch: metadata = SchematicManager.get_schematic_metadata(loaded_sch) print(f"Loaded schematic metadata: {metadata}") # Clean up test file if os.path.exists(test_file): os.remove(test_file) print(f"Cleaned up {test_file}")