Primera version
This commit is contained in:
commit
fb26f0eb54
|
@ -0,0 +1,174 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# UV
|
||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
#uv.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# Ruff stuff:
|
||||
.ruff_cache/
|
||||
|
||||
# PyPI configuration file
|
||||
.pypirc
|
|
@ -0,0 +1,486 @@
|
|||
{
|
||||
"Name": "BlenderCtrl__Main",
|
||||
"Number": "2000",
|
||||
"ProgrammingLanguage": "LAD",
|
||||
"Interface": {},
|
||||
"Networks": [
|
||||
{
|
||||
"index": 1,
|
||||
"title": "Clock Generation",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 2,
|
||||
"title": "Machine Init",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 3,
|
||||
"title": "Filler Head",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 4,
|
||||
"title": "Emergency Pressed",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 5,
|
||||
"title": "Air and CO2 pressure ok and auxiliary ok",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 6,
|
||||
"title": "Blender State Num",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 7,
|
||||
"title": "Delay Power On",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 8,
|
||||
"title": "Production Mode",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 9,
|
||||
"title": "CIp Mode",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 10,
|
||||
"title": "Error Faults",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 11,
|
||||
"title": "Filler Bottle Count Used to push Product",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 12,
|
||||
"title": "Water Bypass Enable",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 13,
|
||||
"title": "Still Water Bypass",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 14,
|
||||
"title": "Manual Syrup Drain Valve Open - Operator Alarm",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 15,
|
||||
"title": "Manual Syrup Drain Valve Open - Operator Alarm",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 16,
|
||||
"title": "Maselli Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 17,
|
||||
"title": "mPDS Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 18,
|
||||
"title": "mPDS Syrup Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 19,
|
||||
"title": "Co2 Analog Input",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 20,
|
||||
"title": "Quality",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 21,
|
||||
"title": "Input Data",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 22,
|
||||
"title": "Sel Brix Source Check",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 23,
|
||||
"title": "Check Water Cooling System Temperature",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 24,
|
||||
"title": "Tank Level",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 25,
|
||||
"title": "Production ONS",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 26,
|
||||
"title": "Blender Prod Mode Init",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 27,
|
||||
"title": "Rinse ONS",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 28,
|
||||
"title": "CIP ONS",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 29,
|
||||
"title": "CIp Mode Init",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 30,
|
||||
"title": "Reset SPWords ",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 31,
|
||||
"title": "Blender Run Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 32,
|
||||
"title": "Tank Pressure Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 33,
|
||||
"title": "Balaiage",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 34,
|
||||
"title": "First Production",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 35,
|
||||
"title": "CIP MAIN Calling ",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 36,
|
||||
"title": "Blender Rinse",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 37,
|
||||
"title": "Safeties",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 38,
|
||||
"title": "Instrument Scanner",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 39,
|
||||
"title": "Vacuum Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 40,
|
||||
"title": "Syrup Room Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 41,
|
||||
"title": "Blend Procedure Data",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 42,
|
||||
"title": "Pneumatic Valve Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 43,
|
||||
"title": "Pumps Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 44,
|
||||
"title": "Prod Report Manager",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 45,
|
||||
"title": "Outputs",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 46,
|
||||
"title": "SLIM BLOCK",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 47,
|
||||
"title": "Interlocking Panel 1",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 48,
|
||||
"title": "Filler Control",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 49,
|
||||
"title": "Blender Ctrl Update PWORD",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 50,
|
||||
"title": "ResetTotalizer",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 51,
|
||||
"title": "ResetWaterTot",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 52,
|
||||
"title": "Water VFM Reset Totalizer",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 53,
|
||||
"title": "ResetCO2Tot",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 54,
|
||||
"title": "Syrup MFM Reset Totalizer",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 55,
|
||||
"title": "ResetProductTot",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 56,
|
||||
"title": "CO2 MFM Reset Tot",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 57,
|
||||
"title": "ResetCO2Tot",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 58,
|
||||
"title": "Reset Totalizer",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 59,
|
||||
"title": "Reset Totalizer",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 60,
|
||||
"title": "Blender Ctrl Command",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 61,
|
||||
"title": "DP Global Diag",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 62,
|
||||
"title": "Profibus",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 63,
|
||||
"title": "Valve Fault",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 64,
|
||||
"title": "All Auto",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 65,
|
||||
"title": "Ctrl HMI Manual Active",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 66,
|
||||
"title": "Mod Copy Recipe",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 67,
|
||||
"title": "to HMI - Recipe Management",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
},
|
||||
{
|
||||
"index": 68,
|
||||
"title": "Recipe Calculation",
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
}
|
||||
],
|
||||
"all_variables": [],
|
||||
"all_function_calls": []
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
# Function Block: BlenderCtrl__Main (FC2000)
|
||||
|
||||
**Programming Language:** LAD
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Interface](#interface)
|
||||
2. [Summary of Variables](#summary-of-variables)
|
||||
3. [Summary of Function Calls](#summary-of-function-calls)
|
||||
4. [Networks Detail](#networks-detail)
|
||||
5. [Call Tree](#call-tree)
|
||||
|
||||
## Interface
|
||||
|
||||
_No interface information available_
|
||||
|
||||
## Summary of Variables
|
||||
|
||||
_No variables found_
|
||||
|
||||
|
||||
## Summary of Function Calls
|
||||
|
||||
_No function calls found_
|
||||
|
||||
|
||||
## Networks Detail (68 networks)
|
||||
|
||||
### Network 1: Clock Generation
|
||||
|
||||
### Network 2: Machine Init
|
||||
|
||||
### Network 3: Filler Head
|
||||
|
||||
### Network 4: Emergency Pressed
|
||||
|
||||
### Network 5: Air and CO2 pressure ok and auxiliary ok
|
||||
|
||||
### Network 6: Blender State Num
|
||||
|
||||
### Network 7: Delay Power On
|
||||
|
||||
### Network 8: Production Mode
|
||||
|
||||
### Network 9: CIp Mode
|
||||
|
||||
### Network 10: Error Faults
|
||||
|
||||
### Network 11: Filler Bottle Count Used to push Product
|
||||
|
||||
### Network 12: Water Bypass Enable
|
||||
|
||||
### Network 13: Still Water Bypass
|
||||
|
||||
### Network 14: Manual Syrup Drain Valve Open - Operator Alarm
|
||||
|
||||
### Network 15: Manual Syrup Drain Valve Open - Operator Alarm
|
||||
|
||||
### Network 16: Maselli Control
|
||||
|
||||
### Network 17: mPDS Control
|
||||
|
||||
### Network 18: mPDS Syrup Control
|
||||
|
||||
### Network 19: Co2 Analog Input
|
||||
|
||||
### Network 20: Quality
|
||||
|
||||
### Network 21: Input Data
|
||||
|
||||
### Network 22: Sel Brix Source Check
|
||||
|
||||
### Network 23: Check Water Cooling System Temperature
|
||||
|
||||
### Network 24: Tank Level
|
||||
|
||||
### Network 25: Production ONS
|
||||
|
||||
### Network 26: Blender Prod Mode Init
|
||||
|
||||
### Network 27: Rinse ONS
|
||||
|
||||
### Network 28: CIP ONS
|
||||
|
||||
### Network 29: CIp Mode Init
|
||||
|
||||
### Network 30: Reset SPWords
|
||||
|
||||
### Network 31: Blender Run Control
|
||||
|
||||
### Network 32: Tank Pressure Control
|
||||
|
||||
### Network 33: Balaiage
|
||||
|
||||
### Network 34: First Production
|
||||
|
||||
### Network 35: CIP MAIN Calling
|
||||
|
||||
### Network 36: Blender Rinse
|
||||
|
||||
### Network 37: Safeties
|
||||
|
||||
### Network 38: Instrument Scanner
|
||||
|
||||
### Network 39: Vacuum Control
|
||||
|
||||
### Network 40: Syrup Room Control
|
||||
|
||||
### Network 41: Blend Procedure Data
|
||||
|
||||
### Network 42: Pneumatic Valve Control
|
||||
|
||||
### Network 43: Pumps Control
|
||||
|
||||
### Network 44: Prod Report Manager
|
||||
|
||||
### Network 45: Outputs
|
||||
|
||||
### Network 46: SLIM BLOCK
|
||||
|
||||
### Network 47: Interlocking Panel 1
|
||||
|
||||
### Network 48: Filler Control
|
||||
|
||||
### Network 49: Blender Ctrl Update PWORD
|
||||
|
||||
### Network 50: ResetTotalizer
|
||||
|
||||
### Network 51: ResetWaterTot
|
||||
|
||||
### Network 52: Water VFM Reset Totalizer
|
||||
|
||||
### Network 53: ResetCO2Tot
|
||||
|
||||
### Network 54: Syrup MFM Reset Totalizer
|
||||
|
||||
### Network 55: ResetProductTot
|
||||
|
||||
### Network 56: CO2 MFM Reset Tot
|
||||
|
||||
### Network 57: ResetCO2Tot
|
||||
|
||||
### Network 58: Reset Totalizer
|
||||
|
||||
### Network 59: Reset Totalizer
|
||||
|
||||
### Network 60: Blender Ctrl Command
|
||||
|
||||
### Network 61: DP Global Diag
|
||||
|
||||
### Network 62: Profibus
|
||||
|
||||
### Network 63: Valve Fault
|
||||
|
||||
### Network 64: All Auto
|
||||
|
||||
### Network 65: Ctrl HMI Manual Active
|
||||
|
||||
### Network 66: Mod Copy Recipe
|
||||
|
||||
### Network 67: to HMI - Recipe Management
|
||||
|
||||
### Network 68: Recipe Calculation
|
||||
|
||||
## Call Tree
|
||||
|
||||
```
|
||||
Function Call Tree:
|
||||
└─ BlenderCtrl__Main
|
||||
|
||||
```
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,306 @@
|
|||
import xml.etree.ElementTree as ET
|
||||
import json
|
||||
import os
|
||||
|
||||
class SiemensLadderDoc:
|
||||
def __init__(self):
|
||||
self.function_calls_map = {} # Mapa de función -> llamadas
|
||||
self.all_variables = set() # Todas las variables usadas
|
||||
self.all_function_calls = set() # Todas las llamadas a funciones
|
||||
|
||||
def extract_semantics(self, xml_file):
|
||||
"""Extrae la semántica principal del archivo XML de Siemens"""
|
||||
try:
|
||||
tree = ET.parse(xml_file)
|
||||
root = tree.getroot()
|
||||
except Exception as e:
|
||||
return f"Error processing XML: {str(e)}"
|
||||
|
||||
# Extraer información del bloque
|
||||
block_info = {}
|
||||
block = root.find(".//SW.Blocks.FC") or root.find(".//SW.Blocks.FB")
|
||||
|
||||
if block is None:
|
||||
return "No function block found in the file"
|
||||
|
||||
# Extraer atributos básicos
|
||||
attr_list = block.find("AttributeList")
|
||||
if attr_list is not None:
|
||||
for attr in attr_list:
|
||||
if attr.tag in ["Name", "Number", "ProgrammingLanguage"]:
|
||||
block_info[attr.tag] = attr.text
|
||||
|
||||
# Extraer interface (inputs, outputs, temp variables)
|
||||
interface_section = block.find(".//Interface")
|
||||
if interface_section is not None:
|
||||
block_info["Interface"] = self.extract_interface(interface_section)
|
||||
|
||||
# Procesar todas las redes
|
||||
compile_units = block.findall(".//SW.Blocks.CompileUnit")
|
||||
networks = []
|
||||
|
||||
block_name = block_info.get('Name', 'Unknown')
|
||||
self.function_calls_map[block_name] = []
|
||||
|
||||
for i, unit in enumerate(compile_units):
|
||||
network = self.process_network(unit, i+1, block_name)
|
||||
networks.append(network)
|
||||
|
||||
# Actualizar todas las variables y llamadas
|
||||
for var in network['variables']:
|
||||
self.all_variables.add(var)
|
||||
|
||||
for call in network['calls']:
|
||||
self.all_function_calls.add(call)
|
||||
if call not in self.function_calls_map[block_name]:
|
||||
self.function_calls_map[block_name].append(call)
|
||||
|
||||
block_info["Networks"] = networks
|
||||
|
||||
# Añadir resúmenes globales
|
||||
block_info["all_variables"] = sorted(list(self.all_variables))
|
||||
block_info["all_function_calls"] = sorted(list(self.all_function_calls))
|
||||
|
||||
return block_info
|
||||
|
||||
def extract_interface(self, interface):
|
||||
"""Extrae la información de interfaz (entradas, salidas, variables temporales)"""
|
||||
result = {}
|
||||
|
||||
# Buscar secciones directamente
|
||||
for section_name in ["Input", "Output", "InOut", "Temp", "Constant", "Return"]:
|
||||
section = interface.find(f".//Section[@Name='{section_name}']")
|
||||
if section is not None:
|
||||
result[section_name] = []
|
||||
|
||||
for member in section.findall("./Member"):
|
||||
result[section_name].append({
|
||||
"Name": member.get("Name"),
|
||||
"Datatype": member.get("Datatype")
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
def process_network(self, network, index, parent_block):
|
||||
"""Procesa una red para extraer sus elementos principales"""
|
||||
result = {
|
||||
"index": index,
|
||||
"title": self.get_network_title(network),
|
||||
"calls": [],
|
||||
"variables": [],
|
||||
"logic_elements": []
|
||||
}
|
||||
|
||||
# Extraer las llamadas a funciones (dentro del elemento Call)
|
||||
call_elements = network.findall(".//Call")
|
||||
for call in call_elements:
|
||||
call_info = call.find("CallInfo")
|
||||
if call_info is not None:
|
||||
call_name = call_info.get("Name", "Unknown")
|
||||
if call_name not in result["calls"]:
|
||||
result["calls"].append(call_name)
|
||||
|
||||
# Registra en el mapa de llamadas para el árbol
|
||||
if call_name not in self.function_calls_map:
|
||||
self.function_calls_map[call_name] = []
|
||||
|
||||
# Buscar accesos a variables (dentro del elemento Access)
|
||||
access_elements = network.findall(".//Access[@Scope='GlobalVariable']")
|
||||
for access in access_elements:
|
||||
var_name = self.extract_variable_name(access)
|
||||
if var_name and var_name not in result["variables"]:
|
||||
result["variables"].append(var_name)
|
||||
|
||||
# Buscar elementos lógicos (dentro del elemento Part)
|
||||
part_elements = network.findall(".//Part")
|
||||
for part in part_elements:
|
||||
part_name = part.get("Name")
|
||||
if part_name and part_name not in result["logic_elements"]:
|
||||
result["logic_elements"].append(part_name)
|
||||
|
||||
return result
|
||||
|
||||
def get_network_title(self, network):
|
||||
"""Extrae el título de una red - Versión corregida sin XPath avanzado"""
|
||||
# Primer intento: Buscar título en italiano
|
||||
title_sections = network.findall(".//MultilingualText[@CompositionName='Title']")
|
||||
for title_section in title_sections:
|
||||
items = title_section.findall(".//MultilingualTextItem")
|
||||
for item in items:
|
||||
attr_list = item.find("AttributeList")
|
||||
if attr_list is not None:
|
||||
culture = attr_list.find("Culture")
|
||||
text = attr_list.find("Text")
|
||||
|
||||
# Priorizar italiano
|
||||
if culture is not None and culture.text == 'it-IT' and text is not None and text.text:
|
||||
return text.text
|
||||
|
||||
# Cualquier otro texto
|
||||
if text is not None and text.text:
|
||||
return text.text
|
||||
|
||||
return "Unnamed Network"
|
||||
|
||||
def extract_variable_name(self, access_element):
|
||||
"""Extrae el nombre de variable desde un elemento Access"""
|
||||
symbol = access_element.find("Symbol")
|
||||
if symbol is not None:
|
||||
components = []
|
||||
for component in symbol.findall("Component"):
|
||||
components.append(component.get("Name", ""))
|
||||
return ".".join(components)
|
||||
return None
|
||||
|
||||
def generate_call_tree(self):
|
||||
"""Genera un árbol de llamadas en formato texto"""
|
||||
if not self.function_calls_map:
|
||||
return "No function calls found."
|
||||
|
||||
def build_tree(function_name, depth=0, visited=None):
|
||||
if visited is None:
|
||||
visited = set()
|
||||
|
||||
if function_name in visited:
|
||||
return f"{' ' * depth}└─ {function_name} (recursive call)\n"
|
||||
|
||||
visited.add(function_name)
|
||||
result = f"{' ' * depth}└─ {function_name}\n"
|
||||
|
||||
if function_name in self.function_calls_map:
|
||||
for called_function in self.function_calls_map[function_name]:
|
||||
result += build_tree(called_function, depth + 1, visited.copy())
|
||||
|
||||
return result
|
||||
|
||||
tree = "Function Call Tree:\n"
|
||||
# Comenzar solo con los bloques principales (que no son llamados por otros)
|
||||
root_functions = set(self.function_calls_map.keys())
|
||||
for func, calls in self.function_calls_map.items():
|
||||
for call in calls:
|
||||
if call in root_functions:
|
||||
root_functions.remove(call)
|
||||
|
||||
for main_function in root_functions:
|
||||
tree += build_tree(main_function)
|
||||
tree += "\n"
|
||||
|
||||
return tree
|
||||
|
||||
def generate_markdown(self, block_info):
|
||||
"""Genera documentación en formato markdown"""
|
||||
if isinstance(block_info, str):
|
||||
return f"# Error\n\n{block_info}"
|
||||
|
||||
block_name = block_info.get('Name', 'Unknown')
|
||||
block_number = block_info.get('Number', 'Unknown')
|
||||
|
||||
md = f"# Function Block: {block_name} (FC{block_number})\n\n"
|
||||
md += f"**Programming Language:** {block_info.get('ProgrammingLanguage', 'Unknown')}\n\n"
|
||||
|
||||
# Tabla de Contenido
|
||||
md += "## Table of Contents\n\n"
|
||||
md += "1. [Interface](#interface)\n"
|
||||
md += "2. [Summary of Variables](#summary-of-variables)\n"
|
||||
md += "3. [Summary of Function Calls](#summary-of-function-calls)\n"
|
||||
md += "4. [Networks Detail](#networks-detail)\n"
|
||||
md += "5. [Call Tree](#call-tree)\n\n"
|
||||
|
||||
# Información de interfaz
|
||||
md += "## Interface\n\n"
|
||||
if "Interface" in block_info and block_info["Interface"]:
|
||||
for section_name, members in block_info["Interface"].items():
|
||||
if members:
|
||||
md += f"### {section_name}\n\n"
|
||||
md += "| Name | Datatype |\n|------|----------|\n"
|
||||
|
||||
for member in members:
|
||||
md += f"| {member['Name']} | {member['Datatype']} |\n"
|
||||
|
||||
md += "\n"
|
||||
else:
|
||||
md += "_No interface information available_\n\n"
|
||||
|
||||
# Resumen de variables
|
||||
md += "## Summary of Variables\n\n"
|
||||
if block_info.get("all_variables"):
|
||||
md += "All global variables used in this function block:\n\n"
|
||||
for var in block_info.get("all_variables"):
|
||||
md += f"- `{var}`\n"
|
||||
else:
|
||||
md += "_No variables found_\n\n"
|
||||
|
||||
# Resumen de llamadas a funciones
|
||||
md += "\n## Summary of Function Calls\n\n"
|
||||
if block_info.get("all_function_calls"):
|
||||
md += "All functions called by this function block:\n\n"
|
||||
for func in block_info.get("all_function_calls"):
|
||||
md += f"- `{func}`\n"
|
||||
else:
|
||||
md += "_No function calls found_\n\n"
|
||||
|
||||
# Detalles de redes
|
||||
networks = block_info.get("Networks", [])
|
||||
md += f"\n## Networks Detail ({len(networks)} networks)\n\n"
|
||||
|
||||
for network in networks:
|
||||
md += f"### Network {network['index']}: {network['title']}\n\n"
|
||||
|
||||
if network['calls']:
|
||||
md += "**Function Calls:**\n"
|
||||
for call in network['calls']:
|
||||
md += f"- `{call}`\n"
|
||||
md += "\n"
|
||||
|
||||
if network['logic_elements']:
|
||||
md += "**Logic Elements:**\n"
|
||||
for element in network['logic_elements']:
|
||||
md += f"- {element}\n"
|
||||
md += "\n"
|
||||
|
||||
if network['variables']:
|
||||
md += "**Variables Used:**\n"
|
||||
for var in network['variables']:
|
||||
md += f"- `{var}`\n"
|
||||
md += "\n"
|
||||
|
||||
# Árbol de llamadas
|
||||
md += "## Call Tree\n\n"
|
||||
md += "```\n"
|
||||
md += self.generate_call_tree()
|
||||
md += "```\n"
|
||||
|
||||
return md
|
||||
|
||||
def process_siemens_file(file_path, output_format="markdown"):
|
||||
"""Procesa un archivo Siemens PLC y genera la documentación"""
|
||||
extractor = SiemensLadderDoc()
|
||||
block_info = extractor.extract_semantics(file_path)
|
||||
|
||||
if output_format.lower() == "json":
|
||||
return json.dumps(block_info, indent=2)
|
||||
elif output_format.lower() == "markdown":
|
||||
return extractor.generate_markdown(block_info)
|
||||
elif output_format.lower() == "call_tree":
|
||||
extractor.extract_semantics(file_path)
|
||||
return extractor.generate_call_tree()
|
||||
else:
|
||||
return "Unknown output format. Supported formats: markdown, json, call_tree"
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python script.py <xml_file> [output_format]")
|
||||
sys.exit(1)
|
||||
|
||||
file_path = sys.argv[1]
|
||||
output_format = sys.argv[2] if len(sys.argv) > 2 else "markdown"
|
||||
|
||||
result = process_siemens_file(file_path, output_format)
|
||||
|
||||
output_file = os.path.splitext(file_path)[0] + "." + ("json" if output_format.lower() == "json" else "md")
|
||||
with open(output_file, "w", encoding="utf-8") as f:
|
||||
f.write(result)
|
||||
|
||||
print(f"Documentation generated: {output_file}")
|
Loading…
Reference in New Issue