# device_handlers

Python API: `modelconverter.utils.device_handlers`

Handlers for driving a physical device.

Benchmarking and analysis of an RVC4 model happen on a real device rather than in the conversion container: the model and its
inputs are pushed to the device, a command is run there and the results are pulled back. This module wraps the two transports used
for that -- ADB and SSH -- behind one interface, so the callers do not have to care which one the device is reachable over.

## Classes

### AdbHandler

Device handler implementation based on Android Debug Bridge.

#### Methods

##### init

```python
def __init__(device_id: str | None = None, silent: bool = True):
```

Initialize an ADB handler for the target device.

If no device ID is provided, the first connected device is selected.

Parameters

 * `device_id` (`str | None`): Optional ADB device identifier.
 * `silent` (`bool`): If `True`, suppress command logging.

Raises

 * `RuntimeError`: If device enumeration fails or no connected device is available.
 * `ValueError`: If the specified device is not connected.
 * `FileNotFoundError`: If the `adb` executable is not available.

##### pull

```python
def pull(src: PathType, dst: PathType, *, check: bool = True) -> tuple[int, str, str]:
```

Copy a file or directory from the device to the local machine.

Parameters

 * `src` (`PathType`): Source path on the device.
 * `dst` (`PathType`): Destination path on the local machine.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

##### push

```python
def push(src: PathType, dst: PathType, *, check: bool = True) -> tuple[int, str, str]:
```

Copy a file or directory from the local machine to the device.

Parameters

 * `src` (`PathType`): Source path on the local machine.
 * `dst` (`PathType`): Destination path on the device.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

##### run

```python
def run(*args, check: bool = True, **kwargs) -> tuple[int, str, str]:
```

Run a subprocess command and return its result.

The command arguments are converted to strings before execution. Output is always captured and decoded using a best-effort
strategy.

Parameters

 * `*args`: Positional command arguments passed to `subprocess.run`.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.
 * `silent`: If `True`, suppress command logging.
 * `**kwargs`: Additional keyword arguments forwarded to `subprocess.run`.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

Raises

 * `subprocess.CalledProcessError`: If `check` is enabled and the subprocess exits with a non-zero status.

##### shell

```python
def shell(cmd: str, *, check: bool = True, silent: bool | None = None) -> tuple[int, str, str]:
```

Execute a shell command on the target device.

Parameters

 * `cmd` (`str`): Shell command to execute on the device.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.
 * `silent` (`bool | None`): If `True`, suppress command logging. If `None`, use the default logging behavior of the handler.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

### DeviceHandler

Abstract interface for communicating with a device.

Implementations provide shell access and file transfer operations over a concrete transport such as SSH or ADB.

#### Methods

##### init

```python
def __init__(silent: bool = True):
```

Initialize the device handler.

Parameters

 * `silent` (`bool`): If `True`, suppress command logging by default.

##### pull

```python
def pull(src: PathType, dst: PathType, *, check: bool = True) -> tuple[int, str, str]:
```

Copy a file or directory from the device to the local machine.

Parameters

 * `src` (`PathType`): Source path on the device.
 * `dst` (`PathType`): Destination path on the local machine.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

##### push

```python
def push(src: PathType, dst: PathType, *, check: bool = True) -> tuple[int, str, str]:
```

Copy a file or directory from the local machine to the device.

Parameters

 * `src` (`PathType`): Source path on the local machine.
 * `dst` (`PathType`): Destination path on the device.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

##### run

```python
def run(*args, check: bool = False, silent: bool = True, **kwargs) -> tuple[int, str, str]:
```

Run a subprocess command and return its result.

The command arguments are converted to strings before execution. Output is always captured and decoded using a best-effort
strategy.

Parameters

 * `*args`: Positional command arguments passed to `subprocess.run`.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.
 * `silent` (`bool`): If `True`, suppress command logging.
 * `**kwargs`: Additional keyword arguments forwarded to `subprocess.run`.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

Raises

 * `subprocess.CalledProcessError`: If `check` is enabled and the subprocess exits with a non-zero status.

##### shell

```python
def shell(cmd: str, *, check: bool = True, silent: bool | None = None) -> tuple[int, str, str]:
```

Execute a shell command on the target device.

Parameters

 * `cmd` (`str`): Shell command to execute on the device.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.
 * `silent` (`bool | None`): If `True`, suppress command logging. If `None`, use the default logging behavior of the handler.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

### SSHHandler

Device handler implementation based on SSH and SCP.

#### Methods

##### init

```python
def __init__(ip: str, silent: bool = True):
```

Initialize an SSH handler for the target device.

Parameters

 * `ip` (`str`): Target device IP address.
 * `silent` (`bool`): If `True`, suppress command logging.

##### pull

```python
def pull(src: PathType, dst: PathType, *, check: bool = True) -> tuple[int, str, str]:
```

Copy a file or directory from the device to the local machine.

Parameters

 * `src` (`PathType`): Source path on the device.
 * `dst` (`PathType`): Destination path on the local machine.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

##### push

```python
def push(src: PathType, dst: PathType, *, check: bool = True) -> tuple[int, str, str]:
```

Copy a file or directory from the local machine to the device.

Parameters

 * `src` (`PathType`): Source path on the local machine.
 * `dst` (`PathType`): Destination path on the device.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

##### shell

```python
def shell(cmd: str, *, check: bool = True, silent: bool | None = None) -> tuple[int, str, str]:
```

Execute a shell command on the target device.

Parameters

 * `cmd` (`str`): Shell command to execute on the device.
 * `check` (`bool`): If `True`, propagate subprocess failures as exceptions.
 * `silent` (`bool | None`): If `True`, suppress command logging. If `None`, use the default logging behavior of the handler.

Returns

 * `tuple[int, str, str]`: A tuple containing return code, stdout, and stderr.

## Functions

### create_handler

```python
def create_handler(device_ip: str | None, device_adb_id: str | None) -> DeviceHandler:
```

Create a handler for the device to run on.

ADB is preferred; an
[SSHHandler](https://docs.luxonis.com/software-v3/ai-inference/conversion/rvc-conversion/offline/modelconverter/modelconverter-api-reference/utils/device_handlers.md)
is only built if
[AdbHandler](https://docs.luxonis.com/software-v3/ai-inference/conversion/rvc-conversion/offline/modelconverter/modelconverter-api-reference/utils/device_handlers.md)
cannot be created and an IP address is available to fall back to.

Parameters

 * `device_ip` (`str | None`): IP address of the device, used for the SSH fallback. `None` if no fallback is available.
 * `device_adb_id` (`str | None`): ADB identifier of the device, or `None` to use the first connected one.

Returns

 * `DeviceHandler`: A handler for the device.

Raises

 * `RuntimeError`: If no ADB device is connected, or ADB cannot be queried, and no IP address was given.
 * `ValueError`: If the requested ADB device is not connected and no IP address was given.
 * `FileNotFoundError`: If the `adb` executable is not available and no IP address was given.
