141
docs/drivers/AbLegacy-DH-Bridging.md
Normal file
141
docs/drivers/AbLegacy-DH-Bridging.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# AB Legacy — DH+ via 1756-DHRIO bridging
|
||||
|
||||
PR ablegacy-13 / [#256](https://github.com/dohertj2/lmxopcua/issues/256). The AB
|
||||
Legacy driver can address a PLC-5 sitting on a DH+ link by routing CIP requests
|
||||
through a 1756-DHRIO module installed in a ControlLogix chassis. This is the
|
||||
canonical way to keep an installed-base PLC-5 fleet alive after the chassis-
|
||||
level migration to ControlLogix; the DHRIO module exposes a DH+ "side" that
|
||||
talks to the legacy PLC-5 / SLC-DH+ peers and a backplane "side" that the
|
||||
ControlLogix CPU + Ethernet bridge can route through.
|
||||
|
||||
## Wire layout
|
||||
|
||||
```
|
||||
OtOpcUa server ──EtherNet/IP──► 1756-EN2T (slot 0) ──backplane──► 1756-DHRIO (slot N) ──DH+──► PLC-5
|
||||
```
|
||||
|
||||
Two CIP hops:
|
||||
|
||||
1. **Backplane** — port `1`, slot `<N>` (the slot the DHRIO module lives in).
|
||||
2. **DH+** — port `2`, station `<S>` (the DH+ node address of the target PLC-5,
|
||||
in **octal**).
|
||||
|
||||
Resulting CIP path: `1,<N>,2,<S>`.
|
||||
|
||||
> The first port `1` is always the backplane; port `2` is the DH+ side of the
|
||||
> 1756-DHRIO module. This mirrors the convention Rockwell uses in RSLinx + RSLogix
|
||||
> 5.
|
||||
|
||||
## Octal station number
|
||||
|
||||
The DH+ network was specified with **octal** node addresses. Rockwell tooling
|
||||
displays them in octal too (RSLogix 5 → "DH+ Node Address" field on the
|
||||
controller properties dialog). The driver follows suit — the station segment
|
||||
of the CIP path **must be parsed as octal** (digits 0..7 only; `8`, `9`, and
|
||||
multi-byte garbage are rejected).
|
||||
|
||||
DH+ addresses run `0..77` octal == `0..63` decimal. Quick reference:
|
||||
|
||||
| Octal | Decimal | Octal | Decimal | Octal | Decimal | Octal | Decimal |
|
||||
|------:|--------:|------:|--------:|------:|--------:|------:|--------:|
|
||||
| 00 | 0 | 20 | 16 | 40 | 32 | 60 | 48 |
|
||||
| 01 | 1 | 21 | 17 | 41 | 33 | 61 | 49 |
|
||||
| 02 | 2 | 22 | 18 | 42 | 34 | 62 | 50 |
|
||||
| 03 | 3 | 23 | 19 | 43 | 35 | 63 | 51 |
|
||||
| 04 | 4 | 24 | 20 | 44 | 36 | 64 | 52 |
|
||||
| 05 | 5 | 25 | 21 | 45 | 37 | 65 | 53 |
|
||||
| 06 | 6 | 26 | 22 | 46 | 38 | 66 | 54 |
|
||||
| 07 | 7 | 27 | 23 | 47 | 39 | 67 | 55 |
|
||||
| 10 | 8 | 30 | 24 | 50 | 40 | 70 | 56 |
|
||||
| 11 | 9 | 31 | 25 | 51 | 41 | 71 | 57 |
|
||||
| 12 | 10 | 32 | 26 | 52 | 42 | 72 | 58 |
|
||||
| 13 | 11 | 33 | 27 | 53 | 43 | 73 | 59 |
|
||||
| 14 | 12 | 34 | 28 | 54 | 44 | 74 | 60 |
|
||||
| 15 | 13 | 35 | 29 | 55 | 45 | 75 | 61 |
|
||||
| 16 | 14 | 36 | 30 | 56 | 46 | 76 | 62 |
|
||||
| 17 | 15 | 37 | 31 | 57 | 47 | 77 | 63 |
|
||||
|
||||
Anything past `77` octal (i.e. decimal > 63) is invalid on a real DH+ network
|
||||
and rejected by the parser.
|
||||
|
||||
## PLC-5 only
|
||||
|
||||
DHRIO bridging is **PLC-5-only**. The driver enforces this at
|
||||
`AbLegacyDriver.InitializeAsync` time: a DH+ bridge path combined with
|
||||
`PlcFamily=Slc500 / MicroLogix / LogixPccc` throws
|
||||
`InvalidOperationException("DHRIO bridging is PLC-5-only")` immediately rather
|
||||
than letting reads silently fail with `BadCommunicationError` on the wire.
|
||||
|
||||
Background: the 1756-DHRIO module only speaks DH+ to PLC-5 / SLC-DH+ peers, and
|
||||
libplctag's PCCC stack only exposes the PLC-5 side. SLC 5/04 boxes on DH+
|
||||
**can** be physically reached through a DHRIO module, but the protocol stack
|
||||
needed to drive them isn't exposed by libplctag — out of scope for this driver.
|
||||
|
||||
## CLI worked example
|
||||
|
||||
PLC-5 at DH+ node `07` (octal == 7 decimal), DHRIO module in slot 3, gateway
|
||||
`192.168.1.10`:
|
||||
|
||||
```powershell
|
||||
otopcua-ablegacy-cli probe `
|
||||
-g ab://192.168.1.10/1,3,2,07 `
|
||||
-P Plc5 `
|
||||
-a N7:0
|
||||
```
|
||||
|
||||
```powershell
|
||||
# Read N7:10 from the PLC-5 across the DHRIO bridge
|
||||
otopcua-ablegacy-cli read `
|
||||
-g ab://192.168.1.10/1,3,2,07 `
|
||||
-P Plc5 `
|
||||
-a N7:10 `
|
||||
-t Int
|
||||
```
|
||||
|
||||
The driver surfaces the parsed bridge form on the host-address record:
|
||||
`BackplaneSlot=3`, `DhPlusPort=2`, `DhPlusStation=7` (decimal-translated). Use
|
||||
those values when reading driver-diagnostics output to confirm the bridge was
|
||||
recognised — a non-bridge CIP path leaves all three fields null.
|
||||
|
||||
## Manual smoke procedure
|
||||
|
||||
There is no automated end-to-end coverage for DH+ bridging because the only
|
||||
path to wire-level validation is real hardware (libplctag's `ab_server` Docker
|
||||
image doesn't simulate the DHRIO + DH+ + PLC-5 stack). The unit-test layer
|
||||
covers parser positive / negative cases.
|
||||
|
||||
Hardware smoke checklist:
|
||||
|
||||
1. Confirm the 1756-DHRIO module is present in the target ControlLogix chassis.
|
||||
RSLinx Classic should show `DH+, 1` under the chassis tree with the PLC-5
|
||||
nodes enumerated underneath.
|
||||
2. Note the DHRIO module's slot number (the `<N>` in `1,<N>,2,<S>`).
|
||||
3. Note the target PLC-5's DH+ node address — read it off the front-panel switch
|
||||
bank, or the controller properties in RSLogix 5. **Read it as octal**.
|
||||
4. From an OtOpcUa box that can reach the EtherNet/IP gateway:
|
||||
|
||||
```powershell
|
||||
otopcua-ablegacy-cli probe -g ab://<gateway>/1,<slot>,2,<station-octal> -P Plc5 -a S:0
|
||||
```
|
||||
|
||||
`S:0` (status file word 0) is non-destructive and present on every PLC-5.
|
||||
5. If the probe succeeds, exercise an N file read against a known
|
||||
non-zero address. Compare against the value displayed in RSLogix 5 →
|
||||
Online → Data → N7.
|
||||
|
||||
If the probe fails with `BadCommunicationError`:
|
||||
|
||||
- Wrong slot number — re-check via RSLinx.
|
||||
- Wrong octal node — convert from RSLogix 5's display value (already octal); a
|
||||
decimal-thinking conversion mistake is the most common smoke failure.
|
||||
- DHRIO module's DH+ baud rate doesn't match the PLC-5's switch setting (57.6k
|
||||
/ 115.2k / 230.4k) — driver-side problem this can't paper over.
|
||||
- A scanner on the DHRIO is in scheduled-mode and starving unscheduled
|
||||
PCCC traffic — bump the DHRIO's unscheduled-message slice in RSLogix 5000.
|
||||
|
||||
## See also
|
||||
|
||||
- [`Driver.AbLegacy.Cli.md`](../Driver.AbLegacy.Cli.md) — the family / CIP-path
|
||||
cheat sheet now carries a DHRIO row.
|
||||
- [`drivers/AbLegacy-Test-Fixture.md`](AbLegacy-Test-Fixture.md) — DH+ bridging
|
||||
is unit-only; no Docker fixture supports it.
|
||||
@@ -132,6 +132,17 @@ driver-side correctness depends on libplctag being correct.
|
||||
`IPerCallHostResolver` contract is verified; real PCCC wire routing across
|
||||
multiple gateways is not.
|
||||
|
||||
### 3a. DH+ via 1756-DHRIO bridging (PR ablegacy-13 / #256)
|
||||
|
||||
Unit-only — coverage lives in `AbLegacyDhPlusBridgingTests`. The CIP-path
|
||||
parser positive / negative cases (octal-station validation, slot bounds, port
|
||||
shape) and the PLC-5-only family guard at `InitializeAsync` are exercised
|
||||
against fakes. There is no Docker fixture for DH+ because libplctag's
|
||||
`ab_server` doesn't simulate the DHRIO + DH+ + PLC-5 stack — wire-level
|
||||
validation requires real hardware. See
|
||||
[`AbLegacy-DH-Bridging.md`](AbLegacy-DH-Bridging.md) for the manual smoke
|
||||
procedure.
|
||||
|
||||
### 4. Alarms / history
|
||||
|
||||
PCCC has no alarm object + no history object. Driver doesn't implement
|
||||
|
||||
Reference in New Issue
Block a user