scl_templates: Aufruf-Template FB_ILS_MTRO_2Sep2Swi (ohne Referenz-Aufrufstelle)

Mubea wird damit vollstaendig aus Templates erzeugt. Der FB existiert noch
nicht in der ILSLib; die Schnittstelle ist aus 2Sep1Swi (Separatoren) und
1Sep2Swi (Weichen) angenommen und steht im Template-Kopf - mit den
SPS-Kollegen abzustimmen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Michael StanglandClaude Opus 5.5 committed 2026-10-28 23:13:02 +01:00
1 parent dd955999a9
commit 25ab362c0a
7 files changed
+215 -52

No files matched your search

+6 -3
View File
@@ -180,9 +180,12 @@ Inside the SCL output, `lib/scl_context.py` (TRO-JSON → render context, all de
sits between `model.py` and `scl_skeleton.py` (context → text only). With `--templates` sits between `model.py` and `scl_skeleton.py` (context → text only). With `--templates`
(opt-in) REGIONs come from Jinja2 templates in `lib/scl_templates/<fbType>.scl.j2` (opt-in) REGIONs come from Jinja2 templates in `lib/scl_templates/<fbType>.scl.j2`
(all 7 types with a reference call site: `1Sep`, `1Sep1Swi`, `1Sep2Swi`, `1Sep_SSCC`, (all 7 types with a reference call site: `1Sep`, `1Sep1Swi`, `1Sep2Swi`, `1Sep_SSCC`,
`Vario`, `Vario_workStation`, `PinStore_Auto`; `2Sep1Swi`, `EmptyCarrBuffer`, `LoadingBoom`, `Vario`, `Vario_workStation`, `PinStore_Auto`; `2Sep1Swi`, `EmptyCarrBuffer`, `LoadingBoom`
`2Sep2Swi` stay generic until a call site exists), each round-trip tested against its reference call site stay generic until a call site exists), each round-trip tested against its reference call site
in `doc/TRO_Katalog/scl_templates/` (`tests/test_scl_templates.py`); every line holding a in `doc/TRO_Katalog/scl_templates/` (`tests/test_scl_templates.py`). Exception: `2Sep2Swi`
has a template WITHOUT reference call site (the FB does not exist in the ILSLib yet - its
interface is assumed from `2Sep1Swi` + `1Sep2Swi`, see the template header; only covered by
rendering the real plants and the golden file); every line holding a
placeholder must carry `TODO(E-Planung)`. Migration steps, decisions per template line placeholder must carry `TODO(E-Planung)`. Migration steps, decisions per template line
and status: `doc/SCL_Templates.md`. Golden files in `tests/fixtures/scl/` pin the SCL output byte for and status: `doc/SCL_Templates.md`. Golden files in `tests/fixtures/scl/` pin the SCL output byte for
byte — rewrite them (`SKEL_UPDATE_GOLDEN=1`) only for a reviewed, intended change. byte — rewrite them (`SKEL_UPDATE_GOLDEN=1`) only for a reviewed, intended change.
+9 -4
View File
@@ -626,8 +626,10 @@ with a real reference call site (`1Sep`, `1Sep1Swi`, `1Sep2Swi`, `1Sep_SSCC`,
`Vario`, `Vario_workStation`, `PinStore_Auto`); each follows its call site in `Vario`, `Vario_workStation`, `PinStore_Auto`); each follows its call site in
`doc/TRO_Katalog/scl_templates/` line for line, and every value that is still `doc/TRO_Katalog/scl_templates/` line for line, and every value that is still
open carries `TODO(E-Planung)`. The line decisions are proposals to be confirmed open carries `TODO(E-Planung)`. The line decisions are proposals to be confirmed
by a PLC engineer (`doc/SCL_Templates.md` §6). `2Sep1Swi`, `EmptyCarrBuffer`, by a PLC engineer (`doc/SCL_Templates.md` §6). `2Sep1Swi`, `EmptyCarrBuffer` and
`LoadingBoom` and `2Sep2Swi` have no call site yet and stay generic. `--strict` stops (exit `1`, no SCL) if any FB type has no `LoadingBoom` have no call site yet and stay generic. `2Sep2Swi` has a template without
a call site (FB not yet in the ILSLib, interface assumed from `2Sep1Swi` + `1Sep2Swi`).
`--strict` stops (exit `1`, no SCL) if any FB type has no
template. Without `--templates` the output is unchanged. template. Without `--templates` the output is unchanged.
**Names from the plant JSON (stage 4, `--json <csv>_anlage.json`).** The **Names from the plant JSON (stage 4, `--json <csv>_anlage.json`).** The
@@ -975,8 +977,11 @@ verified against `data/*.scl` where the source is vendored locally, and against
> Kreisel2/Kreisel1 touch as a single control object with 2 separators, > Kreisel2/Kreisel1 touch as a single control object with 2 separators,
> 2 scanners and 2 switches. **`FB_ILS_MTRO_2Sep2Swi` does not exist** in this > 2 scanners and 2 switches. **`FB_ILS_MTRO_2Sep2Swi` does not exist** in this
> repository or in `doc/TRO_Katalog/scl_templates/`, and has to be created in > repository or in `doc/TRO_Katalog/scl_templates/`, and has to be created in
> the ILSLib — otherwise a future SCL generator will emit a call to a missing > the ILSLib — otherwise the generated FB_Main calls a missing block. Since
> block. The closest verified type is `2Sep1Swi` (2 separators, 2 scanners, > 2026-10-28 there is a call-site template `lib/scl_templates/FB_ILS_MTRO_2Sep2Swi.scl.j2`
> whose header lists the assumed interface (separators as in `2Sep1Swi`, switches
> as in `1Sep2Swi`) - the FB has to be created to match it, or the template
> adjusted. The closest verified type is `2Sep1Swi` (2 separators, 2 scanners,
> **1** switch), which matches the hardware actually present in that export. > **1** switch), which matches the hardware actually present in that export.
> `3Sep2Swi` (3 separators, 3 scanners, 2 switches) was added on 2026-10-14 > `3Sep2Swi` (3 separators, 3 scanners, 2 switches) was added on 2026-10-14
> for the test plant `data/export.csv`, where one Kreisel pulley touches two > for the test plant `data/export.csv`, where one Kreisel pulley touches two
+13 -8
View File
@@ -66,10 +66,12 @@ Coverage per catalog type (`lib/tro_catalog.py`):
| `2Sep1Swi` | `FB_ILS_MTRO_2Sep1Swi` | **no** | yes | from interface only — needs a real call site | | `2Sep1Swi` | `FB_ILS_MTRO_2Sep1Swi` | **no** | yes | from interface only — needs a real call site |
| `EmptyCarrBuffer` | `FB_EmptyCarrBuffer` | **no** | yes | from interface only — needs a real call site | | `EmptyCarrBuffer` | `FB_EmptyCarrBuffer` | **no** | yes | from interface only — needs a real call site |
| `LoadingBoom` | `FB_LoadingBoom_INBOUND` | **no** | yes | from interface only — needs a real call site | | `LoadingBoom` | `FB_LoadingBoom_INBOUND` | **no** | yes | from interface only — needs a real call site |
| `2Sep2Swi` | `FB_ILS_MTRO_2Sep2Swi` | **no** | **no** | no — FB does not exist yet (Mubea needs it) | | `2Sep2Swi` | `FB_ILS_MTRO_2Sep2Swi` | **no** | **no** | ✅ done WITHOUT reference (2026-10-28) — FB does not exist yet (Mubea needs it); interface assumed from `2Sep1Swi` (separators) + `1Sep2Swi` (switches), see template header |
So 7 types can be done with a test against real code. 3 can only be checked against the So 7 types can be done with a test against real code. 3 can only be checked against the
interface until someone supplies a real call site. `2Sep2Swi` stays on the fallback (§9). interface until someone supplies a real call site. `2Sep2Swi` has a template that is only
covered by rendering the real plants and the mubea golden file - the FB has to be created
in the ILSLib to match its assumed interface (or the template adjusted).
--- ---
@@ -410,14 +412,15 @@ as `carousel_run` from connection kinds).
| Situation | Behaviour | Exit | | Situation | Behaviour | Exit |
|---|---|---| |---|---|---|
| Template exists for the TRO's `fbType` | render template | 0 | | Template exists for the TRO's `fbType` | render template | 0 |
| No template (e.g. `2Sep2Swi`) | render with the current `emit_*` code; header lines `// Aus Template : …` / `// Generisch : … (kein Template - von Hand pruefen)` and an entry in the console summary | 0 | | No template (e.g. `2Sep1Swi`) | render with the current `emit_*` code; header lines `// Aus Template : …` / `// Generisch : … (kein Template - von Hand pruefen)` and an entry in the console summary | 0 |
| No template **and** `--strict` | stop, write nothing | 1 | | No template **and** `--strict` | stop, write nothing | 1 |
| Template uses an undefined variable / syntax error | stop, write nothing, show template file and line | 1 | | Template uses an undefined variable / syntax error | stop, write nothing, show template file and line | 1 |
| Naming rule with unknown placeholder | stop, write nothing | 1 | | Naming rule with unknown placeholder | stop, write nothing | 1 |
| Invalid TRO-JSON | unchanged from today | 1 | | Invalid TRO-JSON | unchanged from today | 1 |
With `--templates` the console summary gets a `Templates` line (implemented); the With `--templates` the console summary gets a `Templates` line (implemented); the
`Namensregeln` line follows with step 4. Real output for mubea today: `Namensregeln` line follows with step 4. Real output for mubea before the `2Sep2Swi`
template (since 2026-10-28 mubea is fully rendered from templates):
``` ```
Templates = 4 von 5 Typen (generisch: FB_ILS_MTRO_2Sep2Swi) Templates = 4 von 5 Typen (generisch: FB_ILS_MTRO_2Sep2Swi)
@@ -452,9 +455,9 @@ Each step ends with all tests green and is usable on its own.
| 2 ✅ | `scl_context.py`: build the render context from `TroDocument`; `emit_*` read from it — `tests/test_scl_context.py` | golden files byte-identical (also checked on dematic and showroom, with and without `--start`) | | 2 ✅ | `scl_context.py`: build the render context from `TroDocument`; `emit_*` read from it — `tests/test_scl_context.py` | golden files byte-identical (also checked on dematic and showroom, with and without `--start`) |
| 3 ✅ | Pilot `FB_ILS_MTRO_1Sep1Swi.scl.j2` + `_macros`; switches `--templates`, `--strict`; class-C table (§6) filled with proposals — **still to be confirmed by a PLC engineer**; round-trip test | round trip against TRO107 passes; only the 1Sep1Swi REGIONs (+ header) differ from the generic golden files | | 3 ✅ | Pilot `FB_ILS_MTRO_1Sep1Swi.scl.j2` + `_macros`; switches `--templates`, `--strict`; class-C table (§6) filled with proposals — **still to be confirmed by a PLC engineer**; round-trip test | round trip against TRO107 passes; only the 1Sep1Swi REGIONs (+ header) differ from the generic golden files |
| 4 | `scl_naming.py` + `cfg/scl_naming.ini`; switch `--naming` | naming tests pass; Mubea renders with names instead of TODOs where a rule exists | | 4 | `scl_naming.py` + `cfg/scl_naming.ini`; switch `--naming` | naming tests pass; Mubea renders with names instead of TODOs where a rule exists |
| 5 ✅ | Remaining call-site templates (`1Sep`, `Vario`, `1Sep2Swi`, `1Sep_SSCC`, `Vario_workStation`, `PinStore_Auto`), each with round trip against its reference (`PinStore_Auto`: the parts the reference abbreviates are left out of the comparison); decisions in §6 — **still to be confirmed by a PLC engineer**. Interface check (§8.2) for `Vario_workStation` still open | every round trip passes; HundM05 fully from templates, mubea except `2Sep2Swi` | | 5 ✅ | Remaining call-site templates (`1Sep`, `Vario`, `1Sep2Swi`, `1Sep_SSCC`, `Vario_workStation`, `PinStore_Auto`), each with round trip against its reference (`PinStore_Auto`: the parts the reference abbreviates are left out of the comparison); decisions in §6 — **still to be confirmed by a PLC engineer**. Interface check (§8.2) for `Vario_workStation` still open | every round trip passes; HundM05 fully from templates, mubea too since the `2Sep2Swi` template (2026-10-28, no reference) |
| 6 | Templates on by default; new `--no-templates` keeps the old path for one release | golden files updated and reviewed; one import into TIA Portal (as for Mubea) | | 6 | Templates on by default; new `--no-templates` keeps the old path for one release | golden files updated and reviewed; one import into TIA Portal (as for Mubea) |
| 7 | Remove `emit_*` once every type in use has a template (`2Sep2Swi` needs a call site first) | fallback only for types without FB | | 7 | Remove `emit_*` once every type in use has a template (`2Sep2Swi` has one, but without call site - confirm it once the FB exists) | fallback only for types without FB |
Docs touched along the way: `doc/Python_Scripts.md` §5b, `doc/Commandlines.md` §2.5, Docs touched along the way: `doc/Python_Scripts.md` §5b, `doc/Commandlines.md` §2.5,
`CLAUDE.md` (roadmap), this file. `CLAUDE.md` (roadmap), this file.
@@ -511,8 +514,10 @@ jam-area DBs) until an E-Planung export exists, and the `pruefen` timings.
4. `xInRelease`: `TRUE` as in the reference, or the `"DB_TRO_TEST"` test release used today? 4. `xInRelease`: `TRUE` as in the reference, or the `"DB_TRO_TEST"` test release used today?
5. Real call sites for `2Sep1Swi`, `EmptyCarrBuffer`, `LoadingBoom` — available from 5. Real call sites for `2Sep1Swi`, `EmptyCarrBuffer`, `LoadingBoom` — available from
another plant? another plant?
6. `FB_ILS_MTRO_2Sep2Swi` (Mubea): will it be created in the ILSLib, or should the two 6. `FB_ILS_MTRO_2Sep2Swi` (Mubea): to be created in the ILSLib (decided 2026-10-28,
transfer points be modelled with existing types? the two transfer points stay one TRO). Its call site is drafted in
`lib/scl_templates/FB_ILS_MTRO_2Sep2Swi.scl.j2`; open: the assumed interface
(`bSep<n>Type`, `stInOutCognexInterface1/2`, priority manager, `xNewSwitch`).
7. `nTo1Destinations`: TRO107 has 2 exits but the value 3 ("Info noetig fuer HMI"). Does 7. `nTo1Destinations`: TRO107 has 2 exits but the value 3 ("Info noetig fuer HMI"). Does
it count the destinations behind the switch rather than its exits? If so, which it count the destinations behind the switch rather than its exits? If so, which
destinations — the per-exit target lists in the skeleton could supply them. destinations — the per-exit target lists in the skeleton could supply them.
@@ -0,0 +1,115 @@
{#-
FB_ILS_MTRO_2Sep2Swi - Aufrufstelle in FB_Main
ACHTUNG: KEINE Referenz-Aufrufstelle. Der Baustein existiert noch nicht in der
ILSLib (Anlass: Mubea 500573, Beruehrpunkt Kreisel2/Kreisel1 - zwei
Separatoren laufen auf Ausschleuselement und Kreisel-Weiche zu). Darum gibt es
hier keinen Rundlauf-Test wie bei den anderen Templates, nur das Rendern fuer
die echten Anlagen (tests/test_scl_templates.py) und die Golden-Datei.
Die Schnittstelle ist aus den beiden Nachbarbausteinen ZUSAMMENGESETZT und
muss beim Anlegen des FB so (oder geaendert hier) umgesetzt werden:
zwei Separatoren wie FB_ILS_MTRO_2Sep1Swi (Quelle data/): stInSeparator1/2,
stInSettings.bSep1Type/bSep2Type, arInOutJamEntr1/2,
stInBarcodeReader1/2, stInOutCognexInterface1/2,
xOutStopper1/2
zwei Weichen wie FB_ILS_MTRO_1Sep2Swi (Referenz TRO 267): stInSwitch1/2
mit xNewSwitch, stInSenJam<n> und arInOutJamExit<n> je
Ausgang, xInCarouselRun1/2, xOutSw1ExTo3/xOutSw2ExTo3
Entscheidungen zu den ortsgebundenen Zeilen (doc/SCL_Templates.md §6):
Separatorzeiten 100/50 ms wie die anderen Templates (m.separator), "pruefen"
nSwitchNo fuer BEIDE Weichen (FC_Direction braucht die Nummer;
in TRO 267 fehlt sie bei Weiche 2 - dort offen, Frage 9)
nTo1Destinations Aufteilung der Abgaenge auf die Weichen offen
bSep<n>Type.%X2 TRUE wie bSepType.%X2 in TRO 267, Bedeutung klaeren
xInCarouselRun<n> je Weiche einer - hier sitzen beide an je einem Kreisel
Vorfahrtsregelung nicht verdrahtet: 2Sep1Swi hat stInPriorityManagerDir1..4,
1Sep2Swi ein einzelnes stInPriorityManager - offen
FC_Direction je Weiche einer, Ziel nInDirection1/2
Alle noch mit den SPS-Kollegen zu bestaetigen.
-#}
{% import "_macros.scl.j2" as m %}
REGION {{ t.region_title }}
{{ m.kopf(t) }}
// ACHTUNG: FB_ILS_MTRO_2Sep2Swi existiert noch nicht in der ILSLib - Schnittstelle
// angenommen (2Sep1Swi + 1Sep2Swi), mit den SPS-Kollegen abzustimmen.
{% for s in t.separators %}
{{ m.separator(t, s) }}
{% if not loop.last %}
{% endif %}
{% endfor %}
{{ m.jam_sensors(t) }}
{% for w in t.switches %}
#{{ t.id }}.stInSwitch{{ w.n }}.Settings.nSwitchNo := "{{ w.no.value }}";{{ m.todo(w.no) }}
#{{ t.id }}.stInSwitch{{ w.n }}.Settings.xPluggedExSen3 := FALSE;
#{{ t.id }}.stInSwitch{{ w.n }}.Settings.xPluggedExSen4 := FALSE;
#{{ t.id }}.stInSwitch{{ w.n }}.Settings.xNewSwitch := TRUE;
{% if w.to1_destinations is not none %}
#{{ t.id }}.stInSwitch{{ w.n }}.Settings.nTo1Destinations := {{ w.to1_destinations }}; // Info noetig fuer HMI - {{ TODO }}: pruefen
{% else %}
#{{ t.id }}.stInSwitch{{ w.n }}.Settings.nTo1Destinations := _; // {{ TODO }}: {{ t.successors|length }} Abgaenge auf {{ t.switches|length }} Weichen - Aufteilung festlegen
{% endif %}
{% endfor %}
{{ m.ziele(t) }}
{% for sc in t.scanners %}
#{{ t.id }}.stInBarcodeReader{{ sc.n }}.Settings.xActivateCheckASCI := TRUE;
#{{ t.id }}.stInBarcodeReader{{ sc.n }}.Settings.tTimeout := T#5s;
{{ m.cognex_in(m.cognex(sc), sc) }}
{% endfor %}
// Vorfahrtsregelung: nicht verdrahtet - {{ TODO }}: Schnittstelle des FB klaeren
{% for s in t.separators %}
#{{ t.id }}.stInSettings.bSep{{ s.n }}Type.%X2 := TRUE; // {{ TODO }}: pruefen (Bedeutung)
{% endfor %}
{% set z = [] %}
{% set _ = z.append(('nInMainTroNo := "' ~ t.main_tro.value ~ '"', m.note(t.main_tro))) %}
{% set _ = z.append(("xInSftyOk := " ~ t.safety.value, m.note(t.safety))) %}
{% set _ = z.append(("xInAllRdyToStart := TRUE", "")) %}
{% set _ = z.append(('xInCancel := "cTodoFalse"', "")) %}
{% set _ = z.append(("xInRelease := " ~ t.release, "")) %}
{% for w in t.switches %}
{% set _ = z.append(("xInCarouselRun" ~ w.n ~ " := " ~ t.carousel_run.value, m.note(t.carousel_run, "Kreisel an Weiche " ~ w.n))) %}
{% endfor %}
{% set _ = z.append(("stInOutMachineState := " ~ t.machine_state.value, m.note(t.machine_state, "Schaltschrank"))) %}
{% for s in t.separators %}
{% if t.scanners|length >= s.n %}
{% set sc = t.scanners[s.n - 1] %}
{% set _ = z.append(("stInOutCognexInterface" ~ s.n ~ " := " ~ m.cognex(sc), m.note(sc.interface))) %}
{% else %}
{% set _ = z.append(("stInOutCognexInterface" ~ s.n ~ " := #stCognexInterfaceDummy", "")) %}
{% endif %}
{% endfor %}
{% for j in t.jam_entries %}
{% set _ = z.append(("arInOutJamEntr" ~ j.n ~ " := " ~ j.carriers.value, m.note(j.carriers, j.title ~ " von " ~ j.neighbour))) %}
{% set _ = z.append(("stInOutJamEntr" ~ j.n ~ " := " ~ j.data.value, m.note(j.data))) %}
{% endfor %}
{% for j in t.jam_exits %}
{% set _ = z.append(("arInOutJamExit" ~ j.n ~ " := " ~ j.carriers.value, m.note(j.carriers, j.title ~ " vor " ~ j.neighbour))) %}
{% set _ = z.append(("stInOutJamExit" ~ j.n ~ " := " ~ j.data.value, m.note(j.data))) %}
{% endfor %}
{% for s in t.separators %}
{% set _ = z.append(("xOutStopper" ~ s.n ~ ' => "' ~ s.stopper.value ~ '"', m.note(s.stopper))) %}
{% endfor %}
{% for w in t.switches %}
{% set _ = z.append(("xOutSw" ~ w.n ~ 'ExTo3 => "' ~ w.valve.value ~ '"', m.note(w.valve))) %}
{% endfor %}
{% set _ = z.append(('stInOutHMI := "DB_Interface_HMI".stTRO.' ~ t.id, "")) %}
{% set _ = z.append(('nOutStateLast => "DB_GLOB_TroState".arTroState["' ~ t.main_tro.value ~ '"]', m.note(t.main_tro))) %}
{{ m.call(t, z) }}
{% for sc in t.scanners %}
{{ m.cognex_out(m.cognex(sc), sc) }}
{% if not loop.last %}
{% endif %}
{% endfor %}
{{ m.direction(t) }}
END_REGION
+2 -1
View File
@@ -613,7 +613,8 @@ TRO_CATALOG: tuple[TroDefinition, ...] = (
# Der Baustein FB_ILS_MTRO_2Sep2Swi existiert in diesem Repository nicht # Der Baustein FB_ILS_MTRO_2Sep2Swi existiert in diesem Repository nicht
# und ist auch in doc/TRO_Katalog/scl_templates/ nicht hinterlegt - er muss # und ist auch in doc/TRO_Katalog/scl_templates/ nicht hinterlegt - er muss
# in der ILSLib angelegt werden, sonst erzeugt ein spaeterer # in der ILSLib angelegt werden, sonst erzeugt ein spaeterer
# SCL-Generator einen Aufruf auf einen fehlenden Baustein. # SCL-Generator einen Aufruf auf einen fehlenden Baustein. Die angenommene
# Schnittstelle steht im Kopf von lib/scl_templates/FB_ILS_MTRO_2Sep2Swi.scl.j2.
TroDefinition("2Sep2Swi", "FB_ILS_MTRO_2Sep2Swi", { TroDefinition("2Sep2Swi", "FB_ILS_MTRO_2Sep2Swi", {
TroItem.SEPARATOR: 2, TroItem.SEPARATOR: 2,
TroItem.SWITCH: 2, TroItem.SWITCH: 2,
+63 -34
View File
@@ -16,8 +16,8 @@
// Reihenfolge der REGIONs = Materialfluss. // Reihenfolge der REGIONs = Materialfluss.
// Anfang bei TRO03: Materialeingang ueber SYS1. // Anfang bei TRO03: Materialeingang ueber SYS1.
// //
// Aus Template : FB_ILS_MTRO_1Sep, FB_ILS_MTRO_1Sep1Swi, FB_ILS_MTRO_PinStore_Auto, FB_ILS_MTRO_Vario // Aus Template : FB_ILS_MTRO_1Sep, FB_ILS_MTRO_1Sep1Swi, FB_ILS_MTRO_2Sep2Swi, FB_ILS_MTRO_PinStore_Auto, FB_ILS_MTRO_Vario
// Generisch : FB_ILS_MTRO_2Sep2Swi (kein Template - von Hand pruefen) // Generisch : - (kein Template - von Hand pruefen)
// ============================================================ // ============================================================
FUNCTION_BLOCK "FB_Main" FUNCTION_BLOCK "FB_Main"
@@ -514,42 +514,46 @@ REGION TRO10 (2Sep2Swi) Sep 0005, 0036
// Vorgaenger: TRO01, TRO06, TRO18 // Vorgaenger: TRO01, TRO06, TRO18
// Nachfolger: TRO01, TRO02, TRO11 // Nachfolger: TRO01, TRO02, TRO11
// Einstufung: hoch // Einstufung: hoch
// Aufbau nach Template FB_ILS_MTRO_2Sep2Swi.scl.j2 (Referenz: doc/TRO_Katalog/scl_templates)
// ACHTUNG: FB_ILS_MTRO_2Sep2Swi existiert noch nicht in der ILSLib - Schnittstelle
// angenommen (2Sep1Swi + 1Sep2Swi), mit den SPS-Kollegen abzustimmen.
// Separator 1 = Bauteil 0005 aus dem Layout // Separator 1 = Bauteil 0005 aus dem Layout
#TRO10.stInSeparator1.Settings.nSeparatorNo := "cSep_____"; // TODO(E-Planung) #TRO10.stInSeparator1.Settings.nSeparatorNo := "cSep_____"; // TODO(E-Planung)
#TRO10.stInSeparator1.Settings.tDelayToNextItem := "TimeForSepWaiting_Short"; #TRO10.stInSeparator1.Settings.tDelayToNextItem := "TimeForSepWaiting_Short";
#TRO10.stInSeparator1.Settings.tTrailingTime := t#600ms; // TODO(E-Planung): pruefen #TRO10.stInSeparator1.Settings.tTrailingTime := t#100ms; // TODO(E-Planung): pruefen
#TRO10.stInSeparator1.Settings.tHandlingTime := t#200ms; // TODO(E-Planung): pruefen #TRO10.stInSeparator1.Settings.tHandlingTime := t#50ms; // TODO(E-Planung): pruefen
#TRO10.stInSeparator1.Settings.tJam := "TimeForSepJam"; #TRO10.stInSeparator1.Settings.tJam := "TimeForSepJam";
#TRO10.stInSeparator1.Settings.xPluggedJam := TRUE; #TRO10.stInSeparator1.Settings.xPluggedJam := TRUE;
#TRO10.stInSeparator1.Settings.xPluggedPart := FALSE; #TRO10.stInSeparator1.Settings.xPluggedPart := FALSE;
#TRO10.stInSeparator1.Settings.xPluggedScanner := TRUE; #TRO10.stInSeparator1.Settings.xPluggedScanner := TRUE;
#TRO10.stInSeparator1.stSenInSep := "DB_Inputs".Sensors["cInBG____"]; // TODO(E-Planung) #TRO10.stInSeparator1.stSenInSep := "DB_Inputs".Sensors["cInBG____"]; // TODO(E-Planung)
#TRO10.stInSeparator1.Settings.tSenFree := T#1500ms; // TODO(E-Planung): pruefen
#TRO10.stInSeparator1.Settings.tSenWait := T#4000ms; // TODO(E-Planung): pruefen
// Separator 2 = Bauteil 0036 aus dem Layout // Separator 2 = Bauteil 0036 aus dem Layout
#TRO10.stInSeparator2.Settings.nSeparatorNo := "cSep_____"; // TODO(E-Planung) #TRO10.stInSeparator2.Settings.nSeparatorNo := "cSep_____"; // TODO(E-Planung)
#TRO10.stInSeparator2.Settings.tDelayToNextItem := "TimeForSepWaiting_Short"; #TRO10.stInSeparator2.Settings.tDelayToNextItem := "TimeForSepWaiting_Short";
#TRO10.stInSeparator2.Settings.tTrailingTime := t#600ms; // TODO(E-Planung): pruefen #TRO10.stInSeparator2.Settings.tTrailingTime := t#100ms; // TODO(E-Planung): pruefen
#TRO10.stInSeparator2.Settings.tHandlingTime := t#200ms; // TODO(E-Planung): pruefen #TRO10.stInSeparator2.Settings.tHandlingTime := t#50ms; // TODO(E-Planung): pruefen
#TRO10.stInSeparator2.Settings.tJam := "TimeForSepJam"; #TRO10.stInSeparator2.Settings.tJam := "TimeForSepJam";
#TRO10.stInSeparator2.Settings.xPluggedJam := TRUE; #TRO10.stInSeparator2.Settings.xPluggedJam := TRUE;
#TRO10.stInSeparator2.Settings.xPluggedPart := FALSE; #TRO10.stInSeparator2.Settings.xPluggedPart := FALSE;
#TRO10.stInSeparator2.Settings.xPluggedScanner := TRUE; #TRO10.stInSeparator2.Settings.xPluggedScanner := TRUE;
#TRO10.stInSeparator2.stSenInSep := "DB_Inputs".Sensors["cInBG____"]; // TODO(E-Planung) #TRO10.stInSeparator2.stSenInSep := "DB_Inputs".Sensors["cInBG____"]; // TODO(E-Planung)
#TRO10.stInSeparator2.Settings.tSenFree := T#1500ms; // TODO(E-Planung): pruefen #TRO10.stInSenJam2 := "DB_Inputs".Sensors["cInBG____"]; // TODO(E-Planung)
#TRO10.stInSeparator2.Settings.tSenWait := T#4000ms; // TODO(E-Planung): pruefen #TRO10.stInSenJam3 := "DB_Inputs".Sensors["cInBG____"]; // TODO(E-Planung)
#TRO10.stInSenJam4 := "DB_Inputs".Sensors["cInBG____"]; // TODO(E-Planung)
#TRO10.stInSwitch1.Settings.nSwitchNo := "cSwi_____"; // TODO(E-Planung) #TRO10.stInSwitch1.Settings.nSwitchNo := "cSwi_____"; // TODO(E-Planung)
#TRO10.stInSwitch1.Settings.xPluggedExSen3 := FALSE; #TRO10.stInSwitch1.Settings.xPluggedExSen3 := FALSE;
#TRO10.stInSwitch1.Settings.xPluggedExSen4 := FALSE; #TRO10.stInSwitch1.Settings.xPluggedExSen4 := FALSE;
#TRO10.stInSwitch1.Settings.nTo1Destinations := _; // TODO(E-Planung): dieser TRO hat 3 Abgaenge auf 2 Weichen - Aufteilung festlegen #TRO10.stInSwitch1.Settings.xNewSwitch := TRUE;
#TRO10.stInSwitch1.Settings.nTo1Destinations := _; // TODO(E-Planung): 3 Abgaenge auf 2 Weichen - Aufteilung festlegen
#TRO10.stInSwitch2.Settings.nSwitchNo := "cSwi_____"; // TODO(E-Planung) #TRO10.stInSwitch2.Settings.nSwitchNo := "cSwi_____"; // TODO(E-Planung)
#TRO10.stInSwitch2.Settings.xPluggedExSen3 := FALSE; #TRO10.stInSwitch2.Settings.xPluggedExSen3 := FALSE;
#TRO10.stInSwitch2.Settings.xPluggedExSen4 := FALSE; #TRO10.stInSwitch2.Settings.xPluggedExSen4 := FALSE;
#TRO10.stInSwitch2.Settings.nTo1Destinations := _; // TODO(E-Planung): dieser TRO hat 3 Abgaenge auf 2 Weichen - Aufteilung festlegen #TRO10.stInSwitch2.Settings.xNewSwitch := TRUE;
#TRO10.stInSwitch2.Settings.nTo1Destinations := _; // TODO(E-Planung): 3 Abgaenge auf 2 Weichen - Aufteilung festlegen
// Zielliste je Abgang (aus dem TRO-Graphen berechnet) - // Zielliste je Abgang (aus dem TRO-Graphen berechnet) -
// Grundlage fuer die Zuordnung Ziel -> Richtung in FC_Direction: // Grundlage fuer die Zuordnung Ziel -> Richtung in FC_Direction:
@@ -558,31 +562,47 @@ REGION TRO10 (2Sep2Swi) Sep 0005, 0036
// ueber TRO11: TRO03, TRO04, TRO05, TRO07, TRO11, TRO12, TRO18 // ueber TRO11: TRO03, TRO04, TRO05, TRO07, TRO11, TRO12, TRO18
#TRO10.stInBarcodeReader1.Settings.xActivateCheckASCI := TRUE; #TRO10.stInBarcodeReader1.Settings.xActivateCheckASCI := TRUE;
#TRO10.stInBarcodeReader1.Settings.tTimeout := T#3000ms; #TRO10.stInBarcodeReader1.Settings.tTimeout := T#5s;
// TODO(E-Planung): Cognex-Interface verdrahten (#arCognexInterface["cScanner____"])
#arCognexInterface["cScanner____"].xInCamTriggerReady := "bx____-TriggerReady"; // TODO(E-Planung)
#arCognexInterface["cScanner____"].xInCamTriggerAck := "bx____-TriggerAck"; // TODO(E-Planung)
#arCognexInterface["cScanner____"].xInCamResultsAvailable := "bx____-Results Available"; // TODO(E-Planung)
#arCognexInterface["cScanner____"].xInCamGeneralFault := "bx____-General Fault"; // TODO(E-Planung)
#arCognexInterface["cScanner____"].hwInCamInspectionResults := "BX____~Ergebnisse_–_64_Bytes_1"; // TODO(E-Planung)
#TRO10.stInBarcodeReader2.Settings.xActivateCheckASCI := TRUE; #TRO10.stInBarcodeReader2.Settings.xActivateCheckASCI := TRUE;
#TRO10.stInBarcodeReader2.Settings.tTimeout := T#3000ms; #TRO10.stInBarcodeReader2.Settings.tTimeout := T#5s;
// TODO(E-Planung): Cognex-Interface verdrahten (#arCognexInterface["cScanner____"])
#TRO10.stInPriorityManager.xReleaseOk := TRUE; #arCognexInterface["cScanner____"].xInCamTriggerReady := "bx____-TriggerReady"; // TODO(E-Planung)
#arCognexInterface["cScanner____"].xInCamTriggerAck := "bx____-TriggerAck"; // TODO(E-Planung)
#arCognexInterface["cScanner____"].xInCamResultsAvailable := "bx____-Results Available"; // TODO(E-Planung)
#arCognexInterface["cScanner____"].xInCamGeneralFault := "bx____-General Fault"; // TODO(E-Planung)
#arCognexInterface["cScanner____"].hwInCamInspectionResults := "BX____~Ergebnisse_–_64_Bytes_1"; // TODO(E-Planung)
// Vorfahrtsregelung: nicht verdrahtet - TODO(E-Planung): Schnittstelle des FB klaeren
#TRO10.stInSettings.bSep1Type.%X2 := TRUE; // TODO(E-Planung): pruefen (Bedeutung)
#TRO10.stInSettings.bSep2Type.%X2 := TRUE; // TODO(E-Planung): pruefen (Bedeutung)
#TRO10(nInMainTroNo := "cMainTro____", // TODO(E-Planung) #TRO10(nInMainTroNo := "cMainTro____", // TODO(E-Planung)
xInSftyOk := "DB_InterfaceSafety".stFromSafety.EStopMain.Q, // TODO(E-Planung) xInSftyOk := "DB_InterfaceSafety".stFromSafety.EStopMain.Q, // TODO(E-Planung)
xInAllRdyToStart := TRUE, xInAllRdyToStart := TRUE,
xInCancel := "cTodoFalse",
xInRelease := "DB_TRO_TEST".TRO10, xInRelease := "DB_TRO_TEST".TRO10,
stInOutMachineState := #stInOutControlUnitCabinet, xInCarouselRun1 := #fbCarousel____.xOutConveyorFullSpeed, // TODO(E-Planung) - Kreisel an Weiche 1
stInOutCognexInterface := #stCognexInterfaceDummy, xInCarouselRun2 := #fbCarousel____.xOutConveyorFullSpeed, // TODO(E-Planung) - Kreisel an Weiche 2
stInOutMachineState := #stInOutControlUnitCabinet, // TODO(E-Planung) - Schaltschrank
stInOutCognexInterface1 := #arCognexInterface["cScanner____"], // TODO(E-Planung)
stInOutCognexInterface2 := #arCognexInterface["cScanner____"], // TODO(E-Planung)
arInOutJamEntr1 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0005 von TRO01, TRO06, TRO18 (Aufteilung der Vorgaenger auf die Eingaenge offen) arInOutJamEntr1 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0005 von TRO01, TRO06, TRO18 (Aufteilung der Vorgaenger auf die Eingaenge offen)
stInOutJamEntr1 := "DB_JamArea____".stJam____.stData, stInOutJamEntr1 := "DB_JamArea____".stJam____.stData, // TODO(E-Planung)
arInOutJamEntr2 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0036 von - (Aufteilung der Vorgaenger auf die Eingaenge offen) arInOutJamEntr2 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0036 von - (Aufteilung der Vorgaenger auf die Eingaenge offen)
stInOutJamEntr2 := "DB_JamArea____".stJam____.stData, stInOutJamEntr2 := "DB_JamArea____".stJam____.stData, // TODO(E-Planung)
arInOutJamExit2 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0040 vor TRO01 arInOutJamExit2 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0040 vor TRO01
stInOutJamExit2 := "DB_JamArea____".stJam____.stData, stInOutJamExit2 := "DB_JamArea____".stJam____.stData, // TODO(E-Planung)
arInOutJamExit3 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0012 vor TRO02 arInOutJamExit3 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0012 vor TRO02
stInOutJamExit3 := "DB_JamArea____".stJam____.stData, stInOutJamExit3 := "DB_JamArea____".stJam____.stData, // TODO(E-Planung)
arInOutJamExit4 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0058 vor TRO11 arInOutJamExit4 := "DB_JamArea____".stJam____.arCarrier, // TODO(E-Planung) - Staubereich J0058 vor TRO11
stInOutJamExit4 := "DB_JamArea____".stJam____.stData, stInOutJamExit4 := "DB_JamArea____".stJam____.stData, // TODO(E-Planung)
xOutStopper1 => "MB____", // TODO(E-Planung) xOutStopper1 => "MB____", // TODO(E-Planung)
xOutStopper2 => "MB____", // TODO(E-Planung) xOutStopper2 => "MB____", // TODO(E-Planung)
xOutSw1ExTo3 => "MB____", // TODO(E-Planung) xOutSw1ExTo3 => "MB____", // TODO(E-Planung)
@@ -590,14 +610,23 @@ REGION TRO10 (2Sep2Swi) Sep 0005, 0036
stInOutHMI := "DB_Interface_HMI".stTRO.TRO10, stInOutHMI := "DB_Interface_HMI".stTRO.TRO10,
nOutStateLast => "DB_GLOB_TroState".arTroState["cMainTro____"]); // TODO(E-Planung) nOutStateLast => "DB_GLOB_TroState".arTroState["cMainTro____"]); // TODO(E-Planung)
REGION Direction "bx____-TriggerEnable" := #arCognexInterface["cScanner____"].xOutCamTriggerEnable; // TODO(E-Planung)
"FC_Direction"(nInSwitchNo := "cSwi_____", // TODO(E-Planung) "bx____-Trigger" := #arCognexInterface["cScanner____"].xOutCamTrigger; // TODO(E-Planung)
nOutDirection => #TRO10.nInDirection1, "bx____-ResultsAck" := #arCognexInterface["cScanner____"].xOutCamResultsAck; // TODO(E-Planung)
InOutCarrier := "DB_JamArea____".stJam____.arCarrier[1]);
"FC_Direction"(nInSwitchNo := "cSwi_____", // TODO(E-Planung) "bx____-TriggerEnable" := #arCognexInterface["cScanner____"].xOutCamTriggerEnable; // TODO(E-Planung)
"bx____-Trigger" := #arCognexInterface["cScanner____"].xOutCamTrigger; // TODO(E-Planung)
"bx____-ResultsAck" := #arCognexInterface["cScanner____"].xOutCamResultsAck; // TODO(E-Planung)
REGION Direction
"FC_Direction"(nInSwitchNo := "cSwi_____", // TODO(E-Planung)
nOutDirection => #TRO10.nInDirection1,
InOutCarrier := "DB_JamArea____".stJam____.arCarrier[1]); // TODO(E-Planung)
"FC_Direction"(nInSwitchNo := "cSwi_____", // TODO(E-Planung)
nOutDirection => #TRO10.nInDirection2, nOutDirection => #TRO10.nInDirection2,
InOutCarrier := "DB_JamArea____".stJam____.arCarrier[1]); InOutCarrier := "DB_JamArea____".stJam____.arCarrier[1]); // TODO(E-Planung)
END_REGION END_REGION
END_REGION END_REGION
+7 -2
View File
@@ -17,6 +17,7 @@ Diff pruefen, dann die Referenzen neu schreiben mit
import os import os
import re import re
import shutil
from pathlib import Path from pathlib import Path
import pytest import pytest
@@ -101,7 +102,7 @@ def test_cli_schreibt_referenz(name: str, tmp_path: Path, monkeypatch) -> None:
def test_cli_templates_und_strict(tmp_path: Path, monkeypatch) -> None: def test_cli_templates_und_strict(tmp_path: Path, monkeypatch) -> None:
"""--templates schreibt die Template-Referenz; --strict bricht ab, solange """--templates schreibt die Template-Referenz; --strict bricht ab, solange
ein FB-Typ der Anlage (mubea: u. a. 2Sep2Swi) kein Template hat.""" ein FB-Typ der Anlage kein Template hat (hier: Template-Ordner ohne 2Sep2Swi)."""
if _aktualisieren(): if _aktualisieren():
pytest.skip("Referenzen werden nur ueber die render-Tests geschrieben") pytest.skip("Referenzen werden nur ueber die render-Tests geschrieben")
monkeypatch.setenv("SKEL_RESULTS", str(tmp_path)) monkeypatch.setenv("SKEL_RESULTS", str(tmp_path))
@@ -113,7 +114,11 @@ def test_cli_templates_und_strict(tmp_path: Path, monkeypatch) -> None:
assert _maskiert(ist) == soll assert _maskiert(ist) == soll
(tmp_path / "mubea_FB_Main.scl").unlink() (tmp_path / "mubea_FB_Main.scl").unlink()
assert scl_skeleton.main(["--json", json_file, "--templates", "--strict"]) == 1 ohne_2sep2swi = tmp_path / "templates"
shutil.copytree(scl_skeleton.TEMPLATE_DIR, ohne_2sep2swi)
(ohne_2sep2swi / "FB_ILS_MTRO_2Sep2Swi.scl.j2").unlink()
assert scl_skeleton.main(["--json", json_file, "--templates", str(ohne_2sep2swi),
"--strict"]) == 1
assert not (tmp_path / "mubea_FB_Main.scl").exists() assert not (tmp_path / "mubea_FB_Main.scl").exists()
assert scl_skeleton.main(["--json", json_file, "--templates", assert scl_skeleton.main(["--json", json_file, "--templates",