dicom_echo.cli

dicom-echo

Send a C-ECHO message to the given address.

The C-ECHO procedure functions like a ping, serving to test that the peer SCP is accepting associations.

This command will fail if the peer SCP is unreachable or rejects the association request for the given AE titles.

Reference: https://www.dicomstandard.org/standards/view/message-exchange#sect_9.1.5

Usage

$ dicom-echo [OPTIONS] HOST

Arguments

  • HOST [required]: The socket address of the peer SCP: {host}:{port}

    Optionally, the AE title may be included: {AE title}@{host}:{port}

Options

  • -aec, --called, --called-ae-title TEXT: peer AE title of the host SCP [default: ANY-SCP]
  • -aet, --calling, --calling-ae-title TEXT: the AE title of this client [default: ECHOSCU]
  • -id, --id, --message-id INTEGER: the message ID to send [default: 1]
  • -V, --version: display the version of this program
  • --install-completion: Install completion for the current shell.
  • --show-completion: Show completion for the current shell, to copy it or customize the installation.
  • --help: Show this message and exit.
  1""".. include:: ./cli.md"""  # noqa: D415
  2
  3from __future__ import annotations
  4
  5import logging
  6import sys
  7from pathlib import Path
  8
  9import rich
 10import typer
 11
 12import dicom_echo as echo
 13
 14try:
 15    import typing as t
 16
 17    _ = t.Annotated, t.TypeAlias  # type: ignore[attr-defined]
 18except AttributeError:  # pragma: no cover
 19    # note: for supporting Python 3.8
 20    import typing_extensions as t  # type: ignore[no-redef]
 21
 22__all__ = ['main', 'version_callback']
 23
 24logger = logging.getLogger(__name__)
 25
 26app = typer.Typer(context_settings={'help_option_names': ['-h', '--help']}, rich_markup_mode='rich')
 27this = Path(sys.argv[0]).resolve()
 28command = this.name if this.name != '__main__.py' else this.parent.name
 29
 30
 31def version_callback(value: bool | None) -> None:
 32    """Print the version of this program."""
 33    if not value:
 34        return
 35
 36    rich.print(f'[bold bright_black]{command}[/bold bright_black] {echo.__version__}')
 37    raise typer.Exit()
 38
 39
 40AEC: t.TypeAlias = t.Annotated[
 41    str,
 42    typer.Option(
 43        '-aec', '--called', '--called-ae-title', rich_help_panel='DICOM Options', help='peer AE title of the host SCP'
 44    ),
 45]
 46
 47AET: t.TypeAlias = t.Annotated[
 48    str,
 49    typer.Option(
 50        '-aet', '--calling', '--calling-ae-title', rich_help_panel='DICOM Options', help='the AE title of this client'
 51    ),
 52]
 53
 54ID: t.TypeAlias = t.Annotated[
 55    int, typer.Option('-id', '--id', '--message-id', rich_help_panel='DICOM Options', help='the message ID to send')
 56]
 57
 58VER: t.TypeAlias = t.Annotated[
 59    bool,
 60    typer.Option(
 61        '-V',
 62        '--version',
 63        callback=version_callback,
 64        is_eager=True,
 65        help='display the version of this program',
 66    ),
 67]
 68
 69BLUE_HOST_PURPLE_PORT = r'[blue]{host}[/blue]:[purple]{port}[/purple]'
 70GREEN_AET_BLUE_HOST_PURPLE_PORT = r'[green]{AE title}[/green]@' + BLUE_HOST_PURPLE_PORT
 71HOST_OPTION_HELP = f"""The socket address of the peer SCP: {BLUE_HOST_PURPLE_PORT}
 72
 73    Optionally, the AE title may be included: {GREEN_AET_BLUE_HOST_PURPLE_PORT}
 74"""
 75
 76
 77@app.command()
 78def main(
 79    host: t.Annotated[str, typer.Argument(show_default=False, help=HOST_OPTION_HELP)],
 80    called_ae_title: AEC = echo.DEFAULT_CALLED_AE_TITLE,
 81    calling_ae_title: AET = echo.DEFAULT_CALLING_AE_TITLE,
 82    message_id: ID = 1,
 83    version: VER = False,
 84) -> None:
 85    """Send a `C-ECHO` request to the given address.
 86
 87    The `C-ECHO` procedure functions like a `ping`, serving to test that the peer SCP is accepting associations.
 88
 89    This command will fail if the peer SCP is unreachable or rejects the association request for the given AE titles.
 90
 91    Reference: https://www.dicomstandard.org/standards/view/message-exchange#sect_9.1.5
 92    """
 93    if '@' in host and called_ae_title == echo.DEFAULT_CALLED_AE_TITLE:
 94        called_ae_title, _ = host.split('@')
 95
 96    if rc := echo.send(host, called_ae_title, calling_ae_title, message_id):
 97        rich.print(f':warning: [orange]Warning[/orange]: received non-zero status code: {rc}')
 98        raise typer.Exit(rc)
 99
100    rich.print(':white_check_mark: [green]Success[/green]')
101
102
103logger.debug('successfully imported %s', __name__)
@app.command()
def main( host: Annotated[str, <typer.models.ArgumentInfo object>], called_ae_title: Annotated[str, <typer.models.OptionInfo object>] = 'ANY-SCP', calling_ae_title: Annotated[str, <typer.models.OptionInfo object>] = 'ECHOSCU', message_id: Annotated[int, <typer.models.OptionInfo object>] = 1, version: Annotated[bool, <typer.models.OptionInfo object>] = False) -> None:
 78@app.command()
 79def main(
 80    host: t.Annotated[str, typer.Argument(show_default=False, help=HOST_OPTION_HELP)],
 81    called_ae_title: AEC = echo.DEFAULT_CALLED_AE_TITLE,
 82    calling_ae_title: AET = echo.DEFAULT_CALLING_AE_TITLE,
 83    message_id: ID = 1,
 84    version: VER = False,
 85) -> None:
 86    """Send a `C-ECHO` request to the given address.
 87
 88    The `C-ECHO` procedure functions like a `ping`, serving to test that the peer SCP is accepting associations.
 89
 90    This command will fail if the peer SCP is unreachable or rejects the association request for the given AE titles.
 91
 92    Reference: https://www.dicomstandard.org/standards/view/message-exchange#sect_9.1.5
 93    """
 94    if '@' in host and called_ae_title == echo.DEFAULT_CALLED_AE_TITLE:
 95        called_ae_title, _ = host.split('@')
 96
 97    if rc := echo.send(host, called_ae_title, calling_ae_title, message_id):
 98        rich.print(f':warning: [orange]Warning[/orange]: received non-zero status code: {rc}')
 99        raise typer.Exit(rc)
100
101    rich.print(':white_check_mark: [green]Success[/green]')

Send a C-ECHO request to the given address.

The C-ECHO procedure functions like a ping, serving to test that the peer SCP is accepting associations.

This command will fail if the peer SCP is unreachable or rejects the association request for the given AE titles.

Reference: https://www.dicomstandard.org/standards/view/message-exchange#sect_9.1.5

def version_callback(value: bool | None) -> None:
32def version_callback(value: bool | None) -> None:
33    """Print the version of this program."""
34    if not value:
35        return
36
37    rich.print(f'[bold bright_black]{command}[/bold bright_black] {echo.__version__}')
38    raise typer.Exit()

Print the version of this program.