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

Print the version of this program.