Commit Graph

41 Commits

Author SHA1 Message Date
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 45b2317ee8 feat(docs): add README.md button opening shared doc drawer
Reuses the existing API.md drawer for README; switching between
docs reloads content and updates the drawer title. Backend serves
README.md via /api/docs/readme-md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 16:27:51 +08:00
caoqianming 68b4eec610 fix(logs): follow rotated log files in stream 2026-03-26 13:41:36 +08:00
caoqianming 9f833f3a5e fix(control): refresh unit mappings on config changes 2026-03-26 13:30:14 +08:00
caoqianming dbfa673468 fix(control): validate unit timing configuration 2026-03-26 13:19:10 +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 0545388b85 feat(unit): embed equipments with role_points in unit list and get responses
Unit list and single-unit endpoints now include per-unit equipment list
with signal-role points and monitor data, consistent with unit detail.
Uses batch queries to avoid N+1 DB calls.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 10:26:45 +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 9d787e452b feat(events): use Chinese messages with entity names
Event messages are now stored and displayed in Chinese. Names/codes are
resolved via lightweight DB lookups in persist_event_if_needed (entities
still exist at processing time). SourceDelete passes the name explicitly
since the source is deleted before the async event is processed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 09:53:26 +08:00
caoqianming e304fd342d feat(ops): embed role_points in equipment list, remove unit detail API calls
Equipment list response now includes signal-role points with monitor data,
so the ops view can render signal dots directly from state.equipments
without fetching /api/unit/:id/detail.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 09:34:59 +08:00
caoqianming 08add0d087 refactor(api): embed runtime in unit list/get/detail responses
Remove the standalone GET /api/unit/runtimes endpoint in favour of
embedding runtime directly in existing responses:
- GET /api/unit          → each item now includes `runtime` field
- GET /api/unit/:id      → returns UnitWithRuntime
- GET /api/unit/:id/detail → UnitDetail now includes `runtime`

runtime is null when the engine has not yet initialised the unit.
Frontend loadUnits() reads the embedded runtime field to populate
state.runtimes — one request instead of two.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 09:18:14 +08:00
caoqianming 42cdbbc0cc fix(web): fetch all unit runtimes on page load
Root cause: state.runtimes was empty after refresh because the engine
only pushes UnitRuntimeChanged on state transitions — if the engine
is mid-wait-phase, no push occurs and badges show OFFLINE.

Fix: add GET /api/unit/runtimes batch endpoint (returns all known
runtimes as { unit_id: UnitRuntime }) and call it in parallel with
the unit list fetch inside loadUnits(), so runtime badges are correct
immediately after page load.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 09:11:47 +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 a8d36578fa feat: ws backoff, signal dots, dom cap, unwrap fix, batch size limit
- logs.js: WS reconnect exponential backoff 1s→2s→4s…30s
- ops.js: replace badge+text signal display with red/green/yellow dots
  (sig-on=green, sig-fault=red, sig-warn=yellow, gray=off)
- events.js: cap live-prepended event cards at 100 DOM nodes
- source.rs: fix attach_children unwrap() → Option<TreeNode>/filter_map
- point.rs: add max=500 validation to all batch Vec<Uuid> fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 16:37:14 +08:00
caoqianming 757d6f9a3a feat(control): batch start/stop auto control for all enabled units
Backend:
- POST /api/control/unit/batch-start-auto — starts auto on all enabled
  units that are not fault/comm locked and not already running auto
- POST /api/control/unit/batch-stop-auto — stops auto on all units

Frontend (ops view):
- Add "全部启动" / "全部停止" buttons in the unit sidebar header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:05:23 +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 989a0286e9 feat(sim): simulate RUN signal feedback when SIMULATE_PLC=true
After a successful start/stop command, write run=true/false directly
into the point monitor cache and broadcast PointNewValue via WebSocket.
Gated by SIMULATE_PLC=true env var; real OPC-UA values override it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 11:08:38 +08:00
caoqianming 4076f6575e feat(web): dual-view UI — 运维/配置 tab, ops equipment cards with live signal values
- Add 运维/配置 tab switch; grid-ops / grid-config layout classes
- New ops-panel: unit sidebar + equipment card grid (REM/RUN/FLT signals)
- All equipment cards shown by default; unit click acts as filter
- Signal cells seed from point_monitor cache on render, then update via WS PointNewValue
- New log-stream-panel: SSE realtime log stream, active only in config view
- Backend: get_unit_detail now includes point_monitor (current value) in each point

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 10:25:20 +08:00
caoqianming 2732238be7 feat(api): add GET /api/unit/{id}/detail with nested equipment and points
Returns unit with its equipments, each embedding their bound points.
Uses 2 queries (equipment list + points via ANY) to avoid N+1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 08:37:09 +08:00
caoqianming 856c888667 feat(control): add start-auto, stop-auto, ack-fault, runtime endpoints 2026-03-24 14:56:16 +08:00
caoqianming 628553f2b8 refactor(control): extract pulse command helper to control/command.rs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 14:31:37 +08:00
caoqianming f7dc39a70a fix: point bind bug 2026-03-24 13:39:45 +08:00
caoqianming 97d2f6ebf8 feat(control): add manual equipment pulse commands 2026-03-24 11:16:50 +08:00
caoqianming 4e3d325437 feat(control): add unit and event foundation 2026-03-24 10:20:23 +08:00
caoqianming fec7b60d6b feat(web): reorganize equipment layout and point flows 2026-03-23 12:49:26 +08:00
caoqianming 06ace5e67d refactor(app): split services and web modules 2026-03-23 11:31:38 +08:00
caoqianming 8be82e372e feat(point): add equipment metadata scaffolding 2026-03-23 10:38:20 +08:00
caoqianming a691f07e8e feat(web): add API.md drawer preview 2026-03-20 19:00:46 +08:00
caoqianming 920e37f759 feat(web): add inline point chart panel 2026-03-20 10:54:20 +08:00
caoqianming f33d989905 perf(point): batch point creation queries 2026-03-17 08:25:04 +08:00
caoqianming 7e6c7a7e4c feat(reconnect): add retry backoff and manual reconnect 2026-03-17 08:15:54 +08:00
caoqianming 503aefc4cb refactor(event): rename ReloadEvent to AppEvent and split event channels
Clarify event semantics by renaming ReloadEvent to AppEvent and route control vs telemetry traffic through dedicated channels. This keeps control events isolated from high-frequency PointNewValue updates while preserving the existing send() call pattern.

Made-with: Cursor
2026-03-13 14:44:30 +08:00
caoqianming 5406568969 fix: harden event handling and source safety
Improve runtime resilience by bounding the reload event queue and processing telemetry updates without per-point spawned tasks. Also reduce security risk by sanitizing source responses, avoiding internal error detail leaks, and standardizing write-key configuration with backward compatibility.

Made-with: Cursor
2026-03-13 14:22:16 +08:00
caoqianming 6f215162a3 feat(page): add page table and CRUD handlers 2026-03-11 13:54:14 +08:00
caoqianming efed6aa816 feat: add page 2026-03-11 13:23:05 +08:00
caoqianming 1374abe550 feat(log): add file-based log APIs and switch file logs to JSON 2026-03-09 14:47:19 +08:00
caoqianming d156108148 feat: 为 get_tag_list 接口添加分页功能 2026-03-04 15:19:39 +08:00
caoqianming 606b57eb73 refactor: 优化点位列表查询功能 2026-03-04 13:39:06 +08:00
caoqianming cc7142e556 refactor: 统一使用 PointMonitorInfo,移除 WsPointMonitorInfo 2026-03-03 16:51:18 +08:00
caoqianming c88a0b2398 修复编译错误和警告: 添加缺失的导入,移除未使用的导入和变量 2026-03-03 13:39:58 +08:00
caoqianming 44f4a794d3 feat: 软件第一个版本 2026-03-03 13:32:05 +08:00