Grounds
This application demonstrates a network of ground stations given geospatial locations, minimum elevation angle constraints, and operational status.
The application contains a GroundNetwork (Observer) object class to track the state of each constituent ground station, as well as the LinkStartObserver and LinkEndObserver object classes that monitor Acquisition of Signal (AOS) and Loss of Signal (LOS) events, respectively.
GroundNetwork
- class GroundNetwork(app, grounds)
Bases:
Observable,ObserverThe GroundNetwork object class inherits properties from the Observer object class in the NOS-T tools library.
- app
An application containing a test-run namespace, a name and description for the app, client credentials, and simulation timing instructions.
- Type:
ManagedApplication
- grounds
DataFrame of ground station information including groundId (int), latitude-longitude location (
GeographicPosition), min_elevation (float) angle constraints, and operational status (bool).- Type:
DataFrame
- GroundNetwork.on_change(source, property_name, old_value, new_value)
Standard on_change callback function format inherited from Observer object class.
In this instance, the callback function checks when the PROPERTY_MODE switches to EXECUTING to send a
GroundLocationmessage to the PREFIX/ground/location topic.
- GroundNetwork.on_ready(ch, method, properties, body)
Callback function for subscribed messages on the PREFIX/constellation/ready topic.
For each message received, appends a satellite and its specs to internal lists.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used).
message (
message) – Contains topic the client subscribed to and payload message content as attributes.
- GroundNetwork.all_ready(ch, method, properties, body)
Callback function for subscribed messages on the PREFIX/constellation/allReady topic.
This is a simple trigger that the list of constituent satellites have been finalized and appended to lists.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used).
message (
message) – Contains topic the client subscribed to and payload message content as attributes.
- GroundNetwork.on_commRange(ch, method, properties, body)
Callback function triggered by every
SatelliteStatemessage received on the PREFIX/constellation/location topic.Checks for changes in switch states and records timestamps of state transitions.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used).
message (
message) – Contains topic the client subscribed to and payload message content as attributes.
- GroundNetwork.on_outage(ch, method, properties, body)
Callback function triggered by every
OutageReportmessage received on the PREFIX/outages/report topic.Appends a new outage dictionary to a list of outage dictionaries. Used to indicate which ground station has become inoperable and the expected outage duration.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used).
message (
message) – Contains topic the client subscribed to and payload message content as attributes.
- GroundNetwork.on_restore(ch, method, properties, body)
Callback function triggered by every
OutageRestoremessage received on the PREFIX/outages/restore topic.Notifies observers of restored service at a previously inoperable ground station.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used).
message (
message) – Contains topic the client subscribed to and payload message content as attributes.
- GroundNetwork.fixedCost(ch, method, properties, body)
Callback function triggered by every
LinkChargemessage sent to the PREFIX/constellation/linkCharge topic.Messages only apply to satellites operating under fixed contracts. These messages are intended to create a continuous cost curve for the visualizations.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used).
message (
message) – Contains topic the client subscribed to and payload message content as attributes.
Event Observers
- class LinkStartObserver(app)
Bases:
ObserverThis object class inherits properties from the Observer object class from the observer template in the NOS-T tools library.
- Parameters:
app (
ManagedApplication) – An application containing a test-run namespace, a name and description for the app, client credentials, and simulation timing instructions.
- LinkStartObserver.on_change(source, property_name, old_value, new_value)
Standard on_change callback function format inherited from Observer object class in NOS-T tools library.
In this instance, the callback function checks for notification of the PROPERTY_IN_RANGE and publishes
LinkStartmessage to PREFIX/ground/linkStart topic.
- class LinkEndObserver(app)
Bases:
ObserverThis object class inherits properties from the Observer object class from the observer template in the NOS-T tools library.
- Parameters:
app (
ManagedApplication) – An application containing a test-run namespace, a name and description for the app, client credentials, and simulation timing instructions.
- LinkEndObserver.on_change(source, property_name, old_value, new_value)
Standard on_change callback function format inherited from Observer object class in NOS-T tools library
In this instance, the callback function checks for notification of the PROPERTY_OUT_OF_RANGE and publishes
LinkChargemessage to PREFIX/ground/linkCharge topic.
Schema
Schema are implemented using the pydantic library. The following schema define consistent message structures between this application and other observer applications:
- pydantic settings SatelliteReady
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized initializing message for each satellite in the constellation includes:
Show JSON schema
{ "title": "SatelliteReady", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized initializing message for each satellite in the constellation includes: ", "type": "object", "properties": { "id": { "description": "Unique satellite identifier", "title": "Id", "type": "integer" }, "name": { "description": "Satellite name for labeling", "title": "Name", "type": "string" }, "ssr_capacity": { "description": "Capacity of onboard Solid State Recorder in Gigabytes", "title": "Ssr Capacity", "type": "number" } }, "required": [ "id", "name", "ssr_capacity" ] }
- Fields:
id (int)name (str)ssr_capacity (float)
- field id: int [Required]
Unique satellite identifier
- field name: str [Required]
Satellite name for labeling
- field ssr_capacity: float [Required]
Capacity of onboard Solid State Recorder in Gigabytes
- pydantic settings SatelliteState
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized satellite status message includes:
Show JSON schema
{ "title": "SatelliteState", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized satellite status message includes: \n ", "type": "object", "properties": { "id": { "description": "Unique satellite identifier", "title": "Id", "type": "integer" }, "name": { "description": "Satellite name for labeling", "title": "Name", "type": "string" }, "latitude": { "description": "Latitude (deg) of satellite subpoint location.", "maximum": 90, "minimum": -90, "title": "Latitude", "type": "number" }, "longitude": { "description": "Longitude (deg) of satellite subpoint location.", "maximum": 180, "minimum": -180, "title": "Longitude", "type": "number" }, "altitude": { "description": "Altitude (meters) of satellite above sea level", "title": "Altitude", "type": "number" }, "capacity_used": { "description": "GB of solid state recorder capacity used", "title": "Capacity Used", "type": "number" }, "commRange": { "default": false, "description": "Boolean for if satellite is in ground stations view", "title": "Commrange", "type": "boolean" }, "groundId": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "description": "Ground Station id in view (None if not in view)", "title": "Groundid" }, "totalLinkCount": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "description": "Running count of downlink opportunity per satellite", "title": "Totallinkcount" }, "cumulativeCostBySat": { "description": "Cumulative cost of downlinks and/or fixed cost contracts per satellite", "title": "Cumulativecostbysat", "type": "number" }, "time": { "description": "Time in satellite reference frame", "format": "date-time", "title": "Time", "type": "string" } }, "required": [ "id", "name", "latitude", "longitude", "altitude", "capacity_used", "groundId", "totalLinkCount", "cumulativeCostBySat", "time" ] }
- Fields:
id (int)name (str)latitude (float)longitude (float)altitude (float)capacity_used (float)commRange (bool)groundId (int | None)totalLinkCount (int | None)cumulativeCostBySat (float)time (datetime.datetime)
- field id: int [Required]
Unique satellite identifier
- field name: str [Required]
Satellite name for labeling
- field latitude: float [Required]
Latitude (deg) of satellite subpoint location.
- Constraints:
ge = -90
le = 90
- field longitude: float [Required]
Longitude (deg) of satellite subpoint location.
- Constraints:
ge = -180
le = 180
- field altitude: float [Required]
Altitude (meters) of satellite above sea level
- field capacity_used: float [Required]
GB of solid state recorder capacity used
- field commRange: bool = False
Boolean for if satellite is in ground stations view
- field cumulativeCostBySat: float [Required]
Cumulative cost of downlinks and/or fixed cost contracts per satellite
- field time: datetime [Required]
Time in satellite reference frame
- pydantic settings GroundLocation
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message for ground station information includes:
Show JSON schema
{ "title": "GroundLocation", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message for ground station information includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier", "title": "Groundid", "type": "integer" }, "latitude": { "description": "Latitude (deg) of ground station.", "maximum": 90, "minimum": -90, "title": "Latitude", "type": "number" }, "longitude": { "description": "Longitude (deg) of ground station.", "maximum": 180, "minimum": -180, "title": "Longitude", "type": "number" }, "elevAngle": { "description": "Minimum elevation angle (deg) for satellite-ground communications", "title": "Elevangle", "type": "number" }, "operational": { "default": true, "description": "True, if this ground station is operational", "title": "Operational", "type": "boolean" }, "downlinkRate": { "description": "Downlink rate for this ground station in Megabytes per second", "title": "Downlinkrate", "type": "number" }, "costPerSecond": { "description": "Cost in $ per second for downlinks", "title": "Costpersecond", "type": "number" }, "costMode": { "default": "discrete", "description": "Could be a boolean, options are discrete or fixed, default to discrete", "title": "Costmode", "type": "string" } }, "required": [ "groundId", "latitude", "longitude", "elevAngle", "downlinkRate", "costPerSecond" ] }
- Fields:
groundId (int)latitude (float)longitude (float)elevAngle (float)operational (bool)downlinkRate (float)costPerSecond (float)costMode (str)
- field groundId: int [Required]
Unique ground station identifier
- field latitude: float [Required]
Latitude (deg) of ground station.
- Constraints:
ge = -90
le = 90
- field longitude: float [Required]
Longitude (deg) of ground station.
- Constraints:
ge = -180
le = 180
- field elevAngle: float [Required]
Minimum elevation angle (deg) for satellite-ground communications
- field operational: bool = True
True, if this ground station is operational
- field downlinkRate: float [Required]
Downlink rate for this ground station in Megabytes per second
- field costPerSecond: float [Required]
Cost in $ per second for downlinks
- field costMode: str = 'discrete'
Could be a boolean, options are discrete or fixed, default to discrete
- pydantic settings LinkStart
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message indicating the beginning of a downlink opportunity includes:
Show JSON schema
{ "title": "LinkStart", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message indicating the beginning of a downlink opportunity includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier", "title": "Groundid", "type": "integer" }, "satId": { "description": "Unique satellite identifier that performed the downlink", "title": "Satid", "type": "integer" }, "satName": { "description": "Name of satellite that performed the downlink", "title": "Satname", "type": "string" }, "linkId": { "description": "Unique downlink counter for the specific spacecraft that downlinked", "title": "Linkid", "type": "integer" }, "start": { "description": "Start time in ground network reference frame", "format": "date-time", "title": "Start", "type": "string" }, "data": { "description": "Current amount of data on-board the satellite that needs to be offloaded", "title": "Data", "type": "number" } }, "required": [ "groundId", "satId", "satName", "linkId", "start", "data" ] }
- Fields:
groundId (int)satId (int)satName (str)linkId (int)start (datetime.datetime)data (float)
- field groundId: int [Required]
Unique ground station identifier
- field satId: int [Required]
Unique satellite identifier that performed the downlink
- field satName: str [Required]
Name of satellite that performed the downlink
- field linkId: int [Required]
Unique downlink counter for the specific spacecraft that downlinked
- field start: datetime [Required]
Start time in ground network reference frame
- field data: float [Required]
Current amount of data on-board the satellite that needs to be offloaded
- pydantic settings LinkCharge
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message indicating the end of a downlink opportunity and updating cost ledgers includes:
Show JSON schema
{ "title": "LinkCharge", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message indicating the end of a downlink opportunity and updating cost ledgers includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier", "title": "Groundid", "type": "integer" }, "satId": { "description": "Unique satellite identifier that performed the downlink", "title": "Satid", "type": "integer" }, "satName": { "description": "Name of satellite that performed the downlink", "title": "Satname", "type": "string" }, "linkId": { "description": "Unique downlink counter for the specific spacecraft that downlinked", "title": "Linkid", "type": "integer" }, "end": { "description": "Time stamp for end of downlink when charge is sent", "format": "date-time", "title": "End", "type": "string" }, "duration": { "description": "Time duration of satellite in view for this downlink (s)", "title": "Duration", "type": "number" }, "dataOffload": { "description": "Amount of data offloaded based on linear downlink rates unique to each ground station (GB)", "title": "Dataoffload", "type": "number" }, "downlinkCost": { "description": "Cost of data downlink based on per-second cost rates unique to each ground station", "title": "Downlinkcost", "type": "number" }, "cumulativeCostBySat": { "description": "Dictionary of running totals for downlink costs per satellite", "title": "Cumulativecostbysat", "type": "number" }, "cumulativeCosts": { "description": "Running total of ALL downlink costs for the entirety of the Test Case", "title": "Cumulativecosts", "type": "number" } }, "required": [ "groundId", "satId", "satName", "linkId", "end", "duration", "dataOffload", "downlinkCost", "cumulativeCostBySat", "cumulativeCosts" ] }
- Fields:
groundId (int)satId (int)satName (str)linkId (int)end (datetime.datetime)duration (float)dataOffload (float)downlinkCost (float)cumulativeCostBySat (float)cumulativeCosts (float)
- field groundId: int [Required]
Unique ground station identifier
- field satId: int [Required]
Unique satellite identifier that performed the downlink
- field satName: str [Required]
Name of satellite that performed the downlink
- field linkId: int [Required]
Unique downlink counter for the specific spacecraft that downlinked
- field end: datetime [Required]
Time stamp for end of downlink when charge is sent
- field duration: float [Required]
Time duration of satellite in view for this downlink (s)
- field dataOffload: float [Required]
Amount of data offloaded based on linear downlink rates unique to each ground station (GB)
- field downlinkCost: float [Required]
Cost of data downlink based on per-second cost rates unique to each ground station
- field cumulativeCostBySat: float [Required]
Dictionary of running totals for downlink costs per satellite
- field cumulativeCosts: float [Required]
Running total of ALL downlink costs for the entirety of the Test Case
- pydantic settings OutageReport
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message indicating the beginning of an outage at a ground station includes:
Show JSON schema
{ "title": "OutageReport", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message indicating the beginning of an outage at a ground station includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier experiencing outage", "title": "Groundid", "type": "integer" }, "outageStart": { "description": "Initial time of outage report", "format": "date-time", "title": "Outagestart", "type": "string" }, "outageDuration": { "description": "Duration of the reported outage", "format": "duration", "title": "Outageduration", "type": "string" }, "outageEnd": { "description": "outageStart + outageDuration", "format": "date-time", "title": "Outageend", "type": "string" } }, "required": [ "groundId", "outageStart", "outageDuration", "outageEnd" ] }
- Fields:
groundId (int)outageStart (datetime.datetime)outageDuration (datetime.timedelta)outageEnd (datetime.datetime)
- field groundId: int [Required]
Unique ground station identifier experiencing outage
- field outageStart: datetime [Required]
Initial time of outage report
- field outageDuration: timedelta [Required]
Duration of the reported outage
- field outageEnd: datetime [Required]
outageStart + outageDuration
- pydantic settings OutageRestore
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message indicating the end of an outage with restored service at a ground station includes:
Show JSON schema
{ "title": "OutageRestore", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message indicating the end of an outage with restored service at a ground station includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier", "title": "Groundid", "type": "integer" }, "outageEnd": { "description": "outageStart + outageDuration", "format": "date-time", "title": "Outageend", "type": "string" } }, "required": [ "groundId", "outageEnd" ] }
- Fields:
groundId (int)outageEnd (datetime.datetime)
- field groundId: int [Required]
Unique ground station identifier
- field outageEnd: datetime [Required]
outageStart + outageDuration