hw_import --dxf: gemeinsame Zeichnung (Layout + E-Planung) als Hardwarequelle
hw_import liest mit --dxf statt der Positionsdatei eine DXF, in der Layout
und E-Planung zusammen liegen (Dematic): jeder Block mit Attribut IO ist ein
E-Bauteil (IO/VERW/BEZEICHNUNG/KENNZEICHNUNG, Einfuegepunkt), schon in
Layout-Koordinaten (HardwareDocument.layoutCoordinates). --conveyor-from-motor
nimmt den Foerderer aus der Motornummer, wenn kein K0102/#106 dasteht
("Motor KR-MA0055" -> K0055); "ILS-VARIO" zaehlt als Strecke.
merge_hw_layout: bei layoutCoordinates kein Lagebezug (Identitaet, nichts
abgelegt); --rules findet einen blossen Namen in SKEL_CFG. Neue Regeldatei
cfg/e_planning_dematic.ini (Sensor/Stopper gleiche Nummer, Weichenventil =
Nummer des Stausensors, Abstaende an dematic_merge..dxf gemessen).
Fehler behoben: zwei Antriebs-TROs auf einem Layout-Foerderer (Dematic VF_6,
TRO04/TRO06) bekamen beide denselben Vario-Motor. Jetzt Widerspruch mit
Vorschlag; scl_context faellt dann nicht auf den Motor des Foerderers zurueck.
Dematic: 115 Namen im FB_Main (alle im TIA-Import), offene Stellen 730 -> 615.
cfg/dematic_merge_tro_ids.ini: TRO-IDs der Dematic-Anlage.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+48
-6
@@ -371,6 +371,19 @@ def resolve_transform(points, devices, anchors, cfg_dir: Path, csv_name: str,
|
||||
return transform
|
||||
|
||||
|
||||
def _same_drawing(points: list[LayoutPoint], drawing: str) -> Transform:
|
||||
"""Lagebezug einer gemeinsamen Zeichnung (hw_import --dxf): keiner.
|
||||
|
||||
Die E-Symbole stehen schon in Layout-Koordinaten. Ihr Versatz neben dem
|
||||
Bauteil (Dematic ~600 mm) ist Zeichenabstand, keine Verschiebung - ein
|
||||
eingepasster Bezug wuerde ihn nur verzerren. Er steckt in max_mm/soll_mm
|
||||
der Regeln.
|
||||
"""
|
||||
n = sum(1 for p in points if p.kind == "Separator")
|
||||
return Transform(dx=0.0, dy=0.0, source="zeichnung", anchor="gemeinsame Zeichnung",
|
||||
matched=n, candidates=n, dxf_file=drawing)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Slots
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -529,9 +542,20 @@ def _conveyor_kinds(hw: HardwareDocument) -> dict[str, str]:
|
||||
|
||||
def bind_drives(doc: TroDocument, conveyors: list[ConveyorBinding],
|
||||
hw: HardwareDocument) -> list[Binding]:
|
||||
"""Antriebs-Slots (Vario): Motor und Motorschutz des zugeordneten Foerderers."""
|
||||
"""Antriebs-Slots (Vario): Motor und Motorschutz des zugeordneten Foerderers.
|
||||
|
||||
Tragen mehrere TROs einen Antriebs-Slot auf demselben Layout-Foerderer
|
||||
(Dematic VF_6: zwei Vario-TROs, drei Vario-Motoren), hat jeder TRO seinen
|
||||
eigenen Motor - welcher, sagt die Mehrheit je Foerderer nicht. Dann wird
|
||||
der Antrieb ein Widerspruch (BMK als Vorschlag), Korrektur von Hand.
|
||||
"""
|
||||
devices = hw.by_bmk()
|
||||
by_layout = {c.layout_id: c for c in conveyors if c.status == "zugeordnet"}
|
||||
sharing: dict[str, list[str]] = {}
|
||||
for tro in doc.tros:
|
||||
for s in tro.slots:
|
||||
if s.layout_id and any(r.rstrip("?") in _DRIVE_ROLES for r in s.roles):
|
||||
sharing.setdefault(s.layout_id.split("-", 1)[0], []).append(tro.tro_id)
|
||||
bindings = []
|
||||
for tro in doc.tros:
|
||||
for s in tro.slots:
|
||||
@@ -541,17 +565,24 @@ def bind_drives(doc: TroDocument, conveyors: list[ConveyorBinding],
|
||||
if conv is None:
|
||||
continue
|
||||
roles = [r.rstrip("?") for r in s.roles]
|
||||
shared = sharing.get(s.layout_id.split("-", 1)[0], [])
|
||||
for role, attr in _DRIVE_ROLES.items():
|
||||
bmk = getattr(conv, attr)
|
||||
if role not in roles or not bmk:
|
||||
continue
|
||||
dev = devices.get(bmk)
|
||||
status = "zugeordnet" if dev and dev.in_tia else "widerspruch"
|
||||
note = f"Antrieb von {conv.eplan_name}"
|
||||
if len(shared) > 1:
|
||||
status = "widerspruch"
|
||||
note = (f"{conv.layout_name or conv.layout_id} traegt {len(shared)} "
|
||||
f"Antriebs-TROs ({', '.join(shared)}) - Antrieb je TRO von Hand "
|
||||
f"({OVERRIDES_FILE}); Vorschlag {conv.eplan_name}")
|
||||
bindings.append(Binding(
|
||||
tro=tro.tro_id, slot=s.slot, role=role, layout_id=s.layout_id,
|
||||
bmk=bmk, constant=dev.constant if dev else "",
|
||||
address=dev.address if dev else "", source="positionsdraw",
|
||||
rule="mehrheit", status="zugeordnet" if dev and dev.in_tia else "widerspruch",
|
||||
note=f"Antrieb von {conv.eplan_name}"))
|
||||
rule="mehrheit", status=status, note=note))
|
||||
return bindings
|
||||
|
||||
|
||||
@@ -690,7 +721,9 @@ def build_anlage(doc: TroDocument, hw: HardwareDocument, rules: list[Rule],
|
||||
assignments: list[Assignment] = []
|
||||
conveyors: list[ConveyorBinding] = []
|
||||
if hw.field_devices():
|
||||
if transform is None:
|
||||
if transform is None and hw.layout_coordinates:
|
||||
transform = _same_drawing(points, hw.positions_file)
|
||||
elif transform is None:
|
||||
transform = resolve_transform(points, devices, anchors, cfg_dir, doc.source,
|
||||
hw.positions_file, re_register, warnings,
|
||||
hw.positions_sha256)
|
||||
@@ -856,6 +889,14 @@ def _in_results(name: str, results: Path) -> Path:
|
||||
return results / name
|
||||
|
||||
|
||||
def _in_cfg(name: str, cfg_dir: Path) -> Path:
|
||||
"""Regeldatei: ein blosser Name, der hier nicht liegt, steht in %SKEL_CFG%."""
|
||||
path = Path(name)
|
||||
if path.is_absolute() or path.parent != Path(".") or path.is_file():
|
||||
return path
|
||||
return cfg_dir / name
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
from material_flow import env_dir
|
||||
|
||||
@@ -864,7 +905,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
cfg_dir = env_dir("SKEL_CFG", "cfg")
|
||||
tro_path = _in_results(args.tro, results)
|
||||
hw_path = _in_results(args.hw, results)
|
||||
rules_path = Path(args.rules) if args.rules else cfg_dir / RULES_FILE
|
||||
rules_path = _in_cfg(args.rules, cfg_dir) if args.rules else cfg_dir / RULES_FILE
|
||||
overrides_path = Path(args.overrides) if args.overrides else cfg_dir / OVERRIDES_FILE
|
||||
for label, path in (("TRO-JSON", tro_path), ("Hardware-JSON", hw_path),
|
||||
("Regeln", rules_path)):
|
||||
@@ -955,7 +996,8 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
||||
help="Hardware-JSON <projekt>_hw.json in %%SKEL_RESULTS%% "
|
||||
"(oder ein Pfad)")
|
||||
parser.add_argument("--rules", metavar="DATEI",
|
||||
help=f"Regeldatei. Standard: %%SKEL_CFG%%\\{RULES_FILE}")
|
||||
help=f"Regeldatei (Name in %%SKEL_CFG%% oder ein Pfad), z. B. "
|
||||
f"e_planning_dematic.ini. Standard: %%SKEL_CFG%%\\{RULES_FILE}")
|
||||
parser.add_argument("--overrides", metavar="DATEI",
|
||||
help=f"Handkorrekturen. Standard: %%SKEL_CFG%%\\{OVERRIDES_FILE} "
|
||||
f"(fehlt sie, keine)")
|
||||
|
||||
Reference in New Issue
Block a user