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 を用いて以下の操作を行う方法を説明します。

  1. TLE の登録
  2. 予約可能なパスの取得
  3. コンタクトの作成

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 の各行を line1line2 のフィールドに分けて渡します。 ここで、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"
  }
}

コンタクトの startTimeendTime が引数で渡した AOS/LOS 時刻と異なっていますが、これはコンタクト前後のバッファが加えられたためです。 上記では 5 分となっていますが、この値は場合によって変わる可能性があります。 この startTimeendTime をもとに、地上局の排他予約が行われます。 また、コンタクトの予約後に TLE を更新して AOS/LOS 時刻が変化した場合も、コンタクトの開始・終了時刻内で多少の余裕があれば、基本的には問題なく運用できるはずです。

ただし、statusPENDING の状態では予約は確定していません。 コンタクト作成時の初期状態は 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-ESConnect-ES を、Web アプリケーションフレームワークとして Remix を採用しています。

ソースコードは、GitHub リポジトリ arkedge/clover-apiclient-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 の URL
  • CLOVER_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 UI のホーム画面

使い方の節で説明した機能はすべて実装されているので、ユーザインタフェースを操作しながら Clover の機能を確認してみてください。

Protocol Documentation

Table of Contents

Top

aegs/clover/v1/clover_service.proto

CancelContactRequest

FieldTypeLabelDescription
contact_idint64キャンセルするコンタクトの ID

CancelContactResponse

FieldTypeLabelDescription
contactContactキャンセルされたコンタクト

CreateContactRequest

FieldTypeLabelDescription
satellite_idint64コンタクト対象の衛星の ID
ground_station_idint64コンタクトで使用する地上局の ID
aosgoogle.protobuf.Timestamp作成するコンタクトの AOS 時刻
losgoogle.protobuf.Timestamp作成するコンタクトの LOS 時刻

CreateContactResponse

FieldTypeLabelDescription
contactContact作成されたコンタクト

GetContactRequest

FieldTypeLabelDescription
contact_idint64取得するコンタクトの ID

GetContactResponse

FieldTypeLabelDescription
contactContact指定された ID に対応するコンタクト

GetGroundStationRequest

FieldTypeLabelDescription
ground_station_idint64取得する地上局の ID

GetGroundStationResponse

FieldTypeLabelDescription
ground_stationGroundStation指定された ID に対応する地上局

GetLatestTLERequest

FieldTypeLabelDescription
satellite_idint64TLE を取得する衛星の ID

GetLatestTLEResponse

FieldTypeLabelDescription
tle_recordTLERecord指定された衛星の最新の TLE 情報

GetSatelliteRequest

FieldTypeLabelDescription
satellite_idint64取得する衛星の ID

GetSatelliteResponse

FieldTypeLabelDescription
satelliteSatellite指定された ID に対応する衛星

ListAvailableGroundStationsRequest

FieldTypeLabelDescription
satellite_idint64利用可能な地上局を取得する衛星の ID

ListAvailableGroundStationsResponse

FieldTypeLabelDescription
ground_stationsGroundStationrepeated指定された衛星で利用可能な地上局のリスト

ListPassesRequest

FieldTypeLabelDescription
satellite_idint64パス算出の対象とする衛星の ID
ground_station_idsint64repeatedパス算出の対象とする地上局の ID のリスト

ListPassesResponse

FieldTypeLabelDescription
passesPassrepeatedパスのリスト。 リストは AOS 時刻の昇順でソートされている

ListSatellitesRequest

ListSatellitesResponse

FieldTypeLabelDescription
satellitesSatelliterepeatedクライアントがアクセス可能な衛星のリスト

ListUpcomingContactsRequest

FieldTypeLabelDescription
satellite_idint64コンタクトのリストを取得する対象の衛星 ID

ListUpcomingContactsResponse

FieldTypeLabelDescription
contactsContactrepeated指定された衛星を対象とした現在時刻以降のコンタクトのリスト

RegisterTLERequest

FieldTypeLabelDescription
satellite_idint64TLE を登録する衛星の ID
tleTLE登録する TLE

RegisterTLEResponse

FieldTypeLabelDescription
tle_recordTLERecord登録された TLE の情報

CloverService

アークエッジ・スペースの地上局予約サービス。

Method NameRequest TypeResponse TypeDescription
ListSatellitesListSatellitesRequestListSatellitesResponse衛星のリストを取得する。リストにはクライアントがアクセス可能な衛星しか含まれない。
GetSatelliteGetSatelliteRequestGetSatelliteResponse指定した衛星を取得する。
GetLatestTLEGetLatestTLERequestGetLatestTLEResponse指定した衛星の最新の TLE を取得する。
RegisterTLERegisterTLERequestRegisterTLEResponse指定した衛星の TLE を登録する。 TLE が不正な場合は INVALID_ARGUMENT (3) が、最新の TLE と同じものを登録しようとした場合は ALREADY_EXISTS (6) のエラーが返る。
ListAvailableGroundStationsListAvailableGroundStationsRequestListAvailableGroundStationsResponse指定した衛星について利用可能な地上局のリストを取得する。
GetGroundStationGetGroundStationRequestGetGroundStationResponse指定した地上局を取得する。
ListPassesListPassesRequestListPassesResponse指定した衛星、地上局をもとに直近14日間のパスのリストを取得する。
ListUpcomingContactsListUpcomingContactsRequestListUpcomingContactsResponse指定した衛星について、end_time が現在時刻以降のコンタクトのリストを取得する。
GetContactGetContactRequestGetContactResponse指定したコンタクトを取得する。
CreateContactCreateContactRequestCreateContactResponse新しいコンタクトを作成する。 指定された AOS/LOS に該当するパスが存在しない場合は INVALID_ARGUMENT (3) が、 すでに同じ衛星、地上局、時間帯でコンタクトが存在する場合は ALREADY_EXISTS (6) のエラーが返る。
CancelContactCancelContactRequestCancelContactResponse指定したコンタクトをキャンセルする。 キャンセル不能な状態の場合は FAILED_PRECONDITION (9) のエラーが返る。

Top

aegs/clover/v1/models.proto

Contact

コンタクト。 Clover においては、予約されたパスを表す。

FieldTypeLabelDescription
idint64コンタクトの ID
satellite_idint64コンタクト対象の衛星の ID
ground_station_idint64コンタクトで使用する地上局の ID
statusContact.Statusコンタクトのステータス
start_timegoogle.protobuf.Timestampコンタクトの開始時刻。 AOSに対してバッファを持たせた時刻が設定され、この時刻をもとに予約の排他制御が行われる
end_timegoogle.protobuf.Timestampコンタクトの終了時刻。 LOSに対してバッファを持たせた時刻が設定され、この時刻をもとに予約の排他制御が行われる
create_timegoogle.protobuf.Timestampコンタクトの作成日時
update_timegoogle.protobuf.Timestampコンタクトの更新日時。 基本的にはステータスの変更時刻を表す
passPassDetailsリクエスト時の TLE に基づいて計算されたパスの詳細。 GetContact の場合にのみ値が設定される。 コンタクト時刻の前後にパスが見つからなかった場合は値が設定されない

GroundStation

地上局。

FieldTypeLabelDescription
idint64地上局の ID
namestring地上局の名前
locationLatLngAlt地上局の位置

LatLngAlt

緯度・経度・高度からなる位置情報。 パスの計算に使用される。

FieldTypeLabelDescription
latitudedouble緯度 [deg]
longitudedouble経度 [deg]
altitudedouble楕円体高 [meter]

Pass

衛星パス。

FieldTypeLabelDescription
satelliteSatellite当該パスの衛星
ground_stationGroundStation当該パスの地上局
detailsPassDetails当該パスの AOS/LOS と最大仰角
is_availablebool当該パスがコンタクトとして予約可能かどうか

PassDetails

パスの AOS/LOS 時刻と最大仰角といった詳細情報。

FieldTypeLabelDescription
aosgoogle.protobuf.TimestampAOS (Acquisition of Signal) 時刻
losgoogle.protobuf.TimestampLOS (Loss of Signal) 時刻
max_elevationdouble最大仰角 [deg]

Satellite

衛星。

FieldTypeLabelDescription
idint64衛星の ID
namestring衛星の名前

TLE

TLE (Two-Line Elements)。

FieldTypeLabelDescription
line1stringTLE の1行目
line2stringTLE の2行目

TLERecord

登録された TLE の情報。

FieldTypeLabelDescription
idint64TLE の ID
tleTLE登録された TLE
register_timegoogle.protobuf.TimestampTLE の登録日時

Contact.Status

コンタクトの状態。

NameNumberDescription
STATUS_UNSPECIFIED0ステータスの値が設定されていない場合の値。 この値が設定された場合は異常な状態であるため、アークエッジ・スペースの担当者に連絡すること
STATUS_PENDING1局管理者の確認待ちの状態。 コンタクトを予約した直後の初期状態。 この状態から他の状態に遷移したあと、この状態に戻ることはない
STATUS_SCHEDULED2局管理者に承認され、コンタクトの予約が有効な状態
STATUS_REJECTED3局管理者に拒否され、コンタクトの予約が無効な状態 他の状態に遷移しない終端状態
STATUS_CANCELED4ユーザがコンタクトの予約をキャンセルした状態。 他の状態に遷移しない終端状態
STATUS_RUNNING5コンタクトが実行中の状態。 この状態になると、キャンセルできなくなる
STATUS_COMPLETED6コンタクトが完了した状態。 他の状態に遷移しない終端状態
STATUS_FAILED7コンタクトが何らかの理由で失敗した状態。 他の状態に遷移しない終端状態

Scalar Value Types

.proto TypeNotesC++JavaPythonGoC#PHPRuby
doubledoubledoublefloatfloat64doublefloatFloat
floatfloatfloatfloatfloat32floatfloatFloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32intintegerBignum or Fixnum (as required)
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/longint64longinteger/stringBignum
uint32Uses variable-length encoding.uint32intint/longuint32uintintegerBignum or Fixnum (as required)
uint64Uses variable-length encoding.uint64longint/longuint64ulonginteger/stringBignum or Fixnum (as required)
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32intintegerBignum or Fixnum (as required)
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/longint64longinteger/stringBignum
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.uint32intintuint32uintintegerBignum or Fixnum (as required)
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.uint64longint/longuint64ulonginteger/stringBignum
sfixed32Always four bytes.int32intintint32intintegerBignum or Fixnum (as required)
sfixed64Always eight bytes.int64longint/longint64longinteger/stringBignum
boolboolbooleanbooleanboolboolbooleanTrueClass/FalseClass
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicodestringstringstringString (UTF-8)
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteByteStringstringString (ASCII-8BIT)