Commit Graph

13 Commits

Author SHA1 Message Date
caoqianming 7ae952f93e feat(event): add RemLocal/RemRecovered events for REM-triggered auto-stop
When any equipment's REM signal switches to local mode, fire a dedicated
`unit.rem_local` event (with unit + equipment context) and record it to
the event log. Also fire `unit.rem_recovered` when all REM signals return
to remote. AutoControlStopped is still fired alongside RemLocal when
auto was running at the time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 10:39:17 +08:00
caoqianming 4227747852 feat(control): stop auto-control and disable buttons when REM goes local
- Add `rem_local: bool` to UnitRuntime; set true when any equipment's
  REM signal is false with good quality
- Engine check_fault_comm: stop auto-control and fire AutoControlStopped
  when any equipment switches to local mode
- Block start-auto when rem_local (backend + error message)
- Frontend: disable Start Auto button in units/ops views when rem_local
- Frontend: disable equipment Start/Stop buttons in config view when
  unit's rem_local is true

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 10:30:43 +08:00
caoqianming 9f833f3a5e fix(control): refresh unit mappings on config changes 2026-03-26 13:30:14 +08:00
caoqianming 00c16ae3d7 fix(unit): block auto control start when fault is active or unacknowledged
Prevent starting unit auto control while fault_locked or manual_ack_required,
enforcing that faults must be manually acknowledged before resuming automation.
Also disable the Start Auto button in the frontend with descriptive tooltips.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 10:54:10 +08:00
caoqianming 5a481a5eb3 refactor(simulate): consolidate all simulation code into simulate.rs
Moved simulate_run_feedback from command.rs into simulate.rs where it
reuses patch_signal. command.rs now only contains real PLC command logic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 10:17:44 +08:00
caoqianming b3f92867bc fix(engine): fix supervisor restart, deduplicate helpers, fix notify race
- engine.rs: replace HashSet<Uuid> with HashMap<Uuid, JoinHandle> in
  supervise(); use is_finished() to detect exited tasks so units that
  are disabled then re-enabled get a new task on next 10s scan
- control/mod.rs: extract shared monitor_value_as_bool (using the more
  complete validator version that includes "yes"); remove duplicate
  copies from engine.rs and validator.rs
- runtime.rs: fix get_or_create_notify TOCTOU by using entry API
  instead of read-drop-write pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 09:08:25 +08:00
caoqianming dd0e782450 fix(engine): push WS immediately on notify wake-up
When auto_enabled or fault_locked changes externally, the engine task
wakes via notify but previously only pushed WS on the next state
transition (potentially seconds later). Now push the fresh runtime
immediately in the notify.notified() arm so the frontend reflects
the change without delay.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 08:44:46 +08:00
caoqianming 8c1b7b636d refactor(engine): replace 500ms ticker with per-unit event-driven tasks
- Engine now spawns one async task per enabled unit (supervised every 10s)
- wait_phase uses sleep_until + select! for precise timing; 500ms fault-tick
  runs inside each phase so fault/comm is still checked promptly
- WS UnitRuntimeChanged pushed only on state transitions, not every tick
- ControlRuntimeStore gains notify_unit/get_or_create_notify for instant
  wake-up when handlers change auto_enabled or fault_locked
- UnitRuntime: remove last_tick_at, current_run/stop/distributor_elapsed_sec;
  add display_acc_sec (snapshot at transition, avoids mid-cycle jitter)
- accumulated_run_sec now increments by exact run_time_sec*1000 per cycle
- unit.state_changed events no longer written to DB (too frequent)
- Frontend: show display_acc_sec instead of accumulated_run_sec
- styles: event-card flex-shrink:0 fixes text overlap under flex column

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 08:33:00 +08:00
caoqianming 0077a4ad90 fix(engine): stop coal_feeder before starting distributor on acc_time trigger
When accumulated_run_sec reaches acc_time_sec, the coal feeder must be stopped
before entering DistributorRunning state. Previously the feeder was left running
while the distributor also ran, which is incorrect per the control spec.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:00:24 +08:00
caoqianming b832d98196 fix(control): block manual commands during auto, fix engine stop_time=0 bug, add sim feedback
- validator: reject equipment start/stop when unit auto_enabled
- engine: fix stop_time_sec==0 causing infinite Stopped state (never starts)
- engine: call simulate_run_feedback after auto commands when SIMULATE_PLC=true
- command: extract simulate_run_feedback to shared module (was private in handler)
- web: disable Start/Stop buttons when unit auto is active; sync on WS runtime update

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 12:37:43 +08:00
caoqianming b5a8d6a71d fix(engine): correct fault equipment ID lookup and all_roles data structure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 15:03:26 +08:00
caoqianming 459bb49c65 feat(control): implement state machine engine with fault/comm monitoring
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 14:53:59 +08:00
caoqianming 97d2f6ebf8 feat(control): add manual equipment pulse commands 2026-03-24 11:16:50 +08:00