# Debugging Oak Applications

This guide explains how to debug Python applications running on OAK4 using:

 * VS Code (via [debugpy](https://github.com/microsoft/debugpy))
 * PyCharm Professional (via [pydevd-pycharm](https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html))
 * Web-based debugging (via [web-pdb](https://github.com/romanvm/kodi.web-pdb))

All approaches work with applications deployed and started using oakctl.

## Debugging Python Applications

#### Overview

VS Code debugging is done by attaching to a running Python process on OAK4 using debugpy.

#### 1. VS Code Configuration

Create the file: .vscode/launch.json in your project directory with the following content:

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach to OAK4",
      "type": "python",
      "request": "attach",
      "stopOnEntry": true,
      "justMyCode": false,
      "connect": {
        "host": "<DEVICE_IP>",
        "port": 5678
      },
      "pathMappings": [
        {
          "localRoot": "${workspaceFolder}",
          "remoteRoot": "/app"
        }
      ]
    }
  ]
}
```

> Replace
> `<DEVICE_IP>`
> with the IP address of your OAK4 device.

> **Note (project root / workspace folder):**
> VS Code resolves
> `${workspaceFolder}`
> to the folder you opened in VS Code. If your
> `.vscode/launch.json`
> lives
> **outside**
> the actual project root, update
> `pathMappings.localRoot`
> to point to your real project root.

#### 2. Add Dependency

Add debugpy to your requirements.txt:

```text
debugpy
```

#### 3. Enable debugpy at Application Startup

How you do this depends on how your app is started.

Option A: Modify backend-run.sh to start Python through debugpy:

```bash
exec python3.12 -m debugpy --listen 0.0.0.0:5678 --wait-for-client /app/main.py
```

 * --wait-for-client pauses execution until VS Code attaches
 * Port 5678 must be accessible

Option B: App Uses oakapp.toml Entrypoint

Edit oakapp.toml:

```toml
entrypoint = ["bash","-c","python3.12 -u -m debugpy --listen 0.0.0.0:5678 --wait-for-client /app/main.py"]
```

#### 4. Run and Attach

Start the app:

```bash
oakctl app run .
```

In VS Code:

 * Open Run & Debug
 * Select Attach to OAK4
 * Click Start Debugging

Your breakpoints should now be hit.

Important: PyCharm debugging does not work with the trial license. A Professional license is required.

#### 1. Add Dependency

Add the following to requirements.txt:

```text
pydevd-pycharm~=253.29346.142
```

#### 2. Create debug.py

Create debug.py with the following contents:

```python
#!/usr/bin/env python3

import importlib
import os
import runpy
import sys
import time

def _configure_pycharm_path_mappings() -> None:
    """Configure IDE(local)->container(server) path mapping for breakpoint binding."""

    client_path = os.getenv("PYCHARM_CLIENT_PATH")
    server_path = os.getenv("PYCHARM_SERVER_PATH")
    if not client_path or not server_path:
        return

    for mod in (
        "_pydevd_bundle.pydevd_file_utils",
        "pydevd._pydevd_bundle.pydevd_file_utils",
        "pydevd_file_utils",
    ):
        try:
            pydevd_file_utils = importlib.import_module(mod)
            pydevd_file_utils.setup_client_server_paths([(client_path, server_path)])
            return
        except Exception:
            continue

def attach_pycharm_if_available() -> None:
    host = os.getenv("PYCHARM_DEBUG_HOST", "<YOUR_IP>")
    port = int(os.getenv("PYCHARM_DEBUG_PORT", "5678"))
    timeout_s = float(os.getenv("PYCHARM_DEBUG_TIMEOUT", "30"))

    suspend = os.getenv("PYCHARM_DEBUG_SUSPEND", "0").lower() in {"1", "true", "yes"}

    deadline = time.time() + timeout_s
    while True:
        try:
            import pydevd_pycharm

            _configure_pycharm_path_mappings()

            pydevd_pycharm.settrace(
                host,
                port=port,
                stdout_to_server=True,
                stderr_to_server=True,
                suspend=suspend,
                trace_only_current_thread=False,
                patch_multiprocessing=True,
            )
            return
        except (ConnectionRefusedError, OSError):
            if time.time() > deadline:
                return
            time.sleep(0.5)
        except Exception:
            return

def main() -> None:
    os.chdir("/app")
    if "/app" not in sys.path:
        sys.path.insert(0, "/app")

    attach_pycharm_if_available()
    runpy.run_path("/app/main.py", run_name="__main__")

if __name__ == "__main__":
    main()
```

> Replace <YOUR_IP> with your computer’s IP address.

#### 3. Add Environment Variables to oakapp.toml

```toml
[env]
PYCHARM_CLIENT_PATH = "path/to/app"
PYCHARM_SERVER_PATH = "/app"
```

#### 4. Configure App Startup

Option A: Using backend-run.sh:

```bash
exec python3.12 /app/debug.py
```

Option B: Using oakapp.toml:

```toml
entrypoint = ["bash","-c","python3.12 -u /app/debug.py"]
```

#### 5. Configure PyCharm Debug Server

 1. Open Run → Edit Configurations
 2. Add Python Debug Server
 3. Set IDE host name: your computer IP and Port: 5678
 4. Configure Path Mappings: Local path: your project directory and Remote path: /app
 5. Click Apply → OK
 6. Start the debug server

#### 6. Run the App

```bash
oakctl app run .
```

Your PyCharm debugger should attach automatically.

This option is useful when you cannot attach an IDE debugger. Debugging is done through a browser-based interactive debugger.

#### 1. Add Dependency

Add to requirements.txt:

```text
web-pdb
```

#### 2. Create debug.py:

```python
#!/usr/bin/env python3

import runpy
from pathlib import Path
import web_pdb

WEB_PDB_HOST = "0.0.0.0"
WEB_PDB_PORT = 5555

if __name__ == "__main__":
    print(
        f"Starting with web-pdb debugger "
        f"(available at http://<DEVICE_IP>:{WEB_PDB_PORT})"
    )
    print("The debugger will automatically start if an exception occurs.")

    script_dir = Path(__file__).parent
    main_script = script_dir / "main.py"

    with web_pdb.catch_post_mortem(host=WEB_PDB_HOST, port=WEB_PDB_PORT):
        runpy.run_path(str(main_script), run_name="__main__")
```

> Adjust main.py if your entry script has a different name.

#### 3. Configure Startup

Option A: Using backend-run.sh:

```bash
exec python3.12 /app/debug.py
```

Option B: Using oakapp.toml:

```toml
entrypoint = ["bash","-c","python3.12 -u /app/debug.py"]
```

#### 4. Run and Debug

Start the app:

```bash
oakctl app run .
```

In your web browser, navigate to:

```text
http://<DEVICE_IP>:5555
```

The web debugger will activate automatically on exceptions.

#### Breakpoints Not Hit

 * Ensure path mappings are correct
 * Ensure you are attaching before code execution (or using --wait-for-client)

#### Cannot Connect to Debugger

 * Verify the device IP and port
 * Ensure the firewall allows incoming connections
 * Confirm both devices are on the same network

#### PyCharm Does Not Attach

 * Confirm you are using PyCharm Professional
 * Verify debug server is running before oakctl app run
