Integration — Modbus TCP (edge north-bound)¶
Public · Status: ⬜ planned
1. Purpose¶
Let plant SCADA / PLC systems read live results directly from the edge node over Modbus TCP — no cloud round-trip. Best for control rooms and automation that already speak Modbus.
2. When to use it¶
- You have a PLC / SCADA on the same plant network as the BulkScanPro edge node.
- You want the latest measurement + occupancy/health as registers, in real time.
3. How it works¶
The edge node exposes a Modbus TCP server; your PLC is the client (polls registers). Outbound-only cloud sync is unaffected — this is a local read surface.
graph LR
PLC[PLC / SCADA] -->|Modbus TCP poll| EDGE[BulkScanPro edge node]
4. Register map (🔄 proposed)¶
The node listens on TCP 502, unit id 1. The map is grouped into discrete inputs (read-only
bits, 2x) and input registers (read-only 16-bit words, 3x). Multi-word values are uint32, big-
endian (high word first); scaled integers avoid floats. Addresses are 0-based protocol addresses.
Discrete inputs (read with FC 02)
| Addr | Name | Meaning |
|---|---|---|
10001 |
segment_occupied |
a vehicle is currently over the segment |
10002 |
convoy_active |
a convoy passage is in progress |
10003 |
node_healthy |
edge node up and self-checks passing |
10004 |
sensors_ok |
both LiDARs reachable and streaming |
10005 |
cloud_sync_ok |
last cloud sync within threshold |
Input registers (read with FC 04)
| Addr | Name | Type | Scale / unit |
|---|---|---|---|
30001 |
detector_state |
uint16 | 0 idle · 1 entering · 2 measuring · 3 leaving |
30002–30003 |
last_car_volume |
uint32 | ×1000 → m³ (e.g. 145320 = 145.320 m³) |
30004 |
last_car_length |
uint16 | ×100 → m (e.g. 1845 = 18.45 m) |
30005 |
last_car_position |
uint16 | 1-based index in convoy |
30006 |
last_car_confidence |
uint16 | 0–1000 → 0.000–1.000 |
30007–30008 |
last_car_epoch |
uint32 | Unix seconds (UTC) of the measurement |
30009 |
cars_this_convoy |
uint16 | count so far in the active/last convoy |
30010 |
convoys_today |
uint16 | local-day rolling counter |
30011 |
last_sync_age_s |
uint16 | seconds since last successful cloud sync |
30012 |
map_version |
uint16 | this register map's version (starts at 1) |
A PLC reads last_car_* as the latest completed car; values are stable between cars and update
atomically when last_car_epoch advances.
🔄 This surface is not built yet (tracked in the roadmap). The addresses, scaling, and byte order above are the proposed layout; they're frozen as
map_version1 when the surface ships.