OrangeHorse manufactures industrial sensors. Most of them speak Modbus over RS-485. To test those sensors โ to verify register maps, measure response latency, stress-test bus timing, and capture the raw bytes flying across the wire โ we needed a diagnostic tool. Not a simple Modbus client. A proper industrial diagnostic IDE.
We surveyed the Rust ecosystem. There are Modbus crates. Good ones. But none of them met the four hard requirements our diagnostic tool demanded. Here is why we built oms-modbus, what the requirements were, and where we ended up.
The Four Requirements
1. Three Protocols, One API
Our sensors use Modbus RTU over RS-485. But the diagnostic tool itself needs to communicate over TCP too โ because modern SCADA gateways bridge RS-485 to Ethernet, and a diagnostic tool that can only talk serial is useless in a control room.
Most Rust Modbus crates do TCP or RTU. Not both. And certainly not ASCII, which older Chinese industrial equipment still uses. We needed a single ModbusClient trait that worked across all three protocols, because a diagnostic engineer shouldn't have to rewrite their tool for each transport layer.
2. Passive Bus Monitoring
This was the hardest requirement. A diagnostic tool needs to observe without participating โ like a hardware logic analyzer clipped onto an RS-485 bus. It should see every byte that goes across the wire: the request from a PLC, the sensor's response, the CRC bytes, the silent gaps between frames.
Most Modbus libraries are designed as active participants. The client sends a request, the library decodes the response. There is no concept of "just watching." We needed a WireTap โ a passive observer that sits at the I/O boundary and records everything, with wall-clock timestamps precise to the microsecond.
3. Spec-Compliant Bus Timing
The Modbus Serial Line Protocol specification (V1.02, ยง1.4) requires a minimum 3.5-character silent interval between frames. At baud rates above 19200, this becomes a fixed 1.75 milliseconds. Not "approximately" โ exactly. Below 19200 baud, the interval is proportional: 3.5 ร 11 bits / baud rate.
Why does this matter? Because if you transmit too quickly โ if your library doesn't enforce the silent interval โ the receiving device might see two frames merge into one. On a loaded RS-485 bus with dozens of sensors, missing the 3.5T rule causes frame collisions, CRC errors, and data that looks correct but isn't. Most Modbus libraries simply ignore this requirement and rely on the operating system's serial buffer timing. That works... until it doesn't.
4. Zero Panics in Production
Our diagnostic tools run in industrial environments. A Rust panic in a field tool means a technician 200 km from the office staring at a crash screen. We mandated zero .unwrap() calls in production code. Every error path must be explicit. Every buffer allocation must be checked. Every type conversion must handle overflow.
This is not a performance requirement โ it's a reliability requirement. Modbus is a protocol that can produce malformed frames (noisy RS-485 lines, ground loops, a sensor that implements the spec slightly wrong). The library must handle garbage input gracefully. It may return an error, but it may not terminate the process.
Why Rust?
Because the diagnostic IDE we are building needs three things simultaneously:
- Performance โ decoding Modbus frames at wire speed, with CRC validation, on a live bus
- Safety โ running for hours without memory corruption, use-after-free, or buffer overflows
- Portability โ the same library running on a Windows laptop in a control room, a Linux gateway on a factory floor, and eventually embedded ARM diagnostic hardware
Rust is the only language that delivers all three without compromise. C gives you 1 and 3. C# gives you 2 and 3. Rust gives you all of them โ and the async ecosystem (Tokio) means the same library handles both blocking serial I/O and concurrent TCP connections.
What We Built
OMS Modbus is now a 0.2.0 preview release with:
- 440+ tests, zero failures, zero unwrap calls in production paths
- A single
ModbusClienttrait across TCP, RTU, and ASCII - A passive
WireTapthat records bus traffic with microsecond ISO 8601 timestamps - Bus timing enforcement that respects the 3.5T spec at all baud rates
- The leanest possible dependency tree: 8 runtime crates, no transient dependencies
The library talks to every Modbus sensor in OrangeHorse's product line โ from the OHTS1020 soil sensor to the OHTS1070 weather station. It is also protocol-compatible with Modbus devices from every other vendor.
The Open-Source Decision
We considered keeping oms-modbus internal. It is, after all, the communication layer of a commercial diagnostic product. But two arguments pushed us toward open source:
First, the Modbus ecosystem has a quality problem. Most open-source Modbus libraries are abandoned, incomplete, or subtly broken. Engineers who integrate sensors into larger systems waste weeks debugging protocol edge cases that a good library should handle from day one. By releasing oms-modbus under MIT/Apache-2.0, we raise the baseline for everyone โ including our own customers, who can use the library to integrate our sensors into their Rust-based systems.
Second, open-source libraries attract better bug reports. One user integrating Modbus on an obscure ARM Cortex-M4 discovered a timing edge case we never hit in our x86 test suite. That bug report made the library more robust for our diagnostic tool too. The community stress-tests your code in ways no internal QA process can match.
What Comes Next
Version 0.2.0 is a preview. The API may evolve based on community feedback. We are actively working on:
- Modbus diagnostic CLI โ command-line scanning, register inspection, bus health checks
- Python bindings โ wrapping the Rust core for Python-based SCADA and lab automation
- Embedded targets โ
no_stdsupport for bare-metal diagnostic hardware
If you build industrial tools that speak Modbus, try oms-modbus and open an issue on GitHub. Every bug report, feature request, and pull request makes the library better for the entire IIoT community.
OrangeHorse has been designing industrial environmental sensors since 2017. Contact our engineering team to discuss Modbus integration, custom register maps, or diagnostic tool requirements.