├── .gitignore ├── tests ├── resources │ ├── FileModelInstance.metadata.json │ ├── FileSimulation.zip │ ├── FileModelInstance.zip │ ├── FileSimulation.metadata.json │ ├── MSLModelInstance.metadata.json │ ├── MSLSimulation.metadata.json │ └── MSLFMU.metadata.json ├── __init__.py ├── test_version.py ├── conftest.py ├── test_fmu_msl.py ├── test_simulate_msl.py ├── test_simulate_with_file.py ├── test_model_instance_msl.py └── test_model_instance_with_file.py ├── .jenkins └── python3 │ └── Dockerfile ├── Jenkinsfile ├── Dockerfile ├── README.md ├── Service ├── __init__.py ├── util.py ├── config.py ├── metadata.schema.json ├── omc.py ├── app.py └── api.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | __pycache__ 3 | myenv 4 | LocalTests -------------------------------------------------------------------------------- /tests/resources/FileModelInstance.metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileNames":["BouncingBall.mo"], 3 | "class":"BouncingBall" 4 | } -------------------------------------------------------------------------------- /tests/resources/FileSimulation.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenModelica/OMWebService/master/tests/resources/FileSimulation.zip -------------------------------------------------------------------------------- /tests/resources/FileModelInstance.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenModelica/OMWebService/master/tests/resources/FileModelInstance.zip -------------------------------------------------------------------------------- /tests/resources/FileSimulation.metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileNames":["BouncingBall.mo"], 3 | "class":"BouncingBall", 4 | "startTime":0.0, 5 | "stopTime":3.0 6 | } -------------------------------------------------------------------------------- /tests/resources/MSLModelInstance.metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileNames": [], 3 | "class":"Modelica.Electrical.Analog.Examples.ChuaCircuit", 4 | "libs": [ 5 | { 6 | "name":"Modelica", 7 | "version":"4.0.0" 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /tests/resources/MSLSimulation.metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileNames": [], 3 | "class":"Modelica.Electrical.Analog.Examples.ChuaCircuit", 4 | "startTime":0.0, 5 | "stopTime":1.0, 6 | "libs": [ 7 | { 8 | "name":"Modelica", 9 | "version":"4.0.0" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /tests/resources/MSLFMU.metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileNames": [], 3 | "class":"Modelica.Electrical.Analog.Examples.ChuaCircuit", 4 | "outputFormat":"fmu", 5 | "platforms":["static"], 6 | "libs": [ 7 | { 8 | "name":"Modelica", 9 | "version":"4.0.0" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /.jenkins/python3/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.openmodelica.org/build-deps 2 | 3 | RUN apt-get update \ 4 | && apt-get install -qy gnupg wget ca-certificates apt-transport-https sudo \ 5 | && echo "deb https://build.openmodelica.org/apt `lsb_release -sc` release" > /etc/apt/sources.list.d/openmodelica.list \ 6 | && wget https://build.openmodelica.org/apt/openmodelica.asc -O- | apt-key add - \ 7 | && apt-get update \ 8 | && apt-get install -qy --no-install-recommends omc \ 9 | && rm -rf /var/lib/apt/lists/* 10 | 11 | RUN pip3 install --no-cache pytest dataclasses contextvars -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent none 3 | stages { 4 | stage('test') { 5 | parallel { 6 | stage('python3') { 7 | agent { 8 | dockerfile { 9 | label 'linux' 10 | dir '.jenkins/python3' 11 | additionalBuildArgs '--pull' 12 | } 13 | } 14 | steps { 15 | sh 'hostname' 16 | sh 'HOME="$PWD" python3 setup.py install --user' 17 | sh ''' 18 | export HOME="$PWD" 19 | pytest -v --junit-xml=py3.xml tests 20 | ''' 21 | junit 'py3.xml' 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.openmodelica.org/build-deps 2 | 3 | COPY . /app 4 | 5 | WORKDIR /app 6 | 7 | RUN apt-get update \ 8 | && apt-get install -qy gnupg wget ca-certificates apt-transport-https sudo \ 9 | && echo "deb https://build.openmodelica.org/apt `lsb_release -sc` release" > /etc/apt/sources.list.d/openmodelica.list \ 10 | && wget https://build.openmodelica.org/apt/openmodelica.asc -O- | apt-key add - \ 11 | && apt-get update \ 12 | && apt-get install -qy --no-install-recommends omc \ 13 | && rm -rf /var/lib/apt/lists/* \ 14 | && python3 -m pip install -U . \ 15 | && chmod a+rwx -R /app 16 | 17 | ENV FLASK_ENV=development \ 18 | DOCKER_APP=yes 19 | 20 | ENTRYPOINT [ "python3" ] 21 | 22 | CMD [ "Service/app.py" ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OMWebService 2 | OpenModelica web service, queries via a REST API 3 | 4 | ## Dependencies 5 | 6 | - [Python >= 3.8.5](https://www.python.org/) 7 | - [Python setuptools](https://pypi.org/project/setuptools/) 8 | - [OpenModelica >= 1.19.0](https://openmodelica.org) 9 | 10 | ## Build & Run instructions 11 | 12 | ### Option 1 13 | 14 | Set environment variable `FLASK_ENV=development` for development environment. 15 | Install the dependencies and then run the following commands, 16 | 17 | ```bash 18 | $ cd /path/to/OpenModelica/OMWebService 19 | $ python -m pip install -U . 20 | $ python Service/app.py 21 | ``` 22 | 23 | ### Option 2 24 | 25 | Use the Dockerfile provided to run with docker, 26 | 27 | ```bash 28 | $ cd /path/to/OpenModelica/OMWebService 29 | $ docker build . -t openmodelica/omwebservice 30 | $ docker run --user nobody -p 8080:8080 openmodelica/omwebservice 31 | ``` 32 | 33 | In your browser, open the URL http://localhost:8080/api/ -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | OMWebService Testing 33 | """ -------------------------------------------------------------------------------- /Service/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | OpenModelica web service 33 | """ -------------------------------------------------------------------------------- /tests/test_version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | Tests the version endpoint. 33 | """ 34 | 35 | def test_version(application): 36 | response = application.test_client().get("/api/version") 37 | assert response.status_code == 200 -------------------------------------------------------------------------------- /Service/util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | OpenModelica kernel module. Communicates with OM compiler. 33 | """ 34 | 35 | import logging 36 | 37 | log = logging.getLogger(__name__) 38 | 39 | def pythonBoolToModelicaBool(value): 40 | """Converts the python bool to Modelica.""" 41 | if value: 42 | return "true" 43 | else: 44 | return "false" -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | import pytest 32 | from Service import app 33 | import sys 34 | 35 | # add Service path so that pytest can find config.py 36 | sys.path.insert(0,"./Service") 37 | 38 | @pytest.fixture 39 | def application(): 40 | app_ = app.createApp() 41 | # always set TESTING to true for tests 42 | app_.config.update({ 43 | "TESTING": True 44 | }) 45 | yield app_ 46 | -------------------------------------------------------------------------------- /Service/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | Module for application configurations. 33 | """ 34 | 35 | import tempfile 36 | 37 | class Config: 38 | """Base config.""" 39 | TMPDIR = tempfile.gettempdir() + "/OMWebService" 40 | 41 | class ProductionConfig(Config): 42 | """Production config.""" 43 | SERVER_NAME = "omwebservice.openmodelica.org" 44 | DEBUG = False 45 | TESTING = False 46 | 47 | class DevelopmentConfig(Config): 48 | """Development config.""" 49 | SERVER_NAME = "localhost:8080" 50 | DEBUG = True 51 | TESTING = True -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | OMWebService setup script 33 | """ 34 | 35 | from setuptools import setup 36 | 37 | setup(name="OMWebService", 38 | version="1.0.0", 39 | description="OpenModelica web service", 40 | author="Adeel Asghar", 41 | author_email="adeel.asghar@liu.se", 42 | maintainer="Adeel Asghar", 43 | maintainer_email="adeel.asghar@liu.se", 44 | license="BSD, OSMC-PL 1.2, GPL (user's choice)", 45 | url="http://openmodelica.org/", 46 | packages=["Service"], 47 | install_requires=[ 48 | "jsonschema==2.6.0", 49 | "flask==2.0.3", 50 | "flask-restx==0.5.1", 51 | "OMPython" 52 | ] 53 | ) -------------------------------------------------------------------------------- /tests/test_fmu_msl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | Tests the simulate endpoint and generates Modelica.Electrical.Analog.Examples.ChuaCircuit model FMU. 33 | """ 34 | 35 | from pathlib import Path 36 | import tempfile 37 | import shutil 38 | 39 | # get the resources folder in the tests folder 40 | resources = Path(__file__).parent / "resources" 41 | 42 | def test_simulate(application): 43 | application.config.update({ 44 | "TMPDIR": tempfile.mkdtemp(prefix='test_fmu_msl') 45 | }) 46 | 47 | response = application.test_client().post("/api/simulate", data = { 48 | "MetadataJson": (resources / "MSLFMU.metadata.json").open("rb") 49 | }) 50 | assert response.status_code == 200 51 | data = response.json 52 | file = data.get("file", "") 53 | if not file: 54 | print(data) 55 | assert False 56 | 57 | # cleanup 58 | shutil.rmtree(application.config['TMPDIR'], ignore_errors=True) -------------------------------------------------------------------------------- /tests/test_simulate_msl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | Tests the simulate endpoint with Modelica.Electrical.Analog.Examples.ChuaCircuit model. 33 | """ 34 | 35 | from pathlib import Path 36 | import tempfile 37 | import shutil 38 | 39 | # get the resources folder in the tests folder 40 | resources = Path(__file__).parent / "resources" 41 | 42 | def test_simulate(application): 43 | application.config.update({ 44 | "TMPDIR": tempfile.mkdtemp(prefix='test_simulate_msl') 45 | }) 46 | 47 | response = application.test_client().post("/api/simulate", data = { 48 | "MetadataJson": (resources / "MSLSimulation.metadata.json").open("rb") 49 | }) 50 | assert response.status_code == 200 51 | data = response.json 52 | file = data.get("file", "") 53 | if not file: 54 | print(data) 55 | assert False 56 | 57 | # cleanup 58 | shutil.rmtree(application.config['TMPDIR'], ignore_errors=True) -------------------------------------------------------------------------------- /tests/test_simulate_with_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | Tests the simulate endpoint with BouncingBall file. 33 | """ 34 | 35 | from pathlib import Path 36 | import tempfile 37 | import shutil 38 | 39 | # get the resources folder in the tests folder 40 | resources = Path(__file__).parent / "resources" 41 | 42 | def test_simulate(application): 43 | application.config.update({ 44 | "TMPDIR": tempfile.mkdtemp(prefix='test_simulate_with_file') 45 | }) 46 | 47 | response = application.test_client().post("/api/simulate", data = { 48 | "MetadataJson": (resources / "FileSimulation.metadata.json").open("rb"), 49 | "ModelZip": (resources / "FileSimulation.zip").open("rb") 50 | }) 51 | assert response.status_code == 200 52 | data = response.json 53 | file = data.get("file", "") 54 | if not file: 55 | print(data) 56 | assert False 57 | 58 | # cleanup 59 | shutil.rmtree(application.config['TMPDIR'], ignore_errors=True) -------------------------------------------------------------------------------- /tests/test_model_instance_msl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | Tests the model instance endpoint with Modelica.Electrical.Analog.Examples.ChuaCircuit model. 33 | """ 34 | 35 | from pathlib import Path 36 | import tempfile 37 | import shutil 38 | import pytest 39 | 40 | # get the resources folder in the tests folder 41 | resources = Path(__file__).parent / "resources" 42 | 43 | @pytest.mark.skip(reason="getModeInstance API is missing in the docker image.") 44 | def test_simulate(application): 45 | application.config.update({ 46 | "TMPDIR": tempfile.mkdtemp(prefix='test_model_instance_msl') 47 | }) 48 | 49 | response = application.test_client().post("/api/modelInstance", data = { 50 | "MetadataJson": (resources / "MSLModelInstance.metadata.json").open("rb") 51 | }) 52 | assert response.status_code == 200 53 | data = response.json 54 | file = data.get("file", "") 55 | if not file: 56 | print(data) 57 | assert False 58 | 59 | # cleanup 60 | shutil.rmtree(application.config['TMPDIR'], ignore_errors=True) -------------------------------------------------------------------------------- /Service/metadata.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "description": "A representation of simulation information", 4 | "type": "object", 5 | "properties": { 6 | "fileNames": { 7 | "type": "array", 8 | "items": [ 9 | { 10 | "type": "string", 11 | "description": "The file to load. The file name is relative to zip root." 12 | } 13 | ] 14 | }, 15 | "class": { 16 | "type": "string", 17 | "description": "Class to simulate" 18 | }, 19 | "startTime": { 20 | "type": "number" 21 | }, 22 | "stopTime": { 23 | "type": "number" 24 | }, 25 | "numberOfIntervals": { 26 | "type": "number" 27 | }, 28 | "tolerance": { 29 | "type": "number" 30 | }, 31 | "fileNamePrefix": { 32 | "type": "string" 33 | }, 34 | "options": { 35 | "type": "string" 36 | }, 37 | "outputFormat": { 38 | "type": "string", 39 | "default": "mat", 40 | "description": "Possible values are mat, csv and fmu." 41 | }, 42 | "variableFilter": { 43 | "type": "string" 44 | }, 45 | "cflags": { 46 | "type": "string" 47 | }, 48 | "simflags": { 49 | "type": "string" 50 | }, 51 | "platforms": { 52 | "type": "array", 53 | "items": [ 54 | { 55 | "type": "string" 56 | } 57 | ] 58 | }, 59 | "fmuVersion": { 60 | "type": "string" 61 | }, 62 | "fmuType": { 63 | "type": "string" 64 | }, 65 | "includeResources": { 66 | "type": "boolean" 67 | }, 68 | "libs": { 69 | "type": "array", 70 | "items": [ 71 | { 72 | "type": "object", 73 | "properties": { 74 | "name": { 75 | "type": "string", 76 | "description": "Name of the library to install and load." 77 | }, 78 | "version": { 79 | "type": "string", 80 | "description": "Version of the library to install and load." 81 | } 82 | }, 83 | "required": [ 84 | "name", 85 | "version" 86 | ] 87 | } 88 | ] 89 | } 90 | }, 91 | "required": [ 92 | "class" 93 | ] 94 | } -------------------------------------------------------------------------------- /tests/test_model_instance_with_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | Tests the model instance endpoint with BouncingBall file. 33 | """ 34 | 35 | from pathlib import Path 36 | import tempfile 37 | import shutil 38 | import pytest 39 | 40 | # get the resources folder in the tests folder 41 | resources = Path(__file__).parent / "resources" 42 | 43 | @pytest.mark.skip(reason="getModeInstance API is missing in the docker image.") 44 | def test_simulate(application): 45 | application.config.update({ 46 | "TMPDIR": tempfile.mkdtemp(prefix='test_model_instance_with_file') 47 | }) 48 | 49 | response = application.test_client().post("/api/modelInstance", data = { 50 | "MetadataJson": (resources / "FileModelInstance.metadata.json").open("rb"), 51 | "ModelZip": (resources / "FileModelInstance.zip").open("rb") 52 | }) 53 | assert response.status_code == 200 54 | data = response.json 55 | file = data.get("file", "") 56 | if not file: 57 | print(data) 58 | assert False 59 | 60 | # cleanup 61 | shutil.rmtree(application.config['TMPDIR'], ignore_errors=True) -------------------------------------------------------------------------------- /Service/omc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | OpenModelica kernel module. Communicates with OM compiler. 33 | """ 34 | 35 | import logging 36 | from OMPython import OMCSessionZMQ 37 | 38 | log = logging.getLogger(__name__) 39 | 40 | class OMC: 41 | """OpenModelica Compiler interface""" 42 | 43 | def __init__(self): 44 | self.omcSession = OMCSessionZMQ() 45 | self.errorString = "" 46 | 47 | def __del__(self): 48 | pass 49 | 50 | def sendCommand(self, expression, parsed=True): 51 | """Sends the command to OMC.""" 52 | log.debug("OMC sendCommand: {0} - parsed: {1}".format(expression, parsed)) 53 | 54 | try: 55 | res = self.omcSession.sendExpression(expression, parsed) 56 | log.debug("OMC result: {0}".format(res)) 57 | if expression != "quit()": 58 | errorString = self.omcSession.sendExpression("getErrorString()") 59 | log.debug("OMC getErrorString(): {0}".format(errorString)) 60 | except Exception as ex: 61 | log.error("OMC failed: {0}, parsed={1} with exception: {2}".format(expression, parsed, str(ex))) 62 | raise 63 | 64 | return res -------------------------------------------------------------------------------- /Service/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | Web service application 33 | """ 34 | 35 | import os 36 | import logging 37 | from flask import Flask, Blueprint 38 | from Service import api 39 | 40 | log = logging.getLogger(__name__) 41 | 42 | def createApp(): 43 | """Create the Flask app.""" 44 | app = Flask(__name__) 45 | blueprint = Blueprint("api", __name__, url_prefix="/api") 46 | api.api.init_app(blueprint) 47 | app.register_blueprint(blueprint) 48 | 49 | if os.environ.get("FLASK_ENV") == "development": 50 | app.config.from_object('config.DevelopmentConfig') 51 | logging.basicConfig(level=logging.DEBUG) 52 | else: 53 | app.config.from_object('config.ProductionConfig') 54 | logging.basicConfig(level=logging.WARNING) 55 | 56 | if not os.path.exists(app.config['TMPDIR']): 57 | os.makedirs(app.config['TMPDIR']) 58 | 59 | return app 60 | 61 | def main(): 62 | """web app main entry point.""" 63 | app = createApp() 64 | dockerApp = os.environ.get('DOCKER_APP', False) 65 | if dockerApp: 66 | app.run(host="0.0.0.0", port="8080") # This tells your operating system to listen on all public IPs. 67 | else: 68 | app.run() 69 | 70 | if __name__ == "__main__": 71 | main() -------------------------------------------------------------------------------- /Service/api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of OpenModelica. 5 | # Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), 6 | # c/o Linköpings universitet, Department of Computer and Information Science, 7 | # SE-58183 Linköping, Sweden. 8 | 9 | # All rights reserved. 10 | 11 | # THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR 12 | # THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. 13 | # ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES 14 | # RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, 15 | # ACCORDING TO RECIPIENTS CHOICE. 16 | 17 | # The OpenModelica software and the Open Source Modelica 18 | # Consortium (OSMC) Public License (OSMC-PL) are obtained 19 | # from OSMC, either from the above address, 20 | # from the URLs: http://www.ida.liu.se/projects/OpenModelica or 21 | # http://www.openmodelica.org, and in the OpenModelica distribution. 22 | # GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. 23 | 24 | # This program is distributed WITHOUT ANY WARRANTY; without 25 | # even the implied warranty of MERCHANTABILITY or FITNESS 26 | # FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH 27 | # IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. 28 | 29 | # See the full OSMC Public License conditions for more details. 30 | 31 | """ 32 | Api module using the Flask framework. 33 | """ 34 | 35 | import os 36 | import logging 37 | import flask 38 | from flask import current_app, jsonify 39 | from flask_restx import Resource, Api, reqparse 40 | from Service.omc import OMC 41 | from Service import util 42 | from werkzeug.datastructures import FileStorage 43 | from werkzeug.utils import secure_filename 44 | import tempfile 45 | import zipfile 46 | import json 47 | 48 | log = logging.getLogger(__name__) 49 | 50 | api = Api(version="1.0", title="OMWebService API", description="OMWebService API Documentation") 51 | 52 | allowedExtensions = set(["zip", "json"]) 53 | 54 | def allowedFile(fileName): 55 | return '.' in fileName and fileName.rsplit('.', 1)[1].lower() in allowedExtensions 56 | 57 | def setResultJsonAndQuitOMC(omc, originalDir, messages, file): 58 | resultJson = dict() 59 | if originalDir: 60 | omc.sendCommand("cd(\"{0}\")".format(originalDir.replace('\\','/'))) 61 | omc.sendCommand("quit()") 62 | resultJson["messages"] = messages 63 | resultJson["file"] = file 64 | return jsonify(resultJson) 65 | 66 | def readMetaDataAndZipFile(omc, metaDataJsonFileArg, modelZipFileArg): 67 | uploadDirectory = "" 68 | metaDataJson = {} 69 | # save and read the json file 70 | if metaDataJsonFileArg and allowedFile(metaDataJsonFileArg.filename): 71 | metaDataJsonFileName = secure_filename(metaDataJsonFileArg.filename) 72 | uploadDirectory = tempfile.mkdtemp(dir=current_app.config['TMPDIR']) 73 | # change working directory 74 | omc.sendCommand("cd(\"{0}\")".format(uploadDirectory.replace('\\','/'))) 75 | metaDataJsonFilePath = os.path.join(uploadDirectory, metaDataJsonFileName) 76 | metaDataJsonFileArg.save(metaDataJsonFilePath) 77 | try: 78 | with open(metaDataJsonFilePath) as metaDataJsonFile: 79 | metaDataJson = json.load(metaDataJsonFile) 80 | # json file not found exception 81 | except FileNotFoundError: 82 | return False, uploadDirectory, "The metadata.json file is missing. {0}".format(metaDataJsonFilePath), metaDataJson 83 | else: 84 | return False, uploadDirectory, "The metadata.json file is missing. {0}".format(metaDataJsonFilePath), metaDataJson 85 | 86 | # save and read the zip file 87 | if modelZipFileArg and allowedFile(modelZipFileArg.filename): 88 | modelZipFileName = secure_filename(modelZipFileArg.filename) 89 | modelZipFilePath = os.path.join(uploadDirectory, modelZipFileName) 90 | modelZipFileArg.save(modelZipFilePath) 91 | # unzip the file 92 | with zipfile.ZipFile(modelZipFilePath, 'r') as zip_ref: 93 | zip_ref.extractall(uploadDirectory) 94 | 95 | # load the model in OMC 96 | fileNames = metaDataJson.get("fileNames", []) 97 | for fileName in fileNames: 98 | if not omc.sendCommand("loadFile(\"{0}\")".format(fileName)): 99 | return False, uploadDirectory, "Failed to load the model file {0}. {1}".format(fileName, omc.errorString), metaDataJson 100 | 101 | # load the libs 102 | libs = metaDataJson.get("libs", []) 103 | for lib in libs: 104 | name = lib.get("name", "") 105 | version = lib.get("version", "") 106 | if not omc.sendCommand("installPackage({0}, \"{1}\")".format(name, version)): 107 | return False, uploadDirectory, "Failed to install package {0}.".format(name), metaDataJson 108 | if not omc.sendCommand("loadModel({0}, {{\"{1}\"}})".format(name, version)): 109 | return False, uploadDirectory, "Failed to load package {0}.".format(name), metaDataJson 110 | 111 | return True, uploadDirectory, "", metaDataJson 112 | 113 | @api.errorhandler 114 | def defaultErrorHandler(error): 115 | """Default error handler""" 116 | return {"message": str(error)}, getattr(error, "code", 500) 117 | 118 | @api.route("/version") 119 | class Version(Resource): 120 | """End point to get OpenModelica version""" 121 | 122 | def get(self): 123 | """Gets the OpenModelica version""" 124 | omc = OMC() 125 | version = omc.sendCommand("getVersion()") 126 | omc.sendCommand("quit()") 127 | return jsonify({"version": version}) 128 | 129 | @api.route("/simulate") 130 | class Simulate(Resource): 131 | """End point to simulate a model""" 132 | 133 | parser = reqparse.RequestParser() 134 | parser.add_argument("MetadataJson", location = "files", type = FileStorage, required = True, help = "JSON file with simulation data information") 135 | parser.add_argument("ModelZip", location = "files", type = FileStorage, help = "Zip file containing the extra Modelica files needed for simulation") 136 | 137 | @api.expect(parser) 138 | def post(self): 139 | """Simulate the model.""" 140 | args = self.parser.parse_args() 141 | metaDataJsonFileArg = args["MetadataJson"] 142 | modelZipFileArg = args["ModelZip"] 143 | 144 | omc = OMC() 145 | originalDir = omc.sendCommand("cd()") 146 | metaDataJson = {} 147 | file = "" 148 | 149 | status, uploadDirectory, messages, metaDataJson = readMetaDataAndZipFile(omc, metaDataJsonFileArg, modelZipFileArg) 150 | if not status: 151 | return setResultJsonAndQuitOMC(omc, originalDir, messages, file) 152 | 153 | # simulate the model 154 | className = metaDataJson.get("class", "") 155 | if className: 156 | simulationArguments = [] 157 | if "fileNamePrefix" in metaDataJson: 158 | simulationArguments.append("fileNamePrefix=\"{0}\"".format(metaDataJson["fileNamePrefix"])) 159 | 160 | outputFormat = metaDataJson.get("outputFormat", "mat") 161 | if outputFormat.casefold() == "fmu": 162 | if "fmuVersion" in metaDataJson: 163 | simulationArguments.append("version={0}".format(metaDataJson["fmuVersion"])) 164 | if "fmuType" in metaDataJson: 165 | simulationArguments.append("fmuType={0}".format(metaDataJson["fmuType"])) 166 | if "platforms" in metaDataJson: 167 | platforms = [] 168 | platformsJson = metaDataJson.get("platforms", []) 169 | for platform in platformsJson: 170 | platforms.append("\"{0}\"".format(platform)) 171 | simulationArguments.append("platforms={{{0}}}".format(", ".join(platforms))) 172 | if "includeResources" in metaDataJson: 173 | simulationArguments.append("includeResources={0}".format(metaDataJson["includeResources"])) 174 | else: 175 | if "startTime" in metaDataJson: 176 | simulationArguments.append("startTime={0}".format(metaDataJson["startTime"])) 177 | if "stopTime" in metaDataJson: 178 | simulationArguments.append("stopTime={0}".format(metaDataJson["stopTime"])) 179 | if "numberOfIntervals" in metaDataJson: 180 | simulationArguments.append("numberOfIntervals={0}".format(metaDataJson["numberOfIntervals"])) 181 | if "tolerance" in metaDataJson: 182 | simulationArguments.append("tolerance={0}".format(metaDataJson["tolerance"])) 183 | if "method" in metaDataJson: 184 | simulationArguments.append("method=\"{0}\"".format(metaDataJson["method"])) 185 | if "options" in metaDataJson: 186 | simulationArguments.append("options=\"{0}\"".format(metaDataJson["options"])) 187 | if outputFormat.casefold() == "mat" or outputFormat.casefold() == "csv": 188 | simulationArguments.append("outputFormat=\"{0}\"".format(outputFormat)) 189 | if "variableFilter" in metaDataJson: 190 | simulationArguments.append("variableFilter=\"{0}\"".format(metaDataJson["variableFilter"])) 191 | if "cflags" in metaDataJson: 192 | simulationArguments.append("cflags=\"{0}\"".format(metaDataJson["cflags"])) 193 | if "simflags" in metaDataJson: 194 | simulationArguments.append("simflags=\"{0}\"".format(metaDataJson["simflags"])) 195 | 196 | simulationArgumentsStr = ", ".join(simulationArguments) 197 | if simulationArgumentsStr: 198 | simulationArgumentsStr = ", " + simulationArgumentsStr 199 | 200 | if outputFormat.casefold() == "fmu": 201 | simulationResult = omc.sendCommand("buildModelFMU({0}{1})".format(className, simulationArgumentsStr)) 202 | if simulationResult: 203 | messages = "FMU is generated." 204 | file = flask.url_for('api.download', FileName="{0}/{1}".format(os.path.basename(uploadDirectory), os.path.basename(simulationResult)), _external=True) 205 | else: 206 | messages = "Failed to generate the FMU. {0}".format(omc.errorString) 207 | file = "" 208 | else: 209 | simulationResult = omc.sendCommand("simulate({0}{1})".format(className, simulationArgumentsStr)) 210 | messages = simulationResult["messages"] 211 | if simulationResult["resultFile"]: 212 | file = flask.url_for('api.download', FileName="{0}/{1}".format(os.path.basename(uploadDirectory), os.path.basename(simulationResult["resultFile"])), _external=True) 213 | else: 214 | file = "" 215 | else: 216 | messages = "Class is missing." 217 | file = "" 218 | 219 | return setResultJsonAndQuitOMC(omc, originalDir, messages, file) 220 | 221 | @api.route("/download/", doc=False) 222 | class Download(Resource): 223 | """End point to download the svg file.""" 224 | parser = reqparse.RequestParser() 225 | parser.add_argument("FileName", location = "args", required = True, help = "Path to download SVG file") 226 | 227 | @api.expect(parser) 228 | @api.produces(["application/octet-stream"]) 229 | def get(self): 230 | """Downloads the mat simulation result file.""" 231 | args = self.parser.parse_args() 232 | fileName = args["FileName"] 233 | return flask.send_file(current_app.config['TMPDIR'] + "/" + fileName) 234 | 235 | @api.route("/modelInstance") 236 | class ModelInstance(Resource): 237 | """End point to get the model instance as json""" 238 | 239 | parser = reqparse.RequestParser() 240 | parser.add_argument("MetadataJson", location = "files", type = FileStorage, required = True, help = "JSON file with simulation data information") 241 | parser.add_argument("ModelZip", location = "files", type = FileStorage, help = "Zip file containing the extra Modelica files needed for instantiation") 242 | parser.add_argument("PrettyPrint", location = "form", type = bool, default=False) 243 | 244 | @api.expect(parser) 245 | def post(self): 246 | """Retrieves the model instance.""" 247 | args = self.parser.parse_args() 248 | metaDataJsonFileArg = args["MetadataJson"] 249 | modelZipFileArg = args["ModelZip"] 250 | prettyPrintArg = args["PrettyPrint"] 251 | 252 | omc = OMC() 253 | originalDir = omc.sendCommand("cd()") 254 | metaDataJson = {} 255 | file = "" 256 | 257 | status, uploadDirectory, messages, metaDataJson = readMetaDataAndZipFile(omc, metaDataJsonFileArg, modelZipFileArg) 258 | if not status: 259 | return setResultJsonAndQuitOMC(omc, originalDir, messages, file) 260 | 261 | # simulate the model 262 | className = metaDataJson.get("class", "") 263 | if className: 264 | modelInstanceJson = omc.sendCommand("getModelInstance({0}, {1})".format(className, util.pythonBoolToModelicaBool(prettyPrintArg))) 265 | fileHandle, modelInstanceJsonFilePath = tempfile.mkstemp(dir=current_app.config['TMPDIR'], suffix=".json", prefix="modelInstanceJson-") 266 | try: 267 | os.write(fileHandle, modelInstanceJson.encode()) 268 | finally: 269 | os.close(fileHandle) 270 | messages = "Model instance json is created." 271 | file = flask.url_for('api.download', FileName="{0}".format(os.path.basename(modelInstanceJsonFilePath)), _external=True) 272 | else: 273 | messages = "Class is missing." 274 | file = "" 275 | 276 | return setResultJsonAndQuitOMC(omc, originalDir, messages, file) --------------------------------------------------------------------------------