Primera version
This commit is contained in:
commit
06da71cd46
|
@ -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
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,981 @@
|
|||
{
|
||||
"block_name": "BlenderRun_ProdTime",
|
||||
"block_number": 2040,
|
||||
"language": "LAD",
|
||||
"interface": {},
|
||||
"networks": [
|
||||
{
|
||||
"id": "9",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "26",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "21",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "27",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "22",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "26",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "28",
|
||||
"type": "Add",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"uid": "23",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "24",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "27",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "25",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "1A",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "24",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "21",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "25",
|
||||
"type": "Move",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"uid": "22",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "24",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out1": [
|
||||
{
|
||||
"uid": "23",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2B",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "26",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "21",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "27",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "22",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "26",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "28",
|
||||
"type": "Add",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"uid": "23",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "24",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "27",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "25",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3C",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "24",
|
||||
"type": "Eq",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"uid": "21",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "22",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"pre": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "25",
|
||||
"type": "Coil",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "24",
|
||||
"source_instruction_type": "Eq",
|
||||
"source_pin": "out"
|
||||
},
|
||||
"operand": {
|
||||
"uid": "23",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4D",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "27",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "21",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "28",
|
||||
"type": "Move",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"uid": "22",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "27",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out1": [
|
||||
{
|
||||
"uid": "23",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "29",
|
||||
"type": "Add",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"uid": "24",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "25",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "26",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5E",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "24",
|
||||
"type": "Eq",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"uid": "21",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "22",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"pre": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "25",
|
||||
"type": "Coil",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "24",
|
||||
"source_instruction_type": "Eq",
|
||||
"source_pin": "out"
|
||||
},
|
||||
"operand": {
|
||||
"uid": "23",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "6F",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "30",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "21",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "31",
|
||||
"type": "Move",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"uid": "22",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "30",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out1": [
|
||||
{
|
||||
"uid": "23",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "32",
|
||||
"type": "Add",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"uid": "24",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "25",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "26",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "33",
|
||||
"type": "Add",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"uid": "27",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "28",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "29",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "80",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "29",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "21",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "30",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "22",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "31",
|
||||
"type": "O",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "29",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
},
|
||||
"in2": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "30",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "32",
|
||||
"type": "Move",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"uid": "23",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "31",
|
||||
"source_instruction_type": "O",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out1": [
|
||||
{
|
||||
"uid": "24",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "33",
|
||||
"type": "Move",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"uid": "25",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out1": [
|
||||
{
|
||||
"uid": "26",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "34",
|
||||
"type": "Move",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"uid": "27",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out1": [
|
||||
{
|
||||
"uid": "28",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "91",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "26",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "21",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "27",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "22",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "26",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "28",
|
||||
"type": "Add",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"uid": "23",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "24",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "27",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "25",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "A2",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "35",
|
||||
"type": "Convert",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"uid": "21",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "22",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "36",
|
||||
"type": "Mod",
|
||||
"inputs": {
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "35",
|
||||
"source_instruction_type": "Convert",
|
||||
"source_pin": "eno"
|
||||
},
|
||||
"in1": {
|
||||
"uid": "23",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "24",
|
||||
"scope": "TypedConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "25",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "37",
|
||||
"type": "Eq",
|
||||
"inputs": {
|
||||
"pre": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "36",
|
||||
"source_instruction_type": "Mod",
|
||||
"source_pin": "eno"
|
||||
},
|
||||
"in1": {
|
||||
"uid": "26",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "27",
|
||||
"scope": "TypedConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "38",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "37",
|
||||
"source_instruction_type": "Eq",
|
||||
"source_pin": "out"
|
||||
},
|
||||
"operand": {
|
||||
"uid": "28",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "39",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "29",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "38",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "40",
|
||||
"type": "Add",
|
||||
"inputs": {
|
||||
"in1": {
|
||||
"uid": "30",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "31",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "39",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "32",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "41",
|
||||
"type": "PBox",
|
||||
"inputs": {
|
||||
"bit": {
|
||||
"uid": "33",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "42",
|
||||
"type": "Coil",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "41",
|
||||
"source_instruction_type": "PBox",
|
||||
"source_pin": "out"
|
||||
},
|
||||
"operand": {
|
||||
"uid": "34",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "B3",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "32",
|
||||
"type": "Contact",
|
||||
"inputs": {
|
||||
"operand": {
|
||||
"uid": "21",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "33",
|
||||
"type": "Convert",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"uid": "22",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "32",
|
||||
"source_instruction_type": "Contact",
|
||||
"source_pin": "out"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "23",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "34",
|
||||
"type": "Mod",
|
||||
"inputs": {
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "33",
|
||||
"source_instruction_type": "Convert",
|
||||
"source_pin": "eno"
|
||||
},
|
||||
"in1": {
|
||||
"uid": "24",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "25",
|
||||
"scope": "TypedConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "26",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "35",
|
||||
"type": "Eq",
|
||||
"inputs": {
|
||||
"pre": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "34",
|
||||
"source_instruction_type": "Mod",
|
||||
"source_pin": "eno"
|
||||
},
|
||||
"in1": {
|
||||
"uid": "27",
|
||||
"scope": "LocalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "28",
|
||||
"scope": "TypedConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"instruction_uid": "36",
|
||||
"type": "Add",
|
||||
"inputs": {
|
||||
"en": {
|
||||
"type": "connection",
|
||||
"source_instruction_uid": "35",
|
||||
"source_instruction_type": "Eq",
|
||||
"source_pin": "out"
|
||||
},
|
||||
"in1": {
|
||||
"uid": "29",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"in2": {
|
||||
"uid": "30",
|
||||
"scope": "LiteralConstant",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out": [
|
||||
{
|
||||
"uid": "31",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "C4",
|
||||
"title": "",
|
||||
"logic": [
|
||||
{
|
||||
"instruction_uid": "23",
|
||||
"type": "Move",
|
||||
"inputs": {
|
||||
"in": {
|
||||
"uid": "21",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
},
|
||||
"en": {
|
||||
"type": "powerrail"
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"out1": [
|
||||
{
|
||||
"uid": "22",
|
||||
"scope": "GlobalVariable",
|
||||
"type": "unknown_access"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
# --- Funciones Procesadoras por Tipo de Instrucción ---
|
||||
# Cada función recibe el diccionario de la instrucción del JSON.
|
||||
# Por ahora, solo imprimen información.
|
||||
|
||||
def process_contact(instruction):
|
||||
"""Procesa una instrucción 'Contact'."""
|
||||
print(f" [Contact] UID: {instruction['instruction_uid']}")
|
||||
operand = instruction['inputs'].get('operand', {})
|
||||
print(f" - Checks: {operand.get('scope', '?')} UID: {operand.get('uid', '?')}") # Adaptar si 'unknown_access' se resuelve
|
||||
in_source = instruction['inputs'].get('in', {})
|
||||
if in_source.get('type') == 'powerrail':
|
||||
print(" - Input: Power Rail")
|
||||
elif in_source.get('type') == 'connection':
|
||||
print(f" - Input: From instruction {in_source.get('source_instruction_uid', '?')} (Pin: {in_source.get('source_pin', '?')})")
|
||||
else:
|
||||
print(f" - Input: {in_source}")
|
||||
|
||||
def process_coil(instruction):
|
||||
"""Procesa una instrucción 'Coil'."""
|
||||
print(f" [Coil] UID: {instruction['instruction_uid']}")
|
||||
operand = instruction['inputs'].get('operand', {})
|
||||
print(f" - Assigns to: {operand.get('scope', '?')} UID: {operand.get('uid', '?')}")
|
||||
in_source = instruction['inputs'].get('in', {})
|
||||
if in_source.get('type') == 'connection':
|
||||
print(f" - Condition from: instruction {in_source.get('source_instruction_uid', '?')} (Pin: {in_source.get('source_pin', '?')})")
|
||||
else:
|
||||
print(f" - Condition: {in_source}")
|
||||
|
||||
def process_add(instruction):
|
||||
"""Procesa una instrucción 'Add'."""
|
||||
print(f" [Add] UID: {instruction['instruction_uid']}")
|
||||
in1 = instruction['inputs'].get('in1', {})
|
||||
in2 = instruction['inputs'].get('in2', {})
|
||||
en = instruction['inputs'].get('en', {})
|
||||
outputs = instruction['outputs'].get('out', [])
|
||||
|
||||
print(f" - Input 1: {in1.get('scope', '?')} UID: {in1.get('uid', '?')}")
|
||||
print(f" - Input 2: {in2.get('scope', '?')} UID: {in2.get('uid', '?')}")
|
||||
if en.get('type') == 'powerrail':
|
||||
print(" - Enabled by: Power Rail (Direct)") # Si Add pudiera conectarse directo
|
||||
elif en.get('type') == 'connection':
|
||||
print(f" - Enabled by: instruction {en.get('source_instruction_uid', '?')} (Pin: {en.get('source_pin', '?')})")
|
||||
elif en: # Si 'en' no está presente o no es conexión/powerrail (poco común en Add)
|
||||
print(f" - Enabled by: {en}")
|
||||
else:
|
||||
print(" - Enabled by: Power Rail (Implícito, sin EN)") # Asumir si no hay pin 'en'
|
||||
|
||||
for output in outputs:
|
||||
print(f" - Output to: {output.get('scope', '?')} UID: {output.get('uid', '?')}")
|
||||
|
||||
def process_move(instruction):
|
||||
"""Procesa una instrucción 'Move'."""
|
||||
print(f" [Move] UID: {instruction['instruction_uid']}")
|
||||
in_val = instruction['inputs'].get('in', {})
|
||||
en = instruction['inputs'].get('en', {})
|
||||
outputs = instruction['outputs'].get('out1', []) # Asumiendo pin 'out1' para Move
|
||||
|
||||
print(f" - Input Value: {in_val.get('scope', '?')} UID: {in_val.get('uid', '?')}")
|
||||
if en.get('type') == 'powerrail':
|
||||
print(" - Enabled by: Power Rail")
|
||||
elif en.get('type') == 'connection':
|
||||
print(f" - Enabled by: instruction {en.get('source_instruction_uid', '?')} (Pin: {en.get('source_pin', '?')})")
|
||||
elif en:
|
||||
print(f" - Enabled by: {en}")
|
||||
else:
|
||||
print(" - Enabled by: Power Rail (Implícito, sin EN)")
|
||||
|
||||
for output in outputs:
|
||||
print(f" - Output to: {output.get('scope', '?')} UID: {output.get('uid', '?')}")
|
||||
|
||||
def process_eq(instruction):
|
||||
"""Procesa una instrucción 'Eq' (Equal)."""
|
||||
print(f" [Compare EQ] UID: {instruction['instruction_uid']}")
|
||||
in1 = instruction['inputs'].get('in1', {})
|
||||
in2 = instruction['inputs'].get('in2', {})
|
||||
pre = instruction['inputs'].get('pre', {}) # Condición previa (usualmente PowerRail o conexión)
|
||||
|
||||
print(f" - Input 1: {in1.get('scope', '?')} UID: {in1.get('uid', '?')}")
|
||||
print(f" - Input 2: {in2.get('scope', '?')} UID: {in2.get('uid', '?')}")
|
||||
if pre.get('type') == 'powerrail':
|
||||
print(" - Pre-condition: Power Rail")
|
||||
elif pre.get('type') == 'connection':
|
||||
print(f" - Pre-condition: instruction {pre.get('source_instruction_uid', '?')} (Pin: {pre.get('source_pin', '?')})")
|
||||
else:
|
||||
print(f" - Pre-condition: {pre}")
|
||||
|
||||
# La salida 'out' de Eq usualmente va a otra instrucción (Contact, Coil, Enable pin)
|
||||
# Lo veremos cuando procesemos la instrucción destino
|
||||
|
||||
def process_mod(instruction):
|
||||
"""Procesa una instrucción 'Mod' (Modulo)."""
|
||||
print(f" [Modulo] UID: {instruction['instruction_uid']}")
|
||||
in1 = instruction['inputs'].get('in1', {})
|
||||
in2 = instruction['inputs'].get('in2', {})
|
||||
en = instruction['inputs'].get('en', {})
|
||||
outputs = instruction['outputs'].get('out', [])
|
||||
eno_outputs = instruction['outputs'].get('eno', []) # Mod también puede tener ENO
|
||||
|
||||
print(f" - Input 1 (Dividend): {in1.get('scope', '?')} UID: {in1.get('uid', '?')}")
|
||||
print(f" - Input 2 (Divisor): {in2.get('scope', '?')} UID: {in2.get('uid', '?')}")
|
||||
if en.get('type') == 'powerrail':
|
||||
print(" - Enabled by: Power Rail")
|
||||
elif en.get('type') == 'connection':
|
||||
print(f" - Enabled by: instruction {en.get('source_instruction_uid', '?')} (Pin: {en.get('source_pin', '?')})")
|
||||
elif en:
|
||||
print(f" - Enabled by: {en}")
|
||||
else:
|
||||
print(" - Enabled by: Power Rail (Implícito, sin EN)")
|
||||
|
||||
for output in outputs:
|
||||
print(f" - Output (Remainder) to: {output.get('scope', '?')} UID: {output.get('uid', '?')}")
|
||||
# ENO normalmente se conecta a pines 'en' o 'pre' de la siguiente instrucción
|
||||
|
||||
def process_convert(instruction):
|
||||
"""Procesa una instrucción 'Convert'."""
|
||||
print(f" [Convert] UID: {instruction['instruction_uid']}")
|
||||
in_val = instruction['inputs'].get('in', {})
|
||||
en = instruction['inputs'].get('en', {})
|
||||
outputs = instruction['outputs'].get('out', [])
|
||||
# Podríamos extraer los tipos de datos de TemplateValue si estuvieran en el JSON
|
||||
# template_vals = instruction.get('template_values', {})
|
||||
|
||||
print(f" - Input Value: {in_val.get('scope', '?')} UID: {in_val.get('uid', '?')}")
|
||||
if en.get('type') == 'powerrail':
|
||||
print(" - Enabled by: Power Rail")
|
||||
elif en.get('type') == 'connection':
|
||||
print(f" - Enabled by: instruction {en.get('source_instruction_uid', '?')} (Pin: {en.get('source_pin', '?')})")
|
||||
elif en:
|
||||
print(f" - Enabled by: {en}")
|
||||
else:
|
||||
print(" - Enabled by: Power Rail (Implícito, sin EN)")
|
||||
|
||||
for output in outputs:
|
||||
print(f" - Output to: {output.get('scope', '?')} UID: {output.get('uid', '?')}")
|
||||
# print(f" (Expected DestType: {template_vals.get('DestType', '?')})")
|
||||
|
||||
|
||||
def process_or(instruction):
|
||||
"""Procesa una instrucción 'O' (OR)."""
|
||||
# Las instrucciones 'O' en LAD suelen representar la unión de ramas paralelas.
|
||||
# Este parser simple solo muestra las entradas directas. Reconstruir la lógica OR completa requeriría más análisis.
|
||||
print(f" [OR Logic] UID: {instruction['instruction_uid']}")
|
||||
in1 = instruction['inputs'].get('in1', {})
|
||||
in2 = instruction['inputs'].get('in2', {})
|
||||
# Podría haber in3, in4... si Cardinality > 2
|
||||
|
||||
if in1.get('type') == 'connection':
|
||||
print(f" - Input 1 from: instruction {in1.get('source_instruction_uid', '?')} (Pin: {in1.get('source_pin', '?')})")
|
||||
else:
|
||||
print(f" - Input 1: {in1}")
|
||||
if in2.get('type') == 'connection':
|
||||
print(f" - Input 2 from: instruction {in2.get('source_instruction_uid', '?')} (Pin: {in2.get('source_pin', '?')})")
|
||||
else:
|
||||
print(f" - Input 2: {in2}")
|
||||
|
||||
# La salida 'out' de O usualmente va a otra instrucción (Contact, Coil, Enable pin)
|
||||
|
||||
def process_pbox(instruction):
|
||||
"""Procesa una instrucción 'PBox'."""
|
||||
# PBox puede ser muchas cosas (Rising Edge, Falling Edge, Set, Reset, etc.)
|
||||
# Necesitaríamos más información o convenciones para saber qué hace exactamente.
|
||||
print(f" [PBox - Special?] UID: {instruction['instruction_uid']}")
|
||||
inputs = instruction.get('inputs', {})
|
||||
outputs = instruction.get('outputs', {})
|
||||
for pin, source in inputs.items():
|
||||
if source.get('type') == 'connection':
|
||||
print(f" - Input Pin '{pin}' from: instruction {source.get('source_instruction_uid', '?')} (Pin: {source.get('source_pin', '?')})")
|
||||
elif source.get('type') == 'powerrail':
|
||||
print(f" - Input Pin '{pin}': Power Rail")
|
||||
else:
|
||||
print(f" - Input Pin '{pin}': {source.get('scope', '?')} UID: {source.get('uid', '?')}")
|
||||
|
||||
# La salida de PBox la veremos en el destino
|
||||
|
||||
def process_unknown(instruction):
|
||||
"""Procesa una instrucción de tipo desconocido."""
|
||||
print(f" [Unknown Type: {instruction.get('type', 'N/A')}] UID: {instruction['instruction_uid']}")
|
||||
print(f" - Inputs: {instruction.get('inputs')}")
|
||||
print(f" - Outputs: {instruction.get('outputs')}")
|
||||
|
||||
# --- Mapeo de Tipos a Funciones ---
|
||||
instruction_handlers = {
|
||||
"Contact": process_contact,
|
||||
"Coil": process_coil,
|
||||
"Add": process_add,
|
||||
"Move": process_move,
|
||||
"Eq": process_eq,
|
||||
"Mod": process_mod,
|
||||
"Convert": process_convert,
|
||||
"O": process_or, # 'O' representa un OR lógico en FlgNet
|
||||
"PBox": process_pbox, # Tipo genérico, tratar como desconocido por ahora
|
||||
# Añade más tipos aquí si aparecen
|
||||
}
|
||||
|
||||
# --- Función Principal de Procesamiento ---
|
||||
|
||||
def process_logic_data(data):
|
||||
"""Itera sobre el JSON cargado y procesa cada instrucción."""
|
||||
print("=" * 40)
|
||||
print(f"Processing Block: {data.get('block_name')} ({data.get('block_number')})")
|
||||
print(f"Language: {data.get('language')}")
|
||||
print("-" * 40)
|
||||
|
||||
# Opcional: Imprimir interfaz
|
||||
print("Interface:")
|
||||
for section, members in data.get('interface', {}).items():
|
||||
if members:
|
||||
print(f" {section}:")
|
||||
for member in members:
|
||||
print(f" - {member['name']} ({member['datatype']})")
|
||||
print("-" * 40)
|
||||
|
||||
# Procesar Redes
|
||||
print("Networks:")
|
||||
for network in data.get('networks', []):
|
||||
print(f"\nNetwork ID: {network.get('id')} - Title: '{network.get('title', '')}'")
|
||||
if 'error' in network:
|
||||
print(f" ERROR en esta red: {network['error']}")
|
||||
continue
|
||||
if not network.get('logic'):
|
||||
print(" (No logic instructions found in JSON for this network)")
|
||||
continue
|
||||
|
||||
for instruction in network.get('logic', []):
|
||||
instruction_type = instruction.get('type')
|
||||
# Obtener el handler adecuado, o el default si no se encuentra
|
||||
handler = instruction_handlers.get(instruction_type, process_unknown)
|
||||
try:
|
||||
handler(instruction)
|
||||
except Exception as e:
|
||||
print(f" ERROR procesando instrucción UID {instruction.get('instruction_uid')} (Tipo: {instruction_type}): {e}")
|
||||
# Considerar imprimir más detalles del error o de la instrucción
|
||||
# import traceback
|
||||
# traceback.print_exc()
|
||||
|
||||
|
||||
# --- Ejecución ---
|
||||
if __name__ == "__main__":
|
||||
json_file = 'BlenderRun_ProdTime_simplified.json' # El archivo generado por el script anterior
|
||||
|
||||
if not os.path.exists(json_file):
|
||||
print(f"Error: Archivo JSON no encontrado en {json_file}")
|
||||
print("Asegúrate de haber ejecutado el script de conversión XML a JSON primero.")
|
||||
else:
|
||||
try:
|
||||
with open(json_file, 'r', encoding='utf-8') as f:
|
||||
logic_data = json.load(f)
|
||||
|
||||
process_logic_data(logic_data)
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: El archivo JSON ({json_file}) no es válido: {e}")
|
||||
except Exception as e:
|
||||
print(f"Ocurrió un error inesperado al cargar o procesar el JSON: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
|
@ -0,0 +1,283 @@
|
|||
import json
|
||||
import os
|
||||
from lxml import etree
|
||||
|
||||
# --- Namespaces ---
|
||||
# Define los namespaces con prefijos explícitos. Quitamos 'default'.
|
||||
ns = {
|
||||
'sw': 'http://www.siemens.com/automation/Openness/SW/Interface/v5',
|
||||
'flg': 'http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4'
|
||||
# No incluimos un prefijo para elementos sin namespace o en el namespace por defecto
|
||||
}
|
||||
|
||||
# --- Helper Functions ---
|
||||
|
||||
def get_multilingual_text(element, default_lang='en-US', fallback_lang='it-IT'):
|
||||
"""Intenta extraer texto de un MultilingualText, priorizando idiomas."""
|
||||
if element is None:
|
||||
return ""
|
||||
try:
|
||||
# Accedemos a los elementos sin prefijo directamente
|
||||
text_item = element.xpath(f".//MultilingualTextItem[AttributeList/Culture='{default_lang}']/AttributeList/Text", namespaces=ns)
|
||||
if text_item:
|
||||
return text_item[0].text.strip() if text_item[0].text else ""
|
||||
|
||||
text_item = element.xpath(f".//MultilingualTextItem[AttributeList/Culture='{fallback_lang}']/AttributeList/Text", namespaces=ns)
|
||||
if text_item:
|
||||
return text_item[0].text.strip() if text_item[0].text else ""
|
||||
|
||||
text_item = element.xpath(".//MultilingualTextItem/AttributeList/Text", namespaces=ns)
|
||||
if text_item:
|
||||
return text_item[0].text.strip() if text_item[0].text else ""
|
||||
|
||||
except Exception as e:
|
||||
print(f"Advertencia: Error extrayendo MultilingualText: {e}")
|
||||
pass
|
||||
return ""
|
||||
|
||||
def get_symbol_name(symbol_element):
|
||||
"""Construye el nombre completo del símbolo a partir de sus componentes."""
|
||||
if symbol_element is None:
|
||||
return None
|
||||
# Accedemos a Component sin prefijo
|
||||
components = symbol_element.xpath("./Component/@Name")
|
||||
return ".".join(f'"{c}"' if ' ' in c else c for c in components)
|
||||
|
||||
def parse_access(access_element):
|
||||
"""Parsea un elemento Access para obtener información de variable o constante."""
|
||||
info = {
|
||||
'uid': access_element.get('UId'),
|
||||
'scope': access_element.get('Scope')
|
||||
}
|
||||
# Accedemos a Symbol y Constant sin prefijo
|
||||
symbol = access_element.xpath("./Symbol", namespaces=ns)
|
||||
constant = access_element.xpath("./Constant", namespaces=ns)
|
||||
|
||||
if symbol:
|
||||
info['type'] = 'variable'
|
||||
info['name'] = get_symbol_name(symbol[0])
|
||||
elif constant:
|
||||
# Los hijos de Constant tampoco tienen prefijo aparente
|
||||
const_type_elem = constant[0].xpath("./ConstantType", namespaces=ns)
|
||||
const_val_elem = constant[0].xpath("./ConstantValue", namespaces=ns)
|
||||
info['datatype'] = const_type_elem[0].text if const_type_elem else 'Unknown'
|
||||
info['value_str'] = const_val_elem[0].text if const_val_elem else None # Guardamos original
|
||||
info['value'] = info['value_str'] # Valor procesado
|
||||
info['type'] = 'constant'
|
||||
|
||||
# Intenta convertir el valor si es numérico o booleano
|
||||
if info['value'] is not None:
|
||||
if info['datatype'].lower() in ['int', 'dint', 'udint', 'sint', 'usint', 'lint', 'ulint', 'word', 'dword', 'lword']:
|
||||
# Manejar DINT#60, etc.
|
||||
val_str = info['value'].split('#')[-1] if '#' in info['value'] else info['value']
|
||||
try:
|
||||
info['value'] = int(val_str)
|
||||
except (ValueError, TypeError):
|
||||
info['value'] = info['value_str'] # Mantener como string si falla
|
||||
elif info['datatype'].lower() == 'bool':
|
||||
info['value'] = info['value'].lower() == 'true' or info['value'] == '1'
|
||||
elif info['datatype'].lower() in ['real', 'lreal']:
|
||||
try:
|
||||
info['value'] = float(info['value'])
|
||||
except (ValueError, TypeError):
|
||||
info['value'] = info['value_str'] # Mantener como string si falla
|
||||
# Añadir más conversiones de tipos si es necesario
|
||||
else:
|
||||
# Podría ser TypedConstant, que también tiene un <Constant> dentro
|
||||
# Si llegamos aquí, es algo inesperado
|
||||
info['type'] = 'unknown_access'
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def parse_part(part_element):
|
||||
"""Parsea un elemento Part (instrucción)."""
|
||||
return {
|
||||
'uid': part_element.get('UId'),
|
||||
'name': part_element.get('Name'),
|
||||
# TemplateValue no parece tener prefijo
|
||||
'template_values': {tv.get('Name'): tv.get('Type')
|
||||
for tv in part_element.xpath("./TemplateValue", namespaces=ns)}
|
||||
}
|
||||
|
||||
# --- Main Parsing Logic ---
|
||||
|
||||
def parse_network(network_element):
|
||||
"""Parsea una red (CompileUnit) y extrae su lógica simplificada."""
|
||||
network_logic = []
|
||||
network_id = network_element.get('ID')
|
||||
# Accedemos a ObjectList y MultilingualText sin prefijo
|
||||
title_element = network_element.xpath("./ObjectList/MultilingualText[@CompositionName='Title']", namespaces=ns)
|
||||
network_title = get_multilingual_text(title_element[0]) if title_element else f"Network {network_id}"
|
||||
|
||||
# Usamos el prefijo 'flg' para FlgNet
|
||||
flgnet = network_element.xpath(".//flg:FlgNet", namespaces=ns)
|
||||
if not flgnet:
|
||||
return {'id': network_id, 'title': network_title, 'logic': [], 'error': 'FlgNet not found'}
|
||||
|
||||
flgnet = flgnet[0]
|
||||
|
||||
# 1. Mapear todos los Access y Parts por su UId
|
||||
# Usamos prefijo flg: para Access y Part dentro de FlgNet
|
||||
access_map = {}
|
||||
for acc in flgnet.xpath(".//flg:Access", namespaces=ns):
|
||||
acc_info = parse_access(acc)
|
||||
access_map[acc_info['uid']] = acc_info
|
||||
|
||||
parts_map = {}
|
||||
for part in flgnet.xpath(".//flg:Part", namespaces=ns):
|
||||
part_info = parse_part(part)
|
||||
parts_map[part_info['uid']] = part_info
|
||||
|
||||
# 2. Construir mapa de conexiones (destino -> fuente)
|
||||
wire_connections = {}
|
||||
# Usamos prefijo flg: para Wire y sus hijos
|
||||
for wire in flgnet.xpath(".//flg:Wire", namespaces=ns):
|
||||
source_uid, source_pin = None, None
|
||||
dest_uid, dest_pin = None, None
|
||||
|
||||
children = wire.getchildren()
|
||||
if not children: continue # Ignorar wires vacíos si los hubiera
|
||||
|
||||
source_elem = children[0]
|
||||
dest_elem = children[1] if len(children) > 1 else None
|
||||
|
||||
# Usamos QName para comparar tags con namespace correctamente
|
||||
flg_ns_uri = ns['flg']
|
||||
if source_elem.tag == etree.QName(flg_ns_uri, 'Powerrail'):
|
||||
source_uid, source_pin = 'POWERRAIL', 'out'
|
||||
elif source_elem.tag == etree.QName(flg_ns_uri, 'IdentCon'):
|
||||
source_uid = source_elem.get('UId')
|
||||
source_pin = 'value' # Pin implícito para Access
|
||||
elif source_elem.tag == etree.QName(flg_ns_uri, 'NameCon'):
|
||||
source_uid = source_elem.get('UId')
|
||||
source_pin = source_elem.get('Name')
|
||||
|
||||
if dest_elem is not None:
|
||||
if dest_elem.tag == etree.QName(flg_ns_uri, 'IdentCon'):
|
||||
dest_uid = dest_elem.get('UId')
|
||||
dest_pin = 'value'
|
||||
elif dest_elem.tag == etree.QName(flg_ns_uri, 'NameCon'):
|
||||
dest_uid = dest_elem.get('UId')
|
||||
dest_pin = dest_elem.get('Name')
|
||||
|
||||
if dest_uid and dest_pin and (source_uid is not None or source_pin == 'out'):
|
||||
wire_connections[(dest_uid, dest_pin)] = (source_uid, source_pin)
|
||||
|
||||
|
||||
# 3. Iterar sobre las instrucciones (Parts) y encontrar sus conexiones
|
||||
for part_uid, part_info in parts_map.items():
|
||||
instruction_repr = {
|
||||
'instruction_uid': part_uid,
|
||||
'type': part_info['name'],
|
||||
'inputs': {},
|
||||
'outputs': {}
|
||||
}
|
||||
|
||||
connected_inputs = {k[1]: v for k, v in wire_connections.items() if k[0] == part_uid}
|
||||
|
||||
for dest_pin, (source_uid, source_pin) in connected_inputs.items():
|
||||
if source_uid == 'POWERRAIL':
|
||||
instruction_repr['inputs'][dest_pin] = {'type': 'powerrail'}
|
||||
elif source_uid in access_map:
|
||||
instruction_repr['inputs'][dest_pin] = access_map[source_uid]
|
||||
elif source_uid in parts_map:
|
||||
instruction_repr['inputs'][dest_pin] = {
|
||||
'type': 'connection',
|
||||
'source_instruction_uid': source_uid,
|
||||
'source_instruction_type': parts_map[source_uid]['name'],
|
||||
'source_pin': source_pin
|
||||
}
|
||||
else:
|
||||
# Podría ser una conexión rota o no encontrada
|
||||
instruction_repr['inputs'][dest_pin] = {'type': 'unknown_source', 'uid': source_uid}
|
||||
|
||||
# Encontrar salidas conectadas a Access
|
||||
for (conn_dest_uid, conn_dest_pin), (conn_source_uid, conn_source_pin) in wire_connections.items():
|
||||
if conn_source_uid == part_uid and conn_dest_uid in access_map:
|
||||
if conn_source_pin not in instruction_repr['outputs']:
|
||||
instruction_repr['outputs'][conn_source_pin] = []
|
||||
# Añadimos la info del Access que es el destino
|
||||
instruction_repr['outputs'][conn_source_pin].append(access_map[conn_dest_uid])
|
||||
|
||||
network_logic.append(instruction_repr)
|
||||
|
||||
return {'id': network_id, 'title': network_title, 'logic': network_logic}
|
||||
|
||||
|
||||
def convert_xml_to_json(xml_filepath, json_filepath):
|
||||
"""Función principal para convertir el XML a JSON."""
|
||||
if not os.path.exists(xml_filepath):
|
||||
print(f"Error: Archivo XML no encontrado en {xml_filepath}")
|
||||
return
|
||||
|
||||
try:
|
||||
tree = etree.parse(xml_filepath)
|
||||
root = tree.getroot()
|
||||
|
||||
# Buscar SW.Blocks.FC usando local-name() para robustez inicial
|
||||
# O asumir que no tiene namespace si está bajo Document/Engineering
|
||||
fc_block = root.xpath("//*[local-name()='SW.Blocks.FC']")
|
||||
if not fc_block:
|
||||
print("Error: No se encontró el elemento <SW.Blocks.FC>")
|
||||
return
|
||||
fc_block = fc_block[0]
|
||||
|
||||
# --- Extraer Info General (sin prefijos) ---
|
||||
block_name = fc_block.xpath("./AttributeList/Name/text()")
|
||||
block_number = fc_block.xpath("./AttributeList/Number/text()")
|
||||
block_lang = fc_block.xpath("./AttributeList/ProgrammingLanguage/text()")
|
||||
|
||||
result = {
|
||||
"block_name": block_name[0].strip() if block_name else "Unknown",
|
||||
"block_number": int(block_number[0]) if block_number and block_number[0].isdigit() else None,
|
||||
"language": block_lang[0].strip() if block_lang else "Unknown",
|
||||
"interface": {},
|
||||
"networks": []
|
||||
}
|
||||
|
||||
# --- Extraer Interfaz (con prefijo sw:) ---
|
||||
interface_sections = fc_block.xpath(".//sw:Interface/sw:Sections/sw:Section", namespaces=ns)
|
||||
for section in interface_sections:
|
||||
section_name = section.get('Name')
|
||||
members = []
|
||||
for member in section.xpath("./sw:Member", namespaces=ns):
|
||||
members.append({
|
||||
"name": member.get('Name'),
|
||||
"datatype": member.get('Datatype')
|
||||
})
|
||||
result["interface"][section_name] = members
|
||||
|
||||
# --- Extraer Lógica de Redes (CompileUnit sin prefijo, contenido con flg:) ---
|
||||
# Buscamos SW.Blocks.CompileUnit sin prefijo, asumiendo que es hijo directo de ObjectList
|
||||
networks = fc_block.xpath("./ObjectList/SW.Blocks.CompileUnit", namespaces=ns)
|
||||
network_count = 0
|
||||
for network_elem in networks:
|
||||
network_count += 1
|
||||
parsed_network = parse_network(network_elem)
|
||||
result["networks"].append(parsed_network)
|
||||
|
||||
if network_count == 0:
|
||||
print("Advertencia: No se encontraron redes (SW.Blocks.CompileUnit). Verifica la estructura del XML.")
|
||||
|
||||
|
||||
# --- Escribir resultado a JSON ---
|
||||
with open(json_filepath, 'w', encoding='utf-8') as f:
|
||||
json.dump(result, f, indent=4, ensure_ascii=False)
|
||||
|
||||
print(f"Conversión completada. Archivo JSON guardado en: {json_filepath}")
|
||||
|
||||
except etree.XMLSyntaxError as e:
|
||||
print(f"Error de sintaxis XML: {e}")
|
||||
except Exception as e:
|
||||
print(f"Ocurrió un error inesperado durante el procesamiento: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
# --- Ejecución ---
|
||||
if __name__ == "__main__":
|
||||
xml_file = 'BlenderRun_ProdTime.xml'
|
||||
json_file = 'BlenderRun_ProdTime_simplified.json'
|
||||
|
||||
convert_xml_to_json(xml_file, json_file)
|
Loading…
Reference in New Issue