1pragma ComponentBehavior: Bound
7import QGroundControl.Controls
8import QGroundControl.FactControls
9import QGroundControl.GPS
14 property GPSReceiver receiver: QGroundControl.gpsManager.receiver
15 property RTKSettings settings: QGroundControl.settingsManager.rtkSettings
16 property SettingsFact autoConnectFact: settings.autoConnect as SettingsFact
17 property list<gpsSerialPortEntry> serialPorts: root.receiver.serialPortEntries
18 property list<int> serialBaudRates: root.receiver.serialBaudRates
19 /// Hosts that already show receiver errors elsewhere can hide the inline message.
20 property bool showErrorMessage: true
22 readonly property int role: settings.receiverRole.rawValue
23 readonly property bool configuredBase: role === RTKSettings.ConfiguredBase
24 readonly property int manufacturer: settings.baseReceiverManufacturers.rawValue
25 readonly property int baseMode: settings.useFixedBasePosition.rawValue
26 readonly property gpsReceiverPresentation presentation: receiver.capabilitiesFor(role, manufacturer)
27 // A pending automatic reconnect keeps the saved connection; stop it before editing.
28 readonly property bool _active: receiver.hasReceiver || receiver.reconnecting
29 readonly property bool _editable: !_active
30 readonly property int _connection: settings.connectionType.rawValue
31 readonly property bool _udp: receiver.effectiveConnectionType === RTKSettings.Udp
32 readonly property bool _tcp: receiver.effectiveConnectionType === RTKSettings.Tcp
33 readonly property bool _serial: receiver.effectiveConnectionType === RTKSettings.Serial
34 readonly property bool _connectionSupported: receiver.connectionSupported
35 readonly property list<string> _baseModeNames: settings.useFixedBasePosition.enumStrings
36 // Automatic detection words the Quectel notes for a receiver that may not be one.
37 readonly property string _quectelOnly: presentation.automatic
38 ? qsTr("Applies only if a Quectel receiver is identified.") + " " : ""
40 heading: qsTr("GNSS Receiver")
42 component Field: GPSField {
43 required property Fact fact
44 /// Shows the field when the setting itself is visible.
45 property bool shown: true
46 readonly property SettingsFact _setting: fact as SettingsFact
49 visible: shown && (!_setting || _setting.userVisible)
52 component SettingField: Field {
55 Layout.fillWidth: true
56 Layout.minimumWidth: 0
61 component ComboField: Field {
63 property alias comboBox: combo
66 Layout.fillWidth: true
67 Layout.minimumWidth: 0
72 component SwitchField: Field {
74 property alias toggle: slider
78 Accessible.name: switchField.fact.label
79 fact: switchField.fact
83 component ModeButton: QGCRadioButton {
84 Layout.fillWidth: true
85 Layout.minimumWidth: 0
86 focusPolicy: Qt.StrongFocus
91 fact: root.settings.receiverRole
92 comboBox.objectName: "rtkReceiverRole"
93 comboBox.enabled: root._editable
94 note: root.configuredBase
95 ? qsTr("QGroundControl configures a supported receiver as an RTK base station and forwards its RTCM corrections to vehicles.")
96 : qsTr("QGroundControl never configures this receiver. Its NMEA, u-blox UBX or Septentrio SBF position output provides the ground station position. Configure the receiver's output externally and select its existing baud rate. No survey-in status is inferred.")
100 fact: root.settings.forwardReceiverRtcm
101 note: root.settings.forwardReceiverRtcm.shortDescription
102 shown: !root.configuredBase
103 toggle.objectName: "rtkForwardReceiverRtcm"
104 toggle.enabled: root._editable
108 fact: root.settings.baseReceiverManufacturers
109 shown: root.configuredBase
110 comboBox.objectName: "rtkManufacturer"
111 comboBox.enabled: root._editable
114 objectName: "rtkAutomaticExplanation"
115 visible: root.presentation.automatic
116 text: root.settings.baseReceiverManufacturers.shortDescription
121 fact: root.settings.connectionType
122 comboBox.objectName: "rtkConnectionType"
123 comboBox.enabled: root._editable
126 objectName: "rtkTcpOnly"
127 visible: !root.receiver.serialSupported && root._connection === RTKSettings.Serial
128 text: qsTr("Serial receivers are not supported on this platform, so the receiver connects over TCP.")
133 objectName: "rtkTcpHost"
134 fact: root.settings.tcpHost
135 enabled: root._editable
140 objectName: "rtkTcpPort"
141 fact: root.settings.tcpPort
142 enabled: root._editable
144 note: qsTr("Connect to a receiver's TCP port or a serial-to-TCP bridge. A bridge must already run the receiver link at 115200 baud; QGroundControl cannot change a bridge's rate.")
148 objectName: "rtkUdpPort"
149 fact: root.settings.udpPort
150 enabled: root._editable
154 objectName: "rtkUdpExplanation"
155 warning: !root._connectionSupported
156 text: root._connectionSupported ? root.settings.udpPort.shortDescription
157 : qsTr("A configured base needs a serial or TCP connection. UDP only receives data.")
161 GPSReceiverSerialPort {
162 Layout.minimumWidth: 0
163 visible: root.receiver.serialSupported && root._serial
164 deviceFact: root.settings.serialDevice
165 baudFact: root.settings.serialBaudRate
166 serialPorts: root.serialPorts
167 serialBaudRates: root.serialBaudRates
168 anyDeviceLabel: root.configuredBase && root.autoConnectFact.rawValue ? qsTr("Any RTK receiver on USB") : ""
169 allowAutoBaud: !root.presentation.passive
170 editable: root._editable
174 visible: root._editable && root.configuredBase
175 text: root.presentation.automatic
176 ? qsTr("If the identified receiver does not support the selected base mode, connecting fails and names the receiver. Auto baud tries every rate the supported receivers use.")
177 : !root.presentation.specificReceiver
178 ? qsTr("Select a receiver type and its connection to connect manually. Auto baud detects the rate of configurable receivers.")
179 : qsTr("Connect only the selected receiver; automatic connections configure it too. A USB adapter's identity only decides which USB ports are tried, not the GNSS manufacturer.")
183 objectName: "rtkPersistentConfigurationWarning"
184 visible: root.presentation.restartOnConnect
185 text: root._quectelOnly + qsTr("Without permission to save, Quectel role and base settings must already match settings saved externally. The receiver restarts on connection. Survey-In counts accepted 1 Hz observations; its accuracy limit filters each observation and does not guarantee final position accuracy.")
189 objectName: "rtkSurveySavesPosition"
190 visible: root.presentation.surveyMaySavePosition && root.baseMode === BaseModeDefinition.BaseSurveyIn
191 text: root._quectelOnly + qsTr("The Quectel receiver may automatically store the completed survey position in its own memory.")
195 Layout.minimumWidth: 0
196 visible: root.presentation.rtkBase
197 enabled: root._editable
200 objectName: "rtkSurveyMode"
201 text: root._baseModeNames[BaseModeDefinition.BaseSurveyIn]
202 checked: root.baseMode === BaseModeDefinition.BaseSurveyIn
203 onClicked: root.settings.useFixedBasePosition.rawValue = BaseModeDefinition.BaseSurveyIn
204 visible: root.presentation.surveyIn
207 objectName: "rtkFixedMode"
208 text: root._baseModeNames[BaseModeDefinition.BaseFixed]
209 checked: root.baseMode === BaseModeDefinition.BaseFixed
210 onClicked: root.settings.useFixedBasePosition.rawValue = BaseModeDefinition.BaseFixed
213 text: root._baseModeNames[BaseModeDefinition.BaseReceiverAveraging]
214 checked: root.baseMode === BaseModeDefinition.BaseReceiverAveraging
215 onClicked: root.settings.useFixedBasePosition.rawValue = BaseModeDefinition.BaseReceiverAveraging
216 visible: root.presentation.receiverAveraging
221 visible: !root.receiver.baseModeSupported
222 text: qsTr("The selected base mode is not supported by this receiver. Choose a supported mode explicitly.")
226 fact: root.settings.receiverAveragingDuration
227 shown: root.presentation.receiverAveraging && root.baseMode === BaseModeDefinition.BaseReceiverAveraging
228 enabled: root._editable
229 note: root.settings.receiverAveragingDuration.shortDescription
233 Layout.minimumWidth: 0
234 spacing: ScreenTools.defaultFontPixelHeight / 2
235 visible: root.baseMode === BaseModeDefinition.BaseSurveyIn
236 && (root.presentation.surveyAccuracy || root.presentation.surveyDuration)
237 enabled: root._editable
240 Layout.fillWidth: true
241 Layout.minimumWidth: 0
242 label: root.presentation.observationAccuracyFilter ? qsTr("Observation accuracy limit")
243 : root.settings.surveyInAccuracyLimit.label
244 fact: root.settings.surveyInAccuracyLimit
245 majorTickStepSize: 0.1
246 visible: root.presentation.surveyAccuracy && (root.settings.surveyInAccuracyLimit as SettingsFact).userVisible
250 Layout.fillWidth: true
251 Layout.minimumWidth: 0
252 label: root.presentation.acceptedObservationTime ? qsTr("Accepted observation time")
253 : root.settings.surveyInMinObservationDuration.label
254 fact: root.settings.surveyInMinObservationDuration
255 majorTickStepSize: 10
256 visible: root.presentation.surveyDuration
257 && (root.settings.surveyInMinObservationDuration as SettingsFact).userVisible
261 // The fixed base position reads as one value, so its coordinates are not divided.
263 Layout.minimumWidth: 0
264 spacing: ScreenTools.defaultFontPixelHeight / 2
265 visible: root.baseMode === BaseModeDefinition.BaseFixed && root.presentation.rtkBase
266 enabled: root._editable
268 SettingField { fact: root.settings.fixedBasePositionLatitude }
269 SettingField { fact: root.settings.fixedBasePositionLongitude }
270 SettingField { fact: root.settings.fixedBasePositionAltitude }
272 fact: root.settings.fixedBasePositionAccuracy
273 shown: root.presentation.fixedBaseAccuracy
278 fact: root.settings.compactRtcmCorrections
279 note: root.settings.compactRtcmCorrections.shortDescription
280 shown: root.configuredBase && root.presentation.compactObservations
281 toggle.objectName: "rtkCompactRtcm"
282 toggle.enabled: root._editable
286 Layout.minimumWidth: 0
287 spacing: ScreenTools.defaultFontPixelHeight / 4
288 visible: root.presentation.persistentConfiguration
291 objectName: "rtkPersistentChangesCheckBox"
292 Layout.fillWidth: true
293 Layout.minimumWidth: 0
294 text: root.presentation.automatic ? qsTr("Allow flash save and restart if a Quectel receiver is identified")
295 : qsTr("Allow flash save and restart")
296 focusPolicy: Qt.StrongFocus
298 enabled: root._editable
299 checked: root.receiver.persistentChangesAllowed
300 onClicked: root.receiver.persistentChangesAllowed = checked
304 objectName: "rtkPersistentConsentWarning"
305 text: root._quectelOnly + qsTr("For this connection only, allow QGroundControl to write requested base role or base-setting changes to receiver flash and restart it. Changes may remain saved even if reconnecting fails. No factory reset is performed. Permission is cleared after each attempt and is never used by automatic connections. To use the receiver as a rover again, restore its role with Quectel QGNSS or $PQTMCFGRCVRMODE,W,1 followed by $PQTMSAVEPAR.")
310 fact: root.autoConnectFact
311 note: root.autoConnectFact.rawValue ? root.autoConnectFact.shortDescription : ""
312 toggle.objectName: "rtkAutoConnect"
316 objectName: "rtkConnectButton"
317 Layout.fillWidth: true
318 Layout.minimumWidth: 0
320 focusPolicy: Qt.StrongFocus
321 text: root._active ? qsTr("Disconnect") : qsTr("Connect")
322 enabled: root._active || root.receiver.canConnect
325 root.receiver.disconnectReceiver()
327 root.receiver.connectReceiver()
333 objectName: "rtkErrorMessage"
334 visible: root.showErrorMessage && text.length > 0
335 text: root.receiver.errorMessage || ""
338 // The permission is for the configuration shown here, so leaving the page withdraws it.
339 Component.onDestruction: {
341 receiver.persistentChangesAllowed = false