Add persistent material integration state
This commit is contained in:
@@ -53,9 +53,13 @@ class MaterialConsumptionIntegrator:
|
||||
are always UTC.
|
||||
"""
|
||||
|
||||
def __init__(self, config: MaterialIntegratorConfig) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
config: MaterialIntegratorConfig,
|
||||
initial_state: MaterialIntegrationState | None = None,
|
||||
) -> None:
|
||||
self._config = config
|
||||
self._state = MaterialIntegrationState()
|
||||
self._state = initial_state or MaterialIntegrationState()
|
||||
|
||||
@property
|
||||
def config(self) -> MaterialIntegratorConfig:
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
"""Serialization helpers for persistent material-integration state."""
|
||||
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from production_analytics.calculations.material_consumption import (
|
||||
MaterialIntegrationState,
|
||||
)
|
||||
|
||||
|
||||
def material_state_to_dict(state: MaterialIntegrationState) -> dict[str, object]:
|
||||
"""Convert integration state to a JSON-serializable dictionary."""
|
||||
return {
|
||||
"cumulative_consumption_kg": state.cumulative_consumption_kg,
|
||||
"integrated_running_seconds": state.integrated_running_seconds,
|
||||
"last_processed_timestamp": (
|
||||
state.last_processed_timestamp.astimezone(UTC).isoformat()
|
||||
if state.last_processed_timestamp is not None
|
||||
else None
|
||||
),
|
||||
"last_material_rate_kg_per_hour": state.last_material_rate_kg_per_hour,
|
||||
"last_gate_value": state.last_gate_value,
|
||||
"integration_active": state.integration_active,
|
||||
}
|
||||
|
||||
|
||||
def material_state_from_dict(data: dict[str, object]) -> MaterialIntegrationState:
|
||||
"""Restore integration state from a JSON-compatible dictionary."""
|
||||
raw_timestamp = data["last_processed_timestamp"]
|
||||
|
||||
timestamp = (
|
||||
datetime.fromisoformat(str(raw_timestamp)).astimezone(UTC)
|
||||
if raw_timestamp is not None
|
||||
else None
|
||||
)
|
||||
|
||||
return MaterialIntegrationState(
|
||||
cumulative_consumption_kg=float(data["cumulative_consumption_kg"]),
|
||||
integrated_running_seconds=float(data["integrated_running_seconds"]),
|
||||
last_processed_timestamp=timestamp,
|
||||
last_material_rate_kg_per_hour=(
|
||||
float(data["last_material_rate_kg_per_hour"])
|
||||
if data["last_material_rate_kg_per_hour"] is not None
|
||||
else None
|
||||
),
|
||||
last_gate_value=(
|
||||
float(data["last_gate_value"])
|
||||
if data["last_gate_value"] is not None
|
||||
else None
|
||||
),
|
||||
integration_active=bool(data["integration_active"]),
|
||||
)
|
||||
|
||||
|
||||
def save_material_state(path: str, state: MaterialIntegrationState) -> None:
|
||||
"""Persist integration state as UTF-8 JSON."""
|
||||
import json
|
||||
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(material_state_to_dict(state), f, indent=2)
|
||||
|
||||
|
||||
def load_material_state(path: str) -> MaterialIntegrationState:
|
||||
"""Load integration state from UTF-8 JSON."""
|
||||
import json
|
||||
|
||||
with open(path, encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
return material_state_from_dict(data)
|
||||
Reference in New Issue
Block a user