There is alternative method for authentication, which doesn't use Swift Concurrency:
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 entities
www.space-track.org provides several kinds of data: satellite catalog, general perturbations, predicted and historical decay information etc. Each of them can be requested by a specifiec request. The corresponding responses contains a list of some entities.
For example, the response for satellite catalog request contains a list of satellites. The satellite in this terminology is just set of properties: satellite name, number, launch date, launch number in the year etc.
SpaceTrack package provides speciel public structures for each of these entities. Let’s name them entities structures. The received entities list is wrapped by another structure, containing the list itself and the total number of such entities, satisfying the provided filter.
Filtering
To support filters each entity structure provides Key enumiration. Its members represent the properties of coresponding entities. This enumiration supports the following operators: ==, !=, <, >. One should use them to construct some filter. For example:
let filter = Satellite.Key.name == "NOAA 17"
There are also such methods as oneOf and between:
let filter1 = Satellite.Key.noradCatId.oneOf(values: [25544, 23118, 19186])
let filter2 = Satellite.Key.launchYear.between(from: 2007, to: 2022)
One may construct filter with several conditions using && operator:
let filter = Satellite.Key.name == "NOAA" && Satellite.Key.inclination > 98;
Sorting
Key enumirations can be used to sort the requested entities list. For that Key provides asc and desc read-only properties:
let order1 = Satellite.Key.name.asc
let order2 = Satellite.Key.launchYear.desc
You may sort the result by several fields using & operator:
let order = Satellite.Key.name.asc & Satellite.Key.launchYear.desc
Supported requests
Satellite catalog
To get the available list of the satellites one should use satelliteCatalog method.
For example, let’s request first 10 satellites with “NOAA” word in their names,
launched after 2000 year and sorted by name:
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)")
With EventLoopFuture
Use `requestSatelliteCatalog` method if you don't want to deal with Swift Concurrency.
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)")
Satellite catalog debut
To get new records added to the Satellite Catalog use satelliteCatalogDebut method. It operates by the same entity, used for satellite catalog, but the Satellite.debut field contains the date and time when the object was first added into the catalog.
Let’s get the last 10 objects, added into the catalog during the last 7 days:
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)")
With EventLoopFuture
Use `requestSatelliteCatalogDebut` method if you don't want to deal with Swift Concurrency.
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)")
Satellite catalog changes
To get the list of the satellites, changed in the catalog during about the last 60 days, use satelliteCatalogChanges method:
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)")
With EventLoopFuture
Use `requestSatelliteCatalogChanges` method if you don't want to deal with Swift Concurrency.
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)")
General perturbations
To get the keplerian elements of the satellite one should use generalPerturbations method:
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)")
With EventLoopFuture
Use `requestGeneralPerturbations` method if you don't want to deal with Swift Concurrency.
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)")
General perturbations history
To get keplerian elements from historical data use generalPerturbationsHistory method. It operates by GeneralPerturbations entity.
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)")
With EventLoopFuture
Use `requestGeneralPerturbationsHistory` method if you don't want to deal with Swift Concurrency.
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)")
Launch sites
List of launch sites found in satellite catalog records can be received with launchSiteList method.
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)")
With EventLoopFuture
Use `requestLaunchSiteList` method if you don't want to deal with Swift Concurrency.
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 messages
To get Tracking and Impact Prediction (TIP) Messages use TIPMessageList method:
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)")
With EventLoopFuture
Use `requestTIPMessageList` method if you don't want to deal with Swift Concurrency.
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
To request predicted and historical decay information use decay method:
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)")
With EventLoopFuture
Use `requestDecay` method if you don't want to deal with Swift Concurrency.
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)")
Conjunction data message
To request conjunction data messages list use conjunctionDataMessageList method:
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)")
With EventLoopFuture
Use `requestConjunctionDataMessageList` method if you don't want to deal with Swift Concurrency.
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
To request accounting of man-made objects that have been or are in orbit use boxscore method:
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)")
With EventLoopFuture
Use `requestBoxscore` method if you don't want to deal with Swift Concurrency.
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)")
SpaceTrack
The SpaceTrack package allows to interact with www.space-track.org API.
Installation
To add SpaceTrack package into your project one should insert this line into
dependencies
array in your Package.swift file:One should also add something like that:
in your target specification.
Client
The
Client
class is “entry point” of this package. It’s responsible for:It uses AsyncHTTPClient package, based on swift-nio package, and threfore requires
EventLoopGroup
instance.You may ask client to create this group:
or pass already existing one:
Alternatively one can ask client to create event loop group itself:
Authentication
www.space-track.org provides a data to registered users only. It means that you should create an account there if you don’t have it yet.
To receive a data you should authorize the client instance.
With EventLoopFuture
There is alternative method for authentication, which doesn't use Swift Concurrency:
SpaceTrack entities
www.space-track.org provides several kinds of data: satellite catalog, general perturbations, predicted and historical decay information etc. Each of them can be requested by a specifiec request. The corresponding responses contains a list of some entities.
For example, the response for satellite catalog request contains a list of satellites. The satellite in this terminology is just set of properties: satellite name, number, launch date, launch number in the year etc.
SpaceTrack package provides speciel public structures for each of these entities. Let’s name them entities structures. The received entities list is wrapped by another structure, containing the list itself and the total number of such entities, satisfying the provided filter.
Filtering
To support filters each entity structure provides
Key
enumiration. Its members represent the properties of coresponding entities. This enumiration supports the following operators:==
,!=
,<
,>
. One should use them to construct some filter. For example:There are also such methods as
oneOf
andbetween
:One may construct filter with several conditions using
&&
operator:Sorting
Key
enumirations can be used to sort the requested entities list. For thatKey
providesasc
anddesc
read-only properties:You may sort the result by several fields using
&
operator:Supported requests
Satellite catalog
To get the available list of the satellites one should use
satelliteCatalog
method.For example, let’s request first 10 satellites with “NOAA” word in their names, launched after 2000 year and sorted by name:
With EventLoopFuture
Use `requestSatelliteCatalog` method if you don't want to deal with Swift Concurrency.
Satellite catalog debut
To get new records added to the Satellite Catalog use
satelliteCatalogDebut
method. It operates by the same entity, used for satellite catalog, but theSatellite.debut
field contains the date and time when the object was first added into the catalog.Let’s get the last 10 objects, added into the catalog during the last 7 days:
With EventLoopFuture
Use `requestSatelliteCatalogDebut` method if you don't want to deal with Swift Concurrency.
Satellite catalog changes
To get the list of the satellites, changed in the catalog during about the last 60 days, use
satelliteCatalogChanges
method:With EventLoopFuture
Use `requestSatelliteCatalogChanges` method if you don't want to deal with Swift Concurrency.
General perturbations
To get the keplerian elements of the satellite one should use
generalPerturbations
method:With EventLoopFuture
Use `requestGeneralPerturbations` method if you don't want to deal with Swift Concurrency.
General perturbations history
To get keplerian elements from historical data use
generalPerturbationsHistory
method. It operates byGeneralPerturbations
entity.With EventLoopFuture
Use `requestGeneralPerturbationsHistory` method if you don't want to deal with Swift Concurrency.
Launch sites
List of launch sites found in satellite catalog records can be received with
launchSiteList
method.With EventLoopFuture
Use `requestLaunchSiteList` method if you don't want to deal with Swift Concurrency.
TIP messages
To get Tracking and Impact Prediction (TIP) Messages use
TIPMessageList
method:With EventLoopFuture
Use `requestTIPMessageList` method if you don't want to deal with Swift Concurrency.
Decay
To request predicted and historical decay information use
decay
method:With EventLoopFuture
Use `requestDecay` method if you don't want to deal with Swift Concurrency.
Conjunction data message
To request conjunction data messages list use
conjunctionDataMessageList
method:With EventLoopFuture
Use `requestConjunctionDataMessageList` method if you don't want to deal with Swift Concurrency.
Boxscore
To request accounting of man-made objects that have been or are in orbit use
boxscore
method:With EventLoopFuture
Use `requestBoxscore` method if you don't want to deal with Swift Concurrency.