Clover とは
Clover は、アークエッジ・スペースの衛星運用システム「Aegs」の一部で、地上局予約のための Web サービスです。 gRPC の API を提供しています。
Clover には、主に以下のような機能があります。
- 衛星の TLE を登録する
- 登録された TLE をもとにした使用地上局におけるパスを算出する
- パス時間における地上局を予約申請する
なお、Clover では予約されたパスを「コンタクト(Contact)」と呼びます。
このドキュメントでは、アークエッジ・スペース等の地上局の利用者を対象に、Clover API の利用方法を説明します。
認証
Clover API の認証は、相互 TLS 認証(mTLS)を使用します。 mTLS で Clover と通信するには、アークエッジ・スペースが発行するクライアント証明書と、対応する秘密鍵が必要になります。 この節では、クライアントの登録申請と、grpcurl を使用した通信例を紹介します。
クライアントの登録を申請する
Clover のクライアント登録を申請するには、アークエッジ・スペースの担当者に使用する衛星について以下の項目をご連絡ください。
- 衛星の名前
- 使用する地上局
- TLS 証明書の Common Name に使用するクライアント名(例:
clover-client.arkedgespace.com
)
連絡を受領後、設定が完了しだいアークエッジ・スペースの担当者より以下をお送りします。
- Clover のテスト環境、本番環境それぞれのホスト名
- TLS 証明書
- 秘密鍵
特に、秘密鍵は関係者以外に漏れることのないよう注意して管理してください。
TLS 証明書には、原則として発行から1年の有効期限が設定されています。 更新する場合は、有効期限が切れる1ヶ月前から1週間前のあいだに更新する旨を担当者にご連絡ください。
発行された認証情報を用いて Clover と通信する
ここでは、grpcurl という gRPC サーバと通信するためのコマンドラインツールを用いて Clover と通信する例を示します。
- ホスト名:
clover.example.com
- TLS 証明書のパス:
./cert.pem
- 秘密鍵のパス:
./secret.pem
とすると、次のコマンドで登録されている衛星のリストを取得するリクエストを送ることができます。
$ grpcurl -cert ./cert.pem -key ./secret.pem clover.example.com:443 aegs.clover.v1.CloverService/ListSatellites
コマンドの結果として、以下のような JSON が標準出力に表示されれば通信は成功です。
{
"satellites": [
{
"id": "42",
"name": "ExampleSat"
}
]
}
grpcurl コマンドの引数について、aegs.clover.v1.CloverService/ListSatellites
は gRPC のサービスとメソッドを指します。
次の「使い方」節でその他の API の使い方を説明します。
使い方
この節では、Clover API を用いて以下の操作を行う方法を説明します。
- TLE の登録
- 予約可能なパスの取得
- コンタクトの作成
Clover API は Protocol Buffers で定義されているため、これをもとに各種プログラミング言語のクライアントコードを生成できます。 しかし、ここでは特定のプログラミング言語を用いるのではなく、前節に引き続き grpcurl を用いて説明します。 grpcurl は、コマンドラインツールとしてシンプルなインタフェースを備えており、特定のプログラミング言語の文法やエコシステムの前提知識なしに利用できるからです。 ユーザインタフェースの作成や自動化など、より高度な形で利用する場合は、使用する言語に応じた gRPC クライアントの開発方法を調べてみてください。 クライアント実装例の節では、Clover UI という参考実装を紹介しています。
使用した grpcurl のバージョンは以下のとおりです。
$ grpcurl -version
grpcurl 1.9.1
また、通信・認証のための情報は、前節と同様に以下を仮定します。
- ホスト名:
clover.example.com
- TLS 証明書のパス:
./cert.pem
- 秘密鍵のパス:
./secret.pem
本説の説明は、Clover API の最低限の使い方を説明することを目的としているため、より詳しいインタフェースについては API リファレンスに相当する Protocol Documentation を参照してください。
TLE の登録
はじめに、衛星の TLE を Clover に登録します。
メソッド RegisterTLE
にパラメータとして、対象の衛星の ID satellite_id
と、TLE の各行を line1
、line2
のフィールドに分けて渡します。
ここで、satellite_id
は仮に 42 とし、TLE には執筆時点の国際宇宙ステーション(ISS)のものを用いることにします。
$ grpcurl -cert ./cert.pem -key ./secret.pem \
-d '{"satellite_id":42,"tle":{"line1":"1 25544U 98067A 24291.20635394 .00024836 00000+0 44173-3 0 9994","line2":"2 25544 51.6384 71.0223 0009135 77.3827 282.8183 15.49966283477470"}}' \
clover.example.com:443 aegs.clover.v1.CloverService/RegisterTLE
登録した最新の TLE はメソッド GetLatestTLE
で確認できます。
$ grpcurl -cert ./cert.pem -key ./secret.pem \
-d '{"satellite_id":42}' \
clover.example.com:443 aegs.clover.v1.CloverService/GetLatestTLE
TLE が登録できていれば、以下のように登録した TLE が返るはずです。
{
"tleRecord": {
"id": "100",
"tle": {
"line1": "1 25544U 98067A 24291.20635394 .00024836 00000+0 44173-3 0 9994",
"line2": "2 25544 51.6384 71.0223 0009135 77.3827 282.8183 15.49966283477470"
},
"registerTime": "2024-10-17T08:15:01.874Z"
}
}
予約可能なパスの取得
TLE を登録すれば、各地上局でのパスを取得できるようになります。
パスの算出には衛星 ID に加えて地上局 ID も必要なため、まず ListAvailableGroundStations
で利用可能な地上局の ID を調べます:
$ grpcurl -cert ./cert.pem -key ./secret.pem \
-d '{"satellite_id":42}' \
clover.example.com:443 aegs.clover.v1.CloverService/ListAvailableGroundStations
{
"groundStations": [
{
"id": "1",
"name": "アークエッジ・スペース局",
"location": {
"latitude": 35.637313872,
"longitude": 139.78881425,
"altitude": 12.34
}
}
]
}
上記で得た地上局 ID を使って、ListPasses
でパスを取得します。
地上局 ID は複数指定することもできます。
$ grpcurl -cert ./cert.pem -key ./secret.pem \
-d '{"satellite_id":42,"ground_station_ids":[1]}' \
clover.example.com:443 aegs.clover.v1.CloverService/ListPasses
{
"passes": [
{
"satellite": {
"id": "42",
"name": "ExampleSat"
},
"groundStation": {
"id": "1",
"name": "牧之原局",
"location": {
"latitude": 34.734444,
"longitude": 138.194444,
"altitude": 92.6129
}
},
"details": {
"aos": "2024-10-17T18:58:01Z",
"los": "2024-10-17T19:08:18Z",
"maxElevation": 28.136736561211773
}
},
// ...
直近 2 週間分のパスを取得することができました。
コンタクトの作成
取得したパスをもとに、地上局の予約「コンタクト」を作成します。
CreateContact
に取得したパスの AOS/LOS を渡してください。
なお、ListPasses
で得られるパスの AOS/LOS 以外を指定した場合はエラーが返ります。
$ grpcurl -cert ./cert.pem -key ./secret.pem \
-d '{"satellite_id":42,"ground_station_id":1,"aos":"2024-10-17T18:58:01Z","los":"2024-10-17T19:08:18Z"}' \
clover.example.com:443 aegs.clover.v1.CloverService/ListPasses
コンタクトの作成に成功すると、作成されたコンタクトの情報が返ります。
{
"contact": {
"id": "200",
"satelliteId": "42",
"groundStationId": "1",
"status": "STATUS_PENDING",
"startTime": "2024-10-17T18:53:01Z",
"endTime": "2024-10-17T19:13:18Z",
"createTime": "2024-10-17T10:15:14.297Z",
"updateTime": "2024-10-17T10:15:14.297Z"
}
}
コンタクトの startTime
と endTime
が引数で渡した AOS/LOS 時刻と異なっていますが、これはコンタクト前後のバッファが加えられたためです。
上記では 5 分となっていますが、この値は場合によって変わる可能性があります。
この startTime
と endTime
をもとに、地上局の排他予約が行われます。
また、コンタクトの予約後に TLE を更新して AOS/LOS 時刻が変化した場合も、コンタクトの開始・終了時刻内で多少の余裕があれば、基本的には問題なく運用できるはずです。
ただし、status
が PENDING
の状態では予約は確定していません。
コンタクト作成時の初期状態は PENDING
で、地上局管理者が承認した場合に SCHEDULED
に遷移し、そこで予約が確定します。
また、SCHEDULED
に遷移したあとでも、当該時間に地上局利用ができない場合は REJECTED
になります。
一度 REJECTED
になったあと、他の状態に遷移することはありません。
コンタクトの状態は GetContact
で定期的に確認してください。
TLE を更新した場合は、最新の AOS/LOS 時刻も確認できます。
$ grpcurl -cert ./cert.pem -key ./secret.pem \
-d '{"contact_id":200}' \
clover.example.com:443 aegs.clover.v1.CloverService/GetContact
{
"contact": {
"id": "78",
"satelliteId": "2",
"groundStationId": "1",
"status": "STATUS_SCHEDULED",
"startTime": "2024-10-17T18:53:01Z",
"endTime": "2024-10-17T19:13:18Z",
"createTime": "2024-10-17T10:15:14.297Z",
"updateTime": "2024-10-17T11:40:01.864Z",
"pass": {
"aos": "2024-10-17T18:58:01Z",
"los": "2024-10-17T19:08:18Z",
"maxElevation": 28.128380846399544
}
}
}
コンタクトの開始時刻以前であれば、CancelContact
でコンタクトをキャンセルできます。
一度キャンセルしたコンタクトはもとに戻せないので、誤ってキャンセルした等の場合は再度コンタクトを作成してください。
$ grpcurl -cert ./cert.pem -key ./secret.pem \
-d '{"contact_id":200}' \
clover.example.com:443 aegs.clover.v1.CloverService/CancelContact
{
"contact": {
"id": "200",
"satelliteId": "42",
"groundStationId": "1",
"status": "STATUS_CANCELED",
"startTime": "2024-10-17T18:53:01Z",
"endTime": "2024-10-17T19:13:18Z",
"createTime": "2024-10-17T10:15:14.297Z",
"updateTime": "2024-10-17T12:21:59.976Z"
}
}
以上が、Clover API の基本的な使い方です。 その他のメソッドや、各パラメータの詳細は Protocol Documentation を参照してください。
クライアント実装例
Clover API のクライアント参考実装として、Clover UI を紹介します。
Clover UI はユーザーインタフェース(UI)を備える TypeScript 製の Web アプリケーションです。 Protocol Buffers と gRPC の TypeScript 実装として Protobuf-ES と Connect-ES を、Web アプリケーションフレームワークとして Remix を採用しています。
ソースコードは、GitHub リポジトリ arkedge/clover-api の client-ui
ディレクトリ以下にあるので、クライアント実装の参考にしてください。
また、Clover UI の linux/amd64
向けコンテナイメージを GitHub Container registry より配布しています。
https://github.com/arkedge/clover-api/pkgs/container/clover-ui
以下、こちらで配布しているコンテナイメージから Clover UI を起動する方法を説明します。
Clover UI の起動
Docker のインストール
コンテナの起動に Docker CLI を用いるため、Docker を利用できる Linux 環境を用意してください。
https://docs.docker.com/engine/install/
Clover UI コンテナの起動
コンテナイメージから Clover UI を起動するには、以下の 3 つの環境変数を起動時に渡す必要があります。
CLOVER_BASE_URL
: HTTP over TLS プロトコルの Clover の URLCLOVER_CLIENT_CERT
: クライアント TLS 証明書CLOVER_KEY
: 証明書に対応する秘密鍵
認証の節で説明されているとおり、これらの値はクライアントの登録時にアークエッジ・スペースの担当者から送付されます。
ここでは、前節までと同様に以下を仮定することにします。
- ホスト名:
clover.example.com
- TLS 証明書のパス:
./cert.pem
- 秘密鍵のパス:
./secret.pem
すると、次のコマンドで GitHub Container registry のコンテナイメージから Clover UI を起動できます。
$ docker run \
-e CLOVER_BASE_URL=https://clover.example.com \
-e CLOVER_CLIENT_CERT="$(cat cert.pem)" \
-e CLOVER_CLIENT_KEY="$(cat key.pem)" \
-p 3000:3000 \
ghcr.io/arkedge/clover-ui:latest
Clover UI はデフォルトで 3000 番ポートを使用するため、オプション -p 3000:3000
でホスト側の 3000 番ポートからコンテナの 3000 番ポートにアクセスできるようにしています。
http://localhost:3000 にアクセスして、以下のような画面が表示されていれば Clover UI の起動は成功です。
使い方の節で説明した機能はすべて実装されているので、ユーザインタフェースを操作しながら Clover の機能を確認してみてください。
Protocol Documentation
Table of Contents
aegs/clover/v1/clover_service.proto
CancelContactRequest
Field | Type | Label | Description |
---|---|---|---|
contact_id | int64 | キャンセルするコンタクトの ID |
CancelContactResponse
Field | Type | Label | Description |
---|---|---|---|
contact | Contact | キャンセルされたコンタクト |
CreateContactRequest
Field | Type | Label | Description |
---|---|---|---|
satellite_id | int64 | コンタクト対象の衛星の ID | |
ground_station_id | int64 | コンタクトで使用する地上局の ID | |
aos | google.protobuf.Timestamp | 作成するコンタクトの AOS 時刻 | |
los | google.protobuf.Timestamp | 作成するコンタクトの LOS 時刻 |
CreateContactResponse
Field | Type | Label | Description |
---|---|---|---|
contact | Contact | 作成されたコンタクト |
GetContactRequest
Field | Type | Label | Description |
---|---|---|---|
contact_id | int64 | 取得するコンタクトの ID |
GetContactResponse
Field | Type | Label | Description |
---|---|---|---|
contact | Contact | 指定された ID に対応するコンタクト |
GetGroundStationRequest
Field | Type | Label | Description |
---|---|---|---|
ground_station_id | int64 | 取得する地上局の ID |
GetGroundStationResponse
Field | Type | Label | Description |
---|---|---|---|
ground_station | GroundStation | 指定された ID に対応する地上局 |
GetLatestTLERequest
Field | Type | Label | Description |
---|---|---|---|
satellite_id | int64 | TLE を取得する衛星の ID |
GetLatestTLEResponse
Field | Type | Label | Description |
---|---|---|---|
tle_record | TLERecord | 指定された衛星の最新の TLE 情報 |
GetSatelliteRequest
Field | Type | Label | Description |
---|---|---|---|
satellite_id | int64 | 取得する衛星の ID |
GetSatelliteResponse
Field | Type | Label | Description |
---|---|---|---|
satellite | Satellite | 指定された ID に対応する衛星 |
ListAvailableGroundStationsRequest
Field | Type | Label | Description |
---|---|---|---|
satellite_id | int64 | 利用可能な地上局を取得する衛星の ID |
ListAvailableGroundStationsResponse
Field | Type | Label | Description |
---|---|---|---|
ground_stations | GroundStation | repeated | 指定された衛星で利用可能な地上局のリスト |
ListPassesRequest
Field | Type | Label | Description |
---|---|---|---|
satellite_id | int64 | パス算出の対象とする衛星の ID | |
ground_station_ids | int64 | repeated | パス算出の対象とする地上局の ID のリスト |
ListPassesResponse
Field | Type | Label | Description |
---|---|---|---|
passes | Pass | repeated | パスのリスト。 リストは AOS 時刻の昇順でソートされている |
ListSatellitesRequest
ListSatellitesResponse
Field | Type | Label | Description |
---|---|---|---|
satellites | Satellite | repeated | クライアントがアクセス可能な衛星のリスト |
ListUpcomingContactsRequest
Field | Type | Label | Description |
---|---|---|---|
satellite_id | int64 | コンタクトのリストを取得する対象の衛星 ID |
ListUpcomingContactsResponse
Field | Type | Label | Description |
---|---|---|---|
contacts | Contact | repeated | 指定された衛星を対象とした現在時刻以降のコンタクトのリスト |
RegisterTLERequest
RegisterTLEResponse
Field | Type | Label | Description |
---|---|---|---|
tle_record | TLERecord | 登録された TLE の情報 |
CloverService
アークエッジ・スペースの地上局予約サービス。
Method Name | Request Type | Response Type | Description |
---|---|---|---|
ListSatellites | ListSatellitesRequest | ListSatellitesResponse | 衛星のリストを取得する。リストにはクライアントがアクセス可能な衛星しか含まれない。 |
GetSatellite | GetSatelliteRequest | GetSatelliteResponse | 指定した衛星を取得する。 |
GetLatestTLE | GetLatestTLERequest | GetLatestTLEResponse | 指定した衛星の最新の TLE を取得する。 |
RegisterTLE | RegisterTLERequest | RegisterTLEResponse | 指定した衛星の TLE を登録する。 TLE が不正な場合は INVALID_ARGUMENT (3) が、最新の TLE と同じものを登録しようとした場合は ALREADY_EXISTS (6) のエラーが返る。 |
ListAvailableGroundStations | ListAvailableGroundStationsRequest | ListAvailableGroundStationsResponse | 指定した衛星について利用可能な地上局のリストを取得する。 |
GetGroundStation | GetGroundStationRequest | GetGroundStationResponse | 指定した地上局を取得する。 |
ListPasses | ListPassesRequest | ListPassesResponse | 指定した衛星、地上局をもとに直近14日間のパスのリストを取得する。 |
ListUpcomingContacts | ListUpcomingContactsRequest | ListUpcomingContactsResponse | 指定した衛星について、end_time が現在時刻以降のコンタクトのリストを取得する。 |
GetContact | GetContactRequest | GetContactResponse | 指定したコンタクトを取得する。 |
CreateContact | CreateContactRequest | CreateContactResponse | 新しいコンタクトを作成する。 指定された AOS/LOS に該当するパスが存在しない場合は INVALID_ARGUMENT (3) が、 すでに同じ衛星、地上局、時間帯でコンタクトが存在する場合は ALREADY_EXISTS (6) のエラーが返る。 |
CancelContact | CancelContactRequest | CancelContactResponse | 指定したコンタクトをキャンセルする。 キャンセル不能な状態の場合は FAILED_PRECONDITION (9) のエラーが返る。 |
aegs/clover/v1/models.proto
Contact
コンタクト。 Clover においては、予約されたパスを表す。
Field | Type | Label | Description |
---|---|---|---|
id | int64 | コンタクトの ID | |
satellite_id | int64 | コンタクト対象の衛星の ID | |
ground_station_id | int64 | コンタクトで使用する地上局の ID | |
status | Contact.Status | コンタクトのステータス | |
start_time | google.protobuf.Timestamp | コンタクトの開始時刻。 AOSに対してバッファを持たせた時刻が設定され、この時刻をもとに予約の排他制御が行われる | |
end_time | google.protobuf.Timestamp | コンタクトの終了時刻。 LOSに対してバッファを持たせた時刻が設定され、この時刻をもとに予約の排他制御が行われる | |
create_time | google.protobuf.Timestamp | コンタクトの作成日時 | |
update_time | google.protobuf.Timestamp | コンタクトの更新日時。 基本的にはステータスの変更時刻を表す | |
pass | PassDetails | リクエスト時の TLE に基づいて計算されたパスの詳細。 GetContact の場合にのみ値が設定される。 コンタクト時刻の前後にパスが見つからなかった場合は値が設定されない |
GroundStation
地上局。
LatLngAlt
緯度・経度・高度からなる位置情報。 パスの計算に使用される。
Pass
衛星パス。
Field | Type | Label | Description |
---|---|---|---|
satellite | Satellite | 当該パスの衛星 | |
ground_station | GroundStation | 当該パスの地上局 | |
details | PassDetails | 当該パスの AOS/LOS と最大仰角 | |
is_available | bool | 当該パスがコンタクトとして予約可能かどうか |
PassDetails
パスの AOS/LOS 時刻と最大仰角といった詳細情報。
Field | Type | Label | Description |
---|---|---|---|
aos | google.protobuf.Timestamp | AOS (Acquisition of Signal) 時刻 | |
los | google.protobuf.Timestamp | LOS (Loss of Signal) 時刻 | |
max_elevation | double | 最大仰角 [deg] |
Satellite
衛星。
TLE
TLE (Two-Line Elements)。
TLERecord
登録された TLE の情報。
Field | Type | Label | Description |
---|---|---|---|
id | int64 | TLE の ID | |
tle | TLE | 登録された TLE | |
register_time | google.protobuf.Timestamp | TLE の登録日時 |
Contact.Status
コンタクトの状態。
Name | Number | Description |
---|---|---|
STATUS_UNSPECIFIED | 0 | ステータスの値が設定されていない場合の値。 この値が設定された場合は異常な状態であるため、アークエッジ・スペースの担当者に連絡すること |
STATUS_PENDING | 1 | 局管理者の確認待ちの状態。 コンタクトを予約した直後の初期状態。 この状態から他の状態に遷移したあと、この状態に戻ることはない |
STATUS_SCHEDULED | 2 | 局管理者に承認され、コンタクトの予約が有効な状態 |
STATUS_REJECTED | 3 | 局管理者に拒否され、コンタクトの予約が無効な状態 他の状態に遷移しない終端状態 |
STATUS_CANCELED | 4 | ユーザがコンタクトの予約をキャンセルした状態。 他の状態に遷移しない終端状態 |
STATUS_RUNNING | 5 | コンタクトが実行中の状態。 この状態になると、キャンセルできなくなる |
STATUS_COMPLETED | 6 | コンタクトが完了した状態。 他の状態に遷移しない終端状態 |
STATUS_FAILED | 7 | コンタクトが何らかの理由で失敗した状態。 他の状態に遷移しない終端状態 |