Compare commits

...

81 Commits

Author SHA1 Message Date
g.jahn cd6b9dc31f in BMK Liste Sensoren hinzugefügt 827072102 / 400101729 / 200000525
Verb.Leitung hinzugefügt
Sensor Kabel ergänzt
2026-06-23 15:02:22 +02:00
g.jahn f4dac5677e Doppelbügelerkennung neue Kabelzuweisung 2026-06-22 10:20:42 +02:00
g.jahn 8d0915b97e Kabelzuordnung 790000213 Doppelbügelerkennung geändert 2026-06-22 10:09:48 +02:00
g.jahn 4a4cdcacc6 Bezeichnung in 721002008 geändert 2026-06-22 09:36:04 +02:00
g.jahn db9653286d Sensor für Doppelbügelerkennung eingetragen 790000213 2026-06-22 09:19:06 +02:00
m.stangl 50609f80cf Symboltabelle um Encoder und Scanner ergänzt in Doku 2026-06-18 12:18:42 +02:00
m.stangl 8c11d15494 Verweis auf die Symbole und deren Aufbau noch dazu 2026-06-18 12:12:37 +02:00
m.stangl b6ab35d8be Abschnitt in der ioconverter Anwenderdoku noch genauer beschrieben 2026-06-18 12:07:27 +02:00
m.stangl eca5a82644 eigene Doku für iocnonvertert gebaut 2026-06-18 12:01:03 +02:00
m.stangl 046bcf7290 kleinere Berichtigungen noch im Readme.md 2026-06-18 11:49:35 +02:00
m.stangl a1d86500f2 Icons etwas grösser gemacht 2026-06-18 11:46:56 +02:00
m.stangl bed533e66b icons noch in die Vorschau des Reamde.md mit rein 2026-06-18 11:41:29 +02:00
m.stangl 64506684a2 Claude.md aktualisiert. Einfaches Readme.md für die gitea Vorschaug gebaut. Doku aktualisiert 2026-06-18 11:36:45 +02:00
m.stangl e157acf77e nach den Encoder Symbolen muss in Zukunft auch gesucht werden, wenn man die Kabel dazu möchte 2026-06-18 11:03:06 +02:00
m.stangl 5e7880a3ad Scannerkabel und Encoder Kabel nicht nur speziell auf eine SivasNummer definieren, sondern generell. Sonst fehlt der Fallback, falls eine andere Sivasnummer im Symbol steht 2026-06-18 10:44:39 +02:00
m.stangl 45c8973975 Kleiner Fix, falls ein Leerzeichen vom Sivas mitkommt, wird die Datei nicht gefunden. 2026-06-18 10:43:13 +02:00
g.jahn 594abb8b2e Encoder hinzugefügt 2026-06-18 10:05:47 +02:00
g.jahn d1ab663ff5 BX HINZUGEFÜGT 2026-06-18 09:59:14 +02:00
g.jahn 437c6d23fd Ventilkabel eingetragen [WD_Q-929012603] mit Kabel 2026-06-17 13:35:57 +02:00
g.jahn cfe1104c5c [WD_I-200000375] Sensorkabel in Kabel.cfg eingetragen 2026-06-17 13:16:51 +02:00
g.jahn 78d6edd6a8 Ventilkabel eingetragen in BMK.cfg MB-929012603 = WD_Q-929012603 2026-06-17 11:43:48 +02:00
g.jahn 4956525f24 Teilenummer 929012603 in [WD_Q-929012603] eingetragen 2026-06-17 10:23:16 +02:00
g.jahn 676429c053 929012603 - WEGEVENT.5/2 MONOSTABIL SY5120-5WAOU-C6F-Q in Bezeichner.cfg und im Kabel.cfg [WD_I-929012603] hinzugefügt. 2026-06-16 14:43:21 +02:00
g.jahn f868032b67 lAYER VON ILS_Encoder-800 eingetragen 2026-06-11 12:55:10 +02:00
g.jahn 8c98f99d39 noch fehlende Layer Omniflo und Flex Layer eingetragen. 2026-06-11 12:49:53 +02:00
g.jahn e07968981b Kabelbezeichnung WF_BX auf WF_B geändert 2026-06-10 08:07:42 +02:00
g.jahn b0af6f73dc BMK umbennant, BX = WF_B, WD_I zu BX = WF_BX, WD_I 2026-06-09 13:03:18 +02:00
g.jahn 143d790a1d [WF_BX-829534306] Scannerkabel zugeordnet 2026-06-09 12:54:15 +02:00
g.jahn 28dc81d21f Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-04-29 10:50:28 +02:00
g.jahn e3be04ec39 ILS Layer hinzugefügt von den neuen Symbole;
790821103 = SCHALTSCHRANK 1200x2000x400 KPL. hinzugefügt
2026-04-29 10:49:30 +02:00
m.schellhammer 75f6e8dca8 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-04-21 11:40:28 +02:00
m.schellhammer c572496f3d BMK.cfg , [Cabinet-Pattern] um Bedientableau-Kennung erweitert (+CZ...) 2026-04-21 08:45:29 +02:00
g.jahn cc7cd3c331 Kabel 725000012-3G1,0MM², Steuerleitung hinzugefügt 2026-04-20 16:29:05 +02:00
g.jahn 41811cc827 Rollenschalternummer geändert Art. falsch
Anführungszeichen hinzugefügt haben gefehlt
2026-04-20 16:13:32 +02:00
Michael Stangl f9fd2a0069 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-04-20 15:34:18 +02:00
Michael Stangl 4d5aeb5596 Fehlende Länge des Tunnels zu Fehler deklariert 2026-04-20 15:34:11 +02:00
m.schellhammer ace2eb2dd9 in Bezeichner.cfg die Steuerleitungen und die Bedientableaus kpl. 790002xxx + Rollenschalter 822035037+822035100+822035101 hinzugefügt. 2026-04-17 14:07:46 +02:00
m.schellhammer f58ad8a6bc Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-04-15 17:44:01 +02:00
m.schellhammer 0ec0f75a05 Unterverteiler, Schaltschrankkennzeichnung auf 1-stellige Anlagenkennzeichnung erweitert. 2026-04-15 17:43:16 +02:00
m.stangl e34526b2dd Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-04-15 17:03:34 +02:00
m.stangl 161a940a3b Toter Code und Funktionen entfernt 2026-04-15 17:03:26 +02:00
m.schellhammer 309e2f615e Schaltschrank 700002021 in Bezeichner hinzugefügt 2026-04-15 13:03:48 +02:00
g.jahn 32e5a67fbb Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-04-15 12:34:59 +02:00
g.jahn 5574d1c8d7 Layer Omniflo erweitert; Für Schaltschrank und Bedientableau 2026-04-15 12:17:55 +02:00
m.schellhammer d7fcc2d89a Änderungen vom 23.03.2026 2026-03-23 12:20:15 +01:00
g.jahn acc70e0307 RESET, reset, Firewall in die single Spalte verschoben. 2026-02-26 12:12:07 +01:00
g.jahn 7d3cfc423a trans Block verwendet für Begriffe RESET, reset, Firewall. 2026-02-26 11:14:24 +01:00
g.jahn 1dad277073 Einige Begriffe ergänzt 2026-02-26 11:07:19 +01:00
m.stangl 10caa9d07f Berichtigung von lib/translate.py aus dem letzen Merge 2026-02-25 15:50:06 +01:00
m.stangl 7ec65d6c77 .bat datei Änderung erneut eingepflegt. Ging anscheinend verloren 2026-02-24 16:53:38 +01:00
g.jahn 20b36cea9b alter gemergter Block entfernt 2026-02-24 16:07:05 +01:00
g.jahn be1864c4d8 reset wird jetzt nach reset übersetzt 2026-02-24 16:01:15 +01:00
g.jahn 6b7eaa43df Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen
# Conflicts:
#	translation/CS.cfg
2026-02-24 15:54:16 +01:00
m.schellhammer 04d73b78c4 ANpassunge 2026-02-24 15:46:31 +01:00
m.stangl 71cf567b8d Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-02-24 15:44:42 +01:00
m.stangl b2f93da92b .txt Dateien können jetzt auch auf die Icons gedroppt werden 2026-02-24 15:44:32 +01:00
m.schellhammer 0067b8bf7d Übersetzungstexte CS überarbeitet. 2026-02-24 13:56:32 +01:00
m.schellhammer 2ea1042792 1) translator.cfg reset von Transfer zu single verschoben
2) cs-cfg symbol-layer text-IT hinzugefügt
2026-02-24 08:55:10 +01:00
m.stangl aba46bd13a argument --retranslate-txt impl. Neue Routinen _parse_txt_sections _run_retranslate_txt 2026-02-17 15:33:47 +01:00
m.stangl ff6ba900c6 refactoring von translate.py. Config lesen in eine Methode gepackt. Multilang-json Struktur in eigene Methode 2026-02-17 15:02:58 +01:00
m.stangl a3a37003b6 Rawconfig Parser verwendet, damit die Sektion [trans] keine Probleme mehr bereitet, weil Zuordnungen fehlen. 2026-02-17 14:38:13 +01:00
m.schellhammer 554f1f3c1f transverblock eingesetzt 2026-02-17 13:56:21 +01:00
m.schellhammer 1872ea90f3 Doppelte Zeile Entfernt 2026-02-17 13:48:11 +01:00
m.schellhammer 4dc6119768 Doppelten Text in Zeile 80 entfernt 2026-02-17 13:37:07 +01:00
m.schellhammer bb9eab77f2 tschechische Übersetzungen erweitert und korrigiert. 2026-02-12 10:29:00 +01:00
g.jahn a916151e63 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-02-12 08:28:06 +01:00
g.jahn e29a5d1534 Text angepasst 2026-02-12 08:27:41 +01:00
m.schellhammer 0bb00183d4 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-02-12 07:59:23 +01:00
m.stangl a54885eef3 transfer Block in CS.cfg eingefügt 2026-02-11 23:27:48 +01:00
m.stangl de2720af45 transfer Sektion wird mit berücksichtigt von translate_block_attribute 2026-02-11 23:26:54 +01:00
m.schellhammer 163332f86c TEXTE ANGEPASST 2026-02-11 13:36:09 +01:00
m.schellhammer 4b7bc5e2ee NEUE TEXTE HINZUGEFÜGT 2026-02-11 13:29:20 +01:00
m.stangl a79db3f116 Ziel ist der übersetzen dxf ist jetzt der Share 2026-02-11 09:53:44 +01:00
m.stangl 58a70aaf5d übersetzte dxf datei wird ins Ziel verschoben 2026-02-11 09:49:15 +01:00
m.stangl 28cd3c630e main Funktion aufgeteilt 2026-02-10 17:25:07 +01:00
m.stangl 002b5e0bf1 Prorammbeschreibung aktualisiert. Duplikate werden aus den zu übersetzenden Texten entfernt. 2026-02-10 16:48:01 +01:00
m.stangl 46e2d8663b Es wird in Zukunft immer ein multilang Block geschrieben. Nur ohne --translate wird die flache Hierarchie nach wie vor bedient 2026-02-10 15:51:09 +01:00
m.stangl 5cbd290a16 Korrektur: Translated und untranslated müssen neu angeschaut werden 2026-02-10 15:44:16 +01:00
m.schellhammer beb84c0bf9 ignoremuster ergänzt 2026-02-10 11:29:38 +01:00
m.schellhammer e1725df45a Pfad angepasst 2026-02-10 11:28:30 +01:00
m.schellhammer 4a676b6316 Übersetzungen in sich entfernt 2026-02-10 11:27:44 +01:00
20 changed files with 2386 additions and 801 deletions
+298
View File
@@ -0,0 +1,298 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Overview
This is a Python-based cable routing automation tool for industrial plant layouts. The system reads DXF files containing equipment positions and cable trays, calculates optimal cable paths using graph algorithms, and generates cable lists with SIVAS article numbers for procurement.
## Architecture
The codebase follows a modular three-stage pipeline:
1. **Position Extraction** ([getpositions.py](lib/getpositions.py)) - Extracts equipment positions and cable tray geometries from DXF files
2. **Route Calculation** ([routing.py](lib/routing.py)) - Builds graph models and calculates shortest paths between equipment and distributors
3. **Output Generation** ([drawdxf.py](lib/drawdxf.py)) - Creates DXF files with cable paths and Excel lists with cable specifications
### Pipeline Data Flow
```
DXF file
→ getpositions.py → *_positionsdraw.json (positions, racks, distributors, mappings)
→ routing.py → *_todraw.json (cable routes with coordinates and lengths)
→ drawdxf.py → *.dxf + *.xlsx + BOM (final output files)
```
The JSON intermediate files serve as interfaces between stages and are valuable for debugging. Each stage can be run independently.
### Workflow Modes
The system supports four primary workflows:
1. **Full Cable Routing** (`getexdraw.bat`) - Complete pipeline from DXF input to cable paths and BOMs
2. **I/O Conversion** (`ioconverter.bat`) - Converts DXF equipment data to Excel formats for TIA, WSCAD, and other systems
3. **Text Extraction** (`extract.bat`) - Extracts all TEXT and MTEXT objects from DXF files to multiple formats (Excel, JSON, Text) for translation purposes
4. **Translation** (`tr2dxf.bat`, `tr2dxf_cs.bat`, etc.) - Translates DXF text content into target languages (Czech, English, French, Italian, Spanish)
### Core Modules
- **[plant.py](lib/plant.py)** - Main business logic containing the `Anlage` class that models industrial plants, manages equipment connections, and implements graph-based routing algorithms
- **[model.py](lib/model.py)** - Data classes for points, equipment, distributors, and cable trays using dataclasses and dacite
- **[graphbuild.py](lib/graphbuild.py)** - Graph construction utilities for network topology
- **[linesweep.py](lib/linesweep.py)** - Geometric algorithms for line intersection detection
### Utility Modules
- **[error_collector.py](lib/error_collector.py)** - Centralized error/warning collection system with two severity levels; used across getpositions and drawdxf
- **[utils.py](lib/utils.py)** - Common utility functions: file I/O, environment variable checks, JSON operations, DXF file handling, dictionary merging
- **[updateconfignames.py](lib/updateconfignames.py)** - Updates SIVAS article descriptions in `bezeichner.cfg` from external SIVAS database exports (CSV files in `data/`)
- **[flags.py](lib/flags.py)** - Icon/flag generation using PIL for language flags (EN, FR, IT, ES, CS)
### Export & Conversion Modules
- **[portalexport.py](lib/portalexport.py)** - Exports equipment I/O data to Excel formats for TIA Portal and WSCAD
- **[ioconverter.py](lib/ioconverter.py)** - `ExcelConverter` class for converting I/O lists with input/output identifier mappings
- **[translate.py](lib/translate.py)** - Comprehensive text extraction/translation: extracts TEXT, MTEXT, and block attributes from DXF/DWG files; supports Excel, JSON, Text export formats
### DXF Utility Modules
- **[create_dxf_symbols.py](lib/create_dxf_symbols.py)** - Creates DXF symbol blocks (grounding, switchboard, subdistribution, motor symbols)
- **[create_example.py](lib/create_example.py)** - `TestDataGenerator` for generating synthetic test DXF files with defined layouts
- **[create_numbers.py](lib/create_numbers.py)** - Generates/updates numbered symbols in DXF files based on RENAMER layer configuration
### Configuration System
The system uses configuration files in `cfg/`:
- **`BMK.cfg`** - Equipment identification codes, cable type mappings, routing inclusion/exclusion rules, cabinet/tunnel patterns, length adjustments
- **`kabel.cfg`** - SIVAS article number mappings for different cable types and lengths (sections like `[MA]`, `[WD_Q]`, `[WD_I]`, etc.)
- **`allgemein.cfg`** - Layer names for racks/distributors/tunnels, geometric tolerances, connection parameters
- **`bezeichner.cfg`** - Article number descriptions, auto-populated from SIVAS database
- **`translator.cfg`** - Text filtering for translation (wildcard and regex ignore patterns)
- **`enumerate.cfg`** - Symbol enumeration settings (RENAMER layers, polyline distances)
- **`translation/CS.cfg`** - Czech language translation key mappings
**Important**: When adding a new equipment prefix, it must be added to **both** `[Routing-Include]` and `[Cable-Mapping]` in `BMK.cfg`, and the corresponding cable section must exist in `kabel.cfg`.
**Article-specific mappings**: `[Cable-Mapping]` supports article-number-specific entries like `MB-929012603 = WD_Q-929012603` alongside generic prefix mappings like `MA = MA`. The specific entry takes precedence when the sensor's article number matches.
**Current prefixes in `[Routing-Include]`**: MA, MB, QM, BG, BP, BX, PO, SF, PF, GF
## Common Commands
### Main Execution
```bash
# Process a DXF file for cable routing (drag-and-drop onto desktop shortcut in production)
bin\getexdraw.bat <filename.dxf>
# Convert DXF to I/O lists for TIA Portal, WSCAD, etc.
bin\ioconverter.bat <filename.dxf>
# Extract text from DXF files for translation
bin\extract.bat <filename.dxf>
# Translate DXF to Czech (also: tr2dxf_en, tr2dxf_fr, tr2dxf_it, tr2dxf_es)
bin\tr2dxf_cs.bat <filename.dxf>
# PowerShell alternative for getexdraw
bin\getexdraw.ps1 <filename.dxf>
# Manual execution of pipeline stages
bin\getpositions.bat --filename <file.dxf> -s -r -w <output.json>
bin\routing.bat --filename <positions.json> -w <todraw.json>
bin\draw_dxf.bat --filename <todraw.json> --new <output.dxf> -x <output.xlsx>
bin\portalexport.bat --filename <positions.json> --outname <basename>
bin\translate.bat --filename <file.dxf> --extract --export-type excel,json --outname <output>
```
**Note**: All `.bat` scripts have corresponding `.sh` equivalents for Linux/macOS systems.
### Development and Testing
```bash
# Install Python dependencies
bin\install_py.bat
# Run automated test suite (all test files)
bin\run_tests.bat
# Run test for a single file (most common for development)
bin\run_test.bat <testname>
bin\run_test.bat easy
bin\run_test.bat easy --clean
# Run tests for specific file (alternative syntax)
bin\run_tests.bat --file <testname>
# Run tests in different modes
bin\run_test.bat <testname> --ioconverter
bin\run_test.bat <testname> --translation
bin\run_tests.bat --ioconverter
# Create reference files from current outputs
bin\run_tests.bat --create-references
# Clean up work folders after tests
bin\run_tests.bat --clean
# Run unit tests
bin\run_unittests.bat
# Individual component testing
python lib\getpositions.py --help
python lib\routing.py --graph # Shows visual graph
python lib\drawdxf.py --help
```
### Production Deployment
```bash
# Create desktop shortcuts with drag-and-drop icons for all tools
bin\dropItem_create.bat
# Remove desktop shortcuts
bin\dropItem_remove.bat
```
### Configuration Management
```bash
# Update SIVAS article descriptions
python lib\updateconfignames.py
# Convert between formats
python lib\ioconverter.py
```
## Development Guidelines
### Code Style
- Use German comments and variable names for consistency with existing codebase
- Follow dataclass patterns established in [model.py](lib/model.py)
- Maintain separation between geometric operations (Shapely) and graph algorithms (NetworkX)
### Configuration Changes
- Always update corresponding `.cfg` files when adding new equipment types or cable categories
- A new equipment prefix needs entries in: `[Routing-Include]`, `[Cable-Mapping]` (both in `BMK.cfg`), and a matching section in `kabel.cfg`
- Test configuration changes with sample DXF files in [testdata/](testdata/) directory
- Configuration files use Windows INI format with specific section naming conventions
### Error Handling
The system uses [error_collector.py](lib/error_collector.py) for centralized error/warning collection with two severity levels:
- **Errors** (critical issues that affect output correctness):
- Equipment connection failures (distance tolerances)
- Missing SIVAS article numbers
- Invalid DXF block attributes
- Graph routing failures
- Missing or overdefined tunnel positions
- Duplicate equipment IDs
- **Warnings** (potential issues, processing continues):
- Missing or incomplete block attributes
- Invalid KENNZEICHNUNG format
- Missing tunnel length specifications
All issues are collected in the `warnings` section of output JSON files (e.g., `*_positionsdraw.json`). Critical errors also generate separate `*_errors.json` files. See [doc/Anwenderdoku_kurz.md](doc/Anwenderdoku_kurz.md) for detailed error descriptions and resolution steps.
### Config Validation
On startup, `getpositions.py` validates configuration consistency and reports:
- Prefixes in `[Routing-Include]` without a `[Cable-Mapping]` entry
- Cable sections referenced in `[Cable-Mapping]` that are missing from `kabel.cfg`
### Testing
The project includes a comprehensive automated test suite:
- Test DXF files stored in [testdata/](testdata/) (e.g., `easy.dxf`, `easy_sps.dxf`, `easy_hoehe.dxf`, `easy_3tunnels.dxf`, `Erdungsbsp.dxf`)
- Reference JSON outputs stored alongside test DXF files
- Test runner ([run_tests.py](lib/run_tests.py)) compares generated outputs against references with diff reporting
- Supports `getexdraw`, `ioconverter`, and `translate` workflow testing
- Visual graph debugging available with `--graph` flag in routing
- Test cases cover: standard routing, SPS integration, height differences, tunnel overdefinition, grounding, duplicate IDs, translation
- Unit tests in `lib/` (`error_collector_test.py`, `utils_test.py`, `flags_test.py`, `create_numbers_test.py`, `getpositions_test.py`)
- Additional edge case tests in [tests/](tests/) directory (e.g., `test_ioconverter_errors.py`)
## File Structure
```text
bin/ # Batch scripts (.bat) and shell scripts (.sh) for all workflows
cfg/ # Configuration files (BMK, cable mappings, tolerances, translation filters)
cfg/translation/# Language-specific translation configs (CS.cfg)
lib/ # Python modules (core pipeline, utilities, tests)
work/ # Working directory for processing results (generated output)
testdata/ # Test DXF files and reference outputs for automated testing
tests/ # Additional test files and edge case test data
doc/ # Comprehensive German documentation (Markdown + PDF)
doc/img/Icons/ # Icons for desktop shortcuts
data/ # SIVAS article number CSV reference files (auto-populated)
translation/ # Translation configurations
```
## Dependencies
Key Python packages (see [lib/requirements.txt](lib/requirements.txt)):
- `ezdxf` - DXF file reading/writing
- `shapely` - Geometric operations
- `networkx` - Graph algorithms
- `openpyxl` - Excel output generation
- `pandas` - Data manipulation
- `matplotlib` - Graph visualization
- `dacite` - Dataclass conversion utilities
- `PyMuPDF` - PDF processing capabilities
- `pillow` - Image processing (flag/icon generation)
- `pytest` - Testing framework
## Output Files
### Cable Routing Workflow (getexdraw)
- `*_cables.dxf` - DXF with drawn cable paths
- `*_cables.xlsx` - Cable list with lengths and SIVAS numbers
- `*_BOM.xlsx` - Complete bill of materials
- `*_positionsdraw.json` - Intermediate position data with routing info
- `*_todraw.json` - Intermediate routing data for drawing
- `*_errors.json` - Error report (if validation fails)
### I/O Conversion Workflow (ioconverter)
- `*-TIA.xlsx` - Excel export for TIA Portal
- `*-WSCAD.xlsx` - Excel export for WSCAD
- `*_positionsconv.json` - Intermediate position data for conversion
- `*_errors.json` - Error report (if validation fails)
### Text Extraction Workflow (extract)
- `*_texts.xlsx` - Excel file with all TEXT and MTEXT entities from DXF for translation
### Translation Workflow (tr2dxf)
- Translated DXF files with text replaced in target language
## Environment Variables
The system uses environment variables defined in [bin/setenv.bat](bin/setenv.bat):
- `PROJECT` - Root directory of the project
- `PROJECT_BIN` - Binary/script directory
- `PROJECT_CFG` - Configuration directory
- `PROJECT_DOC` - Documentation directory
- `PROJECT_LIB` - Python library directory
- `PROJECT_DATA` - SIVAS reference data directory
- `PROJECT_WORK` - Working directory for outputs
- `PROJECT_TEST` - Test data directory (testdata/)
- `PROJECT_LOG` - Log directory
- `PROJECT_TRANSLATION` - Translation directory
- `PROJECT_IO_RESULTS` - Network location for I/O converter results
- `PROJECT_BOM_RESULTS` - Network location for BOM results
- `SIVAS_TEILESTAMM` - Path to SIVAS parts database export tool
- `SIVAS_EXCEL_EXPORT_DIR` - Output directory for SIVAS data exports
- `INSTALL_DIR` - Desktop shortcut installation location
Local overrides can be placed in `bin/_setenv.bat` (not tracked in git).
+114
View File
@@ -0,0 +1,114 @@
# Kabeltool - Automatisierte Kabellängenermittlung
Automatisiertes Toolset zur Ermittlung von Kabellängen in industriellen Anlagenlayouts. Aus einer DXF-Zeichnung werden Gerätepositionen und Kabeltrassen extrahiert, optimale Kabelwege berechnet und Stücklisten mit SIVAS-Artikelnummern erzeugt.
Die Übersetzungswerkzeuge ermöglichen den einfachen Transfer der .dxf Dateien in eine andere Sprache.
## Liste der vorhandenen Werkzeuge
| | Workflow | Skript | Beschreibung | Ausgabe |
|---|----------|--------|--------------|---------|
| <img src="doc/img/Icons/Icon_getex.png" width="128"> | **Cable Routing** | `getexdraw.bat` | Vollständige Kabelberechnung mit Wegführung und Stücklisten | `*_cables.dxf`, `*_cables.xlsx`, `*_BOM.xlsx` |
| <img src="doc/img/Icons/Icon_portal.png" width="128"> | **I/O Conversion** | `ioconverter.bat` | Export von Gerätelisten für TIA Portal, WSCAD u.a. | `*-TIA.xlsx`, `*-WSCAD.xlsx` |
| <img src="doc/img/Icons/dxf2txt.png" width="128"> | **Text Extraction** | `extract.bat` | Textextraktion aus DXF für Übersetzung | `*_texts.xlsx`, `*_texts.json` |
| <img src="doc/img/Icons/dxfCs.png" width="128"> | **Translation** | `tr2dxf_<lang>.bat` | Übersetzung von DXF-Texten (CS, EN, FR, IT, ES) | `*_<lang>.dxf` |
## Verwendung
DXF-Datei per **Drag & Drop** auf die Desktop-Verknüpfung ziehen (erstellt via `bin\dropItem_create.bat`) oder direkt aufrufen:
```bash
bin\getexdraw.bat <meine_anlage.dxf>
```
## Pipelines
### Cable Routing (`getexdraw.bat`)
```text
DXF-Datei
1. getpositions.py --> Positionen extrahieren --> *_positionsdraw.json
2. routing.py --> Kabelwege berechnen --> *_todraw.json
3. drawdxf.py --> DXF + Excel erzeugen --> *_cables.dxf, *_cables.xlsx, *_BOM.xlsx
```
### I/O Conversion (`ioconverter.bat`)
```text
DXF-Datei
1. getpositions.py --> Positionen extrahieren --> *_positionsconv.json
2. portalexport.py --> Excel-Export erzeugen --> *-TIA.xlsx, *-WSCAD.xlsx, *-EA.xlsx
```
### Text Extraction & Translation (`extract.bat` / `tr2dxf_<lang>.bat`)
```text
DXF-Datei
1. translate.py --extract --> Texte extrahieren --> *_texts.xlsx, *_texts.json
2. translate.py --translate --> Texte übersetzen --> *_<lang>.dxf
```
## Installation
```bash
# Repository klonen
git clone http://gitea.schoenenberger.de/mistangl/kabellaengen.git
# Python-Abhängigkeiten installieren
bin\install_py.bat
# Desktop-Verknüpfungen erstellen
bin\dropItem_create.bat
```
**Voraussetzung**: Python 3.x (lokal installiert oder via `NETWORK_INTERPRETER_PATH` Umgebungsvariable).
## Konfiguration
Konfigurationsdateien in `cfg/` steuern das Verhalten:
| Datei | Zweck |
|-------|-------|
| `allgemein.cfg` | Layernamen, geometrische Toleranzen |
| `BMK.cfg` | Betriebsmittelkennzeichnung, Kabeltyp-Zuordnung, Routing-Regeln |
| `kabel.cfg` | SIVAS-Artikelnummern je Kabeltyp und Kabellänge |
| `bezeichner.cfg` | Artikelnummern-Bezeichner (automatisch aus SIVAS ergänzt) |
> **Hinweis**: Neuer BMK-Prefix muss in `BMK.cfg` unter `[Routing-Include]` **und** `[Cable-Mapping]` eingetragen werden. Die zugewiesene Kabel-Sektion muss in `kabel.cfg` existieren.
## Tests
```bash
# Alle Tests
bin\run_tests.bat
# Einzeltest
bin\run_test.bat easy
# Unit-Tests
bin\run_unittests.bat
```
## Projektstruktur
```text
bin/ Batch- und Shell-Skripte
cfg/ Konfigurationsdateien
lib/ Python-Module
work/ Arbeitsverzeichnis (Ausgabedateien)
testdata/ Test-DXF-Dateien und Referenzdaten
data/ SIVAS-Artikeldaten (CSV)
doc/ Dokumentation (Deutsch)
```
## Dokumentation
- [Anwenderdokumentation](doc/Anwenderdoku.md) - Vollständige Anleitung mit Fehlerbehandlung
- [Kurzanleitung / Fehlerfälle](doc/Anwenderdoku_kurz.md) - Kompakte Referenz
- [I/O Converter](doc/Anwenderdoku_ioconverter.md) - EA-Listen und TIA-Portal/WSCAD-Export
- [Übersetzungsworkflow](doc/translate.md) - Dokumentation zum Textextraktions- und Übersetzungssystem
- [Symbole](doc/Symbole_und_Benennungen.md) - Beschreibung des Aufbaus und Attribute der zu verwendenden Symbole, damit die Erkennung funktioniert
## Lizenz
Intern - Schoenenberger
+26 -12
View File
@@ -1,6 +1,6 @@
@echo off
REM Zentrale Batch-Datei für DXF/JSON-Übersetzungen
REM Zentrale Batch-Datei fr DXF/JSON-bersetzungen
REM Wird von tr2dxf_XX.bat Dateien mit Sprachparameter aufgerufen
if [%1]==[] goto usage
@@ -22,16 +22,13 @@ REM echo Erweiterung: %EXT%
REM echo Verzeichnis: %DIR%
REM echo Sprache: %LANG%
if exist "%PROJECT_BIN%\_setenv.bat" (
echo Lade lokale Umgebungseinstellungen aus _setenv.bat...
call "%PROJECT_BIN%\_setenv.bat"
)
REM Zielverzeichnis
set TARGET_DIR=%PROJECT_WORK%
mkdir "%TARGET_DIR%"
REM Prüfe Dateityp und wähle entsprechenden Workflow
REM Prfe Dateityp und whle entsprechenden Workflow
if /I "%EXT%"==".json" goto retranslate_json
if /I "%EXT%"==".txt" goto retranslate_txt
if /I "%EXT%"==".dxf" goto translate_dxf
if /I "%EXT%"==".dwg" goto translate_dxf
goto invalid_filetype
@@ -48,8 +45,9 @@ if not exist "%PROJECT_WORK%\%RESULT_DXF%" (
pause
goto :eof
)
move %PROJECT_WORK%\%RESULT_DXF% %DIR%
echo.
echo === Translation file created: %PROJECT_WORK%\%RESULT_DXF% ===
echo === Translation file created: %DIR%\%RESULT_DXF% ===
pause
goto :eof
@@ -67,20 +65,36 @@ echo === JSON file updated: %INPUT_FILE% ===
pause
goto :eof
:retranslate_txt
echo.
echo === Re-translating TXT file with current %LANG%.cfg ===
call translate.bat --retranslate-txt "%INPUT_FILE%" --translate %LANG%
if errorlevel 1 (
@echo == failed: re-translating TXT
pause
goto :eof
)
echo.
echo === TXT file updated: %INPUT_FILE% ===
pause
goto :eof
:invalid_filetype
@echo FEHLER: Ungültiger Dateityp: %EXT%
@echo Erlaubt sind: .dxf, .dwg, .json
@echo FEHLER: Ungltiger Dateityp: %EXT%
@echo Erlaubt sind: .dxf, .dwg, .json, .txt
pause
goto :eof
:usage
@echo Usage: %0 ^<LANG^> ^<file.dxf^|file.json^>
@echo Usage: %0 ^<LANG^> ^<file.dxf^|file.json^|file.txt^>
@echo LANG: Zielsprache (CS, EN, FR, IT, ES)
@echo - .dxf/.dwg: Extrahiert und übersetzt Texte zur angegebenen Sprache
@echo - .json: Re-übersetzt vorhandene Übersetzungen mit aktueller LANG.cfg
@echo - .dxf/.dwg: Extrahiert und bersetzt Texte zur angegebenen Sprache
@echo - .json: Re-bersetzt vorhandene bersetzungen mit aktueller LANG.cfg
@echo - .txt: Re-bersetzt TXT-Datei (translations/untranslated) mit aktueller LANG.cfg
@echo.
@echo Beispiele:
@echo %0 CS myfile.dxf
@echo %0 EN translations.json
@echo %0 CS translations_texts.txt
exit /B 1
goto :eof
+1 -1
View File
@@ -6,7 +6,7 @@ for %%i in ("%~1") do (
set "EXT=%%~xi"
set "DIR=%%~dpi"
)
call C:\10-Develop\gitrepos\kabellaengen\bin\setenv.bat
call C:\kabellaengen\bin\setenv.bat
REM echo Dateiname ohne Erweiterung: %FILENAME%
REM echo Erweiterung: %EXT%
+13 -2
View File
@@ -13,6 +13,7 @@ BX
PO
SF
PF
GF
# Kürzel die im Routing Prozess ignoriert werden sollen, zum Beispiel bauteile innerhalb der Schaltschränke
@@ -34,6 +35,9 @@ A\d\d\+(UH0\d)
A\d\d\+(UC\d\d\d)
\+(UC\d\d\d\d)
\+(UH\d\d)
A\d\+(UH0\d)
A\d\+(UZ\d\d\d\d)
A\d\d\+(UZ\d\d\d\d)
# Muster für die Erkennung von Tunneln (z.B. Tunnel1, Tunnel_2, Tunnel-3)
# Patterns for the recognition of Tunnels (e.g. Tunnel1, Tunnel_2, Tunnel-3)
@@ -49,16 +53,23 @@ TUNNEL\d+
[Cable-Mapping]
# Format: PREFIX = Cable-Section[, Section2, ...]
MA = MA
MB = WD_Q
MB-929012603 = WD_Q-929012603
QM = WD_Q
BG = WD_I
BG-829422026 = WD_I-829422026
BG-720002003 = WD_I-720002003
BX = WF_B, WD_I
BG-822035037 = WD_I-822035037
BG-200000375 = WD_I-200000375
BG-790000213 = WD_I-790000213
BG-200000525 = WD_I-200000525
BG-400101729 = WD_I-400101729
BG-827072102 = WD_I-827072102
BX = WF_BX, WD_I
PO = WD_PO
BP = WD_I
SF = WD_I
PF = WD_Q
GF = WF_GF
# Anpassung von berechneter kabellänge um Betrag x aufgrund von z.b. an Sensor existierenden Kabelschwänzen
+57
View File
@@ -35,12 +35,19 @@ Busverteiler-Kennzeichnung
UNTERVERTEILER
0-0_Omniflo_Busverteiler-Kennzeichnung
Schaltschrank-ILS
ILS_Schaltschrank
ILS_Busmodul
Omniflo_Schaltschrank
# Layernamen der Tunnel
# Layernames of Tunnels
[GetPos-Layer_Tunnel]
Busverteiler-Kennzeichnung
0-0_Tunnel
Omniflo_Tunnel
ILS_Tunnel
# Layernamen des Equipments (Sensoren, Motoren, etc.)
@@ -52,6 +59,23 @@ REALE_POSITION_IO
0-0_ILS_EINGANG
0-0_ILS_AUSGANG
0-0_ILS_MOTOR
ILS_Eingang
ILS_Eingang-F
ILS_BT-Eingang
ILS_BT-Eingang-F
ILS_BT-Kennzeichnung
ILS_Schaltschrank
ILS_Schaltschrank-Eingang
ILS_Schaltschrank-Eingang-F
ILS_Ausgang
ILS_BT-Ausgang
ILS_BT-Ausgang-F
ILS_Schaltschrank-Ausgang
ILS_Schaltschrank-Ausgang-F
ILS_Motor
ILS_Scanner
ILS_A-Gruppe
ILS_Encoder-800
0-0-Omniflo_EINGANG
0-0-Omniflo_AUSGANG
0-0-Omniflo_MOTOR
@@ -74,7 +98,40 @@ MOTOR
0-0_Omniflo_AM_POT_Pritsche
POT-Erdung
Omniflo_POT-Erdung
Omniflo_Tunnel
ILS_POT-Erdung
ILS_Tunnel
Omniflo_Schaltschrank
Omniflo_Schaltschrank-Eingang
Omniflo_Schaltschrank-Ausgang
Omniflo_Schaltschrank-Eingang-F
Omniflo_Schaltschrank-Ausgang-F
Omniflo_Ausgang
Omniflo_Eingang
Omniflo_Motor
Omniflo_BT-Eingang
Omniflo_BT-Ausgang
Omniflo_BT-Eingang_F
Omniflo_BT-Kennzeichnung
Omniflo_Scanner
Omniflo_Busmodul
Flex_Ausgang
Flex_Eingang
Flex_BT-Ausgang
Flex_BT-Eingang
Flex_BT-Eingang-F
Flex_BT-Kennzeichnung
Flex_Encoder-800
Flex_Motor
Flex_Scanner
Flex_Schaltschrank
Flex_Schaltschrank-Ausgang
Flex_Schaltschrank-Ausgang-F
Flex_Schaltschrank-Eingang
Flex_Schaltschrank-Eingang-F
Flex_Tunnel
Flex_POT-Erdung
+106 -5
View File
@@ -3,7 +3,7 @@
200000215 = Camera DM280 m. Halter für Trolley Id.(AP110) - BG
610554001 = Sensorhalter für WT18-3P420 oder -BG
610554002 = CPC Sensorhalter mit Reflextaster P1NH601 -BG
720002003 = SENSOR INDUK. M18x1, SA=12MM N-BÜ/NO, KABEL-150MM
720002003 = Sensor Induk. M18x1, SA=12mm N-BÜ/NO, Kabel-150mm
722001300 = Verb.-Leitung M12 St-0°/ M8 Bu-0° PUR UL/CSA 1m
722001301 = Verb.-Leitung M12 St-0°/ M8 Bu-0° PUR UL/CSA 2m
722001302 = Verb.-Leitung M12 St-0°/ M8 Bu-0° PUR UL/CSA 3m
@@ -38,8 +38,79 @@
722001357 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 30m
722001358 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 2,5m
722001359 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 40m
722001252 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 3m
722001253 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 5m
722001254 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 10m
722001255 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 15m
722001256 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 20m
722001257 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 30m
722001259 = Verb.-Leitung M12 St-0°/ M12 Bu-0° PUR UL/CSA 40m
723000013 = ADERLEITUNG H07V-K 6MM² GELB/GRÜN (RING a`100m)
725000001 = 12G1,0mm², Steuerleitung
725000002 = 12G1,0mm², Steuerleitung
725000003 = 12G1,5MM², STEUERLEITUNG
725000004 = 14G1,0MM², STEUERLEITUNG
725000005 = 18G1,0MM², STEUERLEITUNG
725000006 = 18G1,5MM², STEUERLEITUNG
725000007 = 14G1,5mm², Steuerleitung
725000009 = 25G1,0MM², STEUERLEITUNG
725000010 = 25G1,5MM², STEUERLEITUNG
725000011 = 3G0,5 MM², STEUERLEITUNG
725000012 = 3G1,0MM², Steuerleitung
725000013 = 25G2,5MM², STEUERLEITUNG
725000014 = 4G1,0MM², STEUERLEITUNG
725000015 = 4G1,5mm², Steuerleitung
725000016 = 5G1,5MM², STEUERLEITUNG
725000017 = 7G1,0mm², Steuerleitung
725000018 = 5G16MM², STEUERLEITUNG VDE 0293-308
725000019 = 8G1MM², STEUERLEITUNG
725000026 = 25G0,5MM², STEUERLEITUNG
725000027 = 34G1,0mm², Steuerleitung
725000028 = 5G6,0MM², STEUERLEITUNG
725000031 = 3G0,75MM², STEUERLEITUNG
725000035 = 5G1,0MM², STEUERLEITUNG
725000036 = 5G1,0MM², STEUERLEITUNG, PURÖ JZ HF 5G1 HF
725000037 = 10G1,0mm², Steuerleitung
725000040 = 3G1,5MM², Steuerleitung
725000041 = 7G1,5MM², STEUERLEITUNG
725000044 = 3G4MM², STEUERLEITUNG
725000045 = 3G2,5MM², STEUERLEITUNG
725000046 = 4G2,5MM², STEUERLEITUNG
725000047 = 5G2,5mm², Steuerleitung
725000048 = 7G2,5MM², STEUERLEITUNG
725000049 = 12G2,5MM², STEUERLEITUNG
725000050 = 4G4,0MM², STEUERLEITUNG
725000051 = 5G4,0MM², STEUERLEITUNG
725000052 = 4G10,0MM², STEUERLEITUNG
725000053 = 5G10,0MM², STEUERLEITUNG
725000054 = 4G1,5MM² CY, STEUERLEITUNG GESCHIRMT
725000055 = 4G0,5MM², STEUERLEITUNG
725000056 = 4G6,0MM², STEUERLEITUNG
725000057 = 12G4,0mm², Steuerleitung
725000058 = 12G1,0MM² CY, STEUERLEITUNG GESCHIRMT
725000060 = 7G4,0MM², STEUERLEITUNG
725000061 = 7G1,0MM² CY, STEUERLEITUNG GESCHIRMT
725000152 = 3G1 mm², Steuerleitung Halogenfrei
725000154 = 5G1 mm², Steuerleitung Halogenfrei
725000155 = 7G1 mm², Steuerleitung Halogenfrei
725000156 = 8G1 mm², Steuerleitung Halogenfrei
725000157 = 12G1mm², Steuerleitung Halogenfrei
725000158 = 18G1 mm², Steuerleitung Halogenfrei
725000159 = 25G1 mm², Steuerleitung Halogenfrei
725000160 = 3G1,5 mm², Steuerleitung Halogenfrei
725000161 = 4G1,5 mm², Steuerleitung Halogenfrei
725000163 = 7G1,5 mm², Steuerleitung Halogenfrei
725000164 = 12G1,5 mm², Steuerleitung Halogenfrei
725000165 = 5G2,5 mm², Steuerleitung Halogenfrei
725000166 = 7G2,5 mm², Steuerleitung Halogenfrei
725000167 = 18G1,5mm², Steuerleitung Halogenfrei
725000169 = 12G2,5 mm², Steuerleitung Halogenfrei
725000170 = 5G4 mm², Steuerleitung Halogenfrei
725000171 = 5G6 mm², Steuerleitung Halogenfrei
725000172 = 5G10 mm², Steuerleitung Halogenfrei
725000180 = 4G1,5 mm², Multiflex 512-Pur grau
725000181 = 7G1,5 mm², Multiflex 512-Pur grau
725000182 = 3G1,5 mm², Multiflex 512-Pur grau
726001040 = Patchkabel Cat6A 4P26 S/FTP 2xRJ45 0,5m grün
726001041 = Patchkabel Cat6A 4P26 S/FTP 2xRJ45 1,0m grün
726001042 = Patchkabel Cat6A 4P26 S/FTP 2xRJ45 1,5m grün
@@ -69,13 +140,11 @@
829422026 = INDUKT. SENSOR LP KPL.
720002011 = Sensor Induk. M18 8mm bündig/PNP-NO/ST M12
703001017 = HILFSCHALTER MIT ZUGFEDERANSCHLUSS F. 3RV2011
725000161 = 4G1,5 mm², Steuerleitung Halogenfrei
725000163 = 7G1,5 mm², Steuerleitung Halogenfrei
725000164 = 12G1,5 mm², Steuerleitung Halogenfrei
790000057 = Sirius act Tableau 4 F "LM-GN+PDT-GE+LDT-BL+NA"
790000057 = SIRIUS ACT Tableau 4 F "LM-GN+PDT-GE+LDT-BL+NA"
790801501 = Busverteiler kpl. ET 200SP DI+DQ, Exact -BG
790820400 = Unterverteiler 1 800x2100x400 -BG
790821106 = SCHALTSCHRANK 2000X2100X400 (HGF) -BG
790821103 = SCHALTSCHRANK 1200x2000x400 KPL.
829434314 = PINABFRAGE LI MECHANISCH KPL.
829534306 = Camera DM280 m. Halter (ILS) - BG
829624040 = UMLENKFLANSCH-c 800 MIT INKEMENTALGEBER KPL.
@@ -87,6 +156,38 @@
829434300 = LICHTTASTER LP+SP ALS STAUMELDER, KPL.
721002006 = Lichtleiterverstärke [Erweiterungseinheit]
721002005 = Lichtleiterverstärker [Basiseinheit]
721002008 = Lichtleiterkabel_M4 2St.
700002021 = AX-KOMPAKT-SCHALTSCHRANK 600X760X210
822035037 = ROLLENSCH. KPL. 1 NO FÜR KF
822035100 = ROLLENSCH. KPL. 1NO F. AFS/ST
822035102 = ROLLENSCH. KPL. 1NO FÜR AP
827072102 = KLEIDERBÜGEL ABFRAGE KPL. MIT SENSOR AM CP
827072105 = TROLLEY-V IDENTIFIKATION MIT SCANNER AUF AP 110
827072110 = SCHLEPPSEGMENTABFRAGE BIDIREKTIONAL
790002020 = SIRIUS ACT TABLEAU 2 FACH "LDT-GE+NA" KPL. (HALTER)
790002021 = SIRIUS ACT TABLEAU 1 FACH "LDT-GN" KPL.
790002022 = Bedientableau kpl. LDT GRÜN+8-STUFENSCHALTER
790002023 = TABLEAU 6- FACH KPL. "NA+DT-WS+ LDT-BL+ DT-GN"
790002024 = TABLEAU 1-F kpl. LDT BLAU
790002026 = Bedientableau 1 F kpl "DT-grün"
790002027 = Bedientableau 2 F -kpl. "LDT-GE+NA"
790002029 = Bedientableau 6 F - kpl.(LM-GN+LM-YE+LM-RD+BLIND+2xSW)
790002039 = Bedientableau 2 F -kpl. "LDT-KL+NA" KPL.
790002040 = Bedientableau 3 F"LDT-BL+LDT-KL+NA" KPL.
790002041 = Bedientableau 4 F kpl."LDT-BL+LDT-BL+LDT-KL+NA"
790002045 = Bedientableau 4 F -kpl. "DT-GN+LDT-BL+DT-WS+NA"
790002057 = Bedientableau 4 F -kpl. "LM-GN+PDT-GE+LDT-BL+NA"
790002058 = Bedientableau 4 F -kpl. LM-GN+PDT-GE+LDT-BL+BLIND
790002059 = Bedientableau 1 F -kpl. "DT-Weiss"
790002061 = Bedientableau 4 F -kpl. "LM-GN+PDT-GE+LDT-BL+NA"
790002064 = Bedientableau 6 F, Not-halt, Ldt-bl, Ldt gn,Blind,
790002066 = Bedientableau 2 F -kpl. "PDT-GE+KN-RAST 1-0-2"
929012603 = WEGEVENT.5/2 MONOSTABIL SY5120-5WAOU-C6F-Q
200000436 = Camera DM280 m. Halter Gefälleprofil ILS
200000478 = Vereinzeler KB-Behängung links
790000213 = DB-Automatisierung für Doppelbügelerkennung kpl.
[Missing]
+107 -1
View File
@@ -53,6 +53,8 @@
30.0=722001357
40.0=722001359
[WD_I-822035037]
100.0=725000012
# Kabel für Sensor 720002003
# cables for sensor 720002003
@@ -66,9 +68,80 @@
30.0=722001357
40.0=722001359
# Kabel für Sensor 790000213
# cables for sensor 790000213
[WD_I-790000213]
2.5=722001358
3.0=722001352
5.0=722001353
10.0=722001354
15.0=722001355
20.0=722001356
30.0=722001357
40.0=722001359
# Kabel für Sensor 200000525
# cables for sensor 200000525
[WD_I-200000525]
3.0=722001252
5.0=722001253
10.0=722001254
15.0=722001255
20.0=722001256
30.0=722001257
40.0=722001259
# Kabel für Sensor 400101729
# cables for sensor 400101729
[WD_I-400101729]
3.0=722001252
5.0=722001253
10.0=722001254
15.0=722001255
20.0=722001256
30.0=722001257
40.0=722001259
# Kabel für Sensor 827072102
# cables for sensor 827072102
[WD_I-827072102]
3.0=722001252
5.0=722001253
10.0=722001254
15.0=722001255
20.0=722001256
30.0=722001257
40.0=722001259
# Daten-Kabel für Scanner (Patchkabel gruen)
# Data-cable for scanners (Patchcable green)
[WF_B]
[WF_BX]
0.25=726001062
0.5=726001040
1.0=726001041
1.5=726001042
2.0=726001043
3.0=726001044
5.0=726001045
10.0=726001046
15.0=726001047
20.0=726001048
25.0=726001049
30.0=726001050
35.0=726001051
40.0=726001052
45.0=726001053
50.0=726001054
55.0=726001055
60.0=726001056
65.0=726001057
85.0=726001060
95.0=726001061
# Daten-Kabel für ENCODER (Patchkabel gruen)
# Data-cable for encoder (Patchcable green)
# ist identisch mit Scanner Kabel
[WF_GF]
0.25=726001062
0.5=726001040
1.0=726001041
@@ -94,3 +167,36 @@
[WD_PO]
100.0=723000013
# Kabel für Sensor 200000375
# cables for sensor 200000375
[WD_I-200000375]
1.0=722001330
2.0=722001331
2.5=722001338
3.0=722001332
5.0=722001333
10.0=722001334
15.0=722001335
20.0=722001336
25.0=722001337
30.0=722001339
35.0=722001340
40.0=722001341
50.0=722001342
# Kabel für Ventil 929012603
# cables for valves 929012603
[WD_Q-929012603]
1.0=722001300
2.0=722001301
2.5=722001308
3.0=722001302
5.0=722001303
10.0=722001304
15.0=722001305
20.0=722001306
25.0=722001307
30.0=722001309
35.0=722001310
40.0=722001311
50.0=722001312
+4 -1
View File
@@ -22,7 +22,6 @@ coord_z = Z=*
KR_code = KR-M*
[ignore_pattern_regex]
# Reguläre Ausdrücke für Texte die NICHT in die Excel Datei geschrieben werden sollen
# Ein Ausdruck pro Zeile (Python regex Syntax)
@@ -83,6 +82,7 @@ coord_arrows_generell_ignorieren = <<<|>>>
#pxqc_patterns = ^\\pxqc; =A0[1-9]\+UC\d{2,4}$
#pxqc_patterns2 = ^\\pxqc; =A1\+UC\d{2,4}$
#pxqc_patterns3 = ^\\pxqc; =A1\+UH\d{2,4}$
Belastung=Belastung \\P(.*?):\\P(\d+) kg \/ (\d+) N
ip_adress = ^.*;(\d{1,3}\.){3}\d{1,3}$
@@ -91,6 +91,9 @@ tunnel = ^\\fArial.*TUNNEL\d+-\d{4}$
kw_A = ^\d+\s*KW\s*-\s*\d+\s*A$
AUZ=\=A\d\d\+UZ\d\d\d\d$
AUC=\=A\d\d\+UC\d\d\d\d$
AUH=\=A\d\d\+UH\d\d$
ILSCV=ILS-CV\\PM\d\d\d\d$
[symbol_attribute]
+30 -54
View File
@@ -32,7 +32,7 @@
- [Warum werden manche Kabeltrassen nicht mit anderen verbunden?](#warum-werden-manche-kabeltrassen-nicht-mit-anderen-verbunden)
- [Warum verbindet das Programm den Sensor mit genau dieser Kabeltrasse?](#warum-verbindet-das-programm-den-sensor-mit-genau-dieser-kabeltrasse)
- [5. Fehlerfälle und Fehlerbehandlung](#5-fehlerfälle-und-fehlerbehandlung)
- [Allgemeine Fehler und Warnungen (beide Workflows)](#allgemeine-fehler-und-warnungen-beide-workflows)
- [Allgemeine Fehler und Warnungen](#allgemeine-fehler-und-warnungen)
- [Detaillierte Beschreibung der Warnungen (Warnings)](#detaillierte-beschreibung-der-warnungen-warnings)
- [1. `missing_attributes` (Fehlende oder unvollständige Block-Attribute)](#1-missing_attributes-fehlende-oder-unvollständige-block-attribute)
- [2. `tunnel_missing_length` (Fehlende Längenangabe bei Tunnel)](#2-tunnel_missing_length-fehlende-längenangabe-bei-tunnel)
@@ -47,9 +47,6 @@
- [Routing Errors (ERR-Routing)](#routing-errors-err-routing)
- [Tunnel Connection Errors](#tunnel-connection-errors)
- [Hinweise zur Excel-Fehlerausgabe (Cable Routing)](#hinweise-zur-excel-fehlerausgabe-cable-routing)
- [I/O Conversion Workflow - Hinweise](#io-conversion-workflow---hinweise)
- [Ausgabedateien bei Fehlern](#ausgabedateien-bei-fehlern)
- [Wichtige Hinweise](#wichtige-hinweise)
# 1. Installation des Programmes und Schnellstart-Guide
@@ -67,17 +64,6 @@ Ist Python installiert, werden per Doppelklick automatisch auf die `bin\install_
## Schnellstart und Vewendung des Programms
Das Programm bietet **drei Hauptworkflows**, die je nach Anwendungsfall eingesetzt werden:
### Workflow-Übersicht
| Workflow | Batch-Datei | Zweck | Ausgabe | Verwendete Configs |
| -------- | ----------- | ----- | ------- | ------------------ |
| **Cable Routing** | `getexdraw.bat` | Vollständige Kabelberechnung mit Längen und Stücklisten | `*_cables.dxf`, `*_cables.xlsx`, `*_BOM.xlsx` | `allgemein.cfg`, `BMK.cfg`, `kabel.cfg`, `bezeichner.cfg` |
| **I/O Conversion** | `ioconverter.bat` | Export von Gerätelisten für TIA Portal, WSCAD, etc. | `*-TIA.xlsx`, `*-WSCAD.xlsx`, u.a. | `allgemein.cfg`, `BMK.cfg` |
| **Translation** | `extract.bat` + `tr2dxf_<lang>.bat` | Textextraktion und Übersetzung von DXF-Inhalten | `*_texts.json`/`.xlsx`, `*_<lang>.dxf` | `allgemein.cfg`, `translation/*.cfg` |
**Hauptworkflow (Cable Routing):**
Im auf dem Desktop erzeugten Ordner findet sich das eigentliche Programm *create_cables*. Um das Programm auszuführen, genügt es die zu verarbeitende .**dxf-Datei** per *Drag and Drop* auf das Programm zu ziehen. Das öffnen der *Command-Shell* bestätigt den Start des Programms und der Anwender wird über den Ablauf informiert.
Die Ausgabe schreibt:
@@ -100,13 +86,13 @@ creating new .dxf ..
done
creating excel file with cable information ..
done
C:\10-Develop\kabellaengen\work\dxfdatei_BOM.xlsx
C:\10-Develop\kabellaengen\work\dxfdatei_cables.dxf
C:\10-Develop\kabellaengen\work\dxfdatei_cables.xlsx
C:\10-Develop\kabellaengen\work\dxfdatei_positions.json
C:\10-Develop\kabellaengen\work\dxfdatei_reduziert.dxf
C:\10-Develop\kabellaengen\work\dxfdatei_positionsdraw.json
C:\10-Develop\kabellaengen\work\dxfdatei_todraw.json
5 Datei(en) verschoben.
Drücken sie eine beliebige Taste . . .
Drücken Sie eine beliebige Taste . . .
```
Das Drücken einer beliebigen Taste beendet das Programm und die Ausgabe kann verwendet werden.
@@ -117,14 +103,15 @@ Verwende z.B. projekt_123.dxf statt mein projekt #1.dxf.
## Standardmäßige Ausgabe des Programms
In den Ordner auf dem Desktop in dem das Kabeltool liegt werden nach Beendigung der Berechnungen die Ausgabedateien abgelegt. Standardmäßig sind dies vier Dateien, wovon letztlich zwei für den Anwender bestimmt sind. In der nachfolgenden Liste steht der name *dxfdatei* stellvertretend für die eingegebene Datei des Benutzers.
In den Ordner auf dem Desktop in dem das Kabeltool liegt werden nach Beendigung der Berechnungen die Ausgabedateien abgelegt. Standardmäßig sind dies fünf Dateien, wovon drei für den Anwender bestimmt sind. In der nachfolgenden Liste steht der Name *dxfdatei* stellvertretend für die eingegebene Datei des Benutzers.
| Dateiname | Details |
|---------------------------|---------------------------------------------------------------------------------------------------|
| `dxfdatei_cables.dxf` | `.dxf`-Datei, **mit Kabelwegen** (z.B. für Import ins Original-Layout als eigenes Layer) und gezeichneten Racks (ggf. in 3D) |
| `dxfdatei_cables.xlsx` | **Excel-Datei** mit Kabellängen, Längenübersicht und Fehler-Übersicht |
| `dxfdatei_positions` | **Zwischendatei** (nicht für Endnutzer bestimmt) |
| `dxfdatei_todraw` | **Zwischendatei** (nicht für Endnutzer bestimmt) |
| Dateiname | Details |
|--------------------------------|---------------------------------------------------------------------------------------------------|
| `dxfdatei_cables.dxf` | `.dxf`-Datei, **mit Kabelwegen** (z.B. für Import ins Original-Layout als eigenes Layer) und gezeichneten Racks (ggf. in 3D) |
| `dxfdatei_cables.xlsx` | **Excel-Datei** mit Kabellängen, Längenübersicht und Fehler-Übersicht |
| `dxfdatei_BOM.xlsx` | **Excel-Datei** mit Gesamtstückliste und Unterverteiler-spezifischer Stückliste |
| `dxfdatei_positionsdraw.json` | **Zwischendatei** (nicht für Endnutzer bestimmt) |
| `dxfdatei_todraw.json` | **Zwischendatei** (nicht für Endnutzer bestimmt) |
### .dxf-Datei: *dxfdatei*_cables.dxf
@@ -483,8 +470,8 @@ Dieses Toolset dient der **automatisierten** und **komfortablen** Ermittlung von
- eine strukturierte `.json`-Datei mit Kabellängen und Pfadkoordinaten
- eine visuelle `.dxf`-Datei mit eingezeichneten Kabelwegen
- eine weitere .dxf-Datei mit einem reduzierten Layout (Kabeltrassen + Kabel + Unterverteiler)
- zukünftig: tabellarische Aufbereitung der Kabellängen mit SIVAS-Nummern (z.B. `.xlsx`)
- eine tabellarische Aufbereitung der Kabellängen mit SIVAS-Nummern (`.xlsx`)
- eine Stückliste (BOM) mit Gesamtübersicht und UV-spezifischer Auflistung (`.xlsx`)
## Allgemeiner Programmablauf
@@ -502,15 +489,24 @@ Die Ausgabe schreibt:
```text
C:\10-Develop\kabellaengen\bin>getexdraw.bat easy.dxf
--hole Positionen
=== Fetching Positions ===
reading file ..done
Validating given configs: Checking for inconsistency.
No Inconsistencies found. Continuing with routing process.
writing results to a json file ...
done
--erzeuge Graph mit Routing
=== Creating Graph for Routing ===
writing results to a json file ...
done
--zeichne Kabel in dxf Datei
done
=== Writing Output Files ===
Cable-Routes exported to new dxf-file
Cable-Summary exported to Excel-file
BOM exported to Excel-file
```
## Ausgabe des Toolsets
@@ -521,6 +517,7 @@ Alle drei oben genannten Teilprogramme erzeugen eine eigene Ausgabedatei. Die Er
- Die .dxf-Datei mit den Kabelwegen: `NamederEingabedatei_cables.dxf`
- Die tabellarische Aufbereitung der Kabellängen mit zugehörigen Sachnummern für jeden Sensor / Aktor: `NamederEingabedatei_cables.xlsx`
- Die Stückliste (BOM): `NamederEingabedatei_BOM.xlsx`
## Informationen zu den Einzelprogrammen
@@ -770,9 +767,9 @@ Schritt 2: Bei Ausbleiben eines Schnittpunktes -> Vergrößern des Kreises. Bei
# 5. Fehlerfälle und Fehlerbehandlung
## Allgemeine Fehler und Warnungen (beide Workflows)
## Allgemeine Fehler und Warnungen
Die folgende Tabelle zeigt alle möglichen Fehler- und Warnungstypen, die von `getpositions.py` erkannt werden. Diese gelten **für beide Workflows** (Cable Routing und I/O Conversion):
Die folgende Tabelle zeigt alle möglichen Fehler- und Warnungstypen, die von `getpositions.py` erkannt werden:
| Fehlertyp | Kategorie | Beschreibung | Ursache | Behebung |
|-----------|-----------|--------------|---------|----------|
@@ -1091,24 +1088,3 @@ Die Fehler-Worksheets in `*_cables.xlsx` erscheinen **nur**, wenn tatsächlich F
3. Führen Sie das Programm erneut aus
4. Beheben Sie verbleibende Routing-Fehler
5. Wiederholen Sie, bis keine ERR-Worksheets mehr erstellt werden
---
## I/O Conversion Workflow - Hinweise
Der **I/O Conversion Workflow** (`ioconverter.bat`) führt **keine Routing-Berechnungen** durch und erzeugt daher auch keine Routing-spezifischen Fehler. Es werden ausschließlich die **allgemeinen Fehler und Warnungen** aus `getpositions.py` gemeldet (siehe [Allgemeine Fehler und Warnungen](#allgemeine-fehler-und-warnungen-beide-workflows)).
### Ausgabedateien bei Fehlern
- `*_errors.json` - enthält alle Fehler und Warnungen aus getpositions
- `*_positionsconv.json` - Zwischenergebnis mit extrahierten Positionen
- `*_TIA.xlsx`, `*_WSCAD.xlsx`, etc. - werden auch bei Warnungen erzeugt, können aber unvollständig sein
### Wichtige Hinweise
- **Fehlende Attribute** führen dazu, dass Elemente in den Export-Dateien fehlen
- **Fehlende KENNZEICHNUNG** verhindert die korrekte Zuordnung zu Unterverteilern
- **Doppelte IDs** können zu falschen Einträgen in den Excel-Listen führen
**Empfehlung:** Beheben Sie alle Warnungen aus `*_errors.json`, bevor Sie die Export-Dateien an nachgelagerte Systeme (TIA Portal, WSCAD) übergeben.
+197
View File
@@ -0,0 +1,197 @@
# Anwenderdoku zum I/O Converter (ioconverter) <!-- omit in toc -->
- [Zweck des Programms](#zweck-des-programms)
- [Schnellstart](#schnellstart)
- [Verwendung per Drag \& Drop](#verwendung-per-drag--drop)
- [Verwendung per Kommandozeile](#verwendung-per-kommandozeile)
- [Pipeline und Programmablauf](#pipeline-und-programmablauf)
- [Ausgabedateien](#ausgabedateien)
- [EA-Liste (`*_EA.xlsx`)](#ea-liste-_eaxlsx)
- [TIA-Portal-Export (`*_TIA.xlsx`)](#tia-portal-export-_tiaxlsx)
- [WSCAD-Export (`*_WSCAD.xlsx`)](#wscad-export-_wscadxlsx)
- [Konfiguration und Symbolerkennung](#konfiguration-und-symbolerkennung)
- [Fehlerfälle und Fehlerbehandlung](#fehlerfälle-und-fehlerbehandlung)
- [Allgemeine Fehler und Warnungen](#allgemeine-fehler-und-warnungen)
- [Ausgabedateien bei Fehlern](#ausgabedateien-bei-fehlern)
- [Empfohlene Vorgehensweise](#empfohlene-vorgehensweise)
- [Erweiterte Optionen](#erweiterte-optionen)
## Zweck des Programms
Der **I/O Converter** (`ioconverter.bat`) dient der vereinfachten Ableitung von **Ein-/Ausgangslisten (EA-Listen)** sowie der **Eingabedaten für das Siemens TIA Portal** und **WSCAD** aus einer DXF-Layoutzeichnung.
Das Programm extrahiert alle relevanten Geräteinformationen (Sensoren, Aktoren, Schaltschrankelemente) aus dem Layout und erzeugt daraus formatierte Excel-Dateien, die direkt in die jeweiligen Zielsysteme importiert werden können. Das Routing und die Kabelberechnung entfallen dabei vollständig - es geht ausschließlich um die **Geräte- und IO-Daten**.
## Schnellstart
### Verwendung per Drag & Drop
Im Desktop-Ordner *Kabeltool* (erstellt via `bin\dropItem_create.bat`) befindet sich die Verknüpfung *io_converter*. Die zu verarbeitende **.dxf-Datei** einfach per **Drag & Drop** auf diese Verknüpfung ziehen.
> [!IMPORTANT]
> Der Dateiname darf **keine Leerzeichen oder Sonderzeichen** enthalten.
> Verwende z. B. `projekt_123.dxf` statt `mein projekt #1.dxf`.
### Verwendung per Kommandozeile
```bash
bin\ioconverter.bat <meine_anlage.dxf>
```
Die Ausgabe schreibt:
```text
=== Fetching Positions ===
...
=== Creating Excel Files for TIA, WSCAD, .. ===
Export 'EA' erfolgreich: ...\work\meine_anlage_EA.xlsx
Export 'TIA' erfolgreich: ...\work\meine_anlage_TIA.xlsx
Export 'WSCAD' erfolgreich: ...\work\meine_anlage_WSCAD.xlsx
```
Die erzeugten Dateien werden automatisch in das Ergebnisverzeichnis (`PROJECT_IO_RESULTS`) verschoben.
## Pipeline und Programmablauf
Der I/O Converter arbeitet in zwei Schritten:
```text
DXF-Datei
1. getpositions.py --> Positionen und Attribute extrahieren --> *_positionsconv.json
2. portalexport.py --> Excel-Export erzeugen --> *_EA.xlsx, *_TIA.xlsx, *_WSCAD.xlsx
```
1. **Positionsextraktion** (`getpositions.py`): Liest die DXF-Datei ein und extrahiert alle Blöcke mit ihren Attributen (IO, SPS, KENNZEICHNUNG, BEZEICHNUNG, VERW, TEXT-D/E/ES/F, ARTINR). Das Ergebnis wird als `*_positionsconv.json` gespeichert.
2. **Excel-Export** (`portalexport.py`): Liest die JSON-Zwischendatei und erzeugt daraus die Excel-Dateien in den gewünschten Formaten. Die Daten werden dabei nach SPS-Nummer gruppiert - pro SPS entsteht ein eigener Satz Ausgabedateien (z.B. `anlage-SPS1_TIA.xlsx`, `anlage-SPS2_TIA.xlsx`).
## Ausgabedateien
Standardmäßig werden **drei Excel-Dateien** pro SPS erzeugt:
### EA-Liste (`*_EA.xlsx`)
Eine einfache Übersicht aller Ein- und Ausgänge. Die Datei enthält folgende Worksheets:
**Ein-, Ausgaenge**: Listet alle erkannten Eingänge und Ausgänge mit Name, Kommentar (Bezeichnung) und Bezug (Kennzeichnung) auf. Die Klassifizierung in Ein- oder Ausgang erfolgt automatisch anhand der Identifier aus dem Block (z.B. DI, FDI = Eingang; DQ, K, M = Ausgang).
**Duplikate / Errors**: Falls doppelte Namen oder fehlerhafte Einträge erkannt werden, werden diese in separaten Worksheets aufgeführt.
### TIA-Portal-Export (`*_TIA.xlsx`)
Im TIA-Portal-Importformat mit folgenden Worksheets:
**PLC Tags**: Enthält die Spalten `Name`, `Path`, `Data Type`, `Logical Address`, `Comment`, `Hmi Visible`, `Hmi Accessible`, `Hmi Writeable`, `Typeobject ID`, `Version ID`. Diese Datei kann direkt in das Siemens TIA Portal importiert werden.
**Constants**: Enthält Konstanten mit `Name`, `Path`, `Data Type`, `Value`, `Comment`.
### WSCAD-Export (`*_WSCAD.xlsx`)
Im WSCAD-Importformat mit den Spalten `Anschluss`, `Kommentar`, `Symboltext`, `Bezug`, `Sondertext 1-8`. Der Export enthält standardmäßig Bezugsinformationen. Mit der Option `--no_bezug` kann der Export ohne Bezüge erstellt werden.
Für Bauteile mit unvollständigen Anschlüssen werden fehlende Anschlüsse automatisch bis zur Standardanzahl (8 pro Bauteil) ergänzt.
## Konfiguration und Symbolerkennung
Der I/O Converter verwendet folgende Konfigurationsdateien aus `cfg/`:
| Datei | Relevanz für I/O Converter |
|-----------------|---------------------------|
| `allgemein.cfg` | Layernamen für Sensoren, Aktoren, Unterverteiler etc. - bestimmt, welche Blöcke aus der DXF-Datei extrahiert werden |
| `BMK.cfg` | Betriebsmittelkennzeichnungen (`[Routing-Include]`, `[Routing-Ignore]`) - bestimmt, welche Gerätetypen berücksichtigt werden |
> [!NOTE]
> Die Konfigurationsdateien `kabel.cfg` und `bezeichner.cfg` werden vom I/O Converter **nicht** benötigt, da keine Kabelberechnung stattfindet.
Die Erkennung der Symbole (Blöcke) in der DXF-Datei ist die gemeinsame Basis von I/O Converter und Kabelberechnung. Beide Programme nutzen `getpositions.py` mit denselben Regeln zur Symbolsuche:
- Welche **Layer** durchsucht werden, wird in `allgemein.cfg` unter `[GetPos-Layer_Equipment]`, `[GetPos-Layer_Distributors]` etc. festgelegt
- Welche **Betriebsmittelkennzeichen** (BMK-Präfixe) berücksichtigt werden, regelt `BMK.cfg` unter `[Routing-Include]` und `[Routing-Ignore]`
- Welche **Block-Attribute** erwartet werden (KENNZEICHNUNG, SPS, IO, ARTINR, etc.) und wie die Blöcke im Layout angelegt sein müssen
Eine ausführliche Beschreibung der Konfigurationsdateien sowie der Anforderungen an die Layouterstellung findet sich in der [Anwenderdokumentation zur Kabellängenermittlung](Anwenderdoku.md) in den Abschnitten "Anpassung des Verhaltens des Programms" und "Anwenderhinweise zur Layouterstellung".
## Fehlerfälle und Fehlerbehandlung
### Allgemeine Fehler und Warnungen
Der I/O Converter durchläuft dieselbe Positionsextraktion wie der Cable-Routing-Workflow. Es gelten daher die gleichen Fehler- und Warnungstypen aus `getpositions.py`. Die vollständige Fehlertabelle findet sich in der [Anwenderdoku](Anwenderdoku.md) bzw. [Kurzanleitung](Anwenderdoku_kurz.md) im Abschnitt "Fehlerfälle und Fehlerbehandlung".
Die für den I/O Converter relevantesten Fehler sind:
| Fehlertyp | Auswirkung |
|-----------------|------------|
| `double_ids` | **Abbruch** - Doppelte Geräte-IDs führen zum Programmabbruch. Die `*_errors.json` wird erzeugt, aber keine Excel-Dateien. |
| `missing_attributes` | Betroffene Elemente fehlen in den Export-Dateien |
| `mapping_warnings` (keine KENNZEICHNUNG) | Keine korrekte Zuordnung zu Unterverteilern möglich |
| `missing_sps_prefix` | Gerät kann keiner SPS zugeordnet werden |
### Ausgabedateien bei Fehlern
- `*_errors.json` - enthält alle Fehler und Warnungen aus der Positionsextraktion
- `*_positionsconv.json` - Zwischenergebnis mit extrahierten Positionen
- `*_EA.xlsx`, `*_TIA.xlsx`, `*_WSCAD.xlsx` - werden auch bei Warnungen erzeugt, können aber unvollständig sein
> [!IMPORTANT]
> Bei `double_ids`-Fehlern bricht das Programm nach der Positionsextraktion ab. Es werden **keine** Excel-Dateien erzeugt. Beheben Sie zuerst die doppelten IDs im Layout.
### Empfohlene Vorgehensweise
1. Programm ausführen
2. Falls `*_errors.json` erstellt wurde: Fehler prüfen und im Layout korrigieren
3. Erneut ausführen bis keine Fehler mehr auftreten
4. Export-Dateien an nachgelagerte Systeme (TIA Portal, WSCAD) übergeben
> [!TIP]
> Beheben Sie alle Warnungen aus `*_errors.json`, bevor Sie die Export-Dateien an nachgelagerte Systeme übergeben, um Vollständigkeit sicherzustellen.
## Erweiterte Optionen
### Einzelne Exportformate erzeugen
Der `portalexport.py` kann auch direkt aufgerufen werden, um nur bestimmte Exportformate zu erzeugen:
```bash
# Nur TIA-Export erzeugen
bin\portalexport.bat --filename <positionsconv.json> --outname <basename> --mode TIA
# Nur WSCAD-Export ohne Bezüge
bin\portalexport.bat --filename <positionsconv.json> --outname <basename> --mode WSCAD --no_bezug
# Nur EA-Liste
bin\portalexport.bat --filename <positionsconv.json> --outname <basename> --mode EA
```
### Spezialfall: Eingabe über Textdatei (ohne DXF)
Für den Fall, dass die IO-Daten **nicht aus einer DXF-Datei** stammen, sondern bereits in aufbereiteter Form vorliegen, kann `portalexport.py` auch direkt mit einer Textdatei als Eingabe arbeiten. Damit wird die gesamte DXF-Verarbeitung (`getpositions.py`) übersprungen.
**Anwendungsfälle:**
- IO-Listen aus einem **anderen System** (z.B. manuell gepflegte Excel-Listen, Datenbank-Exporte) sollen in das TIA- oder WSCAD-Format konvertiert werden
- Daten aus der DXF-Extraktion sollen **vorab korrigiert oder ergänzt** werden, bevor der Excel-Export erfolgt
- **Testen** des Exporters ohne eine DXF-Datei verarbeiten zu müssen
**Aufruf:**
```bash
bin\portalexport.bat --input <eingabe.txt> --mode TIA
```
**Format der Textdatei:** Die Datei muss pro Zeile einen Eintrag im folgenden CSV-Format mit einfachen Anführungszeichen enthalten:
```text
'<IO>','<BEZEICHNUNG>','<VERW>','<KENNZEICHNUNG>','<TEXT-D>','<TEXT-E>','<TEXT-ES>','<TEXT-F>'
```
**Beispiel:**
```text
'DI01','Stausensor 1 (ILS-CV M0108)','Jam detector','=A01+UC0101-KF1DI1','','','',''
'DQ04','Motor MA0062','CV-M0062_0,75','=A01+UH01-KF1DQ04','Motor MA0062','Motor MA0062','',''
```
Die Felder entsprechen den Block-Attributen aus der DXF-Datei. Dieses Format wird auch intern von `portalexport.py` erzeugt, wenn es die JSON-Daten aus `getpositions.py` verarbeitet.
> [!NOTE]
> Bei der Eingabe per Textdatei entfällt die Gruppierung nach SPS-Nummer - alle Einträge werden in einem Satz Ausgabedateien zusammengefasst. Ebenso werden keine `getpositions`-Fehler und -Warnungen in die Excel-Dateien geschrieben, da keine DXF-Validierung stattfindet.
+11 -18
View File
@@ -9,10 +9,10 @@
- [Excel-Datei: *dxfdatei*\_BOM.xlsx](#excel-datei-dxfdatei_bomxlsx)
- [Fehlerfälle und Fehlerbehandlung](#fehlerfälle-und-fehlerbehandlung)
- [Übersicht](#übersicht)
- [Zwei Haupt-Workflows](#zwei-haupt-workflows)
- [Programmablauf](#programmablauf)
- [Fehler- und Warnungskategorien](#fehler--und-warnungskategorien)
- [Fehlerausgabe](#fehlerausgabe)
- [Allgemeine Fehler und Warnungen (beide Workflows)](#allgemeine-fehler-und-warnungen-beide-workflows)
- [Allgemeine Fehler und Warnungen](#allgemeine-fehler-und-warnungen)
- [Struktur der Error-JSON-Datei](#struktur-der-error-json-datei)
- [Arbeiten mit Fehlerfällen](#arbeiten-mit-fehlerfällen)
- [Beispiele aus Testdaten](#beispiele-aus-testdaten)
@@ -187,20 +187,14 @@ Hinweis: Diese Ansicht ist besonders nützlich zur **vorbereitenden Bestellplanu
Das Programm führt während der Verarbeitung umfassende Validierungen durch und erkennt verschiedene Arten von Fehlern im Layout. Die Fehlerbehandlung unterscheidet sich je nach Anwendungsfall:
### Zwei Haupt-Workflows
### Programmablauf
Das Kabeltool unterstützt zwei verschiedene Workflows:
Das Kabeltool (`getexdraw.bat`) arbeitet in drei Schritten:
1. **Cable Routing Workflow** (`getexdraw.bat`):
- Schritt 1: `getpositions.py` - Extrahiert Positionen und validiert Layout
- Schritt 2: `routing.py` - Berechnet Kabelwege über Graph-Algorithmen
- Schritt 3: `drawdxf.py` - Erzeugt DXF mit Kabelwegen und Excel-Listen
- **Ausgabe**: `*_cables.dxf`, `*_cables.xlsx`, `*_BOM.xlsx`
2. **I/O Conversion Workflow** (`ioconverter.bat`):
- Schritt 1: `getpositions.py` - Extrahiert Positionen und validiert Layout
- Schritt 2: `portalexport.py` - Konvertiert zu Excel-Formaten (TIA, WSCAD, EA)
- **Ausgabe**: `*_TIA.xlsx`, `*_WSCAD.xlsx`, `*_EA.xlsx`
1. `getpositions.py` - Extrahiert Positionen und validiert Layout
2. `routing.py` - Berechnet Kabelwege über Graph-Algorithmen
3. `drawdxf.py` - Erzeugt DXF mit Kabelwegen und Excel-Listen
- **Ausgabe**: `*_cables.dxf`, `*_cables.xlsx`, `*_BOM.xlsx`
### Fehler- und Warnungskategorien
@@ -211,15 +205,14 @@ Die Fehlerbehandlung unterscheidet zwischen zwei Kategorien:
### Fehlerausgabe
**Für beide Workflows gilt:**
- Falls Fehler oder Warnungen auftreten, schreibt `getpositions.py` **automatisch** eine JSON-Datei `*_errors.json` in den `work`-Ordner
- Im **Cable Routing Workflow** werden zusätzliche Fehler in der Excel-Datei `*_cables.xlsx` als separate Worksheets ausgegeben (siehe [ERR-Worksheets](#erweiterte-ausgabe-im-fehlerfall))
- Zusätzliche Fehler werden in der Excel-Datei `*_cables.xlsx` als separate Worksheets ausgegeben (siehe [ERR-Worksheets](#erweiterte-ausgabe-im-fehlerfall))
Im Ordner [testdata/](testdata/) finden sich Beispiel-DXF-Dateien, die gezielt bestimmte Fehlerfälle demonstrieren (z.B. [easy_3tunnels_errors.json](testdata/easy_3tunnels_errors.json), [easy_tunnelerror1.json](testdata/easy_tunnelerror1.json)).
## Allgemeine Fehler und Warnungen (beide Workflows)
## Allgemeine Fehler und Warnungen
Die folgende Tabelle zeigt alle möglichen Fehler- und Warnungstypen, die von `getpositions.py` erkannt werden. Diese gelten **für beide Workflows** (Cable Routing und I/O Conversion):
Die folgende Tabelle zeigt alle möglichen Fehler- und Warnungstypen, die von `getpositions.py` erkannt werden:
| Fehlertyp | Kategorie | Beschreibung | Ursache | Behebung |
|-----------|-----------|--------------|---------|----------|
+284
View File
@@ -0,0 +1,284 @@
# Symbole und Benennungen im DXF-Layout
Diese Dokumentation beschreibt, wie Symbole und Texte in der DXF-Zeichnung benannt und strukturiert sein muessen, damit sie vom System erkannt werden.
---
## 1. Sensoren / Aktoren / Motoren (Equipment)
Equipment wird ueber **INSERT-Bloecke mit Attributen** erkannt.
### Block-Attribute
| Attribut-Tag | Bedeutung | Beispiel | Pflicht |
|---|---|---|---|
| `NAME` | Geraete-ID (moderner Block) | `MA0062`, `BG3240` | Ja (oder IO+B) |
| `IO` | Geraete-ID (I/O-Block, Legacy) | `MA0062` | Alternativ zu NAME |
| `B` | Geraete-ID (Technik-Block, Legacy) | `MA0062` | Alternativ zu NAME |
| `ARTINR` | SIVAS-Artikelnummer | `790902001` | Ja |
| `KENNZEICHNUNG` | Routing-Adresse | `=A01+UH01-KF1DQ04` | Ja |
| `SPS` | SPS-Praefix / Anlage | `1` | Ja (fuer Zuordnung) |
| `VERW` | Verwendung/Beschreibung | `CV-M0062_0,75` | Nein |
| `REALE_POSITION` | Marker fuer tatsaechliche Position | `x` | Nein |
### Geraete-Praefix (erste 2 Zeichen der ID)
Welche Geraete geroutet werden, bestimmt die `cfg/BMK.cfg`:
**Routing-Include** (werden geroutet):
| Praefix | Typ |
|---|---|
| `MA` | Motoren |
| `MB` | Ventile |
| `QM` | Ventile/Pumpen |
| `BG` | Sensoren/Naeherungsschalter |
| `BP` | Naeherungsschalter |
| `BX` | Mehrzweckgeraete, z.B. Scanner |
| `PO` | Pneumatik-Elemente |
| `SF` | Sicherheitselemente |
| `PF` | Programmierbare Logik |
| `GF` | Encoder |
**Routing-Ignore** (Schaltschrankelemente, nicht geroutet):
| Praefix | Typ |
|---|---|
| `FC` | Steuerungselemente |
| `UH` | Unterverteiler |
| `UC` | Unterverteiler |
| `UZ` | Spezialverteiler |
| `DI` | Digitale Eingaenge |
| `DQ` | Digitale Ausgaenge |
| `QA` | Ausgabegeraete |
### KENNZEICHNUNG-Format
```
=ANLAGE+VERTEILER-KARTE
```
**Beispiel:** `=A01+UH01-KF1DQ04`
| Teil | Bedeutung | Beispiel |
|---|---|---|
| ANLAGE | Anlagengruppe | `A01` |
| VERTEILER | Unterverteiler-ID | `UH01` |
| KARTE | Karte/Kanal | `KF1DQ04` |
Trennzeichen: `=` (Start), `+` (zwischen Anlage und Verteiler), `-` (zwischen Verteiler und Karte)
### Block-Zusammenfuehrung (Legacy Dual-Block)
Bei der alten Dual-Block-Struktur werden zwei Bloecke mit gleicher ID (z.B. `MA0062`) zusammengefuehrt, wenn:
- Beide innerhalb von **1000mm** Abstand liegen
- Einer das `SPS`-Attribut hat, der andere nicht
- Ergebnis-ID: `{id}@{sps}` (z.B. `MA0062@1`)
---
## 2. Unterverteiler (Distributoren)
Unterverteiler koennen auf **zwei Arten** definiert werden: als Text oder als Symbol.
### Variante A: Text (MTEXT)
Ein MTEXT-Element auf einem erlaubten Layer mit folgendem Muster:
```
-UH01 (Minus vor dem Namen)
+UH01 (Plus vor dem Namen)
```
Der Text muss den Verteilernamen als Teilstring enthalten, mit `-` oder `+` davor.
**Erlaubte Layer** (konfiguriert in `cfg/allgemein.cfg`, Sektion `GetPos-Layer_Distributors`):
- `Busverteiler-Kennzeichnung`
- `0-0_ILS_Busverteiler-Kennzeichnung`
- `0-0_ILS_UNTERVERTEILER`
- `0-0_ILS_Unterverteiler`
- `0-0_Omniflo_UNTERVERTEILER`
- `0-0_Omniflo_Unterverteiler`
- `UNTERVERTEILER`
- `0-0_Omniflo_Busverteiler-Kennzeichnung`
- `Schaltschrank-ILS`
### Variante B: Symbol (INSERT-Block)
Ein INSERT-Block mit dem Attribut `NAME`, dessen Wert einem **Cabinet-Pattern** entspricht.
**Cabinet-Patterns** (Regex, konfiguriert in `cfg/BMK.cfg`, Sektion `Cabinet-Pattern`):
| Pattern | Beispiel-Match | Extrahierte ID |
|---|---|---|
| `A\d\d\+(UH0\d)` | `A01+UH01` | `UH01` |
| `A\d\d\+(UC\d\d\d)` | `A01+UC001` | `UC001` |
| `\+(UC\d\d\d\d)` | `+UC0101` | `UC0101` |
| `\+(UH\d\d)` | `+UH01` | `UH01` |
Die Klammer-Gruppe im Regex bestimmt die extrahierte Verteiler-ID.
**Optionale Attribute:**
- `REALE_POSITION` = `x` : Position wird aus Attribut-Position berechnet (Mittelpunkt des Markers)
- `SPS` : SPS-Zuordnung
---
## 3. Tunnel
Tunnel koennen ebenfalls als **Text** oder **Symbol** definiert werden.
### Variante A: Text (MTEXT)
Ein MTEXT-Element auf einem erlaubten Layer mit folgendem Muster:
```
TUNNEL1-5 (Tunnelname-Laenge)
TUNNEL2-10
```
**Regex:** `(TUNNEL\d+)-(\d+)`
| Teil | Bedeutung | Beispiel |
|---|---|---|
| Gruppe 1 | Tunnelname | `TUNNEL1` |
| Gruppe 2 | Laenge in Metern | `5` |
Pro Tunnel muessen genau **2 MTEXT-Elemente** vorhanden sein (Ein- und Ausgang).
**Erlaubte Layer** (konfiguriert in `cfg/allgemein.cfg`, Sektion `GetPos-Layer_Tunnel`):
- `Busverteiler-Kennzeichnung`
- `0-0_Tunnel`
### Variante B: Symbol (INSERT-Block)
Ein INSERT-Block mit dem Attribut `NAME`, dessen Wert einem **Tunnel-Pattern** entspricht.
**Tunnel-Patterns** (Regex, konfiguriert in `cfg/BMK.cfg`, Sektion `Tunnel-Pattern`):
| Pattern | Beispiel |
|---|---|
| `Tunnel\d+` | `Tunnel1`, `Tunnel2` |
| `Tunnel_\d+` | `Tunnel_1`, `Tunnel_2` |
| `Tunnel-\d+` | `Tunnel-1`, `Tunnel-2` |
| `TUNNEL\d+` | `TUNNEL1`, `TUNNEL2` |
**Attribute:**
| Attribut-Tag | Bedeutung | Beispiel | Pflicht |
|---|---|---|---|
| `NAME` | Tunnelname | `Tunnel1` | Ja |
| `LAENGE` | Tunnellaenge in Metern | `5` | Nein (Default: 5) |
| `REALE_POSITION` | Positionsmarker | `x` | Nein |
Pro Tunnel muessen genau **2 Symbole** platziert werden (Ein- und Ausgang).
**Fehler bei Tunnel-Definition:**
- Weniger als 2 Positionen: Fehler `missing_tunnel`
- Mehr als 2 Positionen: Fehler `overdefined_tunnel`
- Fehlende Laenge: Warnung, Default 5m wird verwendet
---
## 4. Kabelpritschen (Racks)
Kabelpritschen werden als **LWPOLYLINE** oder **POLYLINE** auf bestimmten Layern erkannt.
Es sind keine Attribute oder Texte noetig - nur der **Layer** entscheidet.
**Erlaubte Layer** (konfiguriert in `cfg/allgemein.cfg`, Sektion `GetPos-Layer_Racks`):
| Layer | Beschreibung |
|---|---|
| `PRITSCHE_100-60` | Standard 100x60 |
| `PRITSCHE_100-60-SCHRAFF` | Standard 100x60 schraffiert |
| `PRITSCHE_200-60` | Standard 200x60 |
| `PRITSCHE_200-60_ILS` | ILS 200x60 |
| `PRITSCHE_200-60_OMNIFLO` | Omniflo 200x60 |
| `0-0_ILS_PRITSCHE_200-60_storage_Level1` | ILS Storage Level 1 |
| `0-0_ILS_PRITSCHE_200-60_storage_Level2` | ILS Storage Level 2 |
| `0-0_ILS_PRITSCHE_200-60_Workstation` | ILS Workstation |
| `0-0_ILS_Pritsche_200-60_AMR` | ILS AMR |
| `0-0_ILS_PRITSCHE_200-60_Highway` | ILS Highway |
| `0-0_ILS_Pritsche_200-60_Inbound` | ILS Inbound |
| `0-0_Omniflo_Pritsche_200-60_Workstation-Outbound` | Omniflo Workstation Outbound |
| `0-0_Omniflo_Pritsche_200-60_outbound` | Omniflo Outbound |
| `0-0_Omniflo_Pritsche_200-60_AMR` | Omniflo AMR |
| `0-0_Omniflo_Pritsche_200-60_Highway` | Omniflo Highway |
**Validierung:** Wenn die Z-Koordinaten aller Racks mehr als 2000mm auseinanderliegen, wird eine Warnung ausgegeben (Schwellwert konfigurierbar in `cfg/allgemein.cfg`, Sektion `Racks`, Schluessel `MaximalTotalHeightDifferences`).
---
## 5. Zusammenfassung: Was muss im Layout vorhanden sein?
| Element | Erkennungsart | Mindestangaben |
|---|---|---|
| **Sensor/Motor** | INSERT-Block | `NAME` (oder `IO`+`B`), `ARTINR`, `KENNZEICHNUNG` |
| **Unterverteiler** | MTEXT **oder** INSERT-Block | Text: `-UH01` auf richtigem Layer / Block: `NAME` = `A01+UH01` |
| **Tunnel** | MTEXT **oder** INSERT-Block | Text: `TUNNEL1-5` (2x) / Block: `NAME` = `Tunnel1`, `LAENGE` = `5` (2x) |
| **Kabelpritsche** | LWPOLYLINE/POLYLINE | Auf richtigem Layer gezeichnet |
---
## 6. Funktionsreferenz (getpositions.py)
Uebersicht der zentralen Funktionen, die die Erkennung durchfuehren.
### Sensoren / Equipment
| Funktion | Zeile | Aufgabe |
|---|---|---|
| `get_attributes_of_insert(d_insert, d_pos)` | ~76 | Extrahiert ID, Typ und Position aus einem einzelnen INSERT-Block. Prueft zuerst `IO`, dann `NAME`, dann `B`. Bei `REALE_POSITION='x'` wird der Mittelpunkt aus Marker-Geometrie berechnet (Breite/Hoehe aus Config). Gibt `(dict, id, typ)` zurueck. |
| `extract_input_positions(all_inserts, all_positions, error_collector)` | ~221 | Hauptfunktion: Iteriert ueber alle Bloecke, ruft `get_attributes_of_insert()` auf, trennt Sensoren von Schaltschrankelementen anhand des Praefixes. Fuehrt Block-Zusammenfuehrung via `CompareBuffer` durch. |
| `allocate_blocks_together(...)` | ~329 | Fuehrt die Zusammenfuehrung von Dual-Bloecken durch (Legacy). Nutzt `CompareBuffer.positions_are_close()` mit 1000mm Toleranz. |
### Unterverteiler
| Funktion | Zeile | Aufgabe |
|---|---|---|
| `get_subdistributor_positions_from_entities(entities, dist2sensors)` | ~547 | **Text-Erkennung:** Iteriert ueber MTEXT-Entities auf erlaubten Layern. Sucht nach `-{name}` oder `+{name}` im Text. Gibt `{distname: (x, y)}` zurueck. |
| `get_subdistributor_positions_from_symbols(all_inserts, all_positions, dist2sensors)` | ~472 | **Symbol-Erkennung:** Iteriert ueber alle INSERT-Bloecke mit `NAME`-Attribut. Prueft NAME gegen Cabinet-Patterns aus BMK.cfg. Ruft `get_subdistributor_position_of_symbol()` fuer die Positionsextraktion auf. |
| `get_subdistributor_position_of_symbol(d_insert, d_pos)` | ~413 | Hilfsfunktion: Extrahiert Position aus einem einzelnen Unterverteiler-Block. Beruecksichtigt `REALE_POSITION` fuer Mittelpunktberechnung. Gibt `(dict, id)` zurueck. |
### Tunnel
| Funktion | Zeile | Aufgabe |
|---|---|---|
| `get_tunnel_positions_from_entities(entities)` | ~574 | **Text-Erkennung:** Iteriert ueber MTEXT-Entities auf erlaubten Layern. Regex `(TUNNEL\d+)-(\d+)` extrahiert Name und Laenge. Sammelt alle Positionen pro Tunnelname. |
| `get_tunnel_positions_from_symbols(all_inserts, all_positions, error_collector)` | ~493 | **Symbol-Erkennung:** Iteriert ueber alle INSERT-Bloecke mit `NAME`-Attribut. Prueft NAME gegen Tunnel-Patterns aus BMK.cfg. Liest `LAENGE`-Attribut (Default: 5m). Warnung bei fehlender Laenge. |
| `get_tunnel_position_of_symbol(d_insert, d_pos)` | ~441 | Hilfsfunktion: Extrahiert Position und Laenge aus einem einzelnen Tunnel-Block. Beruecksichtigt `REALE_POSITION`. Gibt `(dict, id)` zurueck. |
### Kabelpritschen
| Funktion | Zeile | Aufgabe |
|---|---|---|
| `get_rack_positions(msp)` | ~614 | Sucht LWPOLYLINE und POLYLINE auf erlaubten Layern. Nummeriert Racks automatisch (`Rack_1`, `Rack_2`, ...). Delegiert an `handle_lwpolyline()` bzw. `handle_polyline()`. |
| `handle_lwpolyline(entity, rack_key, ret)` | ~636 | Verarbeitet 2D-Polylinien. Z-Wert kommt global aus `elevation`. |
| `handle_polyline(entity, rack_key, ret)` | ~644 | Verarbeitet 3D-Polylinien. Jeder Vertex hat individuelle x/y/z-Koordinaten. |
| `check_rack_z_coordinates(res_racks, error_collector, config)` | ~654 | Validierung: Prueft ob Z-Koordinaten-Differenz den Schwellwert uebersteigt. |
### Erkennungsablauf im Hauptprogramm
```
1. DXF laden: get_dxf_file() -> msp
2. Alle Bloecke extrahieren: attribs_to_dicts(msp) -> all_inserts, all_positions
3. Sensoren: extract_input_positions(all_inserts, all_positions)
4. Mappings: create_mappings(res_sens) -> sensor2unterverteiler
5. Unterverteiler (Text): get_subdistributor_positions_from_entities(msp.query('MTEXT'))
6. Unterverteiler (Symbol): get_subdistributor_positions_from_symbols(all_inserts, all_positions)
7. Tunnel (Text): get_tunnel_positions_from_entities(msp.query('MTEXT'))
8. Tunnel (Symbol): get_tunnel_positions_from_symbols(all_inserts, all_positions)
9. Racks: get_rack_positions(msp)
```
---
## 7. Konfigurationsdateien
| Datei | Inhalt |
|---|---|
| `cfg/allgemein.cfg` | Layer-Zuordnungen, Geometrie-Parameter, Toleranzen |
| `cfg/BMK.cfg` | Geraete-Praefixe, Cabinet-Patterns, Tunnel-Patterns, Kabelzuordnungen |
| `cfg/kabel.cfg` | SIVAS-Artikelnummern nach Kabeltyp und Laenge |
| `cfg/bezeichner.cfg` | Artikelnummer-Beschreibungen |
+1 -2
View File
@@ -913,8 +913,7 @@ def map_sensor_to_cable_cfg(plines):
section_list = mapping[name_prefix]
else:
sens2cable[pl.id].append("Kein Kabeltyp zugewiesen (BMK.cfg)")
section_list = list()
# TODO was soll hier passieren wenn die Config falsch ist?
continue # Kein Mapping gefunden, Rest überspringen
# Liste aus evtl. mehreren Sektionen erzeugen
sections = [s.strip() for s in section_list.split(",")]
+22 -92
View File
@@ -6,16 +6,12 @@ import re
import sys
from pathlib import Path
import ezdxf
from ezdxf.addons import iterdxf
from shapely.geometry import Point
from ezdxf.lldxf.const import DXFStructureError
from error_collector import ErrorCollector, write_json_file
from error_collector import ErrorCollector
from utils import (
check_environment_var,
check_file_in_work,
dxf_is_binary,
get_dxf_file,
merge_two_dicts,
to_json,
@@ -509,7 +505,6 @@ def get_tunnel_positions_from_symbols(all_inserts: list, all_positions: list, er
ret = {}
tunnel_length = {}
tunnel_missing_length = {}
default_length = "5" # Default-Länge in Metern
for insert, pos in zip(all_inserts, all_positions):
if "NAME" not in insert: # Tunnel haben immer einen eindeutigen Namen
@@ -528,18 +523,17 @@ def get_tunnel_positions_from_symbols(all_inserts: list, all_positions: list, er
ret[id_] = []
ret[id_].append(ld["pos"])
# Sammle Längeninformation falls vorhanden, sonst Default verwenden
# Sammle Längeninformation falls vorhanden, sonst Fehler melden
if "laenge" in ld and ld["laenge"]:
tunnel_length[id_] = ld["laenge"]
else:
warning_msg = f"Tunnel '{id_}' hat keine LAENGE-Angabe. Verwende Default-Länge: {default_length}m"
print(f"WARNUNG: {warning_msg}")
tunnel_missing_length[id_] = warning_msg
tunnel_length[id_] = default_length
error_msg = f"Tunnel '{id_}' hat keine LAENGE-Angabe. Bitte LAENGE-Attribut im DXF-Symbol setzen."
print(f"FEHLER: {error_msg}")
tunnel_missing_length[id_] = error_msg
# Warnings zum ErrorCollector hinzufügen
# Fehlende LAENGE als Fehler melden (stoppt die Verarbeitung)
if error_collector and tunnel_missing_length:
error_collector.add_warnings({"tunnel_missing_length": tunnel_missing_length})
error_collector.add_errors({"tunnel_missing_length": tunnel_missing_length})
# Füge Längeninformation hinzu, falls Tunnel gefunden wurden
if len(tunnel_length) > 0:
@@ -551,10 +545,10 @@ def get_tunnel_positions_from_symbols(all_inserts: list, all_positions: list, er
def get_subdistributor_positions_from_entities(entities, dist2sensors: dict) -> dict:
"""Ermittelt Unterverteiler-Positionen aus einer beliebigen Entity-Iterable.
Erwartet eine Iterable von DXF-Entities (z. B. aus `msp.query("MTEXT")` oder
`iterdxf.modelspace(dxf_path)`) und filtert nach den in der Config erlaubten
Layern. Es werden beide bisher verwendeten Suchmuster in der MTEXT-Zeile
unterstützt ("-<distname>" und "+<distname>").
Erwartet eine Iterable von DXF-Entities (z. B. aus `msp.query("MTEXT")`)
und filtert nach den in der Config erlaubten Layern. Es werden beide bisher
verwendeten Suchmuster in der MTEXT-Zeile unterstützt ("-<distname>" und
"+<distname>").
"""
ret = {}
all_distributors = dist2sensors.keys()
@@ -578,10 +572,10 @@ def get_subdistributor_positions_from_entities(entities, dist2sensors: dict) ->
def get_tunnel_positions_from_entities(entities) -> dict:
"""Ermittelt Tunnel-Ein/Ausgangs-Positionen aus einer beliebigen Entity-Iterable.
Erwartet eine Iterable von DXF-Entities (z. B. aus `msp.query("MTEXT")` oder
`iterdxf.modelspace(dxf_path)`) und filtert nach den in der Config erlaubten
Layern. Erkennt Tunnel anhand des Musters "TUNNEL<nr>-<laenge>" und sammelt
pro Tunnelname die gefundenen Positionen sowie die Länge.
Erwartet eine Iterable von DXF-Entities (z. B. aus `msp.query("MTEXT")`)
und filtert nach den in der Config erlaubten Layern. Erkennt Tunnel anhand
des Musters "TUNNEL<nr>-<laenge>" und sammelt pro Tunnelname die gefundenen
Positionen sowie die Länge.
"""
all_tunnels = dict()
tunnel_length = dict()
@@ -614,17 +608,6 @@ def get_tunnel_positions_from_entities(entities) -> dict:
all_tunnels['length'] = tunnel_length
return all_tunnels
# helper function
def print_line(e) -> None:
print(f"LINE on layer: {e.dxf.layer}\n")
print(f"points: {repr(e.dxf)}\n")
def print_polyline(e) -> None:
print(f"POLYLINE on layer: {e.dxf.layer}\n")
for x, y, start_width, end_width, bulge in e.get_points():
print(f" Punkt: ({x}, {y}), Startbreite: ({start_width}, Endbreite: {end_width})")
if e.is_closed:
print("Diese Polyline ist geschlossen.")
def get_rack_positions(msp) -> dict:
"""Hole alle Positionen aller Kabelpritschen und nummeriere Racks."""
@@ -647,30 +630,6 @@ def get_rack_positions(msp) -> dict:
return ret
def get_rack_positions_iter(dxf_path) -> dict:
"""Hole alle Positionen aller Kabelpritschen (Racks) mithilfe von iterdxf."""
ret = dict()
rack_counter = 1
all_layers = config.items('GetPos-Layer_Racks')
for entity in iterdxf.modelspace(dxf_path):
layer = entity.dxf.layer
if not any(layer == cfg_layer for cfg_layer, _ in all_layers):
continue
rack_key = f"Rack_{rack_counter}"
if entity.dxftype() == "LWPOLYLINE":
handle_lwpolyline(entity, rack_key, ret)
elif entity.dxftype() == "POLYLINE":
handle_polyline(entity, rack_key, ret)
else:
continue
rack_counter += 1
return ret
def handle_lwpolyline(entity, rack_key: str, ret: dict) -> None:
"""Verarbeitet eine 2D LWPOLYLINE mit globalem Z-Wert (elevation)."""
@@ -689,15 +648,6 @@ def handle_polyline(entity, rack_key: str, ret: dict) -> None:
z = vertex.dxf.location.z
ret[rack_key].append([round(x, 1), round(y, 1), round(z, 1)])
def scan(dxf_source) -> dict:
layer_names_inside = list(dxf_source.layers.names())
alle_block_defs = set(dxf_source.blocks.block_names())
used_block_names = set(insert.dxf.name for insert in dxf_source.modelspace().query("INSERT"))
ret = dict()
ret['all_layers'] = layer_names_inside
ret['used_blocks'] = used_block_names
ret['all_blocks'] = alle_block_defs
return ret
def check_rack_z_coordinates(res_racks: dict, error_collector, config) -> None:
"""
@@ -828,17 +778,10 @@ if __name__ == '__main__':
parser.print_help()
exit()
if dxf_is_binary(dxf_path): # Wenn dxf eine binary ist, dann komplett parsen und modelspace anlegen
print("Given .dxf-file is binary dxf. Proceeding to read file. Watch RAM-usage.")
doc = get_dxf_file(dxf_path)
msp = doc.modelspace()
use_iter = False
else:
print("Given .dxf-file is ASCII-dxf. Proceeding to use iterative functions. Process may take longer.")
use_iter = True
doc = get_dxf_file(dxf_path)
msp = doc.modelspace()
res_sens = dict()
res_cables = dict()
res_dist = dict()
res_rac = dict()
res_mappings = dict()
@@ -870,16 +813,12 @@ if __name__ == '__main__':
if args.sensors:
# Sensoren auslesen aus den Symbolen
if use_iter:
all_inserts, all_positions = attribs_to_dicts(iterdxf.modelspace(dxf_path))
else:
all_inserts, all_positions = attribs_to_dicts(msp)
all_inserts, all_positions = attribs_to_dicts(msp)
res_sens, res_schaltschrank_elemente = extract_input_positions(all_inserts, all_positions, error_collector)
output_results['sensors'] = res_sens
output_results['schaltschrank_elemente'] = res_schaltschrank_elemente
#output_results['cables'] = res_cables
if args.console:
print(to_json(res_sens))
@@ -893,10 +832,7 @@ if __name__ == '__main__':
print(to_json(res_mappings))
# Distributoren auslesen (generisch über Entities)
if use_iter:
entities = iterdxf.modelspace(dxf_path)
else:
entities = msp.query('MTEXT')
entities = msp.query('MTEXT')
# die Infos aus den Texten (alter Stil)
res_dist = get_subdistributor_positions_from_entities(entities, res_mappings)
# die Infos aus den Blöcken
@@ -907,10 +843,7 @@ if __name__ == '__main__':
print(to_json(res_dist))
# Tunnel auslesen (generisch über Entities)
if use_iter:
t_entities = iterdxf.modelspace(dxf_path)
else:
t_entities = msp.query('MTEXT')
t_entities = msp.query('MTEXT')
# die Infos aus den Texten (alter Stil)
res_tunnel = get_tunnel_positions_from_entities(t_entities)
# die Infos aus den Blöcken (neuer Stil)
@@ -921,10 +854,7 @@ if __name__ == '__main__':
print(to_json(res_tunnel))
if args.rack:
if use_iter:
res_rac = get_rack_positions_iter(dxf_path)
else:
res_rac = get_rack_positions(msp)
res_rac = get_rack_positions(msp)
output_results['racks'] = res_rac
+13 -4
View File
@@ -4,6 +4,7 @@
Test für die check_rack_z_coordinates Funktion
"""
import configparser
import sys
from pathlib import Path
@@ -13,6 +14,14 @@ sys.path.insert(0, str(Path(__file__).parent))
from getpositions import check_rack_z_coordinates
from error_collector import ErrorCollector
def _make_config(max_height_diff=2000.0):
"""Erzeugt ein minimales Config-Objekt für die Tests."""
config = configparser.ConfigParser()
config.add_section("Racks")
config.set("Racks", "MaximalTotalHeightDifferences", str(max_height_diff))
return config
def test_no_deviation():
"""Test mit Racks ohne starke Abweichung (< 2000mm)"""
print("Test 1: Keine starke Abweichung (< 2000mm)")
@@ -24,7 +33,7 @@ def test_no_deviation():
}
error_collector = ErrorCollector()
check_rack_z_coordinates(racks, error_collector)
check_rack_z_coordinates(racks, error_collector, _make_config())
warnings = error_collector.warnings
if warnings:
@@ -44,7 +53,7 @@ def test_with_deviation():
}
error_collector = ErrorCollector()
check_rack_z_coordinates(racks, error_collector)
check_rack_z_coordinates(racks, error_collector, _make_config())
warnings = error_collector.warnings
if warnings:
@@ -63,7 +72,7 @@ def test_exactly_2000mm():
}
error_collector = ErrorCollector()
check_rack_z_coordinates(racks, error_collector)
check_rack_z_coordinates(racks, error_collector, _make_config())
warnings = error_collector.warnings
if warnings:
@@ -82,7 +91,7 @@ def test_dict_format():
}
error_collector = ErrorCollector()
check_rack_z_coordinates(racks, error_collector)
check_rack_z_coordinates(racks, error_collector, _make_config())
warnings = error_collector.warnings
if warnings:
+1 -1
View File
@@ -573,7 +573,7 @@ class Anlage():
color = "blue"
elif re.match("t-.*", rname):
color = "orange"
tname = rname.split("-")[2]
tname = rname.split("-", 2)[2]
weight = self.get_tunnel_length(tname)
elif re.match("c-.*", rname):
color = "green"
+1 -1
View File
@@ -99,7 +99,7 @@ def prepare_data(rawdata:dict):
for sname, sdata in sensors.items():
dsensors[sname] = {
"point": Point(sdata["pos"]),
"artinr": sdata.get("ARTINR","")
"artinr": sdata.get("ARTINR","").strip()
}
subdists = rawdata["distributors"]
+1073 -570
View File
File diff suppressed because it is too large Load Diff
+27 -37
View File
@@ -1,5 +1,5 @@
#Übersetzungsdatei Erweiterung von Nikolai Schwechten 09.12.2025
#Änderungsstand 09.12.2025, 15:02h
#Übersetzungsdatei Erweiterung von Marcus Schellhammer 23.03.2026
#Änderungsstand 23.03.2026, 12:18h
[multi]
@@ -49,6 +49,8 @@ zu System Fortna C=do systému Fortna C
empty Minitrolleys from =prázdné minivozíky z
Feedback Hauptschütze aktiv=Zpětná vazba Hlavní spínač aktivní
Feedback Koppelrelais E-Stop-IF=Zpětná vazba Spínací relé Nouzové zastavení Rozhraní
Feedback Koppelrelais Not-Halt-IF=Zpětná vazba Spojovací relé Not-Halt-IF
Feedback Koppelrelais Not-Halt-Schnittstelle=Zpětná vazba Spínací relé Rozhraní nouzového zastavení
GOH storage level=Úroveň skladování GOH
Hauptschütze aktivieren CH 1 =Aktivovat hlavní stykače CH 1
Hauptschütze aktivieren CH 2 =Aktivovat hlavní stykače CH 2
@@ -57,7 +59,7 @@ Highway Omniflow-System=Systém Highway Omniflow
IF Fire door =Rozhraní protipožární dveře
IF RFID=Rozhraní RFID
infiltrate with TEF=infiltrovat pomocí TEF
loaded Minitrolleys from=naloženými mini vozíky z
loaded Minitrolleys from=naloženými minivozíky z
Loading Station for Hangsacks=Nakládací stanice pro závěsné pytle
LS Endlage ausgefahren=Nabíjecí smyčka Koncová poloha vysunutá
LS Endlage eingefahren=Nabíjecí smyčka koncová poloha zasunuta
@@ -78,7 +80,7 @@ SEW MOVIMOT OK LS=SEW MOVIMOT OK Nabíjecí smyčka
Anfahrwarnung=Varování při rozjezdu
Signalsäule  Hupe=Signální sloupek  Klakson
Signalsäule Hupe=Signální sloupek  Klakson
Signalsäule blau=Signální sloup modrý
Signalsäule blau=Signální sloup modrýp
Signalsäule Blau=Signální sloup modrý
Fehlerhafter Mini-Trolley=Vadný mini vozík
Signalsäule Gelb=Signální sloupek žlutý
@@ -108,15 +110,11 @@ DT Anlage Aus=Tlačítko Vypnout zařízení
LDT Anlage Ein=Světelný tlačítko Zapnout zařízení
LM Brandfall=Světelná signalizace požáru
LM Druckluft fehlt=Kontrolka nedostatku stlačeného vzduchu
Empty Minitrolleys=Prázdné minivozíky
[bigramme]
AMR ILS=AMR ILS
Motor+Bremse=Motor s brzdou
Belastung \PAbhänger:=Zatížení závěsu:
Belastung Hänger=Zatížení závěsů
Belastung Säule=Zatížení sloupu
bottom rail edge:=spodní hrana lišty:
cable tray =kabelový žlab
call for help=volání o pomoc
@@ -135,7 +133,7 @@ Empty hanger=Prázdné věšáky
Empty Minitrolleys=Prázdné minivozíky
empty Minitrolleys=prázdné minivozíky
empty Trolleys=prázdné vozíky
E-stop Kanal =Kanál E-stop
E-stop Kanal=Kanál E-stop
EU pallet=Paleta EU
F2H Workstations=Pracovní stanice F2H
Flat packed=Ploché balení
@@ -147,7 +145,6 @@ GoH pallet=Paleta GoH
Ground Floor=Přízemí
Hand scanner=Ruční skener
Hauptschütze aktivieren=Aktivace hlavního stykače
IF BST=IF BST
Ladebaum aktivieren=Aktivovat nabíjecí strom
Ladeschleife ausfahren =Vysunutí nabíjecí smyčky
Ladeschleife einfahren =Zatáhnout nabíjecí smyčku
@@ -160,7 +157,7 @@ Loading Boom=Nakládací rameno
max. capacity=maximální kapacita
Mounting plate=Montážní deska
MSS ausgelöst=Spuštěný jistič motoru
NA Kanal =Nouzové vypnutí kanálu
NA Kanal=Nouzové vypnutí kanálu
Neigungssensor Ladeschleife =Snímač sklonu Nakládací smyčka
New jet=Nový tryskový motor
Non fault=Bez poruchy
@@ -181,46 +178,32 @@ Sub distributor=Podružný rozvaděč
Vorsicherung 400V=Předřadný jistič 400 V
zu UH=k UH
Sub-distributor=Rozvaděč rozvodné skříně
Aufzugbereich freifahren=Uvolnit prostor pro výtah
Not Halt=Ne zastavit
[single]
#Auskommentiert nach Problemen in Ignore, jetzt hier als Blindübersetzung
A01=A01
UC=UC
UZ=UZ
# deutsche Begriffe und ihre tschechische Übersetzung
# Format: Begriffe in der dxf=tschechisch
ILS-CV=ILS-CV
AMR=AMR
ILS=ILS
Omniflo=Omniflo
OMNIFLO=OMNIFLO
omniflo=omniflo
L x D x H=D x Š x V
area=oblast
Ausfahren=Výsuv
ausgefahren=vyjetý
Beladeposition=Poloha nakládky
Belastung=zatížení
Säule=sloup
Nouzové=Nouzové
Nakládací=Nakládací
nahoru=nahoru
Připraveno=Připraveno
#Belastung=zatížení
#Säule=sloup
Bereichshalt=Zastavení oblasti
Betrieb=Provoz
Betriebsbereit=Připraveno k provozu
BLOCK=Blok
Bodenabstandssensor =Senzor vzdálenosti od podlahy
Brandschutztor=Protipožární vrata
buffer=buffer
Customer=Zákazník
Door=Dveře
Einfahren=Zasunutí
eingefahren=zasunutý
empty=prázdný
Firewall=Firewall
Freigabe=Uvolnění
Freigeben=Uvolnit
gelb=žlutá
@@ -241,38 +224,31 @@ LEVEL=ÚROVEŇ
Level=Úroveň
level=Úroveň
Line=Linka
long=long
LS 1=NS 1
LS 2=NS 2
LS1=NS 1
LS2=NS 2
Meldekontakt=Signalizační kontakt
Motor=Motor
Multi-Purpose-Station=Víceúčelová stanice
Not-Halt=Nouzové zastavení
outbound=odchozí
Outbound=Outbound
pallet=paleta
Paper=Papír
Phasenausfall =Výpadek fáze
Pickstation=Sběrná stanice
Placeholder =Zástupný symbol
Plastic=Plast
Rail=Rail
Reading=Čtení
Release=Vydání
Reserve=Rezerva
Reset=Reset
Rot=Červená
rot=červená
Schaltschrank=Rozvaděč
Schlüsselschalter=Klíčový spínač
Schnitt =Řez
Screen=Obrazovka
short=short
Signalsäule=Signální sloup
Stützfuß=Opěrná noha
supply=supply
Table =Tabulka
Tray=Zásobník
Unterverteiler=Rozvaděč
@@ -280,3 +256,17 @@ Waste=Odpad
Weight=Hmotnost
wheel=kolo
Workstation=Pracovní stanice
Lechtdrucktaster=Osvětlené tlačítko
Vorsicherung=přední pojistka
Vorsicherungen=přední pojistky
Firewall=Firewall
Rail=kolejnice
LDT=TS
DRUCKTASTER=Tlačítko
DT=TL
LEUCHTMELDER=Signální svítidlo
LM=SS
RESET=RESET
reset=reset