Connector Extensions¶
This guide explains how to build connectors using the standard BMS connector API.
Architecture¶
Connector plugins feed updates into ConnectorManager, which forwards normalized updates to BMS UI layers.
1. Implement ConnectorInterface¶
Create a connector class that derives from gva::connector::ConnectorInterface.
Minimum implementation responsibilities:
- Identity and metadata:
connectorId()displayName()description()version()supportedTypes()- Lifecycle:
start()stop()isRunning()status()- Configuration:
configure(const QVariantMap&)configuration() constconfigurationSchema() constvalidateConfiguration(const QVariantMap&, QString&) const
Data Signals¶
Emit the normalized API signals as your source data changes:
positionUpdated(const PositionUpdate&)trackLost(const QString&)videoUpdated(const VideoUpdate&)videoRemoved(const QString&)geofenceUpdated(const GeofenceUpdate&)geofenceRemoved(const QString&)bullseyeUpdated(const BullseyeUpdate&)bullseyeRemoved(const QString&)emergencyAlertUpdated(const EmergencyAlertUpdate&)routeUpdated(const RouteUpdate&)statusChanged(const ConnectorStatus&)errorOccurred(const QString&)
2. Normalize To PositionUpdate¶
Use PositionUpdate as the common contract for track/sensor/platform objects.
Important generic fields for SAPIENT-like connectors:
- Object typing:
objectKindnodeIdparentId- Primary position and kinematics:
latitude,longitude,altitudeheading,speed- Sensor metadata:
sensorLatitude,sensorLongitude,sensorAltitudesensorRangeMeters,sensorBearingDegsensorFovHorizontalDeg,sensorFovRangeMeterssensorIsOptical- Classification metadata:
classifications,behaviours,rfSignalsclassificationSummary,behaviourSummary
Use helper predicates where appropriate:
hasSensorPosition()hasSensorCoverage()isSensorLike()
3. Expose Through The Standard Plugin API¶
Create a plugin class implementing ConnectorPluginInterface from the installed SDK headers (#include <ConnectorPlugin.h>).
Typical pattern:
class MyConnectorPlugin : public QObject, public gva::connector::ConnectorPluginInterface {
Q_OBJECT
GVA_CONNECTOR_PLUGIN(MyConnectorPlugin)
public:
QStringList connectorIds() const override { return {"my-connector"}; }
ConnectorInterface* createConnector(const QString& connectorId, QObject* parent = nullptr) override {
if (connectorId == "my-connector") {
return new MyConnector(parent);
}
return nullptr;
}
QJsonObject pluginMetadata() const override;
};
4. CMake Wiring For A Connector Plugin¶
Create a module target and install it into the BMS plugin directory:
add_library(gva-app-bms-myconnector MODULE
connectors/my-connector/MyConnector.h
connectors/my-connector/MyConnector.cpp
connectors/my-connector/MyConnectorPlugin.h
connectors/my-connector/MyConnectorPlugin.cpp
)
target_include_directories(gva-app-bms-myconnector PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/connectors
)
target_link_libraries(gva-app-bms-myconnector PRIVATE
Qt6::Core
Qt6::Network
)
set_target_properties(gva-app-bms-myconnector PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/gva-bms-connectors
PREFIX "lib"
SUFFIX ".so"
)
install(TARGETS gva-app-bms-myconnector
LIBRARY DESTINATION lib/gva-bms-connectors
COMPONENT gva-app-bms
)
5. Runtime Loading¶
Desktop ConnectorManager loads plugins from:
BMS_CONNECTOR_PLUGIN_DIR(environment override)- default
../lib/gva-bms-connectorsnext to the app install tree
If plugin loading fails, inspect:
- plugin path
- unresolved shared library dependencies
ConnectorPluginInterfaceimplementation and IID
6. Validation Checklist¶
Before shipping a connector:
- Configuration schema appears in UI and validates correctly.
start()andstop()are idempotent.- Status transitions are emitted (
Disconnected,Connecting,Connected,Error). - Stale track cleanup emits
trackLostcorrectly. - Sensor metadata fields are populated consistently for sensor-like objects.
- Plugin loads from install path with no manual library path hacks.