

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 사용자 지정 에페메리스를 사용하여 연락처 예약
<a name="reserving-contacts-with-custom-ephemeris"></a>

## 개요
<a name="w2aac28c19b3"></a>

 사용자 지정 에페메리스(TLE, OEM 또는 방위각 고도)를 사용하는 경우 [ReserveContact](https://docs.aws.amazon.com/ground-station/latest/APIReference/API_ReserveContact.html) API를 사용하여 연락처를 예약할 수 있습니다. 이 섹션에서는 고객 응대를 예약하기 위한 두 가지 일반적인 워크플로와 성공적인 고객 응대 예약을 보장하기 위한 중요한 고려 사항에 대해 설명합니다.

 AWS Ground Station 안테나는 여러 고객 간에 공유되는 리소스입니다. 즉, 연락처를 나열할 때 연락처 창을 사용할 수 있더라도 다른 고객이 예약하기 전에 예약할 수 있습니다. 따라서 예약 후 고객 응대가 `SCHEDULED` 상태에 도달하는지 확인하고 고객 응대 상태 변경에 대한 적절한 모니터링을 구현하는 것이 중요합니다.

**중요**  
 방위각 고도 에페메리스의 경우 `ReserveContact` 요청에서 `satelliteArn` 파라미터를 생략할 수 있으며 에페메리스 ID`trackingOverrides`를 제공해야 합니다. TLE 및 OEM 에페메리스의 경우 여전히를 제공해야 합니다`satelliteArn`.

## 고객 응대 예약 워크플로
<a name="w2aac28c19b5"></a>

 사용자 지정 에페메리스로 연락처를 예약하기 위한 두 가지 기본 워크플로가 있습니다.

1. *List-then-reserve 워크플로:* 먼저 [ListContacts](https://docs.aws.amazon.com/ground-station/latest/APIReference/API_ListContacts.html)를 사용하여 사용 가능한 연락처 창을 나열한 다음 특정 창을 선택하고 예약합니다. 이 접근 방식은 선택하기 전에 사용 가능한 모든 기회를 보고 싶을 때 유용합니다.

1. *직접 예약 워크플로:* 사용 가능한 연락처를 먼저 나열하지 않고 특정 기간 동안 연락처를 직접 예약합니다. 이 접근 방식은 원하는 연락 시간을 이미 알고 있거나 미리 결정된 일정으로 작업하는 경우에 유용합니다.

 두 워크플로 모두 유효하며 선택 사항은 운영 요구 사항에 따라 달라집니다. 다음 섹션에서는 각 접근 방식의 예를 제공합니다.

## 워크플로 1: 사용 가능한 연락처를 나열한 다음 예약
<a name="w2aac28c19b7"></a>

 이 워크플로는 먼저 사용 가능한 연락 기간을 쿼리한 다음 특정 기간을 예약합니다. 이는 선택하기 전에 사용 가능한 모든 기회를 보고 싶을 때 유용합니다.

### 예: 방위각 고도 에페메리스를 사용하여 나열 및 예약
<a name="w2aac28c19b7b5"></a>

```
import boto3
from datetime import datetime, timezone
import time

# Create AWS Ground Station client
ground_station_client = boto3.client("groundstation")

# Create azimuth elevation ephemeris
print("Creating azimuth elevation ephemeris...")
ephemeris_response = ground_station_client.create_ephemeris(
    name="AzEl Ephemeris for Contact",
    ephemeris={
        "azEl": {
            "groundStation": "Ohio 1",
            "data": {
                "azElData": {
                    "angleUnit": "DEGREE_ANGLE",
                    "azElSegmentList": [
                        {
                            "referenceEpoch": "2024-03-15T10:00:00Z",
                            "validTimeRange": {
                                "startTime": "2024-03-15T10:00:00Z",
                                "endTime": "2024-03-15T10:15:00Z",
                            },
                            "azElList": [
                                {"dt": 0.0, "az": 45.0, "el": 10.0},
                                {"dt": 180.0, "az": 50.0, "el": 15.0},
                                {"dt": 360.0, "az": 55.0, "el": 20.0},
                                {"dt": 540.0, "az": 60.0, "el": 25.0},
                                {"dt": 720.0, "az": 65.0, "el": 30.0},
                                {"dt": 900.0, "az": 70.0, "el": 35.0},
                            ],
                        }
                    ],
                }
            },
        }
    },
)

ephemeris_id = ephemeris_response["ephemerisId"]
print(f"Created ephemeris: {ephemeris_id}")

# Wait for ephemeris to become ENABLED
while True:
    status = ground_station_client.describe_ephemeris(ephemerisId=ephemeris_id)[
        "status"
    ]
    if status == "ENABLED":
        print("Ephemeris is ENABLED")
        break
    elif status in ["INVALID", "ERROR"]:
        raise RuntimeError(f"Ephemeris failed: {status}")
    time.sleep(5)

# List available contacts
print("Listing available contacts...")
contacts = ground_station_client.list_contacts(
    # Note: satelliteArn is omitted for azimuth elevation ephemeris
    groundStation="Ohio 1",
    missionProfileArn="arn:aws:groundstation:us-east-2:111122223333:mission-profile/example-profile",
    startTime=datetime(2024, 3, 15, 10, 0, 0, tzinfo=timezone.utc),
    endTime=datetime(2024, 3, 15, 10, 15, 0, tzinfo=timezone.utc),
    statusList=["AVAILABLE"],
    ephemeris={"azEl": {"id": ephemeris_id}},
)

if contacts["contactList"]:
    # Reserve the first available contact
    contact = contacts["contactList"][0]
    print(f"Reserving contact from {contact['startTime']} to {contact['endTime']}...")

    reservation = ground_station_client.reserve_contact(
        # Note: satelliteArn is omitted when using azimuth elevation ephemeris
        missionProfileArn="arn:aws:groundstation:us-east-2:111122223333:mission-profile/example-profile",
        groundStation="Ohio 1",
        startTime=contact["startTime"],
        endTime=contact["endTime"],
        trackingOverrides={
            "programTrackSettings": {"azEl": {"ephemerisId": ephemeris_id}}
        },
    )

    print(f"Reserved contact: {reservation['contactId']}")
else:
    print("No available contacts found")
```

### 예: TLE 에페메리스를 사용하여 나열 및 예약
<a name="w2aac28c19b7b7"></a>

```
import boto3
from datetime import datetime, timedelta, timezone
import time

# Create AWS Ground Station client
ground_station_client = boto3.client("groundstation")

satellite_id = "12345678-1234-1234-1234-123456789012"
satellite_arn = f"arn:aws:groundstation::111122223333:satellite/{satellite_id}"

# Create TLE ephemeris
print("Creating TLE ephemeris...")
ephemeris_response = ground_station_client.create_ephemeris(
    name="TLE Ephemeris for Contact",
    satelliteId=satellite_id,
    enabled=True,
    expirationTime=datetime.now(timezone.utc) + timedelta(days=7),
    priority=1,  # Higher priority than default ephemeris
    ephemeris={
        "tle": {
            "tleData": [
                {
                    "tleLine1": "1 25994U 99068A   24075.54719794  .00000075  00000-0  26688-4 0  9997",
                    "tleLine2": "2 25994  98.2007  30.6589 0001234  89.2782  18.9934 14.57114995111906",
                    "validTimeRange": {
                        "startTime": datetime.now(timezone.utc),
                        "endTime": datetime.now(timezone.utc) + timedelta(days=7),
                    },
                }
            ]
        }
    },
)

ephemeris_id = ephemeris_response["ephemerisId"]
print(f"Created ephemeris: {ephemeris_id}")

# Wait for ephemeris to become ENABLED
while True:
    status = ground_station_client.describe_ephemeris(ephemerisId=ephemeris_id)[
        "status"
    ]
    if status == "ENABLED":
        print("Ephemeris is ENABLED")
        break
    elif status in ["INVALID", "ERROR"]:
        raise RuntimeError(f"Ephemeris failed: {status}")
    time.sleep(5)

# List available contacts
print("Listing available contacts...")
start_time = datetime.now(timezone.utc) + timedelta(hours=1)
end_time = start_time + timedelta(days=1)

contacts = ground_station_client.list_contacts(
    satelliteArn=satellite_arn,  # Required for TLE/OEM ephemeris
    groundStation="Hawaii 1",
    missionProfileArn="arn:aws:groundstation:us-west-2:111122223333:mission-profile/example-profile",
    startTime=start_time,
    endTime=end_time,
    statusList=["AVAILABLE"],
)

if contacts["contactList"]:
    # Reserve the first available contact
    contact = contacts["contactList"][0]
    print(f"Reserving contact from {contact['startTime']} to {contact['endTime']}...")

    reservation = ground_station_client.reserve_contact(
        satelliteArn=satellite_arn,  # Required for TLE/OEM ephemeris
        missionProfileArn="arn:aws:groundstation:us-west-2:111122223333:mission-profile/example-profile",
        groundStation="Hawaii 1",
        startTime=contact["startTime"],
        endTime=contact["endTime"],
        # Note: trackingOverrides is optional for TLE/OEM
        # The system will use the highest priority ephemeris automatically
    )

    print(f"Reserved contact: {reservation['contactId']}")
else:
    print("No available contacts found")
```

## 워크플로 2: 직접 연락처 예약
<a name="w2aac28c19b9"></a>

 이 워크플로는 사용 가능한 기간을 먼저 나열하지 않고 연락처를 직접 예약합니다. 이 접근 방식은 원하는 연락 시간을 이미 알고 있거나 자동 일정을 구현하는 경우에 유용합니다.

### 예: 방위각 고도 에페메리스를 사용한 직접 예약
<a name="w2aac28c19b9b5"></a>

```
import boto3
from datetime import datetime, timezone
import time

# Create AWS Ground Station client
ground_station_client = boto3.client("groundstation")

# Define contact window
contact_start = datetime(2024, 3, 20, 14, 0, 0, tzinfo=timezone.utc)
contact_end = datetime(2024, 3, 20, 14, 15, 0, tzinfo=timezone.utc)

# Create azimuth elevation ephemeris for the specific contact time
print("Creating azimuth elevation ephemeris...")
ephemeris_response = ground_station_client.create_ephemeris(
    name="Direct Contact AzEl Ephemeris",
    ephemeris={
        "azEl": {
            "groundStation": "Ohio 1",
            "data": {
                "azElData": {
                    "angleUnit": "DEGREE_ANGLE",
                    "azElSegmentList": [
                        {
                            "referenceEpoch": contact_start.isoformat(),
                            "validTimeRange": {
                                "startTime": contact_start.isoformat(),
                                "endTime": contact_end.isoformat(),
                            },
                            "azElList": [
                                {"dt": 0.0, "az": 45.0, "el": 10.0},
                                {"dt": 180.0, "az": 50.0, "el": 15.0},
                                {"dt": 360.0, "az": 55.0, "el": 20.0},
                                {"dt": 540.0, "az": 60.0, "el": 25.0},
                                {"dt": 720.0, "az": 65.0, "el": 30.0},
                                {"dt": 900.0, "az": 70.0, "el": 35.0},
                            ],
                        }
                    ],
                }
            },
        }
    },
)

ephemeris_id = ephemeris_response["ephemerisId"]
print(f"Created ephemeris: {ephemeris_id}")

# Wait for ephemeris to become ENABLED
while True:
    status = ground_station_client.describe_ephemeris(ephemerisId=ephemeris_id)[
        "status"
    ]
    if status == "ENABLED":
        print("Ephemeris is ENABLED")
        break
    elif status in ["INVALID", "ERROR"]:
        raise RuntimeError(f"Ephemeris failed: {status}")
    time.sleep(5)

# Directly reserve the contact
print(f"Reserving contact from {contact_start} to {contact_end}...")

reservation = ground_station_client.reserve_contact(
    # Note: satelliteArn is omitted for azimuth elevation
    missionProfileArn="arn:aws:groundstation:us-east-2:111122223333:mission-profile/example-profile",
    groundStation="Ohio 1",
    startTime=contact_start,
    endTime=contact_end,
    trackingOverrides={"programTrackSettings": {"azEl": {"ephemerisId": ephemeris_id}}},
)

print(f"Reserved contact: {reservation['contactId']}")
```

### 예: TLE 에페메리스를 사용한 직접 예약
<a name="w2aac28c19b9b7"></a>

```
import boto3
from datetime import datetime, timedelta, timezone
import time

# Create AWS Ground Station client
ground_station_client = boto3.client("groundstation")

satellite_id = "12345678-1234-1234-1234-123456789012"
satellite_arn = f"arn:aws:groundstation::111122223333:satellite/{satellite_id}"

# Define contact window (based on predicted pass)
contact_start = datetime(2024, 3, 21, 10, 30, 0, tzinfo=timezone.utc)
contact_end = datetime(2024, 3, 21, 10, 42, 0, tzinfo=timezone.utc)

# Create TLE ephemeris
print("Creating TLE ephemeris...")
ephemeris_response = ground_station_client.create_ephemeris(
    name="Direct Contact TLE Ephemeris",
    satelliteId=satellite_id,
    enabled=True,
    expirationTime=contact_end + timedelta(days=1),
    priority=1,
    ephemeris={
        "tle": {
            "tleData": [
                {
                    "tleLine1": "1 25994U 99068A   24080.50000000  .00000075  00000-0  26688-4 0  9999",
                    "tleLine2": "2 25994  98.2007  35.6589 0001234  89.2782  18.9934 14.57114995112000",
                    "validTimeRange": {
                        "startTime": (contact_start - timedelta(hours=1)).isoformat(),
                        "endTime": (contact_end + timedelta(hours=1)).isoformat(),
                    },
                }
            ]
        }
    },
)

ephemeris_id = ephemeris_response["ephemerisId"]
print(f"Created ephemeris: {ephemeris_id}")

# Wait for ephemeris to become ENABLED
while True:
    status = ground_station_client.describe_ephemeris(ephemerisId=ephemeris_id)[
        "status"
    ]
    if status == "ENABLED":
        print("Ephemeris is ENABLED")
        break
    elif status in ["INVALID", "ERROR"]:
        raise RuntimeError(f"Ephemeris failed: {status}")
    time.sleep(5)

# Directly reserve the contact
print(f"Reserving contact from {contact_start} to {contact_end}...")

reservation = ground_station_client.reserve_contact(
    satelliteArn=satellite_arn,  # Required for TLE ephemeris
    missionProfileArn="arn:aws:groundstation:us-west-2:111122223333:mission-profile/example-profile",
    groundStation="Hawaii 1",
    startTime=contact_start,
    endTime=contact_end,
    # Note: trackingOverrides is optional for TLE
    # The system will use the highest priority ephemeris automatically
)

print(f"Reserved contact: {reservation['contactId']}")
```

## 고객 응대 상태 변경 모니터링
<a name="w2aac28c19c11"></a>

 고객 응대를 예약한 후에는 상태를 모니터링하여 로 성공적으로 전환`SCHEDULED`되고 모든 문제에 대한 알림을 받는 것이 중요합니다.는 모든 고객 응대 상태 변경에 대해 Amazon EventBridge에 이벤트를 AWS Ground Station 내보냅니다.

 고객 응대 상태는이 수명 주기를 따릅니다.
+ `SCHEDULING` - 고객 응대가 예약을 위해 처리되고 있습니다.
+ `SCHEDULED` - 연락처가 성공적으로 예약되었으며 실행됩니다.
+ `FAILED_TO_SCHEDULE` - 고객 응대를 예약할 수 없음(터미널 상태)

 고객 응대 상태 및 수명 주기에 대한 자세한 내용은 섹션을 참조하세요[고객 응대 수명 주기 이해](contacts.lifecycle.md).

### EventBridge를 사용하여 고객 응대 상태 모니터링 구현
<a name="w2aac28c19c11c11"></a>

 고객 응대 상태 변경을 실시간으로 모니터링하려면 Ground Station 고객 응대 상태가 변경될 때마다 Lambda 함수를 트리거하는 Amazon EventBridge 규칙을 설정할 수 있습니다. 이 접근 방식은 고객 응대 상태를 폴링하는 것보다 더 효율적이고 확장 가능합니다.

#### 구현 단계
<a name="w2aac28c19c11c11b5"></a>

1. 고객 응대 상태 변경 이벤트를 처리하는 Lambda 함수 생성

1. Ground Station 고객 응대 상태 변경 이벤트와 일치하는 EventBridge 규칙 생성

1. Lambda 함수를 규칙의 대상으로 추가

#### Lambda 함수 핸들러 예제
<a name="w2aac28c19c11c11b7"></a>

 고객 응대 상태 변경 이벤트를 처리하는 Lambda 함수의 전체 예는 `AquaSnppJpssTerraDigIF.yml` CloudFormation 템플릿의 `GroundStationCloudWatchEventHandlerLambda` 리소스를 참조하세요. 이 템플릿은 AWS Ground Station 고객 온보딩 Amazon S3 버킷에서 사용할 수 있습니다. 이 템플릿에 액세스하는 방법에 대한 지침은 데이터 흐름 엔드포인트 예제의 [함께 넣기](examples.pbs-data-dataflow-endpoint.md#examples.pbs-dataflow-endpoint.putting-it-together) 섹션을 참조하세요.

#### EventBridge 규칙 구성
<a name="w2aac28c19c11c11b9"></a>

 EventBridge 규칙은 모든 Ground Station 고객 응대 상태 변경과 일치하도록 다음 이벤트 패턴을 사용해야 합니다.

```
{
  "source": ["aws.groundstation"],
  "detail-type": ["Ground Station Contact State Change"]
}
```

 특정 상태(예: 실패)만 필터링하려면 세부 정보 필터를 추가할 수 있습니다.

```
{
  "source": ["aws.groundstation"],
  "detail-type": ["Ground Station Contact State Change"],
  "detail": {
    "contactStatus": [
      "FAILED_TO_SCHEDULE",
      "FAILED",
      "AWS_FAILED",
      "AWS_CANCELLED"
    ]
  }
}
```

 Lambda 대상으로 EventBridge 규칙을 생성하는 방법에 대한 자세한 지침은 Amazon EventBridge 사용 설명서의 [이벤트에 대응하는 규칙 생성을 참조하세요](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule.html).

### 자동화를 위한 EventBridge 규칙 설정
<a name="w2aac28c19c11c13"></a>

 EventBridge 규칙을 생성하여 고객 응대 상태 변경에 자동으로 응답할 수 있습니다. 예제: 
+ 고객 응대 예약 실패 시 알림 전송
+ Lambda 함수를 트리거하여 고객 응대가 들어올 때 리소스 준비 `PREPASS`
+ 감사 목적으로 고객 응대 완료 기록

 AWS Ground Station 이벤트에 대한 EventBridge 규칙 설정에 대한 자세한 내용은 섹션을 참조하세요[이벤트 AWS Ground Station 로 자동화](monitoring.automating-events.md).

## 모범 사례 및 고려 사항
<a name="w2aac28c19c13"></a>

### 일정 충돌 처리
<a name="w2aac28c19c13b3"></a>

 AWS Ground Station 안테나는 공유 리소스이므로에서 사용할 `ListContacts` 수 있는 고객 응대 기간은 다른 고객이 예약한 후 예약할 수 있습니다. 이를 처리하려면: 

1. 예약 후 항상 고객 응대 상태 확인

1. 대체 기간을 사용하여 재시도 로직 구현

1. 가능하면 미리 연락처를 예약하는 것이 좋습니다.

1. EventBridge 이벤트를 사용하여 `FAILED_TO_SCHEDULE` 상태 모니터링

### 에페메리스 검증 타이밍
<a name="w2aac28c19c13b5"></a>

 에페메리스를 사용하여 연락처를 예약하려면 에페메리스가 `ENABLED` 상태여야 합니다. 검증 프로세스는 일반적으로 에페메리스 유형 및 크기에 따라 몇 초에서 몇 분 정도 걸립니다. 고객 응대를 예약하기 전에 항상 에페메리스 상태를 확인합니다.

### 고객 응대 타이밍 고려 사항
<a name="w2aac28c19c13b7"></a>

 사용자 지정 에페메리스를 사용하는 경우: 
+ 에페메리스가 전체 연락 기간을 포함하는지 확인
+ 방위각 고도 에페메리스의 경우 접촉 전체에서 각도가 안테나를 [사이트 마스크](https://docs.aws.amazon.com/ground-station/latest/ug/locations.site-masks.html) 위에 유지하는지 확인합니다.
+ 향후 연락을 예약할 때 에페메리스 만료 시간 고려

### 에페메리스 유형별 API 차이
<a name="w2aac28c19c13b9"></a>

 `ReserveContact` API는 에페메리스 유형에 따라 다르게 동작합니다.


| 에페메리스 유형 | satelliteArn 필수 | trackingOverrides 필요 | 
| --- | --- | --- | 
| TLE | 예 | 아니요(선택 사항) | 
| OEM | 예 | 아니요(선택 사항) | 
| 방위각 상승 | 아니요(선택 사항) | 예 | 