Skip to content

About

Modbus Poll + SCADA на Rust/Tauri 2: Modbus TCP·RTU·ASCII, байт-точный round-trip .mbp/.mbw, 32 правила на строку, мимик-схемы, спарклайны, CSV-лог

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

mbSCADA icon — mascot girl with orange visor and headset, mbscada-rs badge

📡 mbSCADA

Modbus Poll, reimagined — in pure Rust.

A clean-room Modbus Poll reimplementation with a SCADA mode on top. Poll Modbus/TCP & RTU devices into live value tables, import real Modbus Poll .mbp/.mbw files byte-exactly, style any row from a 32-branch rule tree and build mimic diagrams — all in a ~6 MB single executable. No Modbus Poll sources were read, ever.

Release CI Tests License: MIT Rust Tauri Byte‑exact .mbp ASCII Listed on Remade

English · Русский 🌐 Project site: kostyk348.github.io/mbscada-rs

mbSCADA — live poll tables with quality badges, per-row sparklines and the alarm side panel

🧭 TL;DR

  • 🖥 Modbus Poll, but better. Polls 01/02/03/04, writes 05/06/0F/10, per-poll slave / base-0·1 address / scaling / engineering units — and every connection gets a live traffic log with per-response turnaround.
  • 🤝 Drop-in for your existing configs. Real Modbus Poll .mbp / .mbw files import by folder — and a byte-exact round-trip layer (write(parse(bytes)) == bytes, proven on real 10.5 files) keeps them intact.
  • 🎨 32 styled branches per row. The original gives you two colour rules; here every row gets a first-match rule tree with per-branch dynamic row text («0 → Закрыт, 1 → Открыт»).
  • 📈 Trends, alarms, CSV. Per-row sparklines, hi/hi‑hi/lo/lo‑lo alarms, blink styles — and a one-click CSV value log.
  • 👁 Parameter watch window. Pin the registers you actually watch — or computed tags — into a floating window with big live values, alarm colours and session min/max (v1.2).
  • 🧪 Slave simulator + typed values. The app can answer as a Modbus device — poll it with any master (or with itself): editable register grid, sine/ramp/noise auto-generation, TCP, RTU-over-TCP and — since v1.4 — a physical COM/RS-485 line (USB-RS485 adapter, 9600 8E1 and friends; line garbage never wedges the slave). Values display and write as real / int / uint mixed — float32/64 with all four word orders, 32/64-bit ints, hex/bin — with typed write modals and a per-cell dec → hex → bin display cycle (v1.3).
  • 🧮 Computed tags. Arithmetic on your tags — {T2 jacket} - {T1 reactor}, min(...), pow(...) — evaluated by the engine every scan and shown in their own table (v1.1).
  • 🗄 Journal + archive + diagnostics. Engine events (RX/WR/ERR/SYS) appended to a log file, configurable CSV historian (change-only or interval mode), per-connection/per-poll diagnostics with reconnect counters (v1.1).
  • 🌐 RU/EN built in. One switch in the toolbar flips the entire UI; docs ship in both languages.
  • ⚡ Fast & local. A multithreaded engine (mb-engine) drives all connections concurrently; no telemetry, no cloud, nothing leaves the machine.
  • 🎓 Tutorial + demo project. An interactive tour that highlights real UI elements and auto-advances once you've done the step — plus a "🚀 Demo project" button: the app raises its own slave simulator and polls itself, so live tables, rules, a computed tag and a dressed-up mimic come alive in 10 seconds (v1.5).
  • 🎛 Rules on the mimic + new widgets. Lamps, gauges, bars and values are colored by the fired rule branch (color/text/blink) — exactly like table rows; the "State" widget shows the branch text ("OPEN/CLOSED"), trends plot the history with min/max spans, sliders write a value into a register, computed tags became a widget source, and a "Rule for register…" button sits right in the widget settings (v1.5).
👀 30-second tour
Live tables + alarm panel
SCADA mimic + widgets
Parameter watch window

⬇ Download v1.5.2

Prebuilt installers for every platform — no Rust toolchain needed. Grab them from Releases:

Platform Files
Windows 10/11 x64 NSIS installer .exe · .msi
Linux x86_64 & aarch64 .AppImage (runs anywhere) · .deb
macOS Apple Silicon & Intel .dmg

Windows: WebView2 is preinstalled on Win10/11. Linux AppImage bundles its own WebKit. Every release is built automatically by GitHub Actions from a v* tag — five runners, one commit, all platforms.

✨ Feature tour

📊 Live tables

Live tables: colored alarm rows, per-row sparklines and the alarm side panel

  • Every poll is an independent view of the address space: own function, own register window, own scaling ×mult ÷div +offset, own 0/1 address base.
  • Values render in Modbus-Poll-style formats: u16 / i16 / hex16 / bin16 / ascii16 / u16(swapped) · u32 / i32 / hex32 · float32 in word orders ABCD / CDAB / BADC / DCBA · 64-bit u64 / i64 / f64.
  • Per-row sparklines keep the last 40 samples as inline SVG — the last buffer change blinks.
  • Click a row to write a value (FC 05/06 for bits, FC 16 for word arrays).

🚦 Rules & alarms

  • Threshold alarms exactly like Modbus Poll: hi / hi‑hi / lo / lo‑lo with messages.
  • Styling rules with up to 32 branches per row and operators > ≥ < ≤ = ≠, in-range / out-of-range, bit test.
  • First matching branch wins — the classic «Rule 1 over Rule 2» becomes a full priority list.
  • Dynamic row text per branch: the row label is replaced when a branch fires (state machines live in the table header).
  • Alarm side panel: active alarms surface as cards — severity, fired-at, live value, message — acknowledge one or all, cleared alarms drop to history with durations, optional beep, and a click jumps to the table row.

👁 Parameter watch window (v1.2)

Floating parameter watch window with big live values, alarm colors and session min/max

  • Pin the parameters you actually watch — any register from any poll, or computed tags — into a floating window over the workspace (👁 Watch in the toolbar).
  • Big live values in engineering units, coloured by the rule tree (alarm fg/bg carry over from the table row), session min / max per card, quality and «no link» markers.
  • The pinned set is stored in the project (shared with Save/Open); the window position is remembered per workstation. Double-click a card to give it a custom caption, ✕ unpins, ⟲ resets min/max, clicking a value jumps to the table row.

🧪 Slave simulator & typed values (v1.3)

In-app slave simulator: port, framing, editable register grid with typed view and auto-generation

📖 Full simulator guide (RU): docs/guide-slave-ru.md — quick start, connecting masters, data types, dec/hex/bin display, recipes and troubleshooting. An English version is planned.

  • Both sides of the wire in one app. The new Slave simulator tab serves coils / discrete / holding / input registers over Modbus TCP, RTU-over-TCP and, since v1.4, a physical serial line (USB-RS485 adapter: port, baud, parity, data/stop bits) — point any master at localhost:10502, wire it to an RS-485 bus, or poll it with mbSCADA itself.
  • Live register grid with a typed view (u16 / i16 / hex / u32 / i32 / float CDAB·ABCD): edit a cell and the slave’s data model changes immediately; checkboxes for bit areas; the raw register bits are shown next to the typed value.
  • Auto-generation (sine / ramp / noise with amplitude, base and period) animates the selected range, so alarm rules, trends and mimics have something realistic to chew on.
  • Typed values everywhere. Every poll carries a data type — the quick selector sits right on the table card (one click after the .mbp import). Typed write modals encode the value into registers for you: float → two words with the right word order, i16 → two’s complement, hex/bin inputs accepted as 0x…/0b….
  • Per-cell display: right-click any value to cycle dec → hex → bin (per row), or set the default for the whole poll.
  • UI overhaul under the hood: tables, mimic and the journal now update in place instead of rebuilding the DOM every 300 ms — no more lag and no more double-clicks torn apart by a re-render.

🗺 SCADA mode (mimic diagrams)

Editor with lamps, gauges, bars, live values and toggle-write buttons bound to registers — every widget configurable by double-click… plus the alarm panel and traffic log on the right

Modbus Poll has no SCADA mode. That is the point of mbSCADA.

🧮 Computed tags, journal, archive & diagnostics (v1.1)

  • Computed (virtual) tags: a safe arithmetic evaluator in the engine — {tag} references, p<poll>:<addr> aliases, + - * / % ^, functions min / max / avg / abs / sqrt / round / floor / ceil / pow. Results appear in their own table above the polls (with units and error messages in place), and are archived to CSV together with the live tags.
  • Event journal to file: the engine appends every RX / WR / ERR / SYS line (with full timestamps) to the log file configured in «Журнал и архив» — a permanent record of the exchange alongside the in-app log.
  • Configurable CSV archive: change-only mode (a row when a value changes) or «all tags by period» mode; the file is stored in the project and automatically resumes on start.
  • Diagnostics panel: per connection — TX/RX, errors/timeouts, reconnects, last/avg turnaround, time since the last successful exchange, last error; per poll — ok/err counters and its own turnaround.

🤝 Modbus Poll compatibility

  • Import of .mbp (single window) and .mbw (workspace with the window list) — one by one or by folder.
  • Byte-exact round-trip (mbp_doc): the file is segmented (head / row records / closing marker) and reassembled bit-for-bit; editing an alias touches nothing else. Verified byte-exactly against a private real-file corpus produced by Modbus Poll 10.5 (7 files, RU aliases, UTF‑16 markers); CI runs the same test on a public synthetic corpus.
  • Format, multiplier, address base, aliases and colours carry over into polls; imported polls bind to your own connections (host:port match first, else the first one) — no connections are silently pulled from the files. Each connection carries a default slave ID that its polls inherit (a poll may still override it).
📐 Real corpus layout (reverse-engineered)
[head]                     magic v4=7000 (v5=10010), IP marker (v5), [144][func][addr][qty]
[row record] × qty         marker FF FE FF + len + UTF-16LE alias → PAD 55555555
                           + 6× colour u32 (FF000000 AVG) + zeros
[last row + settings]      the last row's gap holds the settings blob & tail
                           [period][slave][1][0][0][…]
[closing marker]           final empty marker FF FE FF 00 + trailer bytes

🚀 Getting started

Install

Download an installer for your OS from Releases (see the table above), install — and run mbSCADA.

Build from source

Requirements: Rust 1.85+, Windows (WebView2 is preinstalled on Win10/11), or Linux with libudev-dev pkg-config libwebkit2gtk-4.1-dev for GUI work.

git clone https://github.com/kostyk348/mbscada-rs.git
cd mbscada-rs
cargo test                # 68 engine/proto/format tests

# demo slave (no hardware needed): serves registers on 127.0.0.1:502
cargo run -p mb-sim --example demo_server -- 502

# the app (Tauri 2), raw binary
cargo build --release -p mbscada
# → target/release/mbscada

# or full installers for your current OS
cargo install tauri-cli --version '^2'
cargo tauri build

Launch mbSCADA, «Импорт папки…» your .mbp folder and hit Старт — real Modbus Poll windows appear as polls and start flowing.

🏗 Architecture

┌────────────────────────────────────────────────────────────────────┐
│                    Tauri 2 desktop shell (Rust)                    │
│  src-tauri: dialogs, project JSON, CSV append, engine restarts     │
├────────────────────────────────────────────────────────────────────┤
│  UI (vanilla JS)                                                   │
│  tables · rules (32) · SCADA editor · watch window · traffic log   │
├────────────────────────────────────────────────────────────────────┤
│  crates/                                                           │
│  mb-proto    PDU encode/decode · MBAP · RTU+CRC · ASCII ':'+LRC     │
│  mb-format   .mbp/.mbw parser → lossless MbpDoc → semantic Table    │
│  mb-engine   multithreaded poller: TCP · RTU-serial · RtuOverTcp    │
│              · Ascii-serial · AsciiOverTcp, rules, alarms, trends  │
│  mb-sim      slave simulator (+ demo_server example)               │
└────────────────────────────────────────────────────────────────────┘

🗺 Roadmap

  • ✅ Modbus/TCP, RTU, RTU-over-TCP transports with per-connection traffic log (v0.1)
  • ✅ Import .mbp/.mbw by file and by folder (v0.1)
  • ✅ 32-branch styled rules + dynamic row text — UI and engine (v0.2)
  • ✅ Display formats through 64-bit: hex32 / ascii16 / u16‑swapped / u64 / i64 / f64 (v0.3)
  • ✅ Byte-exact .mbp round-trip on a real corpus (v0.4)
  • ✅ Modbus ASCII framing + ASCII serial & over-TCP transports (v0.4)
  • ✅ Per-row sparklines + CSV value log (v0.4)
  • ✅ In-place editing of connections / polls / rules; per-connection default slave ID; imports bound to your own connections (v1.0)
  • ✅ Prebuilt release bundles: Windows x64, Linux x86_64 + aarch64, macOS Intel + Apple Silicon (v1.0)
  • ✅ Alarm side panel (ack, history, sound, jump-to-row) + SCADA gauge / toggle-write widgets (v1.1)
  • ✅ One-click RU/EN UI switch, bilingual docs, refreshed screenshots (v1.1)
  • ✅ Computed tags: safe expression engine + own table + editor (v1.1)
  • ✅ Engine event journal to a log file; configurable CSV historian (change-only / interval) that resumes on start (v1.1)
  • ✅ Diagnostics panel: per-poll ok/err stats, reconnect counters, last-success age (v1.1)
  • ✅ Fix: SCADA gauge colored arc overflowed the widget border (v1.1)
  • ✅ Fix: SCADA gauge arc swept the wrong way above half-scale — SVG large-arc flag on a ≤180° sweep (v1.5.1)
  • ✅ Production-grade alarm panel: colored severity chips (CRIT/HIGH/LOW) next to the value, severity-first sorting, re-alert on level escalation, unacknowledged-critical dot pulse, info level is silent (v1.5.2)
  • ✅ Fix: Windows shortcut kept the old icon after an in-place upgrade — the installer now flushes the shell icon cache (SHChangeNotify via an NSIS hook) (v1.5.2)
  • ✅ Parameter watch window: floating panel of pinned registers / computed tags — big live values, alarm colours, session min/max, custom captions, jump-to-row (v1.2)
  • ✅ In-app slave simulator: Modbus TCP / RTU-over-TCP device emulation with an editable register grid, typed view and sine/ramp/noise auto-generation (v1.3)
  • ✅ Typed values: quick data-type selector on every table card, typed write modals (float / 32-bit word orders, hex/bin inputs), per-cell dec → hex → bin display (v1.3)
  • ✅ Fix: engine regs_per_value ignored f32 word orders — float polls produced wrong rows (v1.3)
  • ✅ UI performance: in-place table/mimic/journal updates instead of full DOM rebuilds — double-clicks no longer torn by the 300 ms re-render (v1.3)
  • ⬜ .mbp writer in the UI — «Save as Modbus Poll» (round-trip layer is already engine-side)
  • ⬜ Per-row trend window (bigger than a sparkline)

⁇ FAQ

Is this a Modbus Poll rip-off? No. This is a clean-room implementation: the wire protocol is public spec, and the .mbp layout was learned from byte-level analysis of files produced by Modbus Poll 10.5 — no proprietary source code was touched.

What "byte-exact round-trip" means for me? Your Modbus Poll files go in, everything else comes back identical. mbSCADA can edit aliases without regenerating the whole file, so unedited bytes stay exactly as Modbus Poll wrote them.

Does it talk to my devices today? TCP / RTU / RTU-over-TCP are production paths with integration tests. ASCII framing and its serial / over-TCP transports are implemented and unit-tested; wire-side integration testing on real devices is on the roadmap.

Why Rust? One executable, no runtime, memory-safe poller — and the whole engine is testable headlessly (see cargo test).

🤝 Contributing

Issues and PRs welcome. The engine is test-first: crates/mb-engine, crates/mb-format / crates/mb-proto all have unit suites covering Tauri-free paths — start there.

mbSCADA mascot

mbSCADA — Modbus Poll for people who also want SCADA.

Download · Build it · Roadmap · License (MIT)

About

Modbus Poll + SCADA на Rust/Tauri 2: Modbus TCP·RTU·ASCII, байт-точный round-trip .mbp/.mbw, 32 правила на строку, мимик-схемы, спарклайны, CSV-лог

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages