How God’s Eye View Resolves Metadata for Tracked Entities: Context Store Architecture
God’s Eye View resolves metadata for tracked entities through a centralized context store that maps every subject to a metadata record via registerEntityContext, retrieves current state via selectTrackedSubjectContext, and merges telemetry updates via refreshTrackedSubjectContext while preserving sticky fields.
God’s Eye View (GEV) is an open-source geospatial visualization project (bilawalsidhu/gods-eye-view) that tracks aircraft, satellites, and maritime vessels in real time. When telemetry arrives from various data layers, the application must resolve which metadata belongs to which visual entity and ensure that critical identifiers remain stable across updates. This resolution logic is centralized in src/data/contextStore.js, which maintains a single source of truth for all tracked subject metadata through a pipeline of registration, selection, and refresh operations.
The Metadata Resolution Pipeline
The context store implements a three-phase resolution pipeline that handles the complete lifecycle of entity metadata. Each phase corresponds to a specific function exported from the store module, operating on a global Map structure that maps entity identifiers to their associated metadata records.
Registration via registerEntityContext
When a new subject appears in the telemetry stream—whether an aircraft entering the surveillance area or a satellite passing overhead—the owning layer invokes registerEntityContext(entity, metadata). This function creates a metadata record containing at minimum the id (unique identifier) and layerId (source layer), then stores it in the global store.entities Map. According to the source implementation in src/data/contextStore.js, this establishes the initial metadata baseline that subsequent operations will reference.
Selection via selectTrackedSubjectContext
UI components such as the cockpit HUD, flight tracking overlays, or military contact displays retrieve metadata through selectTrackedSubjectContext(metadata). This function queries the global store using the provided identifier and returns the existing record if found. If no record exists—indicating the entity has not yet been registered or has been purged—the function returns null, allowing the calling component to handle the absence gracefully. This selection mechanism ensures that all UI elements read from the same centralized state rather than maintaining isolated copies.
Refresh via refreshTrackedSubjectContext
As real-time telemetry arrives—new AIS messages for vessels, ADS-B updates for aircraft, or orbital elements for satellites—the system must merge fresh data with existing records without destroying stable identifiers. The refreshTrackedSubjectContext(metadata) function handles this merge operation, updating fields like altitude, speed, or position while preserving "sticky" metadata that should survive across updates, such as aircraft registrations or vessel IMO numbers.
Sticky Metadata Preservation
Certain fields in the metadata record are designated as sticky: once they receive a non-null value, subsequent telemetry updates cannot overwrite them. This behavior, implemented within the merge logic of registerEntityContext and refreshTrackedSubjectContext, guarantees that stable identifiers remain constant even if upstream data sources temporarily omit them or provide conflicting values. The system checks incoming values against a STICKY_FIELDS array; if a field is sticky and already populated, the existing value is retained regardless of the new telemetry content.
Core Implementation Files
The metadata resolution system spans several key files within the repository, each responsible for distinct aspects of the pipeline:
-
src/data/contextStore.js: Contains the central Map store and the three primary resolution functions (registerEntityContext,selectTrackedSubjectContext,refreshTrackedSubjectContext). This file maintains thestore.entitiesMap that serves as the single source of truth. -
src/cockpitTracking.js: Consumes resolved metadata to populate the primary flight tracking interface, callingselectTrackedSubjectContextto retrieve current aircraft states for display. -
src/layers/flights/tracking.js: Implements the flight layer's integration with the context store, registering new aircraft and refreshing existing ones as ADS-B telemetry streams in. -
src/layers/military/tracking.js: Demonstrates the layer-agnostic nature of the resolution system by handling military contacts using the same registration and refresh patterns as civilian flights. -
src/data/aircraftMeta.js: Provides helper utilities for merging aircraft-specific sticky metadata, containing theSTICKY_FIELDSdefinition and merge logic referenced by the context store. -
src/hud.js: Renders metadata strips and labels by reading resolved records from the context store, displaying callsigns, altitudes, and other tracked properties.
Working with the Context Store API
The following examples demonstrate how to interact with the metadata resolution system in application code.
Registering a New Tracked Object
When a layer detects a new entity, it registers the metadata to establish the tracking baseline:
import { registerEntityContext } from '../data/contextStore.js';
// Create or obtain the Cesium entity for visualization
const aircraftEntity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(lon, lat, alt),
point: { pixelSize: 10, color: Cesium.Color.YELLOW }
});
// Define initial metadata with required id and layerId fields
const aircraftMeta = {
id: 'A0B1C2', // ICAO 24-bit address
layerId: 'flights', // Origin layer identifier
callsign: 'UAL123',
altitudeFt: 32000,
speedMps: 245,
registration: 'N12345' // Sticky field
};
// Register in the global context store
registerEntityContext(aircraftEntity, aircraftMeta);
Selecting Metadata for UI Components
Components retrieve current metadata to render information panels or update visual attributes:
import { selectTrackedSubjectContext } from '../data/contextStore.js';
function updateCockpitDisplay(selectedEntity) {
// Retrieve the resolved metadata record
const record = selectTrackedSubjectContext(selectedEntity);
if (!record) {
console.warn('No metadata found for selected entity');
return;
}
// Update HUD elements with resolved values
hud.updateCallsign(record.callsign);
hud.updateAltitude(record.altitudeFt);
hud.updateSpeed(record.speedMps);
}
Refreshing Metadata on Telemetry Updates
When new data arrives from external feeds, the layer refreshes the context store while allowing sticky fields to persist:
import { refreshTrackedSubjectContext } from '../data/contextStore.js';
function handleFlightUpdate(adsbMessage) {
const incomingMeta = {
id: adsbMessage.icao,
layerId: 'flights',
altitudeFt: adsbMessage.altitude,
speedMps: adsbMessage.velocity,
// callsign might be null in this message
callsign: adsbMessage.callsign
};
// Merge into existing record; sticky fields like registration persist
refreshTrackedSubjectContext(incomingMeta);
}
Internal Sticky Field Merge Logic
The context store implements the following merge strategy to handle sticky metadata preservation:
// Simplified excerpt from src/data/contextStore.js
const STICKY_FIELDS = ['registration', 'imoNumber', 'serialNumber'];
function mergeMetadata(existingMeta, newMeta) {
const merged = { ...existingMeta };
for (const [key, value] of Object.entries(newMeta)) {
if (value === null || value === undefined) continue;
// Preserve existing sticky values
if (STICKY_FIELDS.includes(key) && merged[key] != null) {
continue;
}
merged[key] = value;
}
return merged;
}
Summary
- Centralized Resolution: All entity metadata resolves through
src/data/contextStore.js, which maintains a globalMapof identifiers to metadata records. - Three-Phase Pipeline: The system uses
registerEntityContextfor initialization,selectTrackedSubjectContextfor reads, andrefreshTrackedSubjectContextfor updates. - Sticky Field Protection: Critical identifiers survive telemetry updates through sticky field logic that preserves existing non-null values.
- Layer Agnostic: Any layer (flights, military, maritime) can register entities using the same API, with
layerIddistinguishing ownership. - UI Integration: Cockpit displays and HUD components consume resolved metadata directly from the store, ensuring consistent state across the application.
Frequently Asked Questions
What happens if telemetry arrives for an unregistered entity?
If refreshTrackedSubjectContext receives metadata for an identifier not present in store.entities, the function typically ignores the update or returns early without creating a record. The entity must first be registered via registerEntityContext before the store will maintain its metadata state, ensuring that only explicitly tracked subjects consume memory and processing resources.
How does God's Eye View prevent stale metadata from overwriting critical identifiers?
The context store implements sticky metadata logic within its merge functions. Fields listed in the STICKY_FIELDS array—such as aircraft registrations or vessel IMO numbers—are protected after their initial population. When refreshTrackedSubjectContext processes incoming telemetry, it checks whether a sticky field already contains a non-null value; if so, it discards the incoming value for that field while still updating non-sticky properties like altitude or speed.
Can multiple layers track the same entity simultaneously?
While the context store supports entities from any layer, each metadata record contains a layerId property indicating ownership. If two layers attempt to register entities with the same id, the latter registration will overwrite the former in the global Map. The current implementation assumes unique identifiers across layers; for shared tracking scenarios, layers should coordinate through a single registration point or use composite keys that include the layer identifier.
Why use a centralized Map instead of attaching metadata directly to Cesium entities?
Attaching metadata directly to Cesium entity objects would couple data management to the visualization layer, complicating testing and preventing non-visual systems (such as analytics or alerting modules) from accessing tracking state. The centralized store.entities Map decouples metadata resolution from rendering, allows background workers to update tracking state, and enables sticky-field logic that would be fragile if scattered across multiple entity references.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →