SpaceTrack

SpaceTrack 包允许与 www.space-track.org API 进行交互。

安装

要将 SpaceTrack 包添加到您的项目,应将此行插入到 Package.swift 文件中的 dependencies 数组中

.package(url: "https://github.com/fundaev/spacetrack.git", from: "1.2.0"),

还应添加类似这样的内容

.target(
    name: "MyProject",
    dependencies: [
        .product(name: "SpaceTrack", package: "spacetrack")
    ]
),

在您的目标规范中。

客户端

Client 类是此包的“入口点”。它负责

  1. 身份验证;
  2. www.space-track.org 接收数据。

它使用基于 swift-nio 包的 AsyncHTTPClient 包,因此需要 EventLoopGroup 实例。

您可以要求客户端创建此组

import Foundation
import NIOCore
import SpaceTrack 
...
let client = Client(eventLoopGroupProvider: .createNew)
...

或传递已存在的组

import Foundation
import NIOCore
import SpaceTrack 
...
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
let client = Client(eventLoopGroupProvider: .shared(eventLoopGroup))
...

或者,可以要求客户端自己创建事件循环组

身份验证

www.space-track.org 仅向注册用户提供数据。这意味着如果您还没有帐户,则应该在那里创建一个帐户。

要接收数据,您应该授权客户端实例。

let authResult = try await client.auth(
    username: "your.username@test.info",
    password: "your.password"
)
if (authResult != Result.Success) {
    // handle failed authentication
}

使用 EventLoopFuture

还有另一种身份验证方法,它不使用 Swift 并发

let authFuture = client.authorize(
    username: "your.username@test.info",
    password: "your.password"
)
let result = try authFuture.wait()
if (result != Result.Success) {
    // handle failed authentication
}

SpaceTrack 实体

www.space-track.org 提供几种数据:卫星目录、一般摄动、预测的和历史的衰减信息等。它们中的每一个都可以通过指定的请求来请求。相应的响应包含一些实体的列表。

例如,卫星目录请求的响应包含卫星列表。在此术语中,卫星只是一组属性:卫星名称、编号、发射日期、年度发射编号等。

SpaceTrack 包为每个这些实体提供了特殊的公共结构。 我们将它们命名为实体结构。接收到的实体列表被另一个结构包装,该结构包含列表本身以及满足所提供筛选器的此类实体的总数。

筛选

为了支持过滤器,每个实体结构都提供了 Key 枚举。 它的成员代表相应实体的属性。 该枚举支持以下运算符:==!=<>。 应该使用它们来构建一些过滤器。 例如

let filter = Satellite.Key.name == "NOAA 17"

还有 oneOfbetween 等方法

let filter1 = Satellite.Key.noradCatId.oneOf(values: [25544, 23118, 19186])
let filter2 = Satellite.Key.launchYear.between(from: 2007, to: 2022)

可以使用 && 运算符构造具有多个条件的过滤器

let filter = Satellite.Key.name == "NOAA" && Satellite.Key.inclination > 98;

排序

Key 枚举可用于对请求的实体列表进行排序。 为此,Key 提供 ascdesc 只读属性

let order1 = Satellite.Key.name.asc
let order2 = Satellite.Key.launchYear.desc

您可以使用 & 运算符按多个字段对结果进行排序

let order = Satellite.Key.name.asc & Satellite.Key.launchYear.desc

支持的请求

卫星目录

要获取可用卫星列表,应使用 satelliteCatalog 方法。

例如,让我们请求名称中带有“NOAA”字样,在 2000 年之后发射并按名称排序的前 10 颗卫星

let response = try await client.satelliteCatalog(
    where: Satellite.Key.name == "~~NOAA~~" && Satellite.Key.launchYear > 2000,
    order: Satellite.Key.name.asc,
    limit: 10,
    offset: 100
)

for satellite in response.data {
    print("\(satellite.name)")
}
print("-------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestSatelliteCatalog` 方法。

let future = client.requestSatelliteCatalog(
    where: Satellite.Key.name == "~~NOAA~~" && Satellite.Key.launchYear > 2000,
    order: Satellite.Key.name.asc,
    limit: 10,
    offset: 100
)
let response = try future.wait()
for satellite in response.data {
    print("\(satellite.name)")
}
print("-------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

卫星目录首次发布

要获取添加到卫星目录的新记录,请使用 satelliteCatalogDebut 方法。 它使用与卫星目录相同的实体,但 Satellite.debut 字段包含对象首次添加到目录的日期和时间。

让我们获取过去 7 天内添加到目录中的最后 10 个对象

let response = try await client.satelliteCatalogDebut(
    where: Satellite.Key.debut > Date(timeIntervalSinceNow: -7 * 86400),
    order: Satellite.Key.debut.desc & Satellite.Key.name.asc,
    limit: 10
)

for satellite in response.data {
    print("\(satellite.name)")
}
print("-------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestSatelliteCatalogDebut` 方法。

let future = client.requestSatelliteCatalogDebut(
    where: Satellite.Key.debut > Date(timeIntervalSinceNow: -7 * 86400),
    order: Satellite.Key.debut.desc & Satellite.Key.name.asc,
    limit: 10
)
let response = try future.wait()
for satellite in response.data {
    print("\(satellite.name)")
}
print("-------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

卫星目录更改

要获取过去大约 60 天内在目录中更改的卫星列表,请使用 satelliteCatalogChanges 方法

let satcatChanges = try await client.satelliteCatalogChanges(
    where: SatelliteChange.Key.previousDecay == nil &&
           SatelliteChange.Key.currentDecay != nil,
    order: SatelliteChange.Key.changeMade.desc,
    limit: 10
)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:SS"
for change in satcatChanges.data {
    let decay = dateFormatter.string(from: change.currentDecay!)
    print("\(change.currentName): decay: NULL -> \(decay)")
}
print("-------------------------------------------------------------------")
print("\(satcatChanges.data.count) item(s) from \(satcatChanges.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestSatelliteCatalogChanges` 方法。

let future = client.requestSatelliteCatalogChanges(
    where: SatelliteChange.Key.previousDecay == nil &&
           SatelliteChange.Key.currentDecay != nil,
    order: SatelliteChange.Key.changeMade.desc,
    limit: 10
)
let response = try future.wait()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:SS"
for change in satcatChanges.data {
    let decay = dateFormatter.string(from: change.currentDecay!)
    print("\(change.currentName): decay: NULL -> \(decay)")
}
print("-------------------------------------------------------------------")
print("\(satcatChanges.data.count) item(s) from \(satcatChanges.count)")

一般摄动

要获取卫星的开普勒元素,应使用 generalPerturbations 方法

let response = try await client.generalPerturbations(
    where: GeneralPerturbations.Key.noradCatId == 25544,
    order: GeneralPerturbations.Key.noradCatId.asc,
    limit: 10,
    offset: 0
)
for gp in response.data {
    print("\(gp.semimajorAxis)")
}
print("-------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestGeneralPerturbations` 方法。

let future = client.requestGeneralPerturbations(
    where: GeneralPerturbations.Key.noradCatId == 25544,
    order: GeneralPerturbations.Key.noradCatId.asc,
    limit: 10,
    offset: 0
)
let response = try future.wait()
for gp in response.data {
    print("\(gp.semimajorAxis)")
}
print("-------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

一般摄动历史

要从历史数据中获取开普勒元素,请使用 generalPerturbationsHistory 方法。 它由 GeneralPerturbations 实体操作。

let response = try await client.generalPerturbationsHistory(
    where: GeneralPerturbations.Key.noradCatId == 25544,
    order: GeneralPerturbations.Key.noradCatId.asc,
    limit: 10
)
for gp in response.data {
    print(gp.tleLine1 ?? "-")
    print(gp.tleLine2 ?? "-")
}
print("-------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestGeneralPerturbationsHistory` 方法。

let future = client.requestGeneralPerturbationsHistory(
    where: GeneralPerturbations.Key.noradCatId == 25544,
    order: GeneralPerturbations.Key.noradCatId.asc,
    limit: 10
)
let response = try future.wait()
for gp in response.data {
    print(gp.tleLine1 ?? "-")
    print(gp.tleLine2 ?? "-")
}
print("-------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

发射场

可以在卫星目录记录中找到的发射场列表可以使用 launchSiteList 方法接收。

let response = try await client.launchSiteList(
    where: LaunchSite.Key.launchSite == "~~Center~~",
    order: LaunchSite.Key.siteCode.asc,
    limit: 10
)
for site in response.data {
    print("\(site.siteCode) \(site.launchSite)")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestLaunchSiteList` 方法。

let future = client.requestLaunchSiteList(
    where: LaunchSite.Key.launchSite == "~~Center~~",
    order: LaunchSite.Key.siteCode.asc,
    limit: 10
)
let response = future.wait()
for site in response.data {
    print("\(site.siteCode) \(site.launchSite)")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

TIP 消息

要获取跟踪和影响预测 (TIP) 消息,请使用 TIPMessageList 方法

let response = try await client.TIPMessageList(
    where: TIPMessage.Key.noradCatId > 10000,
    order: TIPMessage.Key.objectNumber.asc,
    limit: 10,
    offset: 3
)
for tip in response.data {
    print("\(tip.objectNumber ?? 0) \(tip.noradCatId ?? 0)")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestTIPMessageList` 方法。

let future = client.requestTIPMessageList(
    where: TIPMessage.Key.noradCatId > 10000,
    order: TIPMessage.Key.objectNumber.asc,
    limit: 10,
    offset: 3
)
let response = future.wait()
for tip in response.data {
    print("\(tip.objectNumber ?? 0) \(tip.noradCatId ?? 0)")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

衰减

要请求预测的和历史的衰减信息,请使用 decay 方法

let response = try await client.decay(
    where: Decay.Key.objectName == "~~NOAA~~",
    order: Decay.Key.objectId.asc,
    limit: 10,
    offset: 100
)
for decay in response.data {
    print("\(decay.objectId) \(tip.objectName)")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestDecay` 方法。

let future = client.requestDecay(
    where: Decay.Key.objectName == "~~NOAA~~",
    order: Decay.Key.objectId.asc,
    limit: 10,
    offset: 100
)
let response = future.wait()
for decay in response.data {
    print("\(decay.objectId) \(tip.objectName)")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

会合数据消息

要请求会合数据消息列表,请使用 conjunctionDataMessageList 方法

let response = try await client.conjunctionDataMessageList(
    where: ConjunctionDataMessage.Key.sat1Name == "~~NOAA~~",
    order: ConjunctionDataMessage.Key.sat1Name.asc,
    limit: 10,
    offset: 3
)
for cdm in response.data {
    print("\(cdm.sat1Id ?? 0) \(cdm.sat1Name ?? "-") \(cdm.sat2Id ?? 0) \(cdm.sat2Name ?? "-")")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestConjunctionDataMessageList` 方法。

let future = client.requestConjunctionDataMessageList(
    where: ConjunctionDataMessage.Key.sat1Name == "~~NOAA~~",
    order: ConjunctionDataMessage.Key.sat1Name.asc,
    limit: 10,
    offset: 3
)
let response = future.wait()
for cdm in response.data {
    print("\(cdm.sat1Id ?? 0) \(cdm.sat1Name ?? "-") \(cdm.sat2Id ?? 0) \(cdm.sat2Name ?? "-")")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

成绩表

要请求对已在或正在轨道上的的人造物体的核算,请使用 boxscore 方法

let response = try await client.boxscore(
    where: Boxscore.Key.orbitalPayloadCount > 0,
    order: Boxscore.Key.orbitalPayloadCount.desc,
    limit: 10,
    offset: 3
)
for boxscore in response.data {
    print("\(boxscore.country) \(boxscore.orbitalPayloadCount ?? 0)")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")

使用 EventLoopFuture

如果您不想处理 Swift 并发,请使用 `requestBoxscore` 方法。

let future = client.requestBoxscore(
    where: Boxscore.Key.orbitalPayloadCount > 0,
    order: Boxscore.Key.orbitalPayloadCount.desc,
    limit: 10,
    offset: 3
)
let response = future.wait()
for boxscore in response.data {
    print("\(boxscore.country) \(boxscore.orbitalPayloadCount ?? 0)")
}
print("-------------------------------------------------------------------")
print("\(response.data.count) item(s) from \(response.count)")