Корректное ожидание подтверждения Bridge

This commit is contained in:
DCCONSTRUCTIONS
2026-08-23 12:14:56 +03:00
parent 7d911b4b1f
commit 456141a3f3
4 changed files with 133 additions and 12 deletions
@@ -18,6 +18,7 @@ import {
backendConnectionTopology,
connectionAttemptForRuntimeError,
hasControlAuthority,
isConnectionControlBootstrapSettling,
isConfirmedLiveState,
isPhysicalStopRecoverySettling,
isRecoveredPhysicalScanning,
@@ -274,12 +275,16 @@ export function XgridsK1Connection({ model, host }: DevicePluginConnectionProps)
: sourceRuntimeBusy || preparedAcquisition
? "warning"
: "neutral";
const connectionControlBootstrapSettling =
isConnectionControlBootstrapSettling(state);
const connectionPhaseLabel = livePreparationPending
? "Подготовка приёма"
: sourceRuntimeBusy || preparedAcquisition
? sourceLabel
: activeRecoveryPresentation
? activeRecoveryPresentation.title
: connectionControlBootstrapSettling
? "Подтверждение подключения"
: physicalStopRecoverySettling
? "Завершение остановки"
: recoveredPhysicalScanning
@@ -307,6 +312,8 @@ export function XgridsK1Connection({ model, host }: DevicePluginConnectionProps)
? sourceTone
: activeRecoveryPresentation
? activeRecoveryPresentation.tone
: connectionControlBootstrapSettling
? "accent"
: physicalRecoveryRequired
? "warning"
: projectedPhase === "error"
@@ -322,6 +329,8 @@ export function XgridsK1Connection({ model, host }: DevicePluginConnectionProps)
? "Команда остановки уже принята. Завершение выполняется без повторной команды."
: activeRecoveryPresentation
? activeRecoveryPresentation.detail
: connectionControlBootstrapSettling
? "Сеть применена. Сервис проверяет управляющее подключение без повторения BLE-команды."
: recoveredPhysicalScanning
? "Локальная запись остановлена, но сканирование ещё продолжается."
: physicalRecoveryRequired
@@ -2021,16 +2021,18 @@ export function K1ProvisioningPipeline({
const changeNetworkActionApplicable = connectionMode === "bridge"
&& connectedReconfigurationActionApplicable(state, "prepare-change-network");
const showNetworkStep = Boolean(
!presentedPhysicalRecoveryRequired
&& !presentedConnectionRecoveryRequired
&& (
connectionPresentationEstablished
|| explicitProvisioningDraftRetained
|| explicitProvisioningDraftContextRetained
|| unresolvedAppliedAttempt
|| connectionAttemptSettling
|| connectionAttemptFailed
|| (changeNetworkDialogue && Boolean(changeNetworkRequiredDeviceId))
connectionAttemptSettling
|| (
!presentedPhysicalRecoveryRequired
&& !presentedConnectionRecoveryRequired
&& (
connectionPresentationEstablished
|| explicitProvisioningDraftRetained
|| explicitProvisioningDraftContextRetained
|| unresolvedAppliedAttempt
|| connectionAttemptFailed
|| (changeNetworkDialogue && Boolean(changeNetworkRequiredDeviceId))
)
)
);
const requestExplicitProvisioning = useCallback((
@@ -3296,6 +3298,8 @@ export function K1ProvisioningPipeline({
? "accent"
: connectionEstablished
? "success"
: connectionAttemptSettling
? "accent"
: networkRecoveryRequired
|| presentedPhysicalRecoveryRequired
|| explicitProvisioningDraftStale
@@ -3330,7 +3334,7 @@ export function K1ProvisioningPipeline({
?? "Сервис не определил точный прежний K1 для безопасной проверки"}
</small>
</div>
) : presentedPhysicalRecoveryRequired ? (
) : presentedPhysicalRecoveryRequired && !connectionAttemptSettling ? (
<div
className="field-stack"
aria-busy={physicalReconnectPending || undefined}
@@ -3388,7 +3392,7 @@ export function K1ProvisioningPipeline({
</p>
) : null}
</div>
) : presentedConnectionRecoveryRequired ? (
) : presentedConnectionRecoveryRequired && !connectionAttemptSettling ? (
<div
className="field-stack"
aria-busy={connectionReconnectPending || undefined}
@@ -466,6 +466,26 @@ export function sourceStatusLabel(state: XgridsK1State | null | undefined): stri
return "Ожидание";
}
/**
* The network write has already crossed its single mutation boundary and the
* service is now proving control authority without another BLE command. This
* current connection intent must remain visibly pending even when an older
* physical-command checkpoint is being reconciled by the same bootstrap.
*/
export function isConnectionControlBootstrapSettling(
state: XgridsK1State | null | undefined,
): boolean {
const attempt = state?.connection_attempt;
if (
!attempt
|| attempt.phase !== "network_applied"
|| attempt.control_state !== "unknown"
) return false;
if (["accepted", "running"].includes(attempt.status)) return true;
return attempt.status === "succeeded"
&& attempt.safe_next_action === "verify-control-read-only";
}
export function operationByIdempotencyKey(
state: XgridsK1State | null | undefined,
action: string,