Auto: s7-d3 — instance-DB / FB parameter resolution

Closes #301
This commit is contained in:
Joseph Doherty
2026-04-26 07:04:40 -04:00
parent c9e28b881e
commit baf1d65875
9 changed files with 797 additions and 14 deletions

View File

@@ -90,6 +90,98 @@ See [`docs/v2/s7.md` "UDT / STRUCT support"](../v2/s7.md#udt--struct-support)
for the full fan-out semantics, the 4-level nesting cap, and the
Optimized-block-access prerequisite.
## Instance DBs / FB parameters
PR-S7-D3 / [#301](https://github.com/dohertj2/lmxopcua/issues/301) — multi-instance
Function-Block (FB) instances are addressed symbolically inside the PLC program
(`MyFB_Instance.MyParam`) but the runtime wire access still needs the absolute
`DBn.DBW_offset`. TIA Portal's "Show all tags" CSV export distinguishes these
rows from regular global DBs via the **`DB type`** column.
### `DB type` column convention
| `DB type` value | Meaning | Path |
|---|---|---|
| (empty) | Legacy export — no column at all (TIA pre-v15 / partial export). Treated as Global. | D1 (existing) |
| `Global DB` / `Global` / `Global Data Block` | Standalone DB declared in the project tree. | D1 (existing) |
| `Globaler Datenbaustein` | Same as above, DE locale. | D1 (existing) |
| `Instance DB` / `Instance` / `Instance Data Block` | Multi-instance FB instance. Member tags are the FB's `IN` / `OUT` / `IN_OUT` / `STAT` parameters. | **D3 (new)** |
| `Instance-DB` / `Instanz-DB` / `Instanz-Datenbaustein` | Same as above (locale + dashing variants). | **D3 (new)** |
The `DB type` column is matched case-insensitively; quoting and surrounding
whitespace are tolerated.
### `MyFB_Instance.MyParam` → `DBn.DBW_offset`
The TIA Portal export ships the **resolved absolute address** in the
`Logical address` column for every instance-DB member — TIA itself walks the FB
interface declaration at export time and writes out the byte-offset-anchored
address verbatim. The importer accepts these rows the same way as a Global-DB
row, with two differences:
1. The row counts under `S7ImportResult.InstanceDbCount` (a sub-counter of
`ParsedCount`) so the operator can see how much of the import depends on the
FB-interface layout.
2. The row is rejected from the UDT placeholder path even if the data type
column happens to match a UDT name pattern — instance-DB members always
import as fully-functional scalar tags.
Example fixture row:
```csv
Name,Path,Data type,Logical address,Comment,Hmi accessible,DB type
MotorFB_1.Speed,FB instances,Int,%DB7.DBW0,Speed setpoint,True,Instance DB
```
The imported `S7TagDefinition` ends up with:
```csharp
new S7TagDefinition(
Name: "MotorFB_1.Speed",
Address: "DB7.DBW0",
DataType: S7DataType.Int16,
Writable: true);
```
### Empty-`Logical address` fallback
When TIA exports an instance-DB row with an empty `Logical address` column
(rare in practice — happens when the export was generated against a
not-yet-compiled project), `InstanceDbResolver` can compute the absolute
address from explicit parent-DB / parent-base-offset / member-offset inputs.
This fallback is exposed at the resolver-class level for advanced bootstrap
scenarios; the CSV path itself does not currently parse interface declarations
out of the file (TIA's CSV doesn't carry them).
For now the operator workflow is: re-export from TIA after compiling the
project so every instance-DB row carries a resolved `Logical address`.
### Re-import on FB-interface edit — caveat
When the FB interface changes — a member is added, removed, or reordered in
TIA — the instance-DB layout shifts on the PLC side. Member byte offsets that
worked yesterday point at the wrong word today; absolute-offset addressing has
no in-band schema check.
**The driver does not auto-detect this.** Operators must:
1. Recompile the FB in TIA Portal.
2. Download the updated program to the PLC.
3. **Re-export "Show all tags" CSV** from the updated project.
4. Re-import the CSV via `AddTiaCsvImport` or the `import-symbols` CLI.
5. Restart the driver instance (Admin UI → Drivers → Reload).
A stale import will silently read / write the wrong byte offsets — the values
will look like valid PLC data but reference whichever member used to live at
that offset before the interface edit. There is no runtime guard; this is the
same caveat that applies to all absolute-offset DB addressing on S7-1200 /
1500 (see [`docs/v2/s7.md` "UDT / STRUCT support"](../v2/s7.md#udt--struct-support)
for the parallel UDT-edit story).
A future enhancement may add a project-fingerprint compare at driver init —
hashing the interface offsets at import time and re-checking against a known
PLC system function. Tracked as a follow-up; not in PR-S7-D3.
## DE locale handling
TIA Portal honours the Windows display locale when writing CSV. A DE-locale
@@ -188,12 +280,14 @@ straight into the driver-instance config under
`--emit summary` writes a single line:
```
Imported 142 tag(s), skipped 3, errors 0, udt-placeholders 5.
Imported 142 tag(s), skipped 3, errors 0, udt-placeholders 5, instance-db 9.
```
`Skipped` covers HMI-accessible-false rows + missing-required-field rows;
`errors` covers rows whose `Address` failed to parse as an S7 address;
`udt-placeholders` covers UDT-typed rows that imported as placeholders.
`udt-placeholders` covers UDT-typed rows that imported as placeholders;
`instance-db` (PR-S7-D3) covers rows whose `DB type` column tagged them as
multi-instance FB-instance members.
## API surface — `IS7SymbolImporter` + `AddTiaCsvImport` / `AddAwlImport`