Безопасное завершение калибровки при отключении K1

This commit is contained in:
DCCONSTRUCTIONS
2026-08-23 13:55:28 +03:00
parent 3e5aedd74d
commit 6e7428a116
2 changed files with 314 additions and 10 deletions
+111 -10
View File
@@ -28455,6 +28455,91 @@ class XgridsK1CompatibilityService:
)
)
@staticmethod
def _matching_accepted_start_scan_over_before_active(
physical_command_proof: Mapping[str, Any] | None,
*,
acquisition_id: str | None,
start_operation_id: str | None,
verified_control: Mapping[str, Any] | None,
) -> bool:
"""Recognize an accepted START followed by bound pre-active SCAN_OVER.
K1 can accept the canonical START and then leave calibration before it
ever reports the target SCANNING state (for example, after losing
power). The physical ledger correctly remains unresolved because no
active target was observed. Local capture may nevertheless terminate
once the same DeviceInfo-bound generation reports fresh, non-retained
SCAN_OVER. This proof never resolves the physical ledger or authorizes
another START/STOP; a later explicit read-only reconciliation remains
mandatory.
"""
if (
not isinstance(physical_command_proof, Mapping)
or not isinstance(acquisition_id, str)
or not acquisition_id
or not isinstance(start_operation_id, str)
or not start_operation_id
or not isinstance(verified_control, Mapping)
or physical_command_proof.get("status") != "unresolved"
or physical_command_proof.get("requires_reconciliation") is not True
or physical_command_proof.get("runtime_bound") is not True
or physical_command_proof.get("reconciliation_ready") is not True
or physical_command_proof.get("observed_session_state") != "scan_over"
or physical_command_proof.get("active_operation_id")
!= start_operation_id
):
return False
record = physical_command_proof.get("record")
if not isinstance(record, Mapping):
return False
expected_binding = (
XgridsK1CompatibilityService._exact_control_binding_document(
verified_control
)
)
baseline = record.get("baseline_status")
response = record.get("application_response")
last_status = record.get("last_status")
last_status_valid = bool(
last_status is None
or (
isinstance(last_status, Mapping)
and last_status.get("session_state") == "scanning"
and last_status.get("project_bound") is True
and last_status.get("init_ready") is True
and last_status.get("mqtt_retained") is False
and last_status.get("system_error_code") is None
)
)
return bool(
expected_binding is not None
and isinstance(record.get("connection"), Mapping)
and dict(record["connection"]) == expected_binding
and record.get("operation_id") == start_operation_id
and record.get("acquisition_id") == acquisition_id
and record.get("action") == "start"
and record.get("stage") == "observing"
and record.get("resolution") is None
and record.get("publish_call_returned") is True
and record.get("qos2_completed") is True
and isinstance(record.get("packet_id"), int)
and not isinstance(record.get("packet_id"), bool)
and int(record["packet_id"]) > 0
and isinstance(baseline, Mapping)
and baseline.get("session_state") == "ready"
and baseline.get("project_bound") is False
and baseline.get("init_ready") is False
and baseline.get("mqtt_retained") is False
and baseline.get("system_error_code") is None
and isinstance(response, Mapping)
and response.get("operation_id") == start_operation_id
and response.get("action") == "start"
and response.get("success") is True
and last_status_valid
)
@staticmethod
def _matching_classified_prepared_stop_active(
physical_command_proof: Mapping[str, Any] | None,
@@ -30254,6 +30339,18 @@ class XgridsK1CompatibilityService:
if isinstance(terminal_control_proof, Mapping)
else None
)
accepted_start_scan_over_before_active = (
self._matching_accepted_start_scan_over_before_active(
physical_command_proof,
acquisition_id=current_acquisition_id,
start_operation_id=canonical_start_operation_id,
verified_control=(
terminal_verified_control
if isinstance(terminal_verified_control, Mapping)
else None
),
)
)
device_reported_scan_over_without_stop = bool(
current is not None
and current.control_mode == "plugin-commanded"
@@ -30262,7 +30359,8 @@ class XgridsK1CompatibilityService:
and isinstance(terminal_control_proof, Mapping)
and terminal_control_proof.get("state") == "failed"
and isinstance(terminal_control_failure, Mapping)
and terminal_control_failure.get("failed_phase") == "scanning"
and terminal_control_failure.get("failed_phase")
in {"initializing", "scanning"}
and terminal_control_failure.get("modeling_command_attempted") is True
and terminal_control_failure.get("stop_command_attempted") is False
and terminal_control_failure.get("diagnostic_snapshot_unavailable") == []
@@ -30281,15 +30379,18 @@ class XgridsK1CompatibilityService:
and physical_command_proof.get("runtime_bound") is True
and physical_command_proof.get("reconciliation_ready") is True
and physical_command_proof.get("observed_session_state") == "scan_over"
and self._matching_start_active_confirmed(
physical_command_proof,
acquisition_id=current_acquisition_id,
start_operation_id=canonical_start_operation_id,
verified_control=(
terminal_verified_control
if isinstance(terminal_verified_control, Mapping)
else None
),
and (
self._matching_start_active_confirmed(
physical_command_proof,
acquisition_id=current_acquisition_id,
start_operation_id=canonical_start_operation_id,
verified_control=(
terminal_verified_control
if isinstance(terminal_verified_control, Mapping)
else None
),
)
or accepted_start_scan_over_before_active
)
)
# Camera-only transport loss is supervised by the backend producer