fix(sim): try OPC UA write first in simulate_run_feedback, fallback to cache patch
Instead of always patching the local cache, first attempt to write the RUN point value through the normal OPC UA path. If the proxy accepts the write, write_point_values_batch already emits PointNewValue locally so no extra work is needed. Only fall back to direct cache patching when the write is rejected. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b28ac23520
commit
3a8a2c1389
|
|
@ -44,8 +44,13 @@ pub async fn send_pulse_command(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simulate RUN signal feedback after a command when SIMULATE_PLC=true.
|
/// Simulate RUN signal feedback after a command when SIMULATE_PLC=true.
|
||||||
/// Looks up the equipment's "run" role point and writes a synthetic Good-quality
|
///
|
||||||
/// monitor entry, then broadcasts PointNewValue over WebSocket.
|
/// Strategy:
|
||||||
|
/// 1. Try writing the desired value to the RUN point via the normal OPC UA write path.
|
||||||
|
/// If the proxy accepts the write, `write_point_values_batch` will emit a local
|
||||||
|
/// `PointNewValue` event that updates the cache and WebSocket automatically.
|
||||||
|
/// 2. If the write is rejected (proxy has no write target or returns an error),
|
||||||
|
/// fall back to directly patching the local monitor cache and broadcasting over WS.
|
||||||
pub async fn simulate_run_feedback(state: &AppState, equipment_id: Uuid, run_on: bool) {
|
pub async fn simulate_run_feedback(state: &AppState, equipment_id: Uuid, run_on: bool) {
|
||||||
let role_points =
|
let role_points =
|
||||||
match crate::service::get_equipment_role_points(&state.pool, equipment_id).await {
|
match crate::service::get_equipment_role_points(&state.pool, equipment_id).await {
|
||||||
|
|
@ -60,6 +65,57 @@ pub async fn simulate_run_feedback(state: &AppState, equipment_id: Uuid, run_on:
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Determine the write value based on the current known value_type for the point.
|
||||||
|
let write_json = {
|
||||||
|
let guard = state
|
||||||
|
.connection_manager
|
||||||
|
.get_point_monitor_data_read_guard()
|
||||||
|
.await;
|
||||||
|
match guard
|
||||||
|
.get(&run_point.point_id)
|
||||||
|
.and_then(|m| m.value_type.as_ref())
|
||||||
|
{
|
||||||
|
Some(crate::telemetry::ValueType::Int) | Some(crate::telemetry::ValueType::UInt) => {
|
||||||
|
serde_json::json!(if run_on { 1 } else { 0 })
|
||||||
|
}
|
||||||
|
_ => serde_json::json!(run_on),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try writing to the proxy server first.
|
||||||
|
let write_ok = match state
|
||||||
|
.connection_manager
|
||||||
|
.write_point_values_batch(crate::connection::BatchSetPointValueReq {
|
||||||
|
items: vec![crate::connection::SetPointValueReqItem {
|
||||||
|
point_id: run_point.point_id,
|
||||||
|
value: write_json,
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(res) => res.success,
|
||||||
|
Err(e) => {
|
||||||
|
tracing::debug!("simulate_run_feedback: write attempt failed: {}", e);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if write_ok {
|
||||||
|
// write_point_values_batch already emitted PointNewValue; nothing more to do.
|
||||||
|
tracing::info!(
|
||||||
|
"simulate_run_feedback: wrote run={} for equipment={} via OPC UA",
|
||||||
|
run_on,
|
||||||
|
equipment_id
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: patch the local cache and push over WebSocket.
|
||||||
|
tracing::debug!(
|
||||||
|
"simulate_run_feedback: OPC UA write rejected, falling back to cache patch for equipment={}",
|
||||||
|
equipment_id
|
||||||
|
);
|
||||||
|
|
||||||
let (value, value_type, value_text) = {
|
let (value, value_type, value_text) = {
|
||||||
let guard = state
|
let guard = state
|
||||||
.connection_manager
|
.connection_manager
|
||||||
|
|
@ -118,9 +174,9 @@ pub async fn simulate_run_feedback(state: &AppState, equipment_id: Uuid, run_on:
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"simulate_run_feedback: equipment={} run={}",
|
"simulate_run_feedback: cache-patched run={} for equipment={}",
|
||||||
equipment_id,
|
run_on,
|
||||||
run_on
|
equipment_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue