Безопасное завершение калибровки при отключении K1
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user