diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..0fe0c29 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,33 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Make a minmal code example that reproduces the bug +2. Write about the environment (OS, OPC Server) +3. Can you reproduce the Bug with the Matrikon Simulation server in nomal opc Mode without the Gateway +4. Paste your environment variables of the Openopc2 + + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. +Copy shell output text here (prefered to screenshots) + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Version [e.g. 22] + - OPC Server + - Python Version + - Environment Variables diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/build_exe.yml b/.github/workflows/build_exe.yml index afd3785..75114a1 100644 --- a/.github/workflows/build_exe.yml +++ b/.github/workflows/build_exe.yml @@ -8,19 +8,26 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v4 - - name: Set up Python + - name: Set up Python (32-bit) uses: actions/setup-python@v5 with: python-version: 3.8 + architecture: x86 - name: Install poetry uses: abatilo/actions-poetry@v3 + - name: Register gbda_aut.dll + run: | + Copy-Item .\lib\gbda_aut.dll C:\Windows\System32\ + regsvr32 /s C:\Windows\System32\gbda_aut.dll + shell: pwsh - name: Install dependencies run: poetry install - name: Build executables run: scripts/build_executables.ps1 - - uses: ncipollo/release-action@v1 + - name: Create GitHub Release + uses: ncipollo/release-action@v1 with: artifacts: | dist/OpenOpcCli.exe dist/OpenOpcServer.exe - dist/OpenOpcService.exe + dist/OpenOpcService.exe \ No newline at end of file diff --git a/CLI.md b/CLI.md index 9b45123..24dd704 100644 --- a/CLI.md +++ b/CLI.md @@ -8,22 +8,22 @@ $ openopc2 CLI [OPTIONS] COMMAND [ARGS]... **Options**: -* `--install-completion`: Install completion for the current shell. -* `--show-completion`: Show completion for the current shell, to copy it or customize the installation. -* `--help`: Show this message and exit. +- `--install-completion`: Install completion for the current shell. +- `--show-completion`: Show completion for the current shell, to copy it or customize the installation. +- `--help`: Show this message and exit. **Commands**: -* `list-clients`: [EXPERIMENTAL] List clients of OpenOPC... -* `list-tags`: List tags (items) of OPC server -* `properties`: Show properties of given tags -* `read`: Read tags -* `server-info`: Display OPC server information -* `write`: Write values +- `list-clients`: \[EXPERIMENTAL\] List clients of OpenOPC... +- `list-tags`: List tags (items) of OPC server +- `properties`: Show properties of given tags +- `read`: Read tags +- `server-info`: Display OPC server information +- `write`: Write values ## `openopc2 CLI list-clients` -[EXPERIMENTAL] List clients of OpenOPC Gateway Server +\[EXPERIMENTAL\] List clients of OpenOPC Gateway Server **Usage**: @@ -33,8 +33,8 @@ $ openopc2 CLI list-clients [OPTIONS] **Options**: -* `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level [default: WARNING] -* `--help`: Show this message and exit. +- `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level \[default: WARNING\] +- `--help`: Show this message and exit. ## `openopc2 CLI list-tags` @@ -48,15 +48,15 @@ $ openopc2 CLI list-tags [OPTIONS] **Options**: -* `--protocol-mode [com|gateway]`: Protocol mode [default: gateway] -* `--opc-server TEXT`: OPC Server to connect to [default: Matrikon.OPC.Simulation] -* `--opc-host TEXT`: OPC Host to connect to [default: localhost] -* `--gateway-host TEXT`: OPC Gateway Host to connect to [default: 192.168.0.115] -* `--gateway-port INTEGER`: OPC Gateway Port to connect to [default: 7766] -* `--recursive / --no-recursive`: Recursively read sub-tags [default: False] -* `--output-csv / --no-output-csv`: Output in CSV format [default: False] -* `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level [default: WARNING] -* `--help`: Show this message and exit. +- `--protocol-mode [com|gateway]`: Protocol mode \[default: gateway\] +- `--opc-server TEXT`: OPC Server to connect to \[default: Matrikon.OPC.Simulation\] +- `--opc-host TEXT`: OPC Host to connect to \[default: localhost\] +- `--gateway-host TEXT`: OPC Gateway Host to connect to \[default: 192.168.0.115\] +- `--gateway-port INTEGER`: OPC Gateway Port to connect to \[default: 7766\] +- `--recursive / --no-recursive`: Recursively read sub-tags \[default: False\] +- `--output-csv / --no-output-csv`: Output in CSV format \[default: False\] +- `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level \[default: WARNING\] +- `--help`: Show this message and exit. ## `openopc2 CLI properties` @@ -70,17 +70,17 @@ $ openopc2 CLI properties [OPTIONS] TAGS... **Arguments**: -* `TAGS...`: Tags to read [required] +- `TAGS...`: Tags to read \[required\] **Options**: -* `--protocol-mode [com|gateway]`: Protocol mode [default: gateway] -* `--opc-server TEXT`: OPC Server to connect to [default: Matrikon.OPC.Simulation] -* `--opc-host TEXT`: OPC Host to connect to [default: localhost] -* `--gateway-host TEXT`: OPC Gateway Host to connect to [default: 192.168.0.115] -* `--gateway-port INTEGER`: OPC Gateway Port to connect to [default: 7766] -* `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level [default: WARNING] -* `--help`: Show this message and exit. +- `--protocol-mode [com|gateway]`: Protocol mode \[default: gateway\] +- `--opc-server TEXT`: OPC Server to connect to \[default: Matrikon.OPC.Simulation\] +- `--opc-host TEXT`: OPC Host to connect to \[default: localhost\] +- `--gateway-host TEXT`: OPC Gateway Host to connect to \[default: 192.168.0.115\] +- `--gateway-port INTEGER`: OPC Gateway Port to connect to \[default: 7766\] +- `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level \[default: WARNING\] +- `--help`: Show this message and exit. ## `openopc2 CLI read` @@ -94,24 +94,24 @@ $ openopc2 CLI read [OPTIONS] TAGS... **Arguments**: -* `TAGS...`: Tags to read [required] +- `TAGS...`: Tags to read \[required\] **Options**: -* `--protocol-mode [com|gateway]`: Protocol mode [default: gateway] -* `--opc-server TEXT`: OPC Server to connect to [default: Matrikon.OPC.Simulation] -* `--opc-host TEXT`: OPC Host to connect to [default: localhost] -* `--gateway-host TEXT`: OPC Gateway Host to connect to [default: 192.168.0.115] -* `--gateway-port INTEGER`: OPC Gateway Port to connect to [default: 7766] -* `--group-size INTEGER`: Group tags into group_size tags per transaction -* `--pause INTEGER`: Sleep time between transactionsin milliseconds [default: 0] -* `--source [cache|device|hybrid]`: Data SOURCE for reads (cache, device, hybrid) [default: hybrid] -* `--update-rate INTEGER`: Update rate for group in milliseconds [default: 0] -* `--timeout INTEGER`: Read timeout in milliseconds [default: 10000] -* `--include-error-messages / --no-include-error-messages`: Include descriptive error message strings [default: False] -* `--output-csv / --no-output-csv`: Output in CSV format [default: False] -* `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level [default: WARNING] -* `--help`: Show this message and exit. +- `--protocol-mode [com|gateway]`: Protocol mode \[default: gateway\] +- `--opc-server TEXT`: OPC Server to connect to \[default: Matrikon.OPC.Simulation\] +- `--opc-host TEXT`: OPC Host to connect to \[default: localhost\] +- `--gateway-host TEXT`: OPC Gateway Host to connect to \[default: 192.168.0.115\] +- `--gateway-port INTEGER`: OPC Gateway Port to connect to \[default: 7766\] +- `--group-size INTEGER`: Group tags into group_size tags per transaction +- `--pause INTEGER`: Sleep time between transactionsin milliseconds \[default: 0\] +- `--source [cache|device|hybrid]`: Data SOURCE for reads (cache, device, hybrid) \[default: hybrid\] +- `--update-rate INTEGER`: Update rate for group in milliseconds \[default: 0\] +- `--timeout INTEGER`: Read timeout in milliseconds \[default: 10000\] +- `--include-error-messages / --no-include-error-messages`: Include descriptive error message strings \[default: False\] +- `--output-csv / --no-output-csv`: Output in CSV format \[default: False\] +- `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level \[default: WARNING\] +- `--help`: Show this message and exit. ## `openopc2 CLI server-info` @@ -125,13 +125,13 @@ $ openopc2 CLI server-info [OPTIONS] **Options**: -* `--protocol-mode [com|gateway]`: Protocol mode [default: gateway] -* `--opc-server TEXT`: OPC Server to connect to [default: Matrikon.OPC.Simulation] -* `--opc-host TEXT`: OPC Host to connect to [default: localhost] -* `--gateway-host TEXT`: OPC Gateway Host to connect to [default: 192.168.0.115] -* `--gateway-port INTEGER`: OPC Gateway Port to connect to [default: 7766] -* `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level [default: WARNING] -* `--help`: Show this message and exit. +- `--protocol-mode [com|gateway]`: Protocol mode \[default: gateway\] +- `--opc-server TEXT`: OPC Server to connect to \[default: Matrikon.OPC.Simulation\] +- `--opc-host TEXT`: OPC Host to connect to \[default: localhost\] +- `--gateway-host TEXT`: OPC Gateway Host to connect to \[default: 192.168.0.115\] +- `--gateway-port INTEGER`: OPC Gateway Port to connect to \[default: 7766\] +- `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level \[default: WARNING\] +- `--help`: Show this message and exit. ## `openopc2 CLI write` @@ -145,17 +145,17 @@ $ openopc2 CLI write [OPTIONS] TAG_VALUE_PAIRS... **Arguments**: -* `TAG_VALUE_PAIRS...`: Tag value pairs to write (use ITEM,VALUE) [required] +- `TAG_VALUE_PAIRS...`: Tag value pairs to write (use ITEM,VALUE) \[required\] **Options**: -* `--protocol-mode [com|gateway]`: Protocol mode [default: gateway] -* `--opc-server TEXT`: OPC Server to connect to [default: Matrikon.OPC.Simulation] -* `--opc-host TEXT`: OPC Host to connect to [default: localhost] -* `--gateway-host TEXT`: OPC Gateway Host to connect to [default: 192.168.0.115] -* `--gateway-port INTEGER`: OPC Gateway Port to connect to [default: 7766] -* `--group-size INTEGER`: Group tags into group_size tags per transaction -* `--pause INTEGER`: Sleep time between transactionsin milliseconds [default: 0] -* `--include-error-messages / --no-include-error-messages`: Include descriptive error message strings [default: False] -* `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level [default: WARNING] -* `--help`: Show this message and exit. +- `--protocol-mode [com|gateway]`: Protocol mode \[default: gateway\] +- `--opc-server TEXT`: OPC Server to connect to \[default: Matrikon.OPC.Simulation\] +- `--opc-host TEXT`: OPC Host to connect to \[default: localhost\] +- `--gateway-host TEXT`: OPC Gateway Host to connect to \[default: 192.168.0.115\] +- `--gateway-port INTEGER`: OPC Gateway Port to connect to \[default: 7766\] +- `--group-size INTEGER`: Group tags into group_size tags per transaction +- `--pause INTEGER`: Sleep time between transactionsin milliseconds \[default: 0\] +- `--include-error-messages / --no-include-error-messages`: Include descriptive error message strings \[default: False\] +- `--log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]`: Log level \[default: WARNING\] +- `--help`: Show this message and exit. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 18c9147..df7118a 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -17,23 +17,23 @@ diverse, inclusive, and healthy community. Examples of behavior that contributes to a positive environment for our community include: -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -* Focusing on what is best not just for us as individuals, but for the +- Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: -* The use of sexualized language or imagery, and sexual attention or +- The use of sexualized language or imagery, and sexual attention or advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities @@ -121,8 +121,8 @@ https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). -[homepage]: https://www.contributor-covenant.org - For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. + +[homepage]: https://www.contributor-covenant.org diff --git a/README.md b/README.md index 4e43736..4070bbc 100644 --- a/README.md +++ b/README.md @@ -2,90 +2,81 @@ LinuxSetup

- [![PyPI version](https://badge.fury.io/py/openopc2.svg)](https://badge.fury.io/py/openopc2) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/openopc2) - - **OpenOPC 2** is a Python Library for OPC DA. It is Open source and free for everyone. It allows you to use -[OPC Classic](https://opcfoundation.org/about/opc-technologies/opc-classic/) (OPC Data Access) in +[OPC Classic](https://opcfoundation.org/about/opc-technologies/opc-classic/) (OPC Data Access) in modern Python environments. OPC Classic is a pure Windows technology by design, but this library includes a Gateway Server -that lets you use OPC Classic on any architecture (Linux, MacOS, Windows, Docker). So this Library creates a gateway -between 2022 and the late 90ties. Like cruising into the sunset with Marty McFly in a Tesla. +that lets you use OPC Classic on any architecture (Linux, MacOS, Windows, Docker). So this Library creates a gateway +between 2022 and the late 90ties. Like cruising into the sunset with Marty McFly in a Tesla. OpenOPC 2 is based on the OpenOPC Library that was initially created by Barry Barnleitner and hosted on Source Forge, but It was completely refactorerd and migrated to Python 3.8+ - # πŸ”₯ Features -* An OpenOPC Gateway Service (a Windows service providing remote access -to the OpenOPC library, which is useful to avoid DCOM issues). -* Command Line Interface (CLI) -* Enables you to use OPC Classic with any Platform -* CLI and Gateway are independent Executables that do not require Python -* A system check module (allows you to check the health of your system) -* A free OPC automation wrapper (required DLL file). -* General documentation with updated procedures (this file). +- An OpenOPC Gateway Service (a Windows service providing remote access + to the OpenOPC library, which is useful to avoid DCOM issues). +- Command Line Interface (CLI) +- Enables you to use OPC Classic with any Platform +- CLI and Gateway are independent Executables that do not require Python +- A system check module (allows you to check the health of your system) +- A free OPC automation wrapper (required DLL file). +- General documentation with updated procedures (this file). # 🐍 OpenOPC vs OpenOPC 2 -Open OPC 2 is based on OpenOPC and should be seen as a successor. If you already have an application that is based on +Open OPC 2 is based on OpenOPC and should be seen as a successor. If you already have an application that is based on OpenOPC, you can migrate with a minimal effort. Our main motivation to build this new version was to improve the developer experience and create a base for other developers that is easier to maintain, test and work with... -* Simpler installation -* Mostly the same api (but we take the freedom to not be compatible) -* No memory leak in the OpenOpcService πŸŽ‰ -* Python 3.8+ (tested with 3.10) -* Typings -* Pyro5, increased security -* We added tests 😎 -* Refactoring for increased readablity -* Nicer CLI -* Pipy Package - - +- Simpler installation +- Mostly the same api (but we take the freedom to not be compatible) +- No memory leak in the OpenOpcService πŸŽ‰ +- Python 3.8+ (tested with 3.10) +- Typings +- Pyro5, increased security +- We added tests 😎 +- Refactoring for increased readablity +- Nicer CLI +- Pipy Package # πŸš€ Getting started -## Windows local installation - -The quickest way to start is the cli application. Start your OPC server and use the openopc2.exe cli application for test (no python -installation required). - - +## Windows local installation +The quickest way to start is the cli application. Start your OPC server and use the openopc2.exe cli application for test (no python +installation required). -Now you know that your OPC server is talking to OpenOPC 2. Then lets get started with python. If you use OpenOPC 2 with +Now you know that your OPC server is talking to OpenOPC 2. Then lets get started with python. If you use OpenOPC 2 with Python in windows directly you are **limited to a 32bit Python** installation. This is because the dlls of OPC are 32bit. -If you prefere working with a 64bit Python version you can simply use the With OpenOPC Gateway. +If you prefer working with a 64bit Python version you can simply use the With OpenOPC Gateway. WindowsSetup -You must install the gbda_aut.dll (in /lib) which is the GrayboxOpcDa wrapper. +You must install the gbda_aut.dll (in /lib) which is the GrayboxOpcDa wrapper. http://gray-box.net/daawrapper.php?lang=en ```console -python -m openopc2 servers +python -m openopc2 list-servers ``` +## Multi platform installation - -## Multi plattform installation -One of the main benefits of OpenOPC 2 ist the OpenOPC gateway. This enables you to use any modern platform for -developting your application. Start the OpenOPC service in the Windows environment where the OPC server is running. +One of the main benefits of OpenOPC 2 is the OpenOPC gateway. This enables you to use any modern platform for +developing your application. Start the OpenOPC service in the Windows environment where the OPC server is running. The Service starts a server (Pyro5) that lets you use the OpenOPC2 OpcDaClient on another machine. Due to the magic of -Pyro (Python Remote Objects) the developer experience and usage of the Library remains the same as if you worke int the -local Windows setup. +Pyro (Python Remote Objects) the developer experience and usage of the Library remains the same as if you work in the +local Windows setup. +([Download the executables here](https://github.com/iterativ/openopc2/releases/latest)) LinuxSetup -On the Windows Machine open the console as administrator. +On the Windows Machine open the console as administrator. ```shell openopcservice install @@ -93,71 +84,66 @@ openopcservice start ``` On your Linux machine -``` + +```shell pip install openopc2 -openopc2 --install` ``` python + ```python from openopc2.da_client import OpcDaClient - - - ``` -# βš™οΈ Configuration +# βš™οΈ Configuration -The configuration of the OpenOpc 2 libray and the OpenOpcGateway is done via environment variables. To initiate them, -simply run: - -```shell -OpenOPC install -``` +The configuration of the OpenOpc 2 library and the OpenOpcGateway is done via environment variables. ``` -OPC_CLASS=Matrikon.OPC.Automation;Graybox.OPC.DAWrapper;HSCOPC.Automation;RSI.OPCAutomation;OPC.Automation +OPC_CLASS=Graybox.OPC.DAWrapper OPC_CLIENT=OpenOPC OPC_GATE_HOST=192.168.1.96 # IMPORTANT: Replace with your IP address OPC_GATE_PORT=7766 OPC_HOST=localhost OPC_MODE=dcom -OPC_SERVER=Hci.TPNServer;HwHsc.OPCServer;opc.deltav.1;AIM.OPC.1;Yokogawa.ExaopcDAEXQ.1;OSI.DA.1;OPC.PHDServerDA.1;Aspen.Infoplus21_DA.1;National Instruments.OPCLabVIEW;RSLinx OPC Server;KEPware.KEPServerEx.V4;Matrikon.OPC.Simulation;Prosys.OPC.Simulation +OPC_SERVER=Matrikon.OPC.Simulation ``` -* If they are not set, open a command prompt window to do that by -typing: +- If they are not set, open a command prompt window (`cmd`) and type: ``` C:\>set ENV_VAR=VALUE C:\>set OPC_GATE_HOST=172.16.4.22 # this is an example ``` -* Make sure the firewall is allowed to keep the port 7766 open. If in -doubt, and you're doing a quick test, just turn off your firewall -completely. +- Alternately, Windows OS system or user environment variables work. + Note that user environment variables take precedent over system environment + variables. -* For easy testing, make sure an OPC server is installed in your Windows -box (i.e. Matrikon OPC Simulation Server). +- Make sure the firewall is allowed to keep the port 7766 open. If in + doubt, and you're doing a quick test, just turn off your firewall + completely. -* The work environment for testing these changes was a remote MacOs with Window10 64bit host and the Matrikon simulation -server. +- For easy testing, make sure an OPC server is installed in your Windows + box (i.e. Matrikon OPC Simulation Server). -* Register the OPC automation wrapper ( `gbda_aut.dll` ) by typing this -in the command line: +- The work environment for testing these changes was a remote MacOs with Window10 64bit host and the Matrikon simulation + server. + +- Register the OPC automation wrapper ( `gbda_aut.dll` ) by typing this + in the command line: ```shell C:\openopc2\lib>regsvr32 gbda_aut.dll ``` -* If, for any reason, you want to uninstall this file and remove it from -your system registry later, type this in the command line: +- If, for any reason, you want to uninstall this file and remove it from + your system registry later, type this in the command line: ```shell C:\openopc2\lib>regsvr32 gbda_aut.dll -u ``` - # CLI The CLI (Command Line Interface) lets you use OpenOPC2 in the shell and offers you a quick way to explore your opc server @@ -173,81 +159,68 @@ The documentation of the CLI can be found [here](CLI.md) WindowsSetup

-

WindowsSetup

-

WindowsSetup

- - # OpenOPC Gateway -This task can be completed from one of two ways (make sure to have it +This task can be completed from one of two ways (make sure to have it installed first): -* By clicking the `Start` link on the "OpenOPC Gateway Service" from the -"Services" window (Start -> Control Panel -> System and Security -> -Administrative Tools). -* By running the `net start SERVICE` command like this: +- By clicking the `Start` link on the "OpenOPC Gateway Service" from the + "Services" window (Start -> Control Panel -> System and Security -> + Administrative Tools). +- By running the `net start SERVICE` command like this: ```shell C:\openopc2\bin> zzzOpenOPCService ``` -* If you have problems starting the service, you can also try to start -this in "debug" mode: +- If you have problems starting the service, you can also try to start + this in "debug" mode: ```shell C:\openopc2\src>python OpenOPCService.py debug ``` - - ```shell C:\openopc2\>net stop zzzOpenOPCService ``` ### Configure the way the OpenOPC Gateway Service starts -If you are going to use this service frequently, it would be better to +If you are going to use this service frequently, it would be better to configure it to start in "automatic" mode. To do this: -* Select the "OpenOPC Gateway Service" from the "Services" window -(Start -> Control Panel -> System and Security -> Administrative Tools). -* Right-click and choose "Properties". -* Change the startup mode to "Automatic". Click "Apply" and "OK" -buttons. -* Start the service (if not already started). - - - +- Select the "OpenOPC Gateway Service" from the "Services" window + (Start -> Control Panel -> System and Security -> Administrative Tools). +- Right-click and choose "Properties". +- Change the startup mode to "Automatic". Click "Apply" and "OK" + buttons. +- Start the service (if not already started). ## πŸ™ Credits OpenOPC 2 is based on the OpenOPC python library that was originally created by Barry Barnleitner and its many Forks on -Github. Without the great work of all the contributors, this would not be possible. Contribution is open for everyone. - -The authors of the var package are: - - -| Years | | Name | User | -|-----------|------|---------------------|------| -| 2008-2012 | πŸ‡ΊπŸ‡Έ | Barry Barnreiter | barry_b@users.sourceforge.net | -| 2014 | πŸ‡·πŸ‡Ί | Anton D. Kachalov | barry_b@users.sourceforge.net | -| 2017 | πŸ‡»πŸ‡ͺ | JosΓ© A. Maita | jose.a.maita@gmail.com| -| 2022 | πŸ‡¨πŸ‡­ | Lorenz Padberg | renzop | -| 2022 | πŸ‡¨πŸ‡­ | Elia Bieri | eliabieri | - +Github. Without the great work of all the contributors, this would not be possible. Contribution is open for everyone. +The authors of the package are (among others): +| Years | | Name | User | +| --------- | --- | ----------------- | ----------------------------- | +| 2008-2012 | πŸ‡ΊπŸ‡Έ | Barry Barnreiter | barry_b@users.sourceforge.net | +| 2014 | πŸ‡·πŸ‡Ί | Anton D. Kachalov | https://github.com/ya-mouse | +| 2017 | πŸ‡»πŸ‡ͺ | JosΓ© A. Maita | https://github.com/joseamaita | +| 2022 | πŸ‡¨πŸ‡­ | Lorenz Padberg | https://github.com/renzop | +| 2022 | πŸ‡¨πŸ‡­ | Elia Bieri | https://github.com/eliabieri | ## πŸ“œ License -This software is licensed under the terms of the GNU GPL v2 license plus -a special linking exception for portions of the package. This license is +This software is licensed under the terms of the GNU GPL v2 license plus +a special linking exception for portions of the package. This license is available in the `LICENSE.txt` file. diff --git a/doc/Roadmap.md b/doc/Roadmap.md index 85f40d2..750ab4d 100644 --- a/doc/Roadmap.md +++ b/doc/Roadmap.md @@ -1,22 +1,25 @@ Version 1.5 Goals: + - Create a maintainable repository - Integration tests coverage 80 % - Python 3.8, 3.9 - Create executables for OpenOPCService and OPC cli - Create pypy package - remain compatible to 1.3 and 1.2 - + Known Issues: + - Return Values sometimes List of tuples and sometimes tuple... causes trouble complex code - write(tag, include_error=True) returns list of tuples (which should be tuple) - too many except: pass this is a very dangerous pattern Future Goals: + - Proper Logging - code refactoring, reduce complexity increase readablility -- replace response tuples with named tuples / dataclasses whatever is suitable +- replace response tuples with named tuples / dataclasses whatever is suitable - improve error handling - introduce encrypted protocol for gateway - write unittests @@ -24,7 +27,7 @@ Future Goals: - test on multiple python versions and platforms Far away Goals: + - OPC UA Gateway - OPC AE support - Rest API - diff --git a/doc/tipps.md b/doc/tipps.md index ef76cb0..a551d26 100644 --- a/doc/tipps.md +++ b/doc/tipps.md @@ -1,5 +1,3 @@ +Start the OpenOPC Gateway locally - -Start the OpenOPC Gateway locally - -python .\OpenOPCService.py --foreground +python .\\OpenOPCService.py --foreground diff --git a/examples/commands.ps1 b/examples/commands.ps1 deleted file mode 100644 index 0ca9224..0000000 --- a/examples/commands.ps1 +++ /dev/null @@ -1,4 +0,0 @@ - - -python -m opc --list --flat -s "Matrikon.OPC.Simulation.1" -python -m opc -s "Matrikon.OPC.Simulation.1" --read 'Bucket Brigade.ArrayOfString' diff --git a/openopc2/config.py b/openopc2/config.py index 574a760..0626c30 100644 --- a/openopc2/config.py +++ b/openopc2/config.py @@ -3,19 +3,27 @@ class OpenOpcConfig: - def __init__(self): - self.OPC_HOST: str = 'localhost' - self.OPC_SERVER: str = os.environ.get('OPC_SERVER', 'Matrikon.OPC.Simulation') - self.OPC_CLIENT: str = 'OpenOPC' - self.OPC_GATEWAY_HOST: str = os.environ.get('OPC_GATE_HOST', '192.168.0.115') - self.OPC_GATEWAY_PORT: int = int(os.environ.get('OPC_GATE_PORT', 7766)) - self.OPC_CLASS: str = os.environ.get('OPC_CLASS', 'Graybox.OPC.DAWrapper') - self.OPC_MODE: Literal["GATEWAY", "COM"] = os.environ.get('OPC_MODE', "gateway") - self.OPC_TIMEOUT: int = os.environ.get('OPC_TIMEOUT', 1000) + def __init__( + self, + opc_host: str = "localhost", + opc_server: str = os.environ.get("OPC_SERVER", "Matrikon.OPC.Simulation"), + opc_client: str = "OpenOPC", + opc_gateway_host: str = os.environ.get("OPC_GATE_HOST", "192.168.0.115"), + opc_gateway_port: int = int(os.environ.get("OPC_GATE_PORT", 7766)), + opc_class: str = os.environ.get("OPC_CLASS", "Graybox.OPC.DAWrapper"), + opc_mode: Literal["GATEWAY", "COM"] = os.environ.get("OPC_MODE", "gateway"), + opc_timeout: int = int(os.environ.get("OPC_TIMEOUT", 1000)), + ): + self.OPC_HOST = opc_host + self.OPC_SERVER = opc_server + self.OPC_CLIENT = opc_client + self.OPC_GATEWAY_HOST = opc_gateway_host + self.OPC_GATEWAY_PORT = opc_gateway_port + self.OPC_CLASS = opc_class + self.OPC_MODE = opc_mode + self.OPC_TIMEOUT = opc_timeout def print_config(self): - print('Open Opc Config:') + print("Open Opc Config:") for key, value in self.__dict__.items(): - print(f'{key:20} : {value}') - - + print(f"{key:20} : {value}") diff --git a/tests/test_config.py b/tests/test_config.py index 7fa0c41..6bfaba9 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,5 +1,9 @@ +import os +from unittest import TestCase + from openopc2.config import OpenOpcConfig + def test_config(): open_opc_config = OpenOpcConfig() open_opc_config.OPC_SERVER = "Matrikon.OPC.Simulation.1" @@ -8,3 +12,19 @@ def test_config(): open_opc_config.OPC_MODE = 'com' return open_opc_config + +class TestOpenOpcConfig(TestCase): + def test_instantiation(self) -> None: + # Confirm env vars won't mess up assertions + for env_var in ["OPC_SERVER", "OPC_GATE_PORT", "OPC_TIMEOUT"]: + self.assertNotIn(env_var, os.environ) + + default_config = OpenOpcConfig() + self.assertEquals(default_config.OPC_SERVER, "Matrikon.OPC.Simulation") + self.assertIsInstance(default_config.OPC_GATEWAY_PORT, int) + self.assertEquals(default_config.OPC_GATEWAY_PORT, 7766) + self.assertIsInstance(default_config.OPC_TIMEOUT, int) + self.assertEquals(default_config.OPC_TIMEOUT, 1000) + + nondefault_config = OpenOpcConfig(opc_server="Another.Server") + self.assertEquals(nondefault_config.OPC_SERVER, "Another.Server")