---
name: escl-query
description: >
  Query and analyze electrical schematics from ESCL files. Use when user has an ESCL file 
  and wants to ask technical questions about the machine, trace power supply chains, 
  find cross-references, analyze impact of failures, understand system architecture, 
  troubleshoot electrical issues, or find component specifications and connections.
  Now includes visual annotation support with highlighted regions and checklists.
---

# ESCL Query Skill

Analyze and answer questions about electrical systems from ESCL files.

## When to Use

User has an .escl file (or ESCL content) and asks:
- "What feeds motor -M7?"
- "Where is contactor -K1M referenced?"
- "What happens if breaker -Q5 trips?"
- "Show me all VFDs in the system"
- "What protects the Spitzendformer motor?"
- "List all components on L502"
- "How is the safety circuit structured?"

---

## Visual Annotation Feature

When answering queries, generate an annotated image showing:
1. Cropped region from the schematic page
2. Highlighted component(s) with colored boxes
3. Auto-generated checklist based on component type

### Image Generation Code

```python
from PIL import Image, ImageDraw, ImageFont
import os

def generate_annotated_image(
    page_image_path: str,
    component_tag: str,
    component_type: str,
    grid_col: tuple,  # (start_col, end_col) 0-9
    grid_row: tuple,  # (start_row, end_row) 1-8
    output_path: str
):
    """
    Generate annotated schematic image with highlight and checklist.
    
    Grid system: columns 0-9 (left to right), rows 1-8 (top to bottom)
    Standard page size at 150 DPI: ~1753 x 1240 pixels
    """
    
    # Load image
    img = Image.open(page_image_path)
    width, height = img.size
    
    # Grid calculation (excluding title block area)
    margin_left = int(width * 0.05)
    margin_right = int(width * 0.95)
    margin_top = int(height * 0.05)
    margin_bottom = int(height * 0.85)  # Leave space for title block
    
    usable_width = margin_right - margin_left
    usable_height = margin_bottom - margin_top
    
    col_width = usable_width / 10
    row_height = usable_height / 8
    
    # Calculate crop region (with padding)
    pad = 20
    x1 = int(margin_left + grid_col[0] * col_width) - pad
    x2 = int(margin_left + (grid_col[1] + 1) * col_width) + pad
    y1 = int(margin_top + (grid_row[0] - 1) * row_height) - pad
    y2 = int(margin_top + grid_row[1] * row_height) + pad
    
    # Ensure bounds
    x1, y1 = max(0, x1), max(0, y1)
    x2, y2 = min(width, x2), min(height, y2)
    
    # Crop region
    cropped = img.crop((x1, y1, x2, y2))
    crop_w, crop_h = cropped.size
    
    # Get checklist for component type
    checklist = get_checklist(component_type)
    
    # Calculate final image size (cropped + checklist area)
    checklist_height = 25 * (len(checklist) + 1)  # 25px per line + header
    final_height = crop_h + checklist_height + 10
    final_width = max(crop_w, 350)  # Min width for checklist text
    
    # Create final image
    final = Image.new('RGB', (final_width, final_height), 'white')
    
    # Paste cropped schematic (centered if narrower than checklist)
    paste_x = (final_width - crop_w) // 2
    final.paste(cropped, (paste_x, 0))
    
    draw = ImageDraw.Draw(final)
    
    # Draw highlight box on cropped region (center area)
    highlight_margin = 30
    box_x1 = paste_x + highlight_margin
    box_y1 = highlight_margin
    box_x2 = paste_x + crop_w - highlight_margin
    box_y2 = crop_h - highlight_margin
    
    # Red highlight box with thicker border
    for i in range(3):
        draw.rectangle(
            [box_x1 - i, box_y1 - i, box_x2 + i, box_y2 + i],
            outline='#CC0000'
        )
    
    # Component tag label
    try:
        font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 14)
        font_small = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 12)
    except:
        font = ImageFont.load_default()
        font_small = font
    
    # Tag label with background
    tag_text = f" {component_tag} "
    tag_bbox = draw.textbbox((0, 0), tag_text, font=font)
    tag_w = tag_bbox[2] - tag_bbox[0]
    tag_h = tag_bbox[3] - tag_bbox[1]
    
    draw.rectangle([box_x1, box_y1 - tag_h - 6, box_x1 + tag_w + 4, box_y1 - 2], fill='#CC0000')
    draw.text((box_x1 + 2, box_y1 - tag_h - 5), tag_text, fill='white', font=font)
    
    # Separator line
    sep_y = crop_h + 5
    draw.line([(10, sep_y), (final_width - 10, sep_y)], fill='#CCCCCC', width=1)
    
    # Checklist
    y_pos = crop_h + 15
    
    # Header
    draw.text((10, y_pos), f"Checklist: {component_type}", fill='#333333', font=font)
    y_pos += 25
    
    # Checklist items
    for item in checklist:
        priority, text = item
        
        # Priority color
        colors = {'critical': '#CC0000', 'important': '#CC9900', 'verify': '#339933'}
        bullet_color = colors.get(priority, '#666666')
        
        # Checkbox
        draw.rectangle([15, y_pos + 2, 25, y_pos + 12], outline='#666666')
        
        # Priority indicator
        draw.ellipse([30, y_pos + 3, 40, y_pos + 13], fill=bullet_color)
        
        # Text
        draw.text((45, y_pos), text, fill='#333333', font=font_small)
        y_pos += 22
    
    # Save
    final.save(output_path)
    return output_path


def get_checklist(component_type: str) -> list:
    """Return checklist items based on component type. Format: (priority, text)"""
    
    checklists = {
        'breaker': [
            ('critical', 'Check set current matches motor FLA'),
            ('critical', 'Verify not tripped'),
            ('important', 'Check aux contact wiring'),
            ('verify', 'Test manual trip/reset'),
        ],
        'contactor': [
            ('critical', 'Verify coil voltage matches supply'),
            ('important', 'Check main contact condition'),
            ('important', 'Verify aux contacts wired correctly'),
            ('verify', 'Listen for chatter (coil issue)'),
        ],
        'motor': [
            ('critical', 'Verify nameplate matches project'),
            ('critical', 'Check rotation direction'),
            ('important', 'Measure insulation resistance'),
            ('verify', 'Check coupling alignment'),
        ],
        'vfd': [
            ('critical', 'Verify motor parameters programmed'),
            ('critical', 'Check safety function (STO) wiring'),
            ('important', 'Verify IP address / bus address'),
            ('important', 'Check braking resistor connection'),
            ('verify', 'Review fault history'),
        ],
        'safety_relay': [
            ('critical', 'Verify dual-channel wiring'),
            ('critical', 'Test feedback loop monitoring'),
            ('critical', 'Check E-Stop chain continuity'),
            ('important', 'Verify reset mode (manual/auto)'),
            ('verify', 'Document response time'),
        ],
        'sensor': [
            ('critical', 'Verify sensor type (PNP/NPN)'),
            ('important', 'Check signal wire to correct input'),
            ('important', 'Verify supply voltage'),
            ('verify', 'Test detection range/sensitivity'),
        ],
        'thermistor': [
            ('critical', 'Verify thermistor type (PTC/NTC)'),
            ('important', 'Check connection to relay input'),
            ('verify', 'Test trip temperature'),
        ],
        'proportional_valve': [
            ('critical', 'Verify analog signal range (0-10V/4-20mA)'),
            ('important', 'Check hydraulic connections'),
            ('important', 'Verify amplifier card settings'),
            ('verify', 'Test stroke at 50% signal'),
        ],
    }
    
    # Default checklist for unknown types
    default = [
        ('important', 'Verify wiring matches schematic'),
        ('important', 'Check supply voltage present'),
        ('verify', 'Test function manually'),
    ]
    
    return checklists.get(component_type.lower(), default)
```

### Usage in Query Response

When answering a query, after finding the relevant component:

```python
# Example: User asks "What protects motor M1?"
# Found: breaker -Q1, page 46, columns 2-3, rows 3-5

generate_annotated_image(
    page_image_path="/home/claude/escl_pages/page_046.png",
    component_tag="-Q1",
    component_type="breaker",
    grid_col=(2, 3),
    grid_row=(3, 5),
    output_path="/mnt/user-data/outputs/check_Q1.png"
)
```

Then present the image to the user along with the text answer.

---

## Query Types

### 1. Component Lookup
**Question:** "What is -U1?" / "Tell me about -M7"

**Method:**
1. Find component block by tag
2. Return type, description, all attributes
3. Include location and cross-references
4. **Generate annotated image if page location known**

**Response format:**
```
-U1 is a VFD (Variable Frequency Drive)
  Model: MDX61B0110-5A3-4-00
  Power: 11kW
  Location: =9/4.3
  Controls: Motor -M7
  
[Annotated image with VFD checklist]
```

### 2. Supply Chain Trace (Upstream)
**Question:** "What feeds -M7?" / "Where does -U1 get power?"

**Method:**
1. Find component
2. Follow fed_by, input, <- references upstream
3. Continue until reaching main supply or potential origin
4. **Generate annotated image showing protection device**

### 3. Consumer Trace (Downstream)
**Question:** "What does L502 supply?" / "What is connected to -Q1?"

**Method:**
1. Find potential or component
2. Collect all consumers
3. Group by type

### 4. Cross-Reference Search
**Question:** "Where is -K1M referenced?" / "Find all uses of -20-K1"

**Method:**
1. Search entire ESCL for tag mentions
2. Extract location context for each
3. Categorize by reference type

### 5. Impact Analysis
**Question:** "What happens if -Q5 trips?" / "What stops when L502 is lost?"

**Method:**
1. Find component/potential
2. Trace all downstream dependencies
3. Identify affected motors, drives, safety functions
4. **Generate annotated image of the component**

### 6. Troubleshooting Support
**Question:** "Motor -M7 will not start, what should I check?"

**Method:**
1. Trace full supply chain
2. Identify all protection and interlock points
3. **Generate annotated image for each checkpoint**

---

## ESCL Location Format

For visual annotation, ESCL should include grid coordinates:

```
breaker -Q1 "Motor protection" {
  model: "3RV2021-4BA10"
  page: 46
  grid: col=2-3, row=3-5
}
```

If grid not specified, estimate from page section references:
- `=section/page.column` → column roughly maps to grid

---

## Response Guidelines

1. **Be specific** - Use exact tags, locations, values from ESCL
2. **Show the path** - For traces, show complete chain with arrows
3. **Include visuals** - Generate annotated image when location is known
4. **Reference locations** - Always include =x/y.z for verification
5. **Auto-checklist** - Include relevant checks based on component type
6. **Present image** - Use `present_files` to show annotated image to user
