End-to-end download via MCP was failing for three reasons; all three
fixed here so the agent can drive the whole flow without manual IDE
clicks.
1. verify_device_reachable did a live gateway.perform_network_scan()
on every call. That freezes the CODESYS UI thread for the full
scan duration, so the user couldn't interact with the IDE during
pre-flight (and a 60s tool timeout was easy to hit). Now reads
gateway.get_cached_network_scan_result() first (instant, no UI
block), only falls back to a live scan when no cache exists.
Adds scan_source ("cache" | "live") to the JSON so callers know
which path was taken.
2. rebind_device_to_scan short-circuited with "already-bound" when
the resolved address matched the cached one. But the IDE's
Select-Device + OK flow re-applies set_gateway_and_address even
when the address didn't change -- that's what refreshes the
device's scanned_* properties and re-establishes a session.
Skipping it left the binding stale even after a successful
rebind call. Always apply now.
3. ensure_online_connection created an online_application but never
opened a device session. login() then waited on (or popped a
dialog for) a session nobody had opened -- which is what the
user was doing manually as "right-click device -> Connect".
Adds _ensure_device_connected() helper that locates the project's
PLC device, creates a ScriptOnlineDevice, and calls connect() if
not already connected. Idempotent; best-effort (logs and falls
through on failure so login() can still try its own path).