Merge #570/#579: native AbCip per-tag config errors, no mistype churn, STRING 82, LWORD type checks; non-blocking lease release (AbCip + AbLegacy)
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe # Conflicts: # src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport/Cip/CipPath.cs
This commit is contained in:
+27
-2
@@ -194,8 +194,33 @@ The driver has two interchangeable wire transports, selected by one `DriverConfi
|
||||
an Unsupported refusal (final review I4): the tag's handle is kept (no re-create, no reconnect), driver
|
||||
health is unchanged (no `Degraded`, nothing fed to the comms-loss watchdog), and the Warning is logged
|
||||
**once per tag** per driver instance, not every poll. The same applies to the libplctag-path width check.
|
||||
- Malformed tag names put the device into backoff, as under libplctag (#570). STRING capacity includes the
|
||||
alignment pad (84, not 82) (#570).
|
||||
The same holds when the controller refuses the **existence read itself** with a type error (CIP
|
||||
`0xFF`/`0x2107`): initialization completes with the status instead of throwing, so the runtime is not
|
||||
disposed and re-created (nor, for a sole lease holder, re-Forward-Opened) on every poll, and the device's
|
||||
connect backoff is not opened (#570). Micro800 `BYTE`/`WORD`/`LWORD` (`0xD1`/`0xD2`/`0xD4`) are checked as
|
||||
integers of their width: a `REAL`/`LREAL` or a narrower integer authored over an `LWORD` is
|
||||
`BadTypeMismatch`, not decoded garbage (#570).
|
||||
- **A malformed tag name is a per-tag configuration error** (#570). A `TagPath` that does not parse, or a
|
||||
name the CIP symbolic encoder refuses (non-ASCII, an empty member such as `A..B`, a member longer than
|
||||
255 characters, an unterminated or non-numeric subscript), reads and writes **`BadConfigurationError`**
|
||||
with one Warning per tag. Nothing reaches the device, so it never opens the device's connect backoff and
|
||||
never degrades driver health — healthy tags on the same device keep reading. (libplctag still reports its
|
||||
own `ErrorBadParam` for a name it rejects.) A malformed **probe** tag does not feed the backoff either.
|
||||
- **STRING capacity:** the built-in Logix `STRING` is 88 bytes on the wire — `LEN` + `DATA[82]` + 2 bytes of
|
||||
alignment padding — so a write holds at most **82** characters (it used to allow 84) and a read never
|
||||
returns the padding as characters. The write still sends the whole 88-byte structure, padding zeroed, as
|
||||
libplctag does. A user string type of any other size keeps the buffer-derived capacity (`size − 4`): the
|
||||
read alone cannot tell its `DATA` length from up to 3 bytes of padding, so a write may accept up to 3
|
||||
characters more than the type holds (#570).
|
||||
- **Releasing a tag never blocks** (#579). Disposing a native tag runtime — the driver does it under the
|
||||
tag's lock on an evict, a reinitialize or a shutdown — releases its connection lease in the background
|
||||
(`ConnectionLease.ReleaseInBackground`, the same shape the native AbLegacy runtime uses). It used to wait
|
||||
up to 2 s for the last lease's Forward Close. Nothing is lost by not waiting: the pool records the close
|
||||
synchronously, so a re-create the next instant still does not open a second session until that Forward
|
||||
Close + UnRegisterSession have finished, and the close is bounded by the connection's own budgets (the
|
||||
open budget for an open still in flight, 1 s for the Forward Close), so a connection is always released.
|
||||
Offline soak: `NativeAbCipLeaseReleaseTests` (25 create/release cycles, no leaked connection); a soak
|
||||
against `ab_server` has not been run.
|
||||
- **A refused operation is not a comms fault.** Any operation a runtime refuses as Unsupported (in AbCip, e.g.
|
||||
a native write whose type cannot be determined) reaches the client as `BadNotSupported`, keeps the tag
|
||||
handle, and leaves driver health unchanged; only real transport failures evict and degrade.
|
||||
|
||||
@@ -150,6 +150,9 @@ Native routing: SLC500/MicroLogix/PLC-5 are direct; `logixpccc` uses Unconnected
|
||||
- **ST (string) byte order is unverified** (no capture); string values may be byte-swapped.
|
||||
- Unlike AbCip, the native AbLegacy runtime has **no element-type check**, so a mis-authored same-width
|
||||
type reads as reinterpreted data (as on libplctag), not `BadTypeMismatch`.
|
||||
- Releasing a native tag (evict, reinitialize, shutdown) never blocks on the connection close: the lease
|
||||
is released in the background (`ConnectionLease.ReleaseInBackground`), the same shape as native AbCip
|
||||
(#579). A re-create cannot overlap the close, because the pool holds the successor connection behind it.
|
||||
|
||||
### Wire evidence (native PCCC)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user